Skip to content

Encode unique TypeTag for each type, to support reasoning about Any-style type identity and downcasts - #2892

Open
SNoAnd wants to merge 4 commits into
verus-lang:mainfrom
CertiKProject:typeid-hash-ids
Open

SNoAnd wants to merge 4 commits into
verus-lang:mainfrom
CertiKProject:typeid-hash-ids

Conversation

@SNoAnd

@SNoAnd SNoAnd commented Sep 3, 2026 •

Copy link
Copy Markdown

Hi! This PR is motivated by an attempt to verify code that uses Any to identify which concrete type is currently carried by a dyn object. Specifically, if AnyFoo: Any, and foo: dyn AnyFoo, we would like to be able to check if foo is some specific AnyFoo, F, with:

(foo as &dyn core::any::Any).is::<F>()

I've written a minimal example of how we're approaching this at: https://github.com/certikproject/typeid-example-pub

We can handle most of the reasoning by creating our own axiomatization of Any. The missing ingredient is the existence of a type identifier that is guaranteed to be distinct across different types. This PR introduces that type as a primitive TypeTag (since TypeId is already taken) that lowers into AIR as a curried application of uninterpreted functions. This could be the basis for eventual Any support within Verus, and in the meantime it is enough to support our needs while hopefully not being intrusive.

Built-in types and type decorations are assigned unique, negative integer values. User-defined types are assigned positive values by hashing their paths. (I played around with a version that just counted all types in the context, but found reasoning about it a bit harder. E.g., what if something perturbs the order? But it's also a reasonable approach if you prefer.)

Since this is likely to be a pretty niche feature, I set it up to only emit axioms if the AST actually contains a type tag, to keep it from destabilizing the solver context for people who aren't using it. This wasn't having much impact relative to the complexity, so I've dropped it.

That's the broad overview. Happy to answer questions and make changes if needed. Thanks for your time!

Assisted by: Claude Code:Opus 5

By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.

Sean Anderson and others added 2 commits September 5, 2026 21:17
`any.rs` was orphaned: the module was never declared, so the two
`assume_specification`s for `TypeId::of` and `TypeId::eq` were not compiled
and the whole type-identity feature was inert. The declaration is present on
`typeid-counter-ids`; it was lost squashing onto upstream, which had added
`pub mod array;` at the same alphabetical slot.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant