diff --git a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_aggregate_literals.rs b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_aggregate_literals.rs index e30eb0f..1aabb19 100644 --- a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_aggregate_literals.rs +++ b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_aggregate_literals.rs @@ -88,9 +88,6 @@ impl Visitor<'_> { field.expr = parse_quote_spanned! {field.member.span()=> ::fayalite::sim::value::ToSimValue::to_sim_value(&(#expr)) }; - field - .colon_token - .get_or_insert(Token![:](field.member.span())); } return parse_quote_spanned! {name_span=> { diff --git a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs index ca06c0b..069f00d 100644 --- a/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs +++ b/crates/fayalite-proc-macros-impl/src/module/transform_body/expand_match.rs @@ -10,7 +10,7 @@ use crate::{ }; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, TokenStreamExt, format_ident, quote_spanned}; -use std::collections::BTreeMap; +use std::collections::BTreeSet; use syn::{ Arm, Attribute, Expr, ExprMatch, FieldPat, Ident, Local, Member, Pat, PatIdent, PatOr, PatParen, PatPath, PatRest, PatStruct, PatTuple, PatTupleStruct, PatWild, Path, PathSegment, @@ -24,65 +24,65 @@ use syn::{ macro_rules! visit_trait { ( - $($vis:vis fn $fn:ident($state:ident: _, $value:ident: &mut $Value:ty) $block:block)* + $($vis:vis fn $fn:ident($state:ident: _, $value:ident: &$Value:ty) $block:block)* ) => { trait VisitMatchPat<'a> { - $(fn $fn(&mut self, $value: &'a mut $Value) { + $(fn $fn(&mut self, $value: &'a $Value) { $fn(self, $value); })* } - $($vis fn $fn<'a>($state: &mut (impl ?Sized + VisitMatchPat<'a>), $value: &'a mut $Value) $block)* + $($vis fn $fn<'a>($state: &mut (impl ?Sized + VisitMatchPat<'a>), $value: &'a $Value) $block)* }; } visit_trait! { - fn visit_match_pat_binding(_state: _, v: &mut MatchPatBinding) { - let MatchPatBinding { mutability: _, ident: _ } = v; + fn visit_match_pat_binding(_state: _, v: &MatchPatBinding) { + let MatchPatBinding { ident: _ } = v; } - fn visit_match_pat_wild(_state: _, v: &mut MatchPatWild) { + fn visit_match_pat_wild(_state: _, v: &MatchPatWild) { let MatchPatWild { underscore_token: _ } = v; } - fn visit_match_pat_rest(_state: _, v: &mut MatchPatRest) { + fn visit_match_pat_rest(_state: _, v: &MatchPatRest) { let MatchPatRest { dot2_token: _ } = v; } - fn visit_match_pat_paren(state: _, v: &mut MatchPatParen) { + fn visit_match_pat_paren(state: _, v: &MatchPatParen) { let MatchPatParen { paren_token: _, pat } = v; state.visit_match_pat(pat); } - fn visit_match_pat_paren_simple(state: _, v: &mut MatchPatParen) { + fn visit_match_pat_paren_simple(state: _, v: &MatchPatParen) { let MatchPatParen { paren_token: _, pat } = v; state.visit_match_pat_simple(pat); } - fn visit_match_pat_or(state: _, v: &mut MatchPatOr) { + fn visit_match_pat_or(state: _, v: &MatchPatOr) { let MatchPatOr { leading_vert: _, cases } = v; for v in cases { state.visit_match_pat(v); } } - fn visit_match_pat_or_simple(state: _, v: &mut MatchPatOr) { + fn visit_match_pat_or_simple(state: _, v: &MatchPatOr) { let MatchPatOr { leading_vert: _, cases } = v; for v in cases { state.visit_match_pat_simple(v); } } - fn visit_match_pat_struct_field(state: _, v: &mut MatchPatStructField) { + fn visit_match_pat_struct_field(state: _, v: &MatchPatStructField) { let MatchPatStructField { field_name: _, colon_token: _, pat } = v; state.visit_match_pat_simple(pat); } - fn visit_match_pat_struct(state: _, v: &mut MatchPatStruct) { + fn visit_match_pat_struct(state: _, v: &MatchPatStruct) { let MatchPatStruct { match_span: _, path: _, brace_token: _, fields, rest: _ } = v; for v in fields { state.visit_match_pat_struct_field(v); } } - fn visit_match_pat_tuple(state: _, v: &mut MatchPatTuple) { + fn visit_match_pat_tuple(state: _, v: &MatchPatTuple) { let MatchPatTuple { paren_token: _, fields } = v; for v in fields { state.visit_match_pat_simple(v); } } - fn visit_match_pat_enum_variant(state: _, v: &mut MatchPatEnumVariant) { + fn visit_match_pat_enum_variant(state: _, v: &MatchPatEnumVariant) { let MatchPatEnumVariant { match_span:_, sim:_, @@ -95,7 +95,7 @@ visit_trait! { state.visit_match_pat_simple(v); } } - fn visit_match_pat_simple(state: _, v: &mut MatchPatSimple) { + fn visit_match_pat_simple(state: _, v: &MatchPatSimple) { match v { MatchPatSimple::Paren(v) => state.visit_match_pat_paren_simple(v), MatchPatSimple::Or(v) => state.visit_match_pat_or_simple(v), @@ -104,7 +104,7 @@ visit_trait! { MatchPatSimple::Rest(v) => state.visit_match_pat_rest(v), } } - fn visit_match_pat(state: _, v: &mut MatchPat) { + fn visit_match_pat(state: _, v: &MatchPat) { match v { MatchPat::Simple(v) => state.visit_match_pat_simple(v), MatchPat::Or(v) => state.visit_match_pat_or(v), @@ -118,15 +118,13 @@ visit_trait! { with_debug_clone_and_fold! { struct MatchPatBinding<> { - mutability: Option, ident: Ident, } } impl ToTokens for MatchPatBinding { fn to_tokens(&self, tokens: &mut TokenStream) { - let Self { mutability, ident } = self; - mutability.to_tokens(tokens); + let Self { ident } = self; ident.to_tokens(tokens); } } @@ -213,20 +211,12 @@ impl ToTokens for MatchPatStructField { colon_token, pat, } = self; - if let ( - None, - MatchPatSimple::Binding(MatchPatBinding { - mutability: _, - ident, - }), - ) = (colon_token, pat) - { + field_name.to_tokens(tokens); + if let (None, MatchPatSimple::Binding(MatchPatBinding { ident })) = (colon_token, pat) { if field_name == ident { - pat.to_tokens(tokens); return; } } - field_name.to_tokens(tokens); colon_token .unwrap_or_else(|| Token![:](field_name.span())) .to_tokens(tokens); @@ -460,7 +450,7 @@ trait ParseMatchPat: Sized { Pat::Ident(PatIdent { attrs: _, by_ref, - mut mutability, + mutability, ident, subpat, }) => { @@ -469,13 +459,10 @@ trait ParseMatchPat: Sized { .errors .error(by_ref, "ref not allowed in #[hdl] patterns"); } - if let Some(mut_token) = mutability { - if state.sim.is_none() { - state - .errors - .error(mut_token, "mut not allowed in #[hdl] patterns"); - mutability = None; // avoid duplicate errors - } + if let Some(mutability) = mutability { + state + .errors + .error(mutability, "mut not allowed in #[hdl] patterns"); } if let Some((at_token, _)) = subpat { state @@ -487,26 +474,18 @@ trait ParseMatchPat: Sized { variant_path, enum_path, variant_name, - }) => { - if let Some(mut_token) = mutability { - state - .errors - .error(mut_token, "mut not allowed on unit variants"); - } - Self::enum_variant( - state, - MatchPatEnumVariant { - match_span: state.match_span, - sim: state.sim, - variant_path, - enum_path, - variant_name, - field: None, - }, - ) - } + }) => Self::enum_variant( + state, + MatchPatEnumVariant { + match_span: state.match_span, + sim: state.sim, + variant_path, + enum_path, + variant_name, + field: None, + }, + ), Err(ident) => Ok(Self::simple(MatchPatSimple::Binding(MatchPatBinding { - mutability, ident, }))), } @@ -1001,16 +980,15 @@ struct HdlMatchParseState<'a> { struct HdlLetPatVisitState<'a> { errors: &'a mut Errors, - bindings: BTreeMap, + bindings: BTreeSet<&'a Ident>, } impl<'a> VisitMatchPat<'a> for HdlLetPatVisitState<'a> { - fn visit_match_pat_binding(&mut self, v: &'a mut MatchPatBinding) { - self.bindings.insert(v.ident.clone(), v.clone()); - v.mutability = None; + fn visit_match_pat_binding(&mut self, v: &'a MatchPatBinding) { + self.bindings.insert(&v.ident); } - fn visit_match_pat_or(&mut self, v: &'a mut MatchPatOr) { + fn visit_match_pat_or(&mut self, v: &'a MatchPatOr) { if let Some(first_inner_vert) = v.first_inner_vert() { self.errors.error( first_inner_vert, @@ -1020,7 +998,7 @@ impl<'a> VisitMatchPat<'a> for HdlLetPatVisitState<'a> { visit_match_pat_or(self, v); } - fn visit_match_pat_or_simple(&mut self, v: &'a mut MatchPatOr) { + fn visit_match_pat_or_simple(&mut self, v: &'a MatchPatOr) { if let Some(first_inner_vert) = v.first_inner_vert() { self.errors.error( first_inner_vert, @@ -1030,7 +1008,7 @@ impl<'a> VisitMatchPat<'a> for HdlLetPatVisitState<'a> { visit_match_pat_or_simple(self, v); } - fn visit_match_pat_enum_variant(&mut self, v: &'a mut MatchPatEnumVariant) { + fn visit_match_pat_enum_variant(&mut self, v: &'a MatchPatEnumVariant) { self.errors.error(v, "refutable pattern in let statement"); } } @@ -1070,7 +1048,7 @@ impl Visitor<'_> { .error(else_, "#[hdl] let ... else { ... } is not implemented"); return empty_let(); } - let Ok(mut pat) = MatchPat::parse( + let Ok(pat) = MatchPat::parse( &mut HdlMatchParseState { sim, match_span: span, @@ -1082,27 +1060,20 @@ impl Visitor<'_> { }; let mut state = HdlLetPatVisitState { errors: &mut self.errors, - bindings: BTreeMap::new(), + bindings: BTreeSet::new(), }; - state.visit_match_pat(&mut pat); + state.visit_match_pat(&pat); let HdlLetPatVisitState { errors: _, bindings, } = state; - let bindings_idents = bindings.keys(); - let bindings = bindings.values(); let retval = if sim.is_some() { parse_quote_spanned! {span=> let (#(#bindings,)*) = { type __MatchTy = ::SimValue; - let __match_value = #expr; - let __match_value = { - use ::fayalite::sim::value::match_sim_value::*; - // use method syntax to deduce the correct trait to call - ::fayalite::sim::value::match_sim_value::MatchSimValueHelper::new(__match_value).__fayalite_match_sim_value() - }; - #let_token #pat #eq_token __match_value #semi_token - (#(#bindings_idents,)*) + let __match_value = ::fayalite::sim::value::ToSimValue::to_sim_value(&(#expr)); + #let_token #pat #eq_token ::fayalite::sim::value::SimValue::into_value(__match_value) #semi_token + (#(#bindings,)*) }; } } else { @@ -1134,7 +1105,7 @@ impl Visitor<'_> { __match_variant, ); #let_token #pat #eq_token __match_variant #semi_token - (#(#bindings_idents,)* __scope,) + (#(#bindings,)* __scope,) }; } }; @@ -1171,13 +1142,8 @@ impl Visitor<'_> { quote_spanned! {span=> { type __MatchTy = ::SimValue; - let __match_value = #expr; - let __match_value = { - use ::fayalite::sim::value::match_sim_value::*; - // use method syntax to deduce the correct trait to call - ::fayalite::sim::value::match_sim_value::MatchSimValueHelper::new(__match_value).__fayalite_match_sim_value() - }; - #match_token __match_value { + let __match_expr = ::fayalite::sim::value::ToSimValue::to_sim_value(&(#expr)); + #match_token ::fayalite::sim::value::SimValue::into_value(__match_expr) { #(#arms)* } } diff --git a/crates/fayalite/src/_docs/modules/module_bodies/hdl_let_statements/destructuring.rs b/crates/fayalite/src/_docs/modules/module_bodies/hdl_let_statements/destructuring.rs index 8d70d21..1fc4705 100644 --- a/crates/fayalite/src/_docs/modules/module_bodies/hdl_let_statements/destructuring.rs +++ b/crates/fayalite/src/_docs/modules/module_bodies/hdl_let_statements/destructuring.rs @@ -31,81 +31,3 @@ //! } //! } //! ``` -//! -//! You can also use `#[hdl(sim)] let` to destructure [`SimValue`]s (or anything that implements [`ToSimValue`]). -//! -//! [`SimValue`]: crate::sim::value::SimValue -//! [`ToSimValue`]: crate::sim::value::ToSimValue -//! -//! ``` -//! # use fayalite::prelude::*; -//! #[hdl] -//! struct MyStruct { -//! a: UInt<8>, -//! b: Bool, -//! c: T, -//! } -//! -//! #[hdl] -//! fn destructure(v: SimValue>) { -//! #[hdl(sim)] -//! let MyStruct:: { -//! a, -//! mut b, -//! c, -//! } = v; -//! -//! // that gives these types: -//! let _: SimValue> = a; -//! let _: SimValue = b; -//! let _: SimValue = c; -//! *b = false; // can modify b since mut was used -//! } -//! -//! #[hdl] -//! fn destructure_ref<'a, T: Type>(v: &'a SimValue>) { -//! #[hdl(sim)] -//! let MyStruct:: { -//! a, -//! b, -//! c, -//! } = v; -//! -//! // that gives these types: -//! let _: &'a SimValue> = a; -//! let _: &'a SimValue = b; -//! let _: &'a SimValue = c; -//! } -//! -//! #[hdl] -//! fn destructure_mut<'a, T: Type>(v: &'a mut SimValue>) { -//! #[hdl(sim)] -//! let MyStruct:: { -//! a, -//! b, -//! c, -//! } = v; -//! -//! **b = true; // you can modify v by modifying b which borrows from it -//! -//! // that gives these types: -//! let _: &'a mut SimValue> = a; -//! let _: &'a mut SimValue = b; -//! let _: &'a mut SimValue = c; -//! } -//! -//! #[hdl] -//! fn destructure_to_sim_value<'a, T: Type>(v: impl ToSimValue>) { -//! #[hdl(sim)] -//! let MyStruct:: { -//! a, -//! b, -//! c, -//! } = v; -//! -//! // that gives these types: -//! let _: SimValue> = a; -//! let _: SimValue = b; -//! let _: SimValue = c; -//! } -//! ``` diff --git a/crates/fayalite/src/_docs/modules/module_bodies/hdl_match_statements.rs b/crates/fayalite/src/_docs/modules/module_bodies/hdl_match_statements.rs index accd3d7..6df70f1 100644 --- a/crates/fayalite/src/_docs/modules/module_bodies/hdl_match_statements.rs +++ b/crates/fayalite/src/_docs/modules/module_bodies/hdl_match_statements.rs @@ -9,78 +9,3 @@ //! //! `#[hdl] match` statements can only match one level of struct/tuple/enum pattern for now, //! e.g. you can match with the pattern `HdlSome(v)`, but not `HdlSome(HdlSome(_))`. -//! -//! You can also use `#[hdl(sim)] match` to match [`SimValue`]s (or anything that implements [`ToSimValue`]). -//! -//! `#[hdl(sim)] match` statements' bodies may have any type, unlike `#[hdl] match`. -//! -//! [`SimValue`]: crate::sim::value::SimValue -//! [`ToSimValue`]: crate::sim::value::ToSimValue -//! -//! ``` -//! # use fayalite::prelude::*; -//! #[hdl] -//! enum MyEnum { -//! A, -//! B(Bool), -//! C(T), -//! } -//! -//! #[hdl] -//! fn match_move(v: SimValue>) -> String { -//! #[hdl(sim)] -//! match v { -//! MyEnum::::A => String::from("got A"), -//! MyEnum::::B(mut b) => { -//! let _: SimValue = b; // b has this type -//! let text = format!("got B({b})"); -//! *b = true; // can modify b since mut was used -//! text -//! } -//! _ => String::from("something else"), -//! } -//! } -//! -//! #[hdl] -//! fn match_ref<'a, T: Type>(v: &'a SimValue>) -> u32 { -//! #[hdl(sim)] -//! match v { -//! MyEnum::::A => 1, -//! MyEnum::::B(b) => { -//! let _: &'a SimValue = b; // b has this type -//! println!("got B({b})"); -//! 5 -//! } -//! _ => 42, -//! } -//! } -//! -//! #[hdl] -//! fn match_mut<'a, T: Type>(v: &'a mut SimValue>) -> Option<&'a mut SimValue> { -//! #[hdl(sim)] -//! match v { -//! MyEnum::::A => None, -//! MyEnum::::B(b) => { -//! println!("got B({b})"); -//! **b = true; // you can modify v by modifying b which borrows from it -//! let _: &'a mut SimValue = b; // b has this type -//! None -//! } -//! MyEnum::::C(v) => Some(v), // you can return matched values -//! _ => None, // HDL enums can have invalid discriminants, so we need this extra match arm -//! } -//! } -//! -//! #[hdl] -//! fn match_to_sim_value<'a, T: Type>(v: impl ToSimValue>) { -//! #[hdl(sim)] -//! match v { -//! MyEnum::::A => println!("got A"), -//! MyEnum::::B(b) => { -//! let _: SimValue = b; // b has this type -//! println!("got B({b})"); -//! } -//! _ => println!("something else"), -//! } -//! } -//! ``` diff --git a/crates/fayalite/src/sim/value.rs b/crates/fayalite/src/sim/value.rs index ff836d5..ff6660c 100644 --- a/crates/fayalite/src/sim/value.rs +++ b/crates/fayalite/src/sim/value.rs @@ -157,13 +157,7 @@ pub struct SimValue { inner: AlternatingCell>, } -impl> fmt::Display for SimValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - T::SimValue::fmt(self, f) - } -} - -impl Clone for SimValue { +impl Clone for SimValue { fn clone(&self) -> Self { Self { inner: AlternatingCell::new_unique(self.inner.share().clone()), @@ -492,117 +486,6 @@ impl SimValuePartialEq for AsyncReset { } } -#[doc(hidden)] -pub mod match_sim_value { - use crate::{ - sim::value::{SimValue, ToSimValue}, - ty::Type, - }; - - #[doc(hidden)] - pub struct MatchSimValueHelper(Option); - - impl MatchSimValueHelper { - pub fn new(v: T) -> Self { - Self(Some(v)) - } - } - - #[doc(hidden)] - pub trait MatchSimValue { - type MatchValue; - - /// use `self` so it comes first in the method resolution order - fn __fayalite_match_sim_value(self) -> Self::MatchValue - where - Self: Sized; - } - - impl MatchSimValue for MatchSimValueHelper> { - type MatchValue = T::SimValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - SimValue::into_value(self.0.expect("should be Some")) - } - } - - impl<'a, T: Type> MatchSimValue for MatchSimValueHelper<&'a SimValue> { - type MatchValue = &'a T::SimValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - SimValue::value(self.0.expect("should be Some")) - } - } - - impl<'a, T: Type> MatchSimValue for MatchSimValueHelper<&'a mut SimValue> { - type MatchValue = &'a mut T::SimValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - SimValue::value_mut(self.0.expect("should be Some")) - } - } - - impl<'a, T> MatchSimValue for MatchSimValueHelper<&'_ &'a T> - where - MatchSimValueHelper<&'a T>: MatchSimValue, - { - type MatchValue = as MatchSimValue>::MatchValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - MatchSimValue::__fayalite_match_sim_value(MatchSimValueHelper(self.0.map(|v| *v))) - } - } - - impl<'a, T> MatchSimValue for MatchSimValueHelper<&'_ mut &'a T> - where - MatchSimValueHelper<&'a T>: MatchSimValue, - { - type MatchValue = as MatchSimValue>::MatchValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - MatchSimValue::__fayalite_match_sim_value(MatchSimValueHelper(self.0.map(|v| *v))) - } - } - - impl<'a, T> MatchSimValue for MatchSimValueHelper<&'a &'_ mut T> - where - MatchSimValueHelper<&'a T>: MatchSimValue, - { - type MatchValue = as MatchSimValue>::MatchValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - MatchSimValue::__fayalite_match_sim_value(MatchSimValueHelper(self.0.map(|v| &**v))) - } - } - - impl<'a, T> MatchSimValue for MatchSimValueHelper<&'a mut &'_ mut T> - where - MatchSimValueHelper<&'a mut T>: MatchSimValue, - { - type MatchValue = as MatchSimValue>::MatchValue; - - fn __fayalite_match_sim_value(self) -> Self::MatchValue { - MatchSimValue::__fayalite_match_sim_value(MatchSimValueHelper(self.0.map(|v| &mut **v))) - } - } - - #[doc(hidden)] - pub trait MatchSimValueFallback { - type MatchValue; - - /// use `&mut self` so it comes later in the method resolution order than MatchSimValue - fn __fayalite_match_sim_value(&mut self) -> Self::MatchValue; - } - - impl MatchSimValueFallback for MatchSimValueHelper { - type MatchValue = ::SimValue; - - fn __fayalite_match_sim_value(&mut self) -> Self::MatchValue { - SimValue::into_value(self.0.take().expect("should be Some").into_sim_value()) - } - } -} - pub trait ToSimValue: ToSimValueWithType<::Type> { type Type: Type; @@ -735,7 +618,7 @@ impl ToSimValueWithType for BitSlice { } } -impl<'a, This: ?Sized + ToSimValue> ToSimValue for &'a This { +impl ToSimValue for &'_ This { type Type = This::Type; fn to_sim_value(&self) -> SimValue { diff --git a/crates/fayalite/tests/sim.rs b/crates/fayalite/tests/sim.rs index be4e207..b4169c6 100644 --- a/crates/fayalite/tests/sim.rs +++ b/crates/fayalite/tests/sim.rs @@ -506,10 +506,10 @@ fn test_enums() { data_out: _, b_out: _, b2_out: _, - } = &expected; - sim.write(sim.io().en, en); - sim.write(sim.io().which_in, which_in); - sim.write(sim.io().data_in, data_in); + } = expected; + sim.write(sim.io().en, &en); + sim.write(sim.io().which_in, &which_in); + sim.write(sim.io().data_in, &data_in); let io = #[hdl(sim)] IO::<_> { en, @@ -528,7 +528,7 @@ fn test_enums() { ); // make sure matching on SimValue works #[hdl(sim)] - match &io.b_out { + match io.b_out { HdlNone => println!("io.b_out is HdlNone"), HdlSome(v) => println!("io.b_out is HdlSome(({:?}, {:?}))", *v.0, *v.1), } @@ -706,13 +706,13 @@ fn test_memories() { w_en, w_data, w_mask, - } = &expected; - sim.write(sim.io().r.addr, r_addr); - sim.write(sim.io().r.en, r_en); - sim.write(sim.io().w.addr, w_addr); - sim.write(sim.io().w.en, w_en); - sim.write(sim.io().w.data, w_data); - sim.write(sim.io().w.mask, w_mask); + } = expected; + sim.write(sim.io().r.addr, &r_addr); + sim.write(sim.io().r.en, &r_en); + sim.write(sim.io().w.addr, &w_addr); + sim.write(sim.io().w.en, &w_en); + sim.write(sim.io().w.data, &w_data); + sim.write(sim.io().w.mask, &w_mask); let io = #[hdl(sim)] IO { r_addr, @@ -1505,7 +1505,7 @@ fn test_many_memories() { w_en, w_data, w_mask, - } = &expected; + } = expected; for (((r, w), w_data), w_mask) in sim .io() .r @@ -1514,10 +1514,10 @@ fn test_many_memories() { .zip(w_data.iter()) .zip(w_mask.iter()) { - sim.write(r.addr, r_addr); - sim.write(r.en, r_en); - sim.write(w.addr, w_addr); - sim.write(w.en, w_en); + sim.write(r.addr, &r_addr); + sim.write(r.en, &r_en); + sim.write(w.addr, &w_addr); + sim.write(w.en, &w_en); sim.write(w.data, w_data); sim.write(w.mask, w_mask); }