Skip to content

[BLOCKED] Builtin trait encoder#154

Open
Trzyq0712 wants to merge 74 commits into
Aurel300:rewrite-2023from
Trzyq0712:tuple_trait
Open

[BLOCKED] Builtin trait encoder#154
Trzyq0712 wants to merge 74 commits into
Aurel300:rewrite-2023from
Trzyq0712:tuple_trait

Conversation

@Trzyq0712
Copy link
Copy Markdown

@Trzyq0712 Trzyq0712 commented Mar 16, 2026

This PR introduces a framework for encoding Rust's builtin traits. Specifically, it adds support for the Sized and Tuple traits as examples.
In Rust, traits like Sized and Tuple are not defined through standard source-code declarations but are instead handled by the compiler's logic. To accurately verify Rust code, Prusti needs to know which types implement these traits.

Key Changes

1. Builtin Trait Encoder

This PR implements a generic BuiltinTraitEnc<T: BuiltinTrait> that depends on BuiltinTrait to provide trait specific logic.
To avoid emitting outputs when not necessary, the builtin trait encoder must be "activated" by the TraitEnc when the latter encounters the corresponding builtin.

2. Specialized Logic for Sized and Tuple

This PR provides concrete implementations for the Sized and Tuple traits.

  • SizedTrait: Decides whether a type is (conditionally) sized, by matching what rustc does internally.
  • TupleTrait: Decides whether a given type is a tuple.

3. RustTy modification

The PR modifies RustTy to also preserve information about the original rust type, but in its "erased" form - meaning the type is stripped of its usage context.
The erased type information is useful as it simplifies the encoding of the checks in the builtin trait encoder.

Rough points

We always compute the checks for all types for builtin traits, even though we might not always emit them.

Blocked by #137

@Trzyq0712 Trzyq0712 changed the title Tuple trait [BLOCKED] Tuple trait Mar 16, 2026
@Trzyq0712 Trzyq0712 changed the title [BLOCKED] Tuple trait [BLOCKED] Tuple trait Mar 16, 2026
Comment thread prusti-encoder/src/encoders/ty/generics/tuple_trait.rs Outdated
const TUPLE_TRAIT_ARGS: <(vir::ManyTyVal, vir::ManyCSnap) as vir::Arity>::Tys<'static> =
(&[vir::TYPE_TYVAL], &[]);

impl TaskEncoder for TupleTraitEnc {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general there is way too much duplication between this and the Sized encoder. If we want to have something like this for all special traits, then this really needs to be reduced a lot to avoid copy-paste errors. At a glance it seems we'll need the encoder to do the same things but the code which checks whether a particular input implements the type is a bit different?

How about a single BuiltinTraitEnc<T: BuiltinTrait> and then trait BuiltinTrait which has the bit of code that actually changes between the encoders?

Copy link
Copy Markdown
Author

@Trzyq0712 Trzyq0712 Mar 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Played around with it. Due to the caching with static, we cannot have impl<T: BuiltinTrait> TaskEncoder for BuiltinTraitEnc<T> { ... }. I'll try to reuse the functionality in other ways.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have extracted the shared logic. Not 100% loving it the solution but please let me know what you think about it.

@Aurel300
Copy link
Copy Markdown
Owner

And a separate question regarding special traits: right now you are invoking all the special trait encoders unconditionally from TyConstructorEnc. We should only trigger this if the impl_* function is used somewhere.

@Aurel300 Aurel300 mentioned this pull request Mar 17, 2026
5 tasks
@Trzyq0712
Copy link
Copy Markdown
Author

And a separate question regarding special traits: right now you are invoking all the special trait encoders unconditionally from TyConstructorEnc. We should only trigger this if the impl_* function is used somewhere.

The issue is that we cannot know ahead of time whether we will be using a certain impl_*.

We somehow need to "record" all types that get fed to TyConstructorEnc. Then on encoding of one of the special traits in TraitEnc, we could trigger the emission of the special trait impl_ function for that trait. Not sure how that would be done.

@Aurel300
Copy link
Copy Markdown
Owner

The issue is that we cannot know ahead of time whether we will be using a certain impl_*.

That's not exactly the issue, right: we must be requesting the impl_* function identifier somewhere (when encoding a refine spec), and at this point it should just be an output ref. The TraitEnc doesn't have to actually encode the function body at this point. Its output can be a dummy (), as long as it still emits the correct outputs in emit_outputs.

We somehow need to "record" all types that get fed to TyConstructorEnc. Then on encoding of one of the special traits in TraitEnc, we could trigger the emission of the special trait impl_ function for that trait. Not sure how that would be done.

Is there sufficient information in all_outputs_local_no_errors? Can TraitEnc (or maybe the special trait encoder(s)) call TyConstructorEnc::all_outputs_local_no_errors() and figure out the impl_* function body then?

(TyConstructorEnc still seems like the wrong place to check anyway, why not TyUsePureEnc or similar? I guess you really want to trigger it for (used) RustTyDecompositions?)

@Trzyq0712 Trzyq0712 changed the title [BLOCKED] Tuple trait [BLOCKED] Builin trait encoder Mar 24, 2026
Comment thread prusti-encoder/src/encoders/ty/rust_ty.rs Outdated
@Aurel300 Aurel300 changed the title [BLOCKED] Builin trait encoder [BLOCKED] Builtin trait encoder Mar 24, 2026
@Trzyq0712
Copy link
Copy Markdown
Author

Trzyq0712 commented Mar 24, 2026

(TyConstructorEnc still seems like the wrong place to check anyway, why not TyUsePureEnc or similar? I guess you really want to trigger it for (used) RustTyDecompositions?)

I'm not sure about moving to TyUsePureEnc. Having it called in TyConstructorEnc gives us the full view of the types defined by the Type adt in viper (I'm not sure if every type referenced in TyUsePureEnc also lands in TyConstructorEnc).

Also we only actually care about RustTys and not RustTyDecompositions. The trait encoders want to use the context-free types.

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.

3 participants