From 6a116e1e129f79d033d3bfd0fb5c6c878918ab09 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Sat, 29 Jun 2024 20:20:16 +0200 Subject: [PATCH 01/39] feat(exporter): serde: represent `u128`/`i128` as strings See https://github.com/serde-rs/json/issues/625. This patch is highly inspired by https://github.com/txpipe/oura/pull/712. --- frontend/exporter/src/constant_utils.rs | 14 ++- frontend/exporter/src/types/copied.rs | 7 +- frontend/exporter/src/types/mod.rs | 1 + frontend/exporter/src/types/serialize_int.rs | 91 ++++++++++++++++++++ 4 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 frontend/exporter/src/types/serialize_int.rs diff --git a/frontend/exporter/src/constant_utils.rs b/frontend/exporter/src/constant_utils.rs index 738c67f0c..9d6f69615 100644 --- a/frontend/exporter/src/constant_utils.rs +++ b/frontend/exporter/src/constant_utils.rs @@ -5,8 +5,18 @@ use rustc_middle::{mir, ty}; Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, )] pub enum ConstantInt { - Int(i128, IntTy), - Uint(u128, UintTy), + Int( + #[serde(with = "serialize_int::signed")] + #[schemars(with = "String")] + i128, + IntTy, + ), + Uint( + #[serde(with = "serialize_int::unsigned")] + #[schemars(with = "String")] + u128, + UintTy, + ), } #[derive( diff --git a/frontend/exporter/src/types/copied.rs b/frontend/exporter/src/types/copied.rs index c35329c71..51c10cb07 100644 --- a/frontend/exporter/src/types/copied.rs +++ b/frontend/exporter/src/types/copied.rs @@ -2120,7 +2120,12 @@ pub enum LitKind { CStr(Vec, StrStyle), Byte(u8), Char(char), - Int(u128, LitIntType), + Int( + #[serde(with = "serialize_int::unsigned")] + #[schemars(with = "String")] + u128, + LitIntType, + ), Float(Symbol, LitFloatType), Bool(bool), Err(ErrorGuaranteed), diff --git a/frontend/exporter/src/types/mod.rs b/frontend/exporter/src/types/mod.rs index 00fbdd947..dfd080a17 100644 --- a/frontend/exporter/src/types/mod.rs +++ b/frontend/exporter/src/types/mod.rs @@ -8,6 +8,7 @@ mod mir; mod mir_traits; mod new; mod replaced; +pub(crate) mod serialize_int; mod todo; pub use copied::*; diff --git a/frontend/exporter/src/types/serialize_int.rs b/frontend/exporter/src/types/serialize_int.rs new file mode 100644 index 000000000..a026f7148 --- /dev/null +++ b/frontend/exporter/src/types/serialize_int.rs @@ -0,0 +1,91 @@ +use serde::{de::Visitor, ser::Serialize, Deserializer, Serializer}; + +pub mod unsigned { + use super::*; + pub fn serialize(value: &u128, serializer: S) -> Result + where + S: Serializer, + { + value.to_string().serialize(serializer) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_any(IntScalarVisitor) + } + + #[derive(Debug)] + struct IntScalarVisitor; + impl<'de> Visitor<'de> for IntScalarVisitor { + type Value = u128; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + dbg!(self); + formatter.write_str("expect to receive integer") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Ok(v.parse().map_err(serde::de::Error::custom)?) + } + + fn visit_u64(self, v: u64) -> Result + where + E: serde::de::Error, + { + Ok(v as u128) + } + } +} +pub mod signed { + use super::*; + pub fn serialize(value: &i128, serializer: S) -> Result + where + S: Serializer, + { + value.to_string().serialize(serializer) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_any(IntScalarVisitor) + } + + #[derive(Debug)] + struct IntScalarVisitor; + impl<'de> Visitor<'de> for IntScalarVisitor { + type Value = i128; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + dbg!(self); + formatter.write_str("expect to receive integer") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Ok(v.parse().map_err(serde::de::Error::custom)?) + } + + fn visit_u64(self, v: u64) -> Result + where + E: serde::de::Error, + { + Ok(v as i128) + } + + fn visit_i64(self, v: i64) -> Result + where + E: serde::de::Error, + { + Ok(v as i128) + } + } +} From df29fbee3cf62ed901d2fd90e0906c4cfdbf9293 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Sat, 29 Jun 2024 21:08:38 +0200 Subject: [PATCH 02/39] feat(frontend): diag: use `annotate_snippets` --- frontend/diagnostics/Cargo.toml | 3 +- frontend/diagnostics/src/lib.rs | 1 + frontend/diagnostics/src/report.rs | 94 ++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 frontend/diagnostics/src/report.rs diff --git a/frontend/diagnostics/Cargo.toml b/frontend/diagnostics/Cargo.toml index d506a5a64..ea8b56b17 100644 --- a/frontend/diagnostics/Cargo.toml +++ b/frontend/diagnostics/Cargo.toml @@ -16,4 +16,5 @@ rustc_private=true serde.workspace = true schemars.workspace = true colored.workspace = true - +annotate-snippets.workspace = true +hax-frontend-exporter.workspace = true diff --git a/frontend/diagnostics/src/lib.rs b/frontend/diagnostics/src/lib.rs index 5c7af4bd5..55fcc382c 100644 --- a/frontend/diagnostics/src/lib.rs +++ b/frontend/diagnostics/src/lib.rs @@ -24,6 +24,7 @@ impl SessionExtTrait for rustc_errors::DiagCtxt { } pub mod error; +pub mod report; #[derive(Debug, Clone, JsonSchema, Serialize, Deserialize)] pub struct Diagnostics { diff --git a/frontend/diagnostics/src/report.rs b/frontend/diagnostics/src/report.rs new file mode 100644 index 000000000..d875d58f3 --- /dev/null +++ b/frontend/diagnostics/src/report.rs @@ -0,0 +1,94 @@ +use super::Diagnostics; +use annotate_snippets::*; +use std::collections::HashMap; +use std::path::{Path, PathBuf}; +use std::rc::Rc; + +/// A context for reporting diagnostics +#[derive(Clone, Debug, Default)] +pub struct ReportCtx { + files: HashMap>, +} + +/// Translates ae line and column position into an absolute offset +fn compute_offset(src: &str, mut line: usize, col: usize) -> usize { + let mut chars = src.chars().enumerate(); + while line > 1 { + while let Some((_offset, ch)) = chars.next() { + if ch == '\n' { + break; + } + } + line -= 1; + } + let offset = chars + .clone() + .next() + .map(|(offset, _ch)| offset) + .unwrap_or(0); + let are_col_first_chars_blank = chars + .take(col) + .all(|(_offset, ch)| matches!(ch, ' ' | '\t')); + if are_col_first_chars_blank { + offset + } else { + offset + col + } +} + +impl ReportCtx { + /// Read the contents of a file. The result is cached. + fn file_contents<'a>(&'a mut self, path: PathBuf) -> Rc { + self.files + .entry(path.clone()) + .or_insert_with(|| { + let s = + std::fs::read_to_string(&path).expect(&format!("Unable to read file {path:?}")); + Rc::new(s) + }) + .clone() + } +} + +impl Diagnostics { + /// Converts a `Diagnostics` to a `annotate_snippets::Message`, + /// which can be accessed via `then`, a callback function. + pub fn with_message FnMut(Message<'a>) -> R>( + &self, + report_ctx: &mut ReportCtx, + working_dir: &Path, + level: Level, + mut then: F, + ) -> R { + let mut snippets_data = vec![]; + + for span in &self.span { + if let Some(path) = span.filename.to_path() { + let source = { + let mut path = path.to_path_buf(); + if path.is_relative() { + path = working_dir.join(&path); + }; + report_ctx.file_contents(path) + }; + let start = compute_offset(&source, span.lo.line, span.lo.col); + let end = compute_offset(&source, span.hi.line, span.hi.col); + let origin = format!("{}", path.display()); + snippets_data.push((source, origin, span.lo.line, start..end)); + }; + } + + let title = format!("[{}] {self}", self.kind.code()); + let message = level.title(&title).snippets(snippets_data.iter().map( + |(source, origin, line, range)| { + Snippet::source(source) + .line_start(*line) + .origin(&origin) + .fold(true) + .annotation(level.span(range.clone())) + }, + )); + + then(message) + } +} From bb15595e924e1c8204aafea742de54f2bfc5200f Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Sat, 29 Jun 2024 21:10:03 +0200 Subject: [PATCH 03/39] refactor(frontend): diag: get rid of generic spans --- cli/options/engine/src/lib.rs | 2 +- cli/subcommands/build.rs | 2 +- engine/lib/diagnostics.ml | 4 +-- frontend/diagnostics/src/lib.rs | 55 ++------------------------------- 4 files changed, 7 insertions(+), 56 deletions(-) diff --git a/cli/options/engine/src/lib.rs b/cli/options/engine/src/lib.rs index d48cc1e8c..ce6bdcb2d 100644 --- a/cli/options/engine/src/lib.rs +++ b/cli/options/engine/src/lib.rs @@ -22,7 +22,7 @@ pub struct File { #[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] pub struct Output { - pub diagnostics: Vec>>, + pub diagnostics: Vec, pub files: Vec, pub debug_json: Option, } diff --git a/cli/subcommands/build.rs b/cli/subcommands/build.rs index dfb5503eb..cfd3d569c 100644 --- a/cli/subcommands/build.rs +++ b/cli/subcommands/build.rs @@ -17,7 +17,7 @@ fn json_schema_static_asset() { let schema = schemars::schema_for!(( hax_frontend_exporter::Item, hax_cli_options::Options, - hax_diagnostics::Diagnostics, + hax_diagnostics::Diagnostics, hax_cli_options_engine::EngineOptions, hax_cli_options_engine::Output, hax_cli_options_engine::WithDefIds, diff --git a/engine/lib/diagnostics.ml b/engine/lib/diagnostics.ml index 6917cada1..fb7183858 100644 --- a/engine/lib/diagnostics.ml +++ b/engine/lib/diagnostics.ml @@ -90,7 +90,7 @@ let compare_thir_span (a : thir_span) (b : thir_span) = type t = { context : Context.t; kind : kind; span : thir_span list } [@@deriving show, eq, compare] -let to_thir_diagnostic (d : t) : Types.diagnostics_for__array_of__span = +let to_thir_diagnostic (d : t) : Types.diagnostics = { kind = d.kind; context = Context.display d.context; span = d.span } let run_hax_pretty_print_diagnostics (s : string) : string = @@ -101,7 +101,7 @@ let run_hax_pretty_print_diagnostics (s : string) : string = ^ ". Here is the JSON representation of the error that occurred:\n" ^ s let pretty_print : t -> string = - to_thir_diagnostic >> Types.to_json_diagnostics_for__array_of__span + to_thir_diagnostic >> Types.to_json_diagnostics >> Yojson.Safe.pretty_to_string >> run_hax_pretty_print_diagnostics let pretty_print_context_kind : Context.t -> kind -> string = diff --git a/frontend/diagnostics/src/lib.rs b/frontend/diagnostics/src/lib.rs index 55fcc382c..f06e57994 100644 --- a/frontend/diagnostics/src/lib.rs +++ b/frontend/diagnostics/src/lib.rs @@ -7,69 +7,20 @@ extern crate rustc_session; extern crate rustc_span; use colored::Colorize; -use rustc_error_messages::MultiSpan; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -pub trait SessionExtTrait { - fn span_hax_err + Clone>(&self, diag: Diagnostics); -} - -impl SessionExtTrait for rustc_errors::DiagCtxt { - fn span_hax_err + Clone>(&self, diag: Diagnostics) { - let span: MultiSpan = diag.span.clone().into(); - let diag = diag.set_span(span.clone()); - self.handle().span_err(span, diag.to_string()); - } -} - pub mod error; pub mod report; #[derive(Debug, Clone, JsonSchema, Serialize, Deserialize)] -pub struct Diagnostics { +pub struct Diagnostics { pub kind: Kind, - pub span: S, + pub span: Vec, pub context: String, } -impl Diagnostics { - pub fn set_span(&self, span: T) -> Diagnostics { - Diagnostics { - kind: self.kind.clone(), - context: self.context.clone(), - span, - } - } -} -impl + Clone> Diagnostics { - pub fn convert( - &self, - // exhaustive list of mapping from spans of type S to spans of type T - mapping: &Vec<(S, T)>, - ) -> Diagnostics> - where - for<'b> &'b S: PartialEq, - { - self.set_span( - self.span - .clone() - .into_iter() - .map(|span| { - mapping - .iter() - .filter(|(candidate, _)| candidate == &span) - .map(|(_, span)| span) - .max() - }) - .flatten() - .cloned() - .collect(), - ) - } -} - -impl std::fmt::Display for Diagnostics { +impl std::fmt::Display for Diagnostics { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "({}) ", self.context)?; match &self.kind { From 7d6db7773964c58b69ec3049b98901d1c55333fd Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Sat, 29 Jun 2024 22:35:26 +0200 Subject: [PATCH 04/39] feat(frontend): drop linter Fixes #611 Fixes #63 --- Cargo.toml | 3 - cli/driver/Cargo.toml | 1 - cli/driver/src/driver.rs | 11 - cli/driver/src/linter.rs | 38 -- cli/options/src/lib.rs | 1 - frontend/lint/Cargo.toml | 21 - frontend/lint/src/lib.rs | 860 --------------------------------------- 7 files changed, 935 deletions(-) delete mode 100644 cli/driver/src/linter.rs delete mode 100644 frontend/lint/Cargo.toml delete mode 100644 frontend/lint/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 6ed486c11..2a23fb67e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,6 @@ members = [ "frontend/exporter", "frontend/exporter/options", "frontend/diagnostics", - "frontend/lint", "cli/options", "cli/options/engine", "cli/subcommands", @@ -24,7 +23,6 @@ default-members = [ "frontend/exporter", "frontend/exporter/options", "frontend/diagnostics", - "frontend/lint", "cli/options", "cli/options/engine", "cli/subcommands", @@ -85,7 +83,6 @@ hax-cli-options = { path = "cli/options", version = "=0.1.0-pre.1" } hax-cli-options-engine = { path = "cli/options/engine", version = "=0.1.0-pre.1" } hax-frontend-exporter-options = { path = "frontend/exporter/options", version = "=0.1.0-pre.1" } hax-diagnostics = { path = "frontend/diagnostics", version = "=0.1.0-pre.1" } -hax-lint = { path = "frontend/lint", version = "=0.1.0-pre.1" } hax-phase-debug-webapp = { path = "engine/utils/phase-debug-webapp", version = "=0.1.0-pre.1" } hax-lib-macros-types = { path = "hax-lib-macros/types", version = "=0.1.0-pre.1" } hax-lib-macros = { path = "hax-lib-macros", version = "=0.1.0-pre.1" } diff --git a/cli/driver/Cargo.toml b/cli/driver/Cargo.toml index 0f33501ff..8858e6135 100644 --- a/cli/driver/Cargo.toml +++ b/cli/driver/Cargo.toml @@ -25,7 +25,6 @@ hax-frontend-exporter.workspace = true hax-cli-options.workspace = true hax-cli-options-engine.workspace = true hax-frontend-exporter-options.workspace = true -hax-lint.workspace = true hax-diagnostics.workspace = true hax-lib-macros-types.workspace = true itertools.workspace = true diff --git a/cli/driver/src/driver.rs b/cli/driver/src/driver.rs index c22e2dab9..2bb9ca5c3 100644 --- a/cli/driver/src/driver.rs +++ b/cli/driver/src/driver.rs @@ -30,10 +30,6 @@ mod exporter; use std::collections::HashSet; use exporter::ExtractionCallbacks; -use hax_lint::Type; - -mod linter; -use linter::LinterCallbacks; mod callbacks_wrapper; mod features; @@ -133,13 +129,6 @@ fn main() { command: command.clone(), macro_calls: std::collections::HashMap::new(), }), - Some(Command::LintCommand(command)) => { - let ltype = match command { - hax_cli_options::LinterCommand::Hacspec => Type::Hacspec, - hax_cli_options::LinterCommand::Rust => Type::Rust, - }; - Box::new(LinterCallbacks::new(ltype)) - } None => { // hacspec lint Box::new(LinterCallbacks::new(Type::Rust)) diff --git a/cli/driver/src/linter.rs b/cli/driver/src/linter.rs deleted file mode 100644 index eeb2e4d93..000000000 --- a/cli/driver/src/linter.rs +++ /dev/null @@ -1,38 +0,0 @@ -use hax_lint::Type; -use rustc_driver::{Callbacks, Compilation}; -use rustc_interface::{ - interface::{self, Compiler}, - Queries, -}; - -pub(crate) struct LinterCallbacks { - ltype: Type, -} - -impl LinterCallbacks { - pub(crate) fn new(ltype: Type) -> Self { - Self { ltype } - } -} - -impl Callbacks for LinterCallbacks { - fn after_crate_root_parsing<'tcx>( - &mut self, - _compiler: &Compiler, - queries: &'tcx Queries<'tcx>, - ) -> Compilation { - Compilation::Continue - } - fn after_expansion<'tcx>( - &mut self, - compiler: &Compiler, - queries: &'tcx Queries<'tcx>, - ) -> Compilation { - queries - .global_ctxt() - .unwrap() - .enter(|tcx| hax_lint::Linter::register(tcx, self.ltype)); - - Compilation::Continue - } -} diff --git a/cli/options/src/lib.rs b/cli/options/src/lib.rs index e99d5f7e3..d2c8e9ec4 100644 --- a/cli/options/src/lib.rs +++ b/cli/options/src/lib.rs @@ -446,7 +446,6 @@ impl NormalizePaths for Command { fn normalize_paths(&mut self) { match self { Command::ExporterCommand(cmd) => cmd.normalize_paths(), - _ => (), } } } diff --git a/frontend/lint/Cargo.toml b/frontend/lint/Cargo.toml deleted file mode 100644 index de8502be5..000000000 --- a/frontend/lint/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "hax-lint" -version.workspace = true -authors.workspace = true -license.workspace = true -homepage.workspace = true -edition.workspace = true -repository.workspace = true -readme.workspace = true - -[package.metadata.rust-analyzer] -rustc_private=true - -[dependencies] -hax-diagnostics.workspace = true -tracing.workspace = true - -[dev-dependencies] -regex = "1" -lazy_static = "1.4" -assert_cmd = "2.0" diff --git a/frontend/lint/src/lib.rs b/frontend/lint/src/lib.rs deleted file mode 100644 index 9b418ce7f..000000000 --- a/frontend/lint/src/lib.rs +++ /dev/null @@ -1,860 +0,0 @@ -#![feature(rustc_private)] - -// rustc middle -extern crate rustc_middle; -use hax_diagnostics::error; -use rustc_middle::hir::nested_filter::OnlyBodies; -use rustc_middle::ty::TyCtxt; - -// rustc errors -extern crate rustc_errors; -use rustc_errors::DiagCtxtHandle; - -// rustc hir -extern crate rustc_hir; - -use rustc_hir::{intravisit::*, *}; - -// rustc span -extern crate rustc_span; -use rustc_span::{def_id::LocalDefId, symbol::Ident, Span, Symbol}; - -// rustc data_structures -extern crate rustc_data_structures; - -// rustc ast -extern crate rustc_ast; -use rustc_ast::ast; - -#[derive(Debug, Clone, Copy)] -pub enum Type { - Rust, - Hacspec, -} - -pub struct Linter<'tcx> { - tcx: TyCtxt<'tcx>, - extern_allow_list: Vec<&'static str>, - trait_block_list: Vec, - ltype: Type, -} - -impl<'tcx> Linter<'tcx> { - /// Register the linter. - pub fn register(tcx: TyCtxt<'tcx>, ltype: Type) { - let hir = tcx.hir(); - - let trait_block_list = vec!["FnMut"]; - let trait_block_list = trait_block_list - .into_iter() - .map(|s| s.to_string()) - .collect(); - - let mut extern_allow_list = vec!["core", "alloc", "std"]; - if matches!(ltype, Type::Hacspec) { - extern_allow_list.append(&mut vec![ - "hacspec_lib", - "secret_integers", - "abstract_integers", - ]); - } - - let mut linter = Self { - tcx, - extern_allow_list, - trait_block_list, - ltype, - }; - hir.visit_all_item_likes_in_crate(&mut linter); - } - - fn dcx(&self) -> DiagCtxtHandle<'tcx> { - self.tcx.dcx() - } -} - -fn has_attr(attrs: &[ast::Attribute], symbol: Symbol) -> bool { - attrs.iter().any(|attr| attr.has_name(symbol)) -} - -macro_rules! skip_derived_non_local { - ($self:ident, $hir_id:expr) => { - if $self.any_parent_is_automatically_derived($hir_id) { - tracing::trace!(" skipping automatically derived code"); - return; - } - if $self.non_local_hir_id($hir_id) { - error::extern_crate($self.dcx(), $self.tcx.def_span($hir_id.owner)); - // Don't keep going - return; - } - }; -} - -macro_rules! skip_v1_lib_macros { - ($self:ident, $hir_id:expr) => { - if $self - .tcx - .def_span($hir_id.owner) - .macro_backtrace() - .any(|data| { - if let Some(parent) = data.parent_module { - tracing::trace!(" macro in {:?}", { data.parent_module }); - if $self.non_local_def_id(parent, $self.tcx.def_span($hir_id.owner)) { - return true; - } - } - false - }) - { - return; - } - }; -} - -impl<'v> Linter<'v> { - fn any_parent_has_attr(&self, hir_id: HirId, symbol: Symbol) -> bool { - let map = &self.tcx.hir(); - let mut prev_enclosing_node = None; - let mut enclosing_node = hir_id; - while Some(enclosing_node) != prev_enclosing_node { - if has_attr(map.attrs(enclosing_node), symbol) { - return true; - } - prev_enclosing_node = Some(enclosing_node); - enclosing_node = map.get_parent_item(enclosing_node).into(); - } - - false - } - - fn any_parent_is_automatically_derived(&self, hir_id: HirId) -> bool { - self.any_parent_has_attr(hir_id, rustc_span::symbol::sym::automatically_derived) - } - - /// Check and warn for non-local def ids. - /// - /// Returns true if the path is non-local. - fn non_local_def_id(&self, def_id: rustc_span::def_id::DefId, span: Span) -> bool { - if !def_id.is_local() { - tracing::trace!(" non local path at: {:?}", span); - - let krate = self.tcx.crate_name(def_id.krate); - tracing::trace!(" crate: {:?}", krate); - if self.extern_allow_list.contains(&krate.as_str()) { - // For the allow list we assume that there's a model - return true; - } - // On everything else we warn. - error::extern_crate(self.dcx(), span); - // } - return true; - } - false - } - - /// Check and warn for non-local paths. - /// - /// Returns true if the path is non-local. - fn non_local_path(&self, qpath: &QPath) -> bool { - match qpath { - QPath::Resolved(_, path) => match path.res { - def::Res::Def(_def_kind, def_id) => self.non_local_def_id(def_id, path.span), - _ => return false, - }, - _ => return false, - } - } - - /// Check and warn for non-local hir ids. - /// - /// Returns true if the path is non-local. - fn non_local_hir_id(&self, hir_id: HirId) -> bool { - if self.non_local_def_id(hir_id.owner.to_def_id(), self.tcx.def_span(hir_id.owner)) { - return true; - } - false - } -} - -impl<'v> Visitor<'v> for Linter<'v> { - type NestedFilter = OnlyBodies; - - fn nested_visit_map(&mut self) -> Self::Map { - tracing::trace!("visiting nested map"); - self.tcx.hir() - } - - fn visit_nested_trait_item(&mut self, id: TraitItemId) { - tracing::trace!("visiting nested trait item"); - - walk_trait_item(self, self.tcx.hir().trait_item(id)); - } - fn visit_nested_impl_item(&mut self, id: ImplItemId) { - tracing::trace!("visiting nested impl item"); - - walk_impl_item(self, self.tcx.hir().impl_item(id)); - } - fn visit_nested_foreign_item(&mut self, _id: ForeignItemId) { - tracing::trace!("visiting nested foreign item"); - } - fn visit_nested_body(&mut self, id: BodyId) { - tracing::trace!("visiting nested body"); - - walk_body(self, self.tcx.hir().body(id)); - } - - fn visit_item(&mut self, i: &'v Item<'v>) { - tracing::trace!("visiting item {:?} at {:?}", i.ident.name, i.span); - skip_derived_non_local!(self, i.hir_id()); - skip_v1_lib_macros!(self, i.hir_id()); - // tracing::trace!(" item kind: {:#?}", i.kind); - - match i.kind { - ItemKind::Union(_, _) => { - // TODO: This should be an error (span_err_with_code) - error::no_union(self.dcx(), i.span); - // self.no_union(i.span) - } - ItemKind::GlobalAsm(_) => error::no_unsafe(self.dcx(), i.span), - ItemKind::Impl(imp) => { - // tracing::trace!(" impl {:?}", imp.self_ty.kind); - if imp.safety == Safety::Unsafe { - error::no_unsafe(self.dcx(), i.span); - } - if let Some(of_trait) = &imp.of_trait { - let def_id = of_trait.hir_ref_id.owner.def_id.to_def_id(); - if self - .tcx - .has_attr(def_id, rustc_span::symbol::sym::automatically_derived) - { - tracing::trace!(" Skipping automatically derived implementations"); - return; - } - } - } - _ => (), - } - - // Check for foreign item - if self.non_local_def_id(i.owner_id.def_id.to_def_id(), i.span) { - // Don't keep walking. - return; - } - - // keep going - walk_item(self, i); - } - fn visit_body(&mut self, b: &Body<'v>) { - tracing::trace!("visiting body"); - skip_derived_non_local!(self, b.value.hir_id); - - // keep going - walk_body(self, b); - } - - /////////////// - - fn visit_id(&mut self, hir_id: HirId) { - tracing::trace!( - "visiting id {hir_id:?} from def path {:?}", - self.tcx.def_path(hir_id.owner.to_def_id()) - ); - - skip_derived_non_local!(self, hir_id); - skip_v1_lib_macros!(self, hir_id); - - // Nothing to do. - } - fn visit_name(&mut self, name: Symbol) { - tracing::trace!("visiting name {:?}", name); - // Nothing to do. - } - fn visit_ident(&mut self, ident: Ident) { - tracing::trace!("visiting ident {:?}", ident); - - // XXX: This really shouldn't be done here but earlier. - if ident.name.as_str() == "FnMut" { - error::no_fn_mut(self.dcx(), ident.span); - return; - } - - walk_ident(self, ident) - } - fn visit_mod(&mut self, m: &'v Mod<'v>, s: Span, n: HirId) { - tracing::trace!("visiting mod {:?}", s); - - // keep going - walk_mod(self, m, n); - } - fn visit_foreign_item(&mut self, i: &'v ForeignItem<'v>) { - tracing::trace!("visiting foreign item {:?} at {:?}", i.ident, i.span); - walk_foreign_item(self, i) - } - fn visit_local(&mut self, l: &'v LetStmt<'v>) { - tracing::trace!("visiting local {:?}", l.span); - walk_local(self, l) - } - fn visit_block(&mut self, b: &'v Block<'v>) { - tracing::trace!("visiting block {:?}", b.span); - - skip_derived_non_local!(self, b.hir_id); - - walk_block(self, b) - } - fn visit_stmt(&mut self, s: &'v Stmt<'v>) { - tracing::trace!( - "visiting stmt {:?} at {:?}", - self.tcx.opt_item_name(s.hir_id.owner.to_def_id()).unwrap(), - s.span - ); - skip_derived_non_local!(self, s.hir_id); - - match &s.kind { - StmtKind::Let(b) => { - // tracing::trace!(" local stmt"); - if let Some(init) = b.init { - match init.kind { - ExprKind::AddrOf(x, f, _s) => { - // Don't allow raw borrows (pointer) and mutable borrows. - if matches!(x, BorrowKind::Raw) || matches!(f, Mutability::Mut) { - error::mut_borrow_let(self.dcx(), b.span) - } - } - _ => (), - } - } - if let Some(_els) = b.els {} - } - StmtKind::Item(_) => (), // tracing::trace!(" item stmt"), - StmtKind::Expr(_) => (), // tracing::trace!(" expr stmt"), - StmtKind::Semi(_) => (), // tracing::trace!(" semi stmt"), - } - - // keep going - walk_stmt(self, s); - } - fn visit_arm(&mut self, a: &'v Arm<'v>) { - tracing::trace!("visiting arm {:?}", a.span); - walk_arm(self, a) - } - fn visit_pat(&mut self, p: &'v Pat<'v>) { - tracing::trace!("visiting pat {:?}", p.span); - walk_pat(self, p) - } - fn visit_pat_field(&mut self, f: &'v PatField<'v>) { - tracing::trace!("visiting pat field {:?} at {:?}", f.ident, f.span); - walk_pat_field(self, f) - } - fn visit_array_length(&mut self, len: &'v ArrayLen) { - tracing::trace!("visiting array length"); - walk_array_len(self, len) - } - fn visit_anon_const(&mut self, c: &'v AnonConst) { - tracing::trace!("visiting anon const"); - walk_anon_const(self, c) - } - fn visit_expr(&mut self, ex: &'v Expr<'v>) { - tracing::trace!("visiting expr {:?}", ex.span); - skip_derived_non_local!(self, ex.hir_id); - // tracing::trace!(" Node: {:#?}", self.tcx.hir().find(ex.hir_id)); - - // eprintln!(" kind: {:?}", ex.kind); - // eprintln!("expr at: {:?}", self.expr_span(ex)); - - match &ex.kind { - ExprKind::Block(block, _) => match block.rules { - BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => { - error::no_unsafe(self.dcx(), block.span) - } - _ => (), - }, - ExprKind::Loop(_block, _label, source, span) => match source { - LoopSource::Loop | LoopSource::While => error::unsupported_loop(self.dcx(), *span), - LoopSource::ForLoop => tracing::trace!("hir for loop"), - }, - // FIXME: where to get this from? - // ExprKind::Async(e, c, b) => self.no_async_await(b.span), - // ExprKind::Await(a) => self.no_async_await(a.span), - ExprKind::InlineAsm(p) => error::no_unsafe(self.dcx(), p.line_spans[0]), - ExprKind::Call(expr, _exprs) => { - // tracing::trace!("call: {:#?}", expr); - if self.tcx.is_foreign_item(expr.hir_id.owner.def_id) { - tracing::trace!("foreign call: {:#?}", expr.span); - } - } - ExprKind::MethodCall(_path, expr, _exprs, _span) => { - // tracing::trace!("method call: {:#?}", path); - if self.tcx.is_foreign_item(expr.hir_id.owner.def_id) { - tracing::trace!("foreign method call: {:#?}", expr.span); - } - } - ExprKind::Path(qpath) => { - if self.non_local_path(qpath) { - // Don't keep walking. - return; - } - } - _ => (), - } - - // keep going - walk_expr(self, ex); - } - fn visit_expr_field(&mut self, field: &'v ExprField<'v>) { - tracing::trace!("visiting expr field {:?}", field.ident); - walk_expr_field(self, field) - } - fn visit_ty(&mut self, t: &'v Ty<'v>) { - tracing::trace!("visiting ty {:?}", t.span); - walk_ty(self, t) - } - fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) { - tracing::trace!("visiting generic param {:?}", p.span); - tracing::trace!(" name: {:?}", p.name); - - walk_generic_param(self, p) - } - fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) { - tracing::trace!("visiting const param default"); - walk_const_param_default(self, ct) - } - fn visit_generics(&mut self, g: &'v Generics<'v>) { - tracing::trace!("visiting generics {:?}", g.span); - walk_generics(self, g) - } - fn visit_where_predicate(&mut self, predicate: &'v WherePredicate<'v>) { - tracing::trace!("visiting where predicate"); - - match predicate { - WherePredicate::BoundPredicate(p) => { - // tracing::trace!(" bound predicate {:#?}", p.bounds); - for bound in p.bounds { - match bound { - GenericBound::Trait(trait_ref, _bound_modifier) => { - tracing::trace!(" trait bound {:?}", trait_ref); - // tracing::trace!( - // " node {:#?}", - // self.tcx.hir().get(trait_ref.trait_ref.hir_ref_id) - // ); - } - _ => (), - } - } - } - WherePredicate::RegionPredicate(p) => error::explicit_lifetime(self.dcx(), p.span), - WherePredicate::EqPredicate(p) => { - tracing::trace!(" eq predicate {:?}/{:?}", p.lhs_ty, p.rhs_ty); - } - } - - // keep going - walk_where_predicate(self, predicate); - } - fn visit_fn_ret_ty(&mut self, ret_ty: &'v FnRetTy<'v>) { - tracing::trace!("visiting fn ret ty"); - walk_fn_ret_ty(self, ret_ty) - } - fn visit_fn_decl(&mut self, fd: &'v FnDecl<'v>) { - tracing::trace!("visiting fn decl"); - walk_fn_decl(self, fd) - } - fn visit_fn( - &mut self, - fk: FnKind<'v>, - fd: &'v FnDecl<'v>, - b: BodyId, - span: Span, - id: LocalDefId, - ) { - tracing::trace!("visiting fn at {:?}", span); - - let hir_id = self.tcx.local_def_id_to_hir_id(id); - - skip_derived_non_local!(self, hir_id); - skip_v1_lib_macros!(self, hir_id); - - fn check_ty_kind(visitor: &Linter, k: &TyKind, span: Span) { - match k { - TyKind::Ptr(_) => error::no_unsafe(visitor.dcx(), span), - TyKind::TraitObject(_, _, _) => { - error::no_trait_objects(visitor.dcx(), span); - } - TyKind::Ref(lifetime, ty) => { - // TODO: check lifetime. only allow anonymous - tracing::trace!(" lifetime {:?}", lifetime.ident); - // tracing::trace!(" ref ty {:#?}", ty); - - // check for mutable self. - // we have to do that here, because we know it's mut here. - if matches!(ty.mutbl, Mutability::Mut) { - if matches!(visitor.ltype, Type::Hacspec) { - // No mutability is allowed here for hacspec - error::no_mut(visitor.dcx(), ty.ty.span); - return; - } - match &ty.ty.kind { - TyKind::Path(path) => match path { - QPath::Resolved(_ty, p) => { - if p.segments[0].ident.as_str() == "Self" { - error::no_mut_self(visitor.dcx(), p.span) - } - } - _ => (), - }, - _ => (), - } - } - - check_ty_kind(visitor, &ty.ty.kind, span) - } - TyKind::OpaqueDef(_, _, _) => { - error::no_trait_objects(visitor.dcx(), span); - } - TyKind::Path(path) => match path { - QPath::Resolved(ty, p) => { - if let Some(ty) = ty { - check_ty_kind(visitor, &ty.kind, span) - } - - // check for trait objects (impl in the path) - if p.segments - .iter() - .any(|s| s.ident.to_string().contains("impl")) - { - error::no_trait_objects(visitor.dcx(), span); - } - } - QPath::TypeRelative(ty, _p) => check_ty_kind(visitor, &ty.kind, span), - QPath::LangItem(_lang_item, _span) => (), - }, - _ => (), - } - } - - match fk { - FnKind::ItemFn(ident, generics, header) => { - tracing::trace!(" ItemFn: {:?}", ident); - // TODO: All this should be an error (span_err_with_code) - // Unsafe functions - if header.safety == Safety::Unsafe { - error::no_unsafe(self.dcx(), span); - } - - // async functions - if let IsAsync::Async(_) = header.asyncness { - error::no_async_await(self.dcx(), span); - } - - // Check generics for lifetimes - for predicate in generics.predicates { - match &predicate { - WherePredicate::RegionPredicate(region) => { - error::explicit_lifetime(self.dcx(), region.span) - } - WherePredicate::BoundPredicate(bound) => { - for bound in bound.bounds { - match bound { - GenericBound::Trait(poly_ref, _modifier) => { - let path_string = poly_ref - .trait_ref - .path - .segments - .iter() - .map(|seg| seg.ident.as_str()) - .collect::>() - .join("::"); - tracing::trace!( - " trait implementation of {:?}", - path_string - ); - - if self.trait_block_list.contains(&path_string) { - error::unsupported_item( - self.dcx(), - poly_ref.span, - path_string, - ); - } - } - _ => (), - } - } - } - _ => (), - } - } - for param in generics.params { - match param.kind { - GenericParamKind::Lifetime { kind } => match kind { - LifetimeParamKind::Explicit => { - error::explicit_lifetime(self.dcx(), param.span) - } - _ => (), - }, - _ => (), - } - } - } - FnKind::Method(ident, sig) => { - tracing::trace!(" Method: {:?}", ident); - // TODO: All this should be an error (span_err_with_code) - // Unsafe functions - if sig.header.safety == Safety::Unsafe { - error::no_unsafe(self.dcx(), span); - } - - // async functions - if let IsAsync::Async(_) = sig.header.asyncness { - error::no_async_await(self.dcx(), span); - } - - // Check method input arguments - for input in sig.decl.inputs { - check_ty_kind(self, &input.kind, input.span); - } - } - FnKind::Closure => (), - } - fd.inputs.iter().for_each(|param| { - // // No dyn/trait object - // FIXME - // tracing::trace!("fd inputs {:#?}", param); - check_ty_kind(self, ¶m.kind, param.span); - }); - - // keep going - walk_fn(self, fk, fd, b, id); - } - fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) { - // FIXME - tracing::trace!("visiting use {:?}", path.span); - - // keep going - walk_use(self, path, hir_id); - } - fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) { - tracing::trace!("visiting trait item {:?} at {:?}", ti.ident.name, ti.span); - skip_derived_non_local!(self, ti.hir_id()); - - // match &ti.kind { - // TraitItemKind::Const(_, _) => self.no_assoc_items(ti.span), - // TraitItemKind::Type(_, _) => self.no_assoc_items(ti.span), - // TraitItemKind::Fn(bounds, ty) => (), - // } - - // keep going - walk_trait_item(self, ti); - } - fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) { - tracing::trace!("visiting trait item ref {:?} at {:?}", ii.ident, ii.span); - walk_trait_item_ref(self, ii) - } - fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) { - tracing::trace!("visiting impl item {:?} at {:?}", ii.ident.name, ii.span,); - skip_derived_non_local!(self, ii.hir_id()); - - // tracing::trace!(" item: {:#?}", ii); - - // Check the trait for this item. - for predicate in ii.generics.predicates { - match predicate { - WherePredicate::BoundPredicate(bound) => { - for bound in bound.bounds { - match bound { - GenericBound::Trait(_poly_ref, _modifier) => { - tracing::trace!(" Skipping trait bound"); - return; - } - _ => (), - } - } - } - _ => (), - } - } - - // /// Traversing an owner node recursively to the top. - // fn traverse_owner(tcx: &TyCtxt, owner_node: OwnerNode, mut ctr: usize) { - // if ctr > 3 { - // // limit recursion. I guess I don't understand this. - // return; - // } - // ctr += 1; - // match owner_node { - // OwnerNode::Item(item) => { - // tracing::trace!(" owner is an item {:?}", item.ident); - // traverse_owner(tcx, tcx.hir().owner(item.owner_id), ctr); - // } - // OwnerNode::ForeignItem(foreign_item) => { - // tracing::trace!(" owner is a foreign item {:?}", foreign_item.ident); - // traverse_owner(tcx, tcx.hir().owner(foreign_item.owner_id), ctr); - // } - // OwnerNode::TraitItem(trait_item) => { - // tracing::trace!(" owner is an item {:?}", trait_item.ident); - // traverse_owner(tcx, tcx.hir().owner(trait_item.owner_id), ctr); - // } - // OwnerNode::ImplItem(impl_item) => { - // tracing::trace!(" owner is an item {:?}", impl_item.ident); - // traverse_owner(tcx, tcx.hir().owner(impl_item.owner_id), ctr); - // } - // OwnerNode::Crate(mot) => tracing::trace!(" owner is an item"), - // } - // } - - // Check out the owner of this impl item, i.e. we want to know the trait - // traverse_owner(self.tcx, self.tcx.hir().owner(ii.owner_id), 0); - - // match &ii.kind { - // ImplItemKind::Const(_, _) => (), // tracing::trace!("impl const {:#?}", ii.ident), - // ImplItemKind::Type(_) => tracing::trace!("impl type {:#?}", ii.ident), - // ImplItemKind::Fn(bounds, ty) => tracing::trace!("impl fn {:#?}", ii.ident), - // } - - if self.non_local_def_id(ii.owner_id.def_id.to_def_id(), ii.span) { - // Don't keep walking. - return; - } - - // keep going - walk_impl_item(self, ii); - } - fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef) { - tracing::trace!("visiting foreign item ref {:?} at {:?}", ii.ident, ii.span); - walk_foreign_item_ref(self, ii) - } - fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) { - tracing::trace!("visiting impl item ref {:?} at {:?}", ii.ident, ii.span); - walk_impl_item_ref(self, ii) - } - fn visit_trait_ref(&mut self, t: &'v TraitRef<'v>) { - tracing::trace!("visiting trait ref"); - walk_trait_ref(self, t) - } - fn visit_param_bound(&mut self, bounds: &'v GenericBound<'v>) { - tracing::trace!("visiting param bound"); - walk_param_bound(self, bounds) - } - fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef<'v>) { - tracing::trace!("visiting poly trait ref {:?}", t.span); - walk_poly_trait_ref(self, t) - } - fn visit_variant_data(&mut self, s: &'v VariantData<'v>) { - tracing::trace!("visiting variant data"); - walk_struct_def(self, s) - } - fn visit_field_def(&mut self, s: &'v FieldDef<'v>) { - tracing::trace!("visiting field def {:?} at {:?}", s.ident, s.span); - walk_field_def(self, s) - } - fn visit_enum_def(&mut self, enum_definition: &'v EnumDef<'v>, item_id: HirId) { - tracing::trace!("visiting enum def"); - walk_enum_def(self, enum_definition, item_id) - } - fn visit_variant(&mut self, v: &'v Variant<'v>) { - tracing::trace!("visiting variant {:?} at {:?}", v.ident, v.span); - walk_variant(self, v) - } - fn visit_label(&mut self, label: &'v rustc_ast::ast::Label) { - tracing::trace!("visiting label {:?}", label.ident); - walk_label(self, label) - } - fn visit_infer(&mut self, inf: &'v InferArg) { - tracing::trace!("visiting infer {:?}", inf.span); - walk_inf(self, inf); - } - fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) { - tracing::trace!("visiting generic arg"); - walk_generic_arg(self, generic_arg); - } - fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { - tracing::trace!("visiting lifetime {:?}", lifetime.ident); - walk_lifetime(self, lifetime) - } - // The span is that of the surrounding type/pattern/expr/whatever. - fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, span: Span) { - tracing::trace!("visiting qpath {span:?}"); - skip_derived_non_local!(self, id); - - // Look for foreign paths - match qpath { - QPath::Resolved(_ty, path) => match path.res { - _ => (), - }, - QPath::TypeRelative(_ty, _path) => (), - QPath::LangItem(item, _span) => { - tracing::trace!(" language item {:?}", item); - } - } - - walk_qpath(self, qpath, id) - } - fn visit_path(&mut self, path: &Path<'v>, id: HirId) { - tracing::trace!("visiting path {:?}", path.span); - - skip_derived_non_local!(self, id); - skip_v1_lib_macros!(self, id); - // tracing::trace!(" node: {:?}", self.tcx.hir().find(id)); - // tracing::trace!(" path: {:?}", path); - - match path.res { - def::Res::Def(def_kind, def_id) => { - if !def_id.is_local() { - tracing::trace!(" non local path at: {:?}", path.span); - // self.extern_crate(path.span); - } - match def_kind { - def::DefKind::Fn => tracing::trace!(" path is Fn"), - def::DefKind::Trait => tracing::trace!(" path trait"), - _ => tracing::trace!(" path is def {:?}", def_kind), - } - } - _ => (), - } - - walk_path(self, path) - } - fn visit_path_segment(&mut self, path_segment: &'v PathSegment<'v>) { - tracing::trace!("visiting path segment {:?}", path_segment.ident); - skip_derived_non_local!(self, path_segment.hir_id); - walk_path_segment(self, path_segment) - } - fn visit_generic_args(&mut self, generic_args: &'v GenericArgs<'v>) { - tracing::trace!("visiting generic args {:?}", generic_args.span_ext); - walk_generic_args(self, generic_args) - } - fn visit_assoc_item_constraint(&mut self, constraint: &'v AssocItemConstraint<'v>) { - tracing::trace!("visiting assoc item constraint {:?}", constraint.span); - // self.no_assoc_items(type_binding.span); - - // keep going - walk_assoc_item_constraint(self, constraint); - } - fn visit_attribute(&mut self, attr: &'v rustc_ast::ast::Attribute) { - tracing::trace!("visiting attribute: {:?}", attr.span); - // match &attr.kind { - // ast::AttrKind::Normal(normal_attr) => { - // tracing::trace!("normal attribute: {:?}", normal_attr.item.path); - // } - // ast::AttrKind::DocComment(comment_kind, symbol) => (), - // } - } - fn visit_associated_item_kind(&mut self, kind: &'v AssocItemKind) { - tracing::trace!("visit assoc item kind {:?}", kind); - // self.no_assoc_items(self.span); - - // keep going - walk_associated_item_kind(self, kind); - } - fn visit_defaultness(&mut self, defaultness: &'v Defaultness) { - tracing::trace!("visiting defaultness"); - walk_defaultness(self, defaultness); - } - fn visit_inline_asm(&mut self, asm: &'v InlineAsm<'v>, _id: HirId) { - tracing::trace!("visiting inline asm"); - error::no_unsafe(self.dcx(), asm.line_spans[0]); // XXX: what's the right span here? - - // don't keep going - // walk_inline_asm(self, asm, id); - } -} From 4569547c34355746c8565360ea72b69a0ce52d68 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Sat, 29 Jun 2024 22:46:07 +0200 Subject: [PATCH 05/39] refactor(frontend): kill `ExporterCommand` indirection --- cli/driver/src/driver.rs | 9 ++++----- cli/options/src/lib.rs | 35 +++++------------------------------ 2 files changed, 9 insertions(+), 35 deletions(-) diff --git a/cli/driver/src/driver.rs b/cli/driver/src/driver.rs index 2bb9ca5c3..4b0aab708 100644 --- a/cli/driver/src/driver.rs +++ b/cli/driver/src/driver.rs @@ -37,7 +37,7 @@ use callbacks_wrapper::*; use features::*; use const_format::formatcp; -use hax_cli_options::{BackendOptions, Command, ExporterCommand, ENV_VAR_OPTIONS_FRONTEND}; +use hax_cli_options::{BackendOptions, Command, ENV_VAR_OPTIONS_FRONTEND}; use rustc_driver::{Callbacks, Compilation}; use rustc_interface::{interface, Queries}; @@ -160,10 +160,9 @@ fn main() { hax_lib_macros_types::HAX_CFG_OPTION_NAME.into(), ]) .chain(match &options.command { - Some(Command::ExporterCommand(ExporterCommand::Backend(BackendOptions { - backend, - .. - }))) => vec!["--cfg".into(), format!("hax_backend_{backend}")], + Command::Backend(BackendOptions { backend, .. }) => { + vec!["--cfg".into(), format!("hax_backend_{backend}")] + } _ => vec![], }) .chain(features.into_iter().map(|s| format!("-Zcrate-attr={}", s))) diff --git a/cli/options/src/lib.rs b/cli/options/src/lib.rs index d2c8e9ec4..7b17af268 100644 --- a/cli/options/src/lib.rs +++ b/cli/options/src/lib.rs @@ -328,7 +328,7 @@ pub struct BackendOptions { } #[derive(JsonSchema, Subcommand, Debug, Clone, Serialize, Deserialize)] -pub enum ExporterCommand { +pub enum Command { /// Translate to a backend. The translated modules will be written /// under the directory `/proofs//extraction`, where /// `` is the translated cargo package name and `` @@ -372,22 +372,6 @@ pub enum ExportBodyKind { MirBuilt, } -#[derive(JsonSchema, Subcommand, Debug, Clone, Serialize, Deserialize)] -pub enum LinterCommand { - /// Lint for the hacspec subset - Hacspec, - /// Lint for the supported Rust subset - Rust, -} - -#[derive(JsonSchema, Subcommand, Debug, Clone, Serialize, Deserialize)] -pub enum Command { - #[command(flatten)] - ExporterCommand(ExporterCommand), - #[clap(subcommand, name = "lint", about = "Lint the code")] - LintCommand(LinterCommand), -} - #[derive(JsonSchema, Parser, Debug, Clone, Serialize, Deserialize)] #[command(author, version = concat!("commit=", env!("HAX_GIT_COMMIT_HASH"), " ", "describe=", env!("HAX_GIT_DESCRIBE")), name = "hax", about, long_about = None)] pub struct Options { @@ -418,7 +402,7 @@ pub struct Options { pub cargo_flags: Vec, #[command(subcommand)] - pub command: Option, + pub command: Command, /// `cargo` caching is disabled by default, this flag enables it back. #[arg(long="enable-cargo-cache", action=clap::builder::ArgAction::SetTrue)] @@ -432,9 +416,9 @@ pub struct Options { pub deps: bool, } -impl NormalizePaths for ExporterCommand { +impl NormalizePaths for Command { fn normalize_paths(&mut self) { - use ExporterCommand::*; + use Command::*; match self { JSON { output_file, .. } => output_file.normalize_paths(), _ => (), @@ -442,18 +426,9 @@ impl NormalizePaths for ExporterCommand { } } -impl NormalizePaths for Command { - fn normalize_paths(&mut self) { - match self { - Command::ExporterCommand(cmd) => cmd.normalize_paths(), - } - } -} impl NormalizePaths for Options { fn normalize_paths(&mut self) { - if let Some(c) = &mut self.command { - c.normalize_paths() - } + self.command.normalize_paths() } } From d6d81896fcc55765f79da0c7e2455fb740186367 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Sat, 29 Jun 2024 22:48:34 +0200 Subject: [PATCH 06/39] refactor(front): run engine *after* rustc, not within --- Cargo.lock | 126 ++++--- Cargo.toml | 2 + cli/driver/Cargo.toml | 3 +- cli/driver/src/callbacks_wrapper.rs | 1 - cli/driver/src/driver.rs | 25 +- cli/driver/src/exporter.rs | 318 ++++------------- cli/options/engine/src/lib.rs | 63 ++++ cli/options/src/lib.rs | 9 + cli/subcommands/Cargo.toml | 7 + cli/subcommands/src/cargo_hax.rs | 324 ++++++++++++++++-- .../src/pretty_print_diagnostics.rs | 4 +- frontend/diagnostics/src/lib.rs | 1 - frontend/exporter/src/types/copied.rs | 29 ++ 13 files changed, 583 insertions(+), 329 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d72d8149a..e1b3d983d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "annotate-snippets" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991" +dependencies = [ + "anstyle", + "unicode-width", +] + [[package]] name = "anstream" version = "0.6.4" @@ -128,14 +138,19 @@ dependencies = [ name = "cargo-hax" version = "0.1.0-pre.1" dependencies = [ + "annotate-snippets", + "ciborium", "clap", "colored", + "const_format", "hax-cli-options", "hax-cli-options-engine", "hax-diagnostics", "hax-frontend-exporter", "hax-frontend-exporter-options", "hax-lib-macros-types", + "hax-phase-debug-webapp", + "inquire", "is-terminal", "itertools", "paste", @@ -175,12 +190,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "779e6b7d17797c0b42023d417228c02889300190e700cb074c3438d9c541d332" dependencies = [ "jobserver", "libc", + "once_cell", ] [[package]] @@ -195,6 +211,33 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cca491388666e04d7248af3f60f0c40cfb0991c72205595d7c396e3510207d1a" +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "clap" version = "4.4.6" @@ -226,7 +269,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.68", ] [[package]] @@ -309,6 +352,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "difflib" version = "0.4.0" @@ -366,7 +415,7 @@ checksum = "eecf8589574ce9b895052fa12d69af7a233f99e6107f5cb8dd1044f2a17bfdcb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.68", ] [[package]] @@ -433,6 +482,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.14.2" @@ -491,7 +550,9 @@ dependencies = [ name = "hax-diagnostics" version = "0.1.0-pre.1" dependencies = [ + "annotate-snippets", "colored", + "hax-frontend-exporter", "schemars", "serde", ] @@ -500,6 +561,7 @@ dependencies = [ name = "hax-driver" version = "0.1.0-pre.1" dependencies = [ + "ciborium", "clap", "colored", "const_format", @@ -509,9 +571,6 @@ dependencies = [ "hax-frontend-exporter", "hax-frontend-exporter-options", "hax-lib-macros-types", - "hax-lint", - "hax-phase-debug-webapp", - "inquire", "itertools", "serde", "serde_json", @@ -585,7 +644,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.68", ] [[package]] @@ -614,18 +673,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.38", -] - -[[package]] -name = "hax-lint" -version = "0.1.0-pre.1" -dependencies = [ - "assert_cmd", - "hax-diagnostics", - "lazy_static", - "regex", - "tracing", + "syn 2.0.68", ] [[package]] @@ -748,9 +796,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] @@ -943,9 +991,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "overload" @@ -1054,18 +1102,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -1237,7 +1285,7 @@ checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.68", ] [[package]] @@ -1341,9 +1389,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -1380,22 +1428,22 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.68", ] [[package]] @@ -1491,7 +1539,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.68", ] [[package]] @@ -1632,7 +1680,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.68", "wasm-bindgen-shared", ] @@ -1654,7 +1702,7 @@ checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index 2a23fb67e..9dbdfa5ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,6 +75,8 @@ quote = "1.0.32" proc-macro2 = "1.0.66" cargo_metadata = "0.15" colored = "2" +ciborium = "0.2" +annotate-snippets = "0.11" # Crates in this repository hax-frontend-exporter = { path = "frontend/exporter", version = "=0.1.0-pre.1" } diff --git a/cli/driver/Cargo.toml b/cli/driver/Cargo.toml index 8858e6135..0cd85f98d 100644 --- a/cli/driver/Cargo.toml +++ b/cli/driver/Cargo.toml @@ -29,9 +29,8 @@ hax-diagnostics.workspace = true hax-lib-macros-types.workspace = true itertools.workspace = true which.workspace = true -inquire = "0.6" const_format = "0.2" tracing.workspace = true tracing-subscriber.workspace = true tracing-tree.workspace = true -hax-phase-debug-webapp.workspace = true +ciborium.workspace = true diff --git a/cli/driver/src/callbacks_wrapper.rs b/cli/driver/src/callbacks_wrapper.rs index 209ded8a2..5ea731fde 100644 --- a/cli/driver/src/callbacks_wrapper.rs +++ b/cli/driver/src/callbacks_wrapper.rs @@ -1,4 +1,3 @@ -use const_format::formatcp; use hax_cli_options::{Command, ENV_VAR_OPTIONS_FRONTEND}; use rustc_driver::{Callbacks, Compilation}; diff --git a/cli/driver/src/driver.rs b/cli/driver/src/driver.rs index 4b0aab708..68cd36698 100644 --- a/cli/driver/src/driver.rs +++ b/cli/driver/src/driver.rs @@ -123,17 +123,11 @@ fn main() { let translate_package = !vanilla_rustc && !is_build_script && (options.deps || is_primary_package); let mut callbacks: Box = if translate_package { - match &options.command { - Some(Command::ExporterCommand(command)) => Box::new(exporter::ExtractionCallbacks { - inline_macro_calls: options.inline_macro_calls.clone(), - command: command.clone(), - macro_calls: std::collections::HashMap::new(), - }), - None => { - // hacspec lint - Box::new(LinterCallbacks::new(Type::Rust)) - } - } + Box::new(exporter::ExtractionCallbacks { + inline_macro_calls: options.inline_macro_calls.clone(), + body_types: options.command.body_kinds(), + macro_calls: std::collections::HashMap::new(), + }) } else { struct CallbacksNoop; impl Callbacks for CallbacksNoop {} @@ -172,13 +166,14 @@ fn main() { let mut callbacks = CallbacksWrapper { sub: &mut *callbacks, - options: hax_cli_options::Options { - force_cargo_build: if translate_package { + options: { + let mut options = options.clone(); + options.force_cargo_build = if translate_package { options.force_cargo_build } else { hax_cli_options::ForceCargoBuild::default() - }, - ..options + }; + options }, }; diff --git a/cli/driver/src/exporter.rs b/cli/driver/src/exporter.rs index 7a62fa8af..51f7a0bfc 100644 --- a/cli/driver/src/exporter.rs +++ b/cli/driver/src/exporter.rs @@ -17,41 +17,6 @@ use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use std::rc::Rc; -fn report_diagnostics( - tcx: TyCtxt<'_>, - output: &hax_cli_options_engine::Output, - mapping: &Vec<(hax_frontend_exporter::Span, rustc_span::Span)>, -) { - for d in &output.diagnostics { - use hax_diagnostics::*; - tcx.dcx().span_hax_err(d.convert(mapping).into()); - } -} - -fn write_files( - tcx: TyCtxt<'_>, - output: &hax_cli_options_engine::Output, - backend: hax_cli_options::Backend, -) { - let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); - let manifest_dir = std::path::Path::new(&manifest_dir); - let relative_path: std::path::PathBuf = ["proofs", format!("{backend}").as_str(), "extraction"] - .iter() - .collect(); - let out_dir = manifest_dir.join(&relative_path); - for file in output.files.clone() { - let path = out_dir.join(&file.path); - std::fs::create_dir_all(&path.parent().unwrap()).unwrap(); - tcx.dcx().note(format!("Writing file {:#?}", path)); - std::fs::write(&path, file.contents).unwrap_or_else(|e| { - tcx.dcx().fatal(format!( - "Unable to write to file {:#?}. Error: {:#?}", - path, e - )) - }) - } -} - type ThirBundle<'tcx> = (Rc>, ExprId); /// Generates a dummy THIR body with an error literal as first expression fn dummy_thir_body<'tcx>( @@ -216,69 +181,12 @@ fn collect_macros( v.macro_calls } -const ENGINE_BINARY_NAME: &str = "hax-engine"; -const ENGINE_BINARY_NOT_FOUND: &str = const_format::formatcp!( - "The binary [{}] was not found in your [PATH].", - ENGINE_BINARY_NAME, -); - -/// Dynamically looks for binary [ENGINE_BINARY_NAME]. First, we -/// check whether [HAX_ENGINE_BINARY] is set, and use that if it -/// is. Then, we try to find [ENGINE_BINARY_NAME] in PATH. If not -/// found, detect whether nodejs is available, download the JS-compiled -/// engine and use it. -use std::process; -fn find_hax_engine() -> process::Command { - use which::which; - - std::env::var("HAX_ENGINE_BINARY") - .ok() - .map(|name| process::Command::new(name)) - .or_else(|| { - which(ENGINE_BINARY_NAME) - .ok() - .map(|name| process::Command::new(name)) - }) - .or_else(|| { - which("node").ok().and_then(|_| { - if let Ok(true) = inquire::Confirm::new(&format!( - "{} Should I try to download it from GitHub?", - ENGINE_BINARY_NOT_FOUND, - )) - .with_default(true) - .prompt() - { - let cmd = process::Command::new("node"); - let engine_js_path: String = - panic!("TODO: Downloading from GitHub is not supported yet."); - cmd.arg(engine_js_path); - Some(cmd) - } else { - None - } - }) - }) - .unwrap_or_else(|| { - fn is_opam_setup_correctly() -> bool { - std::env::var("OPAM_SWITCH_PREFIX").is_ok() - } - use colored::Colorize; - eprintln!("\n{}\n{}\n\n{} {}\n", - &ENGINE_BINARY_NOT_FOUND, - "Please make sure the engine is installed and is in PATH!", - "Hint: With OPAM, `eval $(opam env)` is necessary for OPAM binaries to be in PATH: make sure to run `eval $(opam env)` before running `cargo hax`.".bright_black(), - format!("(diagnostics: {})", if is_opam_setup_correctly() { "opam seems okay ✓" } else {"opam seems not okay ❌"}).bright_black() - ); - panic!("{}", &ENGINE_BINARY_NOT_FOUND) - }) -} - /// Callback for extraction #[derive(Debug, Clone, Serialize)] pub(crate) struct ExtractionCallbacks { pub inline_macro_calls: Vec, - pub command: hax_cli_options::ExporterCommand, pub macro_calls: HashMap, + pub body_types: Vec, } impl From for hax_frontend_exporter_options::Options { @@ -318,170 +226,82 @@ impl Callbacks for ExtractionCallbacks { use std::ops::{Deref, DerefMut}; queries.global_ctxt().unwrap().enter(|tcx| { - use hax_cli_options::ExporterCommand; - match self.command.clone() { - ExporterCommand::JSON { - output_file, - mut kind, - include_extra, - } => { - struct Driver<'tcx> { - options: hax_frontend_exporter_options::Options, - macro_calls: - HashMap, - tcx: TyCtxt<'tcx>, - output_file: PathOrDash, - include_extra: bool, - } - impl<'tcx> Driver<'tcx> { - fn to_json(self) { - let (_, def_ids, impl_infos, converted_items) = convert_thir::( - &self.options, - self.macro_calls.clone(), - self.tcx, - ); + use hax_cli_options::Command; + use hax_frontend_exporter::ThirBody; + use rustc_session::config::CrateType; + use serde::{Deserialize, Serialize}; + use std::fs::File; + use std::io::BufWriter; - let dest = self.output_file.open_or_stdout(); - (if self.include_extra { - serde_json::to_writer( - dest, - &hax_cli_options_engine::WithDefIds { - def_ids, - impl_infos, - items: converted_items, - }, - ) - } else { - serde_json::to_writer(dest, &converted_items) - }) - .unwrap() - } - } - let driver = Driver { - options: self.clone().into(), - macro_calls: self.macro_calls.clone(), - tcx, - output_file, - include_extra, - }; - mod from { - pub use hax_cli_options::ExportBodyKind::{MirBuilt as MB, Thir as T}; - } - mod to { - pub type T = hax_frontend_exporter::ThirBody; - pub type MB = - hax_frontend_exporter::MirBody; - } - kind.sort(); - kind.dedup(); - match kind.as_slice() { - [from::MB] => driver.to_json::(), - [from::T] => driver.to_json::(), - [from::T, from::MB] => driver.to_json::<(to::MB, to::T)>(), - [] => driver.to_json::<()>(), - _ => panic!("Unsupported kind {:#?}", kind), - } - } - ExporterCommand::Backend(backend) => { - if matches!(backend.backend, Backend::Easycrypt | Backend::ProVerif(..)) { - eprintln!( - "⚠️ Warning: Experimental backend \"{}\" is work in progress.", - backend.backend - ) - } + use std::path::PathBuf; - let (spans, _def_ids, impl_infos, converted_items) = - convert_thir(&self.clone().into(), self.macro_calls.clone(), tcx); + let opts = &compiler.sess.opts; + let externs: Vec<_> = opts + .externs + .iter() + .flat_map(|(_, ext)| match &ext.location { + rustc_session::config::ExternLocation::ExactPaths(set) => set + .iter() + .map(|cp| cp.canonicalized()) + .collect::>() + .into_iter(), + _ => vec![].into_iter(), + }) + .map(|path| path.with_extension("haxmeta")) + .collect(); + + let cg_metadata = opts.cg.metadata[0].clone(); + let crate_name = opts.crate_name.clone().unwrap(); + let crate_type = match &opts.crate_types[..] { + [crate_type] => format!("{}", crate_type), + _ => panic!(), + }; + + let output_dir = compiler.sess.io.output_dir.clone().unwrap(); + let haxmeta_path = + output_dir.join(format!("{crate_type}{crate_name}-{cg_metadata}.haxmeta",)); + + let file = File::create(&haxmeta_path).unwrap(); - let engine_options = hax_cli_options_engine::EngineOptions { - backend: backend.clone(), - input: converted_items, + use hax_cli_options_engine::{with_kind_type, HaxMeta}; + with_kind_type!( + self.body_types.clone(), + || { + let (spans, def_ids, impl_infos, items) = + convert_thir(&self.clone().into(), self.macro_calls.clone(), tcx); + let haxmeta: HaxMeta = HaxMeta { + crate_name, + crate_type, + cg_metadata, + externs, impl_infos, + items, + def_ids, }; - let mut engine_subprocess = find_hax_engine() - .stdin(std::process::Stdio::piped()) - .stdout(std::process::Stdio::piped()) - .spawn() - .map_err(|e| { - if let std::io::ErrorKind::NotFound = e.kind() { - panic!( - "The binary [{}] was not found in your [PATH].", - ENGINE_BINARY_NAME - ) - } - e - }) - .unwrap(); + ciborium::into_writer(&haxmeta, BufWriter::new(file)).unwrap(); + } + ); - serde_json::to_writer::<_, hax_cli_options_engine::EngineOptions>( - std::io::BufWriter::new( - engine_subprocess - .stdin - .as_mut() - .expect("Could not write on stdin"), - ), - &engine_options, - ) - .unwrap(); + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let manifest_dir = std::path::Path::new(&manifest_dir); - let out = engine_subprocess.wait_with_output().unwrap(); - if !out.status.success() { - tcx.dcx().fatal(format!( - "{} exited with non-zero code {}\nstdout: {}\n stderr: {}", - ENGINE_BINARY_NAME, - out.status.code().unwrap_or(-1), - String::from_utf8(out.stdout).unwrap(), - String::from_utf8(out.stderr).unwrap(), - )); - return Compilation::Stop; - } - let output: hax_cli_options_engine::Output = - serde_json::from_slice(out.stdout.as_slice()).unwrap_or_else(|_| { - panic!( - "{} outputed incorrect JSON {}", - ENGINE_BINARY_NAME, - String::from_utf8(out.stdout).unwrap() - ) - }); - let options_frontend = - hax_frontend_exporter_options::Options::from(self.clone()); - let state = - hax_frontend_exporter::state::State::new(tcx, options_frontend.clone()); - report_diagnostics( - tcx, - &output, - &spans - .into_iter() - .map(|span| (span.sinto(&state), span.clone())) - .collect(), - ); - if backend.dry_run { - serde_json::to_writer(std::io::BufWriter::new(std::io::stdout()), &output) - .unwrap() - } else { - write_files(tcx, &output, backend.backend); - } - if let Some(debug_json) = &output.debug_json { - use hax_cli_options::DebugEngineMode; - match backend.debug_engine { - Some(DebugEngineMode::Interactive) => { - eprintln!("----------------------------------------------"); - eprintln!("----------------------------------------------"); - eprintln!("----------------------------------------------"); - eprintln!("-- Engine debug mode. Press CTRL+C to exit. --"); - eprintln!("----------------------------------------------"); - eprintln!("----------------------------------------------"); - eprintln!("----------------------------------------------"); - hax_phase_debug_webapp::run(|| debug_json.clone()) - } - Some(DebugEngineMode::File(file)) if !backend.dry_run => { - println!("{}", debug_json) - } - _ => (), - } - } - } + let data = hax_cli_options_engine::EmitHaxMetaMessage { + manifest_dir: manifest_dir.to_path_buf(), + working_dir: opts + .working_dir + .to_path(rustc_span::FileNameDisplayPreference::Local) + .to_path_buf(), + path: haxmeta_path, }; + eprintln!( + "{}{}", + hax_cli_options_engine::HAX_DRIVER_STDERR_PREFIX, + &serde_json::to_string(&hax_cli_options_engine::HaxDriverMessage::EmitHaxMeta( + data + )) + .unwrap() + ); + Compilation::Stop }) } diff --git a/cli/options/engine/src/lib.rs b/cli/options/engine/src/lib.rs index ce6bdcb2d..17e0da979 100644 --- a/cli/options/engine/src/lib.rs +++ b/cli/options/engine/src/lib.rs @@ -1,6 +1,7 @@ use hax_cli_options::*; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use std::path::PathBuf; type ThirBody = hax_frontend_exporter::ThirBody; @@ -38,3 +39,65 @@ pub struct WithDefIds { )>, pub items: Vec>, } + +pub const HAX_DRIVER_STDERR_PREFIX: &str = "::hax-driver::"; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct EmitHaxMetaMessage { + pub working_dir: PathBuf, + pub manifest_dir: PathBuf, + pub path: PathBuf, +} +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum HaxDriverMessage { + EmitHaxMeta(EmitHaxMetaMessage), +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct HaxMeta { + pub crate_name: String, + pub crate_type: String, + pub cg_metadata: String, + pub externs: Vec, + pub items: Vec>, + pub impl_infos: Vec<( + hax_frontend_exporter::DefId, + hax_frontend_exporter::ImplInfos, + )>, + pub def_ids: Vec, +} + +#[macro_export] +macro_rules! with_kind_type { + ($kind:expr, <$t:ident>|| $body:expr) => {{ + mod from { + pub use hax_cli_options::ExportBodyKind::{MirBuilt as MB, Thir as T}; + } + mod to { + pub type T = hax_frontend_exporter::ThirBody; + pub type MB = hax_frontend_exporter::MirBody; + } + let mut kind: Vec = $kind; + kind.sort(); + kind.dedup(); + match kind.as_slice() { + [from::MB] => { + type $t = to::MB; + $body + } + [from::T] => { + type $t = to::T; + $body + } + [from::T, from::MB] => { + type $t = (to::MB, to::T); + $body + } + [] => { + type $t = (); + $body + } + _ => panic!("Unsupported kind {:#?}", kind), + } + }}; +} diff --git a/cli/options/src/lib.rs b/cli/options/src/lib.rs index 7b17af268..5e8f867d3 100644 --- a/cli/options/src/lib.rs +++ b/cli/options/src/lib.rs @@ -364,6 +364,15 @@ pub enum Command { }, } +impl Command { + pub fn body_kinds(&self) -> Vec { + match self { + Command::JSON { kind, .. } => kind.clone(), + _ => vec![ExportBodyKind::Thir], + } + } +} + #[derive( JsonSchema, ValueEnum, Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, )] diff --git a/cli/subcommands/Cargo.toml b/cli/subcommands/Cargo.toml index 0f8e453f3..ebf83b473 100644 --- a/cli/subcommands/Cargo.toml +++ b/cli/subcommands/Cargo.toml @@ -30,8 +30,10 @@ itertools.workspace = true clap.workspace = true paste = "1.0.11" hax-cli-options.workspace = true +hax-frontend-exporter.workspace = true hax-frontend-exporter-options.workspace = true hax-diagnostics.workspace = true +hax-cli-options-engine.workspace = true path-clean = "1.0.1" tempfile = "3.8" which.workspace = true @@ -39,6 +41,11 @@ version_check = "0.9" rustup-toolchain = "0.1" colored.workspace = true is-terminal = "0.4.9" +hax-phase-debug-webapp.workspace = true +inquire = "0.6" +const_format = "0.2" +ciborium.workspace = true +annotate-snippets.workspace = true [build-dependencies] serde.workspace = true diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index 9fd4eff12..e551729c1 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -1,8 +1,13 @@ +use annotate_snippets::{Level, Message, Renderer}; use clap::Parser; use colored::Colorize; -use hax_cli_options::NormalizePaths; -use hax_cli_options::Options; -use std::process::Command; +use hax_cli_options::*; +use hax_cli_options_engine::*; +use is_terminal::IsTerminal; +use std::fs; +use std::io::BufRead; +use std::path::PathBuf; +use std::process; /// Return a toolchain argument to pass to `cargo`: when the correct nightly is /// already present, this is None, otherwise we (1) ensure `rustup` is available @@ -49,7 +54,6 @@ pub fn get_args(subcommand: &str) -> Vec { const RUST_LOG_STYLE: &str = "RUST_LOG_STYLE"; fn rust_log_style() -> String { std::env::var(RUST_LOG_STYLE).unwrap_or_else(|_| { - use is_terminal::IsTerminal; if std::io::stderr().is_terminal() { "always".to_string() } else { @@ -66,25 +70,305 @@ fn rustflags() -> String { [rustflags, "--cfg hax".into()].join(" ") } +const ENGINE_BINARY_NAME: &str = "hax-engine"; +const ENGINE_BINARY_NOT_FOUND: &str = const_format::formatcp!( + "The binary [{}] was not found in your [PATH].", + ENGINE_BINARY_NAME, +); + +/// Dynamically looks for binary [ENGINE_BINARY_NAME]. First, we +/// check whether [HAX_ENGINE_BINARY] is set, and use that if it +/// is. Then, we try to find [ENGINE_BINARY_NAME] in PATH. If not +/// found, detect whether nodejs is available, download the JS-compiled +/// engine and use it. +fn find_hax_engine() -> process::Command { + use which::which; + + std::env::var("HAX_ENGINE_BINARY") + .ok() + .map(|name| process::Command::new(name)) + .or_else(|| { + which(ENGINE_BINARY_NAME) + .ok() + .map(|name| process::Command::new(name)) + }) + .or_else(|| { + which("node").ok().and_then(|_| { + if let Ok(true) = inquire::Confirm::new(&format!( + "{} Should I try to download it from GitHub?", + ENGINE_BINARY_NOT_FOUND, + )) + .with_default(true) + .prompt() + { + let cmd = process::Command::new("node"); + let engine_js_path: String = + panic!("TODO: Downloading from GitHub is not supported yet."); + cmd.arg(engine_js_path); + Some(cmd) + } else { + None + } + }) + }) + .unwrap_or_else(|| { + fn is_opam_setup_correctly() -> bool { + std::env::var("OPAM_SWITCH_PREFIX").is_ok() + } + use colored::Colorize; + let message = format!("hax: {}\n{}\n\n{} {}\n", + &ENGINE_BINARY_NOT_FOUND, + "Please make sure the engine is installed and is in PATH!", + "Hint: With OPAM, `eval $(opam env)` is necessary for OPAM binaries to be in PATH: make sure to run `eval $(opam env)` before running `cargo hax`.".bright_black(), + format!("(diagnostics: {})", if is_opam_setup_correctly() { "opam seems okay ✓" } else {"opam seems not okay ❌"}).bright_black() + ); + report(Level::Error.title(&message)); + std::process::exit(2); + }) +} + +/// Report an `annotate_snippets::Message` now +fn report(message: Message) { + let renderer = Renderer::styled(); + eprintln!("{}", renderer.render(message)) +} + +/// Runs `hax-engine` +fn run_engine( + haxmeta: HaxMeta, + working_dir: PathBuf, + manifest_dir: PathBuf, + options: &Options, + backend: &BackendOptions, +) { + let engine_options = EngineOptions { + backend: backend.clone(), + input: haxmeta.items, + impl_infos: haxmeta.impl_infos, + }; + let mut engine_subprocess = find_hax_engine() + .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .spawn() + .map_err(|e| { + if let std::io::ErrorKind::NotFound = e.kind() { + panic!( + "The binary [{}] was not found in your [PATH].", + ENGINE_BINARY_NAME + ) + } + e + }) + .unwrap(); + + serde_json::to_writer::<_, EngineOptions>( + std::io::BufWriter::new( + engine_subprocess + .stdin + .as_mut() + .expect("Could not write on stdin"), + ), + &engine_options, + ) + .unwrap(); + let out = engine_subprocess.wait_with_output().unwrap(); + if !out.status.success() { + let title = format!( + "hax: {} exited with non-zero code {}\nstdout: {}\n stderr: {}", + ENGINE_BINARY_NAME, + out.status.code().unwrap_or(-1), + String::from_utf8(out.stdout).unwrap(), + String::from_utf8(out.stderr).unwrap(), + ); + report(Level::Error.title(&title)); + std::process::exit(1); + } + let output: Output = serde_json::from_slice(out.stdout.as_slice()).unwrap_or_else(|_| { + panic!( + "{} outputed incorrect JSON {}", + ENGINE_BINARY_NAME, + String::from_utf8(out.stdout).unwrap() + ) + }); + let options_frontend = Options::from(options.clone()); + + { + let mut rctx = hax_diagnostics::report::ReportCtx::default(); + for diag in &output.diagnostics { + diag.with_message(&mut rctx, &working_dir, Level::Error, report); + } + } + if backend.dry_run { + serde_json::to_writer(std::io::BufWriter::new(std::io::stdout()), &output).unwrap() + } else { + let relative_path: PathBuf = [ + "proofs", + format!("{}", backend.backend).as_str(), + "extraction", + ] + .iter() + .collect(); + let out_dir = manifest_dir.join(&relative_path); + for file in output.files.clone() { + let path = out_dir.join(&file.path); + std::fs::create_dir_all(&path.parent().unwrap()).unwrap(); + std::fs::write(&path, file.contents).unwrap(); + let title = format!("hax: wrote file {}", path.display()); + report(Level::Info.title(&title)) + } + } + if let Some(debug_json) = &output.debug_json { + use DebugEngineMode; + match &backend.debug_engine { + Some(DebugEngineMode::Interactive) => { + eprintln!("----------------------------------------------"); + eprintln!("----------------------------------------------"); + eprintln!("----------------------------------------------"); + eprintln!("-- Engine debug mode. Press CTRL+C to exit. --"); + eprintln!("----------------------------------------------"); + eprintln!("----------------------------------------------"); + eprintln!("----------------------------------------------"); + hax_phase_debug_webapp::run(|| debug_json.clone()) + } + Some(DebugEngineMode::File(file)) if !backend.dry_run => { + println!("{}", debug_json) + } + _ => (), + } + } +} + +/// Calls `cargo` with a custom driver which computes `haxmeta` files +/// in `TARGET`. One `haxmeta` file is produced by crate. Each +/// `haxmeta` file contains the full AST of one crate. +fn compute_haxmeta_files(options: &Options) -> (Vec, i32) { + let mut cmd = { + let mut cmd = process::Command::new("cargo"); + if let Some(toolchain) = toolchain() { + cmd.env("RUSTUP_TOOLCHAIN", toolchain); + } + cmd.args(["build".into()].iter().chain(options.cargo_flags.iter())); + const COLOR_FLAG: &str = "--color"; + let explicit_color_flag = options.cargo_flags.iter().any(|flag| flag == COLOR_FLAG); + if !explicit_color_flag && std::io::stderr().is_terminal() { + cmd.args([COLOR_FLAG, "always"]); + } + cmd.stderr(std::process::Stdio::piped()); + cmd.env( + "RUSTC_WORKSPACE_WRAPPER", + std::env::var("HAX_RUSTC_DRIVER_BINARY") + .unwrap_or("driver-hax-frontend-exporter".into()), + ) + .env(RUST_LOG_STYLE, rust_log_style()) + .env(RUSTFLAGS, rustflags()) + .env( + ENV_VAR_OPTIONS_FRONTEND, + serde_json::to_string(&options) + .expect("Options could not be converted to a JSON string"), + ); + cmd + }; + + let mut child = cmd.spawn().unwrap(); + let haxmeta_files = { + let mut haxmeta_files = vec![]; + let stderr = child.stderr.take().unwrap(); + let stderr = std::io::BufReader::new(stderr); + for line in std::io::BufReader::new(stderr).lines() { + if let Ok(line) = line { + if let Some(msg) = line.strip_prefix(HAX_DRIVER_STDERR_PREFIX) { + use HaxDriverMessage; + let msg = serde_json::from_str(msg).unwrap(); + match msg { + HaxDriverMessage::EmitHaxMeta(data) => haxmeta_files.push(data), + } + } else { + eprintln!("{}", line); + } + } + } + haxmeta_files + }; + + let status = child + .wait() + .expect("`driver-hax-frontend-exporter`: could not start?"); + + let exit_code = if !status.success() { + let title = format!("hax: running `cargo build` was not successful, continuing anyway."); + report(Level::Warning.title(&title)); + status.code().unwrap_or(254) + } else { + 0 + }; + (haxmeta_files, exit_code) +} + +/// Run the command given by the user +fn run_command(options: &Options, haxmeta_files: Vec) { + match options.command.clone() { + Command::JSON { + output_file, + kind, + include_extra, + .. + } => { + use {with_kind_type, HaxMeta}; + with_kind_type!(kind, || { + for EmitHaxMetaMessage { path, .. } in haxmeta_files { + let file = std::io::BufReader::new(fs::File::open(&path).unwrap()); + let haxmeta: HaxMeta = ciborium::from_reader(file).unwrap(); + let dest = output_file.open_or_stdout(); + (if include_extra { + serde_json::to_writer( + dest, + &WithDefIds { + def_ids: haxmeta.def_ids, + impl_infos: haxmeta.impl_infos, + items: haxmeta.items, + }, + ) + } else { + serde_json::to_writer(dest, &haxmeta.items) + }) + .unwrap() + } + }); + } + Command::Backend(backend) => { + use hax_frontend_exporter::ThirBody as Body; + use Backend; + + if matches!(backend.backend, Backend::Easycrypt | Backend::ProVerif(..)) { + let title = format!( + "hax: Experimental backend \"{}\" is work in progress.", + backend.backend + ); + report(Level::Warning.title(&title)) + } + + for EmitHaxMetaMessage { + working_dir, + manifest_dir, + path, + } in haxmeta_files + { + let file = std::io::BufReader::new(fs::File::open(&path).unwrap()); + let haxmeta: HaxMeta = ciborium::from_reader(file).unwrap(); + + run_engine(haxmeta, working_dir, manifest_dir, &options, &backend); + } + } + } +} + fn main() { let args: Vec = get_args("hax"); let mut options = Options::parse_from(args.iter()); options.normalize_paths(); - let mut cmd = Command::new("cargo"); - if let Some(toolchain) = toolchain() { - cmd.env("RUSTUP_TOOLCHAIN", toolchain); - } - cmd.args(["build".into()].iter().chain(options.cargo_flags.iter())); - cmd.env( - "RUSTC_WORKSPACE_WRAPPER", - std::env::var("HAX_RUSTC_DRIVER_BINARY").unwrap_or("driver-hax-frontend-exporter".into()), - ) - .env(RUST_LOG_STYLE, rust_log_style()) - .env(RUSTFLAGS, rustflags()) - .env( - hax_cli_options::ENV_VAR_OPTIONS_FRONTEND, - serde_json::to_string(&options).expect("Options could not be converted to a JSON string"), - ); - std::process::exit(cmd.spawn().unwrap().wait().unwrap().code().unwrap_or(254)) + let (haxmeta_files, exit_code) = compute_haxmeta_files(&options); + run_command(&options, haxmeta_files); + + std::process::exit(exit_code) } diff --git a/cli/subcommands/src/pretty_print_diagnostics.rs b/cli/subcommands/src/pretty_print_diagnostics.rs index 22c7c46a2..cd1755b5b 100644 --- a/cli/subcommands/src/pretty_print_diagnostics.rs +++ b/cli/subcommands/src/pretty_print_diagnostics.rs @@ -9,8 +9,8 @@ extern crate rustc_driver; use hax_diagnostics::Diagnostics as D; -use serde_json::{from_reader, Value}; +use serde_json::from_reader; fn main() { - println!("{}", from_reader::<_, D>(std::io::stdin()).unwrap()) + println!("{}", from_reader::<_, D>(std::io::stdin()).unwrap()) } diff --git a/frontend/diagnostics/src/lib.rs b/frontend/diagnostics/src/lib.rs index f06e57994..6105d9596 100644 --- a/frontend/diagnostics/src/lib.rs +++ b/frontend/diagnostics/src/lib.rs @@ -10,7 +10,6 @@ use colored::Colorize; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -pub mod error; pub mod report; #[derive(Debug, Clone, JsonSchema, Serialize, Deserialize)] diff --git a/frontend/exporter/src/types/copied.rs b/frontend/exporter/src/types/copied.rs index 51c10cb07..1ed39f821 100644 --- a/frontend/exporter/src/types/copied.rs +++ b/frontend/exporter/src/types/copied.rs @@ -986,6 +986,35 @@ pub enum FileName { InlineAsm(u64), } +impl FileName { + pub fn to_string(&self) -> String { + match self { + Self::Real(RealFileName::LocalPath(path)) + | Self::Real(RealFileName::Remapped { + local_path: Some(path), + .. + }) + | Self::Real(RealFileName::Remapped { + virtual_name: path, .. + }) => format!("{}", path.display()), + _ => format!("{:?}", self), + } + } + pub fn to_path(&self) -> Option<&std::path::Path> { + match self { + Self::Real(RealFileName::LocalPath(path)) + | Self::Real(RealFileName::Remapped { + local_path: Some(path), + .. + }) + | Self::Real(RealFileName::Remapped { + virtual_name: path, .. + }) => Some(path), + _ => None, + } + } +} + /// Reflects partially [`rustc_middle::ty::InferTy`] #[derive( AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, From 6b03d2737369aca142bb6c97774586dd25833d6d Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Sat, 29 Jun 2024 22:49:16 +0200 Subject: [PATCH 07/39] feat(cli): enable cargo cache by default, use `u64`, not `u128`s --- cli/options/src/lib.rs | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/cli/options/src/lib.rs b/cli/options/src/lib.rs index 5e8f867d3..5e4c52e98 100644 --- a/cli/options/src/lib.rs +++ b/cli/options/src/lib.rs @@ -21,27 +21,20 @@ impl std::convert::From<&str> for DebugEngineMode { } } -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize, Default)] pub struct ForceCargoBuild { - pub data: u128, -} - -impl std::default::Default for ForceCargoBuild { - fn default() -> Self { - ForceCargoBuild { data: 0 } - } + pub data: u64, } impl std::convert::From<&str> for ForceCargoBuild { fn from(s: &str) -> Self { use std::time::{SystemTime, UNIX_EPOCH}; if s == "false" { - ForceCargoBuild { - data: SystemTime::now() - .duration_since(UNIX_EPOCH) - .map(|r| r.as_millis()) - .unwrap_or(0), - } + let data = SystemTime::now() + .duration_since(UNIX_EPOCH) + .map(|r| r.as_millis()) + .unwrap_or(0); + ForceCargoBuild { data: data as u64 } } else { ForceCargoBuild::default() } @@ -413,8 +406,8 @@ pub struct Options { #[command(subcommand)] pub command: Command, - /// `cargo` caching is disabled by default, this flag enables it back. - #[arg(long="enable-cargo-cache", action=clap::builder::ArgAction::SetTrue)] + /// `cargo` caching is enable by default, this flag disables it. + #[arg(long="disable-cargo-cache", action=clap::builder::ArgAction::SetFalse)] pub force_cargo_build: ForceCargoBuild, /// Apply the command to every local package of the dependency closure. By From 5172e1bd1f0fdd4a721b781faff6aebb3e33f930 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Sat, 29 Jun 2024 23:55:41 +0200 Subject: [PATCH 08/39] refactor: kill `hax-cli-options[-engine]`&`hax-diagnostics`, intro `hax-types` --- Cargo.lock | 66 +++------ Cargo.toml | 12 +- PUBLISHING.md | 6 +- cli/driver/Cargo.toml | 4 +- cli/driver/src/callbacks_wrapper.rs | 6 +- cli/driver/src/driver.rs | 6 +- cli/driver/src/exporter.rs | 20 ++- cli/driver/src/features.rs | 2 +- cli/options/engine/Cargo.toml | 23 --- cli/subcommands/Cargo.toml | 8 +- cli/subcommands/build.rs | 10 +- cli/subcommands/src/cargo_hax.rs | 8 +- .../src/pretty_print_diagnostics.rs | 2 +- engine/names/Cargo.toml | 2 +- engine/names/extract/Cargo.toml | 1 - frontend/diagnostics/Cargo.toml | 20 --- frontend/diagnostics/src/error.rs | 131 ------------------ {cli/options => hax-types}/Cargo.toml | 14 +- hax-types/README.md | 8 ++ {cli/options => hax-types}/build.rs | 0 .../lib.rs => hax-types/src/cli_options.rs | 5 +- .../src/diagnostics/mod.rs | 5 +- .../src/diagnostics}/report.rs | 0 .../src/lib.rs => hax-types/src/driver_api.rs | 47 +------ hax-types/src/engine_api.rs | 39 ++++++ hax-types/src/lib.rs | 29 ++++ hax-types/src/prelude.rs | 3 + test-harness/Cargo.toml | 2 +- 28 files changed, 148 insertions(+), 331 deletions(-) delete mode 100644 cli/options/engine/Cargo.toml delete mode 100644 frontend/diagnostics/Cargo.toml delete mode 100644 frontend/diagnostics/src/error.rs rename {cli/options => hax-types}/Cargo.toml (72%) create mode 100644 hax-types/README.md rename {cli/options => hax-types}/build.rs (100%) rename cli/options/src/lib.rs => hax-types/src/cli_options.rs (99%) rename frontend/diagnostics/src/lib.rs => hax-types/src/diagnostics/mod.rs (98%) rename {frontend/diagnostics/src => hax-types/src/diagnostics}/report.rs (100%) rename cli/options/engine/src/lib.rs => hax-types/src/driver_api.rs (54%) create mode 100644 hax-types/src/engine_api.rs create mode 100644 hax-types/src/lib.rs create mode 100644 hax-types/src/prelude.rs diff --git a/Cargo.lock b/Cargo.lock index e1b3d983d..b17655e11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -143,13 +143,11 @@ dependencies = [ "clap", "colored", "const_format", - "hax-cli-options", - "hax-cli-options-engine", - "hax-diagnostics", "hax-frontend-exporter", "hax-frontend-exporter-options", "hax-lib-macros-types", "hax-phase-debug-webapp", + "hax-types", "inquire", "is-terminal", "itertools", @@ -518,45 +516,6 @@ dependencies = [ "paste", ] -[[package]] -name = "hax-cli-options" -version = "0.1.0-pre.1" -dependencies = [ - "clap", - "hax-frontend-exporter-options", - "path-clean", - "schemars", - "serde", - "serde_json", -] - -[[package]] -name = "hax-cli-options-engine" -version = "0.1.0-pre.1" -dependencies = [ - "clap", - "hax-cli-options", - "hax-diagnostics", - "hax-frontend-exporter", - "hax-frontend-exporter-options", - "itertools", - "path-clean", - "schemars", - "serde", - "serde_json", -] - -[[package]] -name = "hax-diagnostics" -version = "0.1.0-pre.1" -dependencies = [ - "annotate-snippets", - "colored", - "hax-frontend-exporter", - "schemars", - "serde", -] - [[package]] name = "hax-driver" version = "0.1.0-pre.1" @@ -565,12 +524,10 @@ dependencies = [ "clap", "colored", "const_format", - "hax-cli-options", - "hax-cli-options-engine", - "hax-diagnostics", "hax-frontend-exporter", "hax-frontend-exporter-options", "hax-lib-macros-types", + "hax-types", "itertools", "serde", "serde_json", @@ -594,7 +551,6 @@ version = "0.1.0-pre.1" dependencies = [ "camino", "cargo_metadata", - "hax-cli-options-engine", "hax-engine-names", "serde", "serde_json", @@ -690,7 +646,7 @@ dependencies = [ "assert_cmd", "cargo_metadata", "enum-iterator", - "hax-cli-options-engine", + "hax-types", "insta", "lazy_static", "libtest-mimic", @@ -699,6 +655,22 @@ dependencies = [ "serde_json", ] +[[package]] +name = "hax-types" +version = "0.1.0-pre.1" +dependencies = [ + "annotate-snippets", + "clap", + "colored", + "hax-frontend-exporter", + "hax-frontend-exporter-options", + "itertools", + "path-clean", + "schemars", + "serde", + "serde_json", +] + [[package]] name = "heck" version = "0.4.1" diff --git a/Cargo.toml b/Cargo.toml index 9dbdfa5ea..64500dd94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,9 +2,6 @@ members = [ "frontend/exporter", "frontend/exporter/options", - "frontend/diagnostics", - "cli/options", - "cli/options/engine", "cli/subcommands", "cli/driver", "test-harness", @@ -16,15 +13,12 @@ members = [ "hax-lib-protocol-macros", "hax-bounded-integers", "engine/names", - "engine/names/extract", + "engine/names/extract", "hax-types", ] exclude = ["tests"] default-members = [ "frontend/exporter", "frontend/exporter/options", - "frontend/diagnostics", - "cli/options", - "cli/options/engine", "cli/subcommands", "cli/driver", "test-harness", @@ -81,12 +75,10 @@ annotate-snippets = "0.11" # Crates in this repository hax-frontend-exporter = { path = "frontend/exporter", version = "=0.1.0-pre.1" } hax-adt-into = { path = "frontend/exporter/adt-into", version = "=0.1.0-pre.1" } -hax-cli-options = { path = "cli/options", version = "=0.1.0-pre.1" } -hax-cli-options-engine = { path = "cli/options/engine", version = "=0.1.0-pre.1" } hax-frontend-exporter-options = { path = "frontend/exporter/options", version = "=0.1.0-pre.1" } -hax-diagnostics = { path = "frontend/diagnostics", version = "=0.1.0-pre.1" } hax-phase-debug-webapp = { path = "engine/utils/phase-debug-webapp", version = "=0.1.0-pre.1" } hax-lib-macros-types = { path = "hax-lib-macros/types", version = "=0.1.0-pre.1" } hax-lib-macros = { path = "hax-lib-macros", version = "=0.1.0-pre.1" } hax-lib = { path = "hax-lib", version = "=0.1.0-pre.1" } hax-engine-names = { path = "engine/names", version = "=0.1.0-pre.1" } +hax-types = { path = "hax-types", version = "=0.1.0-pre.1" } diff --git a/PUBLISHING.md b/PUBLISHING.md index f8e46e624..ae1491466 100644 --- a/PUBLISHING.md +++ b/PUBLISHING.md @@ -14,10 +14,8 @@ and `examples`): 1. `hax-frontend-exporter-options` (`frontend/exporter/options `) 2. `hax-adt-into` (`frontend/exporter/adt-into`) 3. `hax-frontend-exporter` (`frontend/exporter`) -4. `hax-cli-options` (`cli/options`) -5. `hax-diagnostics` (`frontend/diagnostics`) -6. `hax-cli-options-engine` (`cli/options/engine`) -7. `hax-subcommands` (binaries) (`cli/subcommands`) +4. `hax-types` (`hax-types`) +5. `hax-subcommands` (binaries) (`cli/subcommands`) - `cargo-hax` - `hax-export-json-schemas` - `hax-pretty-print-diagnostics` diff --git a/cli/driver/Cargo.toml b/cli/driver/Cargo.toml index 0cd85f98d..fd68bc145 100644 --- a/cli/driver/Cargo.toml +++ b/cli/driver/Cargo.toml @@ -22,10 +22,8 @@ serde_json.workspace = true clap.workspace = true colored.workspace = true hax-frontend-exporter.workspace = true -hax-cli-options.workspace = true -hax-cli-options-engine.workspace = true +hax-types.workspace = true hax-frontend-exporter-options.workspace = true -hax-diagnostics.workspace = true hax-lib-macros-types.workspace = true itertools.workspace = true which.workspace = true diff --git a/cli/driver/src/callbacks_wrapper.rs b/cli/driver/src/callbacks_wrapper.rs index 5ea731fde..5a5bc28a1 100644 --- a/cli/driver/src/callbacks_wrapper.rs +++ b/cli/driver/src/callbacks_wrapper.rs @@ -1,4 +1,4 @@ -use hax_cli_options::{Command, ENV_VAR_OPTIONS_FRONTEND}; +use hax_types::cli_options::{Command, Options, ENV_VAR_OPTIONS_FRONTEND}; use rustc_driver::{Callbacks, Compilation}; use rustc_interface::{interface, Queries}; @@ -8,14 +8,14 @@ use rustc_span::symbol::Symbol; /// configuration in the `config` phase of rustc pub struct CallbacksWrapper<'a> { pub sub: &'a mut (dyn Callbacks + Send + 'a), - pub options: hax_cli_options::Options, + pub options: Options, } impl<'a> Callbacks for CallbacksWrapper<'a> { fn config(&mut self, config: &mut interface::Config) { let options = self.options.clone(); config.psess_created = Some(Box::new(move |parse_sess| { parse_sess.env_depinfo.get_mut().insert(( - Symbol::intern(hax_cli_options::ENV_VAR_OPTIONS_FRONTEND), + Symbol::intern(ENV_VAR_OPTIONS_FRONTEND), Some(Symbol::intern(&serde_json::to_string(&options).unwrap())), )); })); diff --git a/cli/driver/src/driver.rs b/cli/driver/src/driver.rs index 68cd36698..e576e7bc3 100644 --- a/cli/driver/src/driver.rs +++ b/cli/driver/src/driver.rs @@ -37,7 +37,7 @@ use callbacks_wrapper::*; use features::*; use const_format::formatcp; -use hax_cli_options::{BackendOptions, Command, ENV_VAR_OPTIONS_FRONTEND}; +use hax_types::cli_options::{BackendOptions, Command, ENV_VAR_OPTIONS_FRONTEND}; use rustc_driver::{Callbacks, Compilation}; use rustc_interface::{interface, Queries}; @@ -79,7 +79,7 @@ const HAX_VANILLA_RUSTC: &str = "HAX_VANILLA_RUSTC"; fn main() { setup_logging(); - let options: hax_cli_options::Options = + let options: hax_types::cli_options::Options = serde_json::from_str(&std::env::var(ENV_VAR_OPTIONS_FRONTEND).expect(&formatcp!( "Cannot find environnement variable {}", ENV_VAR_OPTIONS_FRONTEND @@ -171,7 +171,7 @@ fn main() { options.force_cargo_build = if translate_package { options.force_cargo_build } else { - hax_cli_options::ForceCargoBuild::default() + hax_types::cli_options::ForceCargoBuild::default() }; options }, diff --git a/cli/driver/src/exporter.rs b/cli/driver/src/exporter.rs index 51f7a0bfc..e5cb1a929 100644 --- a/cli/driver/src/exporter.rs +++ b/cli/driver/src/exporter.rs @@ -1,7 +1,7 @@ -use hax_cli_options::{Backend, PathOrDash, ENV_VAR_OPTIONS_FRONTEND}; use hax_frontend_exporter; use hax_frontend_exporter::state::{ExportedSpans, LocalContextS}; use hax_frontend_exporter::SInto; +use hax_types::cli_options::{Backend, PathOrDash, ENV_VAR_OPTIONS_FRONTEND}; use rustc_driver::{Callbacks, Compilation}; use rustc_interface::interface; use rustc_interface::{interface::Compiler, Queries}; @@ -184,9 +184,9 @@ fn collect_macros( /// Callback for extraction #[derive(Debug, Clone, Serialize)] pub(crate) struct ExtractionCallbacks { - pub inline_macro_calls: Vec, + pub inline_macro_calls: Vec, pub macro_calls: HashMap, - pub body_types: Vec, + pub body_types: Vec, } impl From for hax_frontend_exporter_options::Options { @@ -226,8 +226,8 @@ impl Callbacks for ExtractionCallbacks { use std::ops::{Deref, DerefMut}; queries.global_ctxt().unwrap().enter(|tcx| { - use hax_cli_options::Command; use hax_frontend_exporter::ThirBody; + use hax_types::cli_options::Command; use rustc_session::config::CrateType; use serde::{Deserialize, Serialize}; use std::fs::File; @@ -263,7 +263,7 @@ impl Callbacks for ExtractionCallbacks { let file = File::create(&haxmeta_path).unwrap(); - use hax_cli_options_engine::{with_kind_type, HaxMeta}; + use hax_types::driver_api::{with_kind_type, HaxMeta}; with_kind_type!( self.body_types.clone(), || { @@ -285,7 +285,7 @@ impl Callbacks for ExtractionCallbacks { let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); let manifest_dir = std::path::Path::new(&manifest_dir); - let data = hax_cli_options_engine::EmitHaxMetaMessage { + let data = hax_types::driver_api::EmitHaxMetaMessage { manifest_dir: manifest_dir.to_path_buf(), working_dir: opts .working_dir @@ -295,11 +295,9 @@ impl Callbacks for ExtractionCallbacks { }; eprintln!( "{}{}", - hax_cli_options_engine::HAX_DRIVER_STDERR_PREFIX, - &serde_json::to_string(&hax_cli_options_engine::HaxDriverMessage::EmitHaxMeta( - data - )) - .unwrap() + hax_types::driver_api::HAX_DRIVER_STDERR_PREFIX, + &serde_json::to_string(&hax_types::driver_api::HaxDriverMessage::EmitHaxMeta(data)) + .unwrap() ); Compilation::Stop diff --git a/cli/driver/src/features.rs b/cli/driver/src/features.rs index 8a2d65a1f..b29f854c1 100644 --- a/cli/driver/src/features.rs +++ b/cli/driver/src/features.rs @@ -78,7 +78,7 @@ impl Features { } /// Runs Rustc with a driver that only collects which unstable /// Rustc features are enabled - pub fn detect(options: &hax_cli_options::Options, rustc_args: &Vec) -> Self { + pub fn detect(options: &hax_types::cli_options::Options, rustc_args: &Vec) -> Self { struct CollectFeatures { features: Features, } diff --git a/cli/options/engine/Cargo.toml b/cli/options/engine/Cargo.toml deleted file mode 100644 index 2a649bb7b..000000000 --- a/cli/options/engine/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "hax-cli-options-engine" -version.workspace = true -authors.workspace = true -license.workspace = true -homepage.workspace = true -edition.workspace = true -repository.workspace = true -readme.workspace = true -description = "Defines the data type of the input of the engine. The (OCaml) engine reads JSON on stdin and deserializes the payload according to the JSON Schemas defined by this crate." - -[dependencies] -serde.workspace = true -serde_json.workspace = true -schemars.workspace = true -itertools.workspace = true -clap.workspace = true -hax-diagnostics.workspace = true -hax-cli-options.workspace = true -hax-frontend-exporter.workspace = true -hax-frontend-exporter-options.workspace = true -path-clean = "1.0.1" - diff --git a/cli/subcommands/Cargo.toml b/cli/subcommands/Cargo.toml index ebf83b473..d33a62a4e 100644 --- a/cli/subcommands/Cargo.toml +++ b/cli/subcommands/Cargo.toml @@ -29,11 +29,9 @@ schemars.workspace = true itertools.workspace = true clap.workspace = true paste = "1.0.11" -hax-cli-options.workspace = true hax-frontend-exporter.workspace = true hax-frontend-exporter-options.workspace = true -hax-diagnostics.workspace = true -hax-cli-options-engine.workspace = true +hax-types.workspace = true path-clean = "1.0.1" tempfile = "3.8" which.workspace = true @@ -50,11 +48,9 @@ annotate-snippets.workspace = true [build-dependencies] serde.workspace = true serde_json.workspace = true +hax-types.workspace = true schemars.workspace = true hax-frontend-exporter.workspace = true -hax-diagnostics.workspace = true -hax-cli-options.workspace = true -hax-cli-options-engine.workspace = true hax-lib-macros-types = {workspace = true, features = ["schemars"]} version_check = "0.9" toml = "0.8" diff --git a/cli/subcommands/build.rs b/cli/subcommands/build.rs index cfd3d569c..7f908d7ef 100644 --- a/cli/subcommands/build.rs +++ b/cli/subcommands/build.rs @@ -16,11 +16,11 @@ fn rustc_version_env_var() { fn json_schema_static_asset() { let schema = schemars::schema_for!(( hax_frontend_exporter::Item, - hax_cli_options::Options, - hax_diagnostics::Diagnostics, - hax_cli_options_engine::EngineOptions, - hax_cli_options_engine::Output, - hax_cli_options_engine::WithDefIds, + hax_types::cli_options::Options, + hax_types::diagnostics::Diagnostics, + hax_types::engine_api::EngineOptions, + hax_types::engine_api::Output, + hax_types::engine_api::WithDefIds, hax_lib_macros_types::AttrPayload, )); serde_json::to_writer( diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index e551729c1..706ad5587 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -1,8 +1,9 @@ use annotate_snippets::{Level, Message, Renderer}; use clap::Parser; use colored::Colorize; -use hax_cli_options::*; -use hax_cli_options_engine::*; +use hax_types::cli_options::*; +use hax_types::driver_api::*; +use hax_types::engine_api::*; use is_terminal::IsTerminal; use std::fs; use std::io::BufRead; @@ -193,7 +194,7 @@ fn run_engine( let options_frontend = Options::from(options.clone()); { - let mut rctx = hax_diagnostics::report::ReportCtx::default(); + let mut rctx = hax_types::diagnostics::report::ReportCtx::default(); for diag in &output.diagnostics { diag.with_message(&mut rctx, &working_dir, Level::Error, report); } @@ -313,7 +314,6 @@ fn run_command(options: &Options, haxmeta_files: Vec) { include_extra, .. } => { - use {with_kind_type, HaxMeta}; with_kind_type!(kind, || { for EmitHaxMetaMessage { path, .. } in haxmeta_files { let file = std::io::BufReader::new(fs::File::open(&path).unwrap()); diff --git a/cli/subcommands/src/pretty_print_diagnostics.rs b/cli/subcommands/src/pretty_print_diagnostics.rs index cd1755b5b..a4689db7a 100644 --- a/cli/subcommands/src/pretty_print_diagnostics.rs +++ b/cli/subcommands/src/pretty_print_diagnostics.rs @@ -8,7 +8,7 @@ #![feature(rustc_private)] extern crate rustc_driver; -use hax_diagnostics::Diagnostics as D; +use hax_types::diagnostics::Diagnostics as D; use serde_json::from_reader; fn main() { diff --git a/engine/names/Cargo.toml b/engine/names/Cargo.toml index 5213e4707..efc92fca6 100644 --- a/engine/names/Cargo.toml +++ b/engine/names/Cargo.toml @@ -11,4 +11,4 @@ description = "Dummy crate containing all the Rust names the hax engine should b [dependencies] hax-lib-protocol = {path = "../../hax-lib-protocol"} -hax-lib = {path = "../../hax-lib"} \ No newline at end of file +hax-lib = {path = "../../hax-lib"} diff --git a/engine/names/extract/Cargo.toml b/engine/names/extract/Cargo.toml index 3c845ec32..916319dd4 100644 --- a/engine/names/extract/Cargo.toml +++ b/engine/names/extract/Cargo.toml @@ -11,7 +11,6 @@ description = "Helper binary generating an OCaml module" [build-dependencies] -hax-cli-options-engine.workspace = true serde.workspace = true serde_json.workspace = true cargo_metadata.workspace = true diff --git a/frontend/diagnostics/Cargo.toml b/frontend/diagnostics/Cargo.toml deleted file mode 100644 index ea8b56b17..000000000 --- a/frontend/diagnostics/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "hax-diagnostics" -version.workspace = true -authors.workspace = true -license.workspace = true -homepage.workspace = true -edition.workspace = true -repository.workspace = true -readme.workspace = true -description = "This crate defines types that represent the various errors that can occur in hax." - -[package.metadata.rust-analyzer] -rustc_private=true - -[dependencies] -serde.workspace = true -schemars.workspace = true -colored.workspace = true -annotate-snippets.workspace = true -hax-frontend-exporter.workspace = true diff --git a/frontend/diagnostics/src/error.rs b/frontend/diagnostics/src/error.rs deleted file mode 100644 index 30c780149..000000000 --- a/frontend/diagnostics/src/error.rs +++ /dev/null @@ -1,131 +0,0 @@ -// rustc errors -extern crate rustc_errors; -use rustc_errors::DiagCtxtHandle; - -// rustc data_structures -extern crate rustc_data_structures; - -// rustc span -extern crate rustc_span; -use rustc_span::Span; - -fn warn_span_lint(dcx: DiagCtxtHandle<'_>, span: Span, msg: impl AsRef, lint_name: &str) { - let mut err = dcx.struct_warn(msg.as_ref().to_string()).with_span(span); - err.is_lint(lint_name.to_string(), /* has_future_breakage */ false); - err.emit(); -} - -pub fn explicit_lifetime(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint( - dcx, - span, - "[Hax] Explicit lifetimes are not supported", - "Lifetime", - ); -} - -pub fn mut_borrow_let(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint( - dcx, - span, - "[Hax] Mutable borrows are not supported", - "Mut borrow", - ); -} - -pub fn extern_crate(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint(dcx, span, "[Hax] External items need a model", "External"); -} - -pub fn no_trait_objects(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint( - dcx, - span, - "[Hax] Trait objects are not supported", - "Trait objects", - ); -} - -pub fn no_mut_self(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint( - dcx, - span, - "[Hax] Mutable self is not supported", - "Mutable self", - ); -} - -pub fn no_mut(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint( - dcx, - span, - "[Hax] Mutable arguments are not supported", - "Mutability", - ); -} - -pub fn no_assoc_items(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint( - dcx, - span, - "[Hax] Associated items are not supported", - "Assoc items", - ); -} - -pub fn unsupported_item(dcx: DiagCtxtHandle<'_>, span: Span, ident: String) { - warn_span_lint( - dcx, - span, - format!("[Hax] {ident:?} is not supported"), - "Unsupported item", - ); -} - -pub fn no_fn_mut(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint(dcx, span, "[Hax] FnMut is not supported", "Where"); -} - -pub fn no_where_predicate(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint( - dcx, - span, - "[Hax] Where predicates are not supported", - "Where", - ); -} - -pub fn no_async_await(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint( - dcx, - span, - "[Hax] Async and await are not supported", - "Async", - ); -} - -pub fn no_unsafe(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint(dcx, span, "[Hax] Unsafe code is not supported", "Unsafe"); -} - -pub fn unsupported_loop(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint(dcx, span, "[Hax] loop and while are not supported", "Loops"); -} - -pub fn no_union(dcx: DiagCtxtHandle<'_>, span: Span) { - warn_span_lint( - dcx, - span, - "[Hax] Unions are not supported", - "Unsupported item", - ); -} - -pub fn derive_external_trait(dcx: DiagCtxtHandle<'_>, span: Span, trait_name: String) { - warn_span_lint( - dcx, - span, - format!("[Hax] Implementation of external trait {trait_name} will require a model"), - "External trait", - ); -} diff --git a/cli/options/Cargo.toml b/hax-types/Cargo.toml similarity index 72% rename from cli/options/Cargo.toml rename to hax-types/Cargo.toml index f302e3f18..cbd7587ed 100644 --- a/cli/options/Cargo.toml +++ b/hax-types/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "hax-cli-options" +name = "hax-types" version.workspace = true authors.workspace = true license.workspace = true @@ -7,13 +7,15 @@ homepage.workspace = true edition.workspace = true repository.workspace = true readme.workspace = true -build = "build.rs" -description = "The CLI options read by the `cargo-hax` binary." [dependencies] -serde.workspace = true -serde_json.workspace = true -schemars.workspace = true clap.workspace = true +hax-frontend-exporter.workspace = true hax-frontend-exporter-options.workspace = true +itertools.workspace = true path-clean = "1.0.1" +schemars.workspace = true +serde.workspace = true +colored.workspace = true +serde_json.workspace = true +annotate-snippets.workspace = true \ No newline at end of file diff --git a/hax-types/README.md b/hax-types/README.md new file mode 100644 index 000000000..ee5f1fb81 --- /dev/null +++ b/hax-types/README.md @@ -0,0 +1,8 @@ +# `hax-types` +This crate contains the type definitions that are used to communicate between: + - the command line (the `cargo-hax` binary); + - the custom rustc driver; + - the hax engine (the `hax-engine` binary). + +Those three component send and receive messages in JSON or CBOR on +stdin and stdout. diff --git a/cli/options/build.rs b/hax-types/build.rs similarity index 100% rename from cli/options/build.rs rename to hax-types/build.rs diff --git a/cli/options/src/lib.rs b/hax-types/src/cli_options.rs similarity index 99% rename from cli/options/src/lib.rs rename to hax-types/src/cli_options.rs index 5e4c52e98..0815d88be 100644 --- a/cli/options/src/lib.rs +++ b/hax-types/src/cli_options.rs @@ -1,8 +1,7 @@ +use crate::prelude::*; + use clap::{Parser, Subcommand, ValueEnum}; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; use std::fmt; -use std::path::{Path, PathBuf}; pub use hax_frontend_exporter_options::*; diff --git a/frontend/diagnostics/src/lib.rs b/hax-types/src/diagnostics/mod.rs similarity index 98% rename from frontend/diagnostics/src/lib.rs rename to hax-types/src/diagnostics/mod.rs index 6105d9596..fb9ae699b 100644 --- a/frontend/diagnostics/src/lib.rs +++ b/hax-types/src/diagnostics/mod.rs @@ -1,14 +1,11 @@ -#![feature(rustc_private)] - extern crate rustc_driver; extern crate rustc_error_messages; extern crate rustc_errors; extern crate rustc_session; extern crate rustc_span; +use crate::prelude::*; use colored::Colorize; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; pub mod report; diff --git a/frontend/diagnostics/src/report.rs b/hax-types/src/diagnostics/report.rs similarity index 100% rename from frontend/diagnostics/src/report.rs rename to hax-types/src/diagnostics/report.rs diff --git a/cli/options/engine/src/lib.rs b/hax-types/src/driver_api.rs similarity index 54% rename from cli/options/engine/src/lib.rs rename to hax-types/src/driver_api.rs index 17e0da979..94b8af689 100644 --- a/cli/options/engine/src/lib.rs +++ b/hax-types/src/driver_api.rs @@ -1,44 +1,4 @@ -use hax_cli_options::*; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; -use std::path::PathBuf; - -type ThirBody = hax_frontend_exporter::ThirBody; - -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] -pub struct EngineOptions { - pub backend: BackendOptions, - pub input: Vec>, - pub impl_infos: Vec<( - hax_frontend_exporter::DefId, - hax_frontend_exporter::ImplInfos, - )>, -} - -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] -pub struct File { - pub path: String, - pub contents: String, -} - -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] -pub struct Output { - pub diagnostics: Vec, - pub files: Vec, - pub debug_json: Option, -} - -// This is located here for dependency reason, but this is not related -// to the engine (yet?). -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] -pub struct WithDefIds { - pub def_ids: Vec, - pub impl_infos: Vec<( - hax_frontend_exporter::DefId, - hax_frontend_exporter::ImplInfos, - )>, - pub items: Vec>, -} +use crate::prelude::*; pub const HAX_DRIVER_STDERR_PREFIX: &str = "::hax-driver::"; @@ -71,13 +31,13 @@ pub struct HaxMeta { macro_rules! with_kind_type { ($kind:expr, <$t:ident>|| $body:expr) => {{ mod from { - pub use hax_cli_options::ExportBodyKind::{MirBuilt as MB, Thir as T}; + pub use hax_types::cli_options::ExportBodyKind::{MirBuilt as MB, Thir as T}; } mod to { pub type T = hax_frontend_exporter::ThirBody; pub type MB = hax_frontend_exporter::MirBody; } - let mut kind: Vec = $kind; + let mut kind: Vec<::hax_types::cli_options::ExportBodyKind> = $kind; kind.sort(); kind.dedup(); match kind.as_slice() { @@ -101,3 +61,4 @@ macro_rules! with_kind_type { } }}; } +pub use with_kind_type; diff --git a/hax-types/src/engine_api.rs b/hax-types/src/engine_api.rs new file mode 100644 index 000000000..607087de5 --- /dev/null +++ b/hax-types/src/engine_api.rs @@ -0,0 +1,39 @@ +use crate::cli_options::*; +use crate::prelude::*; + +type ThirBody = hax_frontend_exporter::ThirBody; + +#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +pub struct EngineOptions { + pub backend: BackendOptions, + pub input: Vec>, + pub impl_infos: Vec<( + hax_frontend_exporter::DefId, + hax_frontend_exporter::ImplInfos, + )>, +} + +#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +pub struct File { + pub path: String, + pub contents: String, +} + +#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +pub struct Output { + pub diagnostics: Vec, + pub files: Vec, + pub debug_json: Option, +} + +// This is located here for dependency reason, but this is not related +// to the engine (yet?). +#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +pub struct WithDefIds { + pub def_ids: Vec, + pub impl_infos: Vec<( + hax_frontend_exporter::DefId, + hax_frontend_exporter::ImplInfos, + )>, + pub items: Vec>, +} diff --git a/hax-types/src/lib.rs b/hax-types/src/lib.rs new file mode 100644 index 000000000..9c58a0b73 --- /dev/null +++ b/hax-types/src/lib.rs @@ -0,0 +1,29 @@ +//! This crate contains the type definitions that are used to communicate between: +//! - the command line (the `cargo-hax` binary); +//! - the custom rustc driver; +//! - the hax engine (the `hax-engine` binary). +//! +//! Those three component send and receive messages in JSON or CBOR on +//! stdin and stdout. + +#![feature(rustc_private)] + +pub(crate) mod prelude; + +/// The CLI options for `cargo-hax`. The types defines in this module +/// are also used by the driver and the engine. +pub mod cli_options; + +/// Type to represent errors, mainly in `hax-engine`. The engine +/// doesn't do any reporting itself: it only sends JSON to its stdout, +/// and `cargo-hax` takes care of reporting everything in a rustc +/// style. +pub mod diagnostics; + +/// The types used to communicate between `cargo-hax` and the custom +/// driver. +pub mod driver_api; + +/// The types used to communicate between `cargo-hax` and +/// `hax-engine`. +pub mod engine_api; diff --git a/hax-types/src/prelude.rs b/hax-types/src/prelude.rs new file mode 100644 index 000000000..72a9e3818 --- /dev/null +++ b/hax-types/src/prelude.rs @@ -0,0 +1,3 @@ +pub use schemars::JsonSchema; +pub use serde::{Deserialize, Serialize}; +pub use std::path::{Path, PathBuf}; diff --git a/test-harness/Cargo.toml b/test-harness/Cargo.toml index 619bbd105..e0dbfe4ca 100644 --- a/test-harness/Cargo.toml +++ b/test-harness/Cargo.toml @@ -24,4 +24,4 @@ assert_cmd = "2.0" insta = {version = "1.29.0", features = ["filters", "toml"]} serde = { version = "1.0", features = ["derive"] } regex = "1" -hax-cli-options-engine.workspace = true +hax-types.workspace = true From ee3cfae41af7140b472c07b21c609b1a94bc2896 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Sun, 30 Jun 2024 17:30:11 +0200 Subject: [PATCH 09/39] refactor: `hax-engine` <-> `cargo-hax`: msg based communication --- Cargo.lock | 11 ++++ cli/subcommands/Cargo.toml | 1 + cli/subcommands/build.rs | 2 + cli/subcommands/src/cargo_hax.rs | 108 +++++++++++++++++++------------ engine/bin/js_driver.ml | 15 ++++- engine/bin/lib.ml | 21 +++--- engine/bin/lib.mli | 5 +- engine/bin/native_driver.ml | 21 +++++- engine/lib/hax_io.ml | 59 +++++++++++++++++ hax-types/src/engine_api.rs | 15 +++++ 10 files changed, 203 insertions(+), 55 deletions(-) create mode 100644 engine/lib/hax_io.ml diff --git a/Cargo.lock b/Cargo.lock index b17655e11..f53fd9b94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,6 +156,7 @@ dependencies = [ "rustup-toolchain", "schemars", "serde", + "serde-jsonlines", "serde_json", "tempfile", "toml 0.8.3", @@ -1249,6 +1250,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-jsonlines" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e228faf5f94badfe42723177b62cfb9b187351994cb4e852cd4a6a4c96dbeea8" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "serde_derive" version = "1.0.189" diff --git a/cli/subcommands/Cargo.toml b/cli/subcommands/Cargo.toml index d33a62a4e..f921dcb8c 100644 --- a/cli/subcommands/Cargo.toml +++ b/cli/subcommands/Cargo.toml @@ -44,6 +44,7 @@ inquire = "0.6" const_format = "0.2" ciborium.workspace = true annotate-snippets.workspace = true +serde-jsonlines = "0.5.0" [build-dependencies] serde.workspace = true diff --git a/cli/subcommands/build.rs b/cli/subcommands/build.rs index 7f908d7ef..224b4037c 100644 --- a/cli/subcommands/build.rs +++ b/cli/subcommands/build.rs @@ -21,6 +21,8 @@ fn json_schema_static_asset() { hax_types::engine_api::EngineOptions, hax_types::engine_api::Output, hax_types::engine_api::WithDefIds, + hax_types::engine_api::protocol::FromEngine, + hax_types::engine_api::protocol::ToEngine, hax_lib_macros_types::AttrPayload, )); serde_json::to_writer( diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index 706ad5587..f60b66a3a 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -5,8 +5,10 @@ use hax_types::cli_options::*; use hax_types::driver_api::*; use hax_types::engine_api::*; use is_terminal::IsTerminal; +use serde_jsonlines::BufReadExt; use std::fs; use std::io::BufRead; +use std::io::Write; use std::path::PathBuf; use std::process; @@ -162,61 +164,85 @@ fn run_engine( }) .unwrap(); - serde_json::to_writer::<_, EngineOptions>( - std::io::BufWriter::new( + let mut output = Output { + diagnostics: vec![], + files: vec![], + debug_json: None, + }; + { + let mut rctx = hax_types::diagnostics::report::ReportCtx::default(); + let mut stdin = std::io::BufWriter::new( engine_subprocess .stdin .as_mut() .expect("Could not write on stdin"), - ), - &engine_options, - ) - .unwrap(); - let out = engine_subprocess.wait_with_output().unwrap(); - if !out.status.success() { + ); + + macro_rules! send { + ($value:expr) => { + serde_json::to_writer(&mut stdin, $value).unwrap(); + stdin.write_all(b"\n").unwrap(); + stdin.flush().unwrap(); + }; + }; + + send!(&engine_options); + + let out_dir = { + let relative_path: PathBuf = [ + "proofs", + format!("{}", backend.backend).as_str(), + "extraction", + ] + .iter() + .collect(); + manifest_dir.join(&relative_path) + }; + + let stdout = std::io::BufReader::new(engine_subprocess.stdout.take().unwrap()); + for msg in stdout.json_lines() { + let msg = msg.unwrap(); + match msg { + protocol::FromEngine::Exit => break, + protocol::FromEngine::Diagnostic(diag) => { + if backend.dry_run { + output.diagnostics.push(diag.clone()) + } + diag.with_message(&mut rctx, &working_dir, Level::Error, report); + } + protocol::FromEngine::File(file) => { + if backend.dry_run { + output.files.push(file) + } else { + let path = out_dir.join(&file.path); + std::fs::create_dir_all(&path.parent().unwrap()).unwrap(); + std::fs::write(&path, file.contents).unwrap(); + let title = format!("hax: wrote file {}", path.display()); + report(Level::Info.title(&title)) + } + } + protocol::FromEngine::Ping => { + send!(&protocol::ToEngine::Pong); + } + } + } + drop(stdin); + } + + let exit_status = engine_subprocess.wait().unwrap(); + if !exit_status.success() { let title = format!( - "hax: {} exited with non-zero code {}\nstdout: {}\n stderr: {}", + "hax: {} exited with non-zero code {}", ENGINE_BINARY_NAME, - out.status.code().unwrap_or(-1), - String::from_utf8(out.stdout).unwrap(), - String::from_utf8(out.stderr).unwrap(), + exit_status.code().unwrap_or(-1), ); report(Level::Error.title(&title)); std::process::exit(1); } - let output: Output = serde_json::from_slice(out.stdout.as_slice()).unwrap_or_else(|_| { - panic!( - "{} outputed incorrect JSON {}", - ENGINE_BINARY_NAME, - String::from_utf8(out.stdout).unwrap() - ) - }); let options_frontend = Options::from(options.clone()); - { - let mut rctx = hax_types::diagnostics::report::ReportCtx::default(); - for diag in &output.diagnostics { - diag.with_message(&mut rctx, &working_dir, Level::Error, report); - } - } if backend.dry_run { serde_json::to_writer(std::io::BufWriter::new(std::io::stdout()), &output).unwrap() - } else { - let relative_path: PathBuf = [ - "proofs", - format!("{}", backend.backend).as_str(), - "extraction", - ] - .iter() - .collect(); - let out_dir = manifest_dir.join(&relative_path); - for file in output.files.clone() { - let path = out_dir.join(&file.path); - std::fs::create_dir_all(&path.parent().unwrap()).unwrap(); - std::fs::write(&path, file.contents).unwrap(); - let title = format!("hax: wrote file {}", path.display()); - report(Level::Info.title(&title)) - } } if let Some(debug_json) = &output.debug_json { use DebugEngineMode; diff --git a/engine/bin/js_driver.ml b/engine/bin/js_driver.ml index 0030ada16..ce0ad7a7e 100644 --- a/engine/bin/js_driver.ml +++ b/engine/bin/js_driver.ml @@ -82,4 +82,17 @@ let yojson_of_string_via_js (s : string) : Yojson.Safe.t = in fun_call fn [| string s |> coerce |] |> Obj.magic -let _ = Lib.main (Lib.read_options_from_stdin yojson_of_string_via_js) +let _ = + Hax_engine.Hax_io.init + (module struct + let read_json () = + let line = Stdio.In_channel.input_line Stdio.In_channel.stdin in + Option.map ~f:yojson_of_string_via_js line + + let write_json msg = + let open Stdio.Out_channel in + Yojson.Safe.to_channel stdout msg; + output_char stdout '\n'; + flush stdout + end); + Lib.main () diff --git a/engine/bin/lib.ml b/engine/bin/lib.ml index 497ac3488..e66af48e4 100644 --- a/engine/bin/lib.ml +++ b/engine/bin/lib.ml @@ -2,11 +2,6 @@ open Hax_engine open Base open Stdio -let read_options_from_stdin (yojson_from_string : string -> Yojson.Safe.t) : - Types.engine_options = - In_channel.input_all In_channel.stdin - |> yojson_from_string |> Types.parse_engine_options - let setup_logs (options : Types.engine_options) = let level : Logs.level option = match options.backend.verbose with @@ -131,7 +126,11 @@ let run (options : Types.engine_options) : Types.output = debug_json = None; } -let main (options : Types.engine_options) = +(** Entrypoint of the engine. Assumes `Hax_io.init` was called. *) +let main () = + let options = + Hax_io.read_json () |> Option.value_exn |> Types.parse_engine_options + in Printexc.record_backtrace true; let result = try Ok (run options) with @@ -149,8 +148,14 @@ let main (options : Types.engine_options) = let debug_json = Phase_utils.DebugBindPhase.export () in let results = { results with debug_json } in Logs.info (fun m -> m "Outputting JSON"); - Types.to_json_output results - |> Yojson.Safe.pretty_to_string |> print_endline; + + List.iter + ~f:(fun diag -> Diagnostic diag |> Hax_io.write) + results.diagnostics; + List.iter ~f:(fun file -> File file |> Hax_io.write) results.files; + + Hax_io.close (); + Logs.info (fun m -> m "Exiting Hax engine (success)") | Error (exn, bt) -> Logs.info (fun m -> m "Exiting Hax engine (with an unexpected failure)"); diff --git a/engine/bin/lib.mli b/engine/bin/lib.mli index 4311817b8..86f37aa4f 100644 --- a/engine/bin/lib.mli +++ b/engine/bin/lib.mli @@ -1,4 +1 @@ -val read_options_from_stdin : - (string -> Yojson.Safe.t) -> Hax_engine.Types.engine_options - -val main : Hax_engine.Types.engine_options -> unit +val main : unit -> unit diff --git a/engine/bin/native_driver.ml b/engine/bin/native_driver.ml index 8e74b1bbd..221ea9fdd 100644 --- a/engine/bin/native_driver.ml +++ b/engine/bin/native_driver.ml @@ -1,4 +1,23 @@ open Hax_engine open Base -let _ = Lib.main (Lib.read_options_from_stdin Yojson.Safe.from_string) +let _ = + Hax_io.init + (module struct + let stdin_json_stream = + ref (Yojson.Safe.seq_from_channel In_channel.stdin) + + let read_json () = + match Stdlib.Seq.uncons !stdin_json_stream with + | Some (json, stream) -> + stdin_json_stream := stream; + Some json + | None -> None + + let write_json msg = + let open Stdio.Out_channel in + Yojson.Safe.to_channel stdout msg; + output_char stdout '\n'; + flush stdout + end); + Lib.main () diff --git a/engine/lib/hax_io.ml b/engine/lib/hax_io.ml new file mode 100644 index 000000000..af50a0615 --- /dev/null +++ b/engine/lib/hax_io.ml @@ -0,0 +1,59 @@ +open Prelude + +module type S = sig + val read_json : unit -> Yojson.Safe.t option + val write_json : Yojson.Safe.t -> unit +end + +include ( + struct + (** Contains the module *) + let state = ref None + + let init (module M : S) = state := Some (module M : S) + + let get () : (module S) = + !state + |> Option.value_exn + ~message:"Hax engine: internal error: Hax_io as not initialized" + + let read_json () = + let (module M) = get () in + M.read_json () + + let write_json json = + let (module M) = get () in + M.write_json json + end : + sig + include S + + val init : (module S) -> unit + end) + +let read () : Types.to_engine = + read_json () |> Option.value_exn |> Types.parse_to_engine + +let write (msg : Types.from_engine) : unit = + Types.to_json_from_engine msg |> write_json + +let close () : unit = + write Exit; + (* Ensure no garbadge collect *) + let _ = read_json () in + () + +let request (type a) ~expected (msg : Types.from_engine) + (filter : Types.to_engine -> a option) : a = + write msg; + let response = read () in + match filter response with + | Some value -> value + | None -> + let error = + "Internal error: communication protocol error between `hax-engine` and \ + `cargo-hax`. Expected `" ^ expected ^ "`, got `" + ^ [%show: Types.to_engine] response + ^ "` instead." + in + failwith error diff --git a/hax-types/src/engine_api.rs b/hax-types/src/engine_api.rs index 607087de5..5640af140 100644 --- a/hax-types/src/engine_api.rs +++ b/hax-types/src/engine_api.rs @@ -26,6 +26,21 @@ pub struct Output { pub debug_json: Option, } +pub mod protocol { + use super::*; + #[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] + pub enum FromEngine { + Diagnostic(crate::diagnostics::Diagnostics), + File(File), + Exit, + Ping, + } + #[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] + pub enum ToEngine { + Pong, + } +} + // This is located here for dependency reason, but this is not related // to the engine (yet?). #[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] From 7818b07706c1ec476d5e5dbd690055f75ac5c4e5 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Sun, 30 Jun 2024 17:50:28 +0200 Subject: [PATCH 10/39] feat: use msg instead of binary pretty_print_diagnostics --- cli/subcommands/Cargo.toml | 4 ---- cli/subcommands/src/cargo_hax.rs | 14 +++++++++----- cli/subcommands/src/pretty_print_diagnostics.rs | 16 ---------------- engine/lib/diagnostics.ml | 15 +++++++-------- hax-types/src/engine_api.rs | 2 ++ 5 files changed, 18 insertions(+), 33 deletions(-) delete mode 100644 cli/subcommands/src/pretty_print_diagnostics.rs diff --git a/cli/subcommands/Cargo.toml b/cli/subcommands/Cargo.toml index f921dcb8c..0caf29a05 100644 --- a/cli/subcommands/Cargo.toml +++ b/cli/subcommands/Cargo.toml @@ -18,10 +18,6 @@ name = "cargo-hax" path = "src/json_schema.rs" name = "hax-export-json-schemas" -[[bin]] -path = "src/pretty_print_diagnostics.rs" -name = "hax-pretty-print-diagnostics" - [dependencies] serde.workspace = true serde_json.workspace = true diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index f60b66a3a..1ce678e89 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -202,15 +202,16 @@ fn run_engine( let stdout = std::io::BufReader::new(engine_subprocess.stdout.take().unwrap()); for msg in stdout.json_lines() { let msg = msg.unwrap(); + use protocol::*; match msg { - protocol::FromEngine::Exit => break, - protocol::FromEngine::Diagnostic(diag) => { + FromEngine::Exit => break, + FromEngine::Diagnostic(diag) => { if backend.dry_run { output.diagnostics.push(diag.clone()) } diag.with_message(&mut rctx, &working_dir, Level::Error, report); } - protocol::FromEngine::File(file) => { + FromEngine::File(file) => { if backend.dry_run { output.files.push(file) } else { @@ -221,8 +222,11 @@ fn run_engine( report(Level::Info.title(&title)) } } - protocol::FromEngine::Ping => { - send!(&protocol::ToEngine::Pong); + FromEngine::PrettyPrintDiagnostic(diag) => { + send!(&ToEngine::PrettyPrintedDiagnostic(format!("{}", diag))); + } + FromEngine::Ping => { + send!(&ToEngine::Pong); } } } diff --git a/cli/subcommands/src/pretty_print_diagnostics.rs b/cli/subcommands/src/pretty_print_diagnostics.rs deleted file mode 100644 index a4689db7a..000000000 --- a/cli/subcommands/src/pretty_print_diagnostics.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! This binary is useful for the engine: from OCaml we need to pretty -//! print Hax-errors so that we can inline those as failed items or -//! failed expressions in the generated modules. - -//! Thus, this binary expects a JSON diagnostics error on its stdin -//! and outputs on stdout its pretty, `Display`ed version. - -#![feature(rustc_private)] -extern crate rustc_driver; - -use hax_types::diagnostics::Diagnostics as D; -use serde_json::from_reader; - -fn main() { - println!("{}", from_reader::<_, D>(std::io::stdin()).unwrap()) -} diff --git a/engine/lib/diagnostics.ml b/engine/lib/diagnostics.ml index fb7183858..379dc3d89 100644 --- a/engine/lib/diagnostics.ml +++ b/engine/lib/diagnostics.ml @@ -93,16 +93,15 @@ type t = { context : Context.t; kind : kind; span : thir_span list } let to_thir_diagnostic (d : t) : Types.diagnostics = { kind = d.kind; context = Context.display d.context; span = d.span } -let run_hax_pretty_print_diagnostics (s : string) : string = - try (Utils.Command.run "hax-pretty-print-diagnostics" s).stdout - with e -> - "[run_hax_pretty_print_diagnostics] failed. Exn: " - ^ "[run_hax_pretty_print_diagnostics] failed. Exn: " ^ Exn.to_string e - ^ ". Here is the JSON representation of the error that occurred:\n" ^ s +(** Ask `cargo-hax` to pretty print a diagnostic *) +let ask_diagnostic_pretty_print diag : string = + Hax_io.request (PrettyPrintDiagnostic diag) + ~expected:"PrettyPrintedDiagnostic" (function + | Types.PrettyPrintedDiagnostic s -> Some s + | _ -> None) let pretty_print : t -> string = - to_thir_diagnostic >> Types.to_json_diagnostics - >> Yojson.Safe.pretty_to_string >> run_hax_pretty_print_diagnostics + to_thir_diagnostic >> ask_diagnostic_pretty_print let pretty_print_context_kind : Context.t -> kind -> string = fun context kind -> diff --git a/hax-types/src/engine_api.rs b/hax-types/src/engine_api.rs index 5640af140..8e25f4cb7 100644 --- a/hax-types/src/engine_api.rs +++ b/hax-types/src/engine_api.rs @@ -32,11 +32,13 @@ pub mod protocol { pub enum FromEngine { Diagnostic(crate::diagnostics::Diagnostics), File(File), + PrettyPrintDiagnostic(crate::diagnostics::Diagnostics), Exit, Ping, } #[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] pub enum ToEngine { + PrettyPrintedDiagnostic(String), Pong, } } From 4018f442eb3b22fccd0e320133104164c9f9ce3a Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Sun, 30 Jun 2024 18:03:18 +0200 Subject: [PATCH 11/39] feat: use msg instead of binary rustfmt --- Cargo.lock | 12 +++++++++++ cli/subcommands/Cargo.toml | 2 ++ cli/subcommands/src/cargo_hax.rs | 7 +++++++ engine/lib/print_rust.ml | 34 ++++++++++++++++---------------- engine/lib/utils.ml | 20 ------------------- hax-types/src/engine_api.rs | 2 ++ 6 files changed, 40 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f53fd9b94..64b593c19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -153,11 +153,13 @@ dependencies = [ "itertools", "paste", "path-clean", + "prettyplease", "rustup-toolchain", "schemars", "serde", "serde-jsonlines", "serde_json", + "syn 1.0.109", "tempfile", "toml 0.8.3", "version_check", @@ -1049,6 +1051,16 @@ dependencies = [ "termtree", ] +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2", + "syn 2.0.68", +] + [[package]] name = "proc-macro-error" version = "1.0.4" diff --git a/cli/subcommands/Cargo.toml b/cli/subcommands/Cargo.toml index 0caf29a05..2a1008840 100644 --- a/cli/subcommands/Cargo.toml +++ b/cli/subcommands/Cargo.toml @@ -41,6 +41,8 @@ const_format = "0.2" ciborium.workspace = true annotate-snippets.workspace = true serde-jsonlines = "0.5.0" +prettyplease = "0.2.20" +syn = { version = "2.*", features = ["full"] } [build-dependencies] serde.workspace = true diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index 1ce678e89..713c90f68 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -225,6 +225,13 @@ fn run_engine( FromEngine::PrettyPrintDiagnostic(diag) => { send!(&ToEngine::PrettyPrintedDiagnostic(format!("{}", diag))); } + FromEngine::PrettyPrintRust(code) => { + let code = match syn::parse_file(&code) { + Ok(file) => Ok(prettyplease::unparse(&file)), + Err(err) => Err(format!("{}", err)), + }; + send!(&ToEngine::PrettyPrintedRust(code)); + } FromEngine::Ping => { send!(&ToEngine::Pong); } diff --git a/engine/lib/print_rust.ml b/engine/lib/print_rust.ml index a1ad5f46e..2b97648be 100644 --- a/engine/lib/print_rust.ml +++ b/engine/lib/print_rust.ml @@ -544,23 +544,23 @@ module Raw = struct end let rustfmt (s : string) : string = - let open Utils.Command in - let { stderr; stdout } = run "rustfmt" s in - if String.is_empty stderr then stdout - else - let err = - [%string - "\n\n\ - #######################################################\n\ - ########### WARNING: Failed running rustfmt ###########\n\ - #### STDOUT:\n\ - %{stdout}\n\ - #### STDERR:\n\ - %{stderr}\n\ - #######################################################\n"] - in - Stdio.prerr_endline err; - [%string "/*\n%{err}\n*/\n\n%{s}"] + match + Hax_io.request (PrettyPrintRust s) ~expected:"PrettyPrintedRust" (function + | Types.PrettyPrintedRust s -> Some s + | _ -> None) + with + | Ok formatted -> formatted + | Err error -> + let err = + [%string + "\n\n\ + #######################################################\n\ + ########### WARNING: Failed formatting ###########\n\ + %{error}\n\ + #######################################################\n"] + in + Stdio.prerr_endline err; + [%string "/*\n%{err}\n*/\n\n%{s}"] exception RetokenizationFailure diff --git a/engine/lib/utils.ml b/engine/lib/utils.ml index a5fb74ab8..1243aa98a 100644 --- a/engine/lib/utils.ml +++ b/engine/lib/utils.ml @@ -82,26 +82,6 @@ let sequence (l : 'a option list) : 'a list option = let tabsize = 2 let newline_indent depth : string = "\n" ^ String.make (tabsize * depth) ' ' -module Command = struct - type output = { stderr : string; stdout : string } - - let run (command : string) (stdin_string : string) : output = - let stdout, stdin, stderr = - Unix.open_process_full command (Unix.environment ()) - in - Unix.set_close_on_exec @@ Unix.descr_of_in_channel stdout; - Unix.set_close_on_exec @@ Unix.descr_of_in_channel stderr; - Out_channel.( - output_string stdin stdin_string; - flush stdin; - close stdin); - let strout = In_channel.input_all stdout in - let strerr = In_channel.input_all stderr |> Stdlib.String.trim in - Unix.close @@ Unix.descr_of_in_channel stdout; - Unix.close @@ Unix.descr_of_in_channel stderr; - { stdout = strout; stderr = strerr } -end - module MyInt64 = struct include Base.Int64 diff --git a/hax-types/src/engine_api.rs b/hax-types/src/engine_api.rs index 8e25f4cb7..7459165ca 100644 --- a/hax-types/src/engine_api.rs +++ b/hax-types/src/engine_api.rs @@ -33,12 +33,14 @@ pub mod protocol { Diagnostic(crate::diagnostics::Diagnostics), File(File), PrettyPrintDiagnostic(crate::diagnostics::Diagnostics), + PrettyPrintRust(String), Exit, Ping, } #[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] pub enum ToEngine { PrettyPrintedDiagnostic(String), + PrettyPrintedRust(Result), Pong, } } From 24e6ff2ac8835dcd8e269d54f9581bced1da6310 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Sun, 30 Jun 2024 19:29:34 +0200 Subject: [PATCH 12/39] fix: restore debugging options --- Cargo.lock | 2 +- cli/subcommands/src/cargo_hax.rs | 3 +++ engine/bin/lib.ml | 1 + engine/lib/print_rust.ml | 12 +++++++----- hax-types/src/engine_api.rs | 1 + 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 64b593c19..9b12a55d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -159,7 +159,7 @@ dependencies = [ "serde", "serde-jsonlines", "serde_json", - "syn 1.0.109", + "syn 2.0.68", "tempfile", "toml 0.8.3", "version_check", diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index 713c90f68..41f6143d9 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -222,6 +222,9 @@ fn run_engine( report(Level::Info.title(&title)) } } + FromEngine::DebugString(debug) => { + output.debug_json = Some(debug); + } FromEngine::PrettyPrintDiagnostic(diag) => { send!(&ToEngine::PrettyPrintedDiagnostic(format!("{}", diag))); } diff --git a/engine/bin/lib.ml b/engine/bin/lib.ml index e66af48e4..ae601a8e9 100644 --- a/engine/bin/lib.ml +++ b/engine/bin/lib.ml @@ -154,6 +154,7 @@ let main () = results.diagnostics; List.iter ~f:(fun file -> File file |> Hax_io.write) results.files; + Option.iter ~f:(fun json -> DebugString json |> Hax_io.write) debug_json; Hax_io.close (); Logs.info (fun m -> m "Exiting Hax engine (success)") diff --git a/engine/lib/print_rust.ml b/engine/lib/print_rust.ml index 2b97648be..cf5f1b848 100644 --- a/engine/lib/print_rust.ml +++ b/engine/lib/print_rust.ml @@ -270,7 +270,7 @@ module Raw = struct arms |> concat ~sep:!"," in - !"(match " & pexpr scrutinee & !" {" & arms & !"})" + !"(match (" & pexpr scrutinee & !") {" & arms & !"})" (* | Let { monadic = Some _; _ } -> !"monadic_let!()" *) | Let { monadic; lhs; rhs; body } -> (* TODO: here, [rhs.typ]! *) @@ -278,7 +278,7 @@ module Raw = struct let rhs_typ = pty rhs.span rhs.typ in let note = if String.equal (to_string lhs_typ) (to_string rhs_typ) then !"" - else !"// Note: rhs.typ=" & rhs_typ & !"\n" + else !"#[note(\"rhs.typ=" & rhs_typ & !"\")]\n" in let monadic = match monadic with @@ -538,9 +538,9 @@ module Raw = struct in pattrs e.attrs & pi with NotImplemented -> - !("\n/* print_rust: pitem: not implemented (item: " + !("\n/** print_rust: pitem: not implemented (item: " ^ [%show: concrete_ident] e.ident - ^ ") */\n") + ^ ") */\nconst _: () = ();\n") end let rustfmt (s : string) : string = @@ -557,10 +557,12 @@ let rustfmt (s : string) : string = #######################################################\n\ ########### WARNING: Failed formatting ###########\n\ %{error}\n\ + STRING:\n\ + %{s}\n\ #######################################################\n"] in Stdio.prerr_endline err; - [%string "/*\n%{err}\n*/\n\n%{s}"] + s exception RetokenizationFailure diff --git a/hax-types/src/engine_api.rs b/hax-types/src/engine_api.rs index 7459165ca..77d07f2f8 100644 --- a/hax-types/src/engine_api.rs +++ b/hax-types/src/engine_api.rs @@ -34,6 +34,7 @@ pub mod protocol { File(File), PrettyPrintDiagnostic(crate::diagnostics::Diagnostics), PrettyPrintRust(String), + DebugString(String), Exit, Ping, } From e6529de7edd99eba3d761aee2947de739c822169 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 1 Jul 2024 18:39:49 +0200 Subject: [PATCH 13/39] fix(tests): get rid of lint-related tests --- .../snapshots/toolchain__fnmut lint-rust.snap | 54 ------------------- .../toolchain__mut_arg lint-hacspec.snap | 34 ------------ .../toolchain__v1-lib lint-hacspec.snap | 27 ---------- tests/Cargo.lock | 15 ------ tests/Cargo.toml | 3 -- tests/lint/hacspec/mut_args/Cargo.toml | 10 ---- tests/lint/hacspec/mut_args/src/lib.rs | 3 -- tests/lint/hacspec/v1-lib/Cargo.toml | 11 ---- tests/lint/hacspec/v1-lib/src/lib.rs | 18 ------- tests/lint/rust/fnmut/Cargo.toml | 10 ---- tests/lint/rust/fnmut/src/lib.rs | 20 ------- 11 files changed, 205 deletions(-) delete mode 100644 test-harness/src/snapshots/toolchain__fnmut lint-rust.snap delete mode 100644 test-harness/src/snapshots/toolchain__mut_arg lint-hacspec.snap delete mode 100644 test-harness/src/snapshots/toolchain__v1-lib lint-hacspec.snap delete mode 100644 tests/lint/hacspec/mut_args/Cargo.toml delete mode 100644 tests/lint/hacspec/mut_args/src/lib.rs delete mode 100644 tests/lint/hacspec/v1-lib/Cargo.toml delete mode 100644 tests/lint/hacspec/v1-lib/src/lib.rs delete mode 100644 tests/lint/rust/fnmut/Cargo.toml delete mode 100644 tests/lint/rust/fnmut/src/lib.rs diff --git a/test-harness/src/snapshots/toolchain__fnmut lint-rust.snap b/test-harness/src/snapshots/toolchain__fnmut lint-rust.snap deleted file mode 100644 index e8caed1c8..000000000 --- a/test-harness/src/snapshots/toolchain__fnmut lint-rust.snap +++ /dev/null @@ -1,54 +0,0 @@ ---- -source: test-harness/src/harness.rs -expression: snapshot -info: - kind: - Lint: - linter: rust - info: - name: fnmut - manifest: lint/rust/fnmut/Cargo.toml - description: ~ - spec: - optional: false - broken: false - issue_id: ~ - positive: true - snapshot: - stderr: true - stdout: true - include_flag: ~ - backend_options: ~ ---- -exit = 0 -stderr = ''' -Compiling fnmut v0.1.0 (WORKSPACE_ROOT/lint/rust/fnmut) -warning: [Hax] FnMut is not supported - --> lint/rust/fnmut/src/lib.rs:8:12 - | -8 | F: FnMut(u32) -> u8; - | ^^^^^ - -warning: [Hax] FnMut is not supported - --> lint/rust/fnmut/src/lib.rs:16:12 - | -16 | F: FnMut(u32) -> u8, - | ^^^^^ - -warning: trait `SomeTrait` is never used - --> lint/rust/fnmut/src/lib.rs:5:7 - | -5 | trait SomeTrait { - | ^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: struct `UpdatableStruct` is never constructed - --> lint/rust/fnmut/src/lib.rs:11:8 - | -11 | struct UpdatableStruct {} - | ^^^^^^^^^^^^^^^ - -warning: `fnmut` (lib) generated 4 warnings - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' -stdout = '' diff --git a/test-harness/src/snapshots/toolchain__mut_arg lint-hacspec.snap b/test-harness/src/snapshots/toolchain__mut_arg lint-hacspec.snap deleted file mode 100644 index e6dda41ca..000000000 --- a/test-harness/src/snapshots/toolchain__mut_arg lint-hacspec.snap +++ /dev/null @@ -1,34 +0,0 @@ ---- -source: test-harness/src/harness.rs -expression: snapshot -info: - kind: - Lint: - linter: hacspec - info: - name: mut_arg - manifest: lint/hacspec/mut_args/Cargo.toml - description: ~ - spec: - optional: false - broken: false - issue_id: ~ - positive: true - snapshot: - stderr: true - stdout: true - include_flag: ~ - backend_options: ~ ---- -exit = 0 -stderr = ''' -Compiling mut_arg v0.1.0 (WORKSPACE_ROOT/lint/hacspec/mut_args) -warning: [Hax] Mutable arguments are not supported - --> lint/hacspec/mut_args/src/lib.rs:1:23 - | -1 | pub fn add(left: &mut usize, right: usize) { - | ^^^^^ - -warning: `mut_arg` (lib) generated 1 warning - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' -stdout = '' diff --git a/test-harness/src/snapshots/toolchain__v1-lib lint-hacspec.snap b/test-harness/src/snapshots/toolchain__v1-lib lint-hacspec.snap deleted file mode 100644 index 8cd6cfa62..000000000 --- a/test-harness/src/snapshots/toolchain__v1-lib lint-hacspec.snap +++ /dev/null @@ -1,27 +0,0 @@ ---- -source: test-harness/src/harness.rs -expression: snapshot -info: - kind: - Lint: - linter: hacspec - info: - name: v1-lib - manifest: lint/hacspec/v1-lib/Cargo.toml - description: ~ - spec: - optional: false - broken: false - issue_id: ~ - positive: true - snapshot: - stderr: true - stdout: true - include_flag: ~ - backend_options: ~ ---- -exit = 0 -stderr = ''' -Compiling v1-lib v0.1.0 (WORKSPACE_ROOT/lint/hacspec/v1-lib) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' -stdout = '' diff --git a/tests/Cargo.lock b/tests/Cargo.lock index 69afac770..9d18936a6 100644 --- a/tests/Cargo.lock +++ b/tests/Cargo.lock @@ -235,10 +235,6 @@ version = "0.0.1" name = "fn-to-letfun" version = "0.1.0" -[[package]] -name = "fnmut" -version = "0.1.0" - [[package]] name = "generics" version = "0.1.0" @@ -491,10 +487,6 @@ version = "0.1.0" name = "mut-ref-functionalization" version = "0.1.0" -[[package]] -name = "mut_arg" -version = "0.1.0" - [[package]] name = "naming" version = "0.1.0" @@ -922,13 +914,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "v1-lib" -version = "0.1.0" -dependencies = [ - "hacspec-lib", -] - [[package]] name = "version_check" version = "0.9.4" diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 8dd33e0b7..68ec5ef04 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -8,9 +8,6 @@ members = [ "enum-repr", "pattern-or", "side-effects", - "lint/hacspec/v1-lib", - "lint/hacspec/mut_args", - "lint/rust/fnmut", "mut-ref-functionalization", "generics", "loops", diff --git a/tests/lint/hacspec/mut_args/Cargo.toml b/tests/lint/hacspec/mut_args/Cargo.toml deleted file mode 100644 index 130f2fb6d..000000000 --- a/tests/lint/hacspec/mut_args/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "mut_arg" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] - -[package.metadata.hax-tests.lint.hacspec] diff --git a/tests/lint/hacspec/mut_args/src/lib.rs b/tests/lint/hacspec/mut_args/src/lib.rs deleted file mode 100644 index 418fbec0e..000000000 --- a/tests/lint/hacspec/mut_args/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub fn add(left: &mut usize, right: usize) { - *left += right -} diff --git a/tests/lint/hacspec/v1-lib/Cargo.toml b/tests/lint/hacspec/v1-lib/Cargo.toml deleted file mode 100644 index 3ed25fbd9..000000000 --- a/tests/lint/hacspec/v1-lib/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "v1-lib" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -hacspec-lib = { git = "https://github.com/hacspec/hacspec.git" } - -[package.metadata.hax-tests.lint.hacspec] diff --git a/tests/lint/hacspec/v1-lib/src/lib.rs b/tests/lint/hacspec/v1-lib/src/lib.rs deleted file mode 100644 index a9a12ae08..000000000 --- a/tests/lint/hacspec/v1-lib/src/lib.rs +++ /dev/null @@ -1,18 +0,0 @@ -use hacspec_lib::*; - -bytes!(MyBytes, 8); -array!(State, 16, U32, type_for_indexes: StateIdx); - -public_nat_mod!( - type_name: PublicX25519FieldElement, - type_of_canvas: PublicFieldCanvas, - bit_size_of_field: 256, - modulo_value: "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed" -); - -nat_mod!( - type_name: X25519FieldElement, - type_of_canvas: FieldCanvas, - bit_size_of_field: 256, - modulo_value: "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed" -); diff --git a/tests/lint/rust/fnmut/Cargo.toml b/tests/lint/rust/fnmut/Cargo.toml deleted file mode 100644 index 9bfb81724..000000000 --- a/tests/lint/rust/fnmut/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "fnmut" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] - -[package.metadata.hax-tests.lint.rust] diff --git a/tests/lint/rust/fnmut/src/lib.rs b/tests/lint/rust/fnmut/src/lib.rs deleted file mode 100644 index e2e1f3046..000000000 --- a/tests/lint/rust/fnmut/src/lib.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! Tests for the Rust linter -//! -//! No FnMut - -trait SomeTrait { - fn update_fun(&self, fun: F) -> u8 - where - F: FnMut(u32) -> u8; -} - -struct UpdatableStruct {} - -impl SomeTrait for UpdatableStruct { - fn update_fun(&self, mut fun: F) -> u8 - where - F: FnMut(u32) -> u8, - { - fun(123) - } -} From 79624fa084eff568145d3f998862013f85e7070b Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 1 Jul 2024 18:44:08 +0200 Subject: [PATCH 14/39] fix(frontend): silence warnings --- cli/subcommands/src/cargo_hax.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index 41f6143d9..913e21dec 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -84,6 +84,7 @@ const ENGINE_BINARY_NOT_FOUND: &str = const_format::formatcp!( /// is. Then, we try to find [ENGINE_BINARY_NAME] in PATH. If not /// found, detect whether nodejs is available, download the JS-compiled /// engine and use it. +#[allow(unused_variables, unreachable_code)] fn find_hax_engine() -> process::Command { use which::which; From 1c75e00bc3f23fda18010fb2bd6228e79523d7ac Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 1 Jul 2024 18:45:39 +0200 Subject: [PATCH 15/39] fix(frontend): exit code: reflect engine error --- cli/subcommands/src/cargo_hax.rs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index 913e21dec..ee79b77a4 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -144,7 +144,7 @@ fn run_engine( manifest_dir: PathBuf, options: &Options, backend: &BackendOptions, -) { +) -> bool { let engine_options = EngineOptions { backend: backend.clone(), input: haxmeta.items, @@ -165,6 +165,7 @@ fn run_engine( }) .unwrap(); + let mut error = false; let mut output = Output { diagnostics: vec![], files: vec![], @@ -185,7 +186,7 @@ fn run_engine( stdin.write_all(b"\n").unwrap(); stdin.flush().unwrap(); }; - }; + } send!(&engine_options); @@ -207,6 +208,7 @@ fn run_engine( match msg { FromEngine::Exit => break, FromEngine::Diagnostic(diag) => { + error = true; if backend.dry_run { output.diagnostics.push(diag.clone()) } @@ -272,12 +274,14 @@ fn run_engine( eprintln!("----------------------------------------------"); hax_phase_debug_webapp::run(|| debug_json.clone()) } - Some(DebugEngineMode::File(file)) if !backend.dry_run => { + Some(DebugEngineMode::File(_file)) if !backend.dry_run => { println!("{}", debug_json) } _ => (), } } + + error } /// Calls `cargo` with a custom driver which computes `haxmeta` files @@ -347,7 +351,7 @@ fn compute_haxmeta_files(options: &Options) -> (Vec, i32) { } /// Run the command given by the user -fn run_command(options: &Options, haxmeta_files: Vec) { +fn run_command(options: &Options, haxmeta_files: Vec) -> bool { match options.command.clone() { Command::JSON { output_file, @@ -375,6 +379,7 @@ fn run_command(options: &Options, haxmeta_files: Vec) { .unwrap() } }); + false } Command::Backend(backend) => { use hax_frontend_exporter::ThirBody as Body; @@ -388,6 +393,7 @@ fn run_command(options: &Options, haxmeta_files: Vec) { report(Level::Warning.title(&title)) } + let mut error = false; for EmitHaxMetaMessage { working_dir, manifest_dir, @@ -397,8 +403,9 @@ fn run_command(options: &Options, haxmeta_files: Vec) { let file = std::io::BufReader::new(fs::File::open(&path).unwrap()); let haxmeta: HaxMeta = ciborium::from_reader(file).unwrap(); - run_engine(haxmeta, working_dir, manifest_dir, &options, &backend); + error = error || run_engine(haxmeta, working_dir, manifest_dir, &backend); } + error } } } @@ -409,7 +416,11 @@ fn main() { options.normalize_paths(); let (haxmeta_files, exit_code) = compute_haxmeta_files(&options); - run_command(&options, haxmeta_files); + let error = run_command(&options, haxmeta_files); - std::process::exit(exit_code) + std::process::exit(if exit_code == 0 && error { + 1 + } else { + exit_code + }) } From 36e0906364ae2471d27091982c643c0526ef7b4b Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 1 Jul 2024 18:46:01 +0200 Subject: [PATCH 16/39] chore(frontend): remove unused --- cli/subcommands/src/cargo_hax.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index ee79b77a4..bd7856acf 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -142,7 +142,6 @@ fn run_engine( haxmeta: HaxMeta, working_dir: PathBuf, manifest_dir: PathBuf, - options: &Options, backend: &BackendOptions, ) -> bool { let engine_options = EngineOptions { @@ -256,7 +255,6 @@ fn run_engine( report(Level::Error.title(&title)); std::process::exit(1); } - let options_frontend = Options::from(options.clone()); if backend.dry_run { serde_json::to_writer(std::io::BufWriter::new(std::io::stdout()), &output).unwrap() From c4d3068de9e0ba72982f610e2aa3f43aa596b861 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 1 Jul 2024 18:55:01 +0200 Subject: [PATCH 17/39] feat(frontend): generic derives, use `bincode` + `zstd` --- Cargo.lock | 113 +-- Cargo.toml | 2 +- cli/driver/Cargo.toml | 1 - cli/driver/src/exporter.rs | 4 +- cli/subcommands/Cargo.toml | 1 - cli/subcommands/src/cargo_hax.rs | 6 +- engine/names/Cargo.toml | 1 + engine/names/extract/Cargo.toml | 2 + frontend/exporter/Cargo.toml | 1 + frontend/exporter/adt-into/src/lib.rs | 31 + frontend/exporter/options/Cargo.toml | 3 +- frontend/exporter/options/src/lib.rs | 11 +- frontend/exporter/src/body.rs | 4 +- frontend/exporter/src/constant_utils.rs | 21 +- frontend/exporter/src/index_vec.rs | 10 +- frontend/exporter/src/prelude.rs | 2 + frontend/exporter/src/sinto.rs | 6 +- frontend/exporter/src/state.rs | 3 +- frontend/exporter/src/traits.rs | 16 +- frontend/exporter/src/types/copied.rs | 708 ++++++++++-------- frontend/exporter/src/types/def_id.rs | 11 +- frontend/exporter/src/types/mir.rs | 99 ++- frontend/exporter/src/types/mir_traits.rs | 3 +- .../exporter/src/types/new/item_attributes.rs | 3 +- .../exporter/src/types/new/predicate_id.rs | 5 +- .../src/types/new/typed_constant_kind.rs | 3 +- hax-types/Cargo.toml | 5 +- hax-types/src/cli_options.rs | 44 +- hax-types/src/diagnostics/mod.rs | 6 +- hax-types/src/driver_api.rs | 25 +- hax-types/src/engine_api.rs | 18 +- hax-types/src/prelude.rs | 2 +- 32 files changed, 679 insertions(+), 491 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9b12a55d6..5b250b3b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,6 +96,25 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "bincode" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f11ea1a0346b94ef188834a65c068a03aec181c94896d481d7a0a40d85b0ce95" +dependencies = [ + "bincode_derive", + "serde", +] + +[[package]] +name = "bincode_derive" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e30759b3b99a1b802a7a3aa21c85c3ded5c28e1c83170d82d70f08bbf7f3e4c" +dependencies = [ + "virtue", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -139,7 +158,6 @@ name = "cargo-hax" version = "0.1.0-pre.1" dependencies = [ "annotate-snippets", - "ciborium", "clap", "colored", "const_format", @@ -212,33 +230,6 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cca491388666e04d7248af3f60f0c40cfb0991c72205595d7c396e3510207d1a" -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - [[package]] name = "clap" version = "4.4.6" @@ -353,12 +344,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - [[package]] name = "difflib" version = "0.4.0" @@ -483,16 +468,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if", - "crunchy", -] - [[package]] name = "hashbrown" version = "0.14.2" @@ -523,7 +498,6 @@ dependencies = [ name = "hax-driver" version = "0.1.0-pre.1" dependencies = [ - "ciborium", "clap", "colored", "const_format", @@ -544,6 +518,7 @@ dependencies = [ name = "hax-engine-names" version = "0.1.0-pre.1" dependencies = [ + "bincode", "hax-lib", "hax-lib-protocol", ] @@ -552,8 +527,10 @@ dependencies = [ name = "hax-engine-names-extract" version = "0.1.0-pre.1" dependencies = [ + "bincode", "camino", "cargo_metadata", + "hax-adt-into", "hax-engine-names", "serde", "serde_json", @@ -564,6 +541,7 @@ dependencies = [ name = "hax-frontend-exporter" version = "0.1.0-pre.1" dependencies = [ + "bincode", "extension-traits", "hax-adt-into", "hax-frontend-exporter-options", @@ -580,6 +558,8 @@ dependencies = [ name = "hax-frontend-exporter-options" version = "0.1.0-pre.1" dependencies = [ + "bincode", + "hax-adt-into", "schemars", "serde", "serde_json", @@ -663,8 +643,10 @@ name = "hax-types" version = "0.1.0-pre.1" dependencies = [ "annotate-snippets", + "bincode", "clap", "colored", + "hax-adt-into", "hax-frontend-exporter", "hax-frontend-exporter-options", "itertools", @@ -672,6 +654,7 @@ dependencies = [ "schemars", "serde", "serde_json", + "zstd", ] [[package]] @@ -1017,6 +1000,12 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1639,6 +1628,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "virtue" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dcc60c0624df774c82a0ef104151231d37da4962957d691c011c852b2473314" + [[package]] name = "wait-timeout" version = "0.2.0" @@ -1966,3 +1961,31 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zstd" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.11+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75652c55c0b6f3e6f12eb786fe1bc960396bf05a1eb3bf1f3691c3610ac2e6d4" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index 64500dd94..b5893677f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,7 +69,7 @@ quote = "1.0.32" proc-macro2 = "1.0.66" cargo_metadata = "0.15" colored = "2" -ciborium = "0.2" +bincode = "2.0.0-rc.3" annotate-snippets = "0.11" # Crates in this repository diff --git a/cli/driver/Cargo.toml b/cli/driver/Cargo.toml index fd68bc145..5120b4afd 100644 --- a/cli/driver/Cargo.toml +++ b/cli/driver/Cargo.toml @@ -31,4 +31,3 @@ const_format = "0.2" tracing.workspace = true tracing-subscriber.workspace = true tracing-tree.workspace = true -ciborium.workspace = true diff --git a/cli/driver/src/exporter.rs b/cli/driver/src/exporter.rs index e5cb1a929..fa53b548a 100644 --- a/cli/driver/src/exporter.rs +++ b/cli/driver/src/exporter.rs @@ -261,7 +261,7 @@ impl Callbacks for ExtractionCallbacks { let haxmeta_path = output_dir.join(format!("{crate_type}{crate_name}-{cg_metadata}.haxmeta",)); - let file = File::create(&haxmeta_path).unwrap(); + let mut file = BufWriter::new(File::create(&haxmeta_path).unwrap()); use hax_types::driver_api::{with_kind_type, HaxMeta}; with_kind_type!( @@ -278,7 +278,7 @@ impl Callbacks for ExtractionCallbacks { items, def_ids, }; - ciborium::into_writer(&haxmeta, BufWriter::new(file)).unwrap(); + haxmeta.write(&mut file); } ); diff --git a/cli/subcommands/Cargo.toml b/cli/subcommands/Cargo.toml index 2a1008840..d667f9436 100644 --- a/cli/subcommands/Cargo.toml +++ b/cli/subcommands/Cargo.toml @@ -38,7 +38,6 @@ is-terminal = "0.4.9" hax-phase-debug-webapp.workspace = true inquire = "0.6" const_format = "0.2" -ciborium.workspace = true annotate-snippets.workspace = true serde-jsonlines = "0.5.0" prettyplease = "0.2.20" diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index bd7856acf..c7c77a0c7 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -359,8 +359,7 @@ fn run_command(options: &Options, haxmeta_files: Vec) -> boo } => { with_kind_type!(kind, || { for EmitHaxMetaMessage { path, .. } in haxmeta_files { - let file = std::io::BufReader::new(fs::File::open(&path).unwrap()); - let haxmeta: HaxMeta = ciborium::from_reader(file).unwrap(); + let haxmeta: HaxMeta = HaxMeta::read(fs::File::open(&path).unwrap()); let dest = output_file.open_or_stdout(); (if include_extra { serde_json::to_writer( @@ -398,8 +397,7 @@ fn run_command(options: &Options, haxmeta_files: Vec) -> boo path, } in haxmeta_files { - let file = std::io::BufReader::new(fs::File::open(&path).unwrap()); - let haxmeta: HaxMeta = ciborium::from_reader(file).unwrap(); + let haxmeta: HaxMeta = HaxMeta::read(fs::File::open(&path).unwrap()); error = error || run_engine(haxmeta, working_dir, manifest_dir, &backend); } diff --git a/engine/names/Cargo.toml b/engine/names/Cargo.toml index efc92fca6..d69cdd941 100644 --- a/engine/names/Cargo.toml +++ b/engine/names/Cargo.toml @@ -12,3 +12,4 @@ description = "Dummy crate containing all the Rust names the hax engine should b [dependencies] hax-lib-protocol = {path = "../../hax-lib-protocol"} hax-lib = {path = "../../hax-lib"} +bincode.workspace = true diff --git a/engine/names/extract/Cargo.toml b/engine/names/extract/Cargo.toml index 916319dd4..e05a6ac71 100644 --- a/engine/names/extract/Cargo.toml +++ b/engine/names/extract/Cargo.toml @@ -15,8 +15,10 @@ serde.workspace = true serde_json.workspace = true cargo_metadata.workspace = true hax-engine-names.workspace = true +hax-adt-into.workspace = true tempfile.version = "3.9" camino = "1.1" +bincode.workspace = true [features] default = ["extract_names_mode"] diff --git a/frontend/exporter/Cargo.toml b/frontend/exporter/Cargo.toml index fb52c5cad..3695f9667 100644 --- a/frontend/exporter/Cargo.toml +++ b/frontend/exporter/Cargo.toml @@ -23,6 +23,7 @@ tracing.workspace = true paste = "1.0.11" extension-traits = "1.0.1" lazy_static = "1.4.0" +bincode.workspace = true [features] extract_names_mode = [] diff --git a/frontend/exporter/adt-into/src/lib.rs b/frontend/exporter/adt-into/src/lib.rs index b73a035a4..0c43b9638 100644 --- a/frontend/exporter/adt-into/src/lib.rs +++ b/frontend/exporter/adt-into/src/lib.rs @@ -437,3 +437,34 @@ fn drop_generics(type_path: syn::TypePath) -> syn::TypePath { ..type_path } } + +/// A proc macro unrelated to `adt-into`. This is useful in hax and we don't want a whole crate only for that helper. This proc macro defines some groups of derive clauses that we reuse all the time. This is particularly interesting for serializers and deserializers: today we use `bincode` and `serde`, but maybe we will want to move to something else in the future. +#[proc_macro_attribute] +pub fn derive_group( + attr: proc_macro::TokenStream, + item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + let item: proc_macro2::TokenStream = item.into(); + let groups = format!("{attr}"); + let groups = groups.split(",").map(|s| s.trim()); + let mut errors = vec![]; + let result: proc_macro2::TokenStream = groups + .map(|group| match group { + "Serializers" => quote! { + #[derive(::serde::Serialize, ::serde::Deserialize)] + #[derive(::bincode::Encode, ::bincode::Decode)] + }, + _ => { + errors.push(quote! { + const _: () = compile_error!(concat!( + "derive_group: `", + stringify!(#group), + "` is not a recognized group name" + )); + }); + quote! {} + } + }) + .collect(); + quote! {#(#errors)* #result #item}.into() +} diff --git a/frontend/exporter/options/Cargo.toml b/frontend/exporter/options/Cargo.toml index fadcbc905..a8f04c553 100644 --- a/frontend/exporter/options/Cargo.toml +++ b/frontend/exporter/options/Cargo.toml @@ -13,4 +13,5 @@ description = "The options the `hax-frontend-exporter` crate is sensible to." serde.workspace = true serde_json.workspace = true schemars.workspace = true - +hax-adt-into.workspace = true +bincode.workspace = true diff --git a/frontend/exporter/options/src/lib.rs b/frontend/exporter/options/src/lib.rs index a19c79f70..1accf3d9e 100644 --- a/frontend/exporter/options/src/lib.rs +++ b/frontend/exporter/options/src/lib.rs @@ -1,13 +1,15 @@ +use hax_adt_into::derive_group; use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Debug, Clone, JsonSchema)] pub enum Glob { One, // * Many, // ** } -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Debug, Clone, JsonSchema)] pub enum NamespaceChunk { Glob(Glob), Exact(String), @@ -23,7 +25,8 @@ impl std::convert::From<&str> for NamespaceChunk { } } -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Debug, Clone, JsonSchema)] pub struct Namespace { pub chunks: Vec, } diff --git a/frontend/exporter/src/body.rs b/frontend/exporter/src/body.rs index 89cb57c89..f31966302 100644 --- a/frontend/exporter/src/body.rs +++ b/frontend/exporter/src/body.rs @@ -17,7 +17,7 @@ pub fn get_thir<'tcx, S: UnderOwnerState<'tcx>>( base.cached_thirs.get(&did).unwrap_or_else(msg).clone() } -pub trait IsBody: Sized + Clone { +pub trait IsBody: Sized + Clone + 'static { fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RLocalDefId, s: &S) -> Self; } @@ -83,7 +83,7 @@ mod implementations { } } - impl IsBody for MirBody { + impl IsBody for MirBody { fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RLocalDefId, s: &S) -> Self { let (thir, _) = get_thir(did, s); let mir = Rc::new(s.base().tcx.mir_built(did).borrow().clone()); diff --git a/frontend/exporter/src/constant_utils.rs b/frontend/exporter/src/constant_utils.rs index 9d6f69615..74f5e611c 100644 --- a/frontend/exporter/src/constant_utils.rs +++ b/frontend/exporter/src/constant_utils.rs @@ -1,9 +1,9 @@ use crate::prelude::*; + use rustc_middle::{mir, ty}; -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum ConstantInt { Int( #[serde(with = "serialize_int::signed")] @@ -19,9 +19,8 @@ pub enum ConstantInt { ), } -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum ConstantLiteral { Bool(bool), Char(char), @@ -31,9 +30,8 @@ pub enum ConstantLiteral { } /// The subset of [Expr] that corresponds to constants. -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum ConstantExprKind { Literal(ConstantLiteral), Adt { @@ -96,9 +94,8 @@ pub enum ConstantExprKind { Todo(String), } -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct ConstantFieldExpr { pub field: DefId, pub value: ConstantExpr, diff --git a/frontend/exporter/src/index_vec.rs b/frontend/exporter/src/index_vec.rs index fa9f26335..0e27a6c91 100644 --- a/frontend/exporter/src/index_vec.rs +++ b/frontend/exporter/src/index_vec.rs @@ -1,10 +1,10 @@ use crate::prelude::*; + use rustc_index::{Idx, IndexSlice}; -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] -pub struct IndexVec { +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct IndexVec { pub raw: Vec, _marker: std::marker::PhantomData, } @@ -68,7 +68,7 @@ where macro_rules! make_idx_wrapper { ($($mod:ident)::+, $type:ident) => { - #[derive(Copy, Clone, Eq, Debug, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema)] + #[derive_group(Serializers)]#[derive(Copy, Clone, Eq, Debug, Hash, PartialEq, PartialOrd, Ord, JsonSchema)] #[serde(untagged)] pub enum $type { $type(usize), diff --git a/frontend/exporter/src/prelude.rs b/frontend/exporter/src/prelude.rs index 977d3d4c5..d7350e868 100644 --- a/frontend/exporter/src/prelude.rs +++ b/frontend/exporter/src/prelude.rs @@ -13,3 +13,5 @@ pub use crate::rustc_utils::*; pub use crate::state::*; pub use crate::traits::*; pub use crate::types::*; + +pub(crate) use hax_adt_into::derive_group; diff --git a/frontend/exporter/src/sinto.rs b/frontend/exporter/src/sinto.rs index 81e24e56e..9ee74934c 100644 --- a/frontend/exporter/src/sinto.rs +++ b/frontend/exporter/src/sinto.rs @@ -1,5 +1,4 @@ -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; +use crate::prelude::{derive_group, JsonSchema}; pub trait SInto { fn sinto(&self, s: &S) -> To; @@ -8,7 +7,8 @@ pub trait SInto { #[macro_export] macro_rules! sinto_todo { ($($mod:ident)::+, $type:ident$(<$($lts:lifetime),*$(,)?>)? as $renamed:ident) => { - #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] + #[derive_group(Serializers)] + #[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum $renamed { $type { todo: String diff --git a/frontend/exporter/src/state.rs b/frontend/exporter/src/state.rs index e5563a18c..1bd1508c1 100644 --- a/frontend/exporter/src/state.rs +++ b/frontend/exporter/src/state.rs @@ -240,7 +240,8 @@ pub trait UnderOwnerState<'tcx> = BaseState<'tcx> + HasOwnerId; /// Meta-informations about an `impl TRAIT for /// TYPE where PREDICATES {}` -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct ImplInfos { pub generics: TyGenerics, pub clauses: Vec<(Clause, Span)>, diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 368d13a47..97df6f9ad 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -1,10 +1,10 @@ use crate::prelude::*; + #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: search_clause::PathChunk<'tcx>, state: S as tcx)] -#[derive( - Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema)] pub enum ImplExprPathChunk { AssocItem { item: AssocItem, @@ -21,9 +21,8 @@ pub enum ImplExprPathChunk { /// The source of a particular trait implementation. Most often this is either `Concrete` for a /// concrete `impl Trait for Type {}` item, or `LocalBound` for a context-bound `where T: Trait`. -#[derive( - Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema)] pub enum ImplExprAtom { /// A concrete `impl Trait for Type {}` item. Concrete { @@ -58,9 +57,8 @@ pub enum ImplExprAtom { /// need to combine several concrete trait implementation items. For example, `((1u8, 2u8), /// "hello").clone()` combines the generic implementation of `Clone` for `(A, B)` with the /// concrete implementations for `u8` and `&str`, represented as a tree. -#[derive( - Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema)] pub struct ImplExpr { /// The trait this is an impl for. pub r#trait: TraitRef, diff --git a/frontend/exporter/src/types/copied.rs b/frontend/exporter/src/types/copied.rs index 1ed39f821..0f81a3ce0 100644 --- a/frontend/exporter/src/types/copied.rs +++ b/frontend/exporter/src/types/copied.rs @@ -63,9 +63,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_hir::def_id } /// Reflects [`rustc_middle::thir::LogicalOp`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'a, S>, from: rustc_middle::thir::LogicalOp, state: S as _s)] pub enum LogicalOp { And, @@ -73,9 +72,8 @@ pub enum LogicalOp { } /// Reflects [`rustc_middle::thir::LintLevel`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'slt, S: UnderOwnerState<'slt> + HasThir<'slt>>, from: rustc_middle::thir::LintLevel, state: S as gstate)] pub enum LintLevel { Inherited, @@ -83,9 +81,8 @@ pub enum LintLevel { } /// Reflects [`rustc_ast::ast::AttrStyle`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(, from: rustc_ast::ast::AttrStyle, state: S as _s)] pub enum AttrStyle { Outer, @@ -93,9 +90,8 @@ pub enum AttrStyle { } /// Reflects [`rustc_ast::ast::Attribute`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'slt, S: BaseState<'slt>>, from: rustc_ast::ast::Attribute, state: S as gstate)] pub struct Attribute { pub kind: AttrKind, @@ -107,9 +103,8 @@ pub struct Attribute { /// Generic container for decorating items with a type, a span, /// attributes and other meta-data. -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Decorated { pub ty: Ty, pub span: Span, @@ -119,7 +114,8 @@ pub struct Decorated { } /// Reflects [`rustc_middle::mir::UnOp`] -#[derive(AdtInto, Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Copy, Clone, Debug, JsonSchema)] #[args(<'slt, S: UnderOwnerState<'slt>>, from: rustc_middle::mir::UnOp, state: S as _s)] pub enum UnOp { Not, @@ -128,7 +124,8 @@ pub enum UnOp { } /// Reflects [`rustc_middle::mir::BinOp`] -#[derive(AdtInto, Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Copy, Clone, Debug, JsonSchema)] #[args(<'slt, S: UnderOwnerState<'slt>>, from: rustc_middle::mir::BinOp, state: S as _s)] pub enum BinOp { // We merge the checked and unchecked variants because in either case overflow is failure. @@ -174,7 +171,8 @@ pub type Pat = Decorated; pub type Expr = Decorated; /// Reflects [`rustc_middle::mir::BinOp`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasThir<'tcx>>, from: rustc_middle::middle::region::ScopeData, state: S as gstate)] pub enum ScopeData { Node, @@ -186,7 +184,8 @@ pub enum ScopeData { } /// Reflects [`rustc_middle::mir::BinOp`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasThir<'tcx>>, from: rustc_middle::middle::region::Scope, state: S as gstate)] pub struct Scope { pub id: ItemLocalId, @@ -240,9 +239,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::Ty<'tcx> } /// Reflects [`rustc_hir::hir_id::HirId`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_hir::hir_id::HirId, state: S as gstate)] pub struct HirId { owner: DefId, @@ -258,18 +256,16 @@ impl<'tcx, S: BaseState<'tcx>> SInto for rustc_hir::hir_id::OwnerId { } /// Reflects [`rustc_ast::ast::LitFloatType`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_ast::ast::LitFloatType, state: S as gstate)] pub enum LitFloatType { Suffixed(FloatTy), Unsuffixed, } /// Reflects [`rustc_hir::Movability`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S>, from: rustc_hir::Movability, state: S as _s)] pub enum Movability { Static, @@ -277,7 +273,8 @@ pub enum Movability { } /// Reflects [`rustc_middle::infer::canonical::CanonicalTyVarKind`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::infer::canonical::CanonicalTyVarKind, state: S as gstate)] pub enum CanonicalTyVarKind { General(UniverseIndex), @@ -286,9 +283,8 @@ pub enum CanonicalTyVarKind { } /// Reflects [`rustc_middle::ty::ParamTy`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::ParamTy, state: S as gstate)] pub struct ParamTy { pub index: u32, @@ -296,9 +292,8 @@ pub struct ParamTy { } /// Reflects [`rustc_middle::ty::ParamConst`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(, from: rustc_middle::ty::ParamConst, state: S as gstate)] pub struct ParamConst { pub index: u32, @@ -347,9 +342,8 @@ pub struct ExistentialProjection { } /// Reflects [`rustc_middle::ty::DynKind`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(, from: rustc_middle::ty::DynKind, state: S as _s)] pub enum DynKind { Dyn, @@ -357,9 +351,8 @@ pub enum DynKind { } /// Reflects [`rustc_middle::ty::BoundTyKind`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::BoundTyKind, state: S as gstate)] pub enum BoundTyKind { Anon, @@ -367,9 +360,8 @@ pub enum BoundTyKind { } /// Reflects [`rustc_middle::ty::BoundTy`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::BoundTy, state: S as gstate)] pub struct BoundTy { pub var: BoundVar, @@ -377,9 +369,8 @@ pub struct BoundTy { } /// Reflects [`rustc_middle::ty::BoundRegionKind`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::BoundRegionKind, state: S as gstate)] pub enum BoundRegionKind { BrAnon, @@ -388,9 +379,8 @@ pub enum BoundRegionKind { } /// Reflects [`rustc_middle::ty::BoundRegion`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::BoundRegion, state: S as gstate)] pub struct BoundRegion { pub var: BoundVar, @@ -405,9 +395,8 @@ pub type PlaceholderConst = Placeholder; pub type PlaceholderType = Placeholder; /// Reflects [`rustc_middle::ty::Placeholder`] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Placeholder { pub universe: UniverseIndex, pub bound: T, @@ -425,7 +414,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>, T: SInto, U> SInto> } /// Reflects [`rustc_middle::infer::canonical::Canonical`] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct Canonical { pub max_universe: UniverseIndex, pub variables: Vec, @@ -447,7 +437,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>, T: SInto, U> SInto> } /// Reflects [`rustc_middle::infer::canonical::CanonicalVarKind`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::infer::canonical::CanonicalVarKind>, state: S as gstate)] pub enum CanonicalVarInfo { Ty(CanonicalTyVarKind), @@ -460,7 +451,8 @@ pub enum CanonicalVarInfo { } /// Reflects [`rustc_middle::ty::UserSelfTy`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::UserSelfTy<'tcx>, state: S as gstate)] pub struct UserSelfTy { pub impl_def_id: DefId, @@ -468,7 +460,8 @@ pub struct UserSelfTy { } /// Reflects [`rustc_middle::ty::UserArgs`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::UserArgs<'tcx>, state: S as gstate)] pub struct UserArgs { pub args: Vec, @@ -478,7 +471,8 @@ pub struct UserArgs { /// Reflects [`rustc_middle::ty::UserType`]: this is currently /// disabled, and everything is printed as debug in the /// [`UserType::Todo`] variant. -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::UserType<'tcx>, state: S as _s)] pub enum UserType { // TODO: for now, we don't use user types at all. @@ -508,7 +502,8 @@ pub enum UserType { } /// Reflects [`rustc_hir::def::CtorKind`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(, from: rustc_hir::def::CtorKind, state: S as _s)] pub enum CtorKind { Fn, @@ -516,7 +511,8 @@ pub enum CtorKind { } /// Reflects [`rustc_middle::ty::VariantDiscr`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::VariantDiscr, state: S as gstate)] pub enum DiscriminantDefinition { Explicit(DefId), @@ -524,7 +520,8 @@ pub enum DiscriminantDefinition { } /// Reflects [`rustc_middle::ty::util::Discr`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::util::Discr<'tcx>, state: S as gstate)] pub struct DiscriminantValue { pub val: u128, @@ -532,7 +529,8 @@ pub struct DiscriminantValue { } /// Reflects [`rustc_middle::ty::Visibility`] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum Visibility { Public, Restricted(Id), @@ -548,7 +546,8 @@ impl, U> SInto> for rustc_middle::ty::Visibil } /// Reflects [`rustc_middle::ty::FieldDef`] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct FieldDef { pub did: DefId, /// Field definition of [tuple @@ -589,7 +588,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::Fi } /// Reflects [`rustc_middle::ty::VariantDef`] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct VariantDef { pub def_id: DefId, pub ctor: Option<(CtorKind, DefId)>, @@ -624,9 +624,8 @@ impl VariantDef { } /// Reflects [`rustc_middle::ty::EarlyParamRegion`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::EarlyParamRegion, state: S as gstate)] pub struct EarlyParamRegion { pub index: u32, @@ -634,9 +633,8 @@ pub struct EarlyParamRegion { } /// Reflects [`rustc_middle::ty::LateParamRegion`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::LateParamRegion, state: S as gstate)] pub struct LateParamRegion { pub scope: DefId, @@ -644,9 +642,8 @@ pub struct LateParamRegion { } /// Reflects [`rustc_middle::ty::RegionKind`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::RegionKind<'tcx>, state: S as gstate)] pub enum RegionKind { ReEarlyParam(EarlyParamRegion), @@ -660,9 +657,8 @@ pub enum RegionKind { } /// Reflects [`rustc_middle::ty::Region`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::Region<'tcx>, state: S as s)] pub struct Region { #[value(self.kind().sinto(s))] @@ -670,9 +666,8 @@ pub struct Region { } /// Reflects both [`rustc_middle::ty::GenericArg`] and [`rustc_middle::ty::GenericArgKind`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::GenericArgKind<'tcx>, state: S as s)] pub enum GenericArg { Lifetime(Region), @@ -697,16 +692,16 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto> /// Reflects both [`rustc_middle::ty::GenericArg`] and [`rustc_middle::ty::GenericArgKind`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_ast::ast::LitIntType, state: S as gstate)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum LitIntType { Signed(IntTy), Unsigned(UintTy), Unsuffixed, } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: ExprState<'tcx>>, from: rustc_middle::thir::FruInfo<'tcx>, state: S as gstate)] /// Field Record Update (FRU) informations, this reflects [`rustc_middle::thir::FruInfo`] pub struct FruInfo { @@ -716,21 +711,24 @@ pub struct FruInfo { } /// A field expression: a field name along with a value -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct FieldExpr { pub field: DefId, pub value: Expr, } /// A field pattern: a field name along with a pattern -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct FieldPat { pub field: DefId, pub pattern: Pat, } /// Reflects [`rustc_middle::thir::AdtExpr`] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct AdtExpr { pub info: VariantInformations, pub user_ty: Option, @@ -759,16 +757,16 @@ impl<'tcx, S: ExprState<'tcx>> SInto for rustc_middle::thir::AdtExpr } /// Reflects [`rustc_span::Loc`] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Loc { pub line: usize, pub col: usize, } /// Reflects [`rustc_span::hygiene::DesugaringKind`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(, from: rustc_span::hygiene::DesugaringKind, state: S as _s)] pub enum DesugaringKind { CondTemporary, @@ -784,7 +782,8 @@ pub enum DesugaringKind { } /// Reflects [`rustc_span::hygiene::AstPass`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(, from: rustc_span::hygiene::AstPass, state: S as _s)] pub enum AstPass { StdImports, @@ -793,7 +792,8 @@ pub enum AstPass { } /// Reflects [`rustc_span::hygiene::MacroKind`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(, from: rustc_span::hygiene::MacroKind, state: S as _s)] pub enum MacroKind { Bang, @@ -804,7 +804,8 @@ pub enum MacroKind { /// Reflects [`rustc_span::hygiene::ExpnKind`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_span::hygiene::ExpnKind, state: S as gstate)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum ExpnKind { Root, Macro(MacroKind, Symbol), @@ -815,7 +816,8 @@ pub enum ExpnKind { /// Reflects [`rustc_span::edition::Edition`] #[derive(AdtInto)] #[args(, from: rustc_span::edition::Edition, state: S as _s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum Edition { Edition2015, Edition2018, @@ -826,7 +828,8 @@ pub enum Edition { /// Reflects [`rustc_span::hygiene::ExpnData`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_span::hygiene::ExpnData, state: S as state)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct ExpnData { pub kind: ExpnKind, // pub parent: Box, @@ -841,7 +844,7 @@ pub struct ExpnData { } /// Reflects [`rustc_span::Span`] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, Eq, Ord)] +#[derive(::serde::Serialize, ::serde::Deserialize, Clone, Debug, JsonSchema, Eq, Ord)] pub struct Span { pub lo: Loc, pub hi: Loc, @@ -853,6 +856,44 @@ pub struct Span { // expn_backtrace: Vec, } +impl bincode::Encode for Span { + fn encode( + &self, + encoder: &mut E, + ) -> core::result::Result<(), bincode::error::EncodeError> { + bincode::Encode::encode(&self.lo, encoder)?; + bincode::Encode::encode(&self.hi, encoder)?; + bincode::Encode::encode(&self.filename, encoder)?; + Ok(()) + } +} + +impl bincode::Decode for Span { + fn decode( + decoder: &mut D, + ) -> core::result::Result { + Ok(Self { + lo: bincode::Decode::decode(decoder)?, + hi: bincode::Decode::decode(decoder)?, + filename: bincode::Decode::decode(decoder)?, + rust_span_data: None, + }) + } +} + +impl<'de> bincode::BorrowDecode<'de> for Span { + fn borrow_decode>( + decoder: &mut D, + ) -> core::result::Result { + Ok(Self { + lo: bincode::BorrowDecode::borrow_decode(decoder)?, + hi: bincode::BorrowDecode::borrow_decode(decoder)?, + filename: bincode::BorrowDecode::borrow_decode(decoder)?, + rust_span_data: None, + }) + } +} + const _: () = { // `rust_span_data` is a metadata that should *not* be taken into // account while hashing or comparing @@ -901,7 +942,8 @@ impl<'tcx, S: BaseState<'tcx>> SInto for rustc_span::Span { } /// Reflects [`rustc_middle::thir::LocalVarId`] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct LocalIdent { pub name: String, pub id: HirId, @@ -925,7 +967,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::thir } /// Reflects [`rustc_span::source_map::Spanned`] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct Spanned { pub node: T, pub span: Span, @@ -948,9 +991,8 @@ impl<'tcx, S> SInto for PathBuf { } /// Reflects [`rustc_span::RealFileName`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, PartialEq, Eq, Hash, PartialOrd, Ord)] #[args(, from: rustc_span::RealFileName, state: S as _s)] pub enum RealFileName { LocalPath(PathBuf), @@ -969,9 +1011,8 @@ impl SInto for rustc_data_structures::stable_hasher::Hash64 { /// Reflects [`rustc_span::FileName`] #[derive(AdtInto)] #[args(, from: rustc_span::FileName, state: S as gstate)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Hash, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum FileName { Real(RealFileName), QuoteExpansion(u64), @@ -1016,9 +1057,8 @@ impl FileName { } /// Reflects partially [`rustc_middle::ty::InferTy`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S>, from: rustc_middle::ty::InferTy, state: S as gstate)] pub enum InferTy { #[custom_arm(FROM_TYPE::TyVar(..) => TO_TYPE::TyVar,)] @@ -1033,7 +1073,8 @@ pub enum InferTy { } /// Reflects [`rustc_middle::thir::BlockSafety`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S>, from: rustc_middle::thir::BlockSafety, state: S as _s)] pub enum BlockSafety { Safe, @@ -1043,7 +1084,8 @@ pub enum BlockSafety { } /// Reflects [`rustc_middle::thir::Block`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: ExprState<'tcx>>, from: rustc_middle::thir::Block, state: S as gstate)] pub struct Block { pub targeted_by_break: bool, @@ -1057,7 +1099,8 @@ pub struct Block { /// Reflects [`rustc_ast::ast::BindingMode`] #[derive(AdtInto)] #[args(, from: rustc_ast::ast::BindingMode, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct BindingMode { #[value(self.0.sinto(s))] pub by_ref: ByRef, @@ -1068,7 +1111,8 @@ pub struct BindingMode { /// Reflects [`rustc_ast::ast::ByRef`] #[derive(AdtInto)] #[args(, from: rustc_ast::ast::ByRef, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum ByRef { Yes(Mutability), No, @@ -1077,7 +1121,8 @@ pub enum ByRef { /// Reflects [`rustc_middle::thir::Stmt`] #[derive(AdtInto)] #[args(<'tcx, S: ExprState<'tcx>>, from: rustc_middle::thir::Stmt<'tcx>, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct Stmt { pub kind: StmtKind, } @@ -1085,9 +1130,8 @@ pub struct Stmt { /// Reflects [`rustc_ast::token::Delimiter`] #[derive(AdtInto)] #[args(, from: rustc_ast::token::Delimiter, state: S as _s)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Delimiter { Parenthesis, Brace, @@ -1098,9 +1142,8 @@ pub enum Delimiter { /// Reflects [`rustc_ast::tokenstream::TokenTree`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_ast::tokenstream::TokenTree, state: S as s)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum TokenTree { Token(Token, Spacing), Delimited(DelimSpan, DelimSpacing, Delimiter, TokenStream), @@ -1109,9 +1152,8 @@ pub enum TokenTree { /// Reflects [`rustc_ast::tokenstream::Spacing`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_ast::tokenstream::Spacing, state: S as _s)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Spacing { Alone, Joint, @@ -1121,9 +1163,8 @@ pub enum Spacing { /// Reflects [`rustc_ast::token::BinOpToken`] #[derive(AdtInto)] #[args(, from: rustc_ast::token::BinOpToken, state: S as _s)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum BinOpToken { Plus, Minus, @@ -1140,9 +1181,8 @@ pub enum BinOpToken { /// Reflects [`rustc_ast::token::TokenKind`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_ast::token::TokenKind, state: S as gstate)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum TokenKind { Eq, Lt, @@ -1196,9 +1236,8 @@ impl SInto for rustc_ast::token::IdentIsRaw { /// Reflects [`rustc_ast::token::Token`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_ast::token::Token, state: S as gstate)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Token { pub kind: TokenKind, pub span: Span, @@ -1207,9 +1246,8 @@ pub struct Token { /// Reflects [`rustc_ast::ast::DelimArgs`] #[derive(AdtInto)] #[args(, from: rustc_ast::ast::DelimArgs, state: S as gstate)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct DelimArgs { pub dspan: DelimSpan, pub delim: Delimiter, @@ -1219,9 +1257,8 @@ pub struct DelimArgs { /// Reflects [`rustc_ast::ast::MacCall`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_ast::ast::MacCall, state: S as gstate)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct MacCall { #[map(x.segments.iter().map(|rustc_ast::ast::PathSegment{ident, ..}| ident.as_str().into()).collect())] pub path: Path, @@ -1455,9 +1492,8 @@ impl<'tcx, S: ExprState<'tcx>> SInto for rustc_middle::thir::ArmId { /// Reflects [`rustc_type_ir::IntTy`] #[derive(AdtInto)] #[args(, from: rustc_type_ir::IntTy, state: S as _s)] -#[derive( - Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Copy, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum IntTy { Isize, I8, @@ -1470,9 +1506,8 @@ pub enum IntTy { /// Reflects [`rustc_type_ir::FloatTy`] #[derive(AdtInto)] #[args(, from: rustc_type_ir::FloatTy, state: S as _s)] -#[derive( - Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Copy, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum FloatTy { F16, F32, @@ -1522,9 +1557,8 @@ impl<'tcx, S> SInto for rustc_ast::ast::UintTy { /// Reflects [`rustc_type_ir::UintTy`] #[derive(AdtInto)] #[args(, from: rustc_type_ir::UintTy, state: S as _s)] -#[derive( - Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Copy, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum UintTy { Usize, U8, @@ -1565,9 +1599,8 @@ impl ToString for UintTy { /// Reflects [`rustc_middle::ty::TypeAndMut`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::TypeAndMut<'tcx>, state: S as gstate)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct TypeAndMut { pub ty: Box, pub mutbl: Mutability, @@ -1582,7 +1615,8 @@ impl> SInto> for rustc_middle::ty::List { /// Reflects [`rustc_middle::ty::GenericParamDef`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::GenericParamDef, state: S as state)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct GenericParamDef { pub name: Symbol, pub def_id: DefId, @@ -1594,7 +1628,8 @@ pub struct GenericParamDef { /// Reflects [`rustc_middle::ty::GenericParamDefKind`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::GenericParamDefKind, state: S as state)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum GenericParamDefKind { Lifetime, Type { has_default: bool, synthetic: bool }, @@ -1604,7 +1639,8 @@ pub enum GenericParamDefKind { /// Reflects [`rustc_middle::ty::Generics`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::Generics, state: S as state)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct TyGenerics { pub parent: Option, pub parent_count: usize, @@ -1617,9 +1653,8 @@ pub struct TyGenerics { /// This type merges the information from /// `rustc_type_ir::AliasKind` and `rustc_middle::ty::AliasTy` -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Alias { pub kind: AliasKind, pub args: Vec, @@ -1627,9 +1662,8 @@ pub struct Alias { } /// Reflects [`rustc_middle::ty::AliasKind`] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum AliasKind { /// The projection of a trait type: `>::Type<...>` Projection { @@ -1719,9 +1753,8 @@ impl Alias { /// Reflects [`rustc_middle::ty::TyKind`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::TyKind<'tcx>, state: S as state)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Ty { Bool, Char, @@ -1793,7 +1826,8 @@ pub enum Ty { /// Reflects [`rustc_middle::thir::StmtKind`] #[derive(AdtInto)] #[args(<'tcx, S: ExprState<'tcx>>, from: rustc_middle::thir::StmtKind<'tcx>, state: S as gstate)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum StmtKind { Expr { scope: Scope, @@ -1815,7 +1849,8 @@ pub enum StmtKind { /// Reflects [`rustc_middle::ty::Variance`] #[derive(AdtInto)] #[args(, from: rustc_middle::ty::Variance, state: S as _s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum Variance { Covariant, Invariant, @@ -1826,7 +1861,8 @@ pub enum Variance { /// Reflects [`rustc_middle::ty::CanonicalUserTypeAnnotation`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::CanonicalUserTypeAnnotation<'tcx>, state: S as gstate)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct CanonicalUserTypeAnnotation { pub user_ty: CanonicalUserType, pub span: Span, @@ -1836,7 +1872,8 @@ pub struct CanonicalUserTypeAnnotation { /// Reflects [`rustc_middle::thir::Ascription`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasThir<'tcx>>, from: rustc_middle::thir::Ascription<'tcx>, state: S as gstate)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct Ascription { pub annotation: CanonicalUserTypeAnnotation, pub variance: Variance, @@ -1845,7 +1882,8 @@ pub struct Ascription { /// Reflects [`rustc_hir::RangeEnd`] #[derive(AdtInto)] #[args(, from: rustc_hir::RangeEnd, state: S as _s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum RangeEnd { Included, Excluded, @@ -1854,7 +1892,8 @@ pub enum RangeEnd { /// Reflects [`rustc_middle::thir::PatRange`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasThir<'tcx>>, from: rustc_middle::thir::PatRange<'tcx>, state: S as state)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct PatRange { pub lo: PatRangeBoundary, pub hi: PatRangeBoundary, @@ -1864,7 +1903,8 @@ pub struct PatRange { /// Reflects [`rustc_middle::thir::PatRangeBoundary`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasThir<'tcx>>, from: rustc_middle::thir::PatRangeBoundary<'tcx>, state: S as state)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum PatRangeBoundary { Finite(ConstantExpr), NegInfinity, @@ -1872,7 +1912,8 @@ pub enum PatRangeBoundary { } /// Reflects [`rustc_middle::ty::AdtKind`] -#[derive(AdtInto, Copy, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Copy, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::AdtKind, state: S as _s)] pub enum AdtKind { Struct, @@ -1883,7 +1924,8 @@ pub enum AdtKind { // This comes from MIR // TODO: add the generics and the predicates /// Reflects [`rustc_middle::ty::AdtDef`] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct AdtDef { pub did: DefId, pub adt_kind: AdtKind, @@ -1893,7 +1935,8 @@ pub struct AdtDef { } /// Reflects [`rustc_middle::ty::ReprOptions`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::ReprOptions, state: S as s)] pub struct ReprOptions { pub int: Option, @@ -1938,9 +1981,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::AdtD } /// Describe a variant -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct VariantInformations { pub type_namespace: DefId, @@ -1962,7 +2004,8 @@ pub struct VariantInformations { /// Reflects [`rustc_middle::thir::PatKind`] #[derive(AdtInto)] #[args(<'tcx, S: ExprState<'tcx>>, from: rustc_middle::thir::PatKind<'tcx>, state: S as gstate)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] #[append(rustc_middle::thir::PatKind::Leaf {..} => fatal!(gstate, "PatKind::Leaf: should never come up"),)] pub enum PatKind { Wild, @@ -2050,7 +2093,8 @@ pub enum PatKind { /// Reflects [`rustc_middle::thir::Arm`] #[derive(AdtInto)] #[args(<'tcx, S: ExprState<'tcx>>, from: rustc_middle::thir::Arm<'tcx>, state: S as gstate)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct Arm { pub pattern: Pat, pub guard: Option, @@ -2065,9 +2109,8 @@ pub struct Arm { /// Reflects [`rustc_hir::Safety`] #[derive(AdtInto)] #[args(, from: rustc_hir::Safety, state: S as _s)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Safety { Unsafe, Safe, @@ -2076,7 +2119,8 @@ pub enum Safety { /// Reflects [`rustc_middle::ty::adjustment::PointerCoercion`] #[derive(AdtInto)] #[args(, from: rustc_middle::ty::adjustment::PointerCoercion, state: S as gstate)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum PointerCoercion { ReifyFnPointer, UnsafeFnPointer, @@ -2089,9 +2133,8 @@ pub enum PointerCoercion { /// Reflects [`rustc_middle::mir::BorrowKind`] #[derive(AdtInto)] #[args(, from: rustc_middle::mir::BorrowKind, state: S as gstate)] -#[derive( - Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Copy, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum BorrowKind { Shared, Fake(FakeBorrowKind), @@ -2101,9 +2144,8 @@ pub enum BorrowKind { /// Reflects [`rustc_middle::mir::MutBorrowKind`] #[derive(AdtInto)] #[args(, from: rustc_middle::mir::MutBorrowKind, state: S as _s)] -#[derive( - Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Copy, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum MutBorrowKind { Default, TwoPhaseBorrow, @@ -2113,9 +2155,8 @@ pub enum MutBorrowKind { /// Reflects [`rustc_middle::mir::FakeBorrowKind`] #[derive(AdtInto)] #[args(, from: rustc_middle::mir::FakeBorrowKind, state: S as _s)] -#[derive( - Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Copy, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum FakeBorrowKind { /// A shared (deep) borrow. Data must be immutable and is aliasable. Deep, @@ -2129,9 +2170,8 @@ pub enum FakeBorrowKind { /// Reflects [`rustc_ast::ast::StrStyle`] #[derive(AdtInto)] #[args(, from: rustc_ast::ast::StrStyle, state: S as gstate)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum StrStyle { Cooked, Raw(u8), @@ -2140,9 +2180,8 @@ pub enum StrStyle { /// Reflects [`rustc_ast::ast::LitKind`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_ast::ast::LitKind, state: S as gstate)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum LitKind { Str(Symbol, StrStyle), ByteStr(Vec, StrStyle), @@ -2170,7 +2209,8 @@ impl SInto for rustc_data_structures::packed::Pu128 { #[allow(rustdoc::private_intra_doc_links)] /// Describe a macro invocation, using /// [`macro_invocation_of_raw_mac_invocation`] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct MacroInvokation { pub macro_ident: DefId, pub argument: String, @@ -2180,7 +2220,8 @@ pub struct MacroInvokation { /// Reflects [`rustc_hir::ImplicitSelfKind`] #[derive(AdtInto)] #[args(, from: rustc_hir::ImplicitSelfKind, state: S as _s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum ImplicitSelfKind { Imm, Mut, @@ -2192,9 +2233,8 @@ pub enum ImplicitSelfKind { /// Reflects [`rustc_ast::token::CommentKind`] #[derive(AdtInto)] #[args(, from: rustc_ast::token::CommentKind, state: S as _s)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum CommentKind { Line, Block, @@ -2203,9 +2243,8 @@ pub enum CommentKind { /// Reflects [`rustc_ast::ast::AttrArgs`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_ast::ast::AttrArgs, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum AttrArgs { Empty, Delimited(DelimArgs), @@ -2218,9 +2257,8 @@ pub enum AttrArgs { /// Reflects [`rustc_ast::ast::AttrArgsEq`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_ast::ast::AttrArgsEq, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum AttrArgsEq { Hir(MetaItemLit), #[todo] @@ -2231,9 +2269,8 @@ pub enum AttrArgsEq { /// Reflects [`rustc_ast::ast::MetaItemLit`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_ast::ast::MetaItemLit, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct MetaItemLit { pub symbol: Symbol, pub suffix: Option, @@ -2244,9 +2281,8 @@ pub struct MetaItemLit { /// Reflects [`rustc_ast::ast::AttrItem`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_ast::ast::AttrItem, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct AttrItem { #[map(rustc_ast_pretty::pprust::path_to_string(x))] pub path: String, @@ -2263,9 +2299,8 @@ impl SInto for rustc_ast::tokenstream::LazyAttrTokenStream { /// Reflects [`rustc_ast::ast::NormalAttr`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_ast::ast::NormalAttr, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct NormalAttr { pub item: AttrItem, pub tokens: Option, @@ -2274,9 +2309,8 @@ pub struct NormalAttr { /// Reflects [`rustc_ast::AttrKind`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_ast::AttrKind, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum AttrKind { Normal(NormalAttr), DocComment(CommentKind, Symbol), @@ -2285,7 +2319,8 @@ pub enum AttrKind { /// Reflects [`rustc_middle::thir::Param`] #[derive(AdtInto)] #[args(<'tcx, S: ExprState<'tcx>>, from: rustc_middle::thir::Param<'tcx>, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct Param { pub pat: Option, pub ty: Ty, @@ -2302,7 +2337,8 @@ pub struct Param { /// Reflects [`rustc_middle::thir::ExprKind`] #[derive(AdtInto)] #[args(<'tcx, S: ExprState<'tcx>>, from: rustc_middle::thir::ExprKind<'tcx>, state: S as gstate)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] #[append( rustc_middle::thir::ExprKind::Scope {..} => { fatal!(gstate, "Scope should have been eliminated at this point"); @@ -2658,9 +2694,8 @@ impl<'tcx> ExprKindExt<'tcx> for rustc_middle::thir::Expr<'tcx> { } /// Reflects [`rustc_middle::ty::FnSig`] -#[derive( - AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::FnSig<'tcx>, state: S as s)] pub struct TyFnSig { #[value(self.inputs().sinto(s))] @@ -2676,7 +2711,8 @@ pub struct TyFnSig { pub type PolyFnSig = Binder; /// Function definition -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct FnDef { pub header: FnHeader, pub params: Vec, @@ -2686,7 +2722,8 @@ pub struct FnDef { } /// Reflects [`rustc_hir::FnDecl`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::FnDecl<'tcx>, state: S as tcx)] pub struct FnDecl { pub inputs: Vec, @@ -2697,7 +2734,8 @@ pub struct FnDecl { } /// Reflects [`rustc_hir::FnSig`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::FnSig<'tcx>, state: S as tcx)] pub struct FnSig { pub header: FnHeader, @@ -2706,7 +2744,8 @@ pub struct FnSig { } /// Reflects [`rustc_hir::FnHeader`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_hir::FnHeader, state: S as tcx)] pub struct FnHeader { pub safety: Safety, @@ -2733,7 +2772,8 @@ impl<'x: 'tcx, 'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_hir::Ty<'x /// Reflects [`rustc_hir::UseKind`] #[derive(AdtInto)] #[args(, from: rustc_hir::UseKind, state: S as _s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum UseKind { Single, Glob, @@ -2743,7 +2783,8 @@ pub enum UseKind { /// Reflects [`rustc_hir::IsAuto`] #[derive(AdtInto)] #[args(, from: rustc_hir::IsAuto, state: S as _s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum IsAuto { Yes, No, @@ -2752,7 +2793,8 @@ pub enum IsAuto { /// Reflects [`rustc_hir::Defaultness`] #[derive(AdtInto)] #[args(, from: rustc_hir::Defaultness, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum Defaultness { Default { has_value: bool }, Final, @@ -2761,7 +2803,8 @@ pub enum Defaultness { /// Reflects [`rustc_hir::ImplPolarity`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_hir::ImplPolarity, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum ImplPolarity { Positive, Negative(Span), @@ -2770,7 +2813,8 @@ pub enum ImplPolarity { /// Reflects [`rustc_hir::Constness`] #[derive(AdtInto)] #[args(, from: rustc_hir::Constness, state: S as _s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum Constness { Const, NotConst, @@ -2779,7 +2823,8 @@ pub enum Constness { /// Reflects [`rustc_hir::Generics`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::Generics<'tcx>, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct Generics { pub params: Vec>, pub predicates: Vec>, @@ -2793,7 +2838,8 @@ pub struct Generics { /// Reflects [`rustc_hir::WherePredicate`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::WherePredicate<'tcx>, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum WherePredicate { BoundPredicate(WhereBoundPredicate), RegionPredicate(WhereRegionPredicate), @@ -2812,7 +2858,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>, Body: IsBody> SInto> } /// Reflects [`rustc_hir::ParamName`] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum ParamName { Plain(LocalIdent), Fresh, @@ -2822,7 +2869,8 @@ pub enum ParamName { /// Reflects [`rustc_hir::LifetimeParamKind`] #[derive(AdtInto)] #[args(, from: rustc_hir::LifetimeParamKind, state: S as _s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum LifetimeParamKind { Explicit, Elided(MissingLifetimeKind), @@ -2830,7 +2878,8 @@ pub enum LifetimeParamKind { } /// Reflects [`rustc_hir::AnonConst`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_hir::AnonConst, state: S as s)] pub struct AnonConst { pub hir_id: HirId, @@ -2842,7 +2891,8 @@ pub struct AnonConst { } /// Reflects [`rustc_hir::GenericParamKind`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::GenericParamKind<'tcx>, state: S as tcx)] pub enum GenericParamKind { Lifetime { @@ -2860,7 +2910,8 @@ pub enum GenericParamKind { } /// Reflects [`rustc_hir::GenericParam`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::GenericParam<'tcx>, state: S as s)] pub struct GenericParam { pub hir_id: HirId, @@ -2886,7 +2937,8 @@ pub struct GenericParam { } /// Reflects [`rustc_hir::ImplItem`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::ImplItem<'tcx>, state: S as s)] pub struct ImplItem { pub ident: Ident, @@ -2904,7 +2956,8 @@ pub struct ImplItem { /// Reflects [`rustc_hir::ImplItemKind`], inlining the body of the items. #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::ImplItemKind<'tcx>, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum ImplItemKind { Const(Ty, Body), #[custom_arm(rustc_hir::ImplItemKind::Fn(sig, body) => { @@ -2938,7 +2991,8 @@ pub enum ImplItemKind { /// Reflects [`rustc_hir::AssocItemKind`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_hir::AssocItemKind, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum AssocItemKind { Const, Fn { has_self: bool }, @@ -2960,7 +3014,8 @@ impl< /// Reflects [`rustc_hir::Impl`]. #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::Impl<'tcx>, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct Impl { pub safety: Safety, pub polarity: ImplPolarity, @@ -2995,7 +3050,8 @@ pub struct Impl { /// Reflects [`rustc_hir::IsAsync`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_hir::IsAsync, state: S as _s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum IsAsync { Async(Span), NotAsync, @@ -3004,14 +3060,16 @@ pub enum IsAsync { /// Reflects [`rustc_hir::FnRetTy`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::FnRetTy<'tcx>, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum FnRetTy { DefaultReturn(Span), Return(Ty), } /// Reflects [`rustc_hir::VariantData`] -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::VariantData<'tcx>, state: S as tcx)] pub enum VariantData { Struct { @@ -3034,7 +3092,8 @@ impl SInto for rustc_ast::ast::Recovered { /// Reflects [`rustc_hir::FieldDef`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::FieldDef<'tcx>, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct HirFieldDef { pub span: Span, pub vis_span: Span, @@ -3049,7 +3108,8 @@ pub struct HirFieldDef { /// Reflects [`rustc_hir::Variant`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::Variant<'tcx>, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct Variant { pub ident: Ident, pub hir_id: HirId, @@ -3075,7 +3135,8 @@ pub struct Variant { /// Reflects [`rustc_hir::UsePath`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_hir::UsePath<'tcx>, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct UsePath { pub span: Span, #[map(x.iter().map(|res| res.sinto(s)).collect())] @@ -3097,7 +3158,8 @@ pub struct UsePath { /// Reflects [`rustc_hir::def::Res`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_hir::def::Res, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum Res { Def(DefKind, DefId), PrimTy(PrimTy), @@ -3119,7 +3181,8 @@ pub enum Res { /// Reflects [`rustc_hir::PrimTy`] #[derive(AdtInto)] #[args(, from: rustc_hir::PrimTy, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum PrimTy { Int(IntTy), Uint(UintTy), @@ -3132,7 +3195,8 @@ pub enum PrimTy { /// Reflects [`rustc_hir::def::NonMacroAttrKind`] #[derive(AdtInto)] #[args(, from: rustc_hir::def::NonMacroAttrKind, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum NonMacroAttrKind { Builtin(Symbol), Tool, @@ -3143,7 +3207,8 @@ pub enum NonMacroAttrKind { /// Reflects [`rustc_hir::PathSegment`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_hir::PathSegment<'tcx>, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct PathSegment { pub ident: Ident, pub hir_id: HirId, @@ -3156,7 +3221,8 @@ pub struct PathSegment { /// Reflects [`rustc_hir::ItemKind`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::ItemKind<'tcx>, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum ItemKind { #[disable_mapping] MacroInvokation(MacroInvokation), @@ -3218,7 +3284,8 @@ pub type EnumDef = Vec>; /// Reflects [`rustc_hir::TraitItemKind`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::TraitItemKind<'tcx>, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, JsonSchema)] +#[derive_group(Serializers)] pub enum TraitItemKind { Const(Ty, Option), #[custom_arm( @@ -3246,7 +3313,8 @@ pub enum TraitItemKind { /// Reflects [`rustc_hir::TraitItem`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::TraitItem<'tcx>, state: S as s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct TraitItem { pub ident: Ident, pub owner_id: DefId, @@ -3291,7 +3359,8 @@ impl<'a, 'tcx, S: UnderOwnerState<'tcx>, Body: IsBody> SInto>> /// Reflects [`rustc_hir::ForeignItemKind`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::ForeignItemKind<'tcx>, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, JsonSchema)] +#[derive_group(Serializers)] pub enum ForeignItemKind { Fn(FnDecl, Vec, Generics, Safety), Static(Ty, Mutability, Safety), @@ -3301,7 +3370,8 @@ pub enum ForeignItemKind { /// Reflects [`rustc_hir::ForeignItem`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::ForeignItem<'tcx>, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct ForeignItem { pub ident: Ident, pub kind: ForeignItemKind, @@ -3322,7 +3392,8 @@ impl<'a, S: UnderOwnerState<'a>, Body: IsBody> SInto> /// Reflects [`rustc_hir::OpaqueTy`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::OpaqueTy<'tcx>, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct OpaqueTy { pub generics: Generics, pub bounds: GenericBounds, @@ -3333,7 +3404,8 @@ pub struct OpaqueTy { /// Reflects [`rustc_hir::LifetimeName`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_hir::LifetimeName, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, JsonSchema)] +#[derive_group(Serializers)] pub enum LifetimeName { Param(GlobalIdent), ImplicitObjectLifetimeDefault, @@ -3345,7 +3417,8 @@ pub enum LifetimeName { /// Reflects [`rustc_hir::Lifetime`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_hir::Lifetime, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct Lifetime { pub hir_id: HirId, pub ident: Ident, @@ -3353,11 +3426,10 @@ pub struct Lifetime { } /// Reflects [`rustc_middle::ty::TraitRef`] +#[derive_group(Serializers)] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::TraitRef<'tcx>, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct TraitRef { pub def_id: DefId, #[from(args)] @@ -3368,9 +3440,8 @@ pub struct TraitRef { /// Reflects [`rustc_middle::ty::TraitPredicate`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::TraitPredicate<'tcx>, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct TraitPredicate { pub trait_ref: TraitRef, #[map(x.clone() == rustc_middle::ty::PredicatePolarity::Positive)] @@ -3382,9 +3453,8 @@ pub struct TraitPredicate { /// instead of a tuple struct. This is because the script converting /// JSONSchema types to OCaml doesn't support tuple structs, and this /// is the only tuple struct in the whole AST. -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct OutlivesPredicate { pub lhs: T, pub rhs: Region, @@ -3409,9 +3479,8 @@ pub type RegionOutlivesPredicate = OutlivesPredicate; pub type TypeOutlivesPredicate = OutlivesPredicate; /// Reflects [`rustc_middle::ty::Term`] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum Term { Ty(Ty), Const(ConstantExpr), @@ -3435,9 +3504,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::Term<' /// ^^^^^^^^^^ /// ``` /// (provided the trait `Foo` has an associated type `S`). -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct ProjectionPredicate { /// The `impl Trait for Ty` in `Ty: Trait<..., Type = U>`. pub impl_expr: ImplExpr, @@ -3478,9 +3546,8 @@ impl<'tcx, S: BaseState<'tcx> + HasOwnerId> SInto /// Reflects [`rustc_middle::ty::ClauseKind`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::ClauseKind<'tcx>, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum ClauseKind { Trait(TraitPredicate), RegionOutlives(RegionOutlivesPredicate), @@ -3492,9 +3559,8 @@ pub enum ClauseKind { } /// Reflects [`rustc_middle::ty::Clause`] and adds a hash-consed predicate identifier. -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Clause { pub kind: Binder, pub id: PredicateId, @@ -3510,9 +3576,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::Clau } /// Reflects [`rustc_middle::ty::Predicate`] and adds a hash-consed predicate identifier. -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Predicate { pub kind: Binder, pub id: PredicateId, @@ -3530,9 +3595,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::P /// Reflects [`rustc_middle::ty::BoundVariableKind`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::BoundVariableKind, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum BoundVariableKind { Ty(BoundTyKind), Region(BoundRegionKind), @@ -3540,9 +3604,8 @@ pub enum BoundVariableKind { } /// Reflects [`rustc_middle::ty::Binder`] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct Binder { pub value: T, pub bound_vars: Vec, @@ -3551,9 +3614,8 @@ pub struct Binder { /// Reflects [`rustc_middle::ty::GenericPredicates`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::GenericPredicates<'tcx>, state: S as s)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct GenericPredicates { pub parent: Option, // FIXME: Switch from `Predicate` to `Clause` (will require correct handling of binders). @@ -3576,9 +3638,8 @@ where /// Reflects [`rustc_middle::ty::SubtypePredicate`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::SubtypePredicate<'tcx>, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct SubtypePredicate { pub a_is_expected: bool, pub a: Ty, @@ -3588,9 +3649,8 @@ pub struct SubtypePredicate { /// Reflects [`rustc_middle::ty::CoercePredicate`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::CoercePredicate<'tcx>, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct CoercePredicate { pub a: Ty, pub b: Ty, @@ -3599,9 +3659,8 @@ pub struct CoercePredicate { /// Reflects [`rustc_middle::ty::AliasRelationDirection`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::AliasRelationDirection, state: S as _tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum AliasRelationDirection { Equate, Subtype, @@ -3610,9 +3669,8 @@ pub enum AliasRelationDirection { /// Reflects [`rustc_middle::ty::ClosureKind`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::ClosureKind, state: S as _tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum ClosureKind { Fn, FnMut, @@ -3622,9 +3680,8 @@ pub enum ClosureKind { /// Reflects [`rustc_middle::ty::PredicateKind`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::PredicateKind<'tcx>, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum PredicateKind { Clause(ClauseKind), ObjectSafe(DefId), @@ -3690,7 +3747,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_hir::Gene /// Reflects [`rustc_hir::OpaqueTyOrigin`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_hir::OpaqueTyOrigin, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, JsonSchema)] +#[derive_group(Serializers)] pub enum OpaqueTyOrigin { FnReturn(GlobalIdent), AsyncFn(GlobalIdent), @@ -3700,14 +3758,16 @@ pub enum OpaqueTyOrigin { /// Reflects [`rustc_ast::ast::MacroDef`] #[derive(AdtInto)] #[args(<'tcx, S: BaseState<'tcx>>, from: rustc_ast::ast::MacroDef, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct MacroDef { pub body: DelimArgs, pub macro_rules: bool, } /// Reflects [`rustc_hir::Item`] (and [`rustc_hir::ItemId`]) -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct Item { pub def_id: Option, pub owner_id: DefId, @@ -3757,7 +3817,8 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_span::symbol::Ide /// Reflects [`rustc_hir::WhereBoundPredicate`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: rustc_hir::WhereBoundPredicate<'tcx>, state: S as tcx)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct WhereBoundPredicate { pub hir_id: HirId, pub span: Span, @@ -3771,7 +3832,8 @@ pub struct WhereBoundPredicate { /// Reflects [`rustc_hir::PredicateOrigin`] #[derive(AdtInto)] #[args(, from: rustc_hir::PredicateOrigin, state: S as _s)] -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum PredicateOrigin { WhereClause, GenericParam, @@ -3781,9 +3843,8 @@ pub enum PredicateOrigin { /// Reflects [`rustc_middle::ty::AssocItem`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::AssocItem, state: S as tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct AssocItem { pub def_id: DefId, pub name: Symbol, @@ -3797,9 +3858,8 @@ pub struct AssocItem { /// Reflects [`rustc_middle::ty::ImplTraitInTraitData`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::ImplTraitInTraitData, state: S as _tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum ImplTraitInTraitData { Trait { fn_def_id: DefId, @@ -3813,9 +3873,8 @@ pub enum ImplTraitInTraitData { /// Reflects [`rustc_middle::ty::AssocItemContainer`] #[derive(AdtInto)] #[args(, from: rustc_middle::ty::AssocItemContainer, state: S as _tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum AssocItemContainer { TraitContainer, ImplContainer, @@ -3824,9 +3883,8 @@ pub enum AssocItemContainer { /// Reflects [`rustc_middle::ty::AssocKind`] #[derive(AdtInto)] #[args(, from: rustc_middle::ty::AssocKind, state: S as _tcx)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum AssocKind { Const, Fn, diff --git a/frontend/exporter/src/types/def_id.rs b/frontend/exporter/src/types/def_id.rs index bed97280a..6be754d4b 100644 --- a/frontend/exporter/src/types/def_id.rs +++ b/frontend/exporter/src/types/def_id.rs @@ -10,14 +10,15 @@ //! `hax-engine-names-extract`, and is used to turn off the derive //! attributes `AdtInto` and `JsonSchema`. -pub use serde::{Deserialize, Serialize}; +use hax_adt_into::derive_group; #[cfg(not(feature = "extract_names_mode"))] use crate::{AdtInto, BaseState, JsonSchema, SInto}; pub type Symbol = String; -#[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] #[cfg_attr(not(feature = "extract_names_mode"), derive(AdtInto, JsonSchema))] #[cfg_attr(not(feature = "extract_names_mode"), args(<'a, S: BaseState<'a>>, from: rustc_hir::definitions::DisambiguatedDefPathData, state: S as s))] /// Reflects [`rustc_hir::definitions::DisambiguatedDefPathData`] @@ -27,7 +28,8 @@ pub struct DisambiguatedDefPathItem { } /// Reflects [`rustc_hir::def_id::DefId`] -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] #[cfg_attr(not(feature = "extract_names_mode"), derive(JsonSchema))] pub struct DefId { pub krate: String, @@ -44,7 +46,8 @@ pub struct DefId { } /// Reflects [`rustc_hir::definitions::DefPathData`] -#[derive(Clone, Debug, Serialize, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] #[cfg_attr(not(feature = "extract_names_mode"), derive(AdtInto, JsonSchema))] #[cfg_attr(not(feature = "extract_names_mode"), args(<'ctx, S: BaseState<'ctx>>, from: rustc_hir::definitions::DefPathData, state: S as state))] pub enum DefPathItem { diff --git a/frontend/exporter/src/types/mir.rs b/frontend/exporter/src/types/mir.rs index be4e44c08..0a5b6c5cc 100644 --- a/frontend/exporter/src/types/mir.rs +++ b/frontend/exporter/src/types/mir.rs @@ -1,7 +1,8 @@ use crate::prelude::*; use tracing::trace; -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(, from: rustc_middle::mir::MirPhase, state: S as s)] pub enum MirPhase { Built, @@ -9,14 +10,16 @@ pub enum MirPhase { Runtime(RuntimePhase), } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::mir::SourceInfo, state: S as s)] pub struct SourceInfo { pub span: Span, pub scope: SourceScope, } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::mir::LocalDecl<'tcx>, state: S as s)] pub struct LocalDecl { pub mutability: Mutability, @@ -28,7 +31,8 @@ pub struct LocalDecl { pub name: Option, // This information is contextual, thus the SInto instance initializes it to None, and then we fill it while `SInto`ing MirBody } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum ClearCrossCrate { Clear, Set(T), @@ -45,7 +49,8 @@ impl> SInto> } } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(, from: rustc_middle::mir::RuntimePhase, state: S as _s)] pub enum RuntimePhase { Initial, @@ -53,7 +58,8 @@ pub enum RuntimePhase { Optimized, } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(, from: rustc_middle::mir::AnalysisPhase, state: S as _s)] pub enum AnalysisPhase { Initial, @@ -81,7 +87,7 @@ fn name_of_local( /// Enumerates the kinds of Mir bodies. TODO: use const generics /// instead of an open list of types. pub mod mir_kinds { - use crate::prelude::{Deserialize, JsonSchema, Serialize}; + use crate::prelude::{derive_group, JsonSchema}; use rustc_data_structures::steal::Steal; use rustc_middle::mir::Body; use rustc_middle::ty::TyCtxt; @@ -89,7 +95,8 @@ pub mod mir_kinds { pub trait IsMirKind: Clone { fn get_mir<'tcx>(tcx: TyCtxt<'tcx>, id: LocalDefId) -> &'tcx Steal>; } - #[derive(Clone, Copy, Debug, JsonSchema, Serialize, Deserialize)] + #[derive_group(Serializers)] + #[derive(Clone, Copy, Debug, JsonSchema)] pub struct Built; impl IsMirKind for Built { fn get_mir<'tcx>(tcx: TyCtxt<'tcx>, id: LocalDefId) -> &'tcx Steal> { @@ -99,7 +106,8 @@ pub mod mir_kinds { } pub use mir_kinds::IsMirKind; -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::mir::ConstOperand<'tcx>, state: S as s)] pub struct Constant { pub span: Span, @@ -107,7 +115,8 @@ pub struct Constant { pub const_: TypedConstantKind, } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>, from: rustc_middle::mir::Body<'tcx>, state: S as s)] pub struct MirBody { #[map(x.clone().as_mut().sinto(s))] @@ -141,7 +150,8 @@ pub struct MirBody { pub _kind: std::marker::PhantomData, } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::mir::SourceScopeData<'tcx>, state: S as s)] pub struct SourceScopeData { pub span: Span, @@ -151,20 +161,23 @@ pub struct SourceScopeData { pub local_data: ClearCrossCrate, } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::Instance<'tcx>, state: S as s)] pub struct Instance { pub def: InstanceKind, pub args: Vec, } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::mir::SourceScopeLocalData, state: S as s)] pub struct SourceScopeLocalData { pub lint_root: HirId, } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>, from: rustc_middle::mir::Operand<'tcx>, state: S as s)] pub enum Operand { Copy(Place), @@ -181,7 +194,8 @@ impl Operand { } } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>, from: rustc_middle::mir::Terminator<'tcx>, state: S as s)] pub struct Terminator { pub source_info: SourceInfo, @@ -404,15 +418,15 @@ fn translate_terminator_kind_call<'tcx, S: BaseState<'tcx> + HasMir<'tcx> + HasO } // We don't use the LitIntType on purpose (we don't want the "unsuffixed" case) -#[derive( - Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Copy, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum IntUintTy { Int(IntTy), Uint(UintTy), } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct ScalarInt { /// Little-endian representation of the integer pub data_le_bytes: [u8; 16], @@ -471,7 +485,8 @@ fn translate_switch_targets<'tcx, S: UnderOwnerState<'tcx>>( } } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum SwitchTargets { /// Gives the `if` block and the `else` block If(BasicBlock, BasicBlock), @@ -481,7 +496,8 @@ pub enum SwitchTargets { SwitchInt(IntUintTy, Vec<(ScalarInt, BasicBlock)>, BasicBlock), } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum FunOperand { /// Call to a top-level function designated by its id Id(DefId), @@ -489,7 +505,8 @@ pub enum FunOperand { Move(Place), } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>, from: rustc_middle::mir::TerminatorKind<'tcx>, state: S as s)] pub enum TerminatorKind { Goto { @@ -571,7 +588,8 @@ pub enum TerminatorKind { }, } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>, from: rustc_middle::mir::Statement<'tcx>, state: S as s)] pub struct Statement { pub source_info: SourceInfo, @@ -579,7 +597,8 @@ pub struct Statement { pub kind: Box, } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>, from: rustc_middle::mir::StatementKind<'tcx>, state: S as s)] pub enum StatementKind { Assign((Place, Rvalue)), @@ -600,14 +619,16 @@ pub enum StatementKind { Nop, } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct Place { /// The type of the element on which we apply the projection given by `kind` pub ty: Ty, pub kind: PlaceKind, } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum PlaceKind { Local(Local), Projection { @@ -616,7 +637,8 @@ pub enum PlaceKind { }, } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum ProjectionElemFieldKind { Tuple(FieldIdx), Adt { @@ -628,7 +650,8 @@ pub enum ProjectionElemFieldKind { ClosureState(FieldIdx), } -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub enum ProjectionElem { Deref, Field(ProjectionElemFieldKind), @@ -794,9 +817,8 @@ impl<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>> SInto } } -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct MirFnSig { pub inputs: Vec, pub output: Ty, @@ -830,7 +852,8 @@ pub(crate) fn poly_fn_sig_to_mir_poly_fn_sig<'tcx, S: BaseState<'tcx> + HasOwner sig.sinto(s) } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>, from: rustc_middle::mir::AggregateKind<'tcx>, state: S as s)] pub enum AggregateKind { Array(Ty), @@ -885,7 +908,8 @@ pub enum AggregateKind { RawPtr(Ty, Mutability), } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>, from: rustc_middle::mir::CastKind, state: S as s)] pub enum CastKind { PointerExposeProvenance, @@ -901,7 +925,8 @@ pub enum CastKind { Transmute, } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>, from: rustc_middle::mir::NullOp<'tcx>, state: S as s)] pub enum NullOp { SizeOf, @@ -910,7 +935,8 @@ pub enum NullOp { UbChecks, } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>, from: rustc_middle::mir::Rvalue<'tcx>, state: S as s)] pub enum Rvalue { Use(Operand), @@ -935,7 +961,8 @@ pub enum Rvalue { CopyForDeref(Place), } -#[derive(AdtInto, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(AdtInto, Clone, Debug, JsonSchema)] #[args(<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>, from: rustc_middle::mir::BasicBlockData<'tcx>, state: S as s)] pub struct BasicBlockData { pub statements: Vec, diff --git a/frontend/exporter/src/types/mir_traits.rs b/frontend/exporter/src/types/mir_traits.rs index 422253a42..c415dc063 100644 --- a/frontend/exporter/src/types/mir_traits.rs +++ b/frontend/exporter/src/types/mir_traits.rs @@ -144,7 +144,8 @@ pub fn solve_item_traits<'tcx, S: UnderOwnerState<'tcx>>( /// or a trait definition inside an impl/trait block. However it is possible /// to define an impl/trait inside a function, which can itself be inside a /// block, leading to nested impl blocks. -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct ParamsInfo { /// The total number of generic parameters (regions + types + consts). /// We do not consider the trait clauses as generic parameters. diff --git a/frontend/exporter/src/types/new/item_attributes.rs b/frontend/exporter/src/types/new/item_attributes.rs index bfaa141d1..e1352eae8 100644 --- a/frontend/exporter/src/types/new/item_attributes.rs +++ b/frontend/exporter/src/types/new/item_attributes.rs @@ -1,6 +1,7 @@ use crate::prelude::*; -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct ItemAttributes { attributes: Vec, parent_attributes: Vec, diff --git a/frontend/exporter/src/types/new/predicate_id.rs b/frontend/exporter/src/types/new/predicate_id.rs index cd71bbe2b..fcaac8121 100644 --- a/frontend/exporter/src/types/new/predicate_id.rs +++ b/frontend/exporter/src/types/new/predicate_id.rs @@ -1,9 +1,8 @@ use crate::prelude::*; use rustc_middle::ty; -#[derive( - Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Copy, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] #[serde(transparent)] /// A `PredicateId` is a unique identifier for a clause or a /// predicate. It is computed by hashing predicates and clause in a diff --git a/frontend/exporter/src/types/new/typed_constant_kind.rs b/frontend/exporter/src/types/new/typed_constant_kind.rs index f8bdb6f3a..837c63bf6 100644 --- a/frontend/exporter/src/types/new/typed_constant_kind.rs +++ b/frontend/exporter/src/types/new/typed_constant_kind.rs @@ -1,6 +1,7 @@ use crate::prelude::*; -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] pub struct TypedConstantKind { pub typ: Ty, pub constant_kind: ConstantExpr, diff --git a/hax-types/Cargo.toml b/hax-types/Cargo.toml index cbd7587ed..39d129e92 100644 --- a/hax-types/Cargo.toml +++ b/hax-types/Cargo.toml @@ -18,4 +18,7 @@ schemars.workspace = true serde.workspace = true colored.workspace = true serde_json.workspace = true -annotate-snippets.workspace = true \ No newline at end of file +annotate-snippets.workspace = true +hax-adt-into.workspace = true +bincode.workspace = true +zstd = "0.13.1" diff --git a/hax-types/src/cli_options.rs b/hax-types/src/cli_options.rs index 0815d88be..b8b4b87d5 100644 --- a/hax-types/src/cli_options.rs +++ b/hax-types/src/cli_options.rs @@ -5,7 +5,8 @@ use std::fmt; pub use hax_frontend_exporter_options::*; -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Debug, Clone)] pub enum DebugEngineMode { File(PathOrDash), Interactive, @@ -20,7 +21,8 @@ impl std::convert::From<&str> for DebugEngineMode { } } -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize, Default)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Debug, Clone, Default)] pub struct ForceCargoBuild { pub data: u64, } @@ -40,7 +42,8 @@ impl std::convert::From<&str> for ForceCargoBuild { } } -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] +#[derive_group(Serializers)] +#[derive(Debug, Clone, JsonSchema)] pub enum PathOrDash { Dash, Path(PathBuf), @@ -105,7 +108,8 @@ impl NormalizePaths for PathOrDash { } } -#[derive(JsonSchema, Parser, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Parser, Debug, Clone)] pub struct ProVerifOptions { /// Items for which hax should extract a default-valued process /// macro with a corresponding type signature. This flag expects a @@ -124,7 +128,8 @@ pub struct ProVerifOptions { assume_items: Vec, } -#[derive(JsonSchema, Parser, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Parser, Debug, Clone)] pub struct FStarOptions { /// Set the Z3 per-query resource limit #[arg(long, default_value = "15")] @@ -156,7 +161,8 @@ pub struct FStarOptions { interfaces: Vec, } -#[derive(JsonSchema, Subcommand, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Subcommand, Debug, Clone)] pub enum Backend { /// Use the F* backend Fstar(FStarOptions), @@ -182,14 +188,16 @@ impl fmt::Display for Backend { } } -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Debug, Clone)] enum DepsKind { Transitive, Shallow, None, } -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Debug, Clone)] enum InclusionKind { /// `+query` include the items selected by `query` Included(DepsKind), @@ -197,7 +205,8 @@ enum InclusionKind { Excluded, } -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Debug, Clone)] struct InclusionClause { kind: InclusionKind, namespace: Namespace, @@ -233,7 +242,8 @@ fn parse_inclusion_clause( }) } -#[derive(JsonSchema, Parser, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Parser, Debug, Clone)] pub struct TranslationOptions { /// Controls which Rust item should be extracted or not. /// @@ -275,7 +285,8 @@ pub struct TranslationOptions { include_namespaces: Vec, } -#[derive(JsonSchema, Parser, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Parser, Debug, Clone)] pub struct BackendOptions { #[command(subcommand)] pub backend: Backend, @@ -319,7 +330,8 @@ pub struct BackendOptions { pub translation_options: TranslationOptions, } -#[derive(JsonSchema, Subcommand, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Subcommand, Debug, Clone)] pub enum Command { /// Translate to a backend. The translated modules will be written /// under the directory `/proofs//extraction`, where @@ -365,15 +377,15 @@ impl Command { } } -#[derive( - JsonSchema, ValueEnum, Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(JsonSchema, ValueEnum, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum ExportBodyKind { Thir, MirBuilt, } -#[derive(JsonSchema, Parser, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Parser, Debug, Clone)] #[command(author, version = concat!("commit=", env!("HAX_GIT_COMMIT_HASH"), " ", "describe=", env!("HAX_GIT_DESCRIBE")), name = "hax", about, long_about = None)] pub struct Options { /// Replace the expansion of each macro matching PATTERN by their diff --git a/hax-types/src/diagnostics/mod.rs b/hax-types/src/diagnostics/mod.rs index fb9ae699b..8c65f5099 100644 --- a/hax-types/src/diagnostics/mod.rs +++ b/hax-types/src/diagnostics/mod.rs @@ -9,7 +9,8 @@ use colored::Colorize; pub mod report; -#[derive(Debug, Clone, JsonSchema, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(Debug, Clone, JsonSchema)] pub struct Diagnostics { pub kind: Kind, pub span: Vec, @@ -73,7 +74,8 @@ impl std::fmt::Display for Diagnostics { } } -#[derive(Debug, Clone, JsonSchema, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(Debug, Clone, JsonSchema)] #[repr(u16)] pub enum Kind { /// Unsafe code is not supported diff --git a/hax-types/src/driver_api.rs b/hax-types/src/driver_api.rs index 94b8af689..9782ce3c5 100644 --- a/hax-types/src/driver_api.rs +++ b/hax-types/src/driver_api.rs @@ -2,18 +2,21 @@ use crate::prelude::*; pub const HAX_DRIVER_STDERR_PREFIX: &str = "::hax-driver::"; -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(Debug, Clone)] pub struct EmitHaxMetaMessage { pub working_dir: PathBuf, pub manifest_dir: PathBuf, pub path: PathBuf, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(Debug, Clone)] pub enum HaxDriverMessage { EmitHaxMeta(EmitHaxMetaMessage), } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(Debug, Clone)] pub struct HaxMeta { pub crate_name: String, pub crate_type: String, @@ -27,6 +30,22 @@ pub struct HaxMeta { pub def_ids: Vec, } +impl HaxMeta +where + Body: bincode::Encode + bincode::Decode, +{ + pub fn write(self, write: &mut impl std::io::Write) { + let mut write = zstd::stream::write::Encoder::new(write, 0).unwrap(); + bincode::encode_into_std_write(self, &mut write, bincode::config::standard()).unwrap(); + write.finish().unwrap(); + } + pub fn read(reader: impl std::io::Read) -> Self { + let reader = zstd::stream::read::Decoder::new(reader).unwrap(); + let reader = std::io::BufReader::new(reader); + bincode::decode_from_reader(reader, bincode::config::standard()).unwrap() + } +} + #[macro_export] macro_rules! with_kind_type { ($kind:expr, <$t:ident>|| $body:expr) => {{ diff --git a/hax-types/src/engine_api.rs b/hax-types/src/engine_api.rs index 77d07f2f8..1ea02b356 100644 --- a/hax-types/src/engine_api.rs +++ b/hax-types/src/engine_api.rs @@ -3,7 +3,8 @@ use crate::prelude::*; type ThirBody = hax_frontend_exporter::ThirBody; -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Debug, Clone)] pub struct EngineOptions { pub backend: BackendOptions, pub input: Vec>, @@ -13,13 +14,15 @@ pub struct EngineOptions { )>, } -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Debug, Clone)] pub struct File { pub path: String, pub contents: String, } -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Debug, Clone)] pub struct Output { pub diagnostics: Vec, pub files: Vec, @@ -28,7 +31,8 @@ pub struct Output { pub mod protocol { use super::*; - #[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] + #[derive_group(Serializers)] + #[derive(JsonSchema, Debug, Clone)] pub enum FromEngine { Diagnostic(crate::diagnostics::Diagnostics), File(File), @@ -38,7 +42,8 @@ pub mod protocol { Exit, Ping, } - #[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] + #[derive_group(Serializers)] + #[derive(JsonSchema, Debug, Clone)] pub enum ToEngine { PrettyPrintedDiagnostic(String), PrettyPrintedRust(Result), @@ -48,7 +53,8 @@ pub mod protocol { // This is located here for dependency reason, but this is not related // to the engine (yet?). -#[derive(JsonSchema, Debug, Clone, Serialize, Deserialize)] +#[derive_group(Serializers)] +#[derive(JsonSchema, Debug, Clone)] pub struct WithDefIds { pub def_ids: Vec, pub impl_infos: Vec<( diff --git a/hax-types/src/prelude.rs b/hax-types/src/prelude.rs index 72a9e3818..79105a5b3 100644 --- a/hax-types/src/prelude.rs +++ b/hax-types/src/prelude.rs @@ -1,3 +1,3 @@ +pub(crate) use hax_adt_into::derive_group; pub use schemars::JsonSchema; -pub use serde::{Deserialize, Serialize}; pub use std::path::{Path, PathBuf}; From 8d07550ce38b0f2bea34420c3f23fdb45aa59862 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 1 Jul 2024 18:55:38 +0200 Subject: [PATCH 18/39] chore(test-harness): update, remove lint tests --- test-harness/src/harness.rs | 6 +----- .../snapshots/toolchain__attribute-opaque into-fstar.snap | 4 +--- .../src/snapshots/toolchain__generics into-fstar.snap | 4 +--- .../src/snapshots/toolchain__interface-only into-fstar.snap | 4 +--- .../src/snapshots/toolchain__recursion into-fstar.snap | 4 +--- 5 files changed, 5 insertions(+), 17 deletions(-) diff --git a/test-harness/src/harness.rs b/test-harness/src/harness.rs index 453c8bf48..0fb048adc 100644 --- a/test-harness/src/harness.rs +++ b/test-harness/src/harness.rs @@ -6,13 +6,11 @@ use std::process::{Command, Stdio}; #[derive(Clone, Debug, serde::Serialize)] pub enum TestKind { Translate { backend: String }, - Lint { linter: String }, } impl TestKind { fn as_name(&self) -> String { (match self { - TestKind::Lint { linter } => ["lint".to_string(), linter.clone()], TestKind::Translate { backend } => ["into".to_string(), backend.clone()], }) .join("-") @@ -111,7 +109,6 @@ pub struct Test { impl Test { fn as_args(&self) -> Vec { match &self.kind { - TestKind::Lint { linter } => vec!["lint".to_string(), linter.clone()], TestKind::Translate { backend } => { let mut args = vec![]; args.push("into".to_string()); @@ -187,7 +184,7 @@ impl Test { snapshot.insert( "stdout".to_string(), serde_json::from_str(&sout) - .map(|out: hax_cli_options_engine::Output| { + .map(|out: hax_types::engine_api::Output| { use serde_json::json; json!({ "diagnostics": Value::Array(out.diagnostics.into_iter().map(|diag| json!({ @@ -285,7 +282,6 @@ fn parse_hax_tests_metadata(info: TestInfo, metadata: &Value) -> Vec { info: info.clone(), kind: match a.as_str() { "into" => TestKind::Translate { backend: b }, - "lint" => TestKind::Lint { linter: b }, _ => panic!( "unexpected metadata [hax-tests.{}.{}] for package {:#?}", a, b, info diff --git a/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap b/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap index fd801bc73..2275da427 100644 --- a/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__attribute-opaque into-fstar.snap @@ -23,9 +23,7 @@ info: - +** --- exit = 0 -stderr = ''' -Compiling attribute-opaque v0.1.0 (WORKSPACE_ROOT/attribute-opaque) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__generics into-fstar.snap b/test-harness/src/snapshots/toolchain__generics into-fstar.snap index a69b5ac9b..054403fb6 100644 --- a/test-harness/src/snapshots/toolchain__generics into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__generics into-fstar.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling generics v0.1.0 (WORKSPACE_ROOT/generics) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__interface-only into-fstar.snap b/test-harness/src/snapshots/toolchain__interface-only into-fstar.snap index 66e83f692..9d23e9942 100644 --- a/test-harness/src/snapshots/toolchain__interface-only into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__interface-only into-fstar.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling interface-only v0.1.0 (WORKSPACE_ROOT/cli/interface-only) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__recursion into-fstar.snap b/test-harness/src/snapshots/toolchain__recursion into-fstar.snap index a6ab18608..00c19c914 100644 --- a/test-harness/src/snapshots/toolchain__recursion into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__recursion into-fstar.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling recursion v0.1.0 (WORKSPACE_ROOT/recursion) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] From a8fb44869919304b1747f606d7cb10bede4847ac Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 1 Jul 2024 19:10:46 +0200 Subject: [PATCH 19/39] rustfmt --- frontend/exporter/src/traits.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 97df6f9ad..97c6acbfd 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -1,6 +1,5 @@ use crate::prelude::*; - #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx> >, from: search_clause::PathChunk<'tcx>, state: S as tcx)] #[derive_group(Serializers)] From 4efaf5f9cc2be2886cb0bdaf04a1b15a6e37758c Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 1 Jul 2024 19:20:57 +0200 Subject: [PATCH 20/39] fix(frontend): fix a few serialize clauses --- frontend/exporter/src/types/copied.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/frontend/exporter/src/types/copied.rs b/frontend/exporter/src/types/copied.rs index 0f81a3ce0..e03364a49 100644 --- a/frontend/exporter/src/types/copied.rs +++ b/frontend/exporter/src/types/copied.rs @@ -305,9 +305,8 @@ pub struct ParamConst { /// Reflects [`rustc_middle::ty::ExistentialPredicate`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_middle::ty::ExistentialPredicate<'tcx>, state: S as state)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum ExistentialPredicate { /// E.g. `From`. Note that this isn't `T: From` with a given `T`, this is just /// `From`. Could be written `?: From`. @@ -321,9 +320,8 @@ pub enum ExistentialPredicate { /// Reflects [`rustc_type_ir::ExistentialTraitRef`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_type_ir::ExistentialTraitRef>, state: S as state)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct ExistentialTraitRef { pub def_id: DefId, pub args: Vec, @@ -332,9 +330,8 @@ pub struct ExistentialTraitRef { /// Reflects [`rustc_type_ir::ExistentialProjection`] #[derive(AdtInto)] #[args(<'tcx, S: UnderOwnerState<'tcx>>, from: rustc_type_ir::ExistentialProjection>, state: S as state)] -#[derive( - Clone, Debug, Serialize, Deserialize, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord, -)] +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct ExistentialProjection { pub def_id: DefId, pub args: Vec, From 4415f9cd1da4471509ef9bc6bc5fdf4eda59df69 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 1 Jul 2024 19:51:45 +0200 Subject: [PATCH 21/39] fix(test-harness): use one thread only --- test-harness/src/harness.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test-harness/src/harness.rs b/test-harness/src/harness.rs index 0fb048adc..6d3c0db90 100644 --- a/test-harness/src/harness.rs +++ b/test-harness/src/harness.rs @@ -298,8 +298,11 @@ fn main() { .unwrap(); let workspace_root: String = metadata.workspace_root.into(); + let mut args = libtest_mimic::Arguments::from_args(); + args.test_threads = Some(1); + libtest_mimic::run( - &libtest_mimic::Arguments::from_args(), + &args, metadata .packages .into_iter() From 557f905424d9e0d865bddb97a27b8877e39de2ab Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Mon, 1 Jul 2024 19:52:13 +0200 Subject: [PATCH 22/39] fix(tests): refresh --- test-harness/src/snapshots/toolchain__enum-repr into-coq.snap | 4 +--- .../src/snapshots/toolchain__enum-repr into-fstar.snap | 4 +--- .../src/snapshots/toolchain__enum-repr into-ssprove.snap | 4 +--- test-harness/src/snapshots/toolchain__literals into-coq.snap | 4 +--- .../src/snapshots/toolchain__literals into-fstar.snap | 4 +--- test-harness/src/snapshots/toolchain__loops into-fstar.snap | 4 +--- .../src/snapshots/toolchain__pattern-or into-coq.snap | 4 +--- .../src/snapshots/toolchain__pattern-or into-fstar.snap | 4 +--- .../src/snapshots/toolchain__side-effects into-fstar.snap | 4 +--- .../src/snapshots/toolchain__side-effects into-ssprove.snap | 4 +--- test-harness/src/snapshots/toolchain__slices into-coq.snap | 4 +--- test-harness/src/snapshots/toolchain__slices into-fstar.snap | 4 +--- 12 files changed, 12 insertions(+), 36 deletions(-) diff --git a/test-harness/src/snapshots/toolchain__enum-repr into-coq.snap b/test-harness/src/snapshots/toolchain__enum-repr into-coq.snap index 0190e2c33..22894e237 100644 --- a/test-harness/src/snapshots/toolchain__enum-repr into-coq.snap +++ b/test-harness/src/snapshots/toolchain__enum-repr into-coq.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling enum-repr v0.1.0 (WORKSPACE_ROOT/enum-repr) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__enum-repr into-fstar.snap b/test-harness/src/snapshots/toolchain__enum-repr into-fstar.snap index d58e0846e..600085987 100644 --- a/test-harness/src/snapshots/toolchain__enum-repr into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__enum-repr into-fstar.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling enum-repr v0.1.0 (WORKSPACE_ROOT/enum-repr) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__enum-repr into-ssprove.snap b/test-harness/src/snapshots/toolchain__enum-repr into-ssprove.snap index 3f57950ad..d1e4e4c09 100644 --- a/test-harness/src/snapshots/toolchain__enum-repr into-ssprove.snap +++ b/test-harness/src/snapshots/toolchain__enum-repr into-ssprove.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling enum-repr v0.1.0 (WORKSPACE_ROOT/enum-repr) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__literals into-coq.snap b/test-harness/src/snapshots/toolchain__literals into-coq.snap index 60bc0ec80..c18c543fa 100644 --- a/test-harness/src/snapshots/toolchain__literals into-coq.snap +++ b/test-harness/src/snapshots/toolchain__literals into-coq.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling literals v0.1.0 (WORKSPACE_ROOT/literals) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__literals into-fstar.snap b/test-harness/src/snapshots/toolchain__literals into-fstar.snap index bd997c950..1cef374ae 100644 --- a/test-harness/src/snapshots/toolchain__literals into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__literals into-fstar.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling literals v0.1.0 (WORKSPACE_ROOT/literals) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__loops into-fstar.snap b/test-harness/src/snapshots/toolchain__loops into-fstar.snap index a0e25da02..d4c2e2066 100644 --- a/test-harness/src/snapshots/toolchain__loops into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__loops into-fstar.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling loops v0.1.0 (WORKSPACE_ROOT/loops) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__pattern-or into-coq.snap b/test-harness/src/snapshots/toolchain__pattern-or into-coq.snap index 58a1d4c4d..ee6ab6c8e 100644 --- a/test-harness/src/snapshots/toolchain__pattern-or into-coq.snap +++ b/test-harness/src/snapshots/toolchain__pattern-or into-coq.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling pattern-or v0.1.0 (WORKSPACE_ROOT/pattern-or) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__pattern-or into-fstar.snap b/test-harness/src/snapshots/toolchain__pattern-or into-fstar.snap index 72caa49b6..d74991613 100644 --- a/test-harness/src/snapshots/toolchain__pattern-or into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__pattern-or into-fstar.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling pattern-or v0.1.0 (WORKSPACE_ROOT/pattern-or) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__side-effects into-fstar.snap b/test-harness/src/snapshots/toolchain__side-effects into-fstar.snap index 7ba2bd1f5..40618a18c 100644 --- a/test-harness/src/snapshots/toolchain__side-effects into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__side-effects into-fstar.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling side-effects v0.1.0 (WORKSPACE_ROOT/side-effects) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__side-effects into-ssprove.snap b/test-harness/src/snapshots/toolchain__side-effects into-ssprove.snap index 43aaaaf48..5b366bdb7 100644 --- a/test-harness/src/snapshots/toolchain__side-effects into-ssprove.snap +++ b/test-harness/src/snapshots/toolchain__side-effects into-ssprove.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling side-effects v0.1.0 (WORKSPACE_ROOT/side-effects) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__slices into-coq.snap b/test-harness/src/snapshots/toolchain__slices into-coq.snap index 03c01f905..af66d22c6 100644 --- a/test-harness/src/snapshots/toolchain__slices into-coq.snap +++ b/test-harness/src/snapshots/toolchain__slices into-coq.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling slices v0.1.0 (WORKSPACE_ROOT/slices) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] diff --git a/test-harness/src/snapshots/toolchain__slices into-fstar.snap b/test-harness/src/snapshots/toolchain__slices into-fstar.snap index e454a1d6a..5c32a98e1 100644 --- a/test-harness/src/snapshots/toolchain__slices into-fstar.snap +++ b/test-harness/src/snapshots/toolchain__slices into-fstar.snap @@ -21,9 +21,7 @@ info: backend_options: ~ --- exit = 0 -stderr = ''' -Compiling slices v0.1.0 (WORKSPACE_ROOT/slices) - Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs''' +stderr = 'Finished `dev` profile [unoptimized + debuginfo] target(s) in XXs' [stdout] diagnostics = [] From 338a4443705bd70ede956908f2d37ab0f0b999db Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Tue, 2 Jul 2024 08:18:31 +0200 Subject: [PATCH 23/39] feat(cli): use a hax-specific target directory --- Cargo.lock | 2 ++ cli/subcommands/Cargo.toml | 2 ++ cli/subcommands/src/cargo_hax.rs | 11 +++++++++++ hax-types/src/cli_options.rs | 7 +++++++ 4 files changed, 22 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 5b250b3b2..b5392eb57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -158,6 +158,8 @@ name = "cargo-hax" version = "0.1.0-pre.1" dependencies = [ "annotate-snippets", + "camino", + "cargo_metadata", "clap", "colored", "const_format", diff --git a/cli/subcommands/Cargo.toml b/cli/subcommands/Cargo.toml index d667f9436..e0e026f9f 100644 --- a/cli/subcommands/Cargo.toml +++ b/cli/subcommands/Cargo.toml @@ -42,6 +42,8 @@ annotate-snippets.workspace = true serde-jsonlines = "0.5.0" prettyplease = "0.2.20" syn = { version = "2.*", features = ["full"] } +cargo_metadata.workspace = true +camino = "1.1" [build-dependencies] serde.workspace = true diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index c7c77a0c7..940253e25 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -282,6 +282,14 @@ fn run_engine( error } +/// Uses `cargo metadata` to compute a derived target directory. +fn target_dir(suffix: &str) -> camino::Utf8PathBuf { + let metadata = cargo_metadata::MetadataCommand::new().exec().unwrap(); + let mut dir = metadata.target_directory; + dir.push(suffix); + dir +} + /// Calls `cargo` with a custom driver which computes `haxmeta` files /// in `TARGET`. One `haxmeta` file is produced by crate. Each /// `haxmeta` file contains the full AST of one crate. @@ -298,6 +306,9 @@ fn compute_haxmeta_files(options: &Options) -> (Vec, i32) { cmd.args([COLOR_FLAG, "always"]); } cmd.stderr(std::process::Stdio::piped()); + if !options.no_custom_target_directory { + cmd.env("CARGO_TARGET_DIR", target_dir("hax")); + }; cmd.env( "RUSTC_WORKSPACE_WRAPPER", std::env::var("HAX_RUSTC_DRIVER_BINARY") diff --git a/hax-types/src/cli_options.rs b/hax-types/src/cli_options.rs index b8b4b87d5..8657999f7 100644 --- a/hax-types/src/cli_options.rs +++ b/hax-types/src/cli_options.rs @@ -427,6 +427,13 @@ pub struct Options { /// options like `-C -p ;`). #[arg(long = "deps")] pub deps: bool, + + /// By default, hax use `$CARGO_TARGET_DIR/hax` as target folder, + /// to avoid recompilation when working both with `cargo hax` and + /// `cargo build` (or, e.g. `rust-analyzer`). This option disables + /// this behavior. + #[arg(long)] + pub no_custom_target_directory: bool, } impl NormalizePaths for Command { From a9732a7e94b75a37018d2330b24d8ce035ccdf24 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Tue, 2 Jul 2024 10:35:37 +0200 Subject: [PATCH 24/39] fix(engine/names): stop removing lib paths, seems like that works now --- engine/names/extract/build.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/engine/names/extract/build.rs b/engine/names/extract/build.rs index 209c9227d..ac5a3cf80 100644 --- a/engine/names/extract/build.rs +++ b/engine/names/extract/build.rs @@ -150,9 +150,6 @@ fn get_json() -> String { .stderr(Stdio::piped()); cmd.env("CARGO_TARGET_DIR", target_dir("hax")); - for env in ["DYLD_FALLBACK_LIBRARY_PATH", "LD_LIBRARY_PATH"] { - cmd.env_remove(env); - } let out = cmd.output().unwrap(); let stdout = String::from_utf8(out.stdout).unwrap(); let stderr = String::from_utf8(out.stderr).unwrap(); From c08026f7ef67d113e3d72134c4d71e9f937b19c1 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Tue, 2 Jul 2024 10:36:09 +0200 Subject: [PATCH 25/39] fix(engine/names): do not set CARGO_TARGET_DIR, this is now done by hax --- engine/names/extract/Cargo.toml | 1 - engine/names/extract/build.rs | 8 -------- 2 files changed, 9 deletions(-) diff --git a/engine/names/extract/Cargo.toml b/engine/names/extract/Cargo.toml index e05a6ac71..d0d0082eb 100644 --- a/engine/names/extract/Cargo.toml +++ b/engine/names/extract/Cargo.toml @@ -13,7 +13,6 @@ description = "Helper binary generating an OCaml module" [build-dependencies] serde.workspace = true serde_json.workspace = true -cargo_metadata.workspace = true hax-engine-names.workspace = true hax-adt-into.workspace = true tempfile.version = "3.9" diff --git a/engine/names/extract/build.rs b/engine/names/extract/build.rs index ac5a3cf80..47e7fbc51 100644 --- a/engine/names/extract/build.rs +++ b/engine/names/extract/build.rs @@ -124,13 +124,6 @@ fn reader_to_str(s: String) -> String { result } -fn target_dir(suffix: &str) -> camino::Utf8PathBuf { - let metadata = cargo_metadata::MetadataCommand::new().exec().unwrap(); - let mut dir = metadata.target_directory; - dir.push(suffix); - dir -} - fn get_json() -> String { let mut cmd = Command::new(std::env::var("HAX_CARGO_COMMAND_PATH").unwrap_or("cargo-hax".to_string())); @@ -149,7 +142,6 @@ fn get_json() -> String { .stdout(Stdio::piped()) .stderr(Stdio::piped()); - cmd.env("CARGO_TARGET_DIR", target_dir("hax")); let out = cmd.output().unwrap(); let stdout = String::from_utf8(out.stdout).unwrap(); let stderr = String::from_utf8(out.stderr).unwrap(); From 7cbb33232cc6b68e8b7653398200e11d2acb12ad Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Tue, 2 Jul 2024 10:44:50 +0200 Subject: [PATCH 26/39] chore: update Cargo.lock --- Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index b5392eb57..8b31df4aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -531,7 +531,6 @@ version = "0.1.0-pre.1" dependencies = [ "bincode", "camino", - "cargo_metadata", "hax-adt-into", "hax-engine-names", "serde", From 2a72e1d42ba56fe844c14164c2553027d23ac74b Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Tue, 2 Jul 2024 12:01:20 +0200 Subject: [PATCH 27/39] feat(exporter): add `rustc` default feature The `rustc` feature enables the conversion bridges from rustc types (and AST) to the ones defined in `hax-frontend-exporter`. Enabling `rustc` adds a dependency to `librustc_driver`. --- Cargo.lock | 1 + Cargo.toml | 2 +- cli/driver/Cargo.toml | 4 +- engine/names/extract/build.rs | 1 + frontend/exporter/Cargo.toml | 6 + frontend/exporter/adt-into/src/lib.rs | 1 + frontend/exporter/src/body.rs | 166 ++-- frontend/exporter/src/constant_utils.rs | 776 ++++++++--------- frontend/exporter/src/index_vec.rs | 32 +- frontend/exporter/src/lib.rs | 52 +- frontend/exporter/src/prelude.rs | 12 +- frontend/exporter/src/sinto.rs | 6 +- frontend/exporter/src/state.rs | 13 +- frontend/exporter/src/traits.rs | 797 +++++++++--------- frontend/exporter/src/types/copied.rs | 71 +- frontend/exporter/src/types/def_id.rs | 5 +- frontend/exporter/src/types/index.rs | 1 + frontend/exporter/src/types/mir.rs | 39 +- frontend/exporter/src/types/mod.rs | 2 + frontend/exporter/src/types/new/impl_infos.rs | 12 + .../exporter/src/types/new/item_attributes.rs | 2 + frontend/exporter/src/types/new/mod.rs | 2 + .../exporter/src/types/new/predicate_id.rs | 94 ++- .../src/types/new/typed_constant_kind.rs | 1 + frontend/exporter/src/types/replaced.rs | 28 +- hax-types/Cargo.toml | 3 + hax-types/src/diagnostics/mod.rs | 6 - hax-types/src/lib.rs | 2 - 28 files changed, 1155 insertions(+), 982 deletions(-) create mode 100644 frontend/exporter/src/types/new/impl_infos.rs diff --git a/Cargo.lock b/Cargo.lock index 8b31df4aa..c2a963053 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -543,6 +543,7 @@ name = "hax-frontend-exporter" version = "0.1.0-pre.1" dependencies = [ "bincode", + "cfg-if", "extension-traits", "hax-adt-into", "hax-frontend-exporter-options", diff --git a/Cargo.toml b/Cargo.toml index b5893677f..db955f63d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,7 +73,7 @@ bincode = "2.0.0-rc.3" annotate-snippets = "0.11" # Crates in this repository -hax-frontend-exporter = { path = "frontend/exporter", version = "=0.1.0-pre.1" } +hax-frontend-exporter = { path = "frontend/exporter", version = "=0.1.0-pre.1", default-features = false } hax-adt-into = { path = "frontend/exporter/adt-into", version = "=0.1.0-pre.1" } hax-frontend-exporter-options = { path = "frontend/exporter/options", version = "=0.1.0-pre.1" } hax-phase-debug-webapp = { path = "engine/utils/phase-debug-webapp", version = "=0.1.0-pre.1" } diff --git a/cli/driver/Cargo.toml b/cli/driver/Cargo.toml index 5120b4afd..52e558ad6 100644 --- a/cli/driver/Cargo.toml +++ b/cli/driver/Cargo.toml @@ -21,8 +21,8 @@ serde.workspace = true serde_json.workspace = true clap.workspace = true colored.workspace = true -hax-frontend-exporter.workspace = true -hax-types.workspace = true +hax-frontend-exporter = {workspace = true, features = ["rustc"]} +hax-types = {workspace = true, features = ["rustc"]} hax-frontend-exporter-options.workspace = true hax-lib-macros-types.workspace = true itertools.workspace = true diff --git a/engine/names/extract/build.rs b/engine/names/extract/build.rs index 47e7fbc51..7cc11cc77 100644 --- a/engine/names/extract/build.rs +++ b/engine/names/extract/build.rs @@ -6,6 +6,7 @@ use std::process::{Command, Stdio}; /// impls), we just inline a small module here that contains the three /// type definition we need. See the module for complementary /// informations. +#[allow(unexpected_cfgs)] #[path = "../../../frontend/exporter/src/types/def_id.rs"] mod hax_frontend_exporter_def_id; use hax_frontend_exporter_def_id::*; diff --git a/frontend/exporter/Cargo.toml b/frontend/exporter/Cargo.toml index 3695f9667..ed6f3ade0 100644 --- a/frontend/exporter/Cargo.toml +++ b/frontend/exporter/Cargo.toml @@ -24,6 +24,12 @@ paste = "1.0.11" extension-traits = "1.0.1" lazy_static = "1.4.0" bincode.workspace = true +cfg-if = "1.0.0" [features] +default = ["rustc"] extract_names_mode = [] +# Enables the conversion bridges from rustc types (and AST) to the +# ones defined in this crate. Enabling `rustc` adds a dependency to +# `librustc_driver`. +rustc = [] diff --git a/frontend/exporter/adt-into/src/lib.rs b/frontend/exporter/adt-into/src/lib.rs index 0c43b9638..3e9165b53 100644 --- a/frontend/exporter/adt-into/src/lib.rs +++ b/frontend/exporter/adt-into/src/lib.rs @@ -384,6 +384,7 @@ pub fn adt_into(input: proc_macro::TokenStream) -> proc_macro::TokenStream { }; quote! { + #[cfg(feature = "rustc")] const _ : () = { use #from as FROM_TYPE; use #to as TO_TYPE; diff --git a/frontend/exporter/src/body.rs b/frontend/exporter/src/body.rs index f31966302..99fcd3b5b 100644 --- a/frontend/exporter/src/body.rs +++ b/frontend/exporter/src/body.rs @@ -1,99 +1,109 @@ -use crate::prelude::*; +pub use module::*; -pub use rustc_hir::{ - def_id::{DefId as RDefId, LocalDefId as RLocalDefId}, - hir_id::OwnerId as ROwnerId, -}; - -pub fn get_thir<'tcx, S: UnderOwnerState<'tcx>>( - did: RLocalDefId, - s: &S, -) -> ( - Rc>, - rustc_middle::thir::ExprId, -) { - let base = s.base(); - let msg = || fatal!(s[base.tcx.def_span(did)], "THIR not found for {:?}", did); - base.cached_thirs.get(&did).unwrap_or_else(msg).clone() +#[cfg(not(feature = "rustc"))] +mod module { + pub trait IsBody: Sized + Clone + 'static {} + impl IsBody for T {} } -pub trait IsBody: Sized + Clone + 'static { - fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RLocalDefId, s: &S) -> Self; -} +#[cfg(feature = "rustc")] +mod module { + pub use crate::prelude::*; + pub use rustc_hir::{ + def_id::{DefId as RDefId, LocalDefId as RLocalDefId}, + hir_id::OwnerId as ROwnerId, + }; -pub fn make_fn_def<'tcx, Body: IsBody, S: UnderOwnerState<'tcx>>( - fn_sig: &rustc_hir::FnSig, - body_id: &rustc_hir::BodyId, - s: &S, -) -> FnDef { - let hir_id = body_id.hir_id; - let ldid = hir_id.clone().owner.def_id; + pub fn get_thir<'tcx, S: UnderOwnerState<'tcx>>( + did: RLocalDefId, + s: &S, + ) -> ( + Rc>, + rustc_middle::thir::ExprId, + ) { + let base = s.base(); + let msg = || fatal!(s[base.tcx.def_span(did)], "THIR not found for {:?}", did); + base.cached_thirs.get(&did).unwrap_or_else(msg).clone() + } - let (thir, expr_entrypoint) = get_thir(ldid, s); - let s = &with_owner_id(s.base(), thir.clone(), (), ldid.to_def_id()); - FnDef { - params: thir.params.raw.sinto(s), - ret: thir.exprs[expr_entrypoint].ty.sinto(s), - body: Body::body(ldid, s), - sig_span: fn_sig.span.sinto(s), - header: fn_sig.header.sinto(s), + pub trait IsBody: Sized + Clone + 'static { + fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RLocalDefId, s: &S) -> Self; } -} -pub fn body_from_id<'tcx, Body: IsBody, S: UnderOwnerState<'tcx>>( - id: rustc_hir::BodyId, - s: &S, -) -> Body { - // **Important:** - // We need a local id here, and we get it from the owner id, which must - // be local. It is safe to do so, because if we have access to HIR objects, - // it necessarily means we are exploring a local item (we don't have - // access to the HIR of external objects, only their MIR). - Body::body(s.base().tcx.hir().body_owner_def_id(id), s) -} + pub fn make_fn_def<'tcx, Body: IsBody, S: UnderOwnerState<'tcx>>( + fn_sig: &rustc_hir::FnSig, + body_id: &rustc_hir::BodyId, + s: &S, + ) -> FnDef { + let hir_id = body_id.hir_id; + let ldid = hir_id.clone().owner.def_id; -mod implementations { - use super::*; - impl IsBody for () { - fn body<'tcx, S: UnderOwnerState<'tcx>>(_did: RLocalDefId, _s: &S) -> Self { - () + let (thir, expr_entrypoint) = get_thir(ldid, s); + let s = &with_owner_id(s.base(), thir.clone(), (), ldid.to_def_id()); + FnDef { + params: thir.params.raw.sinto(s), + ret: thir.exprs[expr_entrypoint].ty.sinto(s), + body: Body::body(ldid, s), + sig_span: fn_sig.span.sinto(s), + header: fn_sig.header.sinto(s), } } - impl IsBody for ThirBody { - fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RLocalDefId, s: &S) -> Self { - let (thir, expr) = get_thir(did, s); - if *CORE_EXTRACTION_MODE { - let expr = &thir.exprs[expr.clone()]; - Decorated { - contents: Box::new(ExprKind::Tuple { fields: vec![] }), - hir_id: None, - attributes: vec![], - ty: expr.ty.sinto(s), - span: expr.span.sinto(s), + + pub fn body_from_id<'tcx, Body: IsBody, S: UnderOwnerState<'tcx>>( + id: rustc_hir::BodyId, + s: &S, + ) -> Body { + // **Important:** + // We need a local id here, and we get it from the owner id, which must + // be local. It is safe to do so, because if we have access to HIR objects, + // it necessarily means we are exploring a local item (we don't have + // access to the HIR of external objects, only their MIR). + Body::body(s.base().tcx.hir().body_owner_def_id(id), s) + } + + mod implementations { + use super::*; + impl IsBody for () { + fn body<'tcx, S: UnderOwnerState<'tcx>>(_did: RLocalDefId, _s: &S) -> Self { + () + } + } + impl IsBody for ThirBody { + fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RLocalDefId, s: &S) -> Self { + let (thir, expr) = get_thir(did, s); + if *CORE_EXTRACTION_MODE { + let expr = &thir.exprs[expr.clone()]; + Decorated { + contents: Box::new(ExprKind::Tuple { fields: vec![] }), + hir_id: None, + attributes: vec![], + ty: expr.ty.sinto(s), + span: expr.span.sinto(s), + } + } else { + expr.sinto(&with_owner_id(s.base(), thir, (), did.to_def_id())) } - } else { - expr.sinto(&with_owner_id(s.base(), thir, (), did.to_def_id())) } } - } - impl IsBody for (A, B) { - fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RLocalDefId, s: &S) -> Self { - (A::body(did, s), B::body(did, s)) + impl IsBody for (A, B) { + fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RLocalDefId, s: &S) -> Self { + (A::body(did, s), B::body(did, s)) + } } - } - impl IsBody for MirBody { - fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RLocalDefId, s: &S) -> Self { - let (thir, _) = get_thir(did, s); - let mir = Rc::new(s.base().tcx.mir_built(did).borrow().clone()); - mir.sinto(&with_owner_id(s.base(), thir, mir.clone(), did.to_def_id())) + impl IsBody for MirBody { + fn body<'tcx, S: UnderOwnerState<'tcx>>(did: RLocalDefId, s: &S) -> Self { + let (thir, _) = get_thir(did, s); + let mir = Rc::new(s.base().tcx.mir_built(did).borrow().clone()); + mir.sinto(&with_owner_id(s.base(), thir, mir.clone(), did.to_def_id())) + } } } -} -impl<'tcx, S: UnderOwnerState<'tcx>, Body: IsBody> SInto for rustc_hir::BodyId { - fn sinto(&self, s: &S) -> Body { - body_from_id::(self.clone(), s) + impl<'tcx, S: UnderOwnerState<'tcx>, Body: IsBody> SInto for rustc_hir::BodyId { + fn sinto(&self, s: &S) -> Body { + body_from_id::(self.clone(), s) + } } } diff --git a/frontend/exporter/src/constant_utils.rs b/frontend/exporter/src/constant_utils.rs index 74f5e611c..0f086e64b 100644 --- a/frontend/exporter/src/constant_utils.rs +++ b/frontend/exporter/src/constant_utils.rs @@ -1,7 +1,5 @@ use crate::prelude::*; -use rustc_middle::{mir, ty}; - #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum ConstantInt { @@ -107,153 +105,160 @@ pub struct ConstantFieldExpr { /// two construct to one same `ConstantExpr` type. pub type ConstantExpr = Decorated; -impl From for FieldExpr { - fn from(c: ConstantFieldExpr) -> FieldExpr { - FieldExpr { - value: c.value.into(), - field: c.field, +#[cfg(feature = "rustc")] +pub use self::rustc::*; +#[cfg(feature = "rustc")] +mod rustc { + use super::*; + use rustc_middle::{mir, ty}; + + impl From for FieldExpr { + fn from(c: ConstantFieldExpr) -> FieldExpr { + FieldExpr { + value: c.value.into(), + field: c.field, + } } } -} -impl ConstantLiteral { - /// Rustc always represents string constants as `&[u8]`, but this - /// is not nice to consume. This associated function interpret - /// bytes as an unicode string, and as a byte string otherwise. - fn byte_str(bytes: Vec, style: StrStyle) -> Self { - match String::from_utf8(bytes.clone()) { - Ok(s) => Self::Str(s, style), - Err(_) => Self::ByteStr(bytes, style), + impl ConstantLiteral { + /// Rustc always represents string constants as `&[u8]`, but this + /// is not nice to consume. This associated function interpret + /// bytes as an unicode string, and as a byte string otherwise. + fn byte_str(bytes: Vec, style: StrStyle) -> Self { + match String::from_utf8(bytes.clone()) { + Ok(s) => Self::Str(s, style), + Err(_) => Self::ByteStr(bytes, style), + } } } -} -impl From for Expr { - fn from(c: ConstantExpr) -> Expr { - use ConstantExprKind::*; - let kind = match *c.contents { - Literal(lit) => { - use ConstantLiteral::*; - let mut neg = false; - let node = match lit { - Bool(b) => LitKind::Bool(b), - Char(c) => LitKind::Char(c), - Int(i) => { - use LitIntType::*; - match i { - ConstantInt::Uint(v, t) => LitKind::Int(v, Unsigned(t)), - ConstantInt::Int(v, t) => { - neg = v.is_negative(); - LitKind::Int(v.abs_diff(0), Signed(t)) + impl From for Expr { + fn from(c: ConstantExpr) -> Expr { + use ConstantExprKind::*; + let kind = match *c.contents { + Literal(lit) => { + use ConstantLiteral::*; + let mut neg = false; + let node = match lit { + Bool(b) => LitKind::Bool(b), + Char(c) => LitKind::Char(c), + Int(i) => { + use LitIntType::*; + match i { + ConstantInt::Uint(v, t) => LitKind::Int(v, Unsigned(t)), + ConstantInt::Int(v, t) => { + neg = v.is_negative(); + LitKind::Int(v.abs_diff(0), Signed(t)) + } } } - } - ByteStr(raw, str_style) => LitKind::ByteStr(raw, str_style), - Str(raw, str_style) => LitKind::Str(raw, str_style), - }; - let span = c.span.clone(); - let lit = Spanned { span, node }; - ExprKind::Literal { lit, neg } - } - Adt { info, fields } => ExprKind::Adt(AdtExpr { - info, - fields: fields.into_iter().map(|field| field.into()).collect(), - base: None, - user_ty: None, - }), - // TODO: propagate the generics and trait refs (see #636) - GlobalName { - id, - generics: _, - trait_refs: _, - } => ExprKind::GlobalName { id }, - Borrow(e) => ExprKind::Borrow { - borrow_kind: BorrowKind::Shared, - arg: e.into(), - }, - ConstRef { id } => ExprKind::ConstRef { id }, - Array { fields } => ExprKind::Array { - fields: fields.into_iter().map(|field| field.into()).collect(), - }, - Tuple { fields } => ExprKind::Tuple { - fields: fields.into_iter().map(|field| field.into()).collect(), - }, - kind @ (FnPtr { .. } | TraitConst { .. }) => { - // SH: I see the `Closure` kind, but it's not the same as function pointer? - ExprKind::Todo(format!("FnPtr or TraitConst. kind={:#?}", kind)) + ByteStr(raw, str_style) => LitKind::ByteStr(raw, str_style), + Str(raw, str_style) => LitKind::Str(raw, str_style), + }; + let span = c.span.clone(); + let lit = Spanned { span, node }; + ExprKind::Literal { lit, neg } + } + Adt { info, fields } => ExprKind::Adt(AdtExpr { + info, + fields: fields.into_iter().map(|field| field.into()).collect(), + base: None, + user_ty: None, + }), + // TODO: propagate the generics and trait refs (see #636) + GlobalName { + id, + generics: _, + trait_refs: _, + } => ExprKind::GlobalName { id }, + Borrow(e) => ExprKind::Borrow { + borrow_kind: BorrowKind::Shared, + arg: e.into(), + }, + ConstRef { id } => ExprKind::ConstRef { id }, + Array { fields } => ExprKind::Array { + fields: fields.into_iter().map(|field| field.into()).collect(), + }, + Tuple { fields } => ExprKind::Tuple { + fields: fields.into_iter().map(|field| field.into()).collect(), + }, + kind @ (FnPtr { .. } | TraitConst { .. }) => { + // SH: I see the `Closure` kind, but it's not the same as function pointer? + ExprKind::Todo(format!("FnPtr or TraitConst. kind={:#?}", kind)) + } + Todo(msg) => ExprKind::Todo(msg), + }; + Decorated { + contents: Box::new(kind), + ..c } - Todo(msg) => ExprKind::Todo(msg), - }; - Decorated { - contents: Box::new(kind), - ..c } } -} -pub(crate) fn scalar_int_to_constant_literal<'tcx, S: UnderOwnerState<'tcx>>( - s: &S, - x: rustc_middle::ty::ScalarInt, - ty: rustc_middle::ty::Ty, -) -> ConstantLiteral { - match ty.kind() { - ty::Char => ConstantLiteral::Char( - char::try_from(x) - .s_expect(s, "scalar_int_to_constant_literal: expected a char") - .into(), - ), - ty::Bool => ConstantLiteral::Bool( - x.try_to_bool() - .s_expect(s, "scalar_int_to_constant_literal: expected a bool"), - ), - ty::Int(kind) => { - let v = x.to_int(x.size()); - ConstantLiteral::Int(ConstantInt::Int(v, kind.sinto(s))) - } - ty::Uint(kind) => { - let v = x.to_uint(x.size()); - ConstantLiteral::Int(ConstantInt::Uint(v, kind.sinto(s))) + pub(crate) fn scalar_int_to_constant_literal<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + x: rustc_middle::ty::ScalarInt, + ty: rustc_middle::ty::Ty, + ) -> ConstantLiteral { + match ty.kind() { + ty::Char => ConstantLiteral::Char( + char::try_from(x) + .s_expect(s, "scalar_int_to_constant_literal: expected a char") + .into(), + ), + ty::Bool => ConstantLiteral::Bool( + x.try_to_bool() + .s_expect(s, "scalar_int_to_constant_literal: expected a bool"), + ), + ty::Int(kind) => { + let v = x.to_int(x.size()); + ConstantLiteral::Int(ConstantInt::Int(v, kind.sinto(s))) + } + ty::Uint(kind) => { + let v = x.to_uint(x.size()); + ConstantLiteral::Int(ConstantInt::Uint(v, kind.sinto(s))) + } + _ => fatal!( + s, + "scalar_int_to_constant_literal: the type {:?} is not a literal", + ty + ), } - _ => fatal!( - s, - "scalar_int_to_constant_literal: the type {:?} is not a literal", - ty - ), } -} -pub(crate) fn scalar_to_constant_expr<'tcx, S: UnderOwnerState<'tcx>>( - s: &S, - ty: rustc_middle::ty::Ty<'tcx>, - scalar: &rustc_middle::mir::interpret::Scalar, - span: rustc_span::Span, -) -> ConstantExpr { - use rustc_middle::mir::Mutability; - let cspan = span.sinto(s); - // The documentation explicitly says not to match on a scalar. - // We match on the type and use it to convert the value. - let kind = match ty.kind() { - ty::Char | ty::Bool | ty::Int(_) | ty::Uint(_) => { - let scalar_int = scalar.try_to_scalar_int().unwrap_or_else(|_| { - fatal!( - s[span], - "Type is primitive, but the scalar {:#?} is not a [Int]", - scalar - ) - }); - ConstantExprKind::Literal(scalar_int_to_constant_literal(s, scalar_int, ty)) - } - ty::Ref(region, ty, Mutability::Not) if region.is_erased() => { - let tcx = s.base().tcx; - let pointer = scalar.to_pointer(&tcx).unwrap_or_else(|_| { - fatal!( - s[span], - "Type is [Ref], but the scalar {:#?} is not a [Pointer]", - scalar - ) - }); - use rustc_middle::mir::interpret::GlobalAlloc; - let contents = match tcx.global_alloc(pointer.provenance.s_unwrap(s).alloc_id()) { + pub(crate) fn scalar_to_constant_expr<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + ty: rustc_middle::ty::Ty<'tcx>, + scalar: &rustc_middle::mir::interpret::Scalar, + span: rustc_span::Span, + ) -> ConstantExpr { + use rustc_middle::mir::Mutability; + let cspan = span.sinto(s); + // The documentation explicitly says not to match on a scalar. + // We match on the type and use it to convert the value. + let kind = match ty.kind() { + ty::Char | ty::Bool | ty::Int(_) | ty::Uint(_) => { + let scalar_int = scalar.try_to_scalar_int().unwrap_or_else(|_| { + fatal!( + s[span], + "Type is primitive, but the scalar {:#?} is not a [Int]", + scalar + ) + }); + ConstantExprKind::Literal(scalar_int_to_constant_literal(s, scalar_int, ty)) + } + ty::Ref(region, ty, Mutability::Not) if region.is_erased() => { + let tcx = s.base().tcx; + let pointer = scalar.to_pointer(&tcx).unwrap_or_else(|_| { + fatal!( + s[span], + "Type is [Ref], but the scalar {:#?} is not a [Pointer]", + scalar + ) + }); + use rustc_middle::mir::interpret::GlobalAlloc; + let contents = match tcx.global_alloc(pointer.provenance.s_unwrap(s).alloc_id()) { GlobalAlloc::Static(did) => ConstantExprKind::GlobalName { id: did.sinto(s), generics: Vec::new(), trait_refs: Vec::new() }, GlobalAlloc::Memory(alloc) => { let values = alloc.inner().get_bytes_unchecked(rustc_middle::mir::interpret::AllocRange { @@ -268,190 +273,193 @@ pub(crate) fn scalar_to_constant_expr<'tcx, S: UnderOwnerState<'tcx>>( provenance ) }; - ConstantExprKind::Borrow(contents.decorate(ty.sinto(s), cspan.clone())) - } - // A [Scalar] might also be any zero-sized [Adt] or [Tuple] (i.e., unit) - ty::Tuple(ty) if ty.is_empty() => ConstantExprKind::Tuple { fields: vec![] }, - // It seems we can have ADTs when there is only one variant, and this variant doesn't have any fields. - ty::Adt(def, _) - if let [variant_def] = &def.variants().raw - && variant_def.fields.is_empty() => - { - ConstantExprKind::Adt { - info: get_variant_information(def, rustc_target::abi::FIRST_VARIANT, s), - fields: vec![], + ConstantExprKind::Borrow(contents.decorate(ty.sinto(s), cspan.clone())) } - } - _ => fatal!( - s[span], - "Unexpected type {:#?} for scalar {:#?}", - ty, - scalar - ), - }; - kind.decorate(ty.sinto(s), cspan) -} + // A [Scalar] might also be any zero-sized [Adt] or [Tuple] (i.e., unit) + ty::Tuple(ty) if ty.is_empty() => ConstantExprKind::Tuple { fields: vec![] }, + // It seems we can have ADTs when there is only one variant, and this variant doesn't have any fields. + ty::Adt(def, _) + if let [variant_def] = &def.variants().raw + && variant_def.fields.is_empty() => + { + ConstantExprKind::Adt { + info: get_variant_information(def, rustc_target::abi::FIRST_VARIANT, s), + fields: vec![], + } + } + _ => fatal!( + s[span], + "Unexpected type {:#?} for scalar {:#?}", + ty, + scalar + ), + }; + kind.decorate(ty.sinto(s), cspan) + } -/// Whether a `DefId` is a `AnonConst`. An anonymous constant is -/// generated by Rustc, hoisting every constat bits from items as -/// separate top-level items. This AnonConst mechanism is internal to -/// Rustc; we don't want to reflect that, instead we prefer inlining -/// those. `is_anon_const` is used to detect such AnonConst so that we -/// can evaluate and inline them. -pub(crate) fn is_anon_const<'tcx>( - did: rustc_span::def_id::DefId, - tcx: rustc_middle::ty::TyCtxt<'tcx>, -) -> bool { - matches!( - tcx.def_path(did).data.last().map(|x| x.data), - Some(rustc_hir::definitions::DefPathData::AnonConst) - ) -} + /// Whether a `DefId` is a `AnonConst`. An anonymous constant is + /// generated by Rustc, hoisting every constat bits from items as + /// separate top-level items. This AnonConst mechanism is internal to + /// Rustc; we don't want to reflect that, instead we prefer inlining + /// those. `is_anon_const` is used to detect such AnonConst so that we + /// can evaluate and inline them. + pub(crate) fn is_anon_const<'tcx>( + did: rustc_span::def_id::DefId, + tcx: rustc_middle::ty::TyCtxt<'tcx>, + ) -> bool { + matches!( + tcx.def_path(did).data.last().map(|x| x.data), + Some(rustc_hir::definitions::DefPathData::AnonConst) + ) + } -fn trait_const_to_constant_expr_kind<'tcx, S: BaseState<'tcx> + HasOwnerId>( - s: &S, - _const_def_id: rustc_hir::def_id::DefId, - generics: rustc_middle::ty::GenericArgsRef<'tcx>, - assoc: &rustc_middle::ty::AssocItem, -) -> ConstantExprKind { - assert!(assoc.trait_item_def_id.is_some()); - let name = assoc.name.to_string(); + fn trait_const_to_constant_expr_kind<'tcx, S: BaseState<'tcx> + HasOwnerId>( + s: &S, + _const_def_id: rustc_hir::def_id::DefId, + generics: rustc_middle::ty::GenericArgsRef<'tcx>, + assoc: &rustc_middle::ty::AssocItem, + ) -> ConstantExprKind { + assert!(assoc.trait_item_def_id.is_some()); + let name = assoc.name.to_string(); - // Retrieve the trait information - let impl_expr = get_trait_info(s, generics, assoc); + // Retrieve the trait information + let impl_expr = get_trait_info(s, generics, assoc); - ConstantExprKind::TraitConst { impl_expr, name } -} + ConstantExprKind::TraitConst { impl_expr, name } + } -impl ConstantExprKind { - pub fn decorate(self, ty: Ty, span: Span) -> Decorated { - Decorated { - contents: Box::new(self), - hir_id: None, - attributes: vec![], - ty, - span, + impl ConstantExprKind { + pub fn decorate(self, ty: Ty, span: Span) -> Decorated { + Decorated { + contents: Box::new(self), + hir_id: None, + attributes: vec![], + ty, + span, + } } } -} - -pub enum TranslateUnevalRes { - // TODO: rename - GlobalName(ConstantExpr), - EvaluatedConstant(T), -} -pub trait ConstantExt<'tcx>: Sized + std::fmt::Debug { - fn eval_constant>(&self, s: &S) -> Option; + pub enum TranslateUnevalRes { + // TODO: rename + GlobalName(ConstantExpr), + EvaluatedConstant(T), + } - /// Performs a one-step translation of a constant. - /// - When a constant refers to a named top-level constant, we want to use that, thus we translate the constant to a `ConstantExprKind::GlobalName`. This is captured by the variant `TranslateUnevalRes::GlobalName`. - /// - When a constant refers to a anonymous top-level constant, we evaluate it. If the evaluation fails, we report an error: we expect every AnonConst to be reducible. Otherwise, we return the variant `TranslateUnevalRes::EvaluatedConstant`. - fn translate_uneval( - &self, - s: &impl UnderOwnerState<'tcx>, - ucv: rustc_middle::ty::UnevaluatedConst<'tcx>, - span: rustc_span::Span, - ) -> TranslateUnevalRes { - let tcx = s.base().tcx; - if is_anon_const(ucv.def, tcx) { - TranslateUnevalRes::EvaluatedConstant(self.eval_constant(s).unwrap_or_else(|| { - // TODO: This is triggered when compiling using `generic_const_exprs` - supposely_unreachable_fatal!(s, "TranslateUneval"; {self, ucv}); - })) - } else { - let param_env = s.param_env(); - let ty = s.base().tcx.type_of(ucv.def); - let ty = tcx.instantiate_and_normalize_erasing_regions(ucv.args, param_env, ty); - let kind = if let Some(assoc) = s.base().tcx.opt_associated_item(ucv.def) { - if assoc.trait_item_def_id.is_some() { - // This must be a trait declaration constant - trait_const_to_constant_expr_kind(s, ucv.def, ucv.args, &assoc) + pub trait ConstantExt<'tcx>: Sized + std::fmt::Debug { + fn eval_constant>(&self, s: &S) -> Option; + + /// Performs a one-step translation of a constant. + /// - When a constant refers to a named top-level constant, we want to use that, thus we translate the constant to a `ConstantExprKind::GlobalName`. This is captured by the variant `TranslateUnevalRes::GlobalName`. + /// - When a constant refers to a anonymous top-level constant, we evaluate it. If the evaluation fails, we report an error: we expect every AnonConst to be reducible. Otherwise, we return the variant `TranslateUnevalRes::EvaluatedConstant`. + fn translate_uneval( + &self, + s: &impl UnderOwnerState<'tcx>, + ucv: rustc_middle::ty::UnevaluatedConst<'tcx>, + span: rustc_span::Span, + ) -> TranslateUnevalRes { + let tcx = s.base().tcx; + if is_anon_const(ucv.def, tcx) { + TranslateUnevalRes::EvaluatedConstant(self.eval_constant(s).unwrap_or_else(|| { + // TODO: This is triggered when compiling using `generic_const_exprs` + supposely_unreachable_fatal!(s, "TranslateUneval"; {self, ucv}); + })) + } else { + let param_env = s.param_env(); + let ty = s.base().tcx.type_of(ucv.def); + let ty = tcx.instantiate_and_normalize_erasing_regions(ucv.args, param_env, ty); + let kind = if let Some(assoc) = s.base().tcx.opt_associated_item(ucv.def) { + if assoc.trait_item_def_id.is_some() { + // This must be a trait declaration constant + trait_const_to_constant_expr_kind(s, ucv.def, ucv.args, &assoc) + } else { + // Constant appearing in an inherent impl block. + + // Solve the trait obligations + let parent_def_id = tcx.parent(ucv.def); + let trait_refs = + solve_item_traits(s, param_env, parent_def_id, ucv.args, None); + + // Convert + let id = ucv.def.sinto(s); + let generics = ucv.args.sinto(s); + ConstantExprKind::GlobalName { + id, + generics, + trait_refs, + } + } } else { - // Constant appearing in an inherent impl block. - - // Solve the trait obligations - let parent_def_id = tcx.parent(ucv.def); - let trait_refs = solve_item_traits(s, param_env, parent_def_id, ucv.args, None); - - // Convert + // Top-level constant. + assert!(ucv.args.is_empty(), "top-level constant has generics?"); let id = ucv.def.sinto(s); - let generics = ucv.args.sinto(s); ConstantExprKind::GlobalName { id, - generics, - trait_refs, + generics: vec![], + trait_refs: vec![], } - } - } else { - // Top-level constant. - assert!(ucv.args.is_empty(), "top-level constant has generics?"); - let id = ucv.def.sinto(s); - ConstantExprKind::GlobalName { - id, - generics: vec![], - trait_refs: vec![], - } - }; - let cv = kind.decorate(ty.sinto(s), span.sinto(s)); - TranslateUnevalRes::GlobalName(cv) + }; + let cv = kind.decorate(ty.sinto(s), span.sinto(s)); + TranslateUnevalRes::GlobalName(cv) + } } } -} -impl<'tcx> ConstantExt<'tcx> for ty::Const<'tcx> { - fn eval_constant>(&self, s: &S) -> Option { - let (ty, evaluated) = self - .eval(s.base().tcx, s.param_env(), rustc_span::DUMMY_SP) - .ok()?; - let evaluated = ty::Const::new(s.base().tcx, ty::ConstKind::Value(ty, evaluated)); - (&evaluated != self).then_some(evaluated) + impl<'tcx> ConstantExt<'tcx> for ty::Const<'tcx> { + fn eval_constant>(&self, s: &S) -> Option { + let (ty, evaluated) = self + .eval(s.base().tcx, s.param_env(), rustc_span::DUMMY_SP) + .ok()?; + let evaluated = ty::Const::new(s.base().tcx, ty::ConstKind::Value(ty, evaluated)); + (&evaluated != self).then_some(evaluated) + } } -} -impl<'tcx> ConstantExt<'tcx> for mir::Const<'tcx> { - fn eval_constant>(&self, s: &S) -> Option { - let evaluated = self - .eval(s.base().tcx, s.param_env(), rustc_span::DUMMY_SP) - .ok()?; - let evaluated = mir::Const::Val(evaluated, self.ty()); - (&evaluated != self).then_some(evaluated) + impl<'tcx> ConstantExt<'tcx> for mir::Const<'tcx> { + fn eval_constant>(&self, s: &S) -> Option { + let evaluated = self + .eval(s.base().tcx, s.param_env(), rustc_span::DUMMY_SP) + .ok()?; + let evaluated = mir::Const::Val(evaluated, self.ty()); + (&evaluated != self).then_some(evaluated) + } } -} -impl<'tcx, S: UnderOwnerState<'tcx>> SInto for ty::Const<'tcx> { - fn sinto(&self, s: &S) -> ConstantExpr { - use rustc_middle::query::Key; - let span = self.default_span(s.base().tcx); - match self.kind() { - ty::ConstKind::Param(p) => { - let ty = p.find_ty_from_env(s.param_env()); - let kind = ConstantExprKind::ConstRef { id: p.sinto(s) }; - kind.decorate(ty.sinto(s), span.sinto(s)) - } - ty::ConstKind::Infer(..) => fatal!(s[span], "ty::ConstKind::Infer node? {:#?}", self), - - ty::ConstKind::Unevaluated(ucv) => match self.translate_uneval(s, ucv, span) { - TranslateUnevalRes::EvaluatedConstant(c) => return c.sinto(s), - TranslateUnevalRes::GlobalName(c) => c, - }, - ty::ConstKind::Value(ty, valtree) => valtree_to_constant_expr(s, valtree, ty, span), - ty::ConstKind::Error(_) => fatal!(s[span], "ty::ConstKind::Error"), - ty::ConstKind::Expr(e) => fatal!(s[span], "ty::ConstKind::Expr {:#?}", e), - - ty::ConstKind::Bound(i, bound) => { - supposely_unreachable_fatal!(s[span], "ty::ConstKind::Bound"; {i, bound}); + impl<'tcx, S: UnderOwnerState<'tcx>> SInto for ty::Const<'tcx> { + fn sinto(&self, s: &S) -> ConstantExpr { + use rustc_middle::query::Key; + let span = self.default_span(s.base().tcx); + match self.kind() { + ty::ConstKind::Param(p) => { + let ty = p.find_ty_from_env(s.param_env()); + let kind = ConstantExprKind::ConstRef { id: p.sinto(s) }; + kind.decorate(ty.sinto(s), span.sinto(s)) + } + ty::ConstKind::Infer(..) => { + fatal!(s[span], "ty::ConstKind::Infer node? {:#?}", self) + } + + ty::ConstKind::Unevaluated(ucv) => match self.translate_uneval(s, ucv, span) { + TranslateUnevalRes::EvaluatedConstant(c) => return c.sinto(s), + TranslateUnevalRes::GlobalName(c) => c, + }, + ty::ConstKind::Value(ty, valtree) => valtree_to_constant_expr(s, valtree, ty, span), + ty::ConstKind::Error(_) => fatal!(s[span], "ty::ConstKind::Error"), + ty::ConstKind::Expr(e) => fatal!(s[span], "ty::ConstKind::Expr {:#?}", e), + + ty::ConstKind::Bound(i, bound) => { + supposely_unreachable_fatal!(s[span], "ty::ConstKind::Bound"; {i, bound}); + } + _ => fatal!(s[span], "unexpected case"), } - _ => fatal!(s[span], "unexpected case"), } } -} -// #[tracing::instrument(skip(s))] -pub(crate) fn valtree_to_constant_expr<'tcx, S: UnderOwnerState<'tcx>>( - s: &S, - valtree: rustc_middle::ty::ValTree<'tcx>, - ty: rustc_middle::ty::Ty<'tcx>, - span: rustc_span::Span, -) -> ConstantExpr { - let kind = match (valtree, ty.kind()) { + // #[tracing::instrument(skip(s))] + pub(crate) fn valtree_to_constant_expr<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + valtree: rustc_middle::ty::ValTree<'tcx>, + ty: rustc_middle::ty::Ty<'tcx>, + span: rustc_span::Span, + ) -> ConstantExpr { + let kind = match (valtree, ty.kind()) { (_, ty::Ref(_, inner_ty, _)) => { ConstantExprKind::Borrow(valtree_to_constant_expr(s, valtree, *inner_ty, span)) } @@ -505,99 +513,105 @@ pub(crate) fn valtree_to_constant_expr<'tcx, S: UnderOwnerState<'tcx>>( {valtree, ty} ), }; - kind.decorate(ty.sinto(s), span.sinto(s)) -} + kind.decorate(ty.sinto(s), span.sinto(s)) + } -pub(crate) fn const_value_reference_to_constant_expr<'tcx, S: UnderOwnerState<'tcx>>( - s: &S, - ty: rustc_middle::ty::Ty<'tcx>, - val: rustc_middle::mir::ConstValue<'tcx>, - span: rustc_span::Span, -) -> ConstantExpr { - let tcx = s.base().tcx; - - let dc = tcx - .try_destructure_mir_constant_for_user_output(val, ty) - .s_unwrap(s); - - // Iterate over the fields, which should be values - assert!(dc.variant.is_none()); - - // The type should be tuple - let hax_ty = ty.sinto(s); - match &hax_ty { - Ty::Tuple(_) => (), - _ => { - fatal!(s[span], "Expected the type to be tuple: {:?}", val) - } - }; + pub(crate) fn const_value_reference_to_constant_expr<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + ty: rustc_middle::ty::Ty<'tcx>, + val: rustc_middle::mir::ConstValue<'tcx>, + span: rustc_span::Span, + ) -> ConstantExpr { + let tcx = s.base().tcx; - // Below: we are mutually recursive with [const_value_to_constant_expr], - // which takes a [Const] as input, but it should be - // ok because we call it on a strictly smaller value. - let fields: Vec = dc - .fields - .iter() - .copied() - .map(|(val, ty)| const_value_to_constant_expr(s, ty, val, span)) - .collect(); - (ConstantExprKind::Tuple { fields }).decorate(hax_ty, span.sinto(s)) -} + let dc = tcx + .try_destructure_mir_constant_for_user_output(val, ty) + .s_unwrap(s); + + // Iterate over the fields, which should be values + assert!(dc.variant.is_none()); -pub fn const_value_to_constant_expr<'tcx, S: UnderOwnerState<'tcx>>( - s: &S, - ty: rustc_middle::ty::Ty<'tcx>, - val: rustc_middle::mir::ConstValue<'tcx>, - span: rustc_span::Span, -) -> ConstantExpr { - use rustc_middle::mir::ConstValue; - match val { - ConstValue::Scalar(scalar) => scalar_to_constant_expr(s, ty, &scalar, span), - ConstValue::Indirect { .. } => const_value_reference_to_constant_expr(s, ty, val, span), - ConstValue::Slice { data, meta } => { - let end = meta.try_into().unwrap(); - // This is outside of the interpreter, so we are okay to use - // `inspect_with_uninit_and_ptr_outside_interpreter`. Moreover this is a string/byte - // literal, so we don't have to care about initialization. - // This is copied from `ConstantValue::try_get_slice_bytes_for_diagnostics`, available - // only in a more recent rustc version. - let slice: &[u8] = data - .inner() - .inspect_with_uninit_and_ptr_outside_interpreter(0..end); - ConstantExprKind::Literal(ConstantLiteral::byte_str(slice.to_vec(), StrStyle::Cooked)) + // The type should be tuple + let hax_ty = ty.sinto(s); + match &hax_ty { + Ty::Tuple(_) => (), + _ => { + fatal!(s[span], "Expected the type to be tuple: {:?}", val) + } + }; + + // Below: we are mutually recursive with [const_value_to_constant_expr], + // which takes a [Const] as input, but it should be + // ok because we call it on a strictly smaller value. + let fields: Vec = dc + .fields + .iter() + .copied() + .map(|(val, ty)| const_value_to_constant_expr(s, ty, val, span)) + .collect(); + (ConstantExprKind::Tuple { fields }).decorate(hax_ty, span.sinto(s)) + } + + pub fn const_value_to_constant_expr<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + ty: rustc_middle::ty::Ty<'tcx>, + val: rustc_middle::mir::ConstValue<'tcx>, + span: rustc_span::Span, + ) -> ConstantExpr { + use rustc_middle::mir::ConstValue; + match val { + ConstValue::Scalar(scalar) => scalar_to_constant_expr(s, ty, &scalar, span), + ConstValue::Indirect { .. } => const_value_reference_to_constant_expr(s, ty, val, span), + ConstValue::Slice { data, meta } => { + let end = meta.try_into().unwrap(); + // This is outside of the interpreter, so we are okay to use + // `inspect_with_uninit_and_ptr_outside_interpreter`. Moreover this is a string/byte + // literal, so we don't have to care about initialization. + // This is copied from `ConstantValue::try_get_slice_bytes_for_diagnostics`, available + // only in a more recent rustc version. + let slice: &[u8] = data + .inner() + .inspect_with_uninit_and_ptr_outside_interpreter(0..end); + ConstantExprKind::Literal(ConstantLiteral::byte_str( + slice.to_vec(), + StrStyle::Cooked, + )) .decorate(ty.sinto(s), span.sinto(s)) - } - ConstValue::ZeroSized { .. } => { - // Should be unit - let hty = ty.sinto(s); - let cv = match &hty { - Ty::Tuple(tys) if tys.is_empty() => ConstantExprKind::Tuple { fields: Vec::new() }, - Ty::Arrow(_) => match ty.kind() { - rustc_middle::ty::TyKind::FnDef(def_id, args) => { - let (def_id, generics, generics_impls, method_impl) = - get_function_from_def_id_and_generics(s, *def_id, args); - - ConstantExprKind::FnPtr { - def_id, - generics, - generics_impls, - method_impl, - } + } + ConstValue::ZeroSized { .. } => { + // Should be unit + let hty = ty.sinto(s); + let cv = match &hty { + Ty::Tuple(tys) if tys.is_empty() => { + ConstantExprKind::Tuple { fields: Vec::new() } } - kind => { - fatal!(s[span], "Unexpected:"; {kind}) + Ty::Arrow(_) => match ty.kind() { + rustc_middle::ty::TyKind::FnDef(def_id, args) => { + let (def_id, generics, generics_impls, method_impl) = + get_function_from_def_id_and_generics(s, *def_id, args); + + ConstantExprKind::FnPtr { + def_id, + generics, + generics_impls, + method_impl, + } + } + kind => { + fatal!(s[span], "Unexpected:"; {kind}) + } + }, + _ => { + fatal!( + s[span], + "Expected the type to be tuple or arrow"; + {val, ty} + ) } - }, - _ => { - fatal!( - s[span], - "Expected the type to be tuple or arrow"; - {val, ty} - ) - } - }; + }; - cv.decorate(hty, span.sinto(s)) + cv.decorate(hty, span.sinto(s)) + } } } } diff --git a/frontend/exporter/src/index_vec.rs b/frontend/exporter/src/index_vec.rs index 0e27a6c91..2fb4ad9e4 100644 --- a/frontend/exporter/src/index_vec.rs +++ b/frontend/exporter/src/index_vec.rs @@ -1,15 +1,14 @@ use crate::prelude::*; -use rustc_index::{Idx, IndexSlice}; - #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub struct IndexVec { +pub struct IndexVec { pub raw: Vec, _marker: std::marker::PhantomData, } -impl IndexVec { +#[cfg(feature = "rustc")] +impl IndexVec { pub fn into_iter_enumerated( self, ) -> impl DoubleEndedIterator + ExactSizeIterator { @@ -20,20 +19,23 @@ impl IndexVec { } } -impl std::ops::Deref for IndexVec { - type Target = IndexSlice; +#[cfg(feature = "rustc")] +impl std::ops::Deref for IndexVec { + type Target = rustc_index::IndexSlice; fn deref(&self) -> &Self::Target { Self::Target::from_raw(&self.raw) } } -impl std::ops::DerefMut for IndexVec { +#[cfg(feature = "rustc")] +impl std::ops::DerefMut for IndexVec { fn deref_mut(&mut self) -> &mut Self::Target { Self::Target::from_raw_mut(&mut self.raw) } } -impl Into> for rustc_index::IndexVec { +#[cfg(feature = "rustc")] +impl Into> for rustc_index::IndexVec { fn into(self) -> IndexVec { IndexVec { raw: self.raw, @@ -42,8 +44,14 @@ impl Into> for rustc_index::IndexVec { } } -impl, U: Clone /*TODO: remove me?*/, T: SInto> - SInto> for IndexSlice +#[cfg(feature = "rustc")] +impl< + S, + J: rustc_index::Idx, + I: rustc_index::Idx + SInto, + U: Clone, /*TODO: remove me?*/ + T: SInto, + > SInto> for rustc_index::IndexSlice { fn sinto(&self, s: &S) -> IndexVec { IndexVec { @@ -53,9 +61,10 @@ impl, U: Clone /*TODO: remove me?*/, T: SInto FromIterator for IndexVec where - I: Idx, + I: rustc_index::Idx, { #[inline] fn from_iter>(iter: It) -> Self { @@ -73,6 +82,7 @@ macro_rules! make_idx_wrapper { pub enum $type { $type(usize), } + #[cfg(feature = "rustc")] const _: () = { use rustc_index::Idx; type OriginalType = $($mod::)+$type; diff --git a/frontend/exporter/src/lib.rs b/frontend/exporter/src/lib.rs index b0185721a..89ce6c68b 100644 --- a/frontend/exporter/src/lib.rs +++ b/frontend/exporter/src/lib.rs @@ -1,5 +1,3 @@ -#![feature(rustc_private)] -#![feature(box_patterns)] #![feature(concat_idents)] #![feature(trait_alias)] #![feature(type_changing_struct_update)] @@ -9,33 +7,40 @@ #![allow(incomplete_features)] #![feature(specialization)] #![allow(rustdoc::private_intra_doc_links)] +#![cfg_attr(feature = "rustc", feature(rustc_private))] -extern crate rustc_abi; -extern crate rustc_ast; -extern crate rustc_ast_pretty; -extern crate rustc_data_structures; -extern crate rustc_driver; -extern crate rustc_errors; -extern crate rustc_hir; -extern crate rustc_hir_analysis; -extern crate rustc_index; -extern crate rustc_infer; -extern crate rustc_interface; -extern crate rustc_middle; -extern crate rustc_mir_build; -extern crate rustc_session; -extern crate rustc_span; -extern crate rustc_target; -extern crate rustc_trait_selection; -extern crate rustc_type_ir; +cfg_if::cfg_if! { + if #[cfg(feature = "rustc")] { + extern crate rustc_abi; + extern crate rustc_ast; + extern crate rustc_ast_pretty; + extern crate rustc_data_structures; + extern crate rustc_driver; + extern crate rustc_errors; + extern crate rustc_hir; + extern crate rustc_hir_analysis; + extern crate rustc_index; + extern crate rustc_infer; + extern crate rustc_interface; + extern crate rustc_middle; + extern crate rustc_mir_build; + extern crate rustc_session; + extern crate rustc_span; + extern crate rustc_target; + extern crate rustc_trait_selection; + extern crate rustc_type_ir; + + mod rustc_utils; + pub mod state; + mod utils; + mod deterministic_hash; + } +} mod body; mod constant_utils; -mod rustc_utils; -pub mod state; mod types; -mod deterministic_hash; mod index_vec; mod prelude; @@ -44,7 +49,6 @@ pub use prelude::*; mod sinto; mod traits; -mod utils; pub use hax_adt_into::AdtInto; pub use sinto::SInto; diff --git a/frontend/exporter/src/prelude.rs b/frontend/exporter/src/prelude.rs index d7350e868..c7fd69104 100644 --- a/frontend/exporter/src/prelude.rs +++ b/frontend/exporter/src/prelude.rs @@ -1,4 +1,3 @@ -pub(crate) use crate::utils::*; pub use crate::*; pub use schemars::{schema_for, JsonSchema}; pub use serde::{Deserialize, Serialize}; @@ -9,9 +8,16 @@ pub use std::rc::Rc; pub use crate::body::*; pub use crate::constant_utils::*; pub use crate::index_vec::*; -pub use crate::rustc_utils::*; -pub use crate::state::*; pub use crate::traits::*; pub use crate::types::*; +#[cfg(feature = "rustc")] +pub use self::rustc::*; +#[cfg(feature = "rustc")] +pub mod rustc { + pub use crate::rustc_utils::*; + pub use crate::state::*; + pub use crate::utils::*; +} + pub(crate) use hax_adt_into::derive_group; diff --git a/frontend/exporter/src/sinto.rs b/frontend/exporter/src/sinto.rs index 9ee74934c..dc162aa70 100644 --- a/frontend/exporter/src/sinto.rs +++ b/frontend/exporter/src/sinto.rs @@ -14,6 +14,7 @@ macro_rules! sinto_todo { todo: String }, } + #[cfg(feature = "rustc")] impl<$($($lts,)*)? S> SInto for $($mod)::+::$type$(<$($lts,)*>)? { fn sinto(&self, _: &S) -> $renamed { $renamed::$type{todo: format!("{:?}", self)} @@ -29,6 +30,7 @@ macro_rules! sinto_todo { macro_rules! sinto_as_usize { ($($mod:ident)::+, $type:ident$(<$($lts:lifetime),*$(,)?>)?) => { pub type $type = usize; + #[cfg(feature = "rustc")] impl<$($($lts,)*)? S> SInto for $($mod)::+::$type$(<$($lts,)*>)? { fn sinto(&self, _: &S) -> $type { self.as_usize() @@ -79,8 +81,7 @@ impl> SInto> for [T] { } impl> SInto> for Box<[T]> { fn sinto(&self, s: &S) -> Vec { - let box x = self; - x.into_iter().map(|x| x.sinto(s)).collect() + (&*self).into_iter().map(|x| x.sinto(s)).collect() } } @@ -89,6 +90,7 @@ impl> SInto> for Vec { self.into_iter().map(|x| x.sinto(s)).collect() } } +#[cfg(feature = "rustc")] impl SInto> for rustc_data_structures::sync::Lrc<[u8]> { fn sinto(&self, _s: &S) -> Vec { (**self).iter().cloned().collect() diff --git a/frontend/exporter/src/state.rs b/frontend/exporter/src/state.rs index 1bd1508c1..efdf70691 100644 --- a/frontend/exporter/src/state.rs +++ b/frontend/exporter/src/state.rs @@ -176,7 +176,7 @@ mk!( } ); -pub use types::*; +pub use self::types::*; impl<'tcx> State, (), (), ()> { pub fn new( @@ -238,17 +238,6 @@ pub trait BaseState<'tcx> = HasBase<'tcx> + Clone + IsState<'tcx>; /// State of anything below a `owner_id` pub trait UnderOwnerState<'tcx> = BaseState<'tcx> + HasOwnerId; -/// Meta-informations about an `impl TRAIT for -/// TYPE where PREDICATES {}` -#[derive_group(Serializers)] -#[derive(Clone, Debug, JsonSchema)] -pub struct ImplInfos { - pub generics: TyGenerics, - pub clauses: Vec<(Clause, Span)>, - pub typ: Ty, - pub trait_ref: Option, -} - impl ImplInfos { fn from<'tcx>(base: Base<'tcx>, did: rustc_hir::def_id::DefId) -> Self { let tcx = base.tcx; diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 97c6acbfd..67d7cd47c 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -67,442 +67,457 @@ pub struct ImplExpr { pub args: Vec, } -// FIXME: this has visibility `pub(crate)` only because of https://github.com/rust-lang/rust/issues/83049 -pub(crate) mod search_clause { - use crate::prelude::UnderOwnerState; - use crate::rustc_utils::*; - use crate::{IntoPredicateId, PredicateId}; - use rustc_middle::ty::*; +#[cfg(feature = "rustc")] +pub mod rustc { + use super::*; + // FIXME: this has visibility `pub(crate)` only because of https://github.com/rust-lang/rust/issues/83049 + pub(crate) mod search_clause { + use crate::prelude::UnderOwnerState; + use crate::rustc_utils::*; + use crate::{IntoPredicateId, PredicateId}; + use rustc_middle::ty::*; - fn predicates_to_poly_trait_predicates<'tcx>( - tcx: TyCtxt<'tcx>, - predicates: impl Iterator>, - generics: GenericArgsRef<'tcx>, - ) -> impl Iterator> { - predicates - .map(move |pred| pred.kind().subst(tcx, generics)) - .filter_map(|pred| pred.as_poly_trait_predicate()) - } - - #[derive(Clone, Debug)] - pub enum PathChunk<'tcx> { - AssocItem { - item: AssocItem, - predicate: PolyTraitPredicate<'tcx>, - predicate_id: PredicateId, - index: usize, - }, - Parent { - predicate: PolyTraitPredicate<'tcx>, - predicate_id: PredicateId, - index: usize, - }, - } - pub type Path<'tcx> = Vec>; - - /// Custom equality on `Predicate`s. - /// - /// Sometimes Rustc inserts extra generic arguments: I noticed - /// some `__H` second argument given to core::hash::Hash for - /// instance. `__H` seems to be inserted in [1]. Such extra - /// arguments seems to be ignored by `default_print_def_path` [2]. - /// - /// Hence, for now, equality is decided by comparing the debug - /// string representations of `Predicate`s. - /// - /// Note there exist also predicates that are different, - /// `Eq`-wise, but whose `sinto` counterpart are equal. - /// - /// TODO: figure out how to implement this function in a sane way. - /// - /// [1]: https://github.com/rust-lang/rust/blob/b0889cb4ed0e6f3ed9f440180678872b02e7052c/compiler/rustc_builtin_macros/src/deriving/hash.rs#L20 - /// [2]: https://github.com/rust-lang/rust/blob/b0889cb4ed0e6f3ed9f440180678872b02e7052c/compiler/rustc_middle/src/ty/print/mod.rs#L141 - fn predicate_equality<'tcx, S: UnderOwnerState<'tcx>>( - x: Predicate<'tcx>, - y: Predicate<'tcx>, - param_env: rustc_middle::ty::ParamEnv<'tcx>, - s: &S, - ) -> bool { - let tcx = s.base().tcx; - let erase_and_norm = - |x| tcx.erase_regions(tcx.try_normalize_erasing_regions(param_env, x).unwrap_or(x)); - // Lifetime and constantness are irrelevant when resolving instances - let x = erase_and_norm(x); - let y = erase_and_norm(y); - let sx = format!("{:?}", x.kind().skip_binder()); - let sy = format!("{:?}", y.kind().skip_binder()); - let result = sx == sy; - const DEBUG: bool = false; - if DEBUG && result { - use crate::{Predicate, SInto}; - let xs: Predicate = x.sinto(s); - let ys: Predicate = y.sinto(s); - if x != y { - eprintln!("######################## predicate_equality ########################"); - eprintln!("x={:#?}", x); - eprintln!("y={:#?}", y); - eprintln!("######################## sinto ########################"); - eprintln!("sinto(x)={:#?}", xs); - eprintln!("sinto(y)={:#?}", ys); - } + fn predicates_to_poly_trait_predicates<'tcx>( + tcx: TyCtxt<'tcx>, + predicates: impl Iterator>, + generics: GenericArgsRef<'tcx>, + ) -> impl Iterator> { + predicates + .map(move |pred| pred.kind().subst(tcx, generics)) + .filter_map(|pred| pred.as_poly_trait_predicate()) } - result - } - #[extension_traits::extension(pub trait TraitPredicateExt)] - impl<'tcx, S: UnderOwnerState<'tcx>> PolyTraitPredicate<'tcx> { - #[tracing::instrument(level = "trace", skip(s))] - fn parents_trait_predicates(self, s: &S) -> Vec<(usize, PolyTraitPredicate<'tcx>)> { - let tcx = s.base().tcx; - let predicates = tcx - .predicates_defined_on_or_above(self.def_id()) - .into_iter() - .map(|apred| apred.predicate); - predicates_to_poly_trait_predicates(tcx, predicates, self.skip_binder().trait_ref.args) - .enumerate() - .collect() + #[derive(Clone, Debug)] + pub enum PathChunk<'tcx> { + AssocItem { + item: AssocItem, + predicate: PolyTraitPredicate<'tcx>, + predicate_id: PredicateId, + index: usize, + }, + Parent { + predicate: PolyTraitPredicate<'tcx>, + predicate_id: PredicateId, + index: usize, + }, } - #[tracing::instrument(level = "trace", skip(s))] - fn associated_items_trait_predicates( - self, + pub type Path<'tcx> = Vec>; + + /// Custom equality on `Predicate`s. + /// + /// Sometimes Rustc inserts extra generic arguments: I noticed + /// some `__H` second argument given to core::hash::Hash for + /// instance. `__H` seems to be inserted in [1]. Such extra + /// arguments seems to be ignored by `default_print_def_path` [2]. + /// + /// Hence, for now, equality is decided by comparing the debug + /// string representations of `Predicate`s. + /// + /// Note there exist also predicates that are different, + /// `Eq`-wise, but whose `sinto` counterpart are equal. + /// + /// TODO: figure out how to implement this function in a sane way. + /// + /// [1]: https://github.com/rust-lang/rust/blob/b0889cb4ed0e6f3ed9f440180678872b02e7052c/compiler/rustc_builtin_macros/src/deriving/hash.rs#L20 + /// [2]: https://github.com/rust-lang/rust/blob/b0889cb4ed0e6f3ed9f440180678872b02e7052c/compiler/rustc_middle/src/ty/print/mod.rs#L141 + fn predicate_equality<'tcx, S: UnderOwnerState<'tcx>>( + x: Predicate<'tcx>, + y: Predicate<'tcx>, + param_env: rustc_middle::ty::ParamEnv<'tcx>, s: &S, - ) -> Vec<( - AssocItem, - EarlyBinder<'tcx, Vec<(usize, PolyTraitPredicate<'tcx>)>>, - )> { + ) -> bool { let tcx = s.base().tcx; - tcx.associated_items(self.def_id()) - .in_definition_order() - .filter(|item| item.kind == AssocKind::Type) - .copied() - .map(|item| { - let bounds = tcx.item_bounds(item.def_id).map_bound(|clauses| { - predicates_to_poly_trait_predicates( - tcx, - clauses.into_iter().map(|clause| clause.as_predicate()), - self.skip_binder().trait_ref.args, - ) - .enumerate() - .collect() - }); - (item, bounds) - }) - .collect() + let erase_and_norm = + |x| tcx.erase_regions(tcx.try_normalize_erasing_regions(param_env, x).unwrap_or(x)); + // Lifetime and constantness are irrelevant when resolving instances + let x = erase_and_norm(x); + let y = erase_and_norm(y); + let sx = format!("{:?}", x.kind().skip_binder()); + let sy = format!("{:?}", y.kind().skip_binder()); + let result = sx == sy; + const DEBUG: bool = false; + if DEBUG && result { + use crate::{Predicate, SInto}; + let xs: Predicate = x.sinto(s); + let ys: Predicate = y.sinto(s); + if x != y { + eprintln!( + "######################## predicate_equality ########################" + ); + eprintln!("x={:#?}", x); + eprintln!("y={:#?}", y); + eprintln!( + "######################## sinto ########################" + ); + eprintln!("sinto(x)={:#?}", xs); + eprintln!("sinto(y)={:#?}", ys); + } + } + result } - #[tracing::instrument(level = "trace", skip(s))] - fn path_to( - self, - s: &S, - target: PolyTraitRef<'tcx>, - param_env: rustc_middle::ty::ParamEnv<'tcx>, - ) -> Option> { - let tcx = s.base().tcx; - if predicate_equality(self.upcast(tcx), target.upcast(tcx), param_env, s) { - return Some(vec![]); + #[extension_traits::extension(pub trait TraitPredicateExt)] + impl<'tcx, S: UnderOwnerState<'tcx>> PolyTraitPredicate<'tcx> { + #[tracing::instrument(level = "trace", skip(s))] + fn parents_trait_predicates(self, s: &S) -> Vec<(usize, PolyTraitPredicate<'tcx>)> { + let tcx = s.base().tcx; + let predicates = tcx + .predicates_defined_on_or_above(self.def_id()) + .into_iter() + .map(|apred| apred.predicate); + predicates_to_poly_trait_predicates( + tcx, + predicates, + self.skip_binder().trait_ref.args, + ) + .enumerate() + .collect() + } + #[tracing::instrument(level = "trace", skip(s))] + fn associated_items_trait_predicates( + self, + s: &S, + ) -> Vec<( + AssocItem, + EarlyBinder<'tcx, Vec<(usize, PolyTraitPredicate<'tcx>)>>, + )> { + let tcx = s.base().tcx; + tcx.associated_items(self.def_id()) + .in_definition_order() + .filter(|item| item.kind == AssocKind::Type) + .copied() + .map(|item| { + let bounds = tcx.item_bounds(item.def_id).map_bound(|clauses| { + predicates_to_poly_trait_predicates( + tcx, + clauses.into_iter().map(|clause| clause.as_predicate()), + self.skip_binder().trait_ref.args, + ) + .enumerate() + .collect() + }); + (item, bounds) + }) + .collect() } - let recurse = |p: Self| { - if p == self { - return None; + #[tracing::instrument(level = "trace", skip(s))] + fn path_to( + self, + s: &S, + target: PolyTraitRef<'tcx>, + param_env: rustc_middle::ty::ParamEnv<'tcx>, + ) -> Option> { + let tcx = s.base().tcx; + if predicate_equality(self.upcast(tcx), target.upcast(tcx), param_env, s) { + return Some(vec![]); } - p.path_to(s, target, param_env) - }; - fn cons(hd: T, tail: Vec) -> Vec { - vec![hd].into_iter().chain(tail.into_iter()).collect() - } - self.parents_trait_predicates(s) - .into_iter() - .filter_map(|(index, p)| { - recurse(p).map(|path| { - cons( - PathChunk::Parent { - predicate: p, - predicate_id: p.predicate_id(s), - index, - }, - path, - ) + + let recurse = |p: Self| { + if p == self { + return None; + } + p.path_to(s, target, param_env) + }; + fn cons(hd: T, tail: Vec) -> Vec { + vec![hd].into_iter().chain(tail.into_iter()).collect() + } + self.parents_trait_predicates(s) + .into_iter() + .filter_map(|(index, p)| { + recurse(p).map(|path| { + cons( + PathChunk::Parent { + predicate: p, + predicate_id: p.predicate_id(s), + index, + }, + path, + ) + }) }) - }) - .max_by_key(|path| path.len()) - .or_else(|| { - self.associated_items_trait_predicates(s) - .into_iter() - .filter_map(|(item, binder)| { - binder.skip_binder().into_iter().find_map(|(index, p)| { - recurse(p).map(|path| { - cons( - PathChunk::AssocItem { - item, - predicate_id: p.predicate_id(s), - predicate: p, - index, - }, - path, - ) + .max_by_key(|path| path.len()) + .or_else(|| { + self.associated_items_trait_predicates(s) + .into_iter() + .filter_map(|(item, binder)| { + binder.skip_binder().into_iter().find_map(|(index, p)| { + recurse(p).map(|path| { + cons( + PathChunk::AssocItem { + item, + predicate_id: p.predicate_id(s), + predicate: p, + index, + }, + path, + ) + }) }) }) - }) - .max_by_key(|path| path.len()) - }) + .max_by_key(|path| path.len()) + }) + } } } -} -impl ImplExprAtom { - fn with_args(self, args: Vec, r#trait: TraitRef) -> ImplExpr { - ImplExpr { - r#impl: self, - args, - r#trait, + impl ImplExprAtom { + fn with_args(self, args: Vec, r#trait: TraitRef) -> ImplExpr { + ImplExpr { + r#impl: self, + args, + r#trait, + } } } -} - -#[tracing::instrument(level = "trace", skip(s))] -fn impl_exprs<'tcx, S: UnderOwnerState<'tcx>>( - s: &S, - obligations: &Vec< - rustc_trait_selection::traits::Obligation<'tcx, rustc_middle::ty::Predicate<'tcx>>, - >, -) -> Vec { - obligations - .into_iter() - .flat_map(|obligation| { - obligation - .predicate - .kind() - .as_poly_trait_predicate() - .map(|trait_ref| { - trait_ref - .map_bound(|p| p.trait_ref) - .impl_expr(s, obligation.param_env) - }) - }) - .collect() -} -pub trait IntoImplExpr<'tcx> { - fn impl_expr>( - &self, + #[tracing::instrument(level = "trace", skip(s))] + fn impl_exprs<'tcx, S: UnderOwnerState<'tcx>>( s: &S, - param_env: rustc_middle::ty::ParamEnv<'tcx>, - ) -> ImplExpr; -} + obligations: &Vec< + rustc_trait_selection::traits::Obligation<'tcx, rustc_middle::ty::Predicate<'tcx>>, + >, + ) -> Vec { + obligations + .into_iter() + .flat_map(|obligation| { + obligation + .predicate + .kind() + .as_poly_trait_predicate() + .map(|trait_ref| { + trait_ref + .map_bound(|p| p.trait_ref) + .impl_expr(s, obligation.param_env) + }) + }) + .collect() + } -impl<'tcx> IntoImplExpr<'tcx> for rustc_middle::ty::PolyTraitPredicate<'tcx> { - fn impl_expr>( - &self, - s: &S, - param_env: rustc_middle::ty::ParamEnv<'tcx>, - ) -> ImplExpr { - use rustc_middle::ty::ToPolyTraitRef; - self.to_poly_trait_ref().impl_expr(s, param_env) + pub trait IntoImplExpr<'tcx> { + fn impl_expr>( + &self, + s: &S, + param_env: rustc_middle::ty::ParamEnv<'tcx>, + ) -> ImplExpr; } -} -impl<'tcx> IntoImplExpr<'tcx> for rustc_middle::ty::PolyTraitRef<'tcx> { - #[tracing::instrument(level = "trace", skip(s))] - fn impl_expr>( - &self, - s: &S, - param_env: rustc_middle::ty::ParamEnv<'tcx>, - ) -> ImplExpr { - use rustc_trait_selection::traits::*; - let trait_ref: Binder = self.sinto(s); - let trait_ref = trait_ref.value; - match select_trait_candidate(s, param_env, *self) { - ImplSource::UserDefined(ImplSourceUserDefinedData { - impl_def_id, - args: generics, - nested, - }) => ImplExprAtom::Concrete { - id: impl_def_id.sinto(s), - generics: generics.sinto(s), - } - .with_args(impl_exprs(s, &nested), trait_ref), - ImplSource::Param(nested) => { - use search_clause::TraitPredicateExt; - let tcx = s.base().tcx; - let predicates = &tcx.predicates_defined_on_or_above(s.owner_id()); - let Some((apred, path)) = predicates.into_iter().find_map(|apred| { - apred + + impl<'tcx> IntoImplExpr<'tcx> for rustc_middle::ty::PolyTraitPredicate<'tcx> { + fn impl_expr>( + &self, + s: &S, + param_env: rustc_middle::ty::ParamEnv<'tcx>, + ) -> ImplExpr { + use rustc_middle::ty::ToPolyTraitRef; + self.to_poly_trait_ref().impl_expr(s, param_env) + } + } + impl<'tcx> IntoImplExpr<'tcx> for rustc_middle::ty::PolyTraitRef<'tcx> { + #[tracing::instrument(level = "trace", skip(s))] + fn impl_expr>( + &self, + s: &S, + param_env: rustc_middle::ty::ParamEnv<'tcx>, + ) -> ImplExpr { + use rustc_trait_selection::traits::*; + let trait_ref: Binder = self.sinto(s); + let trait_ref = trait_ref.value; + match select_trait_candidate(s, param_env, *self) { + ImplSource::UserDefined(ImplSourceUserDefinedData { + impl_def_id, + args: generics, + nested, + }) => ImplExprAtom::Concrete { + id: impl_def_id.sinto(s), + generics: generics.sinto(s), + } + .with_args(impl_exprs(s, &nested), trait_ref), + ImplSource::Param(nested) => { + use search_clause::TraitPredicateExt; + let tcx = s.base().tcx; + let predicates = &tcx.predicates_defined_on_or_above(s.owner_id()); + let Some((apred, path)) = predicates.into_iter().find_map(|apred| { + apred + .predicate + .as_trait_clause() + .map(|poly_trait_predicate| poly_trait_predicate) + .and_then(|poly_trait_predicate| { + poly_trait_predicate.path_to(s, self.clone(), param_env) + }) + .map(|path| (apred, path)) + }) else { + supposely_unreachable_fatal!(s, "ImplExprPredNotFound"; { + self, nested, predicates, trait_ref + }) + }; + use rustc_middle::ty::ToPolyTraitRef; + let r#trait = apred .predicate .as_trait_clause() - .map(|poly_trait_predicate| poly_trait_predicate) - .and_then(|poly_trait_predicate| { - poly_trait_predicate.path_to(s, self.clone(), param_env) - }) - .map(|path| (apred, path)) - }) else { - supposely_unreachable_fatal!(s, "ImplExprPredNotFound"; { - self, nested, predicates, trait_ref - }) - }; - use rustc_middle::ty::ToPolyTraitRef; - let r#trait = apred - .predicate - .as_trait_clause() - .s_unwrap(s) - .to_poly_trait_ref() - .sinto(s); - let path = path.sinto(s); - if apred.is_extra_self_predicate { - ImplExprAtom::SelfImpl { r#trait, path } + .s_unwrap(s) + .to_poly_trait_ref() + .sinto(s); + let path = path.sinto(s); + if apred.is_extra_self_predicate { + ImplExprAtom::SelfImpl { r#trait, path } + .with_args(impl_exprs(s, &nested), trait_ref) + } else { + ImplExprAtom::LocalBound { + predicate_id: apred.predicate.predicate_id(s), + r#trait, + path, + } .with_args(impl_exprs(s, &nested), trait_ref) - } else { - ImplExprAtom::LocalBound { - predicate_id: apred.predicate.predicate_id(s), - r#trait, - path, } - .with_args(impl_exprs(s, &nested), trait_ref) } - } - // We ignore the contained obligations here. For example for `(): Send`, the - // obligations contained would be `[(): Send]`, which leads to an infinite loop. There - // might be important obligation shere inother cases; we'll have to see if that comes - // up. - ImplSource::Builtin(source, _ignored) => { - let atom = match source { - BuiltinImplSource::Object { .. } => ImplExprAtom::Dyn, - _ => ImplExprAtom::Builtin { - r#trait: self.skip_binder().sinto(s), - }, - }; - atom.with_args(vec![], trait_ref) + // We ignore the contained obligations here. For example for `(): Send`, the + // obligations contained would be `[(): Send]`, which leads to an infinite loop. There + // might be important obligation shere inother cases; we'll have to see if that comes + // up. + ImplSource::Builtin(source, _ignored) => { + let atom = match source { + BuiltinImplSource::Object { .. } => ImplExprAtom::Dyn, + _ => ImplExprAtom::Builtin { + r#trait: self.skip_binder().sinto(s), + }, + }; + atom.with_args(vec![], trait_ref) + } } } } -} -/// Given a clause `clause` in the context of some impl. block -/// `impl_did`, susbts correctly `Self` from `clause` and (1) derive a -/// `Clause` and (2) resolve an `ImplExpr`. -pub fn super_clause_to_clause_and_impl_expr<'tcx, S: UnderOwnerState<'tcx>>( - s: &S, - impl_did: rustc_span::def_id::DefId, - clause: rustc_middle::ty::Clause<'tcx>, - span: rustc_span::Span, -) -> Option<(Clause, ImplExpr, Span)> { - let tcx = s.base().tcx; - let impl_trait_ref = tcx - .impl_trait_ref(impl_did) - .map(|binder| rustc_middle::ty::Binder::dummy(binder.instantiate_identity()))?; - let original_predicate_id = { - // We don't want the id of the substituted clause id, but the - // original clause id (with, i.e., `Self`) - let s = &with_owner_id(s.base(), (), (), impl_trait_ref.def_id()); - clause.predicate_id(s) - }; - let new_clause = clause.instantiate_supertrait(tcx, impl_trait_ref); - let impl_expr = new_clause - .as_predicate() - .as_trait_clause()? - .impl_expr(s, s.param_env()); - let mut new_clause_no_binder = new_clause.sinto(s); - new_clause_no_binder.id = original_predicate_id; - Some((new_clause_no_binder, impl_expr, span.sinto(s))) -} + /// Given a clause `clause` in the context of some impl. block + /// `impl_did`, susbts correctly `Self` from `clause` and (1) derive a + /// `Clause` and (2) resolve an `ImplExpr`. + pub fn super_clause_to_clause_and_impl_expr<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + impl_did: rustc_span::def_id::DefId, + clause: rustc_middle::ty::Clause<'tcx>, + span: rustc_span::Span, + ) -> Option<(Clause, ImplExpr, Span)> { + let tcx = s.base().tcx; + let impl_trait_ref = tcx + .impl_trait_ref(impl_did) + .map(|binder| rustc_middle::ty::Binder::dummy(binder.instantiate_identity()))?; + let original_predicate_id = { + // We don't want the id of the substituted clause id, but the + // original clause id (with, i.e., `Self`) + let s = &with_owner_id(s.base(), (), (), impl_trait_ref.def_id()); + clause.predicate_id(s) + }; + let new_clause = clause.instantiate_supertrait(tcx, impl_trait_ref); + let impl_expr = new_clause + .as_predicate() + .as_trait_clause()? + .impl_expr(s, s.param_env()); + let mut new_clause_no_binder = new_clause.sinto(s); + new_clause_no_binder.id = original_predicate_id; + Some((new_clause_no_binder, impl_expr, span.sinto(s))) + } -#[tracing::instrument(level = "trace", skip(s))] -pub fn select_trait_candidate<'tcx, S: UnderOwnerState<'tcx>>( - s: &S, - param_env: rustc_middle::ty::ParamEnv<'tcx>, - trait_ref: rustc_middle::ty::PolyTraitRef<'tcx>, -) -> rustc_trait_selection::traits::Selection<'tcx> { - let tcx = s.base().tcx; - match copy_paste_from_rustc::codegen_select_candidate(tcx, (param_env, trait_ref)) { - Ok(selection) => selection, - Err(error) => fatal!( - s, - "Cannot handle error `{:?}` selecting `{:?}`", - error, - trait_ref - ), + #[tracing::instrument(level = "trace", skip(s))] + pub fn select_trait_candidate<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + param_env: rustc_middle::ty::ParamEnv<'tcx>, + trait_ref: rustc_middle::ty::PolyTraitRef<'tcx>, + ) -> rustc_trait_selection::traits::Selection<'tcx> { + let tcx = s.base().tcx; + match copy_paste_from_rustc::codegen_select_candidate(tcx, (param_env, trait_ref)) { + Ok(selection) => selection, + Err(error) => fatal!( + s, + "Cannot handle error `{:?}` selecting `{:?}`", + error, + trait_ref + ), + } } -} -pub mod copy_paste_from_rustc { - use rustc_infer::infer::TyCtxtInferExt; - use rustc_middle::traits::CodegenObligationError; - use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; - use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; - use rustc_trait_selection::traits::{ - Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext, - Unimplemented, - }; + pub mod copy_paste_from_rustc { + use rustc_infer::infer::TyCtxtInferExt; + use rustc_middle::traits::CodegenObligationError; + use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; + use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; + use rustc_trait_selection::traits::{ + Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext, + Unimplemented, + }; - /// Attempts to resolve an obligation to an `ImplSource`. The result is - /// a shallow `ImplSource` resolution, meaning that we do not - /// (necessarily) resolve all nested obligations on the impl. Note - /// that type check should guarantee to us that all nested - /// obligations *could be* resolved if we wanted to. - /// - /// This also expects that `trait_ref` is fully normalized. - pub fn codegen_select_candidate<'tcx>( - tcx: TyCtxt<'tcx>, - (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>), - ) -> Result, CodegenObligationError> { - let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); + /// Attempts to resolve an obligation to an `ImplSource`. The result is + /// a shallow `ImplSource` resolution, meaning that we do not + /// (necessarily) resolve all nested obligations on the impl. Note + /// that type check should guarantee to us that all nested + /// obligations *could be* resolved if we wanted to. + /// + /// This also expects that `trait_ref` is fully normalized. + pub fn codegen_select_candidate<'tcx>( + tcx: TyCtxt<'tcx>, + (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>), + ) -> Result, CodegenObligationError> + { + let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); - // Do the initial selection for the obligation. This yields the - // shallow result we are looking for -- that is, what specific impl. - let infcx = tcx.infer_ctxt().ignoring_regions().build(); - let mut selcx = SelectionContext::new(&infcx); + // Do the initial selection for the obligation. This yields the + // shallow result we are looking for -- that is, what specific impl. + let infcx = tcx.infer_ctxt().ignoring_regions().build(); + let mut selcx = SelectionContext::new(&infcx); - let obligation_cause = ObligationCause::dummy(); - let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref); + let obligation_cause = ObligationCause::dummy(); + let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref); - let selection = match selcx.poly_select(&obligation) { - Ok(Some(selection)) => selection, - Ok(None) => return Err(CodegenObligationError::Ambiguity), - Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented), - Err(e) => { - panic!( - "Encountered error `{:?}` selecting `{:?}` during codegen", - e, trait_ref - ) - } - }; + let selection = match selcx.poly_select(&obligation) { + Ok(Some(selection)) => selection, + Ok(None) => return Err(CodegenObligationError::Ambiguity), + Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented), + Err(e) => { + panic!( + "Encountered error `{:?}` selecting `{:?}` during codegen", + e, trait_ref + ) + } + }; - // Currently, we use a fulfillment context to completely resolve - // all nested obligations. This is because they can inform the - // inference of the impl's type parameters. - // FIXME(-Znext-solver): Doesn't need diagnostics if new solver. - let ocx = ObligationCtxt::new(&infcx); - let impl_source = selection.map(|obligation| { - ocx.register_obligation(obligation.clone()); - obligation - }); + // Currently, we use a fulfillment context to completely resolve + // all nested obligations. This is because they can inform the + // inference of the impl's type parameters. + // FIXME(-Znext-solver): Doesn't need diagnostics if new solver. + let ocx = ObligationCtxt::new(&infcx); + let impl_source = selection.map(|obligation| { + ocx.register_obligation(obligation.clone()); + obligation + }); - // In principle, we only need to do this so long as `impl_source` - // contains unbound type parameters. It could be a slight - // optimization to stop iterating early. - let errors = ocx.select_all_or_error(); - if !errors.is_empty() { - // `rustc_monomorphize::collector` assumes there are no type errors. - // Cycle errors are the only post-monomorphization errors possible; emit them now so - // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization. - for err in errors { - if let ScrubbedTraitError::Cycle(cycle) = err { - infcx.err_ctxt().report_overflow_obligation_cycle(&cycle); + // In principle, we only need to do this so long as `impl_source` + // contains unbound type parameters. It could be a slight + // optimization to stop iterating early. + let errors = ocx.select_all_or_error(); + if !errors.is_empty() { + // `rustc_monomorphize::collector` assumes there are no type errors. + // Cycle errors are the only post-monomorphization errors possible; emit them now so + // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization. + for err in errors { + if let ScrubbedTraitError::Cycle(cycle) = err { + infcx.err_ctxt().report_overflow_obligation_cycle(&cycle); + } } + return Err(CodegenObligationError::FulfillmentError); } - return Err(CodegenObligationError::FulfillmentError); - } - let impl_source = infcx.resolve_vars_if_possible(impl_source); - let impl_source = infcx.tcx.erase_regions(impl_source); + let impl_source = infcx.resolve_vars_if_possible(impl_source); + let impl_source = infcx.tcx.erase_regions(impl_source); - if impl_source.has_infer() { - // Unused lifetimes on an impl get replaced with inference vars, but never resolved, - // causing the return value of a query to contain inference vars. We do not have a concept - // for this and will in fact ICE in stable hashing of the return value. So bail out instead. - infcx.tcx.dcx().has_errors().unwrap(); - return Err(CodegenObligationError::FulfillmentError); - } + if impl_source.has_infer() { + // Unused lifetimes on an impl get replaced with inference vars, but never resolved, + // causing the return value of a query to contain inference vars. We do not have a concept + // for this and will in fact ICE in stable hashing of the return value. So bail out instead. + infcx.tcx.dcx().has_errors().unwrap(); + return Err(CodegenObligationError::FulfillmentError); + } - Ok(impl_source) + Ok(impl_source) + } } } +#[cfg(feature = "rustc")] +pub use self::rustc::*; diff --git a/frontend/exporter/src/types/copied.rs b/frontend/exporter/src/types/copied.rs index e03364a49..12718f29e 100644 --- a/frontend/exporter/src/types/copied.rs +++ b/frontend/exporter/src/types/copied.rs @@ -1,5 +1,6 @@ use crate::prelude::*; -use crate::rustc_middle::query::Key; + +#[cfg(feature = "rustc")] use rustc_middle::ty; impl std::hash::Hash for DefId { @@ -14,6 +15,7 @@ impl std::hash::Hash for DefId { } } +#[cfg(feature = "rustc")] impl<'s, S: BaseState<'s>> SInto for rustc_hir::def_id::DefId { fn sinto(&self, s: &S) -> DefId { s.base().exported_def_ids.borrow_mut().insert(self.clone()); @@ -31,6 +33,7 @@ impl<'s, S: BaseState<'s>> SInto for rustc_hir::def_id::DefId { } } +#[cfg(feature = "rustc")] impl From<&DefId> for rustc_span::def_id::DefId { fn from<'tcx>(def_id: &DefId) -> Self { let (krate, index) = def_id.index; @@ -41,6 +44,7 @@ impl From<&DefId> for rustc_span::def_id::DefId { } } +#[cfg(feature = "rustc")] impl std::convert::From for Path { fn from(v: DefId) -> Vec { std::iter::once(v.krate) @@ -56,6 +60,7 @@ impl std::convert::From for Path { } pub type GlobalIdent = DefId; +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_hir::def_id::LocalDefId { fn sinto(&self, st: &S) -> DefId { self.to_def_id().sinto(st) @@ -192,6 +197,7 @@ pub struct Scope { pub data: ScopeData, } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::mir::Const<'tcx> { fn sinto(&self, s: &S) -> ConstantExpr { use rustc_middle::mir::Const; @@ -205,6 +211,7 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::mi ), Const::Ty(_ty, c) => c.sinto(s), Const::Unevaluated(ucv, _ty) => { + use crate::rustc_middle::query::Key; let span = tcx .def_ident_span(ucv.def) .unwrap_or_else(|| ucv.def.default_span(tcx)); @@ -220,18 +227,21 @@ impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::mi // For ConstantKind we merge all the cases (Ty, Val, Unevaluated) into one pub type ConstantKind = ConstantExpr; +#[cfg(feature = "rustc")] impl SInto for rustc_middle::mir::interpret::AllocId { fn sinto(&self, _: &S) -> u64 { self.0.get() } } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto> for rustc_middle::ty::Ty<'tcx> { fn sinto(&self, s: &S) -> Box { Box::new(self.sinto(s)) } } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::Ty<'tcx> { fn sinto(&self, s: &S) -> Ty { self.kind().sinto(s) @@ -249,6 +259,7 @@ pub struct HirId { } // TODO: If not working: See original +#[cfg(feature = "rustc")] impl<'tcx, S: BaseState<'tcx>> SInto for rustc_hir::hir_id::OwnerId { fn sinto(&self, s: &S) -> DefId { self.to_def_id().sinto(s) @@ -399,6 +410,7 @@ pub struct Placeholder { pub bound: T, } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>, T: SInto, U> SInto> for rustc_middle::ty::Placeholder { @@ -421,6 +433,7 @@ pub struct Canonical { /// Reflects [`rustc_middle::ty::CanonicalUserType`] pub type CanonicalUserType = Canonical; +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>, T: SInto, U> SInto> for rustc_middle::infer::canonical::Canonical<'tcx, T> { @@ -528,10 +541,12 @@ pub struct DiscriminantValue { /// Reflects [`rustc_middle::ty::Visibility`] #[derive_group(Serializers)] #[derive(Clone, Debug, JsonSchema)] -pub enum Visibility { +pub enum Visibility { Public, Restricted(Id), } + +#[cfg(feature = "rustc")] impl, U> SInto> for rustc_middle::ty::Visibility { fn sinto(&self, s: &S) -> Visibility { use rustc_middle::ty::Visibility as T; @@ -556,6 +571,7 @@ pub struct FieldDef { pub span: Span, } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::FieldDef { fn sinto(&self, s: &S) -> FieldDef { let tcx = s.base().tcx; @@ -602,6 +618,7 @@ pub struct VariantDef { pub span: Span, } +#[cfg(feature = "rustc")] impl VariantDef { fn sfrom<'tcx, S: UnderOwnerState<'tcx>>( s: &S, @@ -672,12 +689,14 @@ pub enum GenericArg { Const(ConstantExpr), } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::GenericArg<'tcx> { fn sinto(&self, s: &S) -> GenericArg { self.unpack().sinto(s) } } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto> for rustc_middle::ty::GenericArgsRef<'tcx> { @@ -733,6 +752,7 @@ pub struct AdtExpr { pub base: Option, } +#[cfg(feature = "rustc")] impl<'tcx, S: ExprState<'tcx>> SInto for rustc_middle::thir::AdtExpr<'tcx> { fn sinto(&self, s: &S) -> AdtExpr { let variants = self.adt_def.variants(); @@ -848,8 +868,12 @@ pub struct Span { pub filename: FileName, /// Original rustc span; can be useful for reporting rustc /// diagnostics (this is used in Charon) + #[cfg(feature = "rustc")] #[serde(skip)] pub rust_span_data: Option, + #[cfg(not(feature = "rustc"))] + #[serde(skip)] + pub rust_span_data: Option<()>, // expn_backtrace: Vec, } @@ -921,6 +945,7 @@ const _: () = { } }; +#[cfg(feature = "rustc")] impl Into for rustc_span::Loc { fn into(self) -> Loc { Loc { @@ -930,6 +955,7 @@ impl Into for rustc_span::Loc { } } +#[cfg(feature = "rustc")] impl<'tcx, S: BaseState<'tcx>> SInto for rustc_span::Span { fn sinto(&self, s: &S) -> Span { let set: crate::state::ExportedSpans = s.base().exported_spans; @@ -946,6 +972,7 @@ pub struct LocalIdent { pub id: HirId, } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::thir::LocalVarId { fn sinto(&self, s: &S) -> LocalIdent { LocalIdent { @@ -970,6 +997,7 @@ pub struct Spanned { pub node: T, pub span: Span, } +#[cfg(feature = "rustc")] impl<'s, S: UnderOwnerState<'s>, T: SInto, U> SInto> for rustc_span::source_map::Spanned { @@ -999,6 +1027,7 @@ pub enum RealFileName { }, } +#[cfg(feature = "rustc")] impl SInto for rustc_data_structures::stable_hasher::Hash64 { fn sinto(&self, _: &S) -> u64 { self.as_u64() @@ -1221,6 +1250,7 @@ pub enum TokenKind { Todo(String), } +#[cfg(feature = "rustc")] impl SInto for rustc_ast::token::IdentIsRaw { fn sinto(&self, _s: &S) -> bool { match self { @@ -1266,18 +1296,21 @@ pub struct MacCall { /// string. If you need to reshape that into Rust tokens or construct, /// please use, e.g., `syn`. pub type TokenStream = String; +#[cfg(feature = "rustc")] impl<'t, S> SInto for rustc_ast::tokenstream::TokenStream { fn sinto(&self, _: &S) -> String { rustc_ast_pretty::pprust::tts_to_string(self) } } +#[cfg(feature = "rustc")] impl<'tcx, S: ExprState<'tcx>> SInto for rustc_middle::thir::BlockId { fn sinto(&self, s: &S) -> Block { s.thir().blocks[*self].sinto(s) } } +#[cfg(feature = "rustc")] impl<'tcx, S: ExprState<'tcx>> SInto for rustc_middle::thir::StmtId { fn sinto(&self, s: &S) -> Stmt { s.thir().stmts[*self].sinto(s) @@ -1286,8 +1319,10 @@ impl<'tcx, S: ExprState<'tcx>> SInto for rustc_middle::thir::StmtId { /// While translating expressions, we expect to always have a THIR /// body and an `owner_id` in the state +#[cfg(feature = "rustc")] pub trait ExprState<'tcx> = UnderOwnerState<'tcx> + HasThir<'tcx>; +#[cfg(feature = "rustc")] impl<'tcx, S: ExprState<'tcx>> SInto for rustc_middle::thir::Expr<'tcx> { fn sinto(&self, s: &S) -> Expr { let (hir_id, attributes) = self.hir_id_and_attributes(s); @@ -1435,12 +1470,14 @@ impl<'tcx, S: ExprState<'tcx>> SInto for rustc_middle::thir::Expr<'tcx> } } +#[cfg(feature = "rustc")] impl<'tcx, S: ExprState<'tcx>> SInto for rustc_middle::thir::ExprId { fn sinto(&self, s: &S) -> Expr { s.thir().exprs[*self].sinto(s) } } +#[cfg(feature = "rustc")] impl<'tcx, S: ExprState<'tcx>> SInto for rustc_middle::thir::Pat<'tcx> { fn sinto(&self, s: &S) -> Pat { let rustc_middle::thir::Pat { span, kind, ty } = self; @@ -1480,6 +1517,7 @@ impl<'tcx, S: ExprState<'tcx>> SInto for rustc_middle::thir::Pat<'tcx> { } } +#[cfg(feature = "rustc")] impl<'tcx, S: ExprState<'tcx>> SInto for rustc_middle::thir::ArmId { fn sinto(&self, s: &S) -> Arm { s.thir().arms[*self].sinto(s) @@ -1512,6 +1550,7 @@ pub enum FloatTy { F128, } +#[cfg(feature = "rustc")] impl<'tcx, S> SInto for rustc_ast::ast::FloatTy { fn sinto(&self, _: &S) -> FloatTy { use rustc_ast::ast::FloatTy as T; @@ -1524,6 +1563,7 @@ impl<'tcx, S> SInto for rustc_ast::ast::FloatTy { } } +#[cfg(feature = "rustc")] impl<'tcx, S> SInto for rustc_ast::ast::IntTy { fn sinto(&self, _: &S) -> IntTy { use rustc_ast::ast::IntTy as T; @@ -1537,6 +1577,7 @@ impl<'tcx, S> SInto for rustc_ast::ast::IntTy { } } } +#[cfg(feature = "rustc")] impl<'tcx, S> SInto for rustc_ast::ast::UintTy { fn sinto(&self, _: &S) -> UintTy { use rustc_ast::ast::UintTy as T; @@ -1603,6 +1644,7 @@ pub struct TypeAndMut { pub mutbl: Mutability, } +#[cfg(feature = "rustc")] impl> SInto> for rustc_middle::ty::List { fn sinto(&self, s: &S) -> Vec { self.iter().map(|x| x.sinto(s)).collect() @@ -1677,6 +1719,7 @@ pub enum AliasKind { Weak, } +#[cfg(feature = "rustc")] impl Alias { #[tracing::instrument(level = "trace", skip(s))] fn from<'tcx, S: BaseState<'tcx> + HasOwnerId>( @@ -1948,6 +1991,7 @@ pub struct ReprOptions { pub field_shuffle_seed: u64, } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::AdtDef<'tcx> { fn sinto(&self, s: &S) -> AdtDef { let variants = self @@ -2196,6 +2240,7 @@ pub enum LitKind { Err(ErrorGuaranteed), } +#[cfg(feature = "rustc")] impl SInto for rustc_data_structures::packed::Pu128 { fn sinto(&self, _s: &S) -> u128 { self.0 @@ -2287,6 +2332,7 @@ pub struct AttrItem { pub tokens: Option, } +#[cfg(feature = "rustc")] impl SInto for rustc_ast::tokenstream::LazyAttrTokenStream { fn sinto(&self, st: &S) -> String { self.to_attr_token_stream().to_tokenstream().sinto(st) @@ -2651,6 +2697,7 @@ pub enum ExprKind { Todo(String), } +#[cfg(feature = "rustc")] pub trait ExprKindExt<'tcx> { fn hir_id_and_attributes>( &self, @@ -2662,6 +2709,7 @@ pub trait ExprKindExt<'tcx> { ) -> rustc_middle::thir::Expr<'tcx>; } +#[cfg(feature = "rustc")] impl<'tcx> ExprKindExt<'tcx> for rustc_middle::thir::Expr<'tcx> { fn hir_id_and_attributes>( &self, @@ -2753,6 +2801,7 @@ pub struct FnHeader { pub type ThirBody = Expr; +#[cfg(feature = "rustc")] impl<'x: 'tcx, 'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_hir::Ty<'x> { fn sinto(self: &rustc_hir::Ty<'x>, s: &S) -> Ty { // **Important:** @@ -2843,6 +2892,7 @@ pub enum WherePredicate { EqPredicate(WhereEqPredicate), } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>, Body: IsBody> SInto> for rustc_hir::ImplItemRef { @@ -2996,6 +3046,7 @@ pub enum AssocItemKind { Type, } +#[cfg(feature = "rustc")] impl< 'tcx, S, @@ -3077,6 +3128,7 @@ pub enum VariantData { Unit(HirId, GlobalIdent), } +#[cfg(feature = "rustc")] impl SInto for rustc_ast::ast::Recovered { fn sinto(&self, _s: &S) -> bool { match self { @@ -3324,6 +3376,7 @@ pub struct TraitItem { pub attributes: ItemAttributes, } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>, Body: IsBody> SInto> for rustc_hir::EnumDef<'tcx> { @@ -3332,6 +3385,7 @@ impl<'tcx, S: UnderOwnerState<'tcx>, Body: IsBody> SInto> } } +#[cfg(feature = "rustc")] impl<'a, S: UnderOwnerState<'a>, Body: IsBody> SInto> for rustc_hir::TraitItemRef { @@ -3342,6 +3396,7 @@ impl<'a, S: UnderOwnerState<'a>, Body: IsBody> SInto> } } +#[cfg(feature = "rustc")] impl<'a, 'tcx, S: UnderOwnerState<'tcx>, Body: IsBody> SInto>> for rustc_hir::Mod<'a> { @@ -3377,6 +3432,7 @@ pub struct ForeignItem { pub vis_span: Span, } +#[cfg(feature = "rustc")] impl<'a, S: UnderOwnerState<'a>, Body: IsBody> SInto> for rustc_hir::ForeignItemRef { @@ -3457,6 +3513,7 @@ pub struct OutlivesPredicate { pub rhs: Region, } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>, T, U> SInto> for rustc_middle::ty::OutlivesPredicate<'tcx, T> where @@ -3483,6 +3540,7 @@ pub enum Term { Const(ConstantExpr), } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::Term<'tcx> { fn sinto(&self, s: &S) -> Term { use rustc_middle::ty::TermKind; @@ -3512,6 +3570,7 @@ pub struct ProjectionPredicate { pub ty: Ty, } +#[cfg(feature = "rustc")] impl<'tcx, S: BaseState<'tcx> + HasOwnerId> SInto for rustc_middle::ty::ProjectionPredicate<'tcx> { @@ -3563,6 +3622,7 @@ pub struct Clause { pub id: PredicateId, } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::Clause<'tcx> { fn sinto(&self, s: &S) -> Clause { Clause { @@ -3580,6 +3640,7 @@ pub struct Predicate { pub id: PredicateId, } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_middle::ty::Predicate<'tcx> { fn sinto(&self, s: &S) -> Predicate { Predicate { @@ -3620,6 +3681,7 @@ pub struct GenericPredicates { pub predicates: Vec<(Predicate, Span)>, } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>, T1, T2> SInto> for rustc_middle::ty::Binder<'tcx, T1> where @@ -3694,6 +3756,7 @@ pub enum PredicateKind { type GenericBounds = Vec; /// Compute the bounds for the owner registed in the state `s` +#[cfg(feature = "rustc")] fn region_bounds_at_current_owner<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> GenericBounds { let tcx = s.base().tcx; @@ -3735,6 +3798,7 @@ fn region_bounds_at_current_owner<'tcx, S: UnderOwnerState<'tcx>>(s: &S) -> Gene clauses.sinto(s) } +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_hir::GenericBounds<'tcx> { fn sinto(&self, s: &S) -> GenericBounds { region_bounds_at_current_owner(s) @@ -3775,6 +3839,7 @@ pub struct Item { pub expn_backtrace: Vec, } +#[cfg(feature = "rustc")] impl<'tcx, S: BaseState<'tcx>, Body: IsBody> SInto> for rustc_hir::Item<'tcx> { fn sinto(&self, s: &S) -> Item { let name: String = self.ident.name.to_ident_string(); @@ -3795,6 +3860,7 @@ impl<'tcx, S: BaseState<'tcx>, Body: IsBody> SInto> for rustc_hir: } } +#[cfg(feature = "rustc")] impl<'tcx, S: BaseState<'tcx>, Body: IsBody> SInto> for rustc_hir::ItemId { fn sinto(&self, s: &S) -> Item { let tcx: rustc_middle::ty::TyCtxt = s.base().tcx; @@ -3805,6 +3871,7 @@ impl<'tcx, S: BaseState<'tcx>, Body: IsBody> SInto> for rustc_hir: /// Reflects [`rustc_span::symbol::Ident`] pub type Ident = (Symbol, Span); +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx>> SInto for rustc_span::symbol::Ident { fn sinto(&self, s: &S) -> Ident { (self.name.sinto(s), self.span.sinto(s)) diff --git a/frontend/exporter/src/types/def_id.rs b/frontend/exporter/src/types/def_id.rs index 6be754d4b..cbb38a802 100644 --- a/frontend/exporter/src/types/def_id.rs +++ b/frontend/exporter/src/types/def_id.rs @@ -13,7 +13,10 @@ use hax_adt_into::derive_group; #[cfg(not(feature = "extract_names_mode"))] -use crate::{AdtInto, BaseState, JsonSchema, SInto}; +use crate::{AdtInto, JsonSchema}; + +#[cfg(all(not(feature = "extract_names_mode"), feature = "rustc"))] +use crate::{BaseState, SInto}; pub type Symbol = String; diff --git a/frontend/exporter/src/types/index.rs b/frontend/exporter/src/types/index.rs index 3ce6a3701..2a9c2cc18 100644 --- a/frontend/exporter/src/types/index.rs +++ b/frontend/exporter/src/types/index.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "rustc")] use crate::prelude::*; use crate::sinto_as_usize; diff --git a/frontend/exporter/src/types/mir.rs b/frontend/exporter/src/types/mir.rs index 0a5b6c5cc..75674304b 100644 --- a/frontend/exporter/src/types/mir.rs +++ b/frontend/exporter/src/types/mir.rs @@ -1,4 +1,5 @@ use crate::prelude::*; +#[cfg(feature = "rustc")] use tracing::trace; #[derive_group(Serializers)] @@ -38,6 +39,7 @@ pub enum ClearCrossCrate { Set(T), } +#[cfg(feature = "rustc")] impl> SInto> for rustc_middle::mir::ClearCrossCrate { @@ -68,6 +70,7 @@ pub enum AnalysisPhase { pub type BasicBlocks = IndexVec; +#[cfg(feature = "rustc")] fn name_of_local( local: rustc_middle::mir::Local, var_debug_info: &Vec, @@ -88,22 +91,30 @@ fn name_of_local( /// instead of an open list of types. pub mod mir_kinds { use crate::prelude::{derive_group, JsonSchema}; - use rustc_data_structures::steal::Steal; - use rustc_middle::mir::Body; - use rustc_middle::ty::TyCtxt; - use rustc_span::def_id::LocalDefId; - pub trait IsMirKind: Clone { - fn get_mir<'tcx>(tcx: TyCtxt<'tcx>, id: LocalDefId) -> &'tcx Steal>; - } #[derive_group(Serializers)] #[derive(Clone, Copy, Debug, JsonSchema)] pub struct Built; - impl IsMirKind for Built { - fn get_mir<'tcx>(tcx: TyCtxt<'tcx>, id: LocalDefId) -> &'tcx Steal> { - tcx.mir_built(id) + #[cfg(feature = "rustc")] + pub use rustc::*; + #[cfg(feature = "rustc")] + mod rustc { + use super::*; + use rustc_data_structures::steal::Steal; + use rustc_middle::mir::Body; + use rustc_middle::ty::TyCtxt; + use rustc_span::def_id::LocalDefId; + pub trait IsMirKind: Clone { + fn get_mir<'tcx>(tcx: TyCtxt<'tcx>, id: LocalDefId) -> &'tcx Steal>; + } + impl IsMirKind for Built { + fn get_mir<'tcx>(tcx: TyCtxt<'tcx>, id: LocalDefId) -> &'tcx Steal> { + tcx.mir_built(id) + } } } } + +#[cfg(feature = "rustc")] pub use mir_kinds::IsMirKind; #[derive_group(Serializers)] @@ -185,6 +196,7 @@ pub enum Operand { Constant(Constant), } +#[cfg(feature = "rustc")] impl Operand { pub(crate) fn ty(&self) -> &Ty { match self { @@ -202,6 +214,7 @@ pub struct Terminator { pub kind: TerminatorKind, } +#[cfg(feature = "rustc")] pub(crate) fn get_function_from_def_id_and_generics<'tcx, S: BaseState<'tcx> + HasOwnerId>( s: &S, def_id: rustc_hir::def_id::DefId, @@ -317,6 +330,7 @@ pub(crate) fn get_function_from_def_id_and_generics<'tcx, S: BaseState<'tcx> + H /// The [Operand] comes from a [TerminatorKind::Call]. /// Only supports calls to top-level functions (which are considered as constants /// by rustc); doesn't support closures for now. +#[cfg(feature = "rustc")] fn get_function_from_operand<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>( s: &S, func: &rustc_middle::mir::Operand<'tcx>, @@ -384,6 +398,7 @@ fn get_function_from_operand<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>>( } } +#[cfg(feature = "rustc")] fn translate_terminator_kind_call<'tcx, S: BaseState<'tcx> + HasMir<'tcx> + HasOwnerId>( s: &S, terminator: &rustc_middle::mir::TerminatorKind<'tcx>, @@ -435,6 +450,7 @@ pub struct ScalarInt { // TODO: naming conventions: is "translate" ok? /// Translate switch targets +#[cfg(feature = "rustc")] fn translate_switch_targets<'tcx, S: UnderOwnerState<'tcx>>( s: &S, switch_ty: &Ty, @@ -671,6 +687,7 @@ pub enum ProjectionElem { } // refactor +#[cfg(feature = "rustc")] impl<'tcx, S: UnderOwnerState<'tcx> + HasMir<'tcx>> SInto for rustc_middle::mir::Place<'tcx> { @@ -829,6 +846,7 @@ pub struct MirFnSig { pub type MirPolyFnSig = Binder; +#[cfg(feature = "rustc")] impl<'tcx, S: BaseState<'tcx> + HasOwnerId> SInto for rustc_middle::ty::FnSig<'tcx> { fn sinto(&self, s: &S) -> MirFnSig { let inputs = self.inputs().sinto(s); @@ -845,6 +863,7 @@ impl<'tcx, S: BaseState<'tcx> + HasOwnerId> SInto for rustc_middle: // TODO: we need this function because sometimes, Rust doesn't infer the proper // typeclass instance. +#[cfg(feature = "rustc")] pub(crate) fn poly_fn_sig_to_mir_poly_fn_sig<'tcx, S: BaseState<'tcx> + HasOwnerId>( sig: &rustc_middle::ty::PolyFnSig<'tcx>, s: &S, diff --git a/frontend/exporter/src/types/mod.rs b/frontend/exporter/src/types/mod.rs index dfd080a17..9a1acfa6a 100644 --- a/frontend/exporter/src/types/mod.rs +++ b/frontend/exporter/src/types/mod.rs @@ -5,6 +5,7 @@ mod copied; mod def_id; mod index; mod mir; +#[cfg(feature = "rustc")] mod mir_traits; mod new; mod replaced; @@ -15,6 +16,7 @@ pub use copied::*; pub use def_id::*; pub use index::*; pub use mir::*; +#[cfg(feature = "rustc")] pub use mir_traits::*; pub use new::*; pub use replaced::*; diff --git a/frontend/exporter/src/types/new/impl_infos.rs b/frontend/exporter/src/types/new/impl_infos.rs new file mode 100644 index 000000000..971184b45 --- /dev/null +++ b/frontend/exporter/src/types/new/impl_infos.rs @@ -0,0 +1,12 @@ +use crate::prelude::*; + +/// Meta-informations about an `impl TRAIT for +/// TYPE where PREDICATES {}` +#[derive_group(Serializers)] +#[derive(Clone, Debug, JsonSchema)] +pub struct ImplInfos { + pub generics: TyGenerics, + pub clauses: Vec<(Clause, Span)>, + pub typ: Ty, + pub trait_ref: Option, +} diff --git a/frontend/exporter/src/types/new/item_attributes.rs b/frontend/exporter/src/types/new/item_attributes.rs index e1352eae8..673e8b04f 100644 --- a/frontend/exporter/src/types/new/item_attributes.rs +++ b/frontend/exporter/src/types/new/item_attributes.rs @@ -16,11 +16,13 @@ impl ItemAttributes { } } +#[cfg(feature = "rustc")] lazy_static::lazy_static! { pub static ref CORE_EXTRACTION_MODE: bool = std::env::var_os("HAX_CORE_EXTRACTION_MODE") == Some("on".into()); } +#[cfg(feature = "rustc")] impl ItemAttributes { pub fn from_owner_id<'tcx, S: BaseState<'tcx>>( s: &S, diff --git a/frontend/exporter/src/types/new/mod.rs b/frontend/exporter/src/types/new/mod.rs index ca52e55ac..55925151c 100644 --- a/frontend/exporter/src/types/new/mod.rs +++ b/frontend/exporter/src/types/new/mod.rs @@ -1,10 +1,12 @@ //! This module contains type definitions that have no equivalent in //! Rustc. +mod impl_infos; mod item_attributes; mod predicate_id; mod typed_constant_kind; +pub use impl_infos::*; pub use item_attributes::*; pub use predicate_id::*; pub use typed_constant_kind::*; diff --git a/frontend/exporter/src/types/new/predicate_id.rs b/frontend/exporter/src/types/new/predicate_id.rs index fcaac8121..853a6ed0b 100644 --- a/frontend/exporter/src/types/new/predicate_id.rs +++ b/frontend/exporter/src/types/new/predicate_id.rs @@ -1,5 +1,4 @@ use crate::prelude::*; -use rustc_middle::ty; #[derive_group(Serializers)] #[derive(Copy, Clone, Debug, JsonSchema, Hash, PartialEq, Eq, PartialOrd, Ord)] @@ -9,56 +8,63 @@ use rustc_middle::ty; /// uniform and deterministic way. pub struct PredicateId(u64); -/// Implemented by anything that can be assimilated to a predicate. -pub trait IntoPredicateId<'tcx, S: UnderOwnerState<'tcx>> { - /// Compute a consistent `PredicateId` - fn predicate_id(&self, s: &S) -> PredicateId; -} +#[cfg(feature = "rustc")] +pub use self::rustc::*; +#[cfg(feature = "rustc")] +mod rustc { + use super::*; + use rustc_middle::ty; + /// Implemented by anything that can be assimilated to a predicate. + pub trait IntoPredicateId<'tcx, S: UnderOwnerState<'tcx>> { + /// Compute a consistent `PredicateId` + fn predicate_id(&self, s: &S) -> PredicateId; + } -impl<'tcx, S: UnderOwnerState<'tcx>> IntoPredicateId<'tcx, S> for ty::Clause<'tcx> { - fn predicate_id(&self, s: &S) -> PredicateId { - self.as_predicate().predicate_id(s) + impl<'tcx, S: UnderOwnerState<'tcx>> IntoPredicateId<'tcx, S> for ty::Clause<'tcx> { + fn predicate_id(&self, s: &S) -> PredicateId { + self.as_predicate().predicate_id(s) + } } -} -impl<'tcx, S: UnderOwnerState<'tcx>> IntoPredicateId<'tcx, S> for ty::Predicate<'tcx> { - fn predicate_id(&self, s: &S) -> PredicateId { - // Here, we need to be careful about not hashing a `crate::Predicate`, - // but `crate::Binder` instead, - // otherwise we would get into a infinite recursion. - let poly_kind: Binder = self.kind().sinto(s); - PredicateId(deterministic_hash(&poly_kind)) + impl<'tcx, S: UnderOwnerState<'tcx>> IntoPredicateId<'tcx, S> for ty::Predicate<'tcx> { + fn predicate_id(&self, s: &S) -> PredicateId { + // Here, we need to be careful about not hashing a `crate::Predicate`, + // but `crate::Binder` instead, + // otherwise we would get into a infinite recursion. + let poly_kind: Binder = self.kind().sinto(s); + PredicateId(deterministic_hash(&poly_kind)) + } } -} -impl<'tcx, S: UnderOwnerState<'tcx>> IntoPredicateId<'tcx, S> for ty::PolyTraitPredicate<'tcx> { - fn predicate_id(&self, s: &S) -> PredicateId { - use ty::Upcast; - let predicate: ty::Predicate<'tcx> = (*self).upcast(s.base().tcx); - predicate.predicate_id(s) + impl<'tcx, S: UnderOwnerState<'tcx>> IntoPredicateId<'tcx, S> for ty::PolyTraitPredicate<'tcx> { + fn predicate_id(&self, s: &S) -> PredicateId { + use ty::Upcast; + let predicate: ty::Predicate<'tcx> = (*self).upcast(s.base().tcx); + predicate.predicate_id(s) + } } -} -/// A `PredicateId` can be mapped to itself via SInto. This is useful -/// for mirroring the type [`traits::search_clause::PathChunk`] as -/// [`traits::ImplExprPathChunk`]. -impl<'tcx, S: UnderOwnerState<'tcx>> SInto for PredicateId { - fn sinto(&self, _s: &S) -> PredicateId { - *self + /// A `PredicateId` can be mapped to itself via SInto. This is useful + /// for mirroring the type [`traits::search_clause::PathChunk`] as + /// [`traits::ImplExprPathChunk`]. + impl<'tcx, S: UnderOwnerState<'tcx>> SInto for PredicateId { + fn sinto(&self, _s: &S) -> PredicateId { + *self + } } -} -/// We need identifiers that are stable across different -/// architectures, different paths (which are observable from -/// `Span`s), etc. -/// Rustc's stable hash is not doing what we want here: it is sensible -/// to the environment. Instead, we first `sinto` and then hash with -/// `deterministic_hash` below. -fn deterministic_hash(x: &T) -> u64 { - use crate::deterministic_hash::DeterministicHasher; - use std::collections::hash_map::DefaultHasher; - use std::hash::Hasher; - let mut hasher = DeterministicHasher::new(DefaultHasher::new()); - x.hash(&mut hasher); - hasher.finish() + /// We need identifiers that are stable across different + /// architectures, different paths (which are observable from + /// `Span`s), etc. + /// Rustc's stable hash is not doing what we want here: it is sensible + /// to the environment. Instead, we first `sinto` and then hash with + /// `deterministic_hash` below. + fn deterministic_hash(x: &T) -> u64 { + use crate::deterministic_hash::DeterministicHasher; + use std::collections::hash_map::DefaultHasher; + use std::hash::Hasher; + let mut hasher = DeterministicHasher::new(DefaultHasher::new()); + x.hash(&mut hasher); + hasher.finish() + } } diff --git a/frontend/exporter/src/types/new/typed_constant_kind.rs b/frontend/exporter/src/types/new/typed_constant_kind.rs index 837c63bf6..9658b9105 100644 --- a/frontend/exporter/src/types/new/typed_constant_kind.rs +++ b/frontend/exporter/src/types/new/typed_constant_kind.rs @@ -7,6 +7,7 @@ pub struct TypedConstantKind { pub constant_kind: ConstantExpr, } +#[cfg(feature = "rustc")] impl<'tcx, S: BaseState<'tcx> + HasOwnerId> SInto for rustc_middle::mir::Const<'tcx> { diff --git a/frontend/exporter/src/types/replaced.rs b/frontend/exporter/src/types/replaced.rs index 6af2e21af..fb4731238 100644 --- a/frontend/exporter/src/types/replaced.rs +++ b/frontend/exporter/src/types/replaced.rs @@ -1,19 +1,23 @@ -use crate::prelude::*; - pub type Path = Vec; +pub type Mutability = bool; + +#[cfg(feature = "rustc")] +mod rustc { + use super::*; + use crate::prelude::*; -impl<'t, S> SInto for rustc_span::symbol::Symbol { - fn sinto(&self, _s: &S) -> Symbol { - self.to_ident_string() + impl<'t, S> SInto for rustc_span::symbol::Symbol { + fn sinto(&self, _s: &S) -> Symbol { + self.to_ident_string() + } } -} -pub type Mutability = bool; -impl SInto for rustc_hir::Mutability { - fn sinto(&self, _s: &S) -> Mutability { - match self { - rustc_hir::Mutability::Mut => true, - _ => false, + impl SInto for rustc_hir::Mutability { + fn sinto(&self, _s: &S) -> Mutability { + match self { + rustc_hir::Mutability::Mut => true, + _ => false, + } } } } diff --git a/hax-types/Cargo.toml b/hax-types/Cargo.toml index 39d129e92..2a8b70995 100644 --- a/hax-types/Cargo.toml +++ b/hax-types/Cargo.toml @@ -22,3 +22,6 @@ annotate-snippets.workspace = true hax-adt-into.workspace = true bincode.workspace = true zstd = "0.13.1" + +[features] +rustc = ["hax-frontend-exporter/rustc"] diff --git a/hax-types/src/diagnostics/mod.rs b/hax-types/src/diagnostics/mod.rs index 8c65f5099..096c9a237 100644 --- a/hax-types/src/diagnostics/mod.rs +++ b/hax-types/src/diagnostics/mod.rs @@ -1,9 +1,3 @@ -extern crate rustc_driver; -extern crate rustc_error_messages; -extern crate rustc_errors; -extern crate rustc_session; -extern crate rustc_span; - use crate::prelude::*; use colored::Colorize; diff --git a/hax-types/src/lib.rs b/hax-types/src/lib.rs index 9c58a0b73..ab974d41b 100644 --- a/hax-types/src/lib.rs +++ b/hax-types/src/lib.rs @@ -6,8 +6,6 @@ //! Those three component send and receive messages in JSON or CBOR on //! stdin and stdout. -#![feature(rustc_private)] - pub(crate) mod prelude; /// The CLI options for `cargo-hax`. The types defines in this module From 875f0c51e44170112c00171da53c024b36029b67 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Thu, 4 Jul 2024 20:51:52 +0200 Subject: [PATCH 28/39] chore: fmt --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index db955f63d..5e17ffda4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,8 @@ members = [ "hax-lib-protocol-macros", "hax-bounded-integers", "engine/names", - "engine/names/extract", "hax-types", + "engine/names/extract", + "hax-types", ] exclude = ["tests"] default-members = [ From e5dac02ef8dffe1179c319f70b1e77745c54a88a Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Thu, 4 Jul 2024 20:57:30 +0200 Subject: [PATCH 29/39] fix: kill dependency `const_format` --- Cargo.lock | 28 ---------------------------- cli/driver/Cargo.toml | 1 - cli/driver/src/driver.rs | 5 ++--- cli/subcommands/Cargo.toml | 1 - cli/subcommands/src/cargo_hax.rs | 5 +---- 5 files changed, 3 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c2a963053..fc3e2cff3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -162,7 +162,6 @@ dependencies = [ "cargo_metadata", "clap", "colored", - "const_format", "hax-frontend-exporter", "hax-frontend-exporter-options", "hax-lib-macros-types", @@ -301,26 +300,6 @@ dependencies = [ "windows-sys 0.45.0", ] -[[package]] -name = "const_format" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" -dependencies = [ - "const_format_proc_macros", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - [[package]] name = "crossterm" version = "0.25.0" @@ -502,7 +481,6 @@ version = "0.1.0-pre.1" dependencies = [ "clap", "colored", - "const_format", "hax-frontend-exporter", "hax-frontend-exporter-options", "hax-lib-macros-types", @@ -1597,12 +1575,6 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - [[package]] name = "utf8parse" version = "0.2.1" diff --git a/cli/driver/Cargo.toml b/cli/driver/Cargo.toml index 52e558ad6..9629f3278 100644 --- a/cli/driver/Cargo.toml +++ b/cli/driver/Cargo.toml @@ -27,7 +27,6 @@ hax-frontend-exporter-options.workspace = true hax-lib-macros-types.workspace = true itertools.workspace = true which.workspace = true -const_format = "0.2" tracing.workspace = true tracing-subscriber.workspace = true tracing-tree.workspace = true diff --git a/cli/driver/src/driver.rs b/cli/driver/src/driver.rs index e576e7bc3..66911e338 100644 --- a/cli/driver/src/driver.rs +++ b/cli/driver/src/driver.rs @@ -36,7 +36,6 @@ mod features; use callbacks_wrapper::*; use features::*; -use const_format::formatcp; use hax_types::cli_options::{BackendOptions, Command, ENV_VAR_OPTIONS_FRONTEND}; use rustc_driver::{Callbacks, Compilation}; @@ -80,11 +79,11 @@ fn main() { setup_logging(); let options: hax_types::cli_options::Options = - serde_json::from_str(&std::env::var(ENV_VAR_OPTIONS_FRONTEND).expect(&formatcp!( + serde_json::from_str(&std::env::var(ENV_VAR_OPTIONS_FRONTEND).expect(&format!( "Cannot find environnement variable {}", ENV_VAR_OPTIONS_FRONTEND ))) - .expect(&formatcp!( + .expect(&format!( "Invalid value for the environnement variable {}", ENV_VAR_OPTIONS_FRONTEND )); diff --git a/cli/subcommands/Cargo.toml b/cli/subcommands/Cargo.toml index e0e026f9f..01cb5f729 100644 --- a/cli/subcommands/Cargo.toml +++ b/cli/subcommands/Cargo.toml @@ -37,7 +37,6 @@ colored.workspace = true is-terminal = "0.4.9" hax-phase-debug-webapp.workspace = true inquire = "0.6" -const_format = "0.2" annotate-snippets.workspace = true serde-jsonlines = "0.5.0" prettyplease = "0.2.20" diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index 940253e25..22025712b 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -74,10 +74,7 @@ fn rustflags() -> String { } const ENGINE_BINARY_NAME: &str = "hax-engine"; -const ENGINE_BINARY_NOT_FOUND: &str = const_format::formatcp!( - "The binary [{}] was not found in your [PATH].", - ENGINE_BINARY_NAME, -); +const ENGINE_BINARY_NOT_FOUND: &str = "The binary [hax-engine] was not found in your [PATH]."; /// Dynamically looks for binary [ENGINE_BINARY_NAME]. First, we /// check whether [HAX_ENGINE_BINARY] is set, and use that if it From 53bac37d0b7317018a5c8e6be6679d067cfa9c11 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Thu, 4 Jul 2024 21:00:35 +0200 Subject: [PATCH 30/39] fix: kill dependency `camino` --- Cargo.lock | 2 -- cli/subcommands/Cargo.toml | 1 - cli/subcommands/src/cargo_hax.rs | 4 ++-- engine/names/extract/Cargo.toml | 1 - 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc3e2cff3..5e09cfee6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -158,7 +158,6 @@ name = "cargo-hax" version = "0.1.0-pre.1" dependencies = [ "annotate-snippets", - "camino", "cargo_metadata", "clap", "colored", @@ -508,7 +507,6 @@ name = "hax-engine-names-extract" version = "0.1.0-pre.1" dependencies = [ "bincode", - "camino", "hax-adt-into", "hax-engine-names", "serde", diff --git a/cli/subcommands/Cargo.toml b/cli/subcommands/Cargo.toml index 01cb5f729..93b44cb86 100644 --- a/cli/subcommands/Cargo.toml +++ b/cli/subcommands/Cargo.toml @@ -42,7 +42,6 @@ serde-jsonlines = "0.5.0" prettyplease = "0.2.20" syn = { version = "2.*", features = ["full"] } cargo_metadata.workspace = true -camino = "1.1" [build-dependencies] serde.workspace = true diff --git a/cli/subcommands/src/cargo_hax.rs b/cli/subcommands/src/cargo_hax.rs index 22025712b..4d72a3183 100644 --- a/cli/subcommands/src/cargo_hax.rs +++ b/cli/subcommands/src/cargo_hax.rs @@ -280,11 +280,11 @@ fn run_engine( } /// Uses `cargo metadata` to compute a derived target directory. -fn target_dir(suffix: &str) -> camino::Utf8PathBuf { +fn target_dir(suffix: &str) -> PathBuf { let metadata = cargo_metadata::MetadataCommand::new().exec().unwrap(); let mut dir = metadata.target_directory; dir.push(suffix); - dir + dir.into() } /// Calls `cargo` with a custom driver which computes `haxmeta` files diff --git a/engine/names/extract/Cargo.toml b/engine/names/extract/Cargo.toml index d0d0082eb..61218733d 100644 --- a/engine/names/extract/Cargo.toml +++ b/engine/names/extract/Cargo.toml @@ -16,7 +16,6 @@ serde_json.workspace = true hax-engine-names.workspace = true hax-adt-into.workspace = true tempfile.version = "3.9" -camino = "1.1" bincode.workspace = true [features] From de5d8d0266100e6b3237204448b7ec59aacbc146 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Thu, 4 Jul 2024 21:04:21 +0200 Subject: [PATCH 31/39] fix: fmt docstring --- frontend/exporter/adt-into/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/frontend/exporter/adt-into/src/lib.rs b/frontend/exporter/adt-into/src/lib.rs index 3e9165b53..2d0a115f5 100644 --- a/frontend/exporter/adt-into/src/lib.rs +++ b/frontend/exporter/adt-into/src/lib.rs @@ -439,7 +439,14 @@ fn drop_generics(type_path: syn::TypePath) -> syn::TypePath { } } -/// A proc macro unrelated to `adt-into`. This is useful in hax and we don't want a whole crate only for that helper. This proc macro defines some groups of derive clauses that we reuse all the time. This is particularly interesting for serializers and deserializers: today we use `bincode` and `serde`, but maybe we will want to move to something else in the future. +/// A proc macro unrelated to `adt-into`: it is useful in hax +/// and we don't want a whole crate only for that helper. +/// +/// This proc macro defines some groups of derive clauses that +/// we reuse all the time. This is particularly interesting for +/// serializers and deserializers: today we use `bincode` and +/// `serde`, but maybe we will want to move to something else +/// in the future. #[proc_macro_attribute] pub fn derive_group( attr: proc_macro::TokenStream, From fda471fe5fd5d1caf5419ab8cd1db0f02f1c434d Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Thu, 4 Jul 2024 21:07:52 +0200 Subject: [PATCH 32/39] feat: add doc for bincode manual impls --- frontend/exporter/src/types/copied.rs | 69 ++++++++++++++------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/frontend/exporter/src/types/copied.rs b/frontend/exporter/src/types/copied.rs index 12718f29e..cd59646c7 100644 --- a/frontend/exporter/src/types/copied.rs +++ b/frontend/exporter/src/types/copied.rs @@ -877,43 +877,48 @@ pub struct Span { // expn_backtrace: Vec, } -impl bincode::Encode for Span { - fn encode( - &self, - encoder: &mut E, - ) -> core::result::Result<(), bincode::error::EncodeError> { - bincode::Encode::encode(&self.lo, encoder)?; - bincode::Encode::encode(&self.hi, encoder)?; - bincode::Encode::encode(&self.filename, encoder)?; - Ok(()) +/// We need to define manual `impl`s of `Span`: we want to skip the +/// field `rust_span_data`. The derive macros from `bincode` don't +/// allow that, see https://github.com/bincode-org/bincode/issues/452. +const _: () = { + impl bincode::Encode for Span { + fn encode( + &self, + encoder: &mut E, + ) -> core::result::Result<(), bincode::error::EncodeError> { + bincode::Encode::encode(&self.lo, encoder)?; + bincode::Encode::encode(&self.hi, encoder)?; + bincode::Encode::encode(&self.filename, encoder)?; + Ok(()) + } } -} -impl bincode::Decode for Span { - fn decode( - decoder: &mut D, - ) -> core::result::Result { - Ok(Self { - lo: bincode::Decode::decode(decoder)?, - hi: bincode::Decode::decode(decoder)?, - filename: bincode::Decode::decode(decoder)?, - rust_span_data: None, - }) + impl bincode::Decode for Span { + fn decode( + decoder: &mut D, + ) -> core::result::Result { + Ok(Self { + lo: bincode::Decode::decode(decoder)?, + hi: bincode::Decode::decode(decoder)?, + filename: bincode::Decode::decode(decoder)?, + rust_span_data: None, + }) + } } -} -impl<'de> bincode::BorrowDecode<'de> for Span { - fn borrow_decode>( - decoder: &mut D, - ) -> core::result::Result { - Ok(Self { - lo: bincode::BorrowDecode::borrow_decode(decoder)?, - hi: bincode::BorrowDecode::borrow_decode(decoder)?, - filename: bincode::BorrowDecode::borrow_decode(decoder)?, - rust_span_data: None, - }) + impl<'de> bincode::BorrowDecode<'de> for Span { + fn borrow_decode>( + decoder: &mut D, + ) -> core::result::Result { + Ok(Self { + lo: bincode::BorrowDecode::borrow_decode(decoder)?, + hi: bincode::BorrowDecode::borrow_decode(decoder)?, + filename: bincode::BorrowDecode::borrow_decode(decoder)?, + rust_span_data: None, + }) + } } -} +}; const _: () = { // `rust_span_data` is a metadata that should *not* be taken into From 9175de26d38e1e9bc86f067861600374b2016536 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Thu, 4 Jul 2024 21:10:45 +0200 Subject: [PATCH 33/39] feat: add doc to serialize_int --- frontend/exporter/src/types/serialize_int.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/exporter/src/types/serialize_int.rs b/frontend/exporter/src/types/serialize_int.rs index a026f7148..3d020ea3e 100644 --- a/frontend/exporter/src/types/serialize_int.rs +++ b/frontend/exporter/src/types/serialize_int.rs @@ -1,3 +1,7 @@ +//! This module provides serde manual serializes/deserializers as +//! strings for u128 and i128: those types are not well supported in +//! serde (see https://github.com/serde-rs/json/issues/625). + use serde::{de::Visitor, ser::Serialize, Deserializer, Serializer}; pub mod unsigned { From 2a19f42ab0b070caa043687ce0082711d332a7e7 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Thu, 4 Jul 2024 21:12:41 +0200 Subject: [PATCH 34/39] remove TODO: the bound is needed because of `sinto` --- frontend/exporter/src/index_vec.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/frontend/exporter/src/index_vec.rs b/frontend/exporter/src/index_vec.rs index 2fb4ad9e4..950af531c 100644 --- a/frontend/exporter/src/index_vec.rs +++ b/frontend/exporter/src/index_vec.rs @@ -45,13 +45,8 @@ impl Into> for rustc_index::IndexVec, - U: Clone, /*TODO: remove me?*/ - T: SInto, - > SInto> for rustc_index::IndexSlice +impl, U: Clone, T: SInto> + SInto> for rustc_index::IndexSlice { fn sinto(&self, s: &S) -> IndexVec { IndexVec { From be6f628bbd95bf45d7ea45d58d4905f5c5585a8a Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Thu, 4 Jul 2024 21:14:48 +0200 Subject: [PATCH 35/39] feat: add doc to `extern crate` items --- frontend/exporter/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/exporter/src/lib.rs b/frontend/exporter/src/lib.rs index 89ce6c68b..4c6576480 100644 --- a/frontend/exporter/src/lib.rs +++ b/frontend/exporter/src/lib.rs @@ -11,6 +11,10 @@ cfg_if::cfg_if! { if #[cfg(feature = "rustc")] { + // When the feature `rustc` is enabled, we enable the bridges + // between rustc ASTs, which are defined in the crates + // `rustc_*`. We thus need to import them with `extern crate + // rustc_*` extern crate rustc_abi; extern crate rustc_ast; extern crate rustc_ast_pretty; From ce7b6bb0e6b21aecf648e5a8dcb5b7e52b1962bd Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Fri, 5 Jul 2024 16:27:31 +0200 Subject: [PATCH 36/39] fix: kill more dependencies --- Cargo.lock | 3 --- cli/driver/Cargo.toml | 1 - engine/names/Cargo.toml | 1 - frontend/exporter/Cargo.toml | 1 - 4 files changed, 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e09cfee6..41873af81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -490,14 +490,12 @@ dependencies = [ "tracing", "tracing-subscriber", "tracing-tree", - "which", ] [[package]] name = "hax-engine-names" version = "0.1.0-pre.1" dependencies = [ - "bincode", "hax-lib", "hax-lib-protocol", ] @@ -519,7 +517,6 @@ name = "hax-frontend-exporter" version = "0.1.0-pre.1" dependencies = [ "bincode", - "cfg-if", "extension-traits", "hax-adt-into", "hax-frontend-exporter-options", diff --git a/cli/driver/Cargo.toml b/cli/driver/Cargo.toml index 9629f3278..097f0911a 100644 --- a/cli/driver/Cargo.toml +++ b/cli/driver/Cargo.toml @@ -26,7 +26,6 @@ hax-types = {workspace = true, features = ["rustc"]} hax-frontend-exporter-options.workspace = true hax-lib-macros-types.workspace = true itertools.workspace = true -which.workspace = true tracing.workspace = true tracing-subscriber.workspace = true tracing-tree.workspace = true diff --git a/engine/names/Cargo.toml b/engine/names/Cargo.toml index d69cdd941..efc92fca6 100644 --- a/engine/names/Cargo.toml +++ b/engine/names/Cargo.toml @@ -12,4 +12,3 @@ description = "Dummy crate containing all the Rust names the hax engine should b [dependencies] hax-lib-protocol = {path = "../../hax-lib-protocol"} hax-lib = {path = "../../hax-lib"} -bincode.workspace = true diff --git a/frontend/exporter/Cargo.toml b/frontend/exporter/Cargo.toml index ed6f3ade0..a9ed2b247 100644 --- a/frontend/exporter/Cargo.toml +++ b/frontend/exporter/Cargo.toml @@ -24,7 +24,6 @@ paste = "1.0.11" extension-traits = "1.0.1" lazy_static = "1.4.0" bincode.workspace = true -cfg-if = "1.0.0" [features] default = ["rustc"] From 0d59b0b2435244ab338213810f9761c92bfd60dc Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Fri, 5 Jul 2024 16:28:19 +0200 Subject: [PATCH 37/39] remove `cfg_if` --- frontend/exporter/src/lib.rs | 65 ++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/frontend/exporter/src/lib.rs b/frontend/exporter/src/lib.rs index 4c6576480..9d8f82a61 100644 --- a/frontend/exporter/src/lib.rs +++ b/frontend/exporter/src/lib.rs @@ -9,38 +9,45 @@ #![allow(rustdoc::private_intra_doc_links)] #![cfg_attr(feature = "rustc", feature(rustc_private))] -cfg_if::cfg_if! { - if #[cfg(feature = "rustc")] { - // When the feature `rustc` is enabled, we enable the bridges - // between rustc ASTs, which are defined in the crates - // `rustc_*`. We thus need to import them with `extern crate - // rustc_*` - extern crate rustc_abi; - extern crate rustc_ast; - extern crate rustc_ast_pretty; - extern crate rustc_data_structures; - extern crate rustc_driver; - extern crate rustc_errors; - extern crate rustc_hir; - extern crate rustc_hir_analysis; - extern crate rustc_index; - extern crate rustc_infer; - extern crate rustc_interface; - extern crate rustc_middle; - extern crate rustc_mir_build; - extern crate rustc_session; - extern crate rustc_span; - extern crate rustc_target; - extern crate rustc_trait_selection; - extern crate rustc_type_ir; - - mod rustc_utils; - pub mod state; - mod utils; - mod deterministic_hash; +macro_rules! cfg_feature_rustc { + ($($item:item)*) => { + $( + #[cfg(feature = "rustc")] + $item + )* } } +cfg_feature_rustc! { + // When the feature `rustc` is enabled, we enable the bridges + // between rustc ASTs, which are defined in the crates + // `rustc_*`. We thus need to import them with `extern crate + // rustc_*` + extern crate rustc_abi; + extern crate rustc_ast; + extern crate rustc_ast_pretty; + extern crate rustc_data_structures; + extern crate rustc_driver; + extern crate rustc_errors; + extern crate rustc_hir; + extern crate rustc_hir_analysis; + extern crate rustc_index; + extern crate rustc_infer; + extern crate rustc_interface; + extern crate rustc_middle; + extern crate rustc_mir_build; + extern crate rustc_session; + extern crate rustc_span; + extern crate rustc_target; + extern crate rustc_trait_selection; + extern crate rustc_type_ir; + + mod rustc_utils; + pub mod state; + mod utils; + mod deterministic_hash; +} + mod body; mod constant_utils; mod types; From e6ac47d7ae9befab76922244b746ab0394c5fffd Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Fri, 5 Jul 2024 16:31:02 +0200 Subject: [PATCH 38/39] feat: init dependabot --- dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 dependabot.yml diff --git a/dependabot.yml b/dependabot.yml new file mode 100644 index 000000000..304f54aa1 --- /dev/null +++ b/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: +- package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "weekly" From 43ab211faeb0a6ea1d043a07d0c2e06e9eeee987 Mon Sep 17 00:00:00 2001 From: Lucas Franceschino Date: Fri, 5 Jul 2024 17:03:53 +0200 Subject: [PATCH 39/39] more precise unexpected_cfgs --- engine/names/extract/Cargo.toml | 3 +++ engine/names/extract/build.rs | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/engine/names/extract/Cargo.toml b/engine/names/extract/Cargo.toml index 61218733d..c6f9dacb6 100644 --- a/engine/names/extract/Cargo.toml +++ b/engine/names/extract/Cargo.toml @@ -21,3 +21,6 @@ bincode.workspace = true [features] default = ["extract_names_mode"] extract_names_mode = [] + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(feature, values("rustc"))'] } diff --git a/engine/names/extract/build.rs b/engine/names/extract/build.rs index 7cc11cc77..47e7fbc51 100644 --- a/engine/names/extract/build.rs +++ b/engine/names/extract/build.rs @@ -6,7 +6,6 @@ use std::process::{Command, Stdio}; /// impls), we just inline a small module here that contains the three /// type definition we need. See the module for complementary /// informations. -#[allow(unexpected_cfgs)] #[path = "../../../frontend/exporter/src/types/def_id.rs"] mod hax_frontend_exporter_def_id; use hax_frontend_exporter_def_id::*;