You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 06:57:12