GithubHelp home page GithubHelp logo

prove-rs / z3.rs Goto Github PK

View Code? Open in Web Editor NEW
333.0 9.0 105.0 656 KB

Rust bindings for the Z3 solver.

Rust 99.93% Shell 0.06% C 0.01%
logic-programming smt smt-solver rust-bindings rust ffi-bindings

z3.rs's Introduction

z3 and z3-sys

Rust

This repository contains high-level and low-level Rust bindings for the Z3 solver.

z3

The z3 crate provides high-level bindings to the Z3 solver. It is built on top of, and wraps, the z3-sys crate. This is the crate you'll want to use 99% of the time.

z3-sys

The z3-sys crate provides the raw, unsafe, low-level C API that Z3 exposes.

When should I use z3-sys instead of z3?

The first scenario where it makes sense to use z3-sys directly is when some Z3 feature isn't wrapped into high-level bindings in the z3 crate yet. In this case, it is worth filing an issue and discussing its implementation in the z3 crate, but you can get at the raw, underlying features via the z3-sys crate in the meantime.

The only other time to use z3-sys directly would be if you are writing your own custom high-level API for Z3, instead of using the z3 crate.

Release Process

  1. Make a version bump commit
    1. Bump version for the relevant crate in Cargo.toml
    2. Update version in examples/READMEs
  2. Create a git tag for the commit
    1. i.e. git tag z3-v0.10.0
  3. Push the changes
    1. git push
    2. git push --tags
  4. Publish on crates.io
    1. cargo publish

z3.rs's People

Contributors

andesvl avatar azuremarker avatar badboy avatar bumblepie avatar cdisselkoen avatar davidthien avatar enjhnsn2 avatar fitzgen avatar fpoli avatar freax13 avatar graydon avatar greenbeard avatar hengchu avatar hkalbasi avatar jagill avatar jakobr avatar leaferx avatar lucab avatar lzybkr avatar pat-lafon avatar philipp15b avatar rlkelly avatar sameer avatar seespring avatar skius avatar taegyunkim avatar toolchainz avatar trolldemorted avatar verpeteren avatar waywardmonkeys avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

z3.rs's Issues

Static-link-z3 build should be parallelized

The static link build is pretty slow.

On Windows, the simplest thing is to add

        cfg.cxxflag("-MP");

This is a huge win on my 32 core build machine - going from I don't even know how long (30 minutes?) to around 7 minutes.

An incremental improvement is to also build in parallel with msbuild:

    cfg.build_arg("-m");

This shaved another 2 minutes off the build, maybe it could be improved even better as I'm sure there was some contention over cores, but maybe it's good enough.

I tried setting NUM_JOBS to get cmake to add -m automatically but for whatever reason it didn't seem to work for me.

Would a Windows only PR be welcome?

New crates.io release

Hi! seeing as the crate has undergone some sizable refactoring lately, would it be possible to release a new version on crates.io?

Overloading Rust operators for some of the `Ast` functions

How would you feel about overloading Rust operators, as syntactic sugar for some of the functions in Ast? We can't do all of them, but at least some of the most useful ones like add, sub, mul, div, mod, minus, and, or, xor, not (I may have missed some).

I am happy to work on a PR if this is okay.

Aren't Config, Context, Solver and friends Send-able?

As @hengchu mentioned here, it is not obvious why these types should not implement Send. Just because those types aren't safe for concurrent usage, they are not necessarily unsafe to be used by different threads sequentially.

Them being !Send makes it impossible to use them in worker queue scenarios, which is a serious restriction of the usability.

Do you have an idea whom one could ask or which documentation one could read about that?

Distinguish "unknown" from "unsat"

Currently, using the Solver::check method, there is no way to distinguish an "unknown" answer from an "unsat".

One (non backward compatible) solution would be to:

  1. add a LiftedBool enum, with variants True, False, and Undefined
  2. rename Solver::check to Solver::is_sat
  3. add a Solver::check method that returns a LiftedBool

Rust newbie: fatal error at installation: 'z3.h' file not found

After I've added a z3 dependency to Cargo.toml, cargo run attempts to install the z3 crate, but fails when buidling z3-sys, with the error above. Obviously, it cannot locate the Z3 solver.

How can that be fixed ? Am I supposed to have the Z3 solver's source code in my rust project repository, including z3.h ? Or add a link to a shared library ?

How can I have recursive datatypes with arrays?

This is because I need to make a recursive datatype with the array, like this:

(declare-datatypes () ((V (i Int) (v (Array Int V))))))

I think a parameterized sort would help, like this

(define-sort A (T) (Array T T))

How can I do it or if it is not supported can you give clues to implement this by C API so that I can make pull request?

z3-sys fails to build on Windows?

Hey there! I'm trying to play around with this crate on Windows, and z3-sys is failing to build when I try to do a static build. I'm super new to this and I don't really understand the build errors. Does anyone have any idea what I can do to get this working?

Error output
error: failed to run custom build command for `z3-sys v0.6.2`

Caused by:
process didn't exit successfully: C:\Users\zkat\src\orogene\target\release\build\z3-sys-6bf7b8d11a33477d\build-script-build (exit code: 101)
--- stdout
running: "cmake" "C:\Users\zkat\.cargo\registry\src\github.com-1ecc6299db9ec823\z3-sys-0.6.2\z3" "-G" "Visual Studio 16 2019" "-Thost=x64" "-Ax64" "-DZ3_BUILD_LIBZ3_SHARED=false" "-DZ3_BUILD_EXECUTABLE=false" "-DZ3_BUILD_TEST_EXECUTABLES=false" "-DCMAKE_INSTALL_PREFIX=C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out" "-DCMAKE_C_FLAGS= -nologo -MT -Brepro" "-DCMAKE_C_FLAGS_RELEASE= -nologo -MT -Brepro" "-DCMAKE_CXX_FLAGS= -DWIN32 -D_WINDOWS -nologo -MT -Brepro" "-DCMAKE_CXX_FLAGS_RELEASE= -DWIN32 -D_WINDOWS -nologo -MT -Brepro" "-DCMAKE_ASM_FLAGS= -nologo -MT -Brepro" "-DCMAKE_ASM_FLAGS_RELEASE= -nologo -MT -Brepro" "-DCMAKE_BUILD_TYPE=Release"
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.19041.
-- The CXX compiler identification is MSVC 19.25.28614.0
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Tools/MSVC/14.25.28610/bin/Hostx64/x64/cl.exe - works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Z3 version 4.8.8.0
-- Failed to find git directory.
-- CMake generator: Visual Studio 16 2019
-- Available configurations: Debug;Release;MinSizeRel;RelWithDebInfo
-- Found PythonInterp: C:/Program Files/WindowsApps/PythonSoftwareFoundation.Python.3.8_3.8.752.0_x64__qbz5n2kfra8p0/python3.8.exe
-- PYTHON_EXECUTABLE: C:/Program Files/WindowsApps/PythonSoftwareFoundation.Python.3.8_3.8.752.0_x64__qbz5n2kfra8p0/python3.8.exe
-- Detected target architecture: x86_64
-- Platform: Windows
-- Not using libgmp
-- Not using Z3_API_LOG_SYNC
-- Thread-safe build
-- Performing Test HAS_SSE2
-- Performing Test HAS_SSE2 - Failed
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - not found
-- Found Threads: TRUE
-- Performing Test HAS__W3
-- Performing Test HAS__W3 - Success
-- C++ compiler supports /W3
-- Treating only serious compiler warnings as errors
-- LTO disabled
-- Performing Test HAS_MSVC_NO_OMIT_FRAME_POINTER
-- Performing Test HAS_MSVC_NO_OMIT_FRAME_POINTER - Success
-- Performing Test HAS__Gd
-- Performing Test HAS__Gd - Success
-- C++ compiler supports /Gd
-- Performing Test HAS__EHsc
-- Performing Test HAS__EHsc - Success
-- C++ compiler supports /EHsc
-- CMAKE_CXX_FLAGS: " -DWIN32 -D_WINDOWS -nologo -MT -Brepro"
-- CMAKE_EXE_LINKER_FLAGS: "/machine:x64 /STACK:8388608 /RELEASE"
-- CMAKE_STATIC_LINKER_FLAGS: "/machine:x64"
-- CMAKE_SHARED_LINKER_FLAGS: "/machine:x64 /SUBSYSTEM:WINDOWS /RELEASE"
-- CMAKE_CXX_FLAGS_DEBUG: "/MDd /Zi /Ob0 /Od /RTC1"
-- CMAKE_EXE_LINKER_FLAGS_DEBUG: "/debug /INCREMENTAL:NO /OPT:REF /OPT:ICF /TLBID:1 /NXCOMPAT"
-- CMAKE_SHARED_LINKER_FLAGS_DEBUG: "/debug /INCREMENTAL:NO /OPT:REF /OPT:ICF /TLBID:1"
-- CMAKE_STATIC_LINKER_FLAGS_DEBUG: " /INCREMENTAL:NO"
-- CMAKE_CXX_FLAGS_RELEASE: " -DWIN32 -D_WINDOWS -nologo -MT -Brepro"
-- CMAKE_EXE_LINKER_FLAGS_RELEASE: "/INCREMENTAL:NO"
-- CMAKE_SHARED_LINKER_FLAGS_RELEASE: "/INCREMENTAL:NO"
-- CMAKE_STATIC_LINKER_FLAGS_RELEASE: " /INCREMENTAL:NO"
-- CMAKE_CXX_FLAGS_RELWITHDEBINFO: "/MD /Zi /O2 /Ob1 /DNDEBUG"
-- CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO: "/debug /INCREMENTAL:NO "
-- CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO: "/debug /INCREMENTAL:NO "
-- CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO: " /INCREMENTAL:NO"
-- CMAKE_CXX_FLAGS_MINSIZEREL: "/MD /O1 /Ob1 /DNDEBUG"
-- CMAKE_EXE_LINKER_FLAGS_MINSIZEREL: "/INCREMENTAL:NO /OPT:REF /OPT:ICF /TLBID:1 /NXCOMPAT"
-- CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL: "/INCREMENTAL:NO /OPT:REF /OPT:ICF /TLBID:1"
-- CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL: " /INCREMENTAL:NO"
-- Z3_COMPONENT_CXX_DEFINES: $<$CONFIG:Debug:Z3DEBUG>;$<$CONFIG:Release:_EXTERNAL_RELEASE>;$<$CONFIG:RelWithDebInfo:_EXTERNAL_RELEASE>;-D_WINDOWS;-D_MP_INTERNAL;$<$CONFIG:Debug:_TRACE>;UNICODE;_UNICODE
-- Z3_COMPONENT_CXX_FLAGS: /W3;$<$CONFIG:Debug:/Oy->;$<$CONFIG:MinSizeRel:/Oy->;/Gd;/EHsc
-- Z3_DEPENDENT_LIBS:
-- Z3_COMPONENT_EXTRA_INCLUDE_DIRS: C:/Users/zkat/src/orogene/target/release/build/z3-sys-efa3561d0d5a5b66/out/build/src;C:/Users/zkat/.cargo/registry/src/github.com-1ecc6299db9ec823/z3-sys-0.6.2/z3/src
-- Z3_DEPENDENT_EXTRA_CXX_LINK_FLAGS:
-- CMAKE_INSTALL_LIBDIR: "lib"
-- CMAKE_INSTALL_BINDIR: "bin"
-- CMAKE_INSTALL_INCLUDEDIR: "include"
-- CMAKE_INSTALL_PKGCONFIGDIR: "lib/pkgconfig"
-- CMAKE_INSTALL_Z3_CMAKE_PACKAGE_DIR: "lib/cmake/z3"
-- Adding component util
-- Adding component polynomial
-- Adding rule to generate "algebraic_params.hpp"
-- Adding component dd
-- Adding component hilbert
-- Adding component simplex
-- Adding component automata
-- Adding component interval
-- Adding component realclosure
-- Adding rule to generate "rcf_params.hpp"
-- Adding component subpaving
-- Adding component ast
-- Adding rule to generate "pp_params.hpp"
-- Adding component rewriter
-- Adding rule to generate "arith_rewriter_params.hpp"
-- Adding rule to generate "array_rewriter_params.hpp"
-- Adding rule to generate "bool_rewriter_params.hpp"
-- Adding rule to generate "bv_rewriter_params.hpp"
-- Adding rule to generate "fpa_rewriter_params.hpp"
-- Adding rule to generate "poly_rewriter_params.hpp"
-- Adding rule to generate "rewriter_params.hpp"
-- Adding rule to generate "seq_rewriter_params.hpp"
-- Adding component normal_forms
-- Adding rule to generate "nnf_params.hpp"
-- Adding component model
-- Adding rule to generate "model_evaluator_params.hpp"
-- Adding rule to generate "model_params.hpp"
-- Adding component tactic
-- Adding rule to generate "tactic_params.hpp"
-- Adding component substitution
-- Adding component parser_util
-- Adding rule to generate "parser_params.hpp"
-- Adding component grobner
-- Adding component sat
-- Adding rule to generate "sat_asymm_branch_params.hpp"
-- Adding rule to generate "sat_params.hpp"
-- Adding rule to generate "sat_scc_params.hpp"
-- Adding rule to generate "sat_simplifier_params.hpp"
-- Adding component nlsat
-- Adding rule to generate "nlsat_params.hpp"
-- Adding component lp
-- Adding component core_tactics
-- Adding component subpaving_tactic
-- Adding component aig_tactic
-- Adding component solver
-- Adding rule to generate "combined_solver_params.hpp"
-- Adding rule to generate "parallel_params.hpp"
-- Adding rule to generate "solver_params.hpp"
-- Adding component sat_tactic
-- Adding component arith_tactics
-- Adding component nlsat_tactic
-- Adding component ackermannization
-- Adding rule to generate "ackermannization_params.hpp"
-- Adding rule to generate "ackermannize_bv_tactic_params.hpp"
-- Adding component cmd_context
-- Adding component extra_cmds
-- Adding component smt2parser
-- Adding component proofs
-- Adding component fpa
-- Adding rule to generate "fpa2bv_rewriter_params.hpp"
-- Adding component macros
-- Adding component pattern
-- Adding rule to generate "pattern_inference_params_helper.hpp"
-- Adding component bit_blaster
-- Adding component smt_params
-- Adding rule to generate "smt_params_helper.hpp"
-- Adding component proto_model
-- Adding component smt
-- Adding component bv_tactics
-- Adding component smt_tactic
-- Adding component sls_tactic
-- Adding rule to generate "sls_params.hpp"
-- Adding component qe
-- Adding component muz
-- Adding rule to generate "fp_params.hpp"
-- Adding component dataflow
-- Adding component transforms
-- Adding component rel
-- Adding component clp
-- Adding component tab
-- Adding component bmc
-- Adding component ddnf
-- Adding component spacer
-- Adding component fp
-- Adding component ufbv_tactic
-- Adding component sat_solver
-- Adding component smtlogic_tactics
-- Adding rule to generate "qfufbv_tactic_params.hpp"
-- Adding component fpa_tactics
-- Adding component fd_solver
-- Adding component portfolio
-- Adding component opt
-- Adding rule to generate "opt_params.hpp"
-- Adding component api
-- Adding component api_dll
-- Building documentation disabled
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/zkat/src/orogene/target/release/build/z3-sys-efa3561d0d5a5b66/out/build
running: "cmake" "--build" "." "--target" "install" "--config" "Release" "--"
Microsoft (R) Build Engine version 16.5.0+d4cbfca49 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

Checking Build System
Building Custom Rule C:/Users/zkat/.cargo/registry/src/github.com-1ecc6299db9ec823/z3-sys-0.6.2/z3/src/util/CMakeLists.txt
approx_nat.cpp
approx_set.cpp
bit_util.cpp
bit_vector.cpp
cmd_context_types.cpp
common_msgs.cpp
debug.cpp
env_params.cpp
fixed_bit_vector.cpp
gparams.cpp
hash.cpp
hwf.cpp
inf_int_rational.cpp
inf_rational.cpp
inf_s_integer.cpp
lbool.cpp
luby.cpp
memory_manager.cpp
min_cut.cpp
mpbq.cpp
Generating Code...
Compiling...
mpf.cpp
mpff.cpp
mpfx.cpp
mpn.cpp
mpq.cpp
mpq_inf.cpp
mpz.cpp
page.cpp
params.cpp
permutation.cpp
prime_generator.cpp
rational.cpp
region.cpp
rlimit.cpp
scoped_ctrl_c.cpp
scoped_timer.cpp
sexpr.cpp
s_integer.cpp
small_object_allocator.cpp
smt2_util.cpp
Generating Code...
Compiling...
stack.cpp
statistics.cpp
symbol.cpp
timeit.cpp
timeout.cpp
trace.cpp
util.cpp
warning.cpp
z3_exception.cpp
Generating Code...
LINK : warning LNK4044: unrecognized option '/INCREMENTAL:NO'; ignored [C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\util\util.vcxproj]
util.vcxproj -> C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\util\util.dir\Release\util.lib
Generating "C:/Users/zkat/src/orogene/target/release/build/z3-sys-efa3561d0d5a5b66/out/build/src/math/polynomial/algebraic_params.hpp" from "algebraic_params.pyg"
Access is denied.
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(231,5): error MSB6006: "cmd.exe" exited with code 5. [C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\polynomial\polynomial.vcxproj]
Building Custom Rule C:/Users/zkat/.cargo/registry/src/github.com-1ecc6299db9ec823/z3-sys-0.6.2/z3/src/math/automata/CMakeLists.txt
automaton.cpp
LINK : warning LNK4044: unrecognized option '/INCREMENTAL:NO'; ignored [C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\automata\automata.vcxproj]
automata.vcxproj -> C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\automata\automata.dir\Release\automata.lib
Building Custom Rule C:/Users/zkat/.cargo/registry/src/github.com-1ecc6299db9ec823/z3-sys-0.6.2/z3/src/math/dd/CMakeLists.txt
dd_bdd.cpp
dd_pdd.cpp
Generating Code...
LINK : warning LNK4044: unrecognized option '/INCREMENTAL:NO'; ignored [C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\dd\dd.vcxproj]
dd.vcxproj -> C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\dd\dd.dir\Release\dd.lib
Building Custom Rule C:/Users/zkat/.cargo/registry/src/github.com-1ecc6299db9ec823/z3-sys-0.6.2/z3/src/math/simplex/CMakeLists.txt
simplex.cpp
model_based_opt.cpp
bit_matrix.cpp
Generating Code...
LINK : warning LNK4044: unrecognized option '/INCREMENTAL:NO'; ignored [C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\simplex\simplex.vcxproj]
simplex.vcxproj -> C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\simplex\simplex.dir\Release\simplex.lib
Building Custom Rule C:/Users/zkat/.cargo/registry/src/github.com-1ecc6299db9ec823/z3-sys-0.6.2/z3/src/math/hilbert/CMakeLists.txt
hilbert_basis.cpp
LINK : warning LNK4044: unrecognized option '/INCREMENTAL:NO'; ignored [C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\hilbert\hilbert.vcxproj]
hilbert.vcxproj -> C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\hilbert\hilbert.dir\Release\hilbert.lib
Building Custom Rule C:/Users/zkat/.cargo/registry/src/github.com-1ecc6299db9ec823/z3-sys-0.6.2/z3/src/math/interval/CMakeLists.txt
interval_mpq.cpp
dep_intervals.cpp
Generating Code...
LINK : warning LNK4044: unrecognized option '/INCREMENTAL:NO'; ignored [C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\interval\interval.vcxproj]
interval.vcxproj -> C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\interval\interval.dir\Release\interval.lib
Building Custom Rule C:/Users/zkat/.cargo/registry/src/github.com-1ecc6299db9ec823/z3-sys-0.6.2/z3/src/math/subpaving/CMakeLists.txt
subpaving.cpp
subpaving_hwf.cpp
subpaving_mpf.cpp
subpaving_mpff.cpp
subpaving_mpfx.cpp
subpaving_mpq.cpp
Generating Code...
LINK : warning LNK4044: unrecognized option '/INCREMENTAL:NO'; ignored [C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\subpaving\subpaving.vcxproj]
subpaving.vcxproj -> C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\subpaving\subpaving.dir\Release\subpaving.lib
Generating "C:/Users/zkat/src/orogene/target/release/build/z3-sys-efa3561d0d5a5b66/out/build/src/math/realclosure/rcf_params.hpp" from "rcf_params.pyg"
Access is denied.
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Microsoft\VC\v160\Microsoft.CppCommon.targets(231,5): error MSB6006: "cmd.exe" exited with code 5. [C:\Users\zkat\src\orogene\target\release\build\z3-sys-efa3561d0d5a5b66\out\build\src\math\realclosure\realclosure.vcxproj]

--- stderr
CMake Warning at CMakeLists.txt:60 (message):
Disabling Z3_INCLUDE_GIT_DESCRIBE
Call Stack (most recent call first):
CMakeLists.txt:109 (disable_git_describe)

CMake Warning at CMakeLists.txt:64 (message):
Disabling Z3_INCLUDE_GIT_HASH
Call Stack (most recent call first):
CMakeLists.txt:110 (disable_git_hash)

CMake Warning (dev) at cmake/msvc_legacy_quirks.cmake:160 (message):
Skipping legacy linker MSVC options for x86_64 RELEASE
Call Stack (most recent call first):
CMakeLists.txt:429 (include)
This warning is for project developers. Use -Wno-dev to suppress it.

CMake Warning (dev) at cmake/msvc_legacy_quirks.cmake:160 (message):
Skipping legacy linker MSVC options for x86_64 RELWITHDEBINFO
Call Stack (most recent call first):
CMakeLists.txt:429 (include)
This warning is for project developers. Use -Wno-dev to suppress it.

CMake Warning at examples/CMakeLists.txt:24 (message):
Cannot set built type of external project when building with a
multi-configuration generator

CMake Warning:
Manually-specified variables were not used by the project:

CMAKE_ASM_FLAGS
CMAKE_ASM_FLAGS_RELEASE
CMAKE_BUILD_TYPE
CMAKE_C_FLAGS
CMAKE_C_FLAGS_RELEASE

thread 'main' panicked at '
command did not execute successfully, got: exit code: 1

build script failed, must exit now', C:\Users\zkat.cargo\registry\src\github.com-1ecc6299db9ec823\cmake-0.1.44\src\lib.rs:885:5
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace

warning: build failed, waiting for other jobs to finish...
error: build failed

ast.is_null() error when comparing two dynamic variables

I'm getting an error assertion failed: !ast.is_null() when running this code:

let cfg = Config::new();
let ctx = &Context::new(&cfg);
let x: ast::Dynamic = ast::Bool::new_const(ctx, "a").into();
let y: ast::Dynamic = ast::String::from_str(ctx, "a").unwrap().into();
x._eq(&y);

How should this be handled?

Are there any ways to "catch" the error of Z3_mk_model?

Currently when calling Solver::get_model() without Solver::check() (or Solver::check_assumption) first or with Solver::check() returning UnSat, the process will just print out an error message and then exit, leaving users no room to do any error handling. Are there any workarounds to fix this?

For one workaround I can think of without handling the exception at the boundary of FFI, maybe we can maintain a status in Solver, like

enum SolverStatus {
  UnCheckedOrUnSat,
  Checked
}

And Solver::get_model() would return a Result<Model, [Some Error]> instead of just letting the process exits.

[Feature Request] Owned AST nodes

AST node structs, like ast::Bool and ast::BV, contain reference to the Context. So if I want to store these nodes into my struct, Vec, or something like that, I have to transmute the nodes into <'static>.

Therefore I think we can just implement some "owned" node structs, without lifetime annotations. Like this one:

pub struct OwnedBV {
    pub(crate) ctx: Z3_context,
    pub(crate) z3_ast: Z3_ast,
}

And when this struct drops, invoke Z3_dec_ref for both the context and the AST.

If you are ok with that, I'd like to try to implement this feature and make a PR for it. ๐Ÿ˜„

Optimize gives wrong, unstable results

I have an integer minimization problem that gives different results depending on the order in which assertions are added. If I feed the generated SMT 2.0 code to the standalone z3 executable, the result is always correct.

Repro code: https://github.com/ancorehraq/z3_repro1/blob/master/src/main.rs (sorry it's so big, I tried to minimize it as much as I could)

Output:
...
bad: true, answer: 84
...
bad: false, answer: 51

"z3 -model" with either variant produces:
...
(define-fun used_ORE () Int
51)
...

Reference error when calling `list_subgoals` on ApplyResult

I'm getting a reference error when I call list_subgoals. I believe this can be fixed using a Box but it would be nice to have a more straightforward solution.

pub fn apply_result_error<'ctx>() {
    let cfg = Config::new();
    let ctx = &Context::new(&cfg);
    let goal = Goal::new(&ctx, false, false, false);
    let simplify = Tactic::repeat(
        &ctx,
        Tactic::new(ctx, "propogate-values"),
        10,
    );
    let ar = simplify.apply(&goal, None);

    let result: Vec<Vec<Goal>> = ar.list_subgoals()
        .into_iter()
        .map(|subgoal| {
            simplify.apply(&subgoal, None)
                .list_subgoals()
                .collect()
        })
        .collect();
}

Any ideas?

Improve function signature of Bool::pb_eq for better ergonomics

Currently, calling Bool::pb_eq (and similarly Bool::pb_lt and Bool::pb_gt) looks something like this:

let a = ast::Bool::new_const(&ctx, "a");
let b = ast::Bool::new_const(&ctx, "b");
let c = ast::Bool::new_const(&ctx, "c");
solver.assert(&a.pb_eq( &[&b, &c], vec![1, 2, 3], 3));

I don't like this for a few reasons:

  • It makes it look like there is some order or precedence that makes a more important than the other Bools
  • There isn't a clear matching between the booleans and the coefficients: the first coefficient is tied to a, but at a glance you would think it would be tied to b since a is outside of the list within the function call. Additionally, if you have many weights, it is unclear at a glance which weight applies to which
  • It's even less ergonomic when applying to a list:
solver.assert(&bools[0].pb_eq( &bools[1..], vec![1; 10], 10));

I believe a more intuitive function signature would greatly benefit the usability of these functions.

The first change I would propose would be turning these methods into functions by removing the &self reference. Based on the current implementation, we would need to pass in a context to replace this. This would change the above examples to:

solver.assert(Bool::pb_eq(&ctx, &[&a, &b, &c], vec![1, 2, 3], 3));
solver.assert(Bool::pb_eq(&ctx, &bools[..], vec![1; 10], 10));

Already we see a minor improvement in that we have removed the first problem of apparent arbitrary precedence. There's also much clearer matching between the coefficients and the Bools themselves now that the Bools are all grouped together too. We could stop here, but I would also like to propose one more change: if we look at the implementations from other languages like Python, we can see that instead of passing through a list of Bools and their coefficients separately, they are passed through as a single list of tuples containing both the Bool and their coefficient. I would propose that this is also adopted into the new function signature for a couple of reasons:

  • The coefficients are clearly aligned and matched with their corresponding Bools
  • It removes unclear/undefined behaviour that occurs when the list of coefficients and Bools are of differing lengths: currently no error is thrown and I believe it defaults to 0 for missing coefficients and ignores extra ones. This isn't obvious or intuitive in my opinion. By changing the function signature in this way, we can make it so that you can't have extra/missing coefficients, as it would be caught by the compiler. I believe that this will lead to fewer bugs for users of the function.
  • It is simple to use the iter::zip method to combine a list of Bools with a list of coefficients for use with this new function signature.
    This would change the examples to:
solver.assert(Bool::pb_eq(&ctx, &[(&a, 1), (&b, 2), (&c, 3)], 3));
let values = bools.zip(iter::repeat(1));
solver.assert(Bool::pb_eq(&ctx, values.as_slice(), 10));

To summarise, I would propose that, for a number of ergonomic reasons, the methods Bool::pb_eq, Bool::pb_lt and Bool::pb_gt be changed to functions with the signature
pub fn pb_xx(context: &Context, values: &[(&Bool, i32)], k: i32) -> Bool

Implement Probe

Probe is a class in Z3 used to inspect goals and collect information. This would be a very useful addition.

Examples

It would be great if https://docs.rs/z3 had some top-level documentation with full usage examples for the crate, or linked to useful examples elsewhere. As it is, it's a bit intimidating to look at the whole crate without knowing where to start.

Order-dependent segfault in `set_add`

The following code works fine:

   let cfg = Config::new();
    let ctx = Context::new(&cfg);
    let int_sort = ctx.int_sort();
    let int_set_sort = ctx.set_sort(&int_sort);
    let set = ctx.named_const("set", &int_set_sort);
    let a = ctx.named_int_const("a");
    let result = set.set_add(&a);

However, if you swap the let set... and let a... lines (so that a is defined first), it crashes with SIGSEGV. Oddly, running in lldb doesn't crash: it prints Error: type error and exits with return code 1.

I'm running z3 0.3.1 and z3-sys 0.4.0.

Can't choose a symbolic array index?

I'm storing a fixed/known number of binary expressions in an array and solving for the index of an expression that evaluates to a specific result (i.e. pick the operator to "switch" on, given all expressions have the same operands). This works in Python, but I can't seem to translate it to the Rust bindings. Simplified example:

Below works fine in Python (package z3-solver version 4.8.7.0), solving for 8 (operator) 3 = 24 I get 2, the index of operator *, the correct result:

Python code:

from z3 import *

s = Solver()

result = IntVal(24)
x = IntVal(8)
y = IntVal(3)

A = Array ('A', IntSort(), IntSort())
A = Store(A, 0, x - y)
A = Store(A, 1, x + y)
A = Store(A, 2, x * y)

j = Int('j')
s.add(j >= 0)
s.add(j <= 2)

goal = (Select(A, j) == result)
s.add(goal)
print("Goal: {}".format(goal))

if s.check() == sat:
  print("Model: {}".format(s.model()))
else:
  print("Not found!")

Python output:

Goal: 24 == Store(Store(Store(A, 0, 8 - 3), 1, 8 + 3), 2, 8*3)[j]
Model: [j = 2]

However, trying to write the equivalent in Rust (crate z3 version 0.4, Ubuntu libz3-dev version 4.4.1), I get 0, the index of the - operator, which is incorrect:

extern crate z3;
use z3::ast::Ast;

let config = z3::Config::new();
let ctx = z3::Context::new(&config);
let solver = z3::Solver::new(&ctx);

let result = z3::ast::Int::from_u64(&ctx, 24);
let x = z3::ast::Int::from_u64(&ctx, 8);
let y = z3::ast::Int::from_u64(&ctx, 3);

let A = z3::ast::Array::new_const(&ctx, "A", &z3::Sort::int(&ctx), &z3::Sort::int(&ctx));

A.store(
    &z3::ast::Dynamic::from_ast(&z3::ast::Int::from_u64(&ctx, 0)),
    &z3::ast::Dynamic::from_ast(&x.sub(&[&y])),
);

A.store(
    &z3::ast::Dynamic::from_ast(&z3::ast::Int::from_u64(&ctx, 1)),
    &z3::ast::Dynamic::from_ast(&x.add(&[&y])),
);

A.store(
    &z3::ast::Dynamic::from_ast(&z3::ast::Int::from_u64(&ctx, 2)),
    &z3::ast::Dynamic::from_ast(&x.mul(&[&y])),
);

let j = z3::ast::Int::new_const(&ctx, "j");
solver.assert(&j.ge(&z3::ast::Int::from_u64(&ctx, 0)));
solver.assert(&j.le(&z3::ast::Int::from_u64(&ctx, 2)));

let goal = A
    .select(&z3::ast::Dynamic::from_ast(&j))
    ._eq(&z3::ast::Dynamic::from_ast(&result));
solver.assert(&goal);
println!("Goal: {}", goal);

if solver.check() == z3::SatResult::Sat {
    println!("Model: {}", solver.get_model());
} else {
    println!("Not found!");
}

Rust output:

Goal: (= (select A j) 24)
Model: A -> (_ as-array k!0)
j -> 0
k!0 -> {
  0 -> 24
  else -> 24
}

Any idea what might be going wrong here?

Thanks in advance!

Holding a reference in `DatatypeAccessor::Sort` is awkward

(repeating some context from #137)

The issue with taking a reference to Sort is that a pattern like the following no longer works:

// Translating my own type system into Z3, specifically structs
let my_name: String = ...;
let my_fields: Vec<(String, IrType)> = ...;
let z3_types: HashMap<IrType, DatatypeSort> = ...;

let builder = DatatypeBuilder::new(context, "foo");
let variants = my_fields
    .iter()
    .map(|(name, field)| {
        let z3_ty = match field {
            IrType::Bool => DatatypeAccessor::Sort(Sort::bool(context)),
            // ... other simple types ...
            not_simple_type => {
                let z3_ty: &DatatypeSort = z3_types.get(not_simple_type).unwrap();
                DatatypeAccessor::Sort(z3_ty.sort.clone())
            }
        };
        (name.as_str(), z3_ty)
    })
    .collect();

let new_ty: DatatypeSort<'ctx> = builder.variant("foo_variant", variants).finish();
z3_types.insert(my_name, new_ty);

z3_ty sometimes refers to a sort that lives on the stack, so it can't be returned from the map function. The fix is to make a single sort value outside of the loop (even if the sort will not be used by the variant) so it can be referred to in variants, but can this be avoided? Switching back to the owned Sort value and adding a Clone impl would do this (clone impl was added in #137).

Debugging?

Hi,

I'm generating some assertions, but z3 complains type errors. I wanted to print out the details of the context. For example, print the SMTLib2 format. But z3-rs seems to have no support for any kind of inspection? I'd like to know what to do in this case...

I'm not familiar with z3-rs or z3-c++, so please forgive me if I make any mistakes.

Could z3.rs be my solution?

I've been running into issues with the overhead of constructing Python objects of the Python API for Z3. Would z3.rs avoid these problems in the same way that the C API does (see linked discussion or here for a related Stack Overflow post)?

Update bindings for Z3 4.8.6

The exported functions from the C API have changed:

+    pub fn Z3_mk_set_has_size(c: Z3_context, set: Z3_ast, k: Z3_ast) -> Z3_ast;
+    pub fn Z3_get_seq_sort_basis(c: Z3_context, s: Z3_sort) -> Z3_sort;
+    pub fn Z3_get_re_sort_basis(c: Z3_context, s: Z3_sort) -> Z3_sort;
+    pub fn Z3_mk_lstring(c: Z3_context, len: ::std::os::raw::c_uint, s: Z3_string) -> Z3_ast;
+    pub fn Z3_get_lstring(
+    pub fn Z3_mk_str_lt(c: Z3_context, prefix: Z3_ast, s: Z3_ast) -> Z3_ast;
+    pub fn Z3_mk_str_le(c: Z3_context, prefix: Z3_ast, s: Z3_ast) -> Z3_ast;
+    pub fn Z3_mk_seq_nth(c: Z3_context, s: Z3_ast, index: Z3_ast) -> Z3_ast;
+    pub fn Z3_mk_seq_last_index(c: Z3_context, arg1: Z3_ast, substr: Z3_ast) -> Z3_ast;
+    pub fn Z3_mk_linear_order(
+    pub fn Z3_mk_partial_order(
+    pub fn Z3_mk_piecewise_linear_order(
+    pub fn Z3_mk_tree_order(c: Z3_context, a: Z3_sort, id: ::std::os::raw::c_uint) -> Z3_func_decl;
+    pub fn Z3_mk_transitive_closure(c: Z3_context, f: Z3_func_decl) -> Z3_func_decl;
-    pub fn Z3_get_parser_error(c: Z3_context) -> Z3_string;
-    pub fn Z3_apply_result_convert_model(
+    pub fn Z3_solver_get_trail(c: Z3_context, s: Z3_solver) -> Z3_ast_vector;
+    pub fn Z3_solver_get_levels(
+    pub fn Z3_solver_to_dimacs_string(c: Z3_context, s: Z3_solver) -> Z3_string;
-    pub fn Z3_fixedpoint_push(c: Z3_context, d: Z3_fixedpoint);
-    pub fn Z3_fixedpoint_pop(c: Z3_context, d: Z3_fixedpoint);
+    pub fn Z3_optimize_assert_and_track(c: Z3_context, o: Z3_optimize, a: Z3_ast, t: Z3_ast);

CXX.rs instead of bindgen

i'm currently working on changing z3-sys to use cxx.rs, would you be open to replacing this if I get the interface to match?

Set::del does not delete element from the set

As can be shown from this simple failing test, the Set::del operation does not work

#[test]
fn test_set() {
    let cfg = Config::new();
    let ctx = Context::new(&cfg);
    let solver = Solver::new(&ctx);
    let set = ast::Set::new_const(&ctx, "integer_set", &Sort::int(&ctx));
    let one = ast::Int::from_u64(&ctx, 1);

    solver.push();
    solver.assert(&set._eq(&ast::Set::empty(&ctx, &Sort::int(&ctx))));

    solver.push();
    solver.assert(&set.member(&one));
    // An empty set will never contain 1
    assert_eq!(solver.check(), SatResult::Unsat);
    solver.pop(1);

    solver.push();
    let set_with_one = set.add(&one);
    // Adding 1 to the empty set means it does now contain 1
    solver.assert(&set_with_one.member(&one));
    assert_eq!(solver.check(), SatResult::Sat);
    let set_without_one = set_with_one.del(&one);
    // Removing 1 from the set means it no longer contains 1
    solver.assert(&set_without_one.member(&one));
    assert_eq!(solver.check(), SatResult::Unsat);
    solver.pop(1);
}

I believe this can be fixed simply by changing ast.rs

/// Remove an element from the set.
    ///
    /// Note that the `element` _must be_ of the `Set`'s `eltype` sort.
    //
    // We avoid the binop! macro because the argument has a non-Self type
    pub fn del<A>(&self, element: &A) -> Set<'ctx>
    where
        A: Ast<'ctx>,
    {
        Set::new(self.ctx, unsafe {
            let guard = Z3_MUTEX.lock().unwrap();
            Z3_mk_set_add(self.ctx.z3_ctx, self.z3_ast, element.get_z3_ast())
        })
    }

to
Z3_mk_set_del(self.ctx.z3_ctx, self.z3_ast, element.get_z3_ast())

About Z3_MUTEX

I'm currently developing a multi-threaded program, but it seems like almost every function call to the z3 library is mutex-guarded. My threads will frequently create expressions and eval() them, and each thread has its own Context (unsafe impl Send for Context)

I'm wondering if the Z3_MUTEX will slow down my code. If so, is it safe to remove the Z3_MUTEX in my code? Thanks :)

Segfault using `z3`

I'm not sure if this is a bug in Z3 or in these bindings, so I'm just filing the issue here to start.

The following minimal example produces a segmentation fault:

use z3::ast::{Ast, BV};

fn main() {
    let ctx = z3::Context::new(&z3::Config::new());
    let size = BV::from_u64(&ctx, 0, 64).extract(2, 0).get_size();
    let x = BV::from_u64(&ctx, 0, 64).extract(2, 0);
}

Removing either the let size or the let x lines causes the segfault to go away; it is only present when both lines are there. Likewise, removing either of the extract()s or the get_size() also causes the segfault to go away.

Running in rust-lldb appears to show that the segfault occurs inside Z3 during the call to Z3_del_context() resulting from Context::drop().

Interestingly, adding the line

let x_size = x.get_size();

to the end of the example above produces the strange error Error: sort is not a bit-vector during the call to Z3_get_bv_sort_size(). I don't know if that's helpful or not.

System info:

  • z3: current master (0a2523b)
  • Z3: 4.8.5 (installed via brew)
  • Rust: 1.35.0
  • OS: macOS 10.14.4

Using Proofs

I am trying to write a simple verification backend using z3.rs, I have the statements below.
assertions: (= y (bvmul x #x0000000000000003))
assertions: (= x (bvadd x x))
negated goal: (not (= (bvadd x x) (bvmul x #x0000000000000003)))

So my expectation is that the solver comes up with SAT result, yet I get UNSAT.

I wanted to understand why it does that, so I tried extracting the proof, yet I could not find any useful method that proof uses which I can inspect the process. The code examples are not very useful either, if anyone could post anything allowing me to move forward, I would be grateful.

crates.io

Any chance you can get this uploaded as a rust crate - I'm a bit concerned about pointing to github in our cargo.toml (outages etc.)

Stack overflow when mixing Contexts

The following code causes a stack overflow:

#[test]
fn mix() {
    let cfg = Config::new();
    let ctx0 = Context::new(&cfg);
    let ctx1 = Context::new(&cfg);
    let i0 = ast::Int::fresh_const(&ctx0, "a");
    let i1 = ast::Int::fresh_const(&ctx1, "b");
    ast::Int::add(&ctx0, &[&i0, &i1]);
}
thread 'mix' has overflowed its stack

The C++/Python/C# bindings check to make sure the contexts are the same before calling the Z3 functions. Rust might be able to get away without runtime checking by encoding this into the type system.

Segfault when compiling --release

Forgive me, I'm new to Z3. I was experimenting and I wanted to create a program that solves a sorted list of variables from 0 to 100. My code runs and finds the solution, albeit slowly, when compiled in development mode, but Segfaults when compiled in release mode. I figured I'd raise an issue.

Here's my code:

extern crate z3;

use z3::ast;
use z3::*;

fn main() {
    let cfg = Config::new();
    let ctx = Context::new(&cfg);
    let optimizer = Optimize::new(&ctx);

    let mut v = Vec::new();

    for i in 0..100 {
        let c = ast::Int::new_const(&ctx, format!("cell-{}", i));
        if i == 0 {
            optimizer.assert(&c.gt(&ast::Int::from_i64(&ctx, 0)))
        }
        optimizer.minimize(&c);
        v.push(c);
    }

    for (i, j) in v.iter().zip(v.iter().skip(1)) {
        optimizer.assert(&j.gt(i));
    }

    assert!(optimizer.check());

    let model = optimizer.get_model();

    for i in v.iter() {
        println!("{}: {}", i, model.eval(i).unwrap().as_i64().unwrap());
    }
}

Missing API to create bitvector from value

I'm trying to do math with bitvectors, and running into what seems like a missing API: I don't see any way to create a bitvector from an integer or bool array.

For example:

    let cfg = Config::new();
    let ctx = Context::new(&cfg);
    let b = ctx.named_bitvector_const("bv", 4);
    let s = Solver::new(&ctx);
    s.assert(&b._eq(&ctx.from_u64(1)));

will print the error message

Error: Sorts (_ BitVec 4) and Int are incompatible

My suggested fix is to add pub fn from_u64(ctx: &'ctx Context, u: u64 -> Ast<'ctx> to the Sort type, with an implementation that calls Z3_mk_unsigned_int64() using the given sort. This works for integer, bit-vector, and finite-domain sorts.

Is this something that you'd accept a PR for (or want to implement yourself)?

Consider denying missing debug implementations

#![deny(missing_debug_implementations)]

It is quite nice when every type implements Debug, and this enforces that at the crate level.

In particular, I just found that z3::Solver doesn't implement Debug.

Support for "try_for" tactic

This would allow setting a time limit on tactic execution. It should be a pretty simple wrapper around this function in z3-sys: I'll put up a pull request as well!

Implement interface for Tactic and Goal

There is currently no abstraction on Tactic or Goal, which are useful for things like simplification. I started working on implementing them, but wanted to check if there had been some work on this in the past or any blockers for adding them to the library.

Ast::substitute is unsafe

The substitute method on AST allows arbitrary rewriting while retaining (now inaccurate) types.

<Int as Ast>::substitute<Int, Real>

could internally rewrite the Ast to be of type Real, but retain the rust type Int.

for the function to be safe, we need the more restricted type:

substitute<T>(&self, substitutions: &[(&T, &T)]) -> Self

Or some extra machinery to handle the invalid or retyped ASTs that can be formed by arbitrary substitution.

Constant evaluates to false when calling Model::eval

I have an issue where a constant is evaluated to false when calling Model::eval, even though the solver says that the constant is true in the model.

Code

use z3::{Ast, Config, Context, Solver};

fn main() {
    let config = Config::new();
    let context = Context::new(&config);
    let solver = Solver::new(&context);

    let b = context.fresh_bool_const("b");
    let true_ = Ast::from_bool(&context, true);
    let expr = Ast::_eq(&b, &true_);
    solver.assert(&expr);
    assert!(solver.check());

    println!("Solver: {}", solver.to_string());

    let model = solver.get_model();
    println!("b = {}", model.eval(&b).unwrap().as_bool().unwrap());
}

Expected behavior

After calling solver.check, solver.to_string returns:

(declare-fun b!0 () Bool)
(assert (= b!0 true))
(rmodel->model-converter-wrapper
b!0 -> true
)

I have no prior experience with Z3, but I read this as: a solution was found where b!0 is true. Therefore, I expect model.eval(&b).unwrap().as_bool().unwrap() to be true

Actual behavior

model.eval(&b).unwrap().as_bool().unwrap() returns false

z3-sys fails to build with static linking

In Cargo.toml I have:

z3 = {version="0.11.1", features = ["static-link-z3"]}

When I build I get the following:

error: failed to run custom build command for `z3-sys v0.7.0`

Caused by:
  process didn't exit successfully: `/home/sadmac/coding/biat/target/debug/build/z3-sys-d5ede29e06b013d6/build-script-build` (exit code: 101)
  --- stdout
  running: "cmake" "/home/sadmac/.cargo/registry/src/github.com-1ecc6299db9ec823/z3-sys-0.7.0/z3" "-DZ3_BUILD_LIBZ3_SHARED=false" "-DZ3_BUILD_EXECUTABLE=false" "-DZ3_BUILD_TEST_EXECUTABLES=false" "-DCMAKE_INSTALL_PREFIX=/home/sadmac/coding/biat/target/debug/build/z3-sys-9c1a1749c10cc82d/out" "-DCMAKE_C_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64" "-DCMAKE_C_COMPILER=/usr/bin/cc" "-DCMAKE_CXX_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64" "-DCMAKE_CXX_COMPILER=/usr/bin/c++" "-DCMAKE_ASM_FLAGS= -ffunction-sections -fdata-sections -fPIC -m64" "-DCMAKE_ASM_COMPILER=/usr/bin/cc" "-DCMAKE_BUILD_TYPE=Debug"

  --- stderr
  CMake Error: The source directory "/home/sadmac/.cargo/registry/src/github.com-1ecc6299db9ec823/z3-sys-0.7.0/z3" does not exist.
  Specify --help for usage, or press the help button on the CMake GUI.
  thread 'main' panicked at '
  command did not execute successfully, got: exit code: 1

  build script failed, must exit now', /home/sadmac/.cargo/registry/src/github.com-1ecc6299db9ec823/cmake-0.1.45/src/lib.rs:894:5
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

/home/sadmac/.cargo/registry/src/github.com-1ecc6299db9ec823/z3-sys-0.7.0 contains:

build.rs  Cargo.toml  Cargo.toml.orig  LICENSE.txt  README.md  scripts  src  tests  wrapper.h

Symmetrical version of the varop operators

To implement the AllDifferent constraint on an ensemble of variables stored in a Vec, I haven't found better than

s.assert(&vars[0].distinct(&vars[1..].iter().collect::<Vec<&_>>()));

It feels a bit strange to single out the first variable, considering they all play the same role in the constraint. Would it make sense to imagine something like

s.assert(ast::distinct(&vars));

This could probably apply to all of the functions defined by the varop macro.

Varops crash with empty slice

I appreciate the changes by @bumblepie in #83. However, there seems to be a crash (not a panic!) with an empty slice as the argument to varops:

#[test]
fn test_zero_args() {
    let _ = env_logger::try_init();
    let cfg = Config::new();
    let ctx = Context::new(&cfg);
    let _ = ast::Int::add(&ctx, &[]);
}

Results in

Error: no arguments supplied to arithmetical operator

Most Z3 C API functions require the list of operands to be nonempty.

A slight improvement might be to add an assert! in the right places to guard against an empty slice so the panic can be caught.

Examining AST types (eg DeclKind)

My goal is to parse an AST, converting it to a representation used in another library. For example, if the other representation is of the form:

enum Node {
  BoolLiteral(bool),
  BoolVar(String),
  And(Box<Node>, Box<Node>),
  Or(Box<Node>, Box<Node>),
}

I'd like a z3 AST x and (y or true) to be converted to (dropping boxes/etc)

And(BoolVar("x"), Or(BoolVar("y"), BoolLiteral(true)))

This requires being able to introspect the Ast types at the DeclKind granularity. In the Python/C++ API, they have functions such as Ast::kind() -> AstKind, Ast::func_decl() -> FuncDecl, FuncDecl::kind() -> DeclKind, etc. My initial attempts to mimic those APIs to do this have been partially successful, but ultimately cause errors. The current issue is that my implementation FuncDecl::kind() -> DeclKind (pasted below) is returning an invalid DeclKind (value 0, while Z3_decl_kind starts at 256), but I suspect the larger issue is that I am bad at C and I am monkey coding.

I'd be very interested in having the path of methods that lead to getting DeclKind. I'm happy to send out PRs that may or may not work, but it's also possible that you could do this in your sleep and I'd just get in the way :).

Question/discussion/suggestion: AST subtypes

Trying to combine Asts of different Sorts often results in errors. For instance, you can't add an integer and a bitvector, you can only select on an array, etc. In fact, the Ast type appears to have a number of distinct groups of methods, only one of which applies to any given Ast (depending on its Sort): the first group (add, sub, etc) which apply to integers (and maybe reals? Not sure as I never use reals); the second group (bv*) which apply to bitvectors; select and store which apply to arrays; set_* which apply to sets; and pb_* (I'm not sure what these are either).

Since each of these groups of methods apply to different kinds of Asts, and rarely can different kinds of Asts be mixed without errors, I was wondering if any thought has been given to splitting Ast into a number of subtypes, perhaps IntAst, BVAst, ArrayAst, etc (obviously different names could be used). This would not only clarify exactly which Ast operations apply to each type, it would also help prevent more errors statically at the Rust type level, thus making a safer set of high-level bindings.

I'm potentially willing to help implement this if it's desired and feasible, but I wanted to ask first if it's a reasonable suggestion, and get feedback from anyone with more experience with Z3 (and Rust) than me. Is there a reason this is a bad idea?

test_pb_ops_model fails with linker error

This is on a Debian 9.8, Z3 version 4.8.0 sourced using the package manager.

I have to mention that all other tests run OK if I comment out this one.

cargo test --color=always --no-run --package z3 --test lib test_pb_ops_model -- --exact
   Compiling z3 v0.3.2 (/home/radu/0/projects/z3.rs/z3)
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.13dd3x295s8awfnw.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.19h6al6q14nvbfhb.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.1e9ot4xe6ilycje7.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.1pe8ip2a3dkr9sg9.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.1vc0xcsmhriab9df.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.1x1upuwbbt1zt99i.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.22p9fku1c9ek87o0.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.2432gt1jvesuh1vn.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.25o8adpxo2l52xeb.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.2acaigx4s0pjjcay.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.2k1dphs3573goxiu.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.2qk2gtem7q6y93i.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.2yvxyen20jhjmv2v.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.378i3vldmty6ledi.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.38pve3dupc8d2m8k.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.3ap9ddu6dxj22d40.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.3bxi37my4d1hepd8.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.3yedymlhbje2btu6.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.446qj83m3fpnn5sv.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.44b8xuojtmkc6wgs.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.4qufu8bkus73ftbn.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.4xccnx30stzz2l61.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.54uc5dpf4cspkl90.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.56he1twsapa0h32t.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.5glp2c7p9pdsqqvy.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.8cvmjeezs5a1rpn.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.emf72d8cocn5j5w.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.ikb7v8zgbakqyd9.rcgu.o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.usb4jfgo0nz3fyp.rcgu.o" "-o" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869" "/home/radu/0/projects/z3.rs/target/debug/deps/lib-698daf5a4a769869.34uw3afms39hceq4.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-nodefaultlibs" "-L" "/home/radu/0/projects/z3.rs/target/debug/deps" "-L" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libtest-c3a0bad6f0180507.rlib" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libterm-6540918622214377.rlib" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgetopts-50a203aae2e8a340.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libz3-0952be98c4f45fce.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libz3_sys-990f253237416b9c.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libenv_logger-c117e4fd8606a2d6.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libregex-c5e017f500ea85d7.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libutf8_ranges-0918e619d385a370.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libregex_syntax-f948a5a4f3a9565a.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libucd_util-c7796064d62c625f.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libthread_local-490b6783e7f5080a.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/liblazy_static-afc97fc38871e70e.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libaho_corasick-27e3cb3682fb766a.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libmemchr-3e1032aa5c7637ed.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libatty-8d1d4b29dfd3e4e7.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/liblibc-49802dcd396439e8.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libhumantime-90cdc19170c7d43f.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libquick_error-7922e5169f66e962.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libtermcolor-1c9ff6d92ed1f224.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/liblog-86bd3d03706a8200.rlib" "/home/radu/0/projects/z3.rs/target/debug/deps/libcfg_if-1e34a1283119a981.rlib" "-Wl,--start-group" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-e39317eb74365d3c.rlib" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-4d55a38564aae54a.rlib" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libbacktrace_sys-f8521075e248b627.rlib" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-7c91ffdc8da860d3.rlib" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-0ad27b9879d551d3.rlib" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-588f18eae3ea58be.rlib" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-4ebf5caee903d98f.rlib" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-8895b32baedb08c6.rlib" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-6a9d233d01acc350.rlib" "-Wl,--end-group" "/home/radu/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-851bb3b5f6c4db49.rlib" "-Wl,-Bdynamic" "-lz3" "-lutil" "-lutil" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
  = note: /home/radu/0/projects/z3.rs/target/debug/deps/libz3-0952be98c4f45fce.rlib(z3-0952be98c4f45fce.363hus1v0nu3dsvj.rcgu.o): In function `z3::ast::<impl z3::Ast<'ctx>>::pb_eq':
          /home/radu/0/projects/z3.rs/z3/src/ast.rs:306: undefined reference to `Z3_mk_pbeq'
          collect2: error: ld returned 1 exit status
          

error: aborting due to previous error

error: Could not compile `z3`.

Accessors for Ast children?

We're trying to port a Python lib that uses the Python Z3 bindings to Rust. One functionality gap we came across is the ability to traverse the Ast by accessing a node's children. In python, there are functions for children, num_args, and arg. I'd be very interested in those in z3.rs!

I've opened an RFC PR #105. Some reasons for caution:

  1. I don't really understand the Z3 C API and the right memory model to make sure my unsafe blocks are actually safe.
  2. I chose the more intuitive names of num_children and nth_child rather than num_args and arg, but maybe it's better to keep the APIs similar?
  3. I've just done a few basic tests. I'm happy to do more, if you think I'm going in the right direction.

And thanks for making this crate, btw! It's very helpful to us.

Floating point ast Subtype

May I suggest adding an high lvl api for floating point numbers? I am currently writing a compiler for a DSL whose static analysis heavily relies on making floating point assertions. I was considering just writing my own abstraction but I guess it makes more sense to just add it upstream.

Is there any interest in me writing this abstraction or would some already involved be willing to write it ( I do not have much experience with this project but from looking at sources I guess I should manage)?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.