Rust编译报错:TypeId需派生PartialEq、Eq trait
问题
我是Rust新手,正在开发一个与MQTT broker通信、执行数据库基础操作的后端程序,遇到编译错误无法理解。错误信息如下:
error: to use a constant of type `TypeId` in a pattern, `TypeId` must be annotated with `#[derive(PartialEq, Eq)]` --> C:\Users\ege.yetkin.cargo\registry\src\index.crates.io-6f17d22bba15001f\value-bag-1.0.0-alpha.9\src\internal\cast\primitive.rs:43:33 | 43 | ... $const_ident => |v| Some(Internal::from(unsafe { &*(*v as *const Se... | ^^^^^^^^^^^^ ... 71 | / ... to_internal![ 72 | | ... usize: (USIZE, OPTION_USIZE), 73 | | ... u8: (U8, OPTION_U8), 74 | | ... u16: (U16, OPTION_U16), ... | 96 | | ... String: (STRING, OPTION_STRING), 97 | | ... ]; | |\______\_- in this macro invocation | = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details = note: this error originates in the macro `to_internal`
我原本怀疑问题出在数据库模块,代码如下:
use crate::mqtt::{self, MqttMessage}; use serde::{Deserialize, Serialize}; use serde_json; use sqlx::types::Json; use sqlx::{Connection, Row}; use std::time::{SystemTime, UNIX_EPOCH}; #[derive(Clone, Debug, Default, Serialize, Deserialize)] struct payload { iv: i32, metrics: Vec<data_metrics>, ts: i32, } #[derive(Clone, Debug, Default, Serialize, Deserialize)] struct data_metrics { name: String, timestamp: i64, value: f32, //Used concerete type instead of generic type for value, which makes the code more complicated. //In mqtt messages, consider using simple f32. Depending on the name of signal, we can seperate it } //Seperates mqqtt messages into topic and payload fields pub fn db_control_flow(input: mqtt::MqttMessage) -> Result<(), Box<dyn Error>> { let payload_msg = input.payload; let topic_msg = input.topic; //Print the seperated fields of the mqtt message println!("\nDatabase module message payload :{:#?}\n", &payload_msg); println!("\nDatabase module message topic :{:#?}\n", &topic_msg); //parse the topic into fields //device_id is optional because topic might be for a NODE if let (message_type, mac_add) = extract_topic_parts(topic_msg) { println!("MAC Address = {}", mac_add); //a.k.a. NODE number println!("Message Type = {}", &message_type); //with match flow control the message type //depending on the type make proper function calls match message_type.as_str() { "NBIRTH" => println!("NBIRTH"), "NDEATH" => println!("NDEATH"), "DATA" => { let data = payload_parser(payload_msg); //DB_Values_Insert(data, client_no, Some(device_id)); //Buraya database'e göre değişiklik yapılacak } "NCMD" => println!("NCMD"), "DBIRTH" => println!("DBIRTH"), "DDEATH" => println!("DDEATH"), "DDATA" => println!("DDATA"), "DCMD" => println!("DCMD"), "STATE" => println!("STATE"), _ => println!("Unrecognized message type!"), }; } Ok(()) } //this function devides topic into fields /*TAKES PAYLOAD AS JSON IN STRING TYPE, RETURNS PAYLOAD STRUCT */ //uses serde_json //data base data insert function //ADD ERROR HANDLING pub fn DB_Values_Insert(data: payload, mac_no: String) -> Result<(), Box<dyn Error>> { let url = "postgresql://postgres:123456@localhost:5432/SunJrTestEge"; let mut connection = sqlx::postgres::PgConnection::connect(url).await?; let vec_data_metrics: Vec<data_metrics> = data.metrics; /* let mut deviceID: String = client_no + "/" + device_id.unwrap_or_default().as_str(); */ let deviceID: i32 = 1; //Default value untill devices table is active for metric in vec_data_metrics { let mut signal_id: i32 = 0; match metric.name.as_str() { "VBatt" => signal_id = 1, "TBatt" => signal_id = 2, "SOC" => signal_id = 3, "VOC" => signal_id = 4, "P" => signal_id = 5, _ => println!("Undefined signal id type!"), }; let query = "INSERT INTO values_table (deviceid, signalid, value, timestamp) VALUES ($1, $2, $3, $4)"; sqlx::query(query) .bind(&deviceID) .bind(&signal_id) .bind(&metric.value) .bind(&metric.timestamp) .await?; } Ok(()) } fn extract_topic_parts(topic: String) -> (String, String) { let mut topic_parts = topic.split('/'); let mac_add = topic_parts.next().unwrap_or_default().to_string(); let message_type = topic_parts.next().unwrap_or_default().to_string(); return (message_type, mac_add); } fn payload_parser(payload: String) -> payload { let data_forDB: payload = serde_json::from_str(payload.as_str()).expect("serde failed!"); println!("{:#?}", data_forDB); return data_forDB; }
但移除数据库模块后编译仍报相同错误,求解决方法。
解决方案
这个错误的根源是**value-bag 1.0.0-alpha.9版本的内部bug**,和你的代码无关——错误信息明确指向这个依赖包的源码,且移除你的数据库模块后错误依旧,说明问题出在依赖链里。
解决步骤:
- 检查你的
Cargo.toml,找到间接引入value-bag的依赖(大概率是sqlx或其他日志/序列化相关依赖)。 - 升级该依赖到最新稳定版:比如如果是
sqlx,执行cargo update sqlx更新版本。 - 如果升级后仍有问题,直接在
Cargo.toml中添加patch强制替换value-bag版本:
[patch.crates-io] value-bag = { version = "1.0.0-alpha.11", git = "https://github.com/dtolnay/value-bag" }
(注:alpha.11及以后版本修复了这个TypeId匹配的问题)
- 执行
cargo clean && cargo build重新编译。
额外提示:你的数据库模块代码里有个小问题——db_control_flow函数里的Box<dyn Error>需要导入std::error::Error,否则会编译失败,记得在开头加use std::error::Error;。
内容的提问来源于stack exchange,提问作者tonicChord
相关产品推荐
相关产品推荐

