diff --git a/mk/crates.mk b/mk/crates.mk index f47c4857ef861..3021727cb109f 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -106,7 +106,7 @@ DEPS_rustc_passes := syntax rustc core rustc_front DEPS_rustc_mir := rustc rustc_front syntax DEPS_rustc_resolve := arena rustc rustc_front log syntax DEPS_rustc_platform_intrinsics := rustc rustc_llvm -DEPS_rustc_plugin := rustc rustc_metadata syntax +DEPS_rustc_plugin := rustc rustc_metadata syntax rustc_mir DEPS_rustc_privacy := rustc rustc_front log syntax DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back rustc_mir \ log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index f88034d142a1f..53fd867e7fd48 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -126,6 +126,8 @@ pub mod mir { pub mod repr; pub mod tcx; pub mod visit; + pub mod transform; + pub mod mir_map; } pub mod session; diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 8355154ad21a5..1e21d6aabe97b 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -29,6 +29,7 @@ use middle::lang_items; use middle::ty::{self, Ty, VariantKind}; use middle::def_id::{DefId, DefIndex}; use mir::repr::Mir; +use mir::mir_map::MirMap; use session::Session; use session::search_paths::PathKind; use util::nodemap::{FnvHashMap, NodeMap, NodeSet}; @@ -244,7 +245,7 @@ pub trait CrateStore<'tcx> : Any { item_symbols: &RefCell>, link_meta: &LinkMeta, reachable: &NodeSet, - mir_map: &NodeMap>, + mir_map: &MirMap<'tcx>, krate: &hir::Crate) -> Vec; fn metadata_encoding_version(&self) -> &[u8]; } @@ -428,7 +429,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { item_symbols: &RefCell>, link_meta: &LinkMeta, reachable: &NodeSet, - mir_map: &NodeMap>, + mir_map: &MirMap<'tcx>, krate: &hir::Crate) -> Vec { vec![] } fn metadata_encoding_version(&self) -> &[u8] { unimplemented!() } } diff --git a/src/librustc/mir/mir_map.rs b/src/librustc/mir/mir_map.rs new file mode 100644 index 0000000000000..aa24f6d897969 --- /dev/null +++ b/src/librustc/mir/mir_map.rs @@ -0,0 +1,28 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use util::nodemap::NodeMap; +use mir::repr::Mir; +use mir::transform::MirPass; +use middle::ty; + +pub struct MirMap<'tcx> { + pub map: NodeMap>, +} + +impl<'tcx> MirMap<'tcx> { + pub fn run_passes(&mut self, passes: &mut [Box], tcx: &ty::ctxt<'tcx>) { + for (_, ref mut mir) in &mut self.map { + for pass in &mut *passes { + pass.run_on_mir(mir, tcx) + } + } + } +} diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs new file mode 100644 index 0000000000000..0f18d8d282144 --- /dev/null +++ b/src/librustc/mir/transform.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use mir::repr::Mir; +use middle::ty::ctxt; + +pub trait MirPass { + fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, tcx: &ctxt<'tcx>); +} diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index f0c7182594240..d2f8d3f09fd7c 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -13,6 +13,7 @@ use middle::cstore::CrateStore; use middle::dependency_format; use session::search_paths::PathKind; use util::nodemap::{NodeMap, FnvHashMap}; +use mir::transform::MirPass; use syntax::ast::{NodeId, NodeIdAssigner, Name}; use syntax::codemap::{Span, MultiSpan}; @@ -59,6 +60,7 @@ pub struct Session { pub lint_store: RefCell, pub lints: RefCell>>, pub plugin_llvm_passes: RefCell>, + pub plugin_mir_passes: RefCell>>, pub plugin_attributes: RefCell>, pub crate_types: RefCell>, pub dependency_formats: RefCell, @@ -475,6 +477,7 @@ pub fn build_session_(sopts: config::Options, lint_store: RefCell::new(lint::LintStore::new()), lints: RefCell::new(NodeMap()), plugin_llvm_passes: RefCell::new(Vec::new()), + plugin_mir_passes: RefCell::new(Vec::new()), plugin_attributes: RefCell::new(Vec::new()), crate_types: RefCell::new(Vec::new()), dependency_formats: RefCell::new(FnvHashMap()), diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index e506639932324..6c5b577e0d1a4 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -12,7 +12,7 @@ use rustc::dep_graph::DepGraph; use rustc::front; use rustc::front::map as hir_map; use rustc_mir as mir; -use rustc_mir::mir_map::MirMap; +use rustc::mir::mir_map::MirMap; use rustc::session::{Session, CompileResult, compile_result_from_err_count}; use rustc::session::config::{self, Input, OutputFilenames, OutputType}; use rustc::session::search_paths::PathKind; @@ -545,7 +545,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, }); let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups, - llvm_passes, attributes, .. } = registry; + llvm_passes, attributes, mir_passes, .. } = registry; try!(sess.track_errors(|| { let mut ls = sess.lint_store.borrow_mut(); @@ -561,6 +561,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, } *sess.plugin_llvm_passes.borrow_mut() = llvm_passes; + *sess.plugin_mir_passes.borrow_mut() = mir_passes; *sess.plugin_attributes.borrow_mut() = attributes.clone(); })); @@ -843,11 +844,15 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, "match checking", || middle::check_match::check_crate(tcx)); - let mir_map = + let mut mir_map = time(time_passes, "MIR dump", || mir::mir_map::build_mir_for_crate(tcx)); + time(time_passes, + "MIR passes", + || mir_map.run_passes(&mut sess.plugin_mir_passes.borrow_mut(), tcx)); + time(time_passes, "liveness checking", || middle::liveness::check_crate(tcx)); diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index bc52921e1b8ca..06a2727ea28ae 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -23,6 +23,7 @@ use middle::def_id::{DefId, DefIndex}; use rustc::front::map as hir_map; use rustc::mir::repr::Mir; +use rustc::mir::mir_map::MirMap; use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet}; use std::cell::RefCell; @@ -502,7 +503,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { item_symbols: &RefCell>, link_meta: &LinkMeta, reachable: &NodeSet, - mir_map: &NodeMap>, + mir_map: &MirMap<'tcx>, krate: &hir::Crate) -> Vec { let encode_inlined_item: encoder::EncodeInlinedItem = diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 8df72016078e6..50030ced0abb5 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -30,7 +30,7 @@ use middle::ty::{self, Ty}; use rustc::back::svh::Svh; use rustc::front::map::{LinkedPath, PathElem, PathElems}; use rustc::front::map as ast_map; -use rustc::mir::repr::Mir; +use rustc::mir::mir_map::MirMap; use rustc::session::config; use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet}; @@ -66,7 +66,7 @@ pub struct EncodeParams<'a, 'tcx: 'a> { pub cstore: &'a cstore::CStore, pub encode_inlined_item: EncodeInlinedItem<'a>, pub reachable: &'a NodeSet, - pub mir_map: &'a NodeMap>, + pub mir_map: &'a MirMap<'tcx>, } pub struct EncodeContext<'a, 'tcx: 'a> { @@ -79,7 +79,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> { pub encode_inlined_item: RefCell>, pub type_abbrevs: tyencode::abbrev_map<'tcx>, pub reachable: &'a NodeSet, - pub mir_map: &'a NodeMap>, + pub mir_map: &'a MirMap<'tcx>, } impl<'a, 'tcx> EncodeContext<'a,'tcx> { @@ -824,7 +824,7 @@ fn encode_inlined_item(ecx: &EncodeContext, } fn encode_mir(ecx: &EncodeContext, rbml_w: &mut Encoder, node_id: NodeId) { - if let Some(mir) = ecx.mir_map.get(&node_id) { + if let Some(mir) = ecx.mir_map.map.get(&node_id) { rbml_w.start_tag(tag_mir as usize); rbml_w.emit_opaque(|opaque_encoder| { tls::enter_encoding_context(ecx, opaque_encoder, |_, opaque_encoder| { @@ -1447,7 +1447,7 @@ fn my_visit_expr(expr: &hir::Expr, ecx.tcx.map.with_path(expr.id, |path| encode_path(rbml_w, path)); - assert!(ecx.mir_map.contains_key(&expr.id)); + assert!(ecx.mir_map.map.contains_key(&expr.id)); encode_mir(ecx, rbml_w, expr.id); rbml_w.end_tag(); diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 7d4b0288a038f..0e641bf679d11 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -17,33 +17,34 @@ //! - `#[rustc_mir(pretty="file.mir")]` extern crate syntax; -extern crate rustc; extern crate rustc_front; use build; use graphviz; use pretty; -use transform::{simplify_cfg, MirPass}; +use transform::simplify_cfg; use rustc::dep_graph::DepNode; use rustc::mir::repr::Mir; use hair::cx::Cx; use std::fs::File; -use self::rustc::middle::infer; -use self::rustc::middle::region::CodeExtentData; -use self::rustc::middle::ty::{self, Ty}; -use self::rustc::util::common::ErrorReported; -use self::rustc::util::nodemap::NodeMap; -use self::rustc_front::hir; -use self::rustc_front::intravisit::{self, Visitor}; -use self::syntax::ast; -use self::syntax::attr::AttrMetaMethods; -use self::syntax::codemap::Span; - -pub type MirMap<'tcx> = NodeMap>; +use rustc::mir::transform::MirPass; +use rustc::mir::mir_map::MirMap; +use rustc::middle::infer; +use rustc::middle::region::CodeExtentData; +use rustc::middle::ty::{self, Ty}; +use rustc::util::common::ErrorReported; +use rustc::util::nodemap::NodeMap; +use rustc_front::hir; +use rustc_front::intravisit::{self, Visitor}; +use syntax::ast; +use syntax::attr::AttrMetaMethods; +use syntax::codemap::Span; pub fn build_mir_for_crate<'tcx>(tcx: &ty::ctxt<'tcx>) -> MirMap<'tcx> { - let mut map = NodeMap(); + let mut map = MirMap { + map: NodeMap(), + }; { let mut dump = OuterDump { tcx: tcx, @@ -147,7 +148,7 @@ impl<'a, 'm, 'tcx> Visitor<'tcx> for InnerDump<'a,'m,'tcx> { match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) { Ok(mut mir) => { - simplify_cfg::SimplifyCfg::new().run_on_mir(&mut mir); + simplify_cfg::SimplifyCfg::new().run_on_mir(&mut mir, self.tcx); let meta_item_list = self.attr .iter() @@ -182,7 +183,7 @@ impl<'a, 'm, 'tcx> Visitor<'tcx> for InnerDump<'a,'m,'tcx> { } } - let previous = self.map.insert(id, mir); + let previous = self.map.map.insert(id, mir); assert!(previous.is_none()); } Err(ErrorReported) => {} diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index d851daffe89dd..b927ab489f100 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -15,24 +15,26 @@ use rustc::middle::ty; use rustc::mir::repr::*; use rustc::mir::visit::MutVisitor; -use mir_map::MirMap; -use transform::MirPass; +use rustc::mir::mir_map::MirMap; +use rustc::mir::transform::MirPass; pub fn erase_regions<'tcx>(tcx: &ty::ctxt<'tcx>, mir_map: &mut MirMap<'tcx>) { - let mut eraser = EraseRegions::new(tcx); + let mut eraser = EraseRegions; - for mir in mir_map.iter_mut().map(|(_, v)| v) { - eraser.run_on_mir(mir); + for (_, mir) in &mut mir_map.map { + eraser.run_on_mir(mir, tcx); } } -pub struct EraseRegions<'a, 'tcx: 'a> { +pub struct EraseRegions; + +struct EraseRegionsVisitor<'a, 'tcx: 'a> { tcx: &'a ty::ctxt<'tcx>, } -impl<'a, 'tcx> EraseRegions<'a, 'tcx> { - pub fn new(tcx: &'a ty::ctxt<'tcx>) -> EraseRegions<'a, 'tcx> { - EraseRegions { +impl<'a, 'tcx> EraseRegionsVisitor<'a, 'tcx> { + pub fn new(tcx: &'a ty::ctxt<'tcx>) -> Self { + EraseRegionsVisitor { tcx: tcx } } @@ -56,13 +58,13 @@ impl<'a, 'tcx> EraseRegions<'a, 'tcx> { } } -impl<'a, 'tcx> MirPass<'tcx> for EraseRegions<'a, 'tcx> { - fn run_on_mir(&mut self, mir: &mut Mir<'tcx>) { - self.visit_mir(mir); +impl MirPass for EraseRegions { + fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, tcx: &ty::ctxt<'tcx>) { + EraseRegionsVisitor::new(tcx).visit_mir(mir); } } -impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegions<'a, 'tcx> { +impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> { fn visit_mir(&mut self, mir: &mut Mir<'tcx>) { self.erase_regions_return_ty(&mut mir.return_ty); self.erase_regions_tys(mir.var_decls.iter_mut().map(|d| &mut d.ty)); diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 174718f7b1672..41ea4469734f7 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -11,9 +11,3 @@ pub mod simplify_cfg; pub mod erase_regions; mod util; - -use rustc::mir::repr::Mir; - -pub trait MirPass<'tcx> { - fn run_on_mir(&mut self, mir: &mut Mir<'tcx>); -} diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs index 9d4c73b90f81a..17c5b5f7c3cff 100644 --- a/src/librustc_mir/transform/simplify_cfg.rs +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -11,7 +11,7 @@ use rustc::middle::const_eval::ConstVal; use rustc::mir::repr::*; use transform::util; -use transform::MirPass; +use rustc::mir::transform::MirPass; pub struct SimplifyCfg; @@ -118,8 +118,8 @@ impl SimplifyCfg { } } -impl<'tcx> MirPass<'tcx> for SimplifyCfg { - fn run_on_mir(&mut self, mir: &mut Mir<'tcx>) { +impl MirPass for SimplifyCfg { + fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, _: &::rustc::middle::ty::ctxt<'tcx>) { let mut changed = true; while changed { changed = self.simplify_branches(mir); diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index c55e97412bb1b..464899d5d4fe3 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -71,6 +71,7 @@ extern crate rustc; extern crate rustc_front; extern crate rustc_metadata; +extern crate rustc_mir; pub use self::registry::Registry; diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 3138d7fa1db56..a51fd58db88dd 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -13,6 +13,8 @@ use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint}; use rustc::session::Session; +use rustc::mir::transform::MirPass; + use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT}; use syntax::ext::base::{IdentTT, MultiModifier, MultiDecorator}; use syntax::ext::base::{MacroExpanderFn, MacroRulesTT}; @@ -53,6 +55,9 @@ pub struct Registry<'a> { #[doc(hidden)] pub late_lint_passes: Vec, + #[doc(hidden)] + pub mir_passes: Vec>, + #[doc(hidden)] pub lint_groups: HashMap<&'static str, Vec>, @@ -76,6 +81,7 @@ impl<'a> Registry<'a> { lint_groups: HashMap::new(), llvm_passes: vec!(), attributes: vec!(), + mir_passes: Vec::new(), } } @@ -134,6 +140,11 @@ impl<'a> Registry<'a> { self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect()); } + /// Register a MIR pass + pub fn register_mir_pass(&mut self, pass: Box) { + self.mir_passes.push(pass); + } + /// Register an LLVM pass. /// /// Registration with LLVM itself is handled through static C++ objects with diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 57e69a0efa95e..720ec3f16891c 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -48,7 +48,7 @@ use middle::ty::adjustment::CustomCoerceUnsized; use rustc::dep_graph::DepNode; use rustc::front::map as hir_map; use rustc::util::common::time; -use rustc_mir::mir_map::MirMap; +use rustc::mir::mir_map::MirMap; use session::config::{self, NoDebugInfo, FullDebugInfo}; use session::Session; use trans::_match; @@ -1596,7 +1596,7 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, false }; - let mir = ccx.mir_map().get(&id); + let mir = ccx.mir_map().map.get(&id); let mut fcx = FunctionContext { mir: mir, diff --git a/src/librustc_trans/trans/collector.rs b/src/librustc_trans/trans/collector.rs index 6ec7378859848..df86685e236bd 100644 --- a/src/librustc_trans/trans/collector.rs +++ b/src/librustc_trans/trans/collector.rs @@ -400,7 +400,7 @@ fn load_mir<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, if def_id.is_local() { let node_id = ccx.tcx().map.as_local_node_id(def_id).unwrap(); - let mir_opt = ccx.mir_map().get(&node_id); + let mir_opt = ccx.mir_map().map.get(&node_id); let mir = errors::expect(ccx.sess().diagnostic(), mir_opt, mir_not_found_error_message); diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 38459c1ec3cb7..b2ebaac665be3 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -15,7 +15,7 @@ use middle::cstore::LinkMeta; use middle::def::ExportMap; use middle::def_id::DefId; use middle::traits; -use rustc_mir::mir_map::MirMap; +use rustc::mir::mir_map::MirMap; use trans::adt; use trans::base; use trans::builder::Builder; diff --git a/src/test/auxiliary/dummy_mir_pass.rs b/src/test/auxiliary/dummy_mir_pass.rs new file mode 100644 index 0000000000000..df9ea4ab012e7 --- /dev/null +++ b/src/test/auxiliary/dummy_mir_pass.rs @@ -0,0 +1,52 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// force-host + +#![feature(plugin_registrar, rustc_private)] +#![feature(box_syntax)] + +#[macro_use] extern crate rustc; +extern crate rustc_front; +extern crate rustc_plugin; +extern crate syntax; + +use rustc::mir::transform::MirPass; +use rustc::mir::repr::{Mir, Literal}; +use rustc::mir::visit::MutVisitor; +use rustc::middle::ty; +use rustc::middle::const_eval::ConstVal; +use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; +use rustc_plugin::Registry; +use rustc_front::hir; +use syntax::attr; + +struct Pass; + +impl MirPass for Pass { + fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, tcx: &ty::ctxt<'tcx>) { + Visitor.visit_mir(mir) + } +} + +struct Visitor; + +impl<'tcx> MutVisitor<'tcx> for Visitor { + fn visit_literal(&mut self, literal: &mut Literal<'tcx>) { + if let Literal::Value { value: ConstVal::Int(ref mut i @ 11) } = *literal { + *i = 42; + } + } +} + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_mir_pass(box Pass); +} diff --git a/src/test/run-pass-fulldeps/mir-pass.rs b/src/test/run-pass-fulldeps/mir-pass.rs new file mode 100644 index 0000000000000..acf11e241033c --- /dev/null +++ b/src/test/run-pass-fulldeps/mir-pass.rs @@ -0,0 +1,24 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:dummy_mir_pass.rs +// ignore-stage1 + +#![feature(plugin, rustc_attrs)] +#![plugin(dummy_mir_pass)] + +#[rustc_mir] +fn math() -> i32 { + 11 +} + +pub fn main() { + assert_eq!(math(), 42); +}