diff --git a/.github/workflows/cbmc-latest.yml b/.github/workflows/cbmc-latest.yml index 9191e8250550..71806f0a0cca 100644 --- a/.github/workflows/cbmc-latest.yml +++ b/.github/workflows/cbmc-latest.yml @@ -89,3 +89,8 @@ jobs: - name: Execute Kani performance tests working-directory: ./kani run: ./scripts/kani-perf.sh + + - name: Execute Kani performance ignored tests + working-directory: ./kani + continue-on-error: true + run: cargo run -p compiletest -- --suite perf --mode cargo-kani-test ignore --ignored --no-fail-fast diff --git a/kani-compiler/kani_queries/src/lib.rs b/kani-compiler/kani_queries/src/lib.rs index 156c3e9033c3..11df541e3b03 100644 --- a/kani-compiler/kani_queries/src/lib.rs +++ b/kani-compiler/kani_queries/src/lib.rs @@ -10,7 +10,7 @@ mod unsound_experiments; #[cfg(feature = "unsound_experiments")] use crate::unsound_experiments::UnsoundExperiments; -#[derive(Debug, Clone, Copy, AsRefStr, EnumString, EnumVariantNames, PartialEq, Eq)] +#[derive(Debug, Default, Clone, Copy, AsRefStr, EnumString, EnumVariantNames, PartialEq, Eq)] #[strum(serialize_all = "snake_case")] pub enum ReachabilityType { /// Start the cross-crate reachability analysis from all harnesses in the local crate. @@ -18,6 +18,7 @@ pub enum ReachabilityType { /// Use standard rustc monomorphizer algorithm. Legacy, /// Don't perform any reachability analysis. This will skip codegen for this crate. + #[default] None, /// Start the cross-crate reachability analysis from all public functions in the local crate. PubFns, @@ -25,12 +26,6 @@ pub enum ReachabilityType { Tests, } -impl Default for ReachabilityType { - fn default() -> Self { - ReachabilityType::None - } -} - pub trait UserInput { fn set_emit_vtable_restrictions(&mut self, restrictions: bool); fn get_emit_vtable_restrictions(&self) -> bool; diff --git a/kani-compiler/src/codegen_cprover_gotoc/codegen/intrinsic.rs b/kani-compiler/src/codegen_cprover_gotoc/codegen/intrinsic.rs index 910a842e61d0..98ed0421e05d 100644 --- a/kani-compiler/src/codegen_cprover_gotoc/codegen/intrinsic.rs +++ b/kani-compiler/src/codegen_cprover_gotoc/codegen/intrinsic.rs @@ -365,7 +365,9 @@ impl<'tcx> GotocCtx<'tcx> { "add_with_overflow" => codegen_op_with_overflow!(add_overflow_result), "arith_offset" => self.codegen_offset(intrinsic, instance, fargs, p, loc), "assert_inhabited" => self.codegen_assert_intrinsic(instance, intrinsic, span), - "assert_uninit_valid" => self.codegen_assert_intrinsic(instance, intrinsic, span), + "assert_mem_uninitialized_valid" => { + self.codegen_assert_intrinsic(instance, intrinsic, span) + } "assert_zero_valid" => self.codegen_assert_intrinsic(instance, intrinsic, span), // https://doc.rust-lang.org/core/intrinsics/fn.assume.html // Informs the optimizer that a condition is always true. diff --git a/kani-compiler/src/codegen_cprover_gotoc/codegen/place.rs b/kani-compiler/src/codegen_cprover_gotoc/codegen/place.rs index 97d0c225c963..67801f747acc 100644 --- a/kani-compiler/src/codegen_cprover_gotoc/codegen/place.rs +++ b/kani-compiler/src/codegen_cprover_gotoc/codegen/place.rs @@ -243,7 +243,8 @@ impl<'tcx> GotocCtx<'tcx> { match t { TypeOrVariant::Type(t) => { match t.kind() { - ty::Bool + ty::Alias(..) + | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) @@ -254,10 +255,8 @@ impl<'tcx> GotocCtx<'tcx> { | ty::GeneratorWitness(..) | ty::Foreign(..) | ty::Dynamic(..) - | ty::Projection(_) | ty::Bound(..) | ty::Placeholder(..) - | ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error(_) => unreachable!("type {:?} does not have a field", t), diff --git a/kani-compiler/src/codegen_cprover_gotoc/codegen/typ.rs b/kani-compiler/src/codegen_cprover_gotoc/codegen/typ.rs index f315e1795fa9..fca6ffe5db61 100644 --- a/kani-compiler/src/codegen_cprover_gotoc/codegen/typ.rs +++ b/kani-compiler/src/codegen_cprover_gotoc/codegen/typ.rs @@ -358,20 +358,41 @@ impl<'tcx> GotocCtx<'tcx> { // `Generator::resume(...) -> GeneratorState` function in case we // have an ordinary generator, or the `Future::poll(...) -> Poll` // function in case this is a special generator backing an async construct. - let ret_ty = if self.tcx.generator_is_async(*did) { - let state_did = self.tcx.require_lang_item(LangItem::Poll, None); - let state_adt_ref = self.tcx.adt_def(state_did); - let state_substs = self.tcx.intern_substs(&[sig.return_ty.into()]); - self.tcx.mk_adt(state_adt_ref, state_substs) + let tcx = self.tcx; + let (resume_ty, ret_ty) = if tcx.generator_is_async(*did) { + // The signature should be `Future::poll(_, &mut Context<'_>) -> Poll` + let poll_did = tcx.require_lang_item(LangItem::Poll, None); + let poll_adt_ref = tcx.adt_def(poll_did); + let poll_substs = tcx.intern_substs(&[sig.return_ty.into()]); + let ret_ty = tcx.mk_adt(poll_adt_ref, poll_substs); + + // We have to replace the `ResumeTy` that is used for type and borrow checking + // with `&mut Context<'_>` which is used in codegen. + #[cfg(debug_assertions)] + { + if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() { + let expected_adt = tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, None)); + assert_eq!(*resume_ty_adt, expected_adt); + } else { + panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty); + }; + } + let context_mut_ref = tcx.mk_task_context(); + + (context_mut_ref, ret_ty) } else { - let state_did = self.tcx.require_lang_item(LangItem::GeneratorState, None); - let state_adt_ref = self.tcx.adt_def(state_did); - let state_substs = self.tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); - self.tcx.mk_adt(state_adt_ref, state_substs) + // The signature should be `Generator::resume(_, Resume) -> GeneratorState` + let state_did = tcx.require_lang_item(LangItem::GeneratorState, None); + let state_adt_ref = tcx.adt_def(state_did); + let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]); + let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); + + (sig.resume_ty, ret_ty) }; + ty::Binder::bind_with_vars( - self.tcx.mk_fn_sig( - [env_ty, sig.resume_ty].iter(), + tcx.mk_fn_sig( + [env_ty, resume_ty].iter(), &ret_ty, false, Unsafety::Normal, @@ -813,7 +834,7 @@ impl<'tcx> GotocCtx<'tcx> { ) } } - ty::Projection(_) | ty::Opaque(_, _) => { + ty::Alias(..) => { unreachable!("Type should've been normalized already") } @@ -1226,7 +1247,7 @@ impl<'tcx> GotocCtx<'tcx> { ty::Dynamic(..) | ty::Slice(_) | ty::Str => { unreachable!("Should have generated a fat pointer") } - ty::Projection(_) | ty::Opaque(..) => { + ty::Alias(..) => { unreachable!("Should have been removed by normalization") } diff --git a/kani-compiler/src/kani_compiler.rs b/kani-compiler/src/kani_compiler.rs index 909be072a9db..8af75fb8eb1e 100644 --- a/kani-compiler/src/kani_compiler.rs +++ b/kani-compiler/src/kani_compiler.rs @@ -169,7 +169,7 @@ impl Callbacks for KaniCompiler { rustc_queries: &'tcx rustc_interface::Queries<'tcx>, ) -> Compilation { if self.stubs.is_none() && self.queries.lock().unwrap().get_stubbing_enabled() { - rustc_queries.global_ctxt().unwrap().peek_mut().enter(|tcx| { + rustc_queries.global_ctxt().unwrap().enter(|tcx| { let stubs = self.stubs.insert(self.collect_stubs(tcx)); debug!(?stubs, "after_analysis"); if stubs.is_empty() { Compilation::Continue } else { Compilation::Stop } diff --git a/kani-compiler/src/kani_middle/attributes.rs b/kani-compiler/src/kani_middle/attributes.rs index 3ea8e69a46a5..cf94b518d06d 100644 --- a/kani-compiler/src/kani_middle/attributes.rs +++ b/kani-compiler/src/kani_middle/attributes.rs @@ -276,7 +276,7 @@ fn parse_solver(tcx: TyCtxt, attr: &Attribute) -> Option { } } MetaItemKind::NameValue(lit) if ident_str == "bin" && lit.kind.is_str() => { - Some(CbmcSolver::Binary(lit.token_lit.symbol.to_string())) + Some(CbmcSolver::Binary(lit.symbol.to_string())) } _ => { invalid_arg_err(attr); diff --git a/kani-compiler/src/kani_middle/coercion.rs b/kani-compiler/src/kani_middle/coercion.rs index 799ba3b4766c..71ddd457e075 100644 --- a/kani-compiler/src/kani_middle/coercion.rs +++ b/kani-compiler/src/kani_middle/coercion.rs @@ -17,7 +17,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::traits::{ImplSource, ImplSourceUserDefinedData}; use rustc_middle::ty::adjustment::CustomCoerceUnsized; use rustc_middle::ty::TypeAndMut; -use rustc_middle::ty::{self, ParamEnv, TraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_span::symbol::Symbol; use tracing::trace; @@ -213,10 +213,9 @@ fn custom_coerce_unsize_info<'tcx>( ) -> CustomCoerceUnsized { let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None); - let trait_ref = ty::Binder::dummy(TraitRef { - def_id, - substs: tcx.mk_substs_trait(source_ty, [target_ty.into()]), - }); + let trait_ref = ty::Binder::dummy( + tcx.mk_trait_ref(def_id, tcx.mk_substs_trait(source_ty, [target_ty.into()])), + ); match tcx.codegen_select_candidate((ParamEnv::reveal_all(), trait_ref)) { Ok(ImplSource::UserDefined(ImplSourceUserDefinedData { impl_def_id, .. })) => { diff --git a/kani-compiler/src/session.rs b/kani-compiler/src/session.rs index 69e877fe35e2..9b83d55a8c34 100644 --- a/kani-compiler/src/session.rs +++ b/kani-compiler/src/session.rs @@ -70,7 +70,10 @@ pub fn init_session(args: &ArgMatches, json_hook: bool) { // Initialize the rustc logger using value from RUSTC_LOG. We keep the log control separate // because we cannot control the RUSTC log format unless if we match the exact tracing // version used by RUSTC. - rustc_driver::init_rustc_env_logger(); + // TODO: Enable rustc log when we upgrade the toolchain. + // + // + // rustc_driver::init_rustc_env_logger(); // Install Kani panic hook. if json_hook { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index aa6a41cddcbb..185bd4ff4136 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -2,5 +2,5 @@ # SPDX-License-Identifier: Apache-2.0 OR MIT [toolchain] -channel = "nightly-2022-12-11" +channel = "nightly-2023-01-23" components = ["llvm-tools-preview", "rustc-dev", "rust-src", "rustfmt"] diff --git a/scripts/kani-perf.sh b/scripts/kani-perf.sh index e73986a32ae2..a7e2710773aa 100755 --- a/scripts/kani-perf.sh +++ b/scripts/kani-perf.sh @@ -27,7 +27,7 @@ done suite="perf" mode="cargo-kani-test" echo "Check compiletest suite=$suite mode=$mode" -cargo run -p compiletest -- --suite $suite --mode $mode +cargo run -p compiletest -- --suite $suite --mode $mode --no-fail-fast exit_code=$? echo "Cleaning up..." diff --git a/tests/cargo-kani/vecdeque-cve/src/abstract_vecdeque.rs b/tests/cargo-kani/vecdeque-cve/src/abstract_vecdeque.rs index c128b57dbb59..8bcc44742ed9 100644 --- a/tests/cargo-kani/vecdeque-cve/src/abstract_vecdeque.rs +++ b/tests/cargo-kani/vecdeque-cve/src/abstract_vecdeque.rs @@ -275,8 +275,8 @@ impl AbstractRawVec { fn handle_reserve(result: Result<(), TryReserveError>) { match result.map_err(|e| e.kind()) { - Err(CapacityOverflow) => capacity_overflow(), - Err(AllocError) => handle_alloc_error(), + Err(TryReserveErrorKind::CapacityOverflow) => capacity_overflow(), + Err(TryReserveErrorKind::AllocError) => handle_alloc_error(), Ok(()) => { /* yay */ } } } diff --git a/tests/perf/btreeset/insert_same/Cargo.toml b/tests/perf/btreeset/ignore_insert_same/Cargo.toml similarity index 100% rename from tests/perf/btreeset/insert_same/Cargo.toml rename to tests/perf/btreeset/ignore_insert_same/Cargo.toml diff --git a/tests/perf/btreeset/insert_same/expected b/tests/perf/btreeset/ignore_insert_same/expected similarity index 100% rename from tests/perf/btreeset/insert_same/expected rename to tests/perf/btreeset/ignore_insert_same/expected diff --git a/tests/perf/btreeset/insert_same/src/main.rs b/tests/perf/btreeset/ignore_insert_same/src/main.rs similarity index 100% rename from tests/perf/btreeset/insert_same/src/main.rs rename to tests/perf/btreeset/ignore_insert_same/src/main.rs diff --git a/tests/perf/vec/string/Cargo.toml b/tests/perf/vec/ignore_string/Cargo.toml similarity index 100% rename from tests/perf/vec/string/Cargo.toml rename to tests/perf/vec/ignore_string/Cargo.toml diff --git a/tests/perf/vec/box_dyn/Cargo.toml b/tests/perf/vec/ignore_string/box_dyn/Cargo.toml similarity index 100% rename from tests/perf/vec/box_dyn/Cargo.toml rename to tests/perf/vec/ignore_string/box_dyn/Cargo.toml diff --git a/tests/perf/vec/box_dyn/expected b/tests/perf/vec/ignore_string/box_dyn/expected similarity index 100% rename from tests/perf/vec/box_dyn/expected rename to tests/perf/vec/ignore_string/box_dyn/expected diff --git a/tests/perf/vec/box_dyn/src/main.rs b/tests/perf/vec/ignore_string/box_dyn/src/main.rs similarity index 100% rename from tests/perf/vec/box_dyn/src/main.rs rename to tests/perf/vec/ignore_string/box_dyn/src/main.rs diff --git a/tests/perf/vec/string/expected b/tests/perf/vec/ignore_string/expected similarity index 100% rename from tests/perf/vec/string/expected rename to tests/perf/vec/ignore_string/expected diff --git a/tests/perf/vec/string/src/main.rs b/tests/perf/vec/ignore_string/src/main.rs similarity index 100% rename from tests/perf/vec/string/src/main.rs rename to tests/perf/vec/ignore_string/src/main.rs diff --git a/tests/ui/code-location/expected b/tests/ui/code-location/expected index 20d7f40879bc..1d188e17314a 100644 --- a/tests/ui/code-location/expected +++ b/tests/ui/code-location/expected @@ -1,6 +1,6 @@ module/mod.rs:10:5 in function module::not_empty main.rs:13:5 in function same_file /toolchains/ -alloc/src/vec/mod.rs:3054:81 in function as std::ops::Drop>::drop +alloc/src/vec/mod.rs:3059:81 in function as std::ops::Drop>::drop VERIFICATION:- SUCCESSFUL diff --git a/tools/compiletest/src/header.rs b/tools/compiletest/src/header.rs index fc7ac84b5680..afb9057ad451 100644 --- a/tools/compiletest/src/header.rs +++ b/tools/compiletest/src/header.rs @@ -180,21 +180,17 @@ pub fn make_test_description( path: &Path, src: R, ) -> test::TestDesc { - let mut ignore = false; let mut should_fail = false; - let mut ignore_message = None; - if config.mode == Mode::Kani || config.mode == Mode::Stub { - // If the path to the test contains "fixme" or "ignore", skip it. - let file_path = path.to_str().unwrap(); - (ignore, ignore_message) = if file_path.contains("fixme") { - (true, Some("fixme test")) - } else if file_path.contains("ignore") { - (true, Some("ignore test")) - } else { - (false, None) - }; - } + // If the path to the test contains "fixme" or "ignore", skip it. + let file_path = path.to_str().unwrap(); + let (mut ignore, mut ignore_message) = if file_path.contains("fixme") { + (true, Some("fixme test")) + } else if file_path.contains("ignore") { + (true, Some("ignore test")) + } else { + (false, None) + }; // The `KaniFixme` mode runs tests that are ignored in the `kani` suite if config.mode == Mode::KaniFixme { @@ -207,8 +203,10 @@ pub fn make_test_description( // If the base name does NOT contain "fixme" or "ignore", we skip it. // All "fixme" tests are expected to fail - (ignore, ignore_message) = if base_name.contains("fixme") || base_name.contains("ignore") { + (ignore, ignore_message) = if base_name.contains("fixme") { (false, None) + } else if base_name.contains("ignore") { + (true, Some("ignore test")) } else { (true, Some("regular test")) };