複数のトレイト境界を持つ変数の記述方法
Q&A
解決したいこと
Rustで複数のトレイト境界を持つ変数について記述する方法を知りたいです。
具体的なコードを以下に示します。
Sample Code
まず、oracleクレートを使用しています。query_named
メソッドのoracleクレートでのサンプルコードは以下のとおりです。
pub fn query_named(
&self,
sql: &str,
params: &[(&str, &dyn ToSql)]
) -> Result<ResultSet<'_, Row>>
conn.query_named("insert into emp(empno, ename) values (:id, :name)",
&[("id", &114),
("name", &"Smith")])?;
この引数params
部分について、エラーがあったときに表示させたいという要望がチーム内から出てきました。
params
を変数として切り出すと次のようになります。
let params: [(&str, &dyn ToSql);2] = [("id", &114), ("name", &"Smith")];
conn.query_named("insert into emp(empno, ename) values (:id, :name)", ¶ms)?;
params
と同じ形式を引数に取って文字列にするため、次のようにparams2String
関数を作成しました。
fn param2string(params: &[(&str, &dyn Display)]) -> String {
params
.iter()
.map(|p| format!("{} = {}", p.0, p.1))
.collect::<Vec<_>>()
.join(", ")
}
assert_eq!("id = 114, name = Smith", param2string(&[("id", &114), ("name", &"Smith")]));
param2String
のparams
引数を変数として切り出すと次のようになります。
let params: [(&str, &dyn Display);2] = [("id", &114), ("name", &"Smith")];
assert_eq!("id = 114, name = Smith", param2string(¶ms));
ということで、次の???
部分を完成させれば目的を達成できるのでは、という状態になりました。
let params: [(&str, &dyn ???);2] = [("id", &114), ("name", &"Smith")];
conn.query_named("insert into emp(empno, ename) values (:id, :name)", ¶ms)?;
assert_eq!("id = 114, name = Smith", param2string(¶ms));
試したこと
さしあたり、VSCodeのIntelliSenceでは次のようなコードが例示されました。
let params: [(&str, &dyn (ToSql + Display));2] = [("id", &114), ("name", &"Smith")];
conn.query_named("insert into emp(empno, ename) values (:id, :name)", ¶ms)?;
assert_eq!("id = 114, name = Smith", param2string(¶ms));
しかし、これはコンパイルエラーになります。
only auto traits can be used as additional traits in a trait object
additional non-auto trait
help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: oracle::sql_type::ToSql + std::fmt::Display {}`
note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>
helpに従ってNewTrait
を作成してみます。
trait NewTrait: ToSql + Display{}
let params: [(&str, &(dyn NewTrait)); 2] = [("id", &114), ("name", &"Smith")];
integer
はToSql
とDisplay
のトレイト境界を満たしていますが、NewTrait
のトレイト境界を満たしませんでした。
the trait bound `{integer}: NewTrait` is not satisfied
the trait `NewTrait` is not implemented for `{integer}`
note: required for the cast to the object type `dyn NewTrait`
確認できたのはここまでです。castもしましたが特にエラーメッセージが変わりませんし……
どなたか、このトレイト境界を満たす方法をお願いします。
0