├── .envrc ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ ├── other.md │ └── unsupported-language-feature.md ├── index.html └── workflows │ ├── ci.yml │ ├── doc.yml │ ├── rustc-tests.yml │ └── weekly.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md ├── charon-ml ├── .ocamlformat ├── Makefile ├── README.md ├── name_matcher_parser │ ├── Ast.ml │ ├── Interface.ml │ ├── Lexer.mll │ ├── Parser.mly │ └── dune ├── src │ ├── BigInt.ml │ ├── CharonVersion.ml │ ├── Collections.ml │ ├── Expressions.ml │ ├── ExpressionsUtils.ml │ ├── GAst.ml │ ├── GAstOfJson.ml │ ├── GAstUtils.ml │ ├── Identifiers.ml │ ├── LlbcAst.ml │ ├── LlbcAstUtils.ml │ ├── LlbcOfJson.ml │ ├── Logging.ml │ ├── Meta.ml │ ├── MetaUtils.ml │ ├── NameMatcher.ml │ ├── OfJsonBasic.ml │ ├── PrintExpressions.ml │ ├── PrintGAst.ml │ ├── PrintLlbcAst.ml │ ├── PrintTypes.ml │ ├── PrintUllbcAst.ml │ ├── PrintUtils.ml │ ├── PrintValues.ml │ ├── Scalars.ml │ ├── StringUtils.ml │ ├── Substitute.ml │ ├── Types.ml │ ├── TypesUtils.ml │ ├── Uchar.ml │ ├── UllbcAst.ml │ ├── UllbcAstUtils.ml │ ├── UllbcOfJson.ml │ ├── Utils.ml │ ├── Values.ml │ ├── ValuesUtils.ml │ ├── dune │ └── generated │ │ ├── Generated_Expressions.ml │ │ ├── Generated_GAst.ml │ │ ├── Generated_GAstOfJson.ml │ │ ├── Generated_LlbcAst.ml │ │ ├── Generated_LlbcOfJson.ml │ │ ├── Generated_Meta.ml │ │ ├── Generated_Types.ml │ │ ├── Generated_UllbcAst.ml │ │ ├── Generated_UllbcOfJson.ml │ │ └── Generated_Values.ml └── tests │ ├── Test_Deserialize.ml │ ├── Test_NameMatcher.ml │ ├── Tests.ml │ ├── dune │ └── test-outputs ├── charon.opam ├── charon ├── Cargo.lock ├── Cargo.toml ├── Charon.toml ├── Makefile ├── macros │ ├── .gitignore │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── enum_helpers.rs │ │ └── lib.rs ├── rust-toolchain ├── src │ ├── ast │ │ ├── builtins.rs │ │ ├── expressions.rs │ │ ├── expressions_utils.rs │ │ ├── gast.rs │ │ ├── gast_utils.rs │ │ ├── krate.rs │ │ ├── llbc_ast.rs │ │ ├── llbc_ast_utils.rs │ │ ├── meta.rs │ │ ├── meta_utils.rs │ │ ├── mod.rs │ │ ├── names.rs │ │ ├── names_utils.rs │ │ ├── types.rs │ │ ├── types │ │ │ └── vars.rs │ │ ├── types_utils.rs │ │ ├── ullbc_ast.rs │ │ ├── ullbc_ast_utils.rs │ │ ├── values.rs │ │ ├── values_utils.rs │ │ └── visitor.rs │ ├── bin │ │ ├── charon-driver │ │ │ ├── driver.rs │ │ │ ├── main.rs │ │ │ └── translate │ │ │ │ ├── get_mir.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── resolve_path.rs │ │ │ │ ├── translate_bodies.rs │ │ │ │ ├── translate_closures.rs │ │ │ │ ├── translate_constants.rs │ │ │ │ ├── translate_crate_to_ullbc.rs │ │ │ │ ├── translate_ctx.rs │ │ │ │ ├── translate_functions_to_ullbc.rs │ │ │ │ ├── translate_predicates.rs │ │ │ │ ├── translate_traits.rs │ │ │ │ └── translate_types.rs │ │ ├── charon │ │ │ ├── cli.rs │ │ │ ├── main.rs │ │ │ ├── toml_config.rs │ │ │ └── toolchain.rs │ │ └── generate-ml │ │ │ ├── main.rs │ │ │ └── templates │ │ │ ├── .ocamlformat-ignore │ │ │ ├── Expressions.ml │ │ │ ├── GAst.ml │ │ │ ├── GAstOfJson.ml │ │ │ ├── LlbcAst.ml │ │ │ ├── LlbcOfJson.ml │ │ │ ├── Meta.ml │ │ │ ├── Types.ml │ │ │ ├── UllbcAst.ml │ │ │ ├── UllbcOfJson.ml │ │ │ └── Values.ml │ ├── common.rs │ ├── errors.rs │ ├── export.rs │ ├── ids │ │ ├── generator.rs │ │ ├── mod.rs │ │ └── vector.rs │ ├── lib.rs │ ├── logger.rs │ ├── name_matcher │ │ ├── mod.rs │ │ └── parser.rs │ ├── options.rs │ ├── pretty │ │ ├── fmt_with_ctx.rs │ │ ├── formatter.rs │ │ └── mod.rs │ └── transform │ │ ├── check_generics.rs │ │ ├── compute_short_names.rs │ │ ├── ctx.rs │ │ ├── duplicate_defaulted_methods.rs │ │ ├── duplicate_return.rs │ │ ├── expand_associated_types.rs │ │ ├── filter_invisible_trait_impls.rs │ │ ├── filter_unreachable_blocks.rs │ │ ├── graphs.rs │ │ ├── hide_marker_traits.rs │ │ ├── index_intermediate_assigns.rs │ │ ├── index_to_function_calls.rs │ │ ├── inline_local_panic_functions.rs │ │ ├── inline_promoted_consts.rs │ │ ├── insert_assign_return_unit.rs │ │ ├── insert_storage_lives.rs │ │ ├── lift_associated_item_clauses.rs │ │ ├── merge_goto_chains.rs │ │ ├── mod.rs │ │ ├── monomorphize.rs │ │ ├── ops_to_function_calls.rs │ │ ├── prettify_cfg.rs │ │ ├── reconstruct_asserts.rs │ │ ├── reconstruct_boxes.rs │ │ ├── recover_body_comments.rs │ │ ├── remove_drop_never.rs │ │ ├── remove_dynamic_checks.rs │ │ ├── remove_nops.rs │ │ ├── remove_read_discriminant.rs │ │ ├── remove_unit_locals.rs │ │ ├── remove_unused_locals.rs │ │ ├── remove_unused_methods.rs │ │ ├── reorder_decls.rs │ │ ├── simplify_constants.rs │ │ ├── skip_trait_refs_when_known.rs │ │ ├── ullbc_to_llbc.rs │ │ ├── unbind_item_vars.rs │ │ └── update_block_indices.rs └── tests │ ├── cargo.rs │ ├── cargo │ ├── build-script.out │ ├── build-script │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── build.rs │ │ └── src │ │ │ └── main.rs │ ├── dependencies.out │ ├── dependencies │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── src │ │ │ └── main.rs │ ├── error-dependencies.out │ ├── error-dependencies │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── main.rs │ │ │ └── module.rs │ ├── multi-targets │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ ├── toml.out │ ├── toml │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── Charon.toml │ │ └── src │ │ │ └── main.rs │ ├── unsafe_.out │ ├── unsafe_ │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ └── src │ │ │ └── bin │ │ │ └── unsafe.rs │ ├── workspace.out │ └── workspace │ │ ├── Cargo.lock │ │ ├── Cargo.toml │ │ ├── crate1 │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ │ └── crate2 │ │ ├── Cargo.toml │ │ └── src │ │ └── lib.rs │ ├── cli.rs │ ├── crate_data.rs │ ├── popular-crates.rs │ ├── popular-crates │ └── .gitignore │ ├── test-rust-name-matcher.rs │ ├── ui.rs │ ├── ui │ ├── .gitignore │ ├── arrays.out │ ├── arrays.rs │ ├── arrays_const_generics.out │ ├── arrays_const_generics.rs │ ├── assoc-const-with-generics.out │ ├── assoc-const-with-generics.rs │ ├── associated-types.out │ ├── associated-types.rs │ ├── bitwise.out │ ├── bitwise.rs │ ├── call-to-known-trait-method.out │ ├── call-to-known-trait-method.rs │ ├── closures.out │ ├── closures.rs │ ├── closures_with_where.out │ ├── closures_with_where.rs │ ├── comments.out │ ├── comments.rs │ ├── constants.out │ ├── constants.rs │ ├── copy_nonoverlapping.out │ ├── copy_nonoverlapping.rs │ ├── demo.out │ ├── demo.rs │ ├── dictionary_passing_style_woes.out │ ├── dictionary_passing_style_woes.rs │ ├── disambiguator.out │ ├── disambiguator.rs │ ├── diverging.out │ ├── diverging.rs │ ├── dyn-trait.out │ ├── dyn-trait.rs │ ├── error-dependencies.out │ ├── error-dependencies.rs │ ├── external.out │ ├── external.rs │ ├── find-sized-clause.out │ ├── find-sized-clause.rs │ ├── float.out │ ├── float.rs │ ├── foreign-constant-aux.rs │ ├── foreign-constant.out │ ├── foreign-constant.rs │ ├── gat-causes-unhandled-ty-clause.out │ ├── gat-causes-unhandled-ty-clause.rs │ ├── generic-associated-types.out │ ├── generic-associated-types.rs │ ├── gosim-demo.out │ ├── gosim-demo.rs │ ├── hide-marker-traits.out │ ├── hide-marker-traits.rs │ ├── impl-trait.out │ ├── impl-trait.rs │ ├── issue-114-opaque-bodies-aux.rs │ ├── issue-114-opaque-bodies.out │ ├── issue-114-opaque-bodies.rs │ ├── issue-118-generic-copy.out │ ├── issue-118-generic-copy.rs │ ├── issue-120-bare-discriminant-read.out │ ├── issue-120-bare-discriminant-read.rs │ ├── issue-159-heterogeneous-recursive-definitions.out │ ├── issue-159-heterogeneous-recursive-definitions.rs │ ├── issue-165-vec-macro.out │ ├── issue-165-vec-macro.rs │ ├── issue-166-self-constructors.out │ ├── issue-166-self-constructors.rs │ ├── issue-297-cfg.out │ ├── issue-297-cfg.rs │ ├── issue-320-slice-pattern.out │ ├── issue-320-slice-pattern.rs │ ├── issue-322-macro-disambiguator.out │ ├── issue-322-macro-disambiguator.rs │ ├── issue-323-closure-borrow.out │ ├── issue-323-closure-borrow.rs │ ├── issue-369-mismatched-genericparams.out │ ├── issue-369-mismatched-genericparams.rs │ ├── issue-372-type-param-out-of-range.out │ ├── issue-372-type-param-out-of-range.rs │ ├── issue-378-ctor-as-fn.out │ ├── issue-378-ctor-as-fn.rs │ ├── issue-393-shallowinitbox.out │ ├── issue-393-shallowinitbox.rs │ ├── issue-394-rpit-with-lifetime.out │ ├── issue-394-rpit-with-lifetime.rs │ ├── issue-395-failed-to-normalize.out │ ├── issue-395-failed-to-normalize.rs │ ├── issue-4-slice-try-into-array.out │ ├── issue-4-slice-try-into-array.rs │ ├── issue-4-traits.out │ ├── issue-4-traits.rs │ ├── issue-45-misc.out │ ├── issue-45-misc.rs │ ├── issue-507-cfg.out │ ├── issue-507-cfg.rs │ ├── issue-70-override-provided-method.2.out │ ├── issue-70-override-provided-method.2.rs │ ├── issue-70-override-provided-method.3.out │ ├── issue-70-override-provided-method.3.rs │ ├── issue-70-override-provided-method.out │ ├── issue-70-override-provided-method.rs │ ├── issue-72-hash-missing-impl.out │ ├── issue-72-hash-missing-impl.rs │ ├── issue-73-extern.out │ ├── issue-73-extern.rs │ ├── issue-91-enum-to-discriminant-cast.out │ ├── issue-91-enum-to-discriminant-cast.rs │ ├── issue-92-nonpositive-variant-indices.out │ ├── issue-92-nonpositive-variant-indices.rs │ ├── issue-93-recursive-traits-with-assoc-types.out │ ├── issue-93-recursive-traits-with-assoc-types.rs │ ├── issue-94-recursive-trait-defns.out │ ├── issue-94-recursive-trait-defns.rs │ ├── issue-97-missing-parent-item-clause.out │ ├── issue-97-missing-parent-item-clause.rs │ ├── iterator.out │ ├── iterator.rs │ ├── loops.out │ ├── loops.rs │ ├── match_on_opaque_enum.out │ ├── match_on_opaque_enum.rs │ ├── matches.out │ ├── matches.rs │ ├── max_char.out │ ├── max_char.rs │ ├── method-impl-generalization.out │ ├── method-impl-generalization.rs │ ├── ml-name-matcher-tests.out │ ├── ml-name-matcher-tests.rs │ ├── monomorphization │ │ ├── adt_proj.out │ │ ├── adt_proj.rs │ │ ├── closure-fn.out │ │ ├── closure-fn.rs │ │ ├── closure-fnonce.out │ │ ├── closure-fnonce.rs │ │ ├── closures.out │ │ ├── closures.rs │ │ ├── const_generics.out │ │ ├── const_generics.rs │ │ ├── fn_ptr_generics.out │ │ ├── fn_ptr_generics.rs │ │ ├── trait_impls.out │ │ ├── trait_impls.rs │ │ ├── trait_impls_ullbc.out │ │ └── trait_impls_ullbc.rs │ ├── no_nested_borrows.out │ ├── no_nested_borrows.rs │ ├── non-lifetime-gats.out │ ├── non-lifetime-gats.rs │ ├── opacity.out │ ├── opacity.rs │ ├── opaque-trait.out │ ├── opaque-trait.rs │ ├── opaque_attribute.out │ ├── opaque_attribute.rs │ ├── panics.out │ ├── panics.rs │ ├── params.out │ ├── params.rs │ ├── plain-panic-str.out │ ├── plain-panic-str.rs │ ├── pointers-in-consts-no-warns.out │ ├── pointers-in-consts-no-warns.rs │ ├── pointers-in-consts.out │ ├── pointers-in-consts.rs │ ├── polonius_map.out │ ├── polonius_map.rs │ ├── predicates-on-late-bound-vars.out │ ├── predicates-on-late-bound-vars.rs │ ├── projection-index-from-end.out │ ├── projection-index-from-end.rs │ ├── ptr-offset.out │ ├── ptr-offset.rs │ ├── quantified-clause.out │ ├── quantified-clause.rs │ ├── reconstruct_early_return.out │ ├── reconstruct_early_return.rs │ ├── region-inference-vars.out │ ├── region-inference-vars.rs │ ├── regressions │ │ ├── closure-inside-impl-with-bound-with-assoc-ty.out │ │ └── closure-inside-impl-with-bound-with-assoc-ty.rs │ ├── remove-dynamic-checks.out │ ├── remove-dynamic-checks.rs │ ├── rename_attribute.out │ ├── rename_attribute.rs │ ├── rename_attribute_failure.out │ ├── rename_attribute_failure.rs │ ├── result-unwrap.out │ ├── result-unwrap.rs │ ├── rust-name-matcher-tests.out │ ├── rust-name-matcher-tests.rs │ ├── rvalues.out │ ├── rvalues.rs │ ├── scopes.out │ ├── scopes.rs │ ├── send_bound.out │ ├── send_bound.rs │ ├── simple-cmp.out │ ├── simple-cmp.rs │ ├── simple │ │ ├── additions.out │ │ ├── additions.rs │ │ ├── array_index.out │ │ ├── array_index.rs │ │ ├── assoc-constraint-on-assoc-ty-nested.out │ │ ├── assoc-constraint-on-assoc-ty-nested.rs │ │ ├── assoc-constraint-on-assoc-ty.2.out │ │ ├── assoc-constraint-on-assoc-ty.2.rs │ │ ├── assoc-constraint-on-assoc-ty.out │ │ ├── assoc-constraint-on-assoc-ty.rs │ │ ├── assoc-ty-via-supertrait-and-bounds.out │ │ ├── assoc-ty-via-supertrait-and-bounds.rs │ │ ├── assoc-type-with-fn-bound.out │ │ ├── assoc-type-with-fn-bound.rs │ │ ├── box-into-inner.out │ │ ├── box-into-inner.rs │ │ ├── box-new.out │ │ ├── box-new.rs │ │ ├── call-foreign-defaulted-method.out │ │ ├── call-foreign-defaulted-method.rs │ │ ├── call-inherent-method-with-trait-bound.out │ │ ├── call-inherent-method-with-trait-bound.rs │ │ ├── call-method-via-supertrait-bound.out │ │ ├── call-method-via-supertrait-bound.rs │ │ ├── closure-capture-ref-by-move.out │ │ ├── closure-capture-ref-by-move.rs │ │ ├── closure-fn.out │ │ ├── closure-fn.rs │ │ ├── closure-fnmut.out │ │ ├── closure-fnmut.rs │ │ ├── closure-fnonce.out │ │ ├── closure-fnonce.rs │ │ ├── closure-inside-impl.out │ │ ├── closure-inside-impl.rs │ │ ├── conditional-drop.out │ │ ├── conditional-drop.rs │ │ ├── const-subslice.out │ │ ├── const-subslice.rs │ │ ├── default-method-with-clause-and-marker-trait.out │ │ ├── default-method-with-clause-and-marker-trait.rs │ │ ├── fewer-clauses-in-method-impl.2.out │ │ ├── fewer-clauses-in-method-impl.2.rs │ │ ├── fewer-clauses-in-method-impl.out │ │ ├── fewer-clauses-in-method-impl.rs │ │ ├── gat-default.out │ │ ├── gat-default.rs │ │ ├── generic-impl-with-defaulted-method-with-clause-with-assoc-ty.out │ │ ├── generic-impl-with-defaulted-method-with-clause-with-assoc-ty.rs │ │ ├── generic-impl-with-defaulted-method.out │ │ ├── generic-impl-with-defaulted-method.rs │ │ ├── generic-impl-with-method.out │ │ ├── generic-impl-with-method.rs │ │ ├── match-on-char.out │ │ ├── match-on-char.rs │ │ ├── match-on-float.out │ │ ├── match-on-float.rs │ │ ├── mem-discriminant-from-derive.out │ │ ├── mem-discriminant-from-derive.rs │ │ ├── method-with-assoc-type-constraint.out │ │ ├── method-with-assoc-type-constraint.rs │ │ ├── multiple-promoteds.out │ │ ├── multiple-promoteds.rs │ │ ├── nested-closure.out │ │ ├── nested-closure.rs │ │ ├── nested-inline-const.out │ │ ├── nested-inline-const.rs │ │ ├── opaque-trait-with-clause-in-method.out │ │ ├── opaque-trait-with-clause-in-method.rs │ │ ├── pass-higher-kinded-fn-item-as-closure.out │ │ ├── pass-higher-kinded-fn-item-as-closure.rs │ │ ├── pointee_metadata.out │ │ ├── pointee_metadata.rs │ │ ├── promoted-closure-no-warns.out │ │ ├── promoted-closure-no-warns.rs │ │ ├── promoted-closure.out │ │ ├── promoted-closure.rs │ │ ├── promoted-in-generic-fn.out │ │ ├── promoted-in-generic-fn.rs │ │ ├── promoted-literal-addition-overflow.out │ │ ├── promoted-literal-addition-overflow.rs │ │ ├── promoted-literal-addition.out │ │ ├── promoted-literal-addition.rs │ │ ├── promoted-u32-slice.out │ │ ├── promoted-u32-slice.rs │ │ ├── ptr-from-raw-parts.out │ │ ├── ptr-from-raw-parts.rs │ │ ├── ptr_to_promoted.out │ │ ├── ptr_to_promoted.rs │ │ ├── quantified-trait-type-constraint.out │ │ ├── quantified-trait-type-constraint.rs │ │ ├── slice_increment.out │ │ ├── slice_increment.rs │ │ ├── slice_index.out │ │ ├── slice_index.rs │ │ ├── slice_index_range.out │ │ ├── slice_index_range.rs │ │ ├── supertrait-impl-with-assoc-type-constraint.out │ │ ├── supertrait-impl-with-assoc-type-constraint.rs │ │ ├── vec-push.out │ │ ├── vec-push.rs │ │ ├── vec-with-capacity.out │ │ └── vec-with-capacity.rs │ ├── skip-borrowck.out │ ├── skip-borrowck.rs │ ├── slice-index-range.out │ ├── slice-index-range.rs │ ├── start_from.out │ ├── start_from.rs │ ├── start_from_errors.out │ ├── start_from_errors.rs │ ├── statics.out │ ├── statics.rs │ ├── stealing.out │ ├── stealing.rs │ ├── string-literal.out │ ├── string-literal.rs │ ├── traits.out │ ├── traits.rs │ ├── traits_special.out │ ├── traits_special.rs │ ├── type_alias.out │ ├── type_alias.rs │ ├── type_inference_is_order_dependent.out │ ├── type_inference_is_order_dependent.rs │ ├── typenum.out │ ├── typenum.rs │ ├── ullbc-control-flow.out │ ├── ullbc-control-flow.rs │ ├── unions.out │ ├── unions.rs │ ├── unsafe-impl-send.out │ ├── unsafe-impl-send.rs │ ├── unsafe.out │ ├── unsafe.rs │ ├── unsize.out │ ├── unsize.rs │ └── unsupported │ │ ├── advanced-const-generics.out │ │ ├── advanced-const-generics.rs │ │ ├── issue-79-bound-regions.out │ │ ├── issue-79-bound-regions.rs │ │ ├── unbound-lifetime.out │ │ ├── unbound-lifetime.rs │ │ ├── well-formedness-bound.out │ │ └── well-formedness-bound.rs │ └── util │ └── mod.rs ├── default.nix ├── doc-ml.html ├── doc-rust.html ├── docs ├── limitations.md ├── transformations.md ├── usage.md └── what_charon_does_for_you.md ├── dune-project ├── flake.lock ├── flake.nix ├── name_matcher_parser.opam ├── nix ├── charon-ml.nix ├── charon.nix └── rustc-tests.nix ├── rust-toolchain ├── scripts ├── ci-check-hax-commit.sh ├── ci-check-version-number.sh └── ci-select-dep-versions.py ├── shell.nix └── static └── Charon.jpg /.envrc: -------------------------------------------------------------------------------- 1 | watch_file ./charon/rust-toolchain 2 | use flake 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Propose a new Charon feature 4 | title: 'Feature request: ' 5 | --- 6 | 7 | 18 | 19 | **Code snippet**: 20 | 21 | 24 | 25 | ```rust 26 | // add your code here 27 | 28 | ``` 29 | 30 | **Current Charon output**: 31 | 32 | 36 | 37 | ``` 38 | // paste the output here 39 | 40 | ``` 41 | 42 | **Extra context**: (describe the situation you're in and what problem you're trying to solve) 43 | 44 | **Desired behavior**: (explain what output you would like to get) 45 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/other.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Other 3 | about: An issue that does not fit the other scenarios 4 | --- 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/unsupported-language-feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Unsupported language feature 3 | about: Report a part of rust we don't support 4 | title: Support 5 | labels: C-unsupported-language-feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | 19 | 20 | **Code snippet that is not correctly supported**: 21 | 22 | 25 | 26 | ```rust 27 | // add your code here 28 | 29 | ``` 30 | 31 | **Current Charon output**: 32 | 33 | 38 | 39 | ``` 40 | // paste the output here 41 | 42 | ``` 43 | 44 | **Expected behavior**: (explain how you think Charon should extract this code) 45 | -------------------------------------------------------------------------------- /.github/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | API Docs 8 | 47 | 48 | 49 | 50 |

Charon related API docs

51 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.github/workflows/rustc-tests.yml: -------------------------------------------------------------------------------- 1 | on: 2 | schedule: 3 | - cron: '0 0 * * 0' 4 | workflow_dispatch: 5 | 6 | jobs: 7 | rustc-tests: 8 | runs-on: [self-hosted, linux, nix] 9 | steps: 10 | - uses: actions/checkout@v4 11 | - run: | 12 | nix build -L '.#rustc-tests' 13 | echo "Summary of the results:" > message.txt 14 | echo '```text' >> message.txt 15 | cat result/charon-summary >> message.txt 16 | echo '```' >> message.txt 17 | cat result/charon-grouped-results >> message.txt 18 | - uses: actions/github-script@v7 19 | with: 20 | script: | 21 | const fs = require('node:fs'); 22 | const message = fs.readFileSync('./message.txt', 'utf8'); 23 | github.rest.issues.createComment({ 24 | issue_number: 145, 25 | owner: context.repo.owner, 26 | repo: context.repo.repo, 27 | body: message, 28 | }); 29 | -------------------------------------------------------------------------------- /.github/workflows/weekly.yml: -------------------------------------------------------------------------------- 1 | on: 2 | schedule: 3 | - cron: '0 0 * * 0' 4 | workflow_dispatch: 5 | 6 | jobs: 7 | default: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: ocaml/setup-ocaml@v3 12 | with: 13 | ocaml-compiler: 4.13.1 14 | - run: opam install . --deps-only 15 | - run: opam install ocamlformat odoc 16 | - run: opam exec -- make build 17 | - run: IN_CI=1 opam exec -- make test 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #=================== 2 | # Generated by Cargo 3 | #=================== 4 | # will have compiled files and executables 5 | charon/target 6 | charon/attributes/target 7 | charon/macros/target 8 | charon/tests/cargo/*/target 9 | tests/target 10 | tests/src/betree/target 11 | 12 | #=================== 13 | # Generated by dune 14 | #=================== 15 | _build 16 | 17 | #=================== 18 | # Generated by opam 19 | #=================== 20 | _opam 21 | 22 | #=================== 23 | # Generated by Charon 24 | #=================== 25 | tests/llbc 26 | *.llbc 27 | *.ullbc 28 | 29 | ################## 30 | # Generated by Nix 31 | ################## 32 | result 33 | 34 | # These are backup files generated by rustfmt 35 | **/*.rs.bk 36 | 37 | #====== 38 | # Other 39 | #====== 40 | charon-ml/tests/serialized 41 | /bin 42 | 43 | #=================================== 44 | # Temporary files generated by emacs 45 | #=================================== 46 | nohup.out 47 | *~ 48 | 49 | #====== 50 | # Other 51 | #====== 52 | .vscode 53 | *.mir 54 | *.txt 55 | *# 56 | *.smt2 57 | .#* 58 | -------------------------------------------------------------------------------- /charon-ml/.ocamlformat: -------------------------------------------------------------------------------- 1 | profile = default 2 | version = 0.26.2 3 | margin = 80 4 | 5 | break-cases = fit-or-vertical 6 | doc-comments = before 7 | exp-grouping = preserve 8 | parens-tuple = always 9 | parens-tuple-patterns = multi-line-only 10 | -------------------------------------------------------------------------------- /charon-ml/Makefile: -------------------------------------------------------------------------------- 1 | # Build, after formatting the code 2 | .PHONY: build 3 | build: format build-dev 4 | 5 | # Build, without formatting the code 6 | .PHONY: build-dev 7 | build-dev: 8 | cd .. && dune build && dune build @doc 9 | 10 | # Generate documentation 11 | .PHONY: doc 12 | doc: 13 | cd .. && dune build @doc 14 | 15 | # The tests. 16 | # You can use the environment variable "CHARON_LOG" to activate the log. 17 | # For instance: `CHARON_LOG=1 make tests`. 18 | # WARNING: This requires the llbc-building tests to have been run. Prefer using 19 | # `make test` in the root directory. 20 | .PHONY: tests 21 | tests: 22 | cd .. && dune test 23 | 24 | # Reformat the code 25 | .PHONY: format 26 | format: 27 | @# `dune fmt` returns false if it had to change code; we don't care about that. 28 | dune fmt || true 29 | 30 | # Adapted from https://gitlab.inria.fr/fpottier/visitors/blob/master/Makefile.preprocess 31 | PPX := `ocamlfind query ppx_deriving`/ppx_deriving `ocamlfind query ppx_deriving`/show/ppx_deriving_show.cma `ocamlfind query ppx_deriving`/ord/ppx_deriving_ord.cma `ocamlfind query visitors`/ppx/ppx_deriving_visitors.cma 32 | 33 | %.processed.ml: %.ml 34 | @ echo Preprocessing $<... 35 | @ ocamlfind ppx_tools/rewriter -ppx '$(PPX)' $< \ 36 | | sed -e '/VISITORS.BEGIN/,/VISITORS.END/!d;//d'\ 37 | | ocamlformat --name="$<" - > $@ 38 | -------------------------------------------------------------------------------- /charon-ml/README.md: -------------------------------------------------------------------------------- 1 | # Charon ML 2 | 3 | This folder implement an ML library for Charon, to deserialize and print the 4 | (U)LLBC ASTs. 5 | -------------------------------------------------------------------------------- /charon-ml/name_matcher_parser/Interface.ml: -------------------------------------------------------------------------------- 1 | open Lexing 2 | include Ast 3 | 4 | let colnum pos = pos.pos_cnum - pos.pos_bol - 1 5 | 6 | let pos_string pos = 7 | let l = string_of_int pos.pos_lnum and c = string_of_int (colnum pos + 1) in 8 | "line " ^ l ^ ", column " ^ c 9 | 10 | let parse_pattern (s : string) : pattern = 11 | let lexbuf = Lexing.from_string s in 12 | try Parser.full_pattern Lexer.token lexbuf 13 | with Parser.Error -> 14 | raise 15 | (Failure ("Parse error at " ^ pos_string lexbuf.lex_curr_p ^ ":\n" ^ s)) 16 | -------------------------------------------------------------------------------- /charon-ml/name_matcher_parser/Lexer.mll: -------------------------------------------------------------------------------- 1 | { 2 | open Parser 3 | open Ast 4 | } 5 | 6 | let digit = ['0'-'9'] 7 | let alpha = ['a'-'z' 'A'-'Z'] 8 | let ident = (alpha) (alpha | digit | '_')* 9 | let whitespace = [' ']+ 10 | 11 | (* Rules *) 12 | rule token = parse 13 | | "::" { SEP } 14 | | "mut" { MUT } 15 | | "const" { CONST } 16 | | "fn" { FN } 17 | | "'static" { STATIC_REGION } 18 | | ''' { REGION (index lexbuf) } 19 | | "true" { TRUE } 20 | | "false" { FALSE } 21 | | ident { IDENT (Lexing.lexeme lexbuf) } 22 | | digit { INT (Z.of_string (Lexing.lexeme lexbuf)) } 23 | | '(' { LEFT_BRACKET } 24 | | ')' { RIGHT_BRACKET } 25 | | '{' { LEFT_CURLY } 26 | | '}' { RIGHT_CURLY } 27 | | '[' { LEFT_SQUARE } 28 | | ']' { RIGHT_SQUARE } 29 | | "@" { VAR(index lexbuf) } 30 | | ';' { SEMICOL } 31 | | '&' { AMPERSAND } 32 | | whitespace { token lexbuf } 33 | | eof { EOF } 34 | | '<' { LEFT_ANGLE } 35 | | '>' { RIGHT_ANGLE } 36 | | ',' { COMMA } 37 | | "->" { ARROW } 38 | | '*' { STAR } 39 | | "#" { HASH } 40 | | _ { raise (Failure ("Character not allowed in source text: '" ^ Lexing.lexeme lexbuf ^ "'")) } 41 | 42 | and index = parse 43 | | ident { Some (VarName (Lexing.lexeme lexbuf)) } 44 | | digit+ { Some (VarIndex (int_of_string (Lexing.lexeme lexbuf))) } 45 | | '_' { None } 46 | | "" { None } 47 | -------------------------------------------------------------------------------- /charon-ml/name_matcher_parser/dune: -------------------------------------------------------------------------------- 1 | (ocamllex Lexer) 2 | 3 | (menhir 4 | (modules Parser) 5 | (flags --explain --inspection --table --dump)) 6 | 7 | (library 8 | (name name_matcher_parser) 9 | (public_name name_matcher_parser) 10 | (preprocess 11 | (pps ppx_deriving.show ppx_deriving.ord visitors.ppx)) 12 | (libraries zarith menhirLib) 13 | (flags 14 | ; menhir generates instances of the "unused rec flag" warning 15 | (:standard -w -39))) 16 | -------------------------------------------------------------------------------- /charon-ml/src/BigInt.ml: -------------------------------------------------------------------------------- 1 | (** We use big integers to store the integer values (this way we don't have 2 | to think about the bounds, nor architecture issues - Rust allows to 3 | manipulate 128-bit integers for instance). 4 | *) 5 | type big_int = (Z.t[@opaque]) 6 | [@@deriving 7 | visitors { name = "iter_big_int"; variety = "iter" }, 8 | visitors { name = "map_big_int"; variety = "map" }, 9 | visitors { name = "reduce_big_int"; variety = "reduce" }, 10 | visitors { name = "mapreduce_big_int"; variety = "mapreduce" }] 11 | 12 | let big_int_of_yojson (json : Yojson.Safe.t) : (big_int, string) result = 13 | match json with 14 | | `Int i -> Ok (Z.of_int i) 15 | | `Intlit is -> Ok (Z.of_string is) 16 | | _ -> Error "not an integer or an integer literal" 17 | 18 | let big_int_to_yojson (i : big_int) = `Intlit (Z.to_string i) 19 | 20 | let pp_big_int (fmt : Format.formatter) (bi : big_int) : unit = 21 | Format.pp_print_string fmt (Z.to_string bi) 22 | 23 | let compare_big_int (bi0 : big_int) (bi1 : big_int) : int = Z.compare bi0 bi1 24 | let show_big_int (bi : big_int) : string = Z.to_string bi 25 | let equal_big_int (bi0 : big_int) (bi1 : big_int) : bool = Z.equal bi0 bi1 26 | -------------------------------------------------------------------------------- /charon-ml/src/CharonVersion.ml: -------------------------------------------------------------------------------- 1 | (* This is an automatically generated file, generated from `charon/Cargo.toml`. *) 2 | (* To re-generate this file, rune `make` in the root directory *) 3 | let supported_charon_version = "0.1.94" 4 | -------------------------------------------------------------------------------- /charon-ml/src/Expressions.ml: -------------------------------------------------------------------------------- 1 | open Identifiers 2 | open Types 3 | open Values 4 | include Generated_Expressions 5 | 6 | (* FIXME(#287): Avoid derives triggering deprecation warnings *) 7 | [@@@alert "-deprecated"] 8 | 9 | type var_id = local_id 10 | [@@deriving show, eq, ord] [@@ocaml.alert deprecated "use [local_id] instead"] 11 | 12 | module VarId = LocalId [@@ocaml.alert deprecated "use [LocalId] instead"] 13 | 14 | let all_binops = 15 | [ 16 | BitXor; 17 | BitAnd; 18 | BitOr; 19 | Eq; 20 | Lt; 21 | Le; 22 | Ne; 23 | Ge; 24 | Gt; 25 | Div; 26 | Rem; 27 | Add; 28 | Sub; 29 | Mul; 30 | Shl; 31 | Shr; 32 | ] 33 | -------------------------------------------------------------------------------- /charon-ml/src/ExpressionsUtils.ml: -------------------------------------------------------------------------------- 1 | open Expressions 2 | 3 | let unop_can_fail (unop : unop) : bool = 4 | match unop with 5 | | Neg | Cast _ | PtrMetadata | ArrayToSlice _ -> true 6 | | Not -> false 7 | 8 | let binop_can_fail (binop : binop) : bool = 9 | match binop with 10 | | BitXor 11 | | BitAnd 12 | | BitOr 13 | | Eq 14 | | Lt 15 | | Le 16 | | Ne 17 | | Ge 18 | | Gt 19 | | WrappingAdd 20 | | WrappingSub 21 | | WrappingMul 22 | | CheckedAdd 23 | | CheckedSub 24 | | CheckedMul 25 | | Cmp -> false 26 | | Div | Rem | Add | Sub | Mul | Shl | Shr | Offset -> true 27 | -------------------------------------------------------------------------------- /charon-ml/src/LlbcAst.ml: -------------------------------------------------------------------------------- 1 | open Types 2 | open Values 3 | open Expressions 4 | open Meta 5 | include GAst 6 | include Generated_LlbcAst 7 | 8 | type expr_body = statement gexpr_body [@@deriving show] 9 | type fun_body = expr_body [@@deriving show] 10 | type fun_decl = statement gfun_decl [@@deriving show] 11 | 12 | (** LLBC crate *) 13 | type crate = statement gcrate [@@deriving show] 14 | -------------------------------------------------------------------------------- /charon-ml/src/LlbcOfJson.ml: -------------------------------------------------------------------------------- 1 | (** Functions to load LLBC ASTs from json. 2 | 3 | See the comments for {!Charon.GAstOfJson} 4 | *) 5 | 6 | open OfJsonBasic 7 | open Types 8 | open LlbcAst 9 | include GAstOfJson 10 | include Generated_LlbcOfJson 11 | 12 | let expr_body_of_json (ctx : of_json_ctx) (js : json) : 13 | (expr_body, string) result = 14 | combine_error_msgs js __FUNCTION__ 15 | (match js with 16 | | `Assoc [ ("Structured", body) ] -> 17 | let* body = gexpr_body_of_json block_of_json ctx body in 18 | Ok body 19 | | _ -> Error "") 20 | 21 | let crate_of_json (js : json) : (crate, string) result = 22 | gcrate_of_json expr_body_of_json js 23 | -------------------------------------------------------------------------------- /charon-ml/src/Meta.ml: -------------------------------------------------------------------------------- 1 | (** Meta data like code spans *) 2 | include Generated_Meta 3 | 4 | (** Ordered file name *) 5 | module OrderedFileName : Collections.OrderedType with type t = file_name = 6 | struct 7 | type t = file_name 8 | 9 | let compare = compare_file_name 10 | let to_string s = show_file_name s 11 | let pp_t fmt s = pp_file_name fmt s 12 | let show_t s = show_file_name s 13 | end 14 | 15 | module FileNameSet = Collections.MakeSet (OrderedFileName) 16 | module FileNameMap = Collections.MakeMap (OrderedFileName) 17 | -------------------------------------------------------------------------------- /charon-ml/src/MetaUtils.ml: -------------------------------------------------------------------------------- 1 | open Meta 2 | 3 | let loc_min (l0 : loc) (l1 : loc) : loc = 4 | if l0.line = l1.line then { line = l0.line; col = Int.min l0.col l1.col } 5 | else if l0.line < l1.line then l0 6 | else l1 7 | 8 | let loc_max (l0 : loc) (l1 : loc) : loc = 9 | if l0.line = l1.line then { line = l0.line; col = Int.max l0.col l1.col } 10 | else if l0.line > l1.line then l0 11 | else l1 12 | 13 | (** See the comments in [meta_utils.rs] in Charon. *) 14 | let combine_span (m0 : span) (m1 : span) : span option = 15 | if m0.span.file = m1.span.file then 16 | let span = 17 | { 18 | file = m0.span.file; 19 | beg_loc = loc_min m0.span.beg_loc m1.span.beg_loc; 20 | end_loc = loc_max m0.span.end_loc m1.span.end_loc; 21 | } 22 | in 23 | Some { span; generated_from_span = None } 24 | else None 25 | 26 | (** Safely combine two spans, even if they do not come from the same file - 27 | if this happens, we simply use the first span. *) 28 | let safe_combine_span (m0 : span) (m1 : span) : span = 29 | match combine_span m0 m1 with 30 | | None -> m0 31 | | Some m -> m 32 | 33 | module OrderedSpan : Collections.OrderedType with type t = span = struct 34 | type t = span 35 | 36 | let compare = compare_span 37 | let to_string = show_span 38 | let pp_t fmt x = Format.pp_print_string fmt (show_span x) 39 | let show_t = show_span 40 | end 41 | 42 | module SpanSet = Collections.MakeSet (OrderedSpan) 43 | module SpanMap = Collections.MakeMap (OrderedSpan) 44 | -------------------------------------------------------------------------------- /charon-ml/src/PrintUtils.ml: -------------------------------------------------------------------------------- 1 | open Types 2 | open Expressions 3 | open GAst 4 | 5 | let option_to_string (to_string : 'a -> string) (x : 'a option) : string = 6 | match x with 7 | | Some x -> "Some (" ^ to_string x ^ ")" 8 | | None -> "None" 9 | 10 | let block_id_to_string (id : UllbcAst.BlockId.id) : string = 11 | "block@" ^ UllbcAst.BlockId.to_string id 12 | 13 | (** The formatting environment can be incomplete: if some information is missing 14 | (for instance we can't find the type variable for a given index) we print 15 | the id in raw format. *) 16 | type 'fun_body fmt_env = { 17 | crate : 'fun_body gcrate; 18 | generics : generic_params list; 19 | (** We have a stack of generic parameters, because we can dive into 20 | binders (for instance because of the arrow type). 21 | *) 22 | locals : (local_id * string option) list; 23 | (** The local variables don't need to be ordered (same as the generics) *) 24 | } 25 | 26 | let of_crate (crate : 'fun_body gcrate) : 'fun_body fmt_env = 27 | { crate; generics = []; locals = [] } 28 | 29 | let fmt_env_update_generics_and_preds (env : 'a fmt_env) 30 | (generics : generic_params) : 'a fmt_env = 31 | { env with generics = generics :: env.generics } 32 | 33 | let fmt_env_push_regions (env : 'a fmt_env) (regions : region_var list) : 34 | 'a fmt_env = 35 | { 36 | env with 37 | generics = { TypesUtils.empty_generic_params with regions } :: env.generics; 38 | } 39 | -------------------------------------------------------------------------------- /charon-ml/src/PrintValues.ml: -------------------------------------------------------------------------------- 1 | (** Pretty-printing for primitive values *) 2 | 3 | open Values 4 | open Types 5 | 6 | let integer_type_to_string = function 7 | | Isize -> "isize" 8 | | I8 -> "i8" 9 | | I16 -> "i16" 10 | | I32 -> "i32" 11 | | I64 -> "i64" 12 | | I128 -> "i128" 13 | | Usize -> "usize" 14 | | U8 -> "u8" 15 | | U16 -> "u16" 16 | | U32 -> "u32" 17 | | U64 -> "u64" 18 | | U128 -> "u128" 19 | 20 | let float_type_to_string = function 21 | | F16 -> "f16" 22 | | F32 -> "f32" 23 | | F64 -> "f64" 24 | | F128 -> "f128" 25 | 26 | let literal_type_to_string (ty : literal_type) : string = 27 | match ty with 28 | | TInteger ity -> integer_type_to_string ity 29 | | TFloat fty -> float_type_to_string fty 30 | | TBool -> "bool" 31 | | TChar -> "char" 32 | 33 | let big_int_to_string (bi : big_int) : string = Z.to_string bi 34 | 35 | let scalar_value_to_string (sv : scalar_value) : string = 36 | big_int_to_string sv.value ^ ": " ^ integer_type_to_string sv.int_ty 37 | 38 | let float_value_to_string (fv : float_value) : string = 39 | fv.float_value ^ ": " ^ float_type_to_string fv.float_ty 40 | 41 | let literal_to_string (lit : literal) : string = 42 | match lit with 43 | | VScalar sv -> scalar_value_to_string sv 44 | | VFloat fv -> float_value_to_string fv 45 | | VBool b -> Bool.to_string b 46 | | VChar c -> Uchar.to_string c 47 | | VStr s -> "\"" ^ s ^ "\"" 48 | | VByteStr bs -> "[" ^ String.concat ", " (List.map string_of_int bs) ^ "]" 49 | -------------------------------------------------------------------------------- /charon-ml/src/Uchar.ml: -------------------------------------------------------------------------------- 1 | include Stdlib.Uchar 2 | 3 | let pp fmt u = 4 | if is_char u then Format.fprintf fmt "'%c'" (to_char u) 5 | else Format.fprintf fmt "'\\x%x'" (to_int u) 6 | 7 | let to_string u = Format.asprintf "%a" pp u 8 | -------------------------------------------------------------------------------- /charon-ml/src/UllbcAst.ml: -------------------------------------------------------------------------------- 1 | open Types 2 | open Values 3 | open Expressions 4 | open Meta 5 | open Identifiers 6 | include GAst 7 | include Generated_UllbcAst 8 | 9 | type expr_body = blocks gexpr_body [@@deriving show] 10 | type fun_body = expr_body [@@deriving show] 11 | type fun_decl = blocks gfun_decl [@@deriving show] 12 | 13 | (** ULLBC crate *) 14 | type crate = blocks gcrate [@@deriving show] 15 | -------------------------------------------------------------------------------- /charon-ml/src/UllbcAstUtils.ml: -------------------------------------------------------------------------------- 1 | include GAstUtils 2 | -------------------------------------------------------------------------------- /charon-ml/src/UllbcOfJson.ml: -------------------------------------------------------------------------------- 1 | (** Functions to load ULLBC ASTs from json. 2 | 3 | See the comments for {!GAstOfJson} 4 | *) 5 | 6 | open OfJsonBasic 7 | open Types 8 | open Expressions 9 | open UllbcAst 10 | include GAstOfJson 11 | include Generated_UllbcOfJson 12 | 13 | let expr_body_of_json (ctx : of_json_ctx) (js : json) : 14 | (expr_body, string) result = 15 | combine_error_msgs js __FUNCTION__ 16 | (match js with 17 | | `Assoc [ ("Unstructured", body) ] -> 18 | let* body = gexpr_body_of_json blocks_of_json ctx body in 19 | Ok body 20 | | _ -> Error "") 21 | 22 | let crate_of_json (js : json) : (crate, string) result = 23 | gcrate_of_json expr_body_of_json js 24 | -------------------------------------------------------------------------------- /charon-ml/src/Utils.ml: -------------------------------------------------------------------------------- 1 | exception IntegerOverflow of unit 2 | exception Unimplemented 3 | 4 | (** Utility exception 5 | 6 | When looking for something while exploring a term, it can be easier to 7 | just throw an exception to signal we found what we were looking for. 8 | *) 9 | exception Found 10 | 11 | (** Union Find *) 12 | module UF = UnionFind.Make (UnionFind.StoreMap) 13 | -------------------------------------------------------------------------------- /charon-ml/src/Values.ml: -------------------------------------------------------------------------------- 1 | (** The primitive values. *) 2 | include Generated_Values 3 | -------------------------------------------------------------------------------- /charon-ml/src/ValuesUtils.ml: -------------------------------------------------------------------------------- 1 | open Values 2 | 3 | let literal_as_scalar (v : literal) : scalar_value = 4 | match v with 5 | | VScalar v -> v 6 | | _ -> raise (Failure "Unexpected") 7 | 8 | let literal_type_is_integer (t : literal_type) : bool = 9 | match t with 10 | | TInteger _ -> true 11 | | _ -> false 12 | -------------------------------------------------------------------------------- /charon-ml/src/dune: -------------------------------------------------------------------------------- 1 | (include_subdirs unqualified) 2 | 3 | (library 4 | (name charon) ;; The name as used in the project 5 | (public_name charon) ;; The name as revealed to the projects importing this library 6 | (preprocess 7 | (pps ppx_deriving.show ppx_deriving.ord ppx_deriving.eq visitors.ppx)) 8 | (libraries yojson zarith easy_logging name_matcher_parser unionFind)) 9 | 10 | (documentation 11 | (package charon)) 12 | 13 | (env 14 | (_ 15 | (flags 16 | :standard 17 | -safe-string 18 | -g 19 | ;-dsource 20 | -w 21 | -5@8-11-14-30-33-20-21-26-27-39))) 22 | -------------------------------------------------------------------------------- /charon-ml/tests/Tests.ml: -------------------------------------------------------------------------------- 1 | open Charon 2 | open Logging 3 | module EL = Easy_logging.Logging 4 | 5 | (* Set the log level - we use the environment variable "CHARON_LOG" *) 6 | let log = main_log 7 | 8 | let () = 9 | try 10 | let _ = Unix.getenv "CHARON_LOG" in 11 | log#set_level EL.Debug 12 | with Not_found -> log#set_level EL.Info 13 | 14 | (* Call the tests *) 15 | (* llbc files are copied into the `_build` dir by the `(deps)` rule in `./dune`. *) 16 | let () = Test_Deserialize.run_tests "test-outputs" 17 | let () = Test_NameMatcher.run_tests "test-outputs/ml-name-matcher-tests.llbc" 18 | -------------------------------------------------------------------------------- /charon-ml/tests/dune: -------------------------------------------------------------------------------- 1 | (tests 2 | (names Tests) 3 | (modes byte exe) 4 | (modules Tests Test_Deserialize Test_NameMatcher) 5 | (deps 6 | (glob_files_rec ./test-outputs/*)) 7 | (libraries charon)) 8 | -------------------------------------------------------------------------------- /charon-ml/tests/test-outputs: -------------------------------------------------------------------------------- 1 | ../../charon/tests/ui -------------------------------------------------------------------------------- /charon.opam: -------------------------------------------------------------------------------- 1 | # This file is generated by dune, edit dune-project instead 2 | opam-version: "2.0" 3 | version: "0.1" 4 | synopsis: 5 | "Manipulation of Low-level Borrow Calculus, a MIR-like representation for Rust Code" 6 | description: """ 7 | 8 | This library allows for manipulation of LLBC, the language output by 9 | Charon. Charon acts as an interface between the rustc compiler and program 10 | verification projects. Its purpose is to process Rust .rs files and convert 11 | them into files easy to handle by program verifiers.""" 12 | maintainer: [ 13 | "Son Ho" "Jonathan Protzenko" "Aymeric Fromherz" "Sidney Congard" 14 | ] 15 | authors: ["Son Ho" "Jonathan Protzenko" "Aymeric Fromherz" "Sidney Congard"] 16 | license: "Apache-2.0" 17 | homepage: "https://github.com/AeneasVerif/charon" 18 | bug-reports: "https://github.com/AeneasVerif/charon/issues" 19 | depends: [ 20 | "dune" {>= "3.7"} 21 | "easy_logging" 22 | "ppx_deriving" 23 | "unionFind" 24 | "visitors" 25 | "yojson" 26 | "zarith" 27 | "name_matcher_parser" 28 | "ocamlformat" {with-test} 29 | "odoc" {with-doc} 30 | ] 31 | build: [ 32 | ["dune" "subst"] {dev} 33 | [ 34 | "dune" 35 | "build" 36 | "-p" 37 | name 38 | "-j" 39 | jobs 40 | "@install" 41 | "@runtest" {with-test} 42 | "@doc" {with-doc} 43 | ] 44 | ] 45 | dev-repo: "git+https://github.com/AeneasVerif/charon.git" 46 | -------------------------------------------------------------------------------- /charon/Charon.toml: -------------------------------------------------------------------------------- 1 | [charon] 2 | # This filters Charon to keep only the type definitions we care about for `generate-ml`. 3 | exclude = [ 4 | "_", 5 | "crate::_", 6 | "crate::ast::_", 7 | ] 8 | include = [ 9 | "alloc::alloc::Global", 10 | "alloc::string::String", 11 | "alloc::vec::Vec", 12 | "core::cmp::Ordering", 13 | "core::ops::control_flow::ControlFlow", 14 | "core::option::Option", 15 | "crate::ast", 16 | "crate::ast::expressions", 17 | "crate::ast::gast", 18 | "crate::ast::krate", 19 | "crate::ast::llbc_ast", 20 | "crate::ast::meta", 21 | "crate::ast::names", 22 | "crate::ast::types", 23 | "crate::ast::ullbc_ast", 24 | "crate::ast::values", 25 | "crate::ids::vector::Vector", 26 | "crate::options", 27 | "crate::transform::reorder_decls::DeclarationGroup", 28 | "crate::transform::reorder_decls::GDeclarationGroup", 29 | "std::path::PathBuf", 30 | ] 31 | -------------------------------------------------------------------------------- /charon/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all: build 3 | 4 | .PHONY: build 5 | build: format 6 | CARGO_PROFILE_RELEASE_DEBUG=true cargo build --release 7 | 8 | .PHONY: format 9 | format: 10 | cargo fmt 11 | 12 | .PHONY: test 13 | test: 14 | cargo test 15 | 16 | .PHONY: test-popular-crates 17 | test-popular-crates: 18 | cargo test --release --features popular-crates-test --test popular-crates -- --test-threads 8 19 | 20 | # Build the doc. 21 | # For some reason, I don't manage to build all the packages in one command. 22 | .PHONY: doc 23 | doc: 24 | cargo doc --no-deps -p macros --document-private-items 25 | cargo doc --no-deps --document-private-items 26 | 27 | .PHONY: clean-generated 28 | clean-generated: 29 | find tests -name '*.llbc' -delete 30 | 31 | .PHONY: clean 32 | clean: clean-generated 33 | rm -rf target 34 | -------------------------------------------------------------------------------- /charon/macros/.gitignore: -------------------------------------------------------------------------------- 1 | # We don't need to track the Cargo.lock file in this crate. 2 | # Note that we track those files in the other crates only for Nix. 3 | *.lock -------------------------------------------------------------------------------- /charon/macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "macros" 3 | version = "0.1.0" 4 | authors = ["Son Ho "] 5 | edition = "2021" 6 | license = "Apache-2.0" 7 | 8 | [lib] 9 | proc-macro = true 10 | 11 | [dependencies] 12 | proc-macro2 = "1.0" 13 | quote = "1.0" 14 | syn = { version = "2.0.0", features = ["full"] } 15 | 16 | [dev-dependencies] 17 | assert_tokens_eq = "0.1.0" 18 | -------------------------------------------------------------------------------- /charon/macros/README.md: -------------------------------------------------------------------------------- 1 | # Macros 2 | 3 | This crate defines some macros used in Charon: for technical reasons, some Rust macros 4 | can't be defined and used in the same crate. 5 | -------------------------------------------------------------------------------- /charon/rust-toolchain: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2025-03-29" 3 | components = [ "rust-src", "rustc-dev", "llvm-tools-preview" ] 4 | -------------------------------------------------------------------------------- /charon/src/ast/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod builtins; 2 | pub mod expressions; 3 | pub mod expressions_utils; 4 | pub mod gast; 5 | pub mod gast_utils; 6 | pub mod krate; 7 | pub mod llbc_ast; 8 | pub mod llbc_ast_utils; 9 | pub mod meta; 10 | pub mod meta_utils; 11 | pub mod names; 12 | pub mod names_utils; 13 | pub mod types; 14 | pub mod types_utils; 15 | pub mod ullbc_ast; 16 | pub mod ullbc_ast_utils; 17 | pub mod values; 18 | pub mod values_utils; 19 | pub mod visitor; 20 | 21 | // Re-export everything except llbc/ullbc, for convenience. 22 | pub use crate::errors::Error; 23 | pub use crate::ids::Vector; 24 | pub use builtins::*; 25 | pub use expressions::*; 26 | pub use gast::*; 27 | pub use krate::*; 28 | pub use meta::*; 29 | pub use names::*; 30 | pub use types::*; 31 | pub use types_utils::*; 32 | pub use values::*; 33 | pub use visitor::*; 34 | -------------------------------------------------------------------------------- /charon/src/bin/charon-driver/translate/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod get_mir; 2 | pub mod resolve_path; 3 | pub mod translate_bodies; 4 | pub mod translate_closures; 5 | pub mod translate_constants; 6 | pub mod translate_crate_to_ullbc; 7 | pub mod translate_ctx; 8 | pub mod translate_functions_to_ullbc; 9 | pub mod translate_predicates; 10 | pub mod translate_traits; 11 | pub mod translate_types; 12 | -------------------------------------------------------------------------------- /charon/src/bin/generate-ml/templates/.ocamlformat-ignore: -------------------------------------------------------------------------------- 1 | *.ml 2 | -------------------------------------------------------------------------------- /charon/src/bin/generate-ml/templates/Expressions.ml: -------------------------------------------------------------------------------- 1 | (** WARNING: this file is partially auto-generated. Do not edit `src/Expressions.ml` 2 | by hand. Edit `templates/Expressions.ml` instead, or improve the code 3 | generation tool so avoid the need for hand-writing things. 4 | 5 | `templates/Expressions.ml` contains the manual definitions and some `(* 6 | __REPLACEn__ *)` comments. These comments are replaced by auto-generated 7 | definitions by running `make generate-ml` in the crate root. The 8 | code-generation code is in `charon/src/bin/generate-ml`. 9 | *) 10 | open Identifiers 11 | open Types 12 | open Values 13 | module LocalId = IdGen () 14 | module GlobalDeclId = Types.GlobalDeclId 15 | module FunDeclId = Types.FunDeclId 16 | 17 | (* __REPLACE0__ *) 18 | -------------------------------------------------------------------------------- /charon/src/bin/generate-ml/templates/GAst.ml: -------------------------------------------------------------------------------- 1 | (** WARNING: this file is partially auto-generated. Do not edit `GAst.ml` 2 | by hand. Edit `GAst.template.ml` instead, or improve the code 3 | generation tool so avoid the need for hand-writing things. 4 | 5 | `GAst.template.ml` contains the manual definitions and some `(* 6 | __REPLACEn__ *)` comments. These comments are replaced by auto-generated 7 | definitions by running `make generate-ml` in the crate root. The 8 | code-generation code is in `charon/src/bin/generate-ml`. 9 | *) 10 | 11 | open Types 12 | open Meta 13 | open Expressions 14 | 15 | module FunDeclId = Expressions.FunDeclId 16 | module GlobalDeclId = Expressions.GlobalDeclId 17 | module TraitDeclId = Types.TraitDeclId 18 | module TraitImplId = Types.TraitImplId 19 | module TraitClauseId = Types.TraitClauseId 20 | 21 | (* Imports *) 22 | type builtin_fun_id = Expressions.builtin_fun_id [@@deriving show, ord] 23 | type fun_id = Expressions.fun_id [@@deriving show, ord] 24 | type fun_id_or_trait_method_ref = Expressions.fun_id_or_trait_method_ref [@@deriving show, ord] 25 | type fun_decl_id = Types.fun_decl_id [@@deriving show, ord] 26 | 27 | (* __REPLACE0__ *) 28 | 29 | (* __REPLACE1__ *) 30 | 31 | (* __REPLACE2__ *) 32 | 33 | (* __REPLACE3__ *) 34 | 35 | (* __REPLACE4__ *) 36 | [@@deriving show] 37 | -------------------------------------------------------------------------------- /charon/src/bin/generate-ml/templates/GAstOfJson.ml: -------------------------------------------------------------------------------- 1 | (** WARNING: this file is partially auto-generated. Do not edit `GAstOfJson.ml` 2 | by hand. Edit `GAstOfJson.template.ml` instead, or improve the code 3 | generation tool so avoid the need for hand-writing things. 4 | 5 | `GAstOfJson.template.ml` contains the manual definitions and some `(* 6 | __REPLACEn__ *)` comments. These comments are replaced by auto-generated 7 | definitions by running `make generate-ml` in the crate root. The 8 | code-generation code is in `charon/src/bin/generate-ml`. 9 | *) 10 | 11 | open Yojson.Basic 12 | open OfJsonBasic 13 | open Identifiers 14 | open Meta 15 | open Values 16 | open Types 17 | open Scalars 18 | open Expressions 19 | open GAst 20 | module FileId = IdGen () 21 | 22 | (** The default logger *) 23 | let log = Logging.llbc_of_json_logger 24 | 25 | type id_to_file_map = file FileId.Map.t 26 | type of_json_ctx = id_to_file_map 27 | 28 | let path_buf_of_json = string_of_json 29 | 30 | (* __REPLACE0__ *) 31 | -------------------------------------------------------------------------------- /charon/src/bin/generate-ml/templates/LlbcAst.ml: -------------------------------------------------------------------------------- 1 | open GAst 2 | open Types 3 | open Values 4 | open Expressions 5 | open Meta 6 | 7 | (* __REPLACE0__ *) 8 | -------------------------------------------------------------------------------- /charon/src/bin/generate-ml/templates/LlbcOfJson.ml: -------------------------------------------------------------------------------- 1 | open OfJsonBasic 2 | open Types 3 | open LlbcAst 4 | open GAstOfJson 5 | 6 | (* __REPLACE0__ *) 7 | -------------------------------------------------------------------------------- /charon/src/bin/generate-ml/templates/Meta.ml: -------------------------------------------------------------------------------- 1 | (** WARNING: this file is partially auto-generated. Do not edit `src/Meta.ml` 2 | by hand. Edit `templates/Meta.ml` instead, or improve the code 3 | generation tool so avoid the need for hand-writing things. 4 | 5 | `templates/Meta.ml` contains the manual definitions and some `(* 6 | __REPLACEn__ *)` comments. These comments are replaced by auto-generated 7 | definitions by running `make generate-ml` in the crate root. The 8 | code-generation code is in `charon/src/bin/generate-ml`. 9 | *) 10 | 11 | type path_buf = string 12 | [@@deriving show, ord, eq] 13 | 14 | (* __REPLACE0__ *) 15 | [@@deriving show, ord, eq] 16 | -------------------------------------------------------------------------------- /charon/src/bin/generate-ml/templates/UllbcAst.ml: -------------------------------------------------------------------------------- 1 | open Types 2 | open Values 3 | open Expressions 4 | open Meta 5 | open Identifiers 6 | open GAst 7 | 8 | module BlockId = IdGen () 9 | 10 | (* __REPLACE0__ *) 11 | 12 | (* __REPLACE1__ *) 13 | -------------------------------------------------------------------------------- /charon/src/bin/generate-ml/templates/UllbcOfJson.ml: -------------------------------------------------------------------------------- 1 | open OfJsonBasic 2 | open Types 3 | open Expressions 4 | open UllbcAst 5 | open GAstOfJson 6 | 7 | (* __REPLACE0__ *) 8 | -------------------------------------------------------------------------------- /charon/src/bin/generate-ml/templates/Values.ml: -------------------------------------------------------------------------------- 1 | (** The primitive values. *) 2 | include BigInt 3 | include Uchar 4 | 5 | (* __REPLACE0__ *) 6 | -------------------------------------------------------------------------------- /charon/src/pretty/mod.rs: -------------------------------------------------------------------------------- 1 | //! This module contains functions to pretty-print charon types. 2 | pub mod fmt_with_ctx; 3 | pub mod formatter; 4 | pub use fmt_with_ctx::FmtWithCtx; 5 | -------------------------------------------------------------------------------- /charon/src/transform/filter_invisible_trait_impls.rs: -------------------------------------------------------------------------------- 1 | //! We cannot filter trait impls by name before translating them, because we need to know the 2 | //! trait/type pair that is being implemented. We therefore filter them in a post-processing pass. 3 | use std::collections::HashSet; 4 | 5 | use crate::ast::*; 6 | 7 | use super::{ctx::TransformPass, TransformCtx}; 8 | 9 | pub struct Transform; 10 | impl TransformPass for Transform { 11 | fn transform_ctx(&self, ctx: &mut TransformCtx) { 12 | let exclude: HashSet = ctx 13 | .translated 14 | .trait_impls 15 | .iter() 16 | .filter(|timpl| ctx.opacity_for_name(&timpl.item_meta.name).is_invisible()) 17 | .map(|timpl| timpl.def_id) 18 | .collect(); 19 | 20 | for id in exclude { 21 | ctx.translated.trait_impls.remove(id); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /charon/src/transform/insert_assign_return_unit.rs: -------------------------------------------------------------------------------- 1 | //! When the function's return type is unit, the generated MIR doesn't 2 | //! set the return value to `()`. This can be a concern: in the case 3 | //! of AENEAS, it means the return variable contains ⊥ upon returning. 4 | //! For this reason, when the function has return type unit, we insert 5 | //! an extra assignment just before returning. 6 | use crate::transform::TransformCtx; 7 | use crate::ullbc_ast::*; 8 | 9 | use super::ctx::UllbcPass; 10 | 11 | pub struct Transform; 12 | impl UllbcPass for Transform { 13 | fn transform_function(&self, _ctx: &mut TransformCtx, decl: &mut FunDecl) { 14 | if decl.signature.output.is_unit() { 15 | if let Ok(body) = &mut decl.body { 16 | let body = body.as_unstructured_mut().unwrap(); 17 | for block in &mut body.body { 18 | if let RawTerminator::Return = block.terminator.content { 19 | let return_place = body.locals.return_place(); 20 | let assign_st = Statement::new( 21 | block.terminator.span, 22 | RawStatement::Assign(return_place, Rvalue::unit_value()), 23 | ); 24 | block.statements.push(assign_st) 25 | } 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /charon/src/transform/prettify_cfg.rs: -------------------------------------------------------------------------------- 1 | use crate::llbc_ast::*; 2 | use crate::transform::TransformCtx; 3 | 4 | use super::ctx::LlbcPass; 5 | 6 | pub struct Transform; 7 | 8 | impl Transform { 9 | fn update_statements(locals: &Locals, seq: &mut [Statement]) -> Vec { 10 | // Remove double aborts. This can happen when a function call is turned into an `Abort` by 11 | // `inline_local_panic_functions`. 12 | if let [Statement { 13 | content: RawStatement::Abort(_), 14 | .. 15 | }, Statement { 16 | content: second_abort @ RawStatement::Abort(_), 17 | .. 18 | }, ..] = seq 19 | { 20 | *second_abort = RawStatement::Nop; 21 | return Vec::new(); 22 | } 23 | if let [Statement { 24 | content: RawStatement::Call(call), 25 | .. 26 | }, Statement { 27 | content: second_abort @ RawStatement::Abort(_), 28 | .. 29 | }, ..] = seq 30 | && locals[call.dest.local_id()].ty.kind().is_never() 31 | { 32 | *second_abort = RawStatement::Nop; 33 | return Vec::new(); 34 | } 35 | 36 | Vec::new() 37 | } 38 | } 39 | 40 | impl LlbcPass for Transform { 41 | fn transform_body(&self, _ctx: &mut TransformCtx, b: &mut ExprBody) { 42 | b.body 43 | .transform_sequences(|seq| Transform::update_statements(&b.locals, seq)) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /charon/src/transform/remove_drop_never.rs: -------------------------------------------------------------------------------- 1 | //! The MIR code often contains variables with type `!` that come from `panic!`s and similar 2 | //! `!`-returning` functions. 3 | //! 4 | //! We want to get rid of these variables since they are never initialized. The only instruction 5 | //! that uses them is `StorageLive`/`StorageDead`; we remove these, which may hide some UB but 6 | //! shouldn't have other consequences. 7 | //! 8 | //! The now-unused local will then be removed in `remove_unused_locals`. 9 | use crate::transform::TransformCtx; 10 | use crate::ullbc_ast::*; 11 | 12 | use super::ctx::UllbcPass; 13 | 14 | pub struct Transform; 15 | impl UllbcPass for Transform { 16 | fn transform_body(&self, _ctx: &mut TransformCtx, b: &mut ExprBody) { 17 | let locals = b.locals.clone(); 18 | b.visit_statements(|st: &mut Statement| { 19 | // Remove any `Storage{Live,Dead}(x)` where `x` has type `!`. Otherwise leave it unchanged. 20 | if let RawStatement::StorageLive(var_id) | RawStatement::StorageDead(var_id) = 21 | &st.content 22 | && locals[*var_id].ty.is_never() 23 | { 24 | st.content = RawStatement::Nop; 25 | } 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /charon/src/transform/remove_nops.rs: -------------------------------------------------------------------------------- 1 | //! Remove the useless no-ops. 2 | use crate::ast::*; 3 | use crate::transform::TransformCtx; 4 | 5 | use super::ctx::TransformPass; 6 | 7 | pub struct Transform; 8 | impl TransformPass for Transform { 9 | fn transform_ctx(&self, ctx: &mut TransformCtx) { 10 | ctx.for_each_fun_decl(|_ctx, fun| { 11 | if let Ok(body) = &mut fun.body { 12 | match body { 13 | Body::Unstructured(body) => { 14 | for blk in &mut body.body { 15 | if blk.statements.iter().any(|st| st.content.is_nop()) { 16 | blk.statements.retain(|st| !st.content.is_nop()) 17 | } 18 | } 19 | } 20 | Body::Structured(body) => { 21 | body.body.visit_blocks_bwd(|blk: &mut llbc_ast::Block| { 22 | // Remove all the `Nop`s from this sequence. 23 | if blk.statements.iter().any(|st| st.content.is_nop()) { 24 | blk.statements.retain(|st| !st.content.is_nop()) 25 | } 26 | }); 27 | } 28 | } 29 | } 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /charon/src/transform/remove_unused_methods.rs: -------------------------------------------------------------------------------- 1 | //! Remove the trait/impl methods that were not translated. 2 | use crate::ast::*; 3 | 4 | use super::{ctx::TransformPass, TransformCtx}; 5 | 6 | pub struct Transform; 7 | impl TransformPass for Transform { 8 | fn transform_ctx(&self, ctx: &mut TransformCtx) { 9 | let method_is_translated = |(_, method): &(TraitItemName, Binder)| { 10 | ctx.translated 11 | .fun_decls 12 | .get(method.skip_binder.id) 13 | .is_some() 14 | }; 15 | // Keep only the methods for which we translated the corresponding `FunDecl`. We ensured 16 | // that this would be translated if the method is used or transparently implemented. 17 | for tdecl in ctx.translated.trait_decls.iter_mut() { 18 | tdecl.methods.retain(method_is_translated); 19 | } 20 | for timpl in ctx.translated.trait_impls.iter_mut() { 21 | timpl.methods.retain(method_is_translated); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /charon/src/transform/update_block_indices.rs: -------------------------------------------------------------------------------- 1 | //! Update the block indices to make sure they are consecutive 2 | 3 | use std::mem; 4 | 5 | use crate::ids::*; 6 | use crate::transform::TransformCtx; 7 | use crate::ullbc_ast::*; 8 | 9 | use super::ctx::UllbcPass; 10 | 11 | pub struct Transform; 12 | impl UllbcPass for Transform { 13 | fn transform_body(&self, _ctx: &mut TransformCtx, b: &mut ExprBody) { 14 | // Push each block into a new vector to make it consecutive and return the map from old to 15 | // new ids. 16 | let id_map: Vector = 17 | mem::take(&mut b.body).map(|block| b.body.push(block)); 18 | 19 | // Update the ids. 20 | b.body 21 | .dyn_visit_in_body_mut(|id: &mut BlockId| *id = id_map[*id]); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /charon/tests/cargo/build-script.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | pub fn test_cargo_build_script::FOO() -> u8 4 | { 5 | let @0: u8; // return 6 | 7 | @0 := const (42 : u8) 8 | return 9 | } 10 | 11 | pub const test_cargo_build_script::FOO: u8 = test_cargo_build_script::FOO() 12 | 13 | // Full name: test_cargo_build_script::main 14 | fn main() 15 | { 16 | let @0: (); // return 17 | 18 | @0 := () 19 | @0 := () 20 | return 21 | } 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /charon/tests/cargo/build-script/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "test-cargo-build-script" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /charon/tests/cargo/build-script/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-cargo-build-script" 3 | version = "0.1.0" 4 | authors = ["Son Ho "] 5 | edition = "2021" 6 | -------------------------------------------------------------------------------- /charon/tests/cargo/build-script/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // Set something that we can detect in `main.rs` to be sure the build script was used 3 | // correctly. 4 | println!("cargo:rustc-cfg=abc"); 5 | } 6 | -------------------------------------------------------------------------------- /charon/tests/cargo/build-script/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(unexpected_cfgs)] 2 | #[cfg(abc)] 3 | pub const FOO: u8 = 42; 4 | 5 | // Ensure compilation fails if the build script is not used correctly. 6 | #[cfg(not(abc))] 7 | const _: () = false; 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /charon/tests/cargo/dependencies/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "take_mut" 7 | version = "0.2.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" 10 | 11 | [[package]] 12 | name = "test-cargo-dependencies" 13 | version = "0.1.0" 14 | dependencies = [ 15 | "take_mut", 16 | ] 17 | -------------------------------------------------------------------------------- /charon/tests/cargo/dependencies/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-cargo-dependencies" 3 | version = "0.1.0" 4 | authors = ["Son Ho "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | # Important: because of how we use Nix, only the dependencies of charon itself 9 | # will be available when running tests. So the only dependencies we can list 10 | # here must be in `charon/Cargo.toml`. 11 | take_mut = { version = "0.2.2", optional = true } 12 | 13 | [features] 14 | default = [] 15 | # We activate this feature by calling charon with `--cargo-arg=--features=test_feature`. 16 | test_feature = [ "dep:take_mut" ] 17 | -------------------------------------------------------------------------------- /charon/tests/cargo/dependencies/src/main.rs: -------------------------------------------------------------------------------- 1 | //! This tests the invocation of `charon` on a crate with external dependencies. 2 | 3 | #[cfg(not(feature = "test_feature"))] 4 | fn main() {} 5 | 6 | #[cfg(feature = "test_feature")] 7 | fn main() { 8 | fn silly_incr(x: &mut u32) { 9 | take_mut::take(x, |y| y + 1); 10 | } 11 | 12 | let mut x = 0; 13 | silly_incr(&mut x); 14 | assert_eq!(x, 1); 15 | } 16 | -------------------------------------------------------------------------------- /charon/tests/cargo/error-dependencies.out: -------------------------------------------------------------------------------- 1 | error: Trait aliases are not supported 2 | --> /rustc/library/core/src/ptr/metadata.rs:84:1 3 | 4 | note: the error occurred when translating `core::ptr::metadata::Thin`, which is (transitively) used at the following location(s): 5 | --> src/main.rs:16:27 6 | | 7 | 16 | pub fn custom_null() {} 8 | | --------------- 9 | | 10 | ::: src/module.rs:6:13 11 | | 12 | 6 | let _ = core::ptr::null::(); 13 | | ----------------------- 14 | 7 | let _ = crate::opaque::custom_null::(); 15 | | ---------------------------------- 16 | error: Item `core::ptr::metadata::Thin` caused errors; ignoring. 17 | --> /rustc/library/core/src/ptr/metadata.rs:84:1 18 | 19 | ERROR Charon failed to translate this code (2 errors) 20 | error: could not compile `test-cargo` (bin "test-cargo") 21 | 22 | Caused by: -------------------------------------------------------------------------------- /charon/tests/cargo/error-dependencies/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "test-cargo" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /charon/tests/cargo/error-dependencies/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-cargo" 3 | version = "0.1.0" 4 | authors = ["Son Ho "] 5 | edition = "2021" 6 | -------------------------------------------------------------------------------- /charon/tests/cargo/error-dependencies/src/main.rs: -------------------------------------------------------------------------------- 1 | //! This crate tests the error messages that indicates why we attempt to translate a given 2 | //! definition. We try some fun mutual dependencies to test the output, in particular the 3 | //! multi-file output. 4 | #![feature(ptr_metadata)] 5 | #![feature(register_tool)] 6 | #![register_tool(charon)] 7 | 8 | #[charon::opaque] 9 | mod module; 10 | 11 | #[charon::opaque] 12 | mod opaque { 13 | pub fn fun2() { 14 | crate::module::fun3() 15 | } 16 | pub fn custom_null() {} 17 | } 18 | 19 | fn main() { 20 | crate::module::fun1() 21 | } 22 | -------------------------------------------------------------------------------- /charon/tests/cargo/error-dependencies/src/module.rs: -------------------------------------------------------------------------------- 1 | pub fn fun1() { 2 | crate::opaque::fun2() 3 | } 4 | 5 | pub fn fun3() { 6 | let _ = core::ptr::null::(); 7 | let _ = crate::opaque::custom_null::(); 8 | } 9 | -------------------------------------------------------------------------------- /charon/tests/cargo/multi-targets/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "multi-targets" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /charon/tests/cargo/multi-targets/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "multi-targets" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /charon/tests/cargo/multi-targets/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This package should be compiled on both host target and 2 | //! no-std target via cross-compilation to test 3 | //! `charon cargo` supports `-- --target` correctly. 4 | #![no_std] 5 | 6 | #[cfg(target_os = "none")] 7 | pub fn no_os(left: u64, right: u64) -> u64 { 8 | left + right 9 | } 10 | 11 | #[cfg(target_os = "windows")] 12 | pub fn on_windows(left: u64, right: u64) -> u64 { 13 | left + right 14 | } 15 | 16 | #[cfg(target_family = "unix")] 17 | pub fn on_unix(left: u64, right: u64) -> u64 { 18 | left + right 19 | } 20 | -------------------------------------------------------------------------------- /charon/tests/cargo/toml/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "test-cargo-toml" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /charon/tests/cargo/toml/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-cargo-toml" 3 | version = "0.1.0" 4 | authors = ["Son Ho "] 5 | edition = "2021" 6 | -------------------------------------------------------------------------------- /charon/tests/cargo/toml/Charon.toml: -------------------------------------------------------------------------------- 1 | [charon] 2 | extract_opaque_bodies = true 3 | 4 | [rustc] 5 | flags = ["--cfg", "abc"] 6 | -------------------------------------------------------------------------------- /charon/tests/cargo/toml/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(unexpected_cfgs)] 2 | // The `cfg` is here to test that we correctly passed rustc flags from the `Charon.toml`. The call 3 | // to `is_some` is here to exercice the `extract_opaque_bodies` option. 4 | #[cfg(abc)] 5 | fn main() { 6 | let _ = Some(false).is_some(); 7 | } 8 | -------------------------------------------------------------------------------- /charon/tests/cargo/unsafe_.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::fmt::Arguments 4 | #[lang_item("format_arguments")] 5 | pub opaque type Arguments<'a> 6 | where 7 | 'a : 'a, 8 | 9 | // Full name: core::fmt::{Arguments<'a>}#4::new_const 10 | pub fn new_const<'a, const N : usize>(@1: &'a (Array<&'static (Str), const N : usize>)) -> Arguments<'a> 11 | 12 | // Full name: std::io::stdio::_print 13 | pub fn _print<'_0>(@1: Arguments<'_0>) 14 | 15 | // Full name: unsafe::main 16 | fn main() 17 | { 18 | let @0: (); // return 19 | let @1: (); // anonymous local 20 | let @2: (); // anonymous local 21 | let @3: Arguments<'_>; // anonymous local 22 | let @4: &'_ (Array<&'_ (Str), 1 : usize>); // anonymous local 23 | let @5: &'_ (Array<&'_ (Str), 1 : usize>); // anonymous local 24 | let @6: Array<&'_ (Str), 1 : usize>; // anonymous local 25 | 26 | storage_live(@1) 27 | storage_live(@2) 28 | storage_live(@3) 29 | storage_live(@4) 30 | storage_live(@5) 31 | storage_live(@6) 32 | @6 := [const ("Hello, world!\n")] 33 | @5 := &@6 34 | @4 := &*(@5) 35 | @3 := new_const<'_, 1 : usize>(move (@4)) 36 | storage_dead(@4) 37 | @2 := _print<'_>(move (@3)) 38 | storage_dead(@3) 39 | storage_dead(@6) 40 | storage_dead(@5) 41 | storage_dead(@2) 42 | storage_dead(@1) 43 | @0 := () 44 | @0 := () 45 | return 46 | } 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /charon/tests/cargo/unsafe_/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "unsafe" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /charon/tests/cargo/unsafe_/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "unsafe" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /charon/tests/cargo/unsafe_/src/bin/unsafe.rs: -------------------------------------------------------------------------------- 1 | //! Regression test: the crate name being a keyword created a mismatch between the crate namem we 2 | //! use and the one hax uses, which meant crate items were treated as foreign. 3 | fn main() { 4 | println!("Hello, world!"); 5 | } 6 | -------------------------------------------------------------------------------- /charon/tests/cargo/workspace.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: crate1::random_number 4 | pub fn random_number() -> u32 5 | { 6 | let @0: u32; // return 7 | 8 | @0 := const (4 : u32) 9 | return 10 | } 11 | 12 | // Full name: crate2::extra_random_number 13 | pub fn extra_random_number() -> u32 14 | { 15 | let @0: u32; // return 16 | let @1: u32; // anonymous local 17 | 18 | storage_live(@1) 19 | // Even more random. 20 | @1 := random_number() 21 | @0 := copy (@1) + const (1 : u32) 22 | storage_dead(@1) 23 | return 24 | } 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /charon/tests/cargo/workspace/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "crate1" 7 | version = "0.1.0" 8 | 9 | [[package]] 10 | name = "crate2" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "crate1", 14 | ] 15 | -------------------------------------------------------------------------------- /charon/tests/cargo/workspace/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "crate1", 5 | "crate2", 6 | ] 7 | -------------------------------------------------------------------------------- /charon/tests/cargo/workspace/crate1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "crate1" 3 | version = "0.1.0" 4 | authors = ["Son Ho "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /charon/tests/cargo/workspace/crate1/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[inline(always)] 2 | pub fn random_number() -> u32 { 3 | 4 4 | } 5 | -------------------------------------------------------------------------------- /charon/tests/cargo/workspace/crate2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "crate2" 3 | version = "0.1.0" 4 | authors = ["Son Ho "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | crate1 = { path = "../crate1" } 9 | -------------------------------------------------------------------------------- /charon/tests/cargo/workspace/crate2/src/lib.rs: -------------------------------------------------------------------------------- 1 | use crate1::random_number; 2 | 3 | pub fn extra_random_number() -> u32 { 4 | // Even more random. 5 | random_number() + 1 6 | } 7 | -------------------------------------------------------------------------------- /charon/tests/popular-crates/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /charon/tests/ui/.gitignore: -------------------------------------------------------------------------------- 1 | *.rlib 2 | -------------------------------------------------------------------------------- /charon/tests/ui/arrays_const_generics.rs: -------------------------------------------------------------------------------- 1 | //! Exercise the translation of arrays, features not yet supported by Eurydice 2 | 3 | pub fn index_array_generic(s: [u32; N], i: usize) -> u32 { 4 | s[i] 5 | } 6 | 7 | pub fn index_array_generic_call(s: [u32; N], i: usize) -> u32 { 8 | index_array_generic(s, i) 9 | } 10 | 11 | // Using const generics as values 12 | pub fn const_gen_ret() -> usize { 13 | N 14 | } 15 | 16 | // Comes from https://github.com/AeneasVerif/charon/issues/45 17 | // We initialize an array with a variable length (this uses the `repeat` instruction). 18 | pub fn init_array_variable_len() -> [u8; LEN] { 19 | [0u8; LEN] 20 | } 21 | -------------------------------------------------------------------------------- /charon/tests/ui/assoc-const-with-generics.rs: -------------------------------------------------------------------------------- 1 | struct V { 2 | x: [T; N], 3 | } 4 | 5 | impl V { 6 | const LEN: usize = N; // This has generics 7 | } 8 | 9 | trait HasLen { 10 | const LEN: usize; 11 | } 12 | 13 | impl HasLen for [(); N] { 14 | const LEN: usize = N; 15 | } 16 | 17 | impl HasLen for [bool; N] { 18 | const LEN: usize = N + 1; 19 | } 20 | 21 | pub trait HasDefaultLen { 22 | const LEN: usize = M; 23 | // fn use_array(_a: [(); Self::LEN]) {} 24 | } 25 | 26 | impl HasDefaultLen for [(); N] {} 27 | 28 | impl HasDefaultLen for [bool; N] { 29 | // Recursive constant because we can 30 | const LEN: usize = if true { 31 | N 32 | } else { 33 | >::LEN 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /charon/tests/ui/bitwise.rs: -------------------------------------------------------------------------------- 1 | //! Exercise the bitwise operations 2 | pub fn shift_u32(a: u32) -> u32 { 3 | let i: usize = 16; 4 | let mut t = a >> i; 5 | t <<= i; 6 | t 7 | } 8 | 9 | pub fn shift_i32(a: i32) -> i32 { 10 | let i: isize = 16; 11 | let mut t = a >> i; 12 | t <<= i; 13 | t 14 | } 15 | 16 | pub fn xor_u32(a: u32, b: u32) -> u32 { 17 | a ^ b 18 | } 19 | 20 | pub fn or_u32(a: u32, b: u32) -> u32 { 21 | a | b 22 | } 23 | 24 | pub fn and_u32(a: u32, b: u32) -> u32 { 25 | a & b 26 | } 27 | -------------------------------------------------------------------------------- /charon/tests/ui/call-to-known-trait-method.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | //! Test that we pass generics correctly in the `skip_trait_refs_when_known` pass. 3 | #[derive(Default)] 4 | struct Struct(A); 5 | 6 | trait Trait { 7 | type Item; 8 | fn method(); 9 | } 10 | 11 | impl> Trait for Struct { 12 | type Item = (A, B); 13 | fn method() {} 14 | } 15 | 16 | fn main() { 17 | let _x: as Trait>::Item = (0u8, false); 18 | let _y: Struct = Default::default(); 19 | as Trait>::method::(); 20 | } 21 | -------------------------------------------------------------------------------- /charon/tests/ui/closures_with_where.rs: -------------------------------------------------------------------------------- 1 | trait Ops { 2 | fn of_usize(x: usize) -> Self; 3 | } 4 | 5 | fn test>() -> [T; 1] { 6 | core::array::from_fn(|i| T::of_usize(i)) 7 | } 8 | -------------------------------------------------------------------------------- /charon/tests/ui/copy_nonoverlapping.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--extract-opaque-bodies 2 | //@ charon-args=--opaque core::intrinsics::copy_nonoverlapping::precondition_check 3 | 4 | use std::mem; 5 | use std::ptr; 6 | 7 | fn write(x: &mut T, y: &T) { 8 | unsafe { 9 | ptr::copy_nonoverlapping(y, x, 1); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /charon/tests/ui/dictionary_passing_style_woes.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | trait Iterator { 3 | type Item; 4 | } 5 | trait IntoIterator { 6 | type Item; 7 | type IntoIter: Iterator; 8 | } 9 | impl IntoIterator for I { 10 | type Item = I::Item; 11 | type IntoIter = I; 12 | } 13 | 14 | // See https://github.com/lcnr/random-rust-snippets/issues/2 15 | fn callee(t: ::Item) -> ::Item 16 | where 17 | T: Iterator, 18 | { 19 | t 20 | } 21 | 22 | /// For this to typecheck, we would need to use the blanket impl over the local clause, but rustc 23 | /// does the opposite. 24 | fn caller(t: ::Item) -> ::Item 25 | where 26 | T: Iterator + IntoIterator, 27 | { 28 | callee::(t) 29 | } 30 | 31 | trait X { 32 | type Assoc; 33 | fn method(&self) -> Self::Assoc; 34 | } 35 | trait A: X {} 36 | trait B: X {} 37 | 38 | fn a(x: T) -> T::Assoc { 39 | x.method() 40 | } 41 | fn b(x: T) -> T::Assoc { 42 | x.method() 43 | } 44 | 45 | /// This will pick one of the two parent clauses to resolve `T::Assoc` within this body, which is 46 | /// guaranteed to make one of the two calls fail to typecheck. 47 | fn x(x: T) -> (T::Assoc, T::Assoc) { 48 | (a(x), b(x)) 49 | } 50 | -------------------------------------------------------------------------------- /charon/tests/ui/disambiguator.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | fn test_crate::nonzero_disambiguator::my_function() 4 | { 5 | let @0: (); // return 6 | 7 | @0 := () 8 | @0 := () 9 | return 10 | } 11 | 12 | fn test_crate::nonzero_disambiguator::my_function#1() 13 | { 14 | let @0: (); // return 15 | 16 | @0 := () 17 | @0 := () 18 | return 19 | } 20 | 21 | // Full name: test_crate::nonzero_disambiguator 22 | fn nonzero_disambiguator() 23 | { 24 | let @0: (); // return 25 | let @1: bool; // anonymous local 26 | 27 | storage_live(@1) 28 | @1 := const (true) 29 | if move (@1) { 30 | @0 := test_crate::nonzero_disambiguator::my_function() 31 | } 32 | else { 33 | @0 := test_crate::nonzero_disambiguator::my_function#1() 34 | } 35 | storage_dead(@1) 36 | @0 := () 37 | return 38 | } 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /charon/tests/ui/disambiguator.rs: -------------------------------------------------------------------------------- 1 | //! This generates a rare case of a `DefPathData::ValueNs` with non-zero disambiguator. 2 | fn nonzero_disambiguator() { 3 | if true { 4 | fn my_function() {} 5 | my_function() 6 | } else { 7 | fn my_function() {} 8 | my_function() 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /charon/tests/ui/diverging.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::my_panic 4 | fn my_panic(@1: u32) -> ! 5 | { 6 | let @0: !; // return 7 | let _x@1: u32; // arg #1 8 | 9 | panic(core::panicking::panic_explicit) 10 | } 11 | 12 | // Full name: test_crate::do_something_else 13 | fn do_something_else() 14 | { 15 | let @0: (); // return 16 | 17 | @0 := () 18 | @0 := () 19 | return 20 | } 21 | 22 | // Full name: test_crate::call_my_panic 23 | fn call_my_panic() 24 | { 25 | let @0: (); // return 26 | let @1: !; // anonymous local 27 | 28 | storage_live(@1) 29 | @1 := my_panic(const (0 : u32)) 30 | } 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /charon/tests/ui/diverging.rs: -------------------------------------------------------------------------------- 1 | fn my_panic(_x: u32) -> ! { 2 | panic!() 3 | } 4 | 5 | fn do_something_else() {} 6 | 7 | fn call_my_panic() { 8 | my_panic(0); 9 | do_something_else(); 10 | } 11 | -------------------------------------------------------------------------------- /charon/tests/ui/dyn-trait.rs: -------------------------------------------------------------------------------- 1 | #![feature(register_tool)] 2 | #![register_tool(charon)] 3 | use std::fmt::Display; 4 | 5 | // Opaque because we don't support unsize coercions. 6 | #[charon::opaque] 7 | fn construct(x: T) -> Box { 8 | Box::new(x) 9 | } 10 | 11 | fn destruct(x: &dyn Display) -> String { 12 | x.to_string() 13 | } 14 | 15 | // Opaque because we don't support unsize coercions. 16 | #[charon::opaque] 17 | fn combine() { 18 | let x = String::new(); 19 | let _ = destruct(&*construct(x)); 20 | } 21 | 22 | fn foo(_: &(dyn (for<'a> Fn(&'a T) -> T) + 'static), _: &dyn PartialEq>) {} 23 | 24 | fn bar(_: &dyn (Fn(&dyn Display))) {} 25 | -------------------------------------------------------------------------------- /charon/tests/ui/error-dependencies.out: -------------------------------------------------------------------------------- 1 | error: Trait aliases are not supported 2 | --> /rustc/library/core/src/ptr/metadata.rs:84:1 3 | 4 | note: the error occurred when translating `core::ptr::metadata::Thin`, which is (transitively) used at the following location(s): 5 | --> tests/ui/error-dependencies.rs:9:13 6 | | 7 | 9 | let _ = core::ptr::null::(); 8 | | ----------------------- 9 | ... 10 | 16 | let _ = custom_null::(); 11 | | ------------------- 12 | 17 | } 13 | 18 | fn custom_null() {} 14 | | --------------- 15 | error: Item `core::ptr::metadata::Thin` caused errors; ignoring. 16 | --> /rustc/library/core/src/ptr/metadata.rs:84:1 17 | 18 | ERROR Charon failed to translate this code (2 errors) 19 | -------------------------------------------------------------------------------- /charon/tests/ui/error-dependencies.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | //! This file tests the error messages that indicates why we attempt to translate a given 3 | //! definition. 4 | #![feature(ptr_metadata)] 5 | #![feature(register_tool)] 6 | #![register_tool(charon)] 7 | 8 | pub fn main() { 9 | let _ = core::ptr::null::(); 10 | let _ = opaque::other_error(); 11 | } 12 | 13 | #[charon::opaque] 14 | mod opaque { 15 | pub fn other_error() { 16 | let _ = custom_null::(); 17 | } 18 | fn custom_null() {} 19 | } 20 | -------------------------------------------------------------------------------- /charon/tests/ui/external.rs: -------------------------------------------------------------------------------- 1 | //! This module uses external types and functions 2 | 3 | /// This function uses an external function 4 | pub fn swap<'a, T>(x: &'a mut T, y: &'a mut T) { 5 | std::mem::swap(x, y) 6 | } 7 | 8 | /// This function uses external types and functions 9 | pub fn test_new_non_zero_u32(x: u32) -> std::num::NonZeroU32 { 10 | std::num::NonZeroU32::new(x).unwrap() 11 | } 12 | 13 | use std::vec::Vec; 14 | 15 | #[allow(clippy::vec_init_then_push)] 16 | pub fn test_vec_push() { 17 | let mut v: Vec = Vec::new(); 18 | v.push(0); 19 | } 20 | 21 | use std::cell::Cell; 22 | 23 | pub fn use_get(rc: &Cell) -> u32 { 24 | rc.get() 25 | } 26 | 27 | pub fn incr(rc: &mut Cell) { 28 | *rc.get_mut() += 1; 29 | } 30 | -------------------------------------------------------------------------------- /charon/tests/ui/find-sized-clause.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::Trait 4 | trait Trait 5 | 6 | // Full name: core::marker::Sized 7 | #[lang_item("sized")] 8 | pub trait Sized 9 | 10 | // Full name: core::option::Option 11 | #[lang_item("Option")] 12 | pub enum Option 13 | where 14 | [@TraitClause0]: Sized, 15 | { 16 | None, 17 | Some(T), 18 | } 19 | 20 | // Full name: test_crate::{impl Trait for Option[@TraitClause0]} 21 | impl Trait for Option[@TraitClause0] 22 | where 23 | [@TraitClause0]: Sized, 24 | {} 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /charon/tests/ui/find-sized-clause.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--abort-on-error 2 | trait Trait {} 3 | impl Trait for Option {} 4 | -------------------------------------------------------------------------------- /charon/tests/ui/float.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::test_float 4 | fn test_float(@1: f64) -> f64 5 | { 6 | let @0: f64; // return 7 | let x@1: f64; // arg #1 8 | 9 | @0 := copy (x@1) 10 | return 11 | } 12 | 13 | // Full name: test_crate::sum_float 14 | fn sum_float(@1: f64, @2: f64) -> f64 15 | { 16 | let @0: f64; // return 17 | let x@1: f64; // arg #1 18 | let y@2: f64; // arg #2 19 | let @3: f64; // anonymous local 20 | let @4: f64; // anonymous local 21 | 22 | storage_live(@3) 23 | @3 := copy (x@1) 24 | storage_live(@4) 25 | @4 := copy (y@2) 26 | @0 := move (@3) wrapping.+ move (@4) 27 | storage_dead(@4) 28 | storage_dead(@3) 29 | return 30 | } 31 | 32 | // Full name: test_crate::literal_float 33 | fn literal_float() -> f64 34 | { 35 | let @0: f64; // return 36 | let x@1: f64; // local 37 | let y@2: f64; // local 38 | let @3: f64; // anonymous local 39 | let @4: f64; // anonymous local 40 | 41 | storage_live(x@1) 42 | x@1 := const (1 : f64) 43 | storage_live(y@2) 44 | y@2 := const (1.5 : f64) 45 | storage_live(@3) 46 | @3 := copy (x@1) 47 | storage_live(@4) 48 | @4 := copy (y@2) 49 | @0 := move (@3) wrapping.+ move (@4) 50 | storage_dead(@4) 51 | storage_dead(@3) 52 | storage_dead(y@2) 53 | storage_dead(x@1) 54 | return 55 | } 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /charon/tests/ui/float.rs: -------------------------------------------------------------------------------- 1 | fn test_float(x : f64) -> f64 { 2 | x 3 | } 4 | 5 | fn sum_float(x : f64, y : f64) -> f64 { 6 | x + y 7 | } 8 | 9 | fn literal_float () -> f64 { 10 | let x = 1.0f64; 11 | let y = 1.5f64; 12 | x + y 13 | } 14 | -------------------------------------------------------------------------------- /charon/tests/ui/foreign-constant-aux.rs: -------------------------------------------------------------------------------- 1 | //@ skip 2 | pub const CONSTANT: u8 = 16; 3 | -------------------------------------------------------------------------------- /charon/tests/ui/foreign-constant.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | pub fn foreign_constant_aux::CONSTANT() -> u8 4 | 5 | pub const foreign_constant_aux::CONSTANT: u8 = foreign_constant_aux::CONSTANT() 6 | 7 | // Full name: test_crate::foo 8 | fn foo() -> u8 9 | { 10 | let @0: u8; // return 11 | let @1: u8; // anonymous local 12 | 13 | storage_live(@1) 14 | @1 := foreign_constant_aux::CONSTANT 15 | @0 := move (@1) 16 | return 17 | } 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /charon/tests/ui/foreign-constant.rs: -------------------------------------------------------------------------------- 1 | //@ aux-crate=foreign-constant-aux.rs 2 | fn foo() -> u8 { 3 | foreign_constant_aux::CONSTANT 4 | } 5 | -------------------------------------------------------------------------------- /charon/tests/ui/gat-causes-unhandled-ty-clause.out: -------------------------------------------------------------------------------- 1 | error: Generic associated types are not supported 2 | --> tests/ui/gat-causes-unhandled-ty-clause.rs:4:5 3 | | 4 | 4 | type GAT; 5 | | ^^^^^^^^^^^ 6 | 7 | error: Item `test_crate::HasGAT` caused errors; ignoring. 8 | --> tests/ui/gat-causes-unhandled-ty-clause.rs:3:1 9 | | 10 | 3 | trait HasGAT { 11 | | ^^^^^^^^^^^^ 12 | 13 | error: Found unhandled item clause; this is a bug unless the clause is coming from a GAT. 14 | --> tests/ui/gat-causes-unhandled-ty-clause.rs:12:1 15 | | 16 | 12 | / fn floatify() -> ::Assoc 17 | 13 | | where 18 | 14 | | C: HasGAT, 19 | ... | 20 | 17 | | } 21 | | |_^ 22 | 23 | error: Found unhandled item clause; this is a bug unless the clause is coming from a GAT. 24 | --> tests/ui/gat-causes-unhandled-ty-clause.rs:12:1 25 | | 26 | 12 | / fn floatify() -> ::Assoc 27 | 13 | | where 28 | 14 | | C: HasGAT, 29 | ... | 30 | 17 | | } 31 | | |_^ 32 | 33 | ERROR Charon failed to translate this code (4 errors) 34 | -------------------------------------------------------------------------------- /charon/tests/ui/gat-causes-unhandled-ty-clause.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | //! Regression test minimized from the rustc test suite. This used to cause a panic. 3 | trait HasGAT { 4 | type GAT; 5 | type Friend: HasAssoc; 6 | } 7 | 8 | trait HasAssoc { 9 | type Assoc; 10 | } 11 | 12 | fn floatify() -> ::Assoc 13 | where 14 | C: HasGAT, 15 | { 16 | todo!() 17 | } 18 | -------------------------------------------------------------------------------- /charon/tests/ui/generic-associated-types.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | // See also `non-lifetime-gats.rs` 3 | 4 | pub trait LendingIterator { 5 | type Item<'a> 6 | where 7 | Self: 'a; 8 | 9 | fn next<'a>(&'a mut self) -> Option>; 10 | } 11 | 12 | impl<'a, T> LendingIterator for Option<&'a T> { 13 | type Item<'b> 14 | = &'b T 15 | where 16 | Self: 'b; 17 | 18 | fn next<'b>(&'b mut self) -> Option> { 19 | if let Some(item) = self { 20 | let item = &**item; 21 | Some(item) 22 | } else { 23 | None 24 | } 25 | } 26 | } 27 | 28 | pub fn for_each(mut iter: I, mut f: impl for<'a> FnMut(I::Item<'a>)) { 29 | while let Some(item) = iter.next() { 30 | f(item) 31 | } 32 | } 33 | 34 | pub fn main() { 35 | let x = 42; 36 | let iter = Some(&42); 37 | let mut sum = 0; 38 | for_each(iter, |item| sum += *item); 39 | assert_eq!(sum, 42); 40 | } 41 | 42 | pub mod lifetimes { 43 | pub trait Foo { 44 | fn foo(self) -> T; 45 | } 46 | 47 | pub trait Bar<'a> { 48 | type Type<'b>: for<'c> Foo<&'a &'b &'c ()>; 49 | } 50 | 51 | pub fn bar<'x, 'y, 'z, T>(x: >::Type<'y>) -> &'x &'y &'z () 52 | where 53 | T: Bar<'x>, 54 | { 55 | x.foo() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /charon/tests/ui/gosim-demo.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | fn debug_slice(slice: &[T]) { 4 | for x in slice { 5 | eprintln!("- {x:?}"); 6 | } 7 | } 8 | 9 | fn main() { 10 | debug_slice(&[0, 1, 2]); 11 | } 12 | -------------------------------------------------------------------------------- /charon/tests/ui/hide-marker-traits.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::Idx 4 | trait Idx 5 | 6 | // Full name: test_crate::IndexVec 7 | pub struct IndexVec 8 | where 9 | [@TraitClause1]: Idx, 10 | { 11 | i: I, 12 | } 13 | 14 | // Full name: test_crate::Vector 15 | pub struct Vector 16 | where 17 | [@TraitClause1]: Idx, 18 | { 19 | vector: IndexVec[@TraitClause1], 20 | } 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /charon/tests/ui/hide-marker-traits.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--hide-marker-traits 2 | //! Reproduces a crash when substituting variables with the `--hide-marker-traits` option. 3 | trait Idx {} 4 | 5 | pub struct IndexVec 6 | where 7 | I: Idx, 8 | { 9 | i: I, 10 | } 11 | 12 | pub struct Vector 13 | where 14 | I: Idx, 15 | { 16 | vector: IndexVec, 17 | } 18 | -------------------------------------------------------------------------------- /charon/tests/ui/impl-trait.rs: -------------------------------------------------------------------------------- 1 | pub trait Foo { 2 | type Type: Clone; 3 | 4 | fn get_ty(&self) -> &Self::Type; 5 | } 6 | 7 | impl Foo for () { 8 | type Type = u32; 9 | 10 | fn get_ty(&self) -> &u32 { 11 | &42 12 | } 13 | } 14 | 15 | fn mk_foo() -> impl Foo { 16 | () 17 | } 18 | 19 | fn use_foo() { 20 | let foo = mk_foo(); 21 | let _ = foo.get_ty().clone(); 22 | } 23 | 24 | // "Return Position Impl Trait In Trait". This generates a virtual associated type. 25 | pub trait RPITIT { 26 | fn make_foo() -> impl Foo {} 27 | } 28 | 29 | impl RPITIT for () { 30 | fn make_foo() -> impl Foo { 31 | () 32 | } 33 | } 34 | 35 | fn use_tait() { 36 | let foo = T::make_foo(); 37 | let _ = foo.get_ty().clone(); 38 | } 39 | 40 | pub struct WrapClone(T); 41 | pub fn wrap() -> impl for<'a> FnOnce(&'a U) -> WrapClone<&'a U> { 42 | |x| WrapClone(x) 43 | } 44 | 45 | pub fn use_wrap() { 46 | let f = wrap::(); 47 | let _: WrapClone<&u32> = f(&42); 48 | } 49 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-114-opaque-bodies-aux.rs: -------------------------------------------------------------------------------- 1 | //@ skip 2 | #[inline(always)] 3 | pub fn inline_always() -> u32 { 4 | 42 5 | } 6 | 7 | #[inline] 8 | pub fn inline_sometimes() -> u32 { 9 | 42 10 | } 11 | 12 | #[inline(never)] 13 | pub fn inline_never() -> u32 { 14 | 42 15 | } 16 | 17 | // Generics always have MIR in the crate data. 18 | #[inline(never)] 19 | pub fn inline_generic() -> u32 { 20 | 42 21 | } 22 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-114-opaque-bodies.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--extract-opaque-bodies 2 | //@ aux-crate=issue-114-opaque-bodies-aux.rs 3 | 4 | fn use_inlines() -> u32 { 5 | use issue_114_opaque_bodies_aux::*; 6 | inline_always() + inline_sometimes() + inline_never() + inline_generic::() 7 | } 8 | 9 | fn bool_to_opt(b: bool) -> Option<()> { 10 | b.then_some(()) 11 | } 12 | 13 | fn convert(x: i32) -> i64 { 14 | i64::from(x) 15 | } 16 | 17 | fn vec(_x: Vec) {} 18 | 19 | fn max() -> usize { 20 | usize::MAX 21 | } 22 | 23 | fn partial_eq(_x: T) {} 24 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-118-generic-copy.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | 3 | #[derive(Clone, Copy)] 4 | struct Foo; 5 | fn copy_foo(x: Foo) { 6 | let y = x; 7 | let z = x; 8 | } 9 | 10 | fn copy_generic(x: T) { 11 | let y = x; 12 | let z = x; 13 | } 14 | 15 | trait Trait { 16 | type Ty: Copy; 17 | } 18 | fn copy_assoc_ty(x: T::Ty) { 19 | let y = x; 20 | let z = x; 21 | } 22 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-120-bare-discriminant-read.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--extract-opaque-bodies 2 | //@ charon-args=--mir_optimized 3 | //@ rustc-args=-C opt-level=3 4 | #![feature(core_intrinsics)] 5 | #![allow(internal_features)] 6 | 7 | fn discriminant_value(opt: &Option) -> isize { 8 | core::intrinsics::discriminant_value(opt) 9 | } 10 | 11 | fn is_some(opt: Option) -> bool { 12 | discriminant_value(&opt) != 0 13 | } 14 | 15 | // This doesn't optimize to a bare discriminant read :( 16 | fn my_is_some(opt: Option) -> isize { 17 | match opt { 18 | Some(_) => 1, 19 | None => 0, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-159-heterogeneous-recursive-definitions.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::Ops 4 | trait Ops 5 | { 6 | fn ZERO = test_crate::Ops::ZERO 7 | fn ntt_multiply = test_crate::Ops::ntt_multiply 8 | } 9 | 10 | // Full name: test_crate::Portable 11 | struct Portable {} 12 | 13 | // Full name: test_crate::{impl Ops for Portable}::ZERO 14 | fn {impl Ops for Portable}::ZERO() -> Portable 15 | { 16 | let @0: Portable; // return 17 | 18 | @0 := Portable { } 19 | return 20 | } 21 | 22 | fn test_crate::ntt_multiply() -> Portable 23 | { 24 | let @0: Portable; // return 25 | 26 | @0 := {impl Ops for Portable}::ZERO() 27 | return 28 | } 29 | 30 | // Full name: test_crate::{impl Ops for Portable}::ntt_multiply 31 | fn {impl Ops for Portable}::ntt_multiply() -> Portable 32 | { 33 | let @0: Portable; // return 34 | 35 | @0 := test_crate::ntt_multiply() 36 | return 37 | } 38 | 39 | // Full name: test_crate::{impl Ops for Portable} 40 | impl Ops for Portable { 41 | fn ZERO = {impl Ops for Portable}::ZERO 42 | fn ntt_multiply = {impl Ops for Portable}::ntt_multiply 43 | } 44 | 45 | fn test_crate::Ops::ZERO() -> Self 46 | 47 | fn test_crate::Ops::ntt_multiply() -> Self 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-159-heterogeneous-recursive-definitions.rs: -------------------------------------------------------------------------------- 1 | trait Ops { 2 | fn ZERO() -> Self; 3 | fn ntt_multiply() -> Self; 4 | } 5 | 6 | struct Portable; 7 | 8 | fn ntt_multiply() -> Portable { 9 | Portable::ZERO() 10 | } 11 | 12 | impl Ops for Portable { 13 | fn ZERO() -> Self { 14 | Portable 15 | } 16 | 17 | fn ntt_multiply() -> Self { 18 | ntt_multiply() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-165-vec-macro.rs: -------------------------------------------------------------------------------- 1 | fn foo() { 2 | let _v = vec![1]; 3 | let _v2 = vec![1; 10]; 4 | } 5 | 6 | pub struct Foo; 7 | pub fn bar() { 8 | let _ = vec![Foo]; 9 | } 10 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-166-self-constructors.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::Foo 4 | enum Foo { 5 | A, 6 | B(usize), 7 | } 8 | 9 | // Full name: test_crate::{Foo}::b 10 | pub fn b() -> Foo 11 | { 12 | let @0: Foo; // return 13 | 14 | @0 := Foo::B { 0: const (0 : usize) } 15 | return 16 | } 17 | 18 | // Full name: test_crate::Bar 19 | struct Bar<'a> { 20 | r: &'a (i32), 21 | } 22 | 23 | // Full name: test_crate::{Bar<'a>}#1::new 24 | fn new<'a>(@1: &'a (i32)) -> Bar<'a> 25 | { 26 | let @0: Bar<'_>; // return 27 | let r@1: &'_ (i32); // arg #1 28 | let @2: &'_ (i32); // anonymous local 29 | 30 | storage_live(@2) 31 | @2 := copy (r@1) 32 | @0 := Bar { r: move (@2) } 33 | storage_dead(@2) 34 | return 35 | } 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-166-self-constructors.rs: -------------------------------------------------------------------------------- 1 | enum Foo { 2 | A, 3 | B(usize), 4 | } 5 | 6 | impl Foo { 7 | pub fn b() -> Self { 8 | Self::B(0) 9 | } 10 | } 11 | 12 | struct Bar<'a> { 13 | r: &'a i32, 14 | } 15 | 16 | impl<'a> Bar<'a> { 17 | fn new(r: &'a i32) -> Bar { 18 | Self { r } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-297-cfg.rs: -------------------------------------------------------------------------------- 1 | fn f1(a: &[u8]) -> usize { 2 | let mut sampled = 0; 3 | if a[0] < 42 && a[1] < 16 { 4 | sampled += 100; 5 | } 6 | sampled += 101; 7 | sampled 8 | } 9 | 10 | const FIELD_MODULUS: i16 = 8; 11 | fn f2(a: &[u8], result: &mut [i16]) -> usize { 12 | let mut sampled = 0; 13 | for bytes in a.chunks(3) { 14 | let b1 = bytes[0] as i16; 15 | let b2 = bytes[1] as i16; 16 | let b3 = bytes[2] as i16; 17 | 18 | let d1 = ((b2 & 0xF) << 8) | b1; 19 | let d2 = (b3 << 4) | (b2 >> 4); 20 | 21 | if d1 < FIELD_MODULUS && sampled < 16 { 22 | result[sampled] = d1; 23 | sampled += 1 24 | } 25 | if d2 < FIELD_MODULUS && sampled < 16 { 26 | result[sampled] = d2; 27 | sampled += 1 28 | } 29 | } 30 | sampled 31 | } 32 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-320-slice-pattern.rs: -------------------------------------------------------------------------------- 1 | fn slice_pat1() { 2 | let array: [_; 4] = [0; 4]; 3 | let [_a, _b @ .., _c] = array; 4 | } 5 | 6 | fn slice_pat2() { 7 | let array_ref: &[_; 4] = &[0; 4]; 8 | let [_a, _b @ .., _c] = array_ref; 9 | } 10 | 11 | fn slice_pat3() { 12 | let slice: &[_] = &[0; 4]; 13 | let [_a, _b @ .., _c] = slice else { panic!() }; 14 | } 15 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-322-macro-disambiguator.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | struct test_crate::main::AssertIsAsBytes {} 4 | 5 | struct test_crate::main::AssertIsAsBytes#1 {} 6 | 7 | // Full name: test_crate::main 8 | fn main() 9 | { 10 | let @0: (); // return 11 | let @1: (); // anonymous local 12 | let @2: test_crate::main::AssertIsAsBytes; // anonymous local 13 | let @3: (); // anonymous local 14 | let @4: test_crate::main::AssertIsAsBytes#1; // anonymous local 15 | 16 | storage_live(@1) 17 | storage_live(@2) 18 | @2 := test_crate::main::AssertIsAsBytes { } 19 | storage_dead(@2) 20 | storage_dead(@1) 21 | storage_live(@3) 22 | storage_live(@4) 23 | @4 := test_crate::main::AssertIsAsBytes#1 { } 24 | storage_dead(@4) 25 | storage_dead(@3) 26 | @0 := () 27 | @0 := () 28 | return 29 | } 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-322-macro-disambiguator.rs: -------------------------------------------------------------------------------- 1 | macro_rules! transmute { 2 | () => {{ 3 | struct AssertIsAsBytes; 4 | let _ = AssertIsAsBytes; 5 | }}; 6 | } 7 | 8 | fn main() { 9 | transmute!(); 10 | transmute!(); 11 | } 12 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-323-closure-borrow.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::Rng 4 | struct Rng {} 5 | 6 | // Full name: test_crate::{Rng}::next_u64 7 | fn next_u64<'_0>(@1: &'_0 mut (Rng)) 8 | { 9 | let @0: (); // return 10 | let self@1: &'_ mut (Rng); // arg #1 11 | 12 | @0 := () 13 | @0 := () 14 | return 15 | } 16 | 17 | // Full name: test_crate::new::closure 18 | struct closure<'_0> { 19 | &'_0 mut (Rng), 20 | } 21 | 22 | // Full name: test_crate::new 23 | fn new<'_0>(@1: &'_0 mut (Rng)) 24 | { 25 | let @0: (); // return 26 | let rng@1: &'_ mut (Rng); // arg #1 27 | let @2: closure<'_>; // anonymous local 28 | let @3: &'_ mut (Rng); // anonymous local 29 | 30 | storage_live(@2) 31 | storage_live(@3) 32 | @3 := &uniq *(rng@1) 33 | @2 := closure { 0: move (@3) } 34 | storage_dead(@3) 35 | storage_dead(@2) 36 | @0 := () 37 | @0 := () 38 | return 39 | } 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-323-closure-borrow.rs: -------------------------------------------------------------------------------- 1 | struct Rng; 2 | 3 | impl Rng { 4 | fn next_u64(&mut self) {} 5 | } 6 | 7 | fn new(rng: &mut Rng) { 8 | let _ = || { 9 | rng.next_u64(); 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-369-mismatched-genericparams.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: test_crate::FromResidual 8 | pub trait FromResidual 9 | { 10 | parent_clause0 : [@TraitClause0]: Sized 11 | } 12 | 13 | // Full name: test_crate::Try 14 | pub trait Try 15 | { 16 | parent_clause0 : [@TraitClause0]: FromResidual 17 | parent_clause1 : [@TraitClause1]: Sized 18 | type Residual 19 | } 20 | 21 | // Full name: core::option::Option 22 | #[lang_item("Option")] 23 | pub enum Option 24 | where 25 | [@TraitClause0]: Sized, 26 | { 27 | None, 28 | Some(T), 29 | } 30 | 31 | // Full name: test_crate::{impl FromResidual<()> for Option[@TraitClause0]}#1 32 | impl FromResidual<()> for Option[@TraitClause0] 33 | where 34 | [@TraitClause0]: Sized, 35 | { 36 | parent_clause0 = Sized<()> 37 | } 38 | 39 | // Full name: test_crate::{impl Try for Option[@TraitClause0]} 40 | impl Try for Option[@TraitClause0] 41 | where 42 | [@TraitClause0]: Sized, 43 | { 44 | parent_clause0 = {impl FromResidual<()> for Option[@TraitClause0]}#1[@TraitClause0] 45 | parent_clause1 = Sized<()> 46 | type Residual = () 47 | } 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-369-mismatched-genericparams.rs: -------------------------------------------------------------------------------- 1 | pub trait Try: FromResidual<()> { 2 | type Residual; 3 | } 4 | 5 | pub trait FromResidual {} 6 | 7 | impl Try for Option { 8 | type Residual = (); 9 | } 10 | 11 | impl FromResidual<::Residual> for Option {} 12 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-372-type-param-out-of-range.rs: -------------------------------------------------------------------------------- 1 | pub struct S<'a, K> { 2 | x: &'a K, 3 | } 4 | 5 | impl<'a, K> S<'a, K> { 6 | pub fn f() 7 | where 8 | F: FnMut(&u32), 9 | { 10 | } 11 | 12 | pub fn g() 13 | where 14 | for<'b> F: FnMut(&'b u32), 15 | { 16 | } 17 | } 18 | 19 | pub struct T {} 20 | 21 | impl T { 22 | pub fn f() 23 | where 24 | F: FnMut(&u32), 25 | { 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-378-ctor-as-fn.rs: -------------------------------------------------------------------------------- 1 | static F: fn(u8) -> Option = Some; 2 | 3 | struct Foo(u32, String); 4 | 5 | enum Bar<'a, T> { 6 | Variant(&'a T), 7 | } 8 | 9 | fn main() { 10 | let f = Some; 11 | let _ = f(42); 12 | let f: fn(u8) -> _ = f; 13 | let _ = f(42); 14 | let f = Foo; 15 | let _ = f(42, String::new()); 16 | let f = Bar::Variant; 17 | let _ = f(&42); 18 | } 19 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-393-shallowinitbox.out: -------------------------------------------------------------------------------- 1 | error: Could not reconstruct `Box` initialization; branching during `Box` initialization is not supported. 2 | --> tests/ui/issue-393-shallowinitbox.rs:2:1 3 | | 4 | 2 | / pub fn next(b: bool) -> Option> { 5 | 3 | | let vec = vec![if b { 42 } else { return None }]; 6 | 4 | | Some(vec) 7 | 5 | | } 8 | | |_^ 9 | 10 | ERROR Charon failed to translate this code (1 errors) 11 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-393-shallowinitbox.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | pub fn next(b: bool) -> Option> { 3 | let vec = vec![if b { 42 } else { return None }]; 4 | Some(vec) 5 | } 6 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-394-rpit-with-lifetime.rs: -------------------------------------------------------------------------------- 1 | fn sparse_transitions<'a>() -> impl Iterator + 'a { 2 | core::iter::from_fn(|| None) 3 | } 4 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-395-failed-to-normalize.rs: -------------------------------------------------------------------------------- 1 | pub trait Trait { 2 | type AssocType; 3 | } 4 | pub type Alias = Option<::AssocType>; 5 | 6 | pub trait C {} 7 | 8 | pub struct S(I, F) 9 | where 10 | I: Iterator, 11 | F: C; 12 | 13 | pub type S2 = S; 14 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-4-slice-try-into-array.rs: -------------------------------------------------------------------------------- 1 | pub fn trait_error(s: &[u8]) { 2 | let _array: [u8; 4] = s.try_into().unwrap(); 3 | } 4 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-4-traits.rs: -------------------------------------------------------------------------------- 1 | use std::convert::TryInto; 2 | fn trait_error(s: &[u8]) { 3 | let _array: [u8; 4] = s.try_into().unwrap(); 4 | } 5 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-45-misc.rs: -------------------------------------------------------------------------------- 1 | pub fn map(x: [i32; 256]) -> [i32; 256] { 2 | x.map(|v| v) 3 | } 4 | 5 | pub fn array() -> [u8; LEN] { 6 | [0u8; LEN] 7 | } 8 | 9 | fn cbd(mut prf_input: [u8; 33]) { 10 | for i in 0..3 { 11 | prf_input[0] = i; 12 | } 13 | } 14 | 15 | pub(crate) fn select(lhs: &[u8], rhs: &[u8]) { 16 | debug_assert_eq!(lhs.len(), rhs.len()); 17 | } 18 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-507-cfg.rs: -------------------------------------------------------------------------------- 1 | const CONST: u8 = 0; 2 | 3 | fn f0() { 4 | if 0 < 1 { 5 | if 0 < 1 {} 6 | let x = CONST; 7 | } 8 | } 9 | 10 | fn f1( serialized: &[u8; 1]) { 11 | let previous_true_hints_seen = 0usize; 12 | 13 | let mut i = 0; 14 | 15 | while i < 1 { 16 | if (0 < 1) || (1 > 1) {} 17 | 18 | let mut j = 0; 19 | while j < 1 { 20 | let x = CONST; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-70-override-provided-method.2.rs: -------------------------------------------------------------------------------- 1 | trait Trait { 2 | fn required(&self); 3 | fn provided1(&self) { 4 | self.required(); 5 | self.provided2(); 6 | } 7 | fn provided2(&self) { 8 | self.required(); 9 | self.provided1(); 10 | } 11 | } 12 | 13 | struct Foo; 14 | impl Trait for Foo { 15 | fn required(&self) { 16 | self.provided1(); 17 | } 18 | } 19 | 20 | struct Bar; 21 | impl Trait for Bar { 22 | fn required(&self) { 23 | self.provided2(); 24 | } 25 | fn provided1(&self) { 26 | self.provided2(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-70-override-provided-method.3.rs: -------------------------------------------------------------------------------- 1 | //! Ensure we pass generics correctly when dealing with default methods. 2 | //! We implement the trait twice, one with override and the other without. If we did things right, 3 | //! the two cases should end up identical. 4 | 5 | trait GenericTrait { 6 | fn other_method(); 7 | fn provided>(x: T, y: U) { 8 | if y == x { 9 | Self::other_method() 10 | } 11 | } 12 | } 13 | 14 | struct Override(T); 15 | impl GenericTrait> for Override { 16 | fn other_method() {} 17 | fn provided>>(x: Option, y: U) { 18 | if y == x { 19 | Self::other_method() 20 | } 21 | } 22 | } 23 | 24 | struct NoOverride(T); 25 | impl GenericTrait> for NoOverride { 26 | fn other_method() {} 27 | } 28 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-70-override-provided-method.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let _ = Some(1) == Some(1); 3 | } 4 | 5 | #[derive(PartialEq, PartialOrd)] 6 | struct Foo(u32); 7 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-72-hash-missing-impl.rs: -------------------------------------------------------------------------------- 1 | pub trait Hasher {} 2 | 3 | pub struct DefaultHasher; 4 | impl Hasher for DefaultHasher {} 5 | 6 | pub trait Hash { 7 | fn hash(&self, state: &mut H); 8 | } 9 | 10 | impl Hash for u32 { 11 | fn hash(&self, _state: &mut H) {} 12 | } 13 | 14 | fn main() { 15 | let mut hasher = DefaultHasher; 16 | 0u32.hash(&mut hasher); 17 | } 18 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-73-extern.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::foo 4 | unsafe fn foo(@1: i32) 5 | 6 | fn test_crate::CONST() -> u8 7 | 8 | static test_crate::CONST: u8 = test_crate::CONST() 9 | 10 | // Full name: test_crate::Type 11 | opaque type Type 12 | 13 | // Full name: test_crate::use_type 14 | fn use_type<'_0>(@1: &'_0 (Type)) 15 | { 16 | let @0: (); // return 17 | let _x@1: &'_ (Type); // arg #1 18 | 19 | @0 := () 20 | @0 := () 21 | return 22 | } 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-73-extern.rs: -------------------------------------------------------------------------------- 1 | #![feature(extern_types)] 2 | extern "C" { 3 | fn foo(x: i32); 4 | static CONST: u8; 5 | type Type; 6 | } 7 | 8 | fn use_type(_x: &Type) {} 9 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-91-enum-to-discriminant-cast.rs: -------------------------------------------------------------------------------- 1 | #[derive(Copy, Clone)] 2 | enum Foo { 3 | A, 4 | B, 5 | } 6 | 7 | enum Ordering { 8 | Less = -1, 9 | Equal = 0, 10 | Greater = 1, 11 | } 12 | 13 | fn main() { 14 | let x = Foo::A; 15 | let _ = x as isize; 16 | let _ = x as u8; 17 | 18 | let x = Ordering::Greater; 19 | let _ = x as isize; 20 | } 21 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-92-nonpositive-variant-indices.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::Ordering 4 | enum Ordering { 5 | Less, 6 | Equal, 7 | Greater, 8 | } 9 | 10 | // Full name: test_crate::main 11 | fn main() 12 | { 13 | let @0: (); // return 14 | let @1: Ordering; // anonymous local 15 | 16 | storage_live(@1) 17 | @1 := Ordering::Less { } 18 | match @1 { 19 | Ordering::Less => { 20 | @0 := () 21 | }, 22 | Ordering::Equal => { 23 | @0 := () 24 | }, 25 | Ordering::Greater => { 26 | @0 := () 27 | }, 28 | } 29 | storage_dead(@1) 30 | @0 := () 31 | return 32 | } 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-92-nonpositive-variant-indices.rs: -------------------------------------------------------------------------------- 1 | enum Ordering { 2 | Less = -1, 3 | Equal = 0, 4 | Greater = 1, 5 | } 6 | 7 | fn main() { 8 | match Ordering::Less { 9 | Ordering::Less => {} 10 | Ordering::Equal => {} 11 | Ordering::Greater => {} 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-93-recursive-traits-with-assoc-types.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: test_crate::Trait1 8 | pub trait Trait1 9 | { 10 | parent_clause0 : [@TraitClause0]: Sized 11 | parent_clause1 : [@TraitClause1]: Trait2 12 | type T 13 | } 14 | 15 | // Full name: test_crate::Trait2 16 | pub trait Trait2 17 | { 18 | parent_clause0 : [@TraitClause0]: Trait1 19 | parent_clause1 : [@TraitClause1]: Sized 20 | type U 21 | } 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-93-recursive-traits-with-assoc-types.rs: -------------------------------------------------------------------------------- 1 | pub trait Trait1 { 2 | type T: Trait2; 3 | } 4 | 5 | pub trait Trait2: Trait1 { 6 | type U; 7 | } 8 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-94-recursive-trait-defns.rs: -------------------------------------------------------------------------------- 1 | pub trait Trait1: Sized { 2 | type T: Trait2; 3 | } 4 | 5 | pub trait Trait2: Trait1 {} 6 | 7 | pub trait T1>: Sized {} 8 | pub trait T2>: Sized {} 9 | 10 | pub trait T3 { 11 | type T: T5; 12 | } 13 | 14 | pub trait T4: T3 {} 15 | 16 | pub trait T5 { 17 | type T: T4; 18 | } 19 | 20 | pub trait T6: Sized { 21 | fn f(x: u64) -> () { 22 | T::g(x) 23 | } 24 | } 25 | 26 | pub trait T7: T6 { 27 | fn g(_x: u64) -> (); 28 | } 29 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-97-missing-parent-item-clause.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::Ord 4 | pub trait Ord 5 | 6 | // Full name: core::marker::Sized 7 | #[lang_item("sized")] 8 | pub trait Sized 9 | 10 | // Full name: test_crate::AVLTree 11 | pub struct AVLTree 12 | where 13 | [@TraitClause0]: Sized, 14 | { 15 | x: T, 16 | } 17 | 18 | // Full name: test_crate::{AVLTree[@TraitClause0]}::insert 19 | pub fn insert<'_0, T>(@1: &'_0 mut (AVLTree[@TraitClause0])) 20 | where 21 | [@TraitClause0]: Sized, 22 | [@TraitClause1]: Ord, 23 | { 24 | let @0: (); // return 25 | let self@1: &'_ mut (AVLTree[@TraitClause0]); // arg #1 26 | 27 | panic(core::panicking::panic) 28 | } 29 | 30 | // Full name: test_crate::{impl Ord for u32}#1 31 | impl Ord for u32 {} 32 | 33 | // Full name: test_crate::test 34 | pub fn test(@1: AVLTree[Sized]) 35 | { 36 | let @0: (); // return 37 | let tree@1: AVLTree[Sized]; // arg #1 38 | let @2: (); // anonymous local 39 | let @3: &'_ mut (AVLTree[Sized]); // anonymous local 40 | 41 | storage_live(@2) 42 | storage_live(@3) 43 | @3 := &two-phase-mut tree@1 44 | @2 := insert<'_, u32>[Sized, {impl Ord for u32}#1](move (@3)) 45 | storage_dead(@3) 46 | storage_dead(@2) 47 | @0 := () 48 | @0 := () 49 | return 50 | } 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /charon/tests/ui/issue-97-missing-parent-item-clause.rs: -------------------------------------------------------------------------------- 1 | pub trait Ord {} 2 | 3 | pub struct AVLTree { 4 | pub x: T, 5 | } 6 | 7 | impl AVLTree { 8 | pub fn insert(&mut self) { 9 | unimplemented!(); 10 | } 11 | } 12 | 13 | impl Ord for u32 {} 14 | 15 | pub fn test(mut tree: AVLTree) { 16 | tree.insert(); 17 | } 18 | -------------------------------------------------------------------------------- /charon/tests/ui/iterator.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--translate-all-methods 2 | //! Translate the full iterator trait and a few of standard impls. This is a great testing ground 3 | //! for type-system features. 4 | fn main() { 5 | let a = [0, 1, 2, 3, 4, 5, 6]; 6 | let mut i = 0; 7 | for v in a.into_iter() { 8 | i += v; 9 | } 10 | for v in a.iter() { 11 | i += v; 12 | } 13 | for _ in a.chunks(2) { 14 | i += 1; 15 | } 16 | for _ in a.chunks_exact(2) { 17 | i += 1; 18 | } 19 | let expected = 28; 20 | assert_eq!(i, expected); 21 | } 22 | -------------------------------------------------------------------------------- /charon/tests/ui/match_on_opaque_enum.out: -------------------------------------------------------------------------------- 1 | error: reading the discriminant of an opaque enum. Add `--include test_crate::Enum` to the `charon` arguments to translate this enum. 2 | --> tests/ui/match_on_opaque_enum.rs:9:5 3 | | 4 | 9 | / match x { 5 | 10 | | Enum::A => true, 6 | 11 | | Enum::B => false, 7 | 12 | | } 8 | 13 | | } 9 | | |_^ 10 | 11 | ERROR Charon failed to translate this code (1 errors) 12 | -------------------------------------------------------------------------------- /charon/tests/ui/match_on_opaque_enum.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | //@ charon-args=--opaque crate::Enum 3 | pub enum Enum { 4 | A, 5 | B, 6 | } 7 | 8 | pub fn is_a(x: &Enum) -> bool { 9 | match x { 10 | Enum::A => true, 11 | Enum::B => false, 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /charon/tests/ui/max_char.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | pub fn core::char::methods::{char}::MAX() -> char 4 | { 5 | let @0: char; // return 6 | 7 | @0 := const (􏿿) 8 | return 9 | } 10 | 11 | pub const core::char::methods::{char}::MAX: char = core::char::methods::{char}::MAX() 12 | 13 | pub fn core::char::MAX() -> char 14 | { 15 | let @0: char; // return 16 | let @1: char; // anonymous local 17 | 18 | storage_live(@1) 19 | @1 := core::char::methods::{char}::MAX 20 | @0 := move (@1) 21 | return 22 | } 23 | 24 | pub const core::char::MAX: char = core::char::MAX() 25 | 26 | // Full name: test_crate::main 27 | fn main() 28 | { 29 | let @0: (); // return 30 | let _max_char@1: char; // local 31 | let @2: char; // anonymous local 32 | 33 | storage_live(@2) 34 | storage_live(_max_char@1) 35 | @2 := core::char::MAX 36 | _max_char@1 := move (@2) 37 | @0 := () 38 | storage_dead(_max_char@1) 39 | @0 := () 40 | return 41 | } 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /charon/tests/ui/max_char.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--include std::char::MAX 2 | //@ charon-args=--include core::char::MAX 3 | //@ charon-args=--include core::char::methods::_::MAX 4 | 5 | fn main() { 6 | let _max_char = std::char::MAX; 7 | } 8 | -------------------------------------------------------------------------------- /charon/tests/ui/monomorphization/adt_proj.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | #[lang_item("Result")] 4 | pub enum core::result::Result:: { 5 | Ok(u32), 6 | Err(u32), 7 | } 8 | 9 | // Full name: test_crate::main 10 | fn main() 11 | { 12 | let @0: (); // return 13 | let res@1: core::result::Result::; // local 14 | let n@2: u32; // local 15 | 16 | storage_live(res@1) 17 | res@1 := core::result::Result::::Ok { 0: const (0 : u32) } 18 | storage_live(n@2) 19 | match res@1 { 20 | core::result::Result::::Ok => { 21 | }, 22 | _ => { 23 | storage_dead(n@2) 24 | panic(core::panicking::panic_explicit) 25 | }, 26 | } 27 | n@2 := copy ((res@1 as variant @0).0) 28 | @0 := () 29 | storage_dead(n@2) 30 | storage_dead(res@1) 31 | @0 := () 32 | return 33 | } 34 | 35 | // Full name: core::marker::Sized 36 | #[lang_item("sized")] 37 | pub trait Sized 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /charon/tests/ui/monomorphization/adt_proj.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--monomorphize 2 | // Ensures monomorphization happens when projections on discriminants of generic enums are 3 | // involved -- in this case the discriminant of Result 4 | 5 | fn main() { 6 | let res: Result = Ok(0); 7 | let Ok(n) = res else { panic!() }; 8 | } 9 | -------------------------------------------------------------------------------- /charon/tests/ui/monomorphization/closure-fn.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--monomorphize 2 | fn apply_to(f: &impl Fn(u8, u8) -> u8) -> u8 { 3 | f(10, 20) 4 | } 5 | 6 | fn apply_to_mut(f: &mut impl FnMut(u8, u8) -> u8) -> u8 { 7 | f(10, 20) 8 | } 9 | 10 | fn apply_to_once(f: impl FnOnce(u8, u8) -> u8) -> u8 { 11 | f(10, 20) 12 | } 13 | 14 | fn main() { 15 | let v = 5; 16 | let z = 1; 17 | let mut f = |x, y| v + x + y + z; 18 | f(10, 20); 19 | apply_to(&f); 20 | apply_to_mut(&mut f); 21 | apply_to_once(f); 22 | } 23 | -------------------------------------------------------------------------------- /charon/tests/ui/monomorphization/closure-fnonce.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--monomorphize 2 | 3 | fn apply_to_zero_once(f: impl FnOnce(u8) -> u8) -> u8 { 4 | f(0) 5 | } 6 | 7 | struct NotCopy; 8 | 9 | fn main() { 10 | let z = NotCopy {}; 11 | apply_to_zero_once(|x| { 12 | drop(z); 13 | x + 1 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /charon/tests/ui/monomorphization/closures.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--monomorphize 2 | // Ensures closures are monomorphized and replaced with static function calls 3 | 4 | struct Thing; 5 | 6 | fn apply_to_zero(f: impl Fn(u8) -> u8) -> u8 { 7 | f(0) 8 | } 9 | 10 | fn apply_to_zero_mut(mut f: impl FnMut(u8) -> u8) -> u8 { 11 | f(0) 12 | } 13 | 14 | fn apply_to_zero_once(f: impl FnOnce(u8) -> u8) -> u8 { 15 | f(0) 16 | } 17 | 18 | fn main() { 19 | let z = 1; 20 | apply_to_zero(|x| x + z); 21 | 22 | let mut z = 3; 23 | apply_to_zero_mut(|x| { 24 | z += 1; 25 | x + z 26 | }); 27 | 28 | let z = Thing {}; 29 | apply_to_zero_once(|x| { 30 | drop(z); 31 | x + 1 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /charon/tests/ui/monomorphization/const_generics.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | struct test_crate::Foo:: { 4 | value: bool, 5 | } 6 | 7 | fn test_crate::FooBool() -> test_crate::Foo:: 8 | { 9 | let @0: test_crate::Foo::; // return 10 | 11 | @0 := test_crate::Foo:: { value: const (false) } 12 | return 13 | } 14 | 15 | static test_crate::FooBool: test_crate::Foo:: = test_crate::FooBool() 16 | 17 | // Full name: test_crate::main 18 | fn main() 19 | { 20 | let @0: (); // return 21 | let _b@1: bool; // local 22 | let @2: &'_ (test_crate::Foo::); // anonymous local 23 | let @3: &'_ (test_crate::Foo::); // anonymous local 24 | 25 | storage_live(@3) 26 | storage_live(_b@1) 27 | storage_live(@2) 28 | @3 := &test_crate::FooBool 29 | @2 := move (@3) 30 | _b@1 := copy ((*(@2)).value) 31 | storage_dead(@2) 32 | @0 := () 33 | storage_dead(_b@1) 34 | @0 := () 35 | return 36 | } 37 | 38 | // Full name: core::marker::Sized 39 | #[lang_item("sized")] 40 | pub trait Sized 41 | 42 | struct test_crate::Foo:: { 43 | value: i32, 44 | } 45 | 46 | fn test_crate::FooInt() -> test_crate::Foo:: 47 | { 48 | let @0: test_crate::Foo::; // return 49 | 50 | @0 := test_crate::Foo:: { value: const (0 : i32) } 51 | return 52 | } 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /charon/tests/ui/monomorphization/const_generics.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--monomorphize 2 | // Ensures monomorphization handles globals with generics 3 | 4 | struct Foo { 5 | value: T, 6 | } 7 | 8 | static FooInt: Foo = Foo { value: 0i32 }; 9 | static FooBool: Foo = Foo { value: false }; 10 | 11 | fn main() { 12 | let _b = FooBool.value; 13 | } 14 | -------------------------------------------------------------------------------- /charon/tests/ui/monomorphization/fn_ptr_generics.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | #[lang_item("Option")] 4 | pub enum core::option::Option:: { 5 | None, 6 | Some(u8), 7 | } 8 | 9 | // Full name: test_crate::init_option 10 | fn init_option() 11 | { 12 | let @0: (); // return 13 | let a@1: Array, 6 : usize>; // local 14 | let @2: core::option::Option::; // anonymous local 15 | let b@3: core::option::Option::; // local 16 | let @4: usize; // anonymous local 17 | let @5: &'_ (Array, 6 : usize>); // anonymous local 18 | let @6: &'_ (core::option::Option::); // anonymous local 19 | 20 | storage_live(a@1) 21 | storage_live(@2) 22 | @2 := core::option::Option::::Some { 0: const (4 : u8) } 23 | a@1 := @ArrayRepeat<'_, core::option::Option::, 6 : usize>(move (@2)) 24 | storage_dead(@2) 25 | storage_live(b@3) 26 | storage_live(@4) 27 | @4 := const (0 : usize) 28 | storage_live(@5) 29 | @5 := &a@1 30 | storage_live(@6) 31 | @6 := @ArrayIndexShared<'_, core::option::Option::, 6 : usize>(move (@5), copy (@4)) 32 | b@3 := copy (*(@6)) 33 | storage_dead(@4) 34 | @0 := () 35 | storage_dead(b@3) 36 | storage_dead(a@1) 37 | @0 := () 38 | return 39 | } 40 | 41 | // Full name: core::marker::Sized 42 | #[lang_item("sized")] 43 | pub trait Sized 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /charon/tests/ui/monomorphization/fn_ptr_generics.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--monomorphize 2 | // Ensures monomorphization happens for the generic arguments of function pointers -- in this 3 | // case, the generic args are in the index function, with Option 4 | 5 | fn init_option() { 6 | let a = [Some(4u8); 6]; 7 | let b = a[0]; 8 | } 9 | -------------------------------------------------------------------------------- /charon/tests/ui/monomorphization/trait_impls.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--monomorphize 2 | // Ensures monomorphization happens when trait implementations are involved. 3 | 4 | use std::mem; 5 | 6 | fn do_test(init: T, expected: T) { 7 | assert!(expected == init); 8 | } 9 | 10 | fn main() { 11 | do_test::(true, true); 12 | } 13 | -------------------------------------------------------------------------------- /charon/tests/ui/monomorphization/trait_impls_ullbc.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--monomorphize --ullbc --print-ullbc --no-serialize 2 | // Ensures monomorphization happens when trait implementations are involved. 3 | 4 | use std::mem; 5 | 6 | fn do_test(init: T, expected: T) { 7 | assert!(expected == init); 8 | } 9 | 10 | fn main() { 11 | do_test::(true, true); 12 | } 13 | -------------------------------------------------------------------------------- /charon/tests/ui/non-lifetime-gats.out: -------------------------------------------------------------------------------- 1 | error: Generic associated types are not supported 2 | --> tests/ui/non-lifetime-gats.rs:5:5 3 | | 4 | 5 | type Pointer: Deref; 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | error: Item `test_crate::PointerFamily` caused errors; ignoring. 8 | --> tests/ui/non-lifetime-gats.rs:4:1 9 | | 10 | 4 | pub trait PointerFamily { 11 | | ^^^^^^^^^^^^^^^^^^^^^^^ 12 | 13 | error: Generic associated types are not supported 14 | --> tests/ui/non-lifetime-gats.rs:34:9 15 | | 16 | 34 | type Type: Link; 17 | | ^^^^^^^^^^^^^^^^^^^^^ 18 | 19 | error: Item `test_crate::moar_variables::Trait` caused errors; ignoring. 20 | --> tests/ui/non-lifetime-gats.rs:33:5 21 | | 22 | 33 | pub trait Trait { 23 | | ^^^^^^^^^^^^^^^^^^ 24 | 25 | ERROR Charon failed to translate this code (4 errors) 26 | -------------------------------------------------------------------------------- /charon/tests/ui/non-lifetime-gats.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | use std::ops::Deref; 3 | 4 | pub trait PointerFamily { 5 | type Pointer: Deref; 6 | 7 | fn new(value: T) -> Self::Pointer; 8 | } 9 | 10 | pub struct BoxFamily; 11 | 12 | impl PointerFamily for BoxFamily { 13 | type Pointer = Box; 14 | 15 | fn new(value: T) -> Self::Pointer { 16 | Box::new(value) 17 | } 18 | } 19 | 20 | pub fn make_pointer(x: T) -> F::Pointer { 21 | F::new(x) 22 | } 23 | 24 | pub fn main() { 25 | let _: Box<_> = make_pointer::(42); 26 | } 27 | 28 | pub mod moar_variables { 29 | // Dummy trait to check we handle variables in clauses correctly. 30 | pub trait Link {} 31 | impl Link for U {} 32 | 33 | pub trait Trait { 34 | type Type: Link; 35 | } 36 | 37 | pub struct Foo; 38 | impl Trait> for Foo { 39 | type Type = (T, U); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /charon/tests/ui/opaque-trait.rs: -------------------------------------------------------------------------------- 1 | //! Tests that we correctly translate opaque traits. 2 | //! 3 | //! Constraints: 4 | //! - an impl must have the same set of methods as the trait it implements; 5 | //! - trait methods that are never used are considered not to exist. 6 | //! 7 | //! A method use is: 8 | //! - A call to the trait method via a `TraitMethod` kind of call; 9 | //! - The implementation of a trait method in an impl block. 10 | //! 11 | //! We keep all const and const initializers for now. 12 | #![feature(register_tool)] 13 | #![register_tool(charon)] 14 | 15 | #[charon::opaque] 16 | trait Trait { 17 | // Used in a function body. 18 | const CONST1: usize = 0; 19 | // Used in an implementation. 20 | const CONST2: usize = 0; 21 | const CONST3: usize = 0; 22 | // Used in a function body. 23 | fn method1() {} 24 | // Used in an implementation. 25 | fn method2() {} 26 | fn method3() {} 27 | } 28 | 29 | #[charon::opaque] 30 | impl Trait for () { 31 | const CONST1: usize = 1; 32 | const CONST2: usize = 1; 33 | const CONST3: usize = 1; 34 | fn method1() {} 35 | fn method2() {} 36 | fn method3() {} 37 | } 38 | 39 | impl Trait for u8 { 40 | const CONST2: usize = 2; 41 | // TODO: don't trigger translation of defaulted methods. 42 | fn method2() {} 43 | } 44 | 45 | fn use_method() { 46 | T::method1(); 47 | T::CONST1; 48 | } 49 | -------------------------------------------------------------------------------- /charon/tests/ui/panics.rs: -------------------------------------------------------------------------------- 1 | #![feature(libstd_sys_internals)] 2 | #![feature(rt)] 3 | #![allow(internal_features)] 4 | #![allow(unreachable_code)] 5 | fn panic1() { 6 | panic!(); 7 | } 8 | fn panic2() { 9 | panic!("O no!"); 10 | } 11 | fn panic3() { 12 | panic!("O {}!", "no"); 13 | } 14 | fn panic4() { 15 | assert!(false); 16 | } 17 | fn panic5() { 18 | assert!(false, "assert failed"); 19 | } 20 | fn panic6() { 21 | unreachable!(); 22 | } 23 | fn panic7() { 24 | unreachable!("can't reach {}", "this"); 25 | } 26 | fn panic8() { 27 | todo!(); 28 | } 29 | fn panic9() { 30 | ::std::rt::begin_panic("explicit panic"); 31 | } 32 | -------------------------------------------------------------------------------- /charon/tests/ui/plain-panic-str.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::fmt::Arguments 4 | #[lang_item("format_arguments")] 5 | pub opaque type Arguments<'a> 6 | where 7 | 'a : 'a, 8 | 9 | // Full name: core::fmt::{Arguments<'a>}#4::new_const 10 | pub fn new_const<'a, const N : usize>(@1: &'a (Array<&'static (Str), const N : usize>)) -> Arguments<'a> 11 | 12 | // Full name: test_crate::main 13 | fn main() 14 | { 15 | let @0: (); // return 16 | let @1: Arguments<'_>; // anonymous local 17 | let @2: &'_ (Array<&'_ (Str), 1 : usize>); // anonymous local 18 | let @3: &'_ (Array<&'_ (Str), 1 : usize>); // anonymous local 19 | let @4: Array<&'_ (Str), 1 : usize>; // anonymous local 20 | 21 | storage_live(@1) 22 | storage_live(@2) 23 | storage_live(@3) 24 | storage_live(@4) 25 | @4 := [const ("O no")] 26 | @3 := &@4 27 | @2 := &*(@3) 28 | @1 := new_const<'_, 1 : usize>(move (@2)) 29 | storage_dead(@2) 30 | panic(core::panicking::panic_fmt) 31 | } 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /charon/tests/ui/plain-panic-str.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | panic!("O no"); 3 | } 4 | -------------------------------------------------------------------------------- /charon/tests/ui/pointers-in-consts-no-warns.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | fn test_crate::DISGUISED_INT() -> *const () 4 | { 5 | let @0: *const (); // return 6 | let @1: *const (); // anonymous local 7 | 8 | storage_live(@1) 9 | @1 := cast(const (42 : i32)) 10 | @0 := copy (@1) 11 | storage_dead(@1) 12 | return 13 | } 14 | 15 | const test_crate::DISGUISED_INT: *const () = test_crate::DISGUISED_INT() 16 | 17 | // Full name: test_crate::bar 18 | pub fn bar() 19 | { 20 | let @0: (); // return 21 | let @1: *const (); // anonymous local 22 | let @2: bool; // anonymous local 23 | 24 | storage_live(@2) 25 | storage_live(@1) 26 | @1 := cast(const (43 : usize)) 27 | @2 := const (Opaque(`ConstantExprKind::Cast {{..}}`)) == copy (@1) 28 | if move (@2) { 29 | @0 := () 30 | } 31 | else { 32 | @0 := () 33 | } 34 | storage_dead(@1) 35 | @0 := () 36 | return 37 | } 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /charon/tests/ui/pointers-in-consts-no-warns.rs: -------------------------------------------------------------------------------- 1 | //@ ignore-warnings 2 | const DISGUISED_INT: *const () = 42 as _; 3 | 4 | pub fn bar() { 5 | match 43 as *const () { 6 | DISGUISED_INT => {} 7 | _ => {} 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /charon/tests/ui/pointers-in-consts.out: -------------------------------------------------------------------------------- 1 | error: Unsupported constant: `ConstantExprKind::Cast {..}` 2 | --> tests/ui/pointers-in-consts.rs:6:9 3 | | 4 | 6 | DISGUISED_INT => {} 5 | | ^^^^^^^^^^^^^ 6 | 7 | ERROR Charon failed to translate this code (1 errors) 8 | -------------------------------------------------------------------------------- /charon/tests/ui/pointers-in-consts.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | const DISGUISED_INT: *const () = 42 as _; 3 | 4 | pub fn bar() { 5 | match 43 as *const () { 6 | DISGUISED_INT => {} 7 | _ => {} 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /charon/tests/ui/polonius_map.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--polonius 2 | #![allow(dead_code)] 3 | use std::collections::HashMap; 4 | 5 | /// The example the Rust team uses to illustrate why we need Polonius. 6 | pub fn get_or_insert(map: &mut HashMap) -> &u32 { 7 | match map.get(&22) { 8 | Some(v) => v, 9 | None => { 10 | map.insert(22, 33); 11 | &map[&22] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /charon/tests/ui/predicates-on-late-bound-vars.rs: -------------------------------------------------------------------------------- 1 | // This tests that we correctly support type signatures with predicates involving late bound 2 | // regions. Here, `Option` requires `T: Sized` which is the predicate in question. 3 | 4 | fn wrap<'a>(x: &'a u32) -> Option<&'a u32> { 5 | Some(x) 6 | } 7 | 8 | // The `Clone` bound makes `'a` early-bound. 9 | fn wrap2<'a>(x: &'a u32) -> Option<&'a u32> 10 | where 11 | &'a (): Clone, 12 | { 13 | Some(x) 14 | } 15 | 16 | // Test with a signature from a foreign crate. 17 | fn foo() { 18 | use std::cell::RefCell; 19 | let ref_b = RefCell::new(false); 20 | // `try_borrow` has a type that includes predicates on late bound regions. 21 | let _ = ref_b.try_borrow(); 22 | } 23 | 24 | trait Foo { 25 | type S; 26 | } 27 | // Test normalization order just in case. 28 | fn f, U: Foo>() -> Option { 29 | todo!() 30 | } 31 | -------------------------------------------------------------------------------- /charon/tests/ui/projection-index-from-end.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::slice_pattern_end 4 | fn slice_pattern_end<'_0>(@1: &'_0 (Slice<()>)) 5 | { 6 | let @0: (); // return 7 | let x@1: &'_ (Slice<()>); // arg #1 8 | let @2: usize; // anonymous local 9 | let @3: usize; // anonymous local 10 | let @4: bool; // anonymous local 11 | let _named@5: &'_ (()); // local 12 | let @6: &'_ (Slice<()>); // anonymous local 13 | let @7: usize; // anonymous local 14 | let @8: usize; // anonymous local 15 | let @9: &'_ (()); // anonymous local 16 | 17 | storage_live(@2) 18 | storage_live(@3) 19 | storage_live(@4) 20 | @2 := len(*(x@1)) 21 | @3 := const (1 : usize) 22 | @4 := move (@2) >= move (@3) 23 | if move (@4) { 24 | } 25 | else { 26 | @0 := () 27 | @0 := () 28 | return 29 | } 30 | storage_live(_named@5) 31 | storage_live(@6) 32 | @6 := &*(x@1) 33 | storage_live(@7) 34 | @7 := len(*(x@1)) 35 | storage_live(@8) 36 | @8 := copy (@7) - const (1 : usize) 37 | storage_dead(@7) 38 | storage_live(@9) 39 | @9 := @SliceIndexShared<'_, ()>(move (@6), copy (@8)) 40 | _named@5 := &*(@9) 41 | @0 := () 42 | storage_dead(_named@5) 43 | @0 := () 44 | return 45 | } 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /charon/tests/ui/projection-index-from-end.rs: -------------------------------------------------------------------------------- 1 | fn slice_pattern_end(x: &[()]) { 2 | match x { 3 | [.., _named] => (), 4 | _ => (), 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /charon/tests/ui/ptr-offset.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--include core::ptr::const_ptr::_::offset 2 | 3 | fn main() { 4 | let s = [11, 42]; 5 | let ptr = s.as_ptr(); 6 | unsafe { 7 | assert!(*ptr.offset(1) == 42); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /charon/tests/ui/quantified-clause.rs: -------------------------------------------------------------------------------- 1 | fn foo(_f: F) 2 | where 3 | F: for<'a> FnMut(&'a ()), 4 | { 5 | } 6 | 7 | fn bar<'b, T>() 8 | where 9 | T: 'b, 10 | for<'a> &'b T: 'a, 11 | { 12 | } 13 | 14 | // https://github.com/AeneasVerif/charon/issues/377 15 | pub fn f<'a>(_: &'a ()) -> Option<(&'a u8,)> { 16 | None 17 | } 18 | 19 | pub trait Trait {} 20 | 21 | // https://github.com/hacspec/hax/issues/747 22 | impl Trait for Result 23 | where 24 | for<'a> &'a Result: IntoIterator, 25 | for<'a> <&'a Result as IntoIterator>::Item: Copy, 26 | { 27 | } 28 | -------------------------------------------------------------------------------- /charon/tests/ui/reconstruct_early_return.rs: -------------------------------------------------------------------------------- 1 | fn f() -> usize 2 | { 3 | let mut i = 0; 4 | let mut j = 0; 5 | while i < 32 6 | { 7 | j += 1; 8 | if j > 16 9 | { 10 | j /= 2; 11 | } 12 | else if j > 32 13 | { 14 | return 1; 15 | } 16 | i += 1; 17 | } 18 | 19 | 0 20 | } 21 | -------------------------------------------------------------------------------- /charon/tests/ui/region-inference-vars.rs: -------------------------------------------------------------------------------- 1 | //! Regression test for an old behavior of region variables. 2 | 3 | pub trait MyTryFrom { 4 | type Error; 5 | fn from(v: T) -> Result 6 | where 7 | Self: Sized; 8 | } 9 | 10 | impl MyTryFrom<&bool> for bool { 11 | type Error = (); 12 | fn from(v: &bool) -> Result { 13 | Ok(*v) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /charon/tests/ui/regressions/closure-inside-impl-with-bound-with-assoc-ty.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: test_crate::PrimeField 8 | pub trait PrimeField 9 | { 10 | parent_clause0 : [@TraitClause0]: Sized 11 | } 12 | 13 | // Full name: test_crate::SqrtTables 14 | pub struct SqrtTables 15 | where 16 | [@TraitClause0]: Sized, 17 | { 18 | F, 19 | } 20 | 21 | // Full name: test_crate::{SqrtTables[@TraitClause0]}::sqrt_common::closure 22 | struct closure 23 | where 24 | [@TraitClause0]: Sized, 25 | [@TraitClause1]: PrimeField, 26 | {} 27 | 28 | // Full name: test_crate::{SqrtTables[@TraitClause0]}::sqrt_common 29 | pub fn sqrt_common() 30 | where 31 | [@TraitClause0]: Sized, 32 | [@TraitClause1]: PrimeField, 33 | { 34 | let @0: (); // return 35 | let _closure@1: closure[@TraitClause0, @TraitClause1]; // local 36 | 37 | storage_live(_closure@1) 38 | _closure@1 := closure { } 39 | @0 := () 40 | storage_dead(_closure@1) 41 | @0 := () 42 | return 43 | } 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /charon/tests/ui/regressions/closure-inside-impl-with-bound-with-assoc-ty.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | //! Regression test for issue https://github.com/AeneasVerif/charon/issues/627 3 | pub trait PrimeField { 4 | type Repr; 5 | } 6 | 7 | pub struct SqrtTables(F); 8 | 9 | impl SqrtTables { 10 | pub fn sqrt_common() 11 | where 12 | F: PrimeField, 13 | { 14 | let _closure = |_x: ()| (); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /charon/tests/ui/rename_attribute.rs: -------------------------------------------------------------------------------- 1 | #![feature(register_tool)] 2 | #![register_tool(charon)] 3 | #![register_tool(aeneas)] 4 | 5 | #[charon::rename("BoolTest")] 6 | pub trait BoolTrait { 7 | // Required method 8 | #[charon::rename("getTest")] 9 | fn get_bool(&self) -> bool; 10 | 11 | // Provided method 12 | #[charon::rename("retTest")] 13 | fn ret_true(&self) -> bool { 14 | true 15 | } 16 | } 17 | 18 | #[charon::rename("BoolImpl")] 19 | impl BoolTrait for bool { 20 | fn get_bool(&self) -> bool { 21 | *self 22 | } 23 | } 24 | 25 | #[charon::rename("BoolFn")] 26 | pub fn test_bool_trait(x: bool) -> bool { 27 | x.get_bool() && x.ret_true() 28 | } 29 | 30 | #[charon::rename("TypeTest")] 31 | type Test = i32; 32 | 33 | #[charon::rename("VariantsTest")] 34 | enum SimpleEnum { 35 | #[charon::rename("Variant1")] 36 | FirstVariant, 37 | SecondVariant, 38 | ThirdVariant, 39 | } 40 | 41 | #[charon::rename("StructTest")] 42 | struct Foo { 43 | #[charon::rename("FieldTest")] 44 | field1: u32, 45 | } 46 | 47 | #[charon::rename("Const_Test")] 48 | const C: u32 = 100 + 10 + 1; 49 | 50 | #[aeneas::rename("_TypeAeneas36")] 51 | type Test2 = u32; 52 | -------------------------------------------------------------------------------- /charon/tests/ui/rename_attribute_failure.out: -------------------------------------------------------------------------------- 1 | error: Error parsing attribute: attribute `rename` should not be empty 2 | --> tests/ui/rename_attribute_failure.rs:6:1 3 | | 4 | 6 | #[charon::rename("")] 5 | | ^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | error: Error parsing attribute: attribute `rename` should contain a valid identifier 8 | --> tests/ui/rename_attribute_failure.rs:9:1 9 | | 10 | 9 | #[charon::rename("Test!976?")] 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 12 | 13 | error: Error parsing attribute: attribute `rename` should contain a valid identifier 14 | --> tests/ui/rename_attribute_failure.rs:12:1 15 | | 16 | 12 | #[charon::rename("75Test")] 17 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ 18 | 19 | error: Error parsing attribute: the new name should be between quotes: `rename("aaaa")`. 20 | --> tests/ui/rename_attribute_failure.rs:15:1 21 | | 22 | 15 | #[charon::rename(aaaa)] 23 | | ^^^^^^^^^^^^^^^^^^^^^^^ 24 | 25 | error: There should be at most one `charon::rename("...")` or `aeneas::rename("...")` attribute per declaration 26 | --> tests/ui/rename_attribute_failure.rs:20:1 27 | | 28 | 20 | pub type TestMultiple = (); 29 | | ^^^^^^^^^^^^^^^^^^^^^ 30 | 31 | error: Error parsing attribute: Unrecognized attribute: `charon::something_else("_Type36")` 32 | --> tests/ui/rename_attribute_failure.rs:22:1 33 | | 34 | 22 | #[charon::something_else("_Type36")] 35 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 36 | 37 | ERROR Charon failed to translate this code (6 errors) 38 | -------------------------------------------------------------------------------- /charon/tests/ui/rename_attribute_failure.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | #![feature(register_tool)] 3 | #![register_tool(charon)] 4 | #![register_tool(aeneas)] 5 | 6 | #[charon::rename("")] 7 | pub type TestEmpty = (); 8 | 9 | #[charon::rename("Test!976?")] 10 | pub type TestNonAlphanumeric = (); 11 | 12 | #[charon::rename("75Test")] 13 | pub type TestNotStartingWithLetter = (); 14 | 15 | #[charon::rename(aaaa)] 16 | pub type TestNotQuoted = (); 17 | 18 | #[charon::rename("_Type36")] 19 | #[aeneas::rename("_Type37")] 20 | pub type TestMultiple = (); 21 | 22 | #[charon::something_else("_Type36")] 23 | pub type TestUnrecognizedArg = (); 24 | -------------------------------------------------------------------------------- /charon/tests/ui/result-unwrap.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--extract-opaque-bodies 2 | 3 | fn unwrap(res: Result) -> u32 { 4 | res.unwrap() 5 | } 6 | -------------------------------------------------------------------------------- /charon/tests/ui/scopes.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::Trait 4 | trait Trait<'a, Self> 5 | { 6 | fn method<'b> = test_crate::Trait::method<'a, 'b, Self> 7 | } 8 | 9 | // Full name: test_crate::{impl Trait<'a> for &'a (())}::method 10 | fn {impl Trait<'a> for &'a (())}::method<'a, 'b>(@1: &'b (&'a (()))) -> &'b (()) 11 | 12 | // Full name: test_crate::{impl Trait<'a> for &'a (())} 13 | impl<'a> Trait<'a> for &'a (()) { 14 | fn method<'b> = {impl Trait<'a> for &'a (())}::method<'a, 'b> 15 | } 16 | 17 | // Full name: test_crate::Foo 18 | opaque type Foo<'a> 19 | 20 | fn test_crate::{Foo<'_0>}#1::bar<'_0, '_1>(@1: &'_1 (Foo<'_0>)) -> &'_1 (()) 21 | 22 | // Full name: test_crate::foo 23 | fn foo<'_0>(@1: &'_0 (fn<'_0>(&'_0_0 (u32)) -> u32)) 24 | 25 | fn test_crate::bar<'_0>(@1: &'_0 (fn<'_0>(&'_0_0 (fn<'_0>(&'_0_0 (u32)) -> u32)))) 26 | 27 | // Full name: test_crate::baz 28 | fn baz<'a>(@1: &'a (fn<'b>(&'a (u32), &'b (fn<'c>(&'a (u32), &'b (u32), &'c (u32)) -> u32)))) 29 | 30 | fn test_crate::Trait::method<'a, 'b, Self>(@1: &'b (Self)) -> &'b (()) 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /charon/tests/ui/scopes.rs: -------------------------------------------------------------------------------- 1 | #![feature(register_tool)] 2 | #![register_tool(charon)] 3 | //! Test that we scope things properly. 4 | 5 | trait Trait<'a> { 6 | fn method<'b>(&'b self) -> &'b (); 7 | } 8 | 9 | impl<'a> Trait<'a> for &'a () { 10 | #[charon::opaque] 11 | fn method<'b>(&'b self) -> &'b () { 12 | self 13 | } 14 | } 15 | 16 | #[charon::opaque] 17 | struct Foo<'a>(&'a ()); 18 | 19 | impl Foo<'_> { 20 | #[charon::opaque] 21 | fn bar(&self) -> &() { 22 | self.0 23 | } 24 | } 25 | 26 | #[charon::opaque] 27 | fn foo(_: &fn(&u32) -> u32) {} 28 | 29 | #[charon::opaque] 30 | fn bar(_: &fn(&fn(&u32) -> u32)) {} 31 | 32 | #[charon::opaque] 33 | fn baz<'a>(_: &'a for<'b> fn(&'a u32, &'b for<'c> fn(&'a u32, &'b u32, &'c u32) -> u32)) {} 34 | -------------------------------------------------------------------------------- /charon/tests/ui/send_bound.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: core::marker::Send 8 | #[lang_item("Send")] 9 | pub trait Send 10 | 11 | // Full name: test_crate::foo 12 | fn foo(@1: M) 13 | where 14 | [@TraitClause0]: Sized, 15 | [@TraitClause1]: Send, 16 | { 17 | let @0: (); // return 18 | let _msg@1: M; // arg #1 19 | 20 | @0 := () 21 | drop _msg@1 22 | @0 := () 23 | return 24 | } 25 | 26 | // Full name: test_crate::main 27 | fn main() 28 | { 29 | let @0: (); // return 30 | let @1: (); // anonymous local 31 | let @2: (); // anonymous local 32 | 33 | storage_live(@1) 34 | storage_live(@2) 35 | @2 := () 36 | @1 := foo<()>[Sized<()>, Send<()>](move (@2)) 37 | storage_dead(@2) 38 | storage_dead(@1) 39 | @0 := () 40 | @0 := () 41 | return 42 | } 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /charon/tests/ui/send_bound.rs: -------------------------------------------------------------------------------- 1 | fn foo(_msg: M) {} 2 | 3 | fn main() { 4 | foo(()); 5 | } 6 | -------------------------------------------------------------------------------- /charon/tests/ui/simple-cmp.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--include core::cmp::impls::_::partial_cmp 2 | 3 | fn main() { 4 | let x: i32 = 11; 5 | let y: i32 = 22; 6 | let _ = x.cmp(&y); 7 | } 8 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/additions.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--extract-opaque-bodies 2 | //! Tests the various ways to handle overflow are correctly translated. 3 | fn main() { 4 | let _ = 255u8.wrapping_add(1); 5 | let _ = 255u8.overflowing_add(1); 6 | // This one is meant to be implemented by codegen backends, hence has no useful MIR. 7 | let _ = 255u8.saturating_add(1); 8 | // FIXME(#543): this causes a panic in hax 9 | // unsafe { 10 | // let _ = 255u8.unchecked_add(1); 11 | // } 12 | } 13 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/array_index.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::first 4 | pub fn first(@1: Array) -> u32 5 | { 6 | let @0: u32; // return 7 | let s@1: Array; // arg #1 8 | let @2: usize; // anonymous local 9 | let @3: &'_ (Array); // anonymous local 10 | let @4: &'_ (u32); // anonymous local 11 | 12 | storage_live(@2) 13 | @2 := const (0 : usize) 14 | storage_live(@3) 15 | @3 := &s@1 16 | storage_live(@4) 17 | @4 := @ArrayIndexShared<'_, u32, 0 : usize>(move (@3), copy (@2)) 18 | @0 := copy (*(@4)) 19 | storage_dead(@2) 20 | return 21 | } 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/array_index.rs: -------------------------------------------------------------------------------- 1 | pub fn first(s: [u32; 0]) -> u32 { 2 | s[0] 3 | } 4 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/assoc-constraint-on-assoc-ty-nested.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: test_crate::Trait 8 | trait Trait 9 | { 10 | parent_clause0 : [@TraitClause0]: Sized 11 | } 12 | 13 | // Full name: test_crate::IntoIterator 14 | trait IntoIterator 15 | { 16 | parent_clause0 : [@TraitClause0]: Sized 17 | parent_clause1 : [@TraitClause1]: Trait 18 | } 19 | 20 | // Full name: test_crate::IntoIntoIterator 21 | trait IntoIntoIterator 22 | { 23 | parent_clause0 : [@TraitClause0]: Sized 24 | parent_clause1 : [@TraitClause1]: IntoIterator 25 | } 26 | 27 | // Full name: test_crate::foo 28 | fn foo() 29 | where 30 | [@TraitClause0]: Sized, 31 | [@TraitClause1]: IntoIntoIterator, 32 | [@TraitClause2]: Trait, 33 | { 34 | let @0: (); // return 35 | 36 | @0 := () 37 | @0 := () 38 | return 39 | } 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/assoc-constraint-on-assoc-ty-nested.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | trait Trait { 3 | type Assoc; 4 | } 5 | 6 | trait IntoIterator { 7 | type IntoIter: Trait; 8 | } 9 | 10 | trait IntoIntoIterator { 11 | type IntoIntoIter: IntoIterator; 12 | } 13 | 14 | // We should be able to deduce that `Clause2_Assoc = ()`, but this requires unification of 15 | // identical trait clauses. 16 | fn foo() 17 | where 18 | I: IntoIntoIterator, 19 | <::IntoIntoIter as IntoIterator>::IntoIter: Trait, 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/assoc-constraint-on-assoc-ty.2.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: test_crate::Trait 8 | trait Trait 9 | { 10 | parent_clause0 : [@TraitClause0]: Sized 11 | } 12 | 13 | // Full name: test_crate::IntoIterator 14 | trait IntoIterator 15 | { 16 | parent_clause0 : [@TraitClause0]: Sized 17 | parent_clause1 : [@TraitClause1]: Trait 18 | } 19 | 20 | // Full name: test_crate::foo 21 | fn foo() 22 | where 23 | [@TraitClause0]: Sized, 24 | [@TraitClause1]: IntoIterator, 25 | [@TraitClause2]: Trait, 26 | { 27 | let @0: (); // return 28 | 29 | @0 := () 30 | @0 := () 31 | return 32 | } 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/assoc-constraint-on-assoc-ty.2.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | trait Trait { 3 | type Assoc; 4 | } 5 | 6 | trait IntoIterator { 7 | type IntoIter: Trait; 8 | } 9 | 10 | // We should be able to deduce that `Clause2_Assoc = ()`, but this requires unification of 11 | // identical trait clauses. 12 | // TODO: open an issue to track this 13 | fn foo() 14 | where 15 | I: IntoIterator, 16 | I::IntoIter: Trait, 17 | { 18 | } 19 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/assoc-constraint-on-assoc-ty.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: test_crate::Trait 8 | trait Trait 9 | { 10 | parent_clause0 : [@TraitClause0]: Sized 11 | } 12 | 13 | // Full name: test_crate::takes_trait 14 | fn takes_trait(@1: I) 15 | where 16 | [@TraitClause0]: Sized, 17 | [@TraitClause1]: Trait, 18 | { 19 | let @0: (); // return 20 | let it@1: I; // arg #1 21 | 22 | @0 := () 23 | drop it@1 24 | @0 := () 25 | return 26 | } 27 | 28 | // Full name: test_crate::IntoIterator 29 | trait IntoIterator 30 | { 31 | parent_clause0 : [@TraitClause0]: Sized 32 | parent_clause1 : [@TraitClause1]: Trait 33 | } 34 | 35 | // Full name: test_crate::collect 36 | fn collect(@1: Clause1_IntoIter) 37 | where 38 | [@TraitClause0]: Sized, 39 | [@TraitClause1]: IntoIterator, 40 | { 41 | let @0: (); // return 42 | let it@1: Clause1_IntoIter; // arg #1 43 | let @2: Clause1_IntoIter; // anonymous local 44 | 45 | storage_live(@2) 46 | @2 := move (it@1) 47 | @0 := takes_trait[@TraitClause1::parent_clause0, @TraitClause1::parent_clause1](move (@2)) 48 | storage_dead(@2) 49 | drop it@1 50 | @0 := () 51 | return 52 | } 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/assoc-constraint-on-assoc-ty.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | trait Trait { 3 | type Assoc; 4 | } 5 | fn takes_trait(it: I) {} 6 | 7 | trait IntoIterator { 8 | type IntoIter: Trait; 9 | } 10 | 11 | fn collect(it: I::IntoIter) { 12 | takes_trait(it) 13 | } 14 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/assoc-ty-via-supertrait-and-bounds.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | pub trait HasOutput { 3 | type Output; 4 | } 5 | impl HasOutput for () { 6 | type Output = (); 7 | } 8 | 9 | pub trait HasOutput2: HasOutput {} 10 | impl HasOutput2 for () {} 11 | 12 | struct Wrapper(T); 13 | impl HasOutput for Wrapper { 14 | type Output = ::Output; 15 | } 16 | impl HasOutput2 for Wrapper {} 17 | 18 | fn take() {} 19 | fn main() { 20 | take::>() 21 | } 22 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/assoc-type-with-fn-bound.out: -------------------------------------------------------------------------------- 1 | error: Could not compute the value of Self::Clause1::Clause0::Clause0::Output needed to update generics for item core::ops::function::FnOnce. 2 | Constraints in scope: 3 | - Self::Foo = @Type0_1 4 | --> tests/ui/simple/assoc-type-with-fn-bound.rs:9:5 5 | | 6 | 9 | fn call(&self) -> >::Output; 7 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 8 | 9 | ERROR Charon failed to translate this code (1 errors) 10 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/assoc-type-with-fn-bound.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | //@ charon-args=--remove-associated-types=* 3 | // Fails because of bad handling of `Self` clauses. Should be fixed by 4 | // https://github.com/AeneasVerif/charon/pull/514. 5 | #![feature(unboxed_closures)] 6 | 7 | pub trait Trait { 8 | type Foo: Fn(); 9 | fn call(&self) -> >::Output; 10 | } 11 | 12 | impl Trait for F { 13 | type Foo = F; 14 | fn call(&self) -> >::Output { 15 | self() 16 | } 17 | } 18 | 19 | pub fn use_foo() -> <::Foo as FnOnce<()>>::Output {} 20 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/box-into-inner.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--mir_optimized 2 | fn into_inner(b: Box) { 3 | let _x = *b; 4 | } 5 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/box-new.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: alloc::alloc::Global 8 | #[lang_item("global_alloc_ty")] 9 | pub struct Global {} 10 | 11 | // Full name: test_crate::main 12 | fn main() 13 | { 14 | let @0: (); // return 15 | let @1: alloc::boxed::Box[Sized]; // anonymous local 16 | 17 | storage_live(@1) 18 | @1 := @BoxNew[Sized](const (42 : i32)) 19 | drop @1 20 | storage_dead(@1) 21 | @0 := () 22 | @0 := () 23 | return 24 | } 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/box-new.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--mir=optimized 2 | fn main() { 3 | let _ = Box::new(42); 4 | } 5 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/call-foreign-defaulted-method.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | pub fn test_crate::foo::{impl Trait for ()}::defaulted<'_0>(@1: &'_0 (())) 4 | { 5 | let @0: (); // return 6 | let self@1: &'_ (()); // arg #1 7 | 8 | @0 := () 9 | @0 := () 10 | return 11 | } 12 | 13 | // Full name: test_crate::main 14 | fn main() 15 | { 16 | let @0: (); // return 17 | let @1: (); // anonymous local 18 | let @2: &'_ (()); // anonymous local 19 | let @3: (); // anonymous local 20 | 21 | storage_live(@1) 22 | storage_live(@2) 23 | storage_live(@3) 24 | @3 := () 25 | @2 := &@3 26 | @1 := test_crate::foo::{impl Trait for ()}::defaulted<'_>(move (@2)) 27 | storage_dead(@2) 28 | storage_dead(@3) 29 | storage_dead(@1) 30 | @0 := () 31 | @0 := () 32 | return 33 | } 34 | 35 | // Full name: test_crate::foo::Trait 36 | pub trait Trait 37 | { 38 | fn defaulted<'_0> = defaulted<'_0_0, Self> 39 | } 40 | 41 | // Full name: test_crate::foo::Trait::defaulted 42 | pub fn defaulted<'_0, Self>(@1: &'_0 (Self)) 43 | { 44 | let @0: (); // return 45 | let self@1: &'_ (Self); // arg #1 46 | 47 | @0 := () 48 | @0 := () 49 | return 50 | } 51 | 52 | // Full name: test_crate::foo::{impl Trait for ()} 53 | impl Trait for () { 54 | fn defaulted<'_0> = test_crate::foo::{impl Trait for ()}::defaulted<'_0_0> 55 | } 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/call-foreign-defaulted-method.rs: -------------------------------------------------------------------------------- 1 | //! This tests that we order decl methods _after_ the trait. 2 | #![feature(register_tool)] 3 | #![register_tool(charon)] 4 | use foo::Trait; 5 | fn main() { 6 | let _ = ().defaulted(); 7 | } 8 | 9 | // Make the module opaque so the trait is discovered like a foreign trait. This affects order. 10 | #[charon::opaque] 11 | mod foo { 12 | pub trait Trait { 13 | fn defaulted(&self) {} 14 | } 15 | 16 | impl Trait for () {} 17 | } 18 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/call-inherent-method-with-trait-bound.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | pub trait Trait { 3 | type Type; 4 | } 5 | 6 | impl Trait for () { 7 | type Type = (); 8 | } 9 | 10 | pub struct HashMap(S); 11 | 12 | impl HashMap { 13 | pub fn get(_x: HashMap, _k: Q) {} 14 | } 15 | 16 | pub fn top_level_get(_x: HashMap, _k: Q) {} 17 | 18 | pub fn test1(map: HashMap<()>) { 19 | top_level_get(map, ()); 20 | } 21 | pub fn test2(map: HashMap<()>) { 22 | HashMap::get(map, ()); 23 | } 24 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/call-method-via-supertrait-bound.rs: -------------------------------------------------------------------------------- 1 | trait OtherTrait {} 2 | trait ImpliesOtherTrait: OtherTrait {} 3 | 4 | trait HasMethod { 5 | fn method(&self); 6 | } 7 | impl HasMethod for T { 8 | fn method(&self) {} 9 | } 10 | 11 | fn call_method(x: T) { 12 | let _ = x.method(); 13 | } 14 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/closure-capture-ref-by-move.rs: -------------------------------------------------------------------------------- 1 | fn foo() { 2 | let mut x = 0; 3 | let rx = &mut x; 4 | let mut closure = move || { 5 | *rx += 1; 6 | }; 7 | closure(); 8 | } 9 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/closure-fn.rs: -------------------------------------------------------------------------------- 1 | fn apply_to(f: &impl Fn(u8, u8) -> u8) -> u8 { 2 | f(10, 20) 3 | } 4 | 5 | fn apply_to_mut(f: &mut impl FnMut(u8, u8) -> u8) -> u8 { 6 | f(10, 20) 7 | } 8 | 9 | fn apply_to_once(f: impl FnOnce(u8, u8) -> u8) -> u8 { 10 | f(10, 20) 11 | } 12 | 13 | fn main() { 14 | let v = 5; 15 | let z = 1; 16 | let mut f = |x, y| v + x + y + z; 17 | f(10, 20); 18 | apply_to(&f); 19 | apply_to_mut(&mut f); 20 | apply_to_once(f); 21 | } 22 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/closure-fnmut.rs: -------------------------------------------------------------------------------- 1 | fn apply_to_zero_mut(mut f: impl FnMut(u8) -> u8) -> u8 { 2 | f(0) 3 | } 4 | 5 | fn main() { 6 | let mut z = 3; 7 | apply_to_zero_mut(|x| { 8 | z += 1; 9 | x + z 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/closure-fnonce.rs: -------------------------------------------------------------------------------- 1 | fn apply_to_zero_once(f: impl FnOnce(u8) -> u8) -> u8 { 2 | f(0) 3 | } 4 | 5 | struct NotCopy; 6 | 7 | fn main() { 8 | let z = NotCopy {}; 9 | apply_to_zero_once(|x| { 10 | drop(z); 11 | x + 1 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/closure-inside-impl.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: test_crate::Foo 8 | pub struct Foo 9 | where 10 | [@TraitClause0]: Sized, 11 | { 12 | F, 13 | } 14 | 15 | // Full name: test_crate::{Foo[@TraitClause0]}::method::closure 16 | struct closure 17 | where 18 | [@TraitClause0]: Sized, 19 | [@TraitClause1]: Sized, 20 | {} 21 | 22 | // Full name: test_crate::{Foo[@TraitClause0]}::method 23 | pub fn method() 24 | where 25 | [@TraitClause0]: Sized, 26 | [@TraitClause1]: Sized, 27 | { 28 | let @0: (); // return 29 | let _closure@1: closure[@TraitClause0, @TraitClause1]; // local 30 | 31 | storage_live(_closure@1) 32 | _closure@1 := closure { } 33 | @0 := () 34 | storage_dead(_closure@1) 35 | @0 := () 36 | return 37 | } 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/closure-inside-impl.rs: -------------------------------------------------------------------------------- 1 | pub struct Foo(F); 2 | 3 | impl Foo { 4 | pub fn method() { 5 | let _closure = |_x: ()| (); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/conditional-drop.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--mir=elaborated 2 | fn use_string(_: String) {} 3 | 4 | fn main() { 5 | let s = String::new(); 6 | if false { 7 | use_string(s); 8 | } 9 | // `s` is dropped implicitly here 10 | } 11 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/const-subslice.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::main 4 | fn main() 5 | { 6 | let @0: (); // return 7 | let y@1: &'_ (Slice); // local 8 | let z@2: *const u8; // local 9 | let @3: *const Slice; // anonymous local 10 | let @4: usize; // anonymous local 11 | let @5: *const u8; // anonymous local 12 | let @6: Slice; // anonymous local 13 | let @7: &'_ (Slice); // anonymous local 14 | 15 | storage_live(@6) 16 | storage_live(@7) 17 | storage_live(y@1) 18 | @6 := [const (0 : u8), const (1 : u8), const (2 : u8)] 19 | @7 := &@6 20 | y@1 := move (@7) 21 | storage_live(z@2) 22 | storage_live(@3) 23 | @3 := &raw const *(y@1) 24 | z@2 := cast<*const Slice, *const u8>(move (@3)) 25 | storage_dead(@3) 26 | storage_live(@4) 27 | storage_live(@5) 28 | @5 := copy (z@2) 29 | @4 := cast<*const u8, usize>(move (@5)) 30 | storage_dead(@5) 31 | storage_dead(@4) 32 | @0 := () 33 | storage_dead(z@2) 34 | storage_dead(y@1) 35 | @0 := () 36 | return 37 | } 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/const-subslice.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--mir_optimized 2 | fn main() { 3 | let y: &[u8] = const { 4 | let x: &[u8] = &[0, 1, 2, 3, 4]; 5 | unsafe { std::slice::from_raw_parts(x as *const [u8] as *const u8, 3) } 6 | }; 7 | let z: *const u8 = y as *const [u8] as *const u8; 8 | let _ = z as usize; 9 | } 10 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/default-method-with-clause-and-marker-trait.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::HasAssoc 4 | trait HasAssoc 5 | { 6 | type Assoc 7 | } 8 | 9 | // Full name: test_crate::Trait 10 | trait Trait 11 | { 12 | fn default_method> = default_method[@TraitClause0_1] 13 | } 14 | 15 | fn test_crate::{impl Trait for T}::default_method() -> @TraitClause2::Assoc 16 | where 17 | [@TraitClause2]: HasAssoc, 18 | { 19 | let @0: @TraitClause2::Assoc; // return 20 | 21 | panic(core::panicking::panic) 22 | } 23 | 24 | // Full name: test_crate::{impl Trait for T} 25 | impl Trait for T { 26 | fn default_method> = test_crate::{impl Trait for T}::default_method[@TraitClause0_1] 27 | } 28 | 29 | // Full name: test_crate::main 30 | fn main() 31 | { 32 | let @0: (); // return 33 | 34 | @0 := () 35 | @0 := () 36 | return 37 | } 38 | 39 | // Full name: test_crate::Trait::default_method 40 | fn default_method() -> @TraitClause1::Assoc 41 | where 42 | [@TraitClause1]: HasAssoc, 43 | { 44 | let @0: @TraitClause1::Assoc; // return 45 | 46 | panic(core::panicking::panic) 47 | } 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/default-method-with-clause-and-marker-trait.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--hide-marker-traits 2 | // https://github.com/AeneasVerif/charon/issues/561 3 | use std::marker::PhantomData; 4 | 5 | trait HasAssoc { 6 | type Assoc; 7 | } 8 | trait Trait { 9 | fn default_method() -> T::Assoc { 10 | todo!() 11 | } 12 | } 13 | 14 | // The `Sized` trait is the culprit. 15 | impl Trait for T {} 16 | 17 | fn main() {} 18 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/fewer-clauses-in-method-impl.2.out: -------------------------------------------------------------------------------- 1 | error: Mismatched method generics: 2 | params: 3 | supplied: [@TraitDecl1<()>] 4 | --> tests/ui/simple/fewer-clauses-in-method-impl.2.rs:14:5 5 | | 6 | 14 | <() as Trait>::method() 7 | | ^^^^^^^^^^^^^^^^^^^^^^^ 8 | 9 | ERROR Charon failed to translate this code (1 errors) 10 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/fewer-clauses-in-method-impl.2.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | //@ charon-args=--remove-associated-types=* 3 | trait Trait { 4 | fn method() 5 | where 6 | Self: Sized; 7 | } 8 | 9 | impl Trait for () { 10 | fn method() {} 11 | } 12 | 13 | pub fn main() { 14 | <() as Trait>::method() 15 | } 16 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/fewer-clauses-in-method-impl.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | trait Trait { 3 | fn method(); 4 | } 5 | 6 | impl Trait for () { 7 | fn method() {} 8 | } 9 | 10 | fn main() { 11 | <() as Trait>::method::<()>() 12 | } 13 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/gat-default.out: -------------------------------------------------------------------------------- 1 | 2 | thread 'rustc' panicked at /rustc/920d95eaf23d7eb6b415d09868e4f793024fa604/compiler/rustc_type_ir/src/binder.rs:737:9: 3 | type parameter `U/#1` (U/#1/1) out of range when instantiating, args=[()] 4 | note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace 5 | error: Hax panicked when translating `test_crate::{impl#0}`. 6 | --> tests/ui/simple/gat-default.rs:9:1 7 | | 8 | 9 | impl Collection for () {} 9 | | ^^^^^^^^^^^^^^^^^^^^^^ 10 | 11 | error: Generic associated types are not supported 12 | --> tests/ui/simple/gat-default.rs:6:5 13 | | 14 | 6 | type Sibling = Vec; 15 | | ^^^^^^^^^^^^^^^ 16 | 17 | error: Item `test_crate::Collection` caused errors; ignoring. 18 | --> tests/ui/simple/gat-default.rs:5:1 19 | | 20 | 5 | trait Collection { 21 | | ^^^^^^^^^^^^^^^^ 22 | 23 | 24 | thread 'rustc' panicked at /rustc/920d95eaf23d7eb6b415d09868e4f793024fa604/compiler/rustc_type_ir/src/binder.rs:737:9: 25 | type parameter `U/#1` (U/#1/1) out of range when instantiating, args=[()] 26 | error: Hax panicked when translating `test_crate::{impl#0}`. 27 | --> tests/ui/simple/gat-default.rs:9:1 28 | | 29 | 9 | impl Collection for () {} 30 | | ^^^^^^^^^^^^^^^^^^^^^^ 31 | 32 | error: Item `test_crate::{impl#0}` caused errors; ignoring. 33 | --> tests/ui/simple/gat-default.rs:9:1 34 | | 35 | 9 | impl Collection for () {} 36 | | ^^^^^^^^^^^^^^^^^^^^^^ 37 | 38 | ERROR Charon failed to translate this code (5 errors) 39 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/gat-default.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | //! Test associated type defaults with parameters 3 | #![feature(associated_type_defaults)] 4 | 5 | trait Collection { 6 | type Sibling = Vec; 7 | } 8 | 9 | impl Collection for () {} 10 | 11 | fn main() {} 12 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/generic-impl-with-defaulted-method-with-clause-with-assoc-ty.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | trait HasType { 3 | type Type; 4 | } 5 | 6 | trait HasMethod { 7 | fn method() 8 | where 9 | Self: HasType, 10 | { 11 | } 12 | } 13 | 14 | impl HasMethod for Option {} 15 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/generic-impl-with-defaulted-method.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::BoolTrait 4 | pub trait BoolTrait 5 | { 6 | fn foo<'_0> = foo<'_0_0, Self> 7 | } 8 | 9 | // Full name: core::marker::Sized 10 | #[lang_item("sized")] 11 | pub trait Sized 12 | 13 | // Full name: core::option::Option 14 | #[lang_item("Option")] 15 | pub enum Option 16 | where 17 | [@TraitClause0]: Sized, 18 | { 19 | None, 20 | Some(T), 21 | } 22 | 23 | pub fn test_crate::{impl BoolTrait for Option[@TraitClause0]}::foo<'_0, T>(@1: &'_0 (Option[@TraitClause0])) 24 | where 25 | [@TraitClause0]: Sized, 26 | { 27 | let @0: (); // return 28 | let self@1: &'_ (Option[@TraitClause0]); // arg #1 29 | 30 | @0 := () 31 | @0 := () 32 | return 33 | } 34 | 35 | // Full name: test_crate::{impl BoolTrait for Option[@TraitClause0]} 36 | impl BoolTrait for Option[@TraitClause0] 37 | where 38 | [@TraitClause0]: Sized, 39 | { 40 | fn foo<'_0> = test_crate::{impl BoolTrait for Option[@TraitClause0]}::foo<'_0_0, T>[@TraitClause0] 41 | } 42 | 43 | // Full name: test_crate::BoolTrait::foo 44 | pub fn foo<'_0, Self>(@1: &'_0 (Self)) 45 | { 46 | let @0: (); // return 47 | let self@1: &'_ (Self); // arg #1 48 | 49 | @0 := () 50 | @0 := () 51 | return 52 | } 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/generic-impl-with-defaulted-method.rs: -------------------------------------------------------------------------------- 1 | pub trait BoolTrait { 2 | fn foo(&self) {} 3 | } 4 | 5 | impl BoolTrait for Option {} 6 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/generic-impl-with-method.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::Trait 4 | pub trait Trait 5 | { 6 | fn method<'_0> = test_crate::Trait::method<'_0_0, Self> 7 | } 8 | 9 | // Full name: core::marker::Sized 10 | #[lang_item("sized")] 11 | pub trait Sized 12 | 13 | // Full name: test_crate::{impl Trait for T}::method 14 | pub fn {impl Trait for T}::method<'_0, T>(@1: &'_0 (T)) 15 | where 16 | [@TraitClause0]: Sized, 17 | { 18 | let @0: (); // return 19 | let self@1: &'_ (T); // arg #1 20 | 21 | @0 := () 22 | @0 := () 23 | return 24 | } 25 | 26 | // Full name: test_crate::{impl Trait for T} 27 | impl Trait for T 28 | where 29 | [@TraitClause0]: Sized, 30 | { 31 | fn method<'_0> = {impl Trait for T}::method<'_0_0, T>[@TraitClause0] 32 | } 33 | 34 | pub fn test_crate::Trait::method<'_0, Self>(@1: &'_0 (Self)) 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/generic-impl-with-method.rs: -------------------------------------------------------------------------------- 1 | pub trait Trait { 2 | fn method(&self); 3 | } 4 | 5 | impl Trait for T { 6 | fn method(&self) {} 7 | } 8 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/match-on-char.out: -------------------------------------------------------------------------------- 1 | error: Can't match on type char 2 | --> tests/ui/simple/match-on-char.rs:3:5 3 | | 4 | 3 | match 'x' { 5 | | ^^^^^^^^^ 6 | 7 | ERROR Charon failed to translate this code (1 errors) 8 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/match-on-char.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | fn main() { 3 | match 'x' { 4 | 'a' => {} 5 | _ => {} 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/match-on-float.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::main 4 | fn main() 5 | { 6 | let @0: (); // return 7 | let @1: f64; // anonymous local 8 | let @2: bool; // anonymous local 9 | let @3: bool; // anonymous local 10 | 11 | storage_live(@2) 12 | storage_live(@3) 13 | storage_live(@1) 14 | @1 := const (0.5 : f64) 15 | @3 := const (0.10000000000000001 : f64) == copy (@1) 16 | if move (@3) { 17 | @0 := () 18 | } 19 | else { 20 | @2 := const (0.20000000000000001 : f64) == copy (@1) 21 | if move (@2) { 22 | @0 := () 23 | } 24 | else { 25 | @0 := () 26 | } 27 | } 28 | storage_dead(@1) 29 | @0 := () 30 | return 31 | } 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/match-on-float.rs: -------------------------------------------------------------------------------- 1 | // This compiles to a series of `if`s. 2 | fn main() { 3 | match 0.5 { 4 | 0.1 => {} 5 | 0.2 => {} 6 | _ => {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/mem-discriminant-from-derive.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | // This derive generates code that uses `mem::discriminant`, which involves the builtin associated 3 | // type `::Discriminant`. 4 | #[derive(PartialEq)] 5 | enum Enum { 6 | Some(u8), 7 | None, 8 | } 9 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/method-with-assoc-type-constraint.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | pub trait IntoIterator { 3 | type Item; 4 | } 5 | 6 | pub trait FromIterator: Sized { 7 | fn from_iter(iter: T) -> Self 8 | where 9 | T: IntoIterator; 10 | } 11 | 12 | impl FromIterator<()> for () { 13 | fn from_iter>(iter: I) -> () {} 14 | } 15 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/multiple-promoteds.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--mir_optimized 2 | fn six() -> u32 { 3 | let x = &(0 + 1); 4 | let y = &(2 + 3); 5 | x + y 6 | } 7 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/nested-closure.rs: -------------------------------------------------------------------------------- 1 | struct Foo<'a, T>(&'a T); 2 | 3 | impl<'a, T> Foo<'a, T> 4 | where 5 | T: Clone, 6 | { 7 | pub fn test_nested_closures<'b>(x: &'a &'b T) -> T { 8 | let clo = || |_y: &u32| |_z: &u32| (*x).clone(); 9 | clo()(&0)(&1) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/nested-inline-const.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::main 4 | fn main() 5 | { 6 | let @0: (); // return 7 | let @1: i32; // anonymous local 8 | 9 | storage_live(@1) 10 | @1 := const (1 : i32) + const (9 : i32) 11 | storage_dead(@1) 12 | @0 := () 13 | @0 := () 14 | return 15 | } 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/nested-inline-const.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let _ = 1 + const { 2 + const { 3 + 4 } }; 3 | } 4 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/opaque-trait-with-clause-in-method.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: test_crate::opaque::Iterator 8 | pub trait Iterator 9 | 10 | // Full name: test_crate::foo 11 | fn foo() 12 | where 13 | [@TraitClause0]: Sized, 14 | [@TraitClause1]: Iterator, 15 | { 16 | let @0: (); // return 17 | 18 | @0 := () 19 | @0 := () 20 | return 21 | } 22 | 23 | // Full name: test_crate::opaque::Product 24 | pub trait Product 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/opaque-trait-with-clause-in-method.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--opaque test_crate::opaque 2 | //! We're only translating `Product` because it appears in the clauses of the `Binder` that we 3 | //! construct unconditionally even for methods we won't end up translating. 4 | //! Ideally we wouldn't translate `Product` either. 5 | mod opaque { 6 | pub trait Product {} 7 | pub trait Iterator { 8 | fn product() {} 9 | } 10 | } 11 | fn foo() {} 12 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/pass-higher-kinded-fn-item-as-closure.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | pub fn flabada<'a>(x: &'a ()) -> &'a () { 3 | x 4 | } 5 | 6 | pub fn call<'b, F: Fn(&'b ()) -> &'b ()>(_: F) {} 7 | 8 | pub fn flibidi() { 9 | call(flabada); 10 | } 11 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/pointee_metadata.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | #![feature(ptr_metadata)] 3 | 4 | fn empty_metadata() { 5 | let _ = (&0u32 as *const u32).to_raw_parts(); 6 | } 7 | 8 | fn slice_metadata() { 9 | let _ = (&[0u32, 1u32] as *const [u32]).to_raw_parts(); 10 | } 11 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/promoted-closure-no-warns.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::foo::closure 4 | struct closure {} 5 | 6 | // Full name: test_crate::foo 7 | pub fn foo() -> &'static (closure) 8 | { 9 | let @0: &'_ (closure); // return 10 | let @1: &'_ (closure); // anonymous local 11 | let @2: &'_ (closure); // anonymous local 12 | let @3: &'_ (closure); // anonymous local 13 | let @4: &'_ (closure); // anonymous local 14 | let @5: closure; // anonymous local 15 | 16 | storage_live(@3) 17 | storage_live(@4) 18 | storage_live(@5) 19 | @5 := closure { } 20 | @4 := &@5 21 | storage_live(@1) 22 | storage_live(@2) 23 | @3 := move (@4) 24 | @2 := &*(@3) 25 | @1 := &*(@2) 26 | @0 := &*(@1) 27 | storage_dead(@2) 28 | storage_dead(@1) 29 | return 30 | } 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/promoted-closure-no-warns.rs: -------------------------------------------------------------------------------- 1 | //@ ignore-warnings 2 | //@ charon-args=--mir_optimized 3 | pub fn foo() -> &'static impl Fn(u32) -> u32 { 4 | &|x: u32| x 5 | } 6 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/promoted-closure.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::foo::closure 4 | struct closure {} 5 | 6 | // Full name: test_crate::foo 7 | pub fn foo() -> &'static (closure) 8 | { 9 | let @0: &'_ (closure); // return 10 | let @1: &'_ (closure); // anonymous local 11 | let @2: &'_ (closure); // anonymous local 12 | let @3: &'_ (closure); // anonymous local 13 | let @4: &'_ (closure); // anonymous local 14 | let @5: closure; // anonymous local 15 | 16 | storage_live(@3) 17 | storage_live(@4) 18 | storage_live(@5) 19 | @5 := closure { } 20 | @4 := &@5 21 | storage_live(@1) 22 | storage_live(@2) 23 | @3 := move (@4) 24 | @2 := &*(@3) 25 | @1 := &*(@2) 26 | @0 := &*(@1) 27 | storage_dead(@2) 28 | storage_dead(@1) 29 | return 30 | } 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/promoted-closure.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--mir_optimized 2 | pub fn foo() -> &'static impl Fn(u32) -> u32 { 3 | &|x: u32| x 4 | } 5 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/promoted-in-generic-fn.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: core::mem::size_of 8 | #[lang_item("mem_size_of")] 9 | pub fn size_of() -> usize 10 | where 11 | [@TraitClause0]: Sized, 12 | 13 | // Full name: test_crate::f 14 | fn f() 15 | where 16 | [@TraitClause0]: Sized, 17 | { 18 | let @0: (); // return 19 | let @1: &'_ (usize); // anonymous local 20 | let @2: &'_ (usize); // anonymous local 21 | let @3: &'_ (usize); // anonymous local 22 | let @4: usize; // anonymous local 23 | 24 | storage_live(@2) 25 | storage_live(@3) 26 | storage_live(@4) 27 | // This can't be evaluated generically. 28 | @4 := size_of[@TraitClause0]() 29 | @3 := &@4 30 | storage_live(@1) 31 | @2 := move (@3) 32 | @1 := &*(@2) 33 | storage_dead(@1) 34 | @0 := () 35 | @0 := () 36 | return 37 | } 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/promoted-in-generic-fn.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--mir=promoted 2 | fn f() { 3 | // This can't be evaluated generically. 4 | let _ = &size_of::(); 5 | } 6 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/promoted-literal-addition-overflow.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | pub fn core::num::{u32}#8::MAX() -> u32 4 | 5 | pub const core::num::{u32}#8::MAX: u32 = core::num::{u32}#8::MAX() 6 | 7 | // Full name: test_crate::overflow 8 | fn overflow() -> &'static (u32) 9 | { 10 | let @0: &'_ (u32); // return 11 | let @1: &'_ (u32); // anonymous local 12 | let @2: &'_ (u32); // anonymous local 13 | let @3: &'_ (u32); // anonymous local 14 | let @4: u32; // anonymous local 15 | let @5: (u32, bool); // anonymous local 16 | let @6: u32; // anonymous local 17 | 18 | storage_live(@2) 19 | storage_live(@3) 20 | storage_live(@4) 21 | storage_live(@5) 22 | storage_live(@6) 23 | storage_live(@1) 24 | @6 := core::num::{u32}#8::MAX 25 | @5 := move (@6) checked.+ const (1 : u32) 26 | @4 := move ((@5).0) 27 | @3 := &@4 28 | @2 := move (@3) 29 | @1 := &*(@2) 30 | @0 := &*(@1) 31 | storage_dead(@1) 32 | return 33 | } 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/promoted-literal-addition-overflow.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--mir_optimized 2 | #[allow(arithmetic_overflow)] 3 | fn overflow() -> &'static u32 { 4 | &(u32::MAX + 1) 5 | } 6 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/promoted-literal-addition.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::two 4 | fn two() -> &'static (u32) 5 | { 6 | let @0: &'_ (u32); // return 7 | let @1: &'_ (u32); // anonymous local 8 | let @2: &'_ (u32); // anonymous local 9 | let @3: &'_ (u32); // anonymous local 10 | let @4: u32; // anonymous local 11 | let @5: (u32, bool); // anonymous local 12 | 13 | storage_live(@2) 14 | storage_live(@3) 15 | storage_live(@4) 16 | storage_live(@5) 17 | storage_live(@1) 18 | @5 := const (1 : u32) checked.+ const (1 : u32) 19 | @4 := move ((@5).0) 20 | @3 := &@4 21 | @2 := move (@3) 22 | @1 := &*(@2) 23 | @0 := &*(@1) 24 | storage_dead(@1) 25 | return 26 | } 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/promoted-literal-addition.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--mir_optimized 2 | fn two() -> &'static u32 { 3 | &(1 + 1) 4 | } 5 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/promoted-u32-slice.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::foo 4 | pub fn foo() -> &'static (Slice) 5 | { 6 | let @0: &'_ (Slice); // return 7 | let @1: &'_ (Array); // anonymous local 8 | let @2: &'_ (Array); // anonymous local 9 | let @3: &'_ (Array); // anonymous local 10 | let @4: &'_ (Array); // anonymous local 11 | let @5: Array; // anonymous local 12 | 13 | storage_live(@3) 14 | storage_live(@4) 15 | storage_live(@5) 16 | @5 := [const (0 : u32), const (1 : u32), const (2 : u32), const (3 : u32)] 17 | @4 := &@5 18 | storage_live(@1) 19 | storage_live(@2) 20 | @3 := move (@4) 21 | @2 := &*(@3) 22 | @1 := &*(@2) 23 | @0 := @ArrayToSliceShared<'_, u32, 4 : usize>(move (@1)) 24 | storage_dead(@1) 25 | storage_dead(@2) 26 | return 27 | } 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/promoted-u32-slice.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--mir_optimized 2 | pub fn foo() -> &'static [u32] { 3 | &[0, 1, 2, 3] 4 | } 5 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/ptr-from-raw-parts.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: core::ptr::metadata::from_raw_parts 8 | pub fn from_raw_parts(@1: *const impl Thin, @2: Pointee::Metadata) -> *const T 9 | where 10 | [@TraitClause0]: Sized, 11 | [@TraitClause1]: Thin, 12 | { 13 | let @0: *const T; // return 14 | let data_pointer@1: *const impl Thin; // arg #1 15 | let metadata@2: Pointee::Metadata; // arg #2 16 | 17 | @0 := @PtrFromPartsShared<'_, T>(copy (data_pointer@1), copy (metadata@2)) 18 | return 19 | } 20 | 21 | // Full name: test_crate::main 22 | fn main() 23 | { 24 | let @0: (); // return 25 | let a@1: Array; // local 26 | let @2: *const Slice; // anonymous local 27 | let @3: *const Array; // anonymous local 28 | 29 | storage_live(a@1) 30 | a@1 := @ArrayRepeat<'_, u32, 2 : usize>(const (1 : u32)) 31 | storage_live(@2) 32 | storage_live(@3) 33 | @3 := &raw const a@1 34 | @2 := from_raw_parts, Array>[Sized>, Thin>](move (@3), const (2 : usize)) 35 | storage_dead(@3) 36 | storage_dead(@2) 37 | @0 := () 38 | storage_dead(a@1) 39 | @0 := () 40 | return 41 | } 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/ptr-from-raw-parts.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--exclude=core::ptr::metadata::Thin 2 | //@ charon-args=--exclude=core::ptr::metadata::Pointee 3 | //@ charon-args=--include=core::ptr::metadata::from_raw_parts 4 | #![feature(ptr_metadata)] 5 | 6 | fn main() { 7 | let a = [1u32; 2]; 8 | let _: *const [u32] = core::ptr::from_raw_parts(&raw const a, 2); 9 | } 10 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/ptr_to_promoted.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::main 4 | fn main() 5 | { 6 | let @0: (); // return 7 | let x@1: *const u8; // local 8 | let @2: &'_ (u8); // anonymous local 9 | let @3: usize; // anonymous local 10 | let @4: *const u8; // anonymous local 11 | let @5: &'_ (u8); // anonymous local 12 | let @6: &'_ (u8); // anonymous local 13 | let @7: u8; // anonymous local 14 | 15 | storage_live(@5) 16 | storage_live(@6) 17 | storage_live(@7) 18 | @7 := const (0 : u8) 19 | @6 := &@7 20 | storage_live(x@1) 21 | storage_live(@2) 22 | @5 := move (@6) 23 | @2 := &*(@5) 24 | x@1 := &raw const *(@2) 25 | storage_dead(@2) 26 | storage_live(@3) 27 | storage_live(@4) 28 | @4 := copy (x@1) 29 | @3 := cast<*const u8, usize>(move (@4)) 30 | storage_dead(@4) 31 | storage_dead(@3) 32 | @0 := () 33 | storage_dead(x@1) 34 | @0 := () 35 | return 36 | } 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/ptr_to_promoted.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--mir_optimized 2 | fn main() { 3 | let x: *const u8 = &0; 4 | let _ = x as usize; 5 | } 6 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/quantified-trait-type-constraint.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: test_crate::Trait 8 | trait Trait<'a, Self, Self_Type> 9 | { 10 | parent_clause0 : [@TraitClause0]: Sized 11 | } 12 | 13 | // Full name: test_crate::foo 14 | fn foo() 15 | where 16 | [@TraitClause0]: Sized, 17 | [@TraitClause1]: for<'a> Trait<'a, T, &'_ (())>, 18 | { 19 | let @0: (); // return 20 | 21 | @0 := () 22 | @0 := () 23 | return 24 | } 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/quantified-trait-type-constraint.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--remove-associated-types=* 2 | trait Trait<'a> { 3 | type Type; 4 | } 5 | 6 | // This is incorrectly translated (https://github.com/AeneasVerif/charon/issues/534). 7 | fn foo() 8 | where 9 | T: for<'a> Trait<'a, Type = &'a ()>, 10 | { 11 | } 12 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/slice_increment.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::incr 4 | pub fn incr<'_0>(@1: &'_0 mut (Slice)) 5 | { 6 | let @0: (); // return 7 | let s@1: &'_ mut (Slice); // arg #1 8 | let @2: usize; // anonymous local 9 | let @3: u32; // anonymous local 10 | let @4: &'_ mut (Slice); // anonymous local 11 | let @5: &'_ mut (u32); // anonymous local 12 | let @6: &'_ (Slice); // anonymous local 13 | let @7: &'_ (u32); // anonymous local 14 | 15 | storage_live(@3) 16 | storage_live(@2) 17 | @2 := const (0 : usize) 18 | storage_live(@6) 19 | @6 := &*(s@1) 20 | storage_live(@7) 21 | @7 := @SliceIndexShared<'_, u32>(move (@6), copy (@2)) 22 | @3 := copy (*(@7)) + const (1 : u32) 23 | storage_live(@4) 24 | @4 := &mut *(s@1) 25 | storage_live(@5) 26 | @5 := @SliceIndexMut<'_, u32>(move (@4), copy (@2)) 27 | *(@5) := move (@3) 28 | storage_dead(@2) 29 | @0 := () 30 | @0 := () 31 | return 32 | } 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/slice_increment.rs: -------------------------------------------------------------------------------- 1 | pub fn incr(s: &mut [u32]) { 2 | s[0] += 1; 3 | } 4 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/slice_index.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::first 4 | pub fn first<'_0>(@1: &'_0 (Slice)) -> u32 5 | { 6 | let @0: u32; // return 7 | let s@1: &'_ (Slice); // arg #1 8 | let @2: usize; // anonymous local 9 | let @3: &'_ (Slice); // anonymous local 10 | let @4: &'_ (u32); // anonymous local 11 | 12 | storage_live(@2) 13 | @2 := const (0 : usize) 14 | storage_live(@3) 15 | @3 := &*(s@1) 16 | storage_live(@4) 17 | @4 := @SliceIndexShared<'_, u32>(move (@3), copy (@2)) 18 | @0 := copy (*(@4)) 19 | storage_dead(@2) 20 | return 21 | } 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/slice_index.rs: -------------------------------------------------------------------------------- 1 | pub fn first(s: &[u32]) -> u32 { 2 | s[0] 3 | } 4 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/slice_index_range.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--extract-opaque-bodies 2 | pub fn slice_index_range(slice: &[u8]) -> &[u8] { 3 | &slice[0..=10] 4 | } 5 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/supertrait-impl-with-assoc-type-constraint.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: core::marker::Sized 4 | #[lang_item("sized")] 5 | pub trait Sized 6 | 7 | // Full name: test_crate::HasAssoc 8 | trait HasAssoc 9 | { 10 | parent_clause0 : [@TraitClause0]: Sized 11 | type Assoc 12 | } 13 | 14 | // Full name: test_crate::SuperTrait 15 | trait SuperTrait 16 | 17 | // Full name: test_crate::Trait 18 | trait Trait 19 | { 20 | parent_clause0 : [@TraitClause0]: SuperTrait 21 | } 22 | 23 | // Full name: test_crate::{impl SuperTrait for T} 24 | impl SuperTrait for T 25 | where 26 | [@TraitClause0]: HasAssoc, 27 | [@TraitClause1]: Sized, 28 | @TraitClause0::Assoc = (), 29 | {} 30 | 31 | // Full name: test_crate::{impl Trait for T}#1 32 | impl Trait for T 33 | where 34 | [@TraitClause0]: HasAssoc, 35 | [@TraitClause1]: Sized, 36 | @TraitClause0::Assoc = (), 37 | { 38 | parent_clause0 = {impl SuperTrait for T}[@TraitClause0, @TraitClause1] 39 | } 40 | 41 | // Full name: test_crate::main 42 | fn main() 43 | { 44 | let @0: (); // return 45 | 46 | @0 := () 47 | @0 := () 48 | return 49 | } 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/supertrait-impl-with-assoc-type-constraint.rs: -------------------------------------------------------------------------------- 1 | trait HasAssoc { 2 | type Assoc; 3 | } 4 | 5 | trait SuperTrait {} 6 | trait Trait: SuperTrait {} 7 | 8 | impl SuperTrait for T where T: HasAssoc {} 9 | impl Trait for T where T: HasAssoc {} 10 | 11 | fn main() {} 12 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/vec-push.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--include=alloc::vec::* 2 | fn vec(x: &mut Vec) { 3 | x.push(42) 4 | } 5 | -------------------------------------------------------------------------------- /charon/tests/ui/simple/vec-with-capacity.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--include=alloc::vec::* 2 | fn vec() { 3 | let _: Vec = Vec::with_capacity(42); 4 | } 5 | -------------------------------------------------------------------------------- /charon/tests/ui/skip-borrowck.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--skip-borrowck 2 | fn choose<'a, T>(b: bool, x: &'a mut T, y: &'a mut T) -> &'a mut T { 3 | if b { 4 | x 5 | } else { 6 | y 7 | } 8 | } 9 | 10 | pub fn choose_test() { 11 | let mut x = 0; 12 | let mut y = 0; 13 | let z = choose(true, &mut x, &mut y); 14 | *z += 1; 15 | assert!(*z == 1); 16 | // drop(z) 17 | assert!(x == 1); 18 | assert!(y == 0); 19 | assert!(*z == 1); // z is not valid anymore 20 | } 21 | -------------------------------------------------------------------------------- /charon/tests/ui/slice-index-range.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--include core::slice::index::_ 2 | 3 | fn main() { 4 | let array = [1, 2, 3, 4, 5, 6]; 5 | let slice = &array[2..5]; 6 | assert!(slice[0] == 3); 7 | } 8 | -------------------------------------------------------------------------------- /charon/tests/ui/start_from.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--start-from=crate::module1 2 | //@ charon-args=--start-from=test_crate::module2 3 | //@ charon-args=--start-from=std::iter::once 4 | //@ charon-args=--start-from=std::clone::Clone::clone_from 5 | //@ charon-args=--start-from=std::slice::Iter::as_slice 6 | //@ charon-args=--start-from=u32::wrapping_add 7 | 8 | fn dont_translate() {} 9 | 10 | mod module1 { 11 | fn do_translate() {} 12 | } 13 | mod module2 { 14 | fn do_translate() {} 15 | } 16 | mod module3 { 17 | fn dont_translate() {} 18 | } 19 | -------------------------------------------------------------------------------- /charon/tests/ui/start_from_errors.out: -------------------------------------------------------------------------------- 1 | error: path start_from_errors does not correspond to any item 2 | 3 | error: path module2 does not correspond to any item 4 | 5 | error: path std::iter:once does not correspond to any item 6 | 7 | error: Cannot register item `core::ops::deref::Deref::Target` with kind `AssocTy` 8 | --> /rustc/library/core/src/ops/deref.rs:143:5 9 | 10 | ERROR Charon failed to translate this code (4 errors) 11 | -------------------------------------------------------------------------------- /charon/tests/ui/start_from_errors.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | //@ charon-args=--start-from=start_from_errors::module1 3 | //@ charon-args=--start-from=module2 4 | //@ charon-args=--start-from=std::iter:once 5 | //@ charon-args=--start-from=std::ops::Deref::Target 6 | 7 | mod module1 {} 8 | mod module2 {} 9 | -------------------------------------------------------------------------------- /charon/tests/ui/statics.rs: -------------------------------------------------------------------------------- 1 | #![feature(raw_ref_op)] 2 | 3 | fn constant() { 4 | const CONST: usize = 0; 5 | 6 | let _val = CONST; 7 | let _ref = &CONST; 8 | let _ref_mut = &mut CONST; 9 | } 10 | 11 | fn shared_static() { 12 | static SHARED_STATIC: usize = 0; 13 | 14 | let _val = SHARED_STATIC; 15 | let _ref = &SHARED_STATIC; 16 | let _ptr = &raw const SHARED_STATIC; 17 | } 18 | 19 | fn mut_static() { 20 | static mut MUT_STATIC: usize = 0; 21 | 22 | unsafe { 23 | let _val = MUT_STATIC; 24 | let _ref = &MUT_STATIC; 25 | let _ref_mut = &mut MUT_STATIC; 26 | let _ptr = &raw const MUT_STATIC; 27 | let _ptr_mut = &raw mut MUT_STATIC; 28 | } 29 | } 30 | 31 | fn non_copy_static() { 32 | struct Foo; 33 | impl Foo { 34 | fn method(&self) {} 35 | } 36 | 37 | static FOO: Foo = Foo; 38 | FOO.method() 39 | } 40 | -------------------------------------------------------------------------------- /charon/tests/ui/stealing.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | fn test_crate::SLICE() -> Array<(), 4 : usize> 4 | { 5 | let @0: Array<(), 4 : usize>; // return 6 | let @1: (); // anonymous local 7 | 8 | storage_live(@1) 9 | @1 := () 10 | @0 := @ArrayRepeat<'_, (), 4 : usize>(move (@1)) 11 | storage_dead(@1) 12 | return 13 | } 14 | 15 | static test_crate::SLICE: Array<(), 4 : usize> = test_crate::SLICE() 16 | 17 | // Full name: test_crate::four 18 | fn four() -> usize 19 | { 20 | let @0: usize; // return 21 | 22 | @0 := const (2 : usize) + const (2 : usize) 23 | return 24 | } 25 | 26 | fn test_crate::BAR() -> Array<(), 42 : usize> 27 | { 28 | let @0: Array<(), 42 : usize>; // return 29 | let @1: (); // anonymous local 30 | 31 | storage_live(@1) 32 | @1 := () 33 | @0 := @ArrayRepeat<'_, (), 42 : usize>(move (@1)) 34 | storage_dead(@1) 35 | return 36 | } 37 | 38 | const test_crate::BAR: Array<(), 42 : usize> = test_crate::BAR() 39 | 40 | fn test_crate::FOO() -> usize 41 | { 42 | let @0: usize; // return 43 | 44 | @0 := const (42 : usize) 45 | return 46 | } 47 | 48 | const test_crate::FOO: usize = test_crate::FOO() 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /charon/tests/ui/stealing.rs: -------------------------------------------------------------------------------- 1 | // Translating this needs the evaluatable MIR of `fn four()`, which steals its `mir_built` body. 2 | // There's no simple ordering of the translation of items that can avoid all stealing. 3 | static SLICE: [(); four()] = [(); 4]; 4 | 5 | const fn four() -> usize { 6 | 2 + 2 7 | } 8 | 9 | // The order counts, we want to translate `BAR` first to steal `FOO`. 10 | const BAR: [(); FOO] = [(); FOO]; 11 | const FOO: usize = 42; 12 | -------------------------------------------------------------------------------- /charon/tests/ui/string-literal.rs: -------------------------------------------------------------------------------- 1 | static FOO: &str = "hello"; 2 | static BAR: &[u8] = b"hello"; 3 | 4 | fn main() { 5 | let _s = "Hello".to_string(); 6 | } 7 | -------------------------------------------------------------------------------- /charon/tests/ui/traits_special.rs: -------------------------------------------------------------------------------- 1 | // The example below (in particular the impl block) is peculiar with regards 2 | // to the treatment of regions. In particular, when we translate the implementation 3 | // of `from` to LLBC, we get something which looks like this: 4 | // ``` 5 | // 6 | // fn crate::{bool}::from<@R0, @R1>(@1: &@R1 (bool)) -> 7 | // core::result::Result::Error> { 8 | // // ^^^ 9 | // // HERE 10 | // ... // omitted 11 | // } 12 | // ``` 13 | pub trait From { 14 | type Error; 15 | fn from(v: T) -> Result 16 | where 17 | Self: std::marker::Sized; 18 | } 19 | 20 | impl From<&bool> for bool { 21 | type Error = (); 22 | 23 | fn from(v: &bool) -> Result { 24 | Ok(*v) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /charon/tests/ui/type_alias.rs: -------------------------------------------------------------------------------- 1 | use std::borrow::Cow; 2 | // type Foo = usize; 3 | // type Generic<'a, T> = &'a T; 4 | // type Generic2<'a, T: Clone> = Cow<'a, [T]>; 5 | // type GenericWithoutBound<'a, T> = Cow<'a, [T]>; 6 | struct Generic2<'a, T: Clone>(Cow<'a, [T]>); 7 | -------------------------------------------------------------------------------- /charon/tests/ui/type_inference_is_order_dependent.rs: -------------------------------------------------------------------------------- 1 | //! See https://github.com/rust-lang/rust/issues/41756. 2 | use std::fmt::Debug; 3 | 4 | trait Left {} 5 | trait Right {} 6 | 7 | trait Join { 8 | fn test(); 9 | } 10 | 11 | // If we swap the two clauses, a different type is selected in `try_it`. 12 | impl Join for T 13 | where 14 | T: Left, 15 | T: Right, 16 | U: Default + Debug, 17 | { 18 | fn test() { 19 | println!("{:?}", U::default()) 20 | } 21 | } 22 | 23 | impl Left for T {} 24 | impl Right for T {} 25 | 26 | fn try_it() 27 | where 28 | T: Left, 29 | T: Right<()>, 30 | { 31 | >::test() 32 | } 33 | -------------------------------------------------------------------------------- /charon/tests/ui/typenum.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::UInt 4 | pub struct UInt { 5 | U, 6 | B, 7 | } 8 | 9 | // Full name: test_crate::UTerm 10 | pub struct UTerm {} 11 | 12 | // Full name: test_crate::B0 13 | pub struct B0 {} 14 | 15 | // Full name: test_crate::LongType 16 | pub type LongType = UInt, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0> 17 | 18 | // Full name: test_crate::foo 19 | pub fn foo() 20 | { 21 | let @0: (); // return 22 | 23 | @0 := () 24 | @0 := () 25 | return 26 | } 27 | 28 | // Full name: test_crate::main 29 | pub fn main() 30 | { 31 | let @0: (); // return 32 | let @1: (); // anonymous local 33 | 34 | storage_live(@1) 35 | @1 := foo, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>>() 36 | storage_dead(@1) 37 | @0 := () 38 | @0 := () 39 | return 40 | } 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /charon/tests/ui/typenum.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--hide-marker-traits 2 | pub struct UInt(U, B); 3 | pub struct UTerm; 4 | pub struct B0; 5 | 6 | pub type LongType = 7 | UInt, B0>, B0>, B0>, B0>, B0>, B0>, B0>, B0>; 8 | 9 | pub fn foo() {} 10 | pub fn main() { 11 | foo::(); 12 | } 13 | -------------------------------------------------------------------------------- /charon/tests/ui/ullbc-control-flow.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--ullbc --print-ullbc --no-serialize 2 | //! Test the pre-reconstruction output so we don't accidentally regress passes in ways that are 3 | //! invisible post-reconstruction. 4 | pub fn nested_loops_enum(step_out: usize, step_in: usize) -> usize { 5 | let mut s = 0; 6 | 7 | for _ in 0..128 { 8 | s += 1; 9 | } 10 | 11 | for _ in 0..(step_out) { 12 | // Test comment 13 | for _ in 0..(step_in) { 14 | s += 1; 15 | assert!(s >= 1); 16 | } 17 | } 18 | 19 | s 20 | } 21 | -------------------------------------------------------------------------------- /charon/tests/ui/unions.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::Foo 4 | union Foo { 5 | one: u64, 6 | two: Array, 7 | } 8 | 9 | // Full name: test_crate::use_union 10 | fn use_union() 11 | { 12 | let @0: (); // return 13 | let one@1: Foo; // local 14 | let @2: (); // anonymous local 15 | let _two@3: Array; // local 16 | 17 | storage_live(one@1) 18 | one@1 := Foo { one: const (42 : u64) } 19 | storage_live(@2) 20 | (one@1).one := const (43 : u64) 21 | storage_dead(@2) 22 | storage_live(_two@3) 23 | _two@3 := copy ((one@1).two) 24 | @0 := () 25 | storage_dead(_two@3) 26 | storage_dead(one@1) 27 | @0 := () 28 | return 29 | } 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /charon/tests/ui/unions.rs: -------------------------------------------------------------------------------- 1 | union Foo { 2 | one: u64, 3 | two: [u32; 2], 4 | } 5 | 6 | fn use_union() { 7 | let mut one = Foo { one: 42 }; 8 | unsafe { 9 | one.one = 43; 10 | } 11 | let _two = unsafe { one.two }; 12 | } 13 | -------------------------------------------------------------------------------- /charon/tests/ui/unsafe-impl-send.out: -------------------------------------------------------------------------------- 1 | # Final LLBC before serialization: 2 | 3 | // Full name: test_crate::Foo 4 | struct Foo { 5 | *const (), 6 | } 7 | 8 | // Full name: core::marker::Send 9 | #[lang_item("Send")] 10 | pub trait Send 11 | 12 | // Full name: test_crate::{impl Send for Foo} 13 | impl Send for Foo {} 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /charon/tests/ui/unsafe-impl-send.rs: -------------------------------------------------------------------------------- 1 | //! Regression test for something that caused a panic in charon. 2 | 3 | struct Foo(*const ()); 4 | 5 | unsafe impl Send for Foo {} 6 | -------------------------------------------------------------------------------- /charon/tests/ui/unsafe.rs: -------------------------------------------------------------------------------- 1 | //@ charon-args=--exclude=core::ptr::metadata::Thin 2 | 3 | //! The 5 "unsafe superpowers" (https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#unsafe-superpowers). 4 | #![feature(core_intrinsics)] 5 | #![allow(internal_features)] 6 | 7 | fn call_unsafe_fn() { 8 | let x: *const _ = std::ptr::null::(); 9 | let _ = unsafe { x.read() }; 10 | } 11 | 12 | fn deref_raw_ptr() { 13 | let x: *const _ = std::ptr::null::(); 14 | let _ = unsafe { *x }; 15 | } 16 | 17 | unsafe trait Trait {} 18 | 19 | unsafe impl Trait for () {} 20 | 21 | static mut COUNTER: usize = 0; 22 | 23 | fn access_mutable_static() { 24 | unsafe { 25 | COUNTER += 1; 26 | } 27 | } 28 | 29 | union Foo { 30 | one: u64, 31 | two: [u32; 2], 32 | } 33 | 34 | fn access_union_field() { 35 | let one = Foo { one: 42 }; 36 | let _two = unsafe { one.two }; 37 | } 38 | 39 | fn assume() { 40 | unsafe { std::intrinsics::assume(true) } 41 | } 42 | -------------------------------------------------------------------------------- /charon/tests/ui/unsize.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Display; 2 | use std::rc::Rc; 3 | 4 | fn foo() { 5 | let array: [_; 2] = [0, 0]; 6 | let _: &[_] = &array; 7 | let _: Box<[_]> = Box::new(array); 8 | let _: Rc<[_]> = Rc::new(array); 9 | 10 | let string = String::new(); 11 | let _: &dyn Display = &string; 12 | let _: Box = Box::new(string.clone()); 13 | let _: Rc = Rc::new(string.clone()); 14 | } 15 | -------------------------------------------------------------------------------- /charon/tests/ui/unsupported/advanced-const-generics.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | #![feature(generic_const_exprs)] 3 | #![feature(adt_const_params)] 4 | #![allow(incomplete_features)] 5 | #![allow(dead_code)] 6 | use std::marker::ConstParamTy; 7 | 8 | #[derive(ConstParamTy, PartialEq, Eq, Debug)] 9 | enum Foo { 10 | A, 11 | B, 12 | } 13 | 14 | fn foo() -> Foo { 15 | X 16 | } 17 | 18 | fn bar() 19 | where 20 | [(); N + 1]:, 21 | { 22 | let _: [(); N + 1] = [(); N + 1]; 23 | } 24 | -------------------------------------------------------------------------------- /charon/tests/ui/unsupported/issue-79-bound-regions.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let slice: &[i32] = &[0]; 3 | let _ = slice.iter().next(); 4 | } 5 | -------------------------------------------------------------------------------- /charon/tests/ui/unsupported/unbound-lifetime.out: -------------------------------------------------------------------------------- 1 | error[E0261]: use of undeclared lifetime name `'a` 2 | --> tests/ui/unsupported/unbound-lifetime.rs:5:13 3 | | 4 | 5 | fn get(_x: &'a u32) {} 5 | | - ^^ undeclared lifetime 6 | | | 7 | | help: consider introducing lifetime `'a` here: `<'a>` 8 | 9 | error: Unexpected region kind: Region { kind: ReError(ErrorGuaranteed { todo: "ErrorGuaranteed(())" }) } 10 | --> tests/ui/unsupported/unbound-lifetime.rs:5:1 11 | | 12 | 5 | fn get(_x: &'a u32) {} 13 | | ^^^^^^^^^^^^^^^^^^^^^^ 14 | 15 | error: Item `test_crate::get` caused errors; ignoring. 16 | --> tests/ui/unsupported/unbound-lifetime.rs:5:1 17 | | 18 | 5 | fn get(_x: &'a u32) {} 19 | | ^^^^^^^^^^^^^^^^^^^ 20 | 21 | error: aborting due to 1 previous error 22 | 23 | For more information about this error, try `rustc --explain E0261`. 24 | ERROR Code failed to compile 25 | -------------------------------------------------------------------------------- /charon/tests/ui/unsupported/unbound-lifetime.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | // See https://github.com/AeneasVerif/charon/issues/306 3 | 4 | // This is incorrect code but the error is weird. 5 | fn get(_x: &'a u32) {} 6 | -------------------------------------------------------------------------------- /charon/tests/ui/unsupported/well-formedness-bound.out: -------------------------------------------------------------------------------- 1 | error: Well-formedness clauses are unsupported 2 | --> tests/ui/unsupported/well-formedness-bound.rs:4:5 3 | | 4 | 4 | &'a ():, 5 | | ^^^^^^ 6 | 7 | error: Item `test_crate::get` caused errors; ignoring. 8 | --> tests/ui/unsupported/well-formedness-bound.rs:2:1 9 | | 10 | 2 | / pub fn get<'a>(x: &'a u32) -> Option<&'a u32> 11 | 3 | | where 12 | 4 | | &'a ():, 13 | | |____________^ 14 | 15 | ERROR Charon failed to translate this code (2 errors) 16 | -------------------------------------------------------------------------------- /charon/tests/ui/unsupported/well-formedness-bound.rs: -------------------------------------------------------------------------------- 1 | //@ known-failure 2 | pub fn get<'a>(x: &'a u32) -> Option<&'a u32> 3 | where 4 | &'a ():, 5 | { 6 | Some(x) 7 | } 8 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | # This file provides backward compatibility to nix < 2.4 clients 2 | { system ? builtins.currentSystem }: 3 | let 4 | lock = builtins.fromJSON (builtins.readFile ./flake.lock); 5 | 6 | inherit (lock.nodes.flake-compat.locked) owner repo rev narHash; 7 | 8 | flake-compat = fetchTarball { 9 | url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; 10 | sha256 = narHash; 11 | }; 12 | 13 | flake = import flake-compat { inherit system; src = ./.; }; 14 | in 15 | flake.defaultNix 16 | 17 | -------------------------------------------------------------------------------- /doc-ml.html: -------------------------------------------------------------------------------- 1 | ./_build/default/_doc/_html/charon/index.html -------------------------------------------------------------------------------- /doc-rust.html: -------------------------------------------------------------------------------- 1 | ./charon/target/doc/charon/index.html -------------------------------------------------------------------------------- /docs/limitations.md: -------------------------------------------------------------------------------- 1 | # Current limitations of Charon 2 | 3 | Charon is alpha software. In particular, it is currently poorly documented, doesn't support all the 4 | Rust features we'd like, and has several breaking changes planned in the near future. 5 | 6 | ## Planned breaking changes 7 | 8 | - https://github.com/AeneasVerif/charon/issues/287 9 | - https://github.com/AeneasVerif/charon/issues/194 10 | - https://github.com/AeneasVerif/charon/issues/582 11 | - Some potential rework of how we handle builtins like `SliceIndexMut` 12 | - Name matcher behavior likely to change in subtle ways 13 | (https://github.com/AeneasVerif/charon/issues/319). 14 | 15 | ## Known unsoundnesses 16 | 17 | - https://github.com/AeneasVerif/charon/issues/583 18 | - https://github.com/AeneasVerif/charon/issues/584 19 | 20 | ## Unsupported Rust features 21 | 22 | Tracked here: https://github.com/AeneasVerif/charon/issues/142 23 | 24 | ## Missing information in the translated output 25 | 26 | - Bodies of functions in foreign crates often cause errors (https://github.com/AeneasVerif/charon/issues/543); 27 | - Bodies of std functions (https://github.com/AeneasVerif/charon/issues/545); 28 | - Drops (https://github.com/AeneasVerif/charon/issues/152); 29 | - Layout information (https://github.com/AeneasVerif/charon/issues/581); 30 | - Lifetime information inside function bodies (not planned). 31 | -------------------------------------------------------------------------------- /docs/what_charon_does_for_you.md: -------------------------------------------------------------------------------- 1 | # What Charon Does For You 2 | 3 | The purpose of Charon is to centralize the efforts of extracting information from rustc internals 4 | and turning them into a uniform and usable shape. Here are some things that Charon does once so you 5 | don't have to do it yourself: 6 | 7 | TODO: explain each item 8 | 9 | - Trait resolution (explicitly track how each trait bound was proven to hold); 10 | - Reconstruct expressions from all the various constant representations; 11 | - Hide the distinction between early- and late-bound lifetime variables; 12 | - Make non-overriden default methods in impl blocks appear as normal methods; 13 | - Handle trait method implementations that have a more general signature than as declared in the trait (WIP: https://github.com/AeneasVerif/charon/issues/513); 14 | - Represent closures as normal structs that implement the `Fn*` traits (WIP: https://github.com/AeneasVerif/charon/issues/194); 15 | - Many useful post-processing transformations to make the output more usable; see [the dedicated file](./transformations.md). 16 | -------------------------------------------------------------------------------- /dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 3.7) 2 | 3 | (using menhir 2.1) 4 | 5 | (map_workspace_root false) 6 | 7 | (name charon) 8 | 9 | (version 0.1) 10 | 11 | (generate_opam_files true) 12 | 13 | (source 14 | (uri git+https://github.com/AeneasVerif/charon.git)) 15 | 16 | (homepage "https://github.com/AeneasVerif/charon") 17 | 18 | (bug_reports "https://github.com/AeneasVerif/charon/issues") 19 | 20 | (authors "Son Ho" "Jonathan Protzenko" "Aymeric Fromherz" "Sidney Congard") 21 | 22 | (maintainers 23 | "Son Ho" 24 | "Jonathan Protzenko" 25 | "Aymeric Fromherz" 26 | "Sidney Congard") 27 | 28 | (license Apache-2.0) 29 | 30 | (package 31 | (name charon) 32 | (synopsis 33 | "Manipulation of Low-level Borrow Calculus, a MIR-like representation for Rust Code") 34 | (description 35 | "\n This library allows for manipulation of LLBC, the language output by\n Charon. Charon acts as an interface between the rustc compiler and program\n verification projects. Its purpose is to process Rust .rs files and convert\n them into files easy to handle by program verifiers.") 36 | (depends 37 | easy_logging 38 | ppx_deriving 39 | unionFind 40 | visitors 41 | yojson 42 | zarith 43 | name_matcher_parser 44 | (ocamlformat :with-test))) 45 | 46 | (package 47 | (name name_matcher_parser) 48 | (synopsis "Parser to define name matchers") 49 | (description "") 50 | (depends 51 | (menhir :build) 52 | menhirLib 53 | ppx_deriving 54 | visitors 55 | zarith)) 56 | -------------------------------------------------------------------------------- /name_matcher_parser.opam: -------------------------------------------------------------------------------- 1 | # This file is generated by dune, edit dune-project instead 2 | opam-version: "2.0" 3 | version: "0.1" 4 | synopsis: "Parser to define name matchers" 5 | description: "" 6 | maintainer: [ 7 | "Son Ho" "Jonathan Protzenko" "Aymeric Fromherz" "Sidney Congard" 8 | ] 9 | authors: ["Son Ho" "Jonathan Protzenko" "Aymeric Fromherz" "Sidney Congard"] 10 | license: "Apache-2.0" 11 | homepage: "https://github.com/AeneasVerif/charon" 12 | bug-reports: "https://github.com/AeneasVerif/charon/issues" 13 | depends: [ 14 | "dune" {>= "3.7"} 15 | "menhir" {build} 16 | "menhirLib" 17 | "ppx_deriving" 18 | "visitors" 19 | "zarith" 20 | "odoc" {with-doc} 21 | ] 22 | build: [ 23 | ["dune" "subst"] {dev} 24 | [ 25 | "dune" 26 | "build" 27 | "-p" 28 | name 29 | "-j" 30 | jobs 31 | "@install" 32 | "@runtest" {with-test} 33 | "@doc" {with-doc} 34 | ] 35 | ] 36 | dev-repo: "git+https://github.com/AeneasVerif/charon.git" 37 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | charon/rust-toolchain -------------------------------------------------------------------------------- /scripts/ci-check-hax-commit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Check that we're using a hax commit that's merged into hax main. 3 | 4 | HAX_COMMIT="$(toml2json charon/Cargo.lock | jq -r \ 5 | '.package[] 6 | | select(.name == "hax-frontend-exporter").source 7 | | capture("^git\\+https://github.com/cryspen/hax\\?branch=(?[a-z]+)#(?[a-f0-9]+)$") 8 | | select(.branch == "main") 9 | | .commit 10 | ')" 11 | echo "This PR uses hax commit $HAX_COMMIT" 12 | 13 | git clone https://github.com/cryspen/hax 14 | cd hax 15 | HAX_MAIN="$(git rev-parse HEAD)" 16 | 17 | if ! git merge-base --is-ancestor "$HAX_COMMIT" "$HAX_MAIN"; then 18 | echo "Error: commit $HAX_COMMIT is not merged into hax's main branch." 19 | exit 1 20 | fi 21 | -------------------------------------------------------------------------------- /scripts/ci-check-version-number.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Compares this version with `main`, and checks that if `charon-ml` changed, 3 | # then so did the version in `Cargo.toml`. 4 | if git diff origin/main --quiet -- charon-ml/src/generated/Generated_*OfJson.ml; then 5 | echo '`charon-ml` was not changed in this PR; all good.' 6 | else 7 | echo -n '`charon-ml` was changed in this PR ' 8 | if git diff origin/main --quiet -- charon-ml/src/CharonVersion.ml; then 9 | echo 'but the charon version was not updated properly!' 10 | exit 1 11 | else 12 | echo 'and the charon version was updated properly.' 13 | fi 14 | fi 15 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | # This file provides backward compatibility to nix < 2.4 clients 2 | { system ? builtins.currentSystem }: 3 | let 4 | lock = builtins.fromJSON (builtins.readFile ./flake.lock); 5 | 6 | inherit (lock.nodes.flake-compat.locked) owner repo rev narHash; 7 | 8 | flake-compat = fetchTarball { 9 | url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; 10 | sha256 = narHash; 11 | }; 12 | 13 | flake = import flake-compat { inherit system; src = ./.; }; 14 | in 15 | flake.shellNix 16 | -------------------------------------------------------------------------------- /static/Charon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AeneasVerif/charon/4c76ec0ce2e26accc19f32fe246eab59a1d208d1/static/Charon.jpg --------------------------------------------------------------------------------