Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ambiguous associated type when access Entity::Column #2156

Closed
Ayana-chan opened this issue Mar 14, 2024 · 5 comments
Closed

ambiguous associated type when access Entity::Column #2156

Ayana-chan opened this issue Mar 14, 2024 · 5 comments

Comments

@Ayana-chan
Copy link

Description

I use sea-orm-cli to genetate entity for my database, but I get ambiguous associated type when I'm trying access Entity::Column.

Steps to Reproduce

My table is called node. Therefore sea-orm-cli generate these codes in entity_crate:

//! module `node`
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
#[sea_orm(table_name = "node")]
#[serde(rename_all = "camelCase")]
pub struct Model {
    #[sea_orm(primary_key, auto_increment = false)]
    pub id: String,
    #[sea_orm(unique)]
    pub peer_id: String,
    pub rpc_address: String,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}

impl ActiveModelBehavior for ActiveModel {}

And it would set Node to be the alias of node::Entity:

//! module `prelude`
pub use super::node::Entity as Node;

Then I want to INSERT ... ON DUPLICATE KEY UPDATE, so I write:

// new node item
let new_node = node::ActiveModel {
    id: Set(new_uuid.clone()),
    peer_id: Set("abcd peer id".to_string()),
    rpc_address: Set("88.88.88.88:1234".to_string()),
};
// what to do when duplicate key (at column peer_id)
// The compile error occurs here
let dup_conflict = sea_query::OnConflict::column(Node::Column::PeerId)
    .update_columns([
        Node::Column::RpcAddress,
    ])
    .to_owned();
// execute
let result = Node::insert(new_node)
    .on_conflict(dup_conflict)
    .exec(&conn)
    .await.unwrap();

I get:

ambiguous associated type (at Node::Column)
help: use fully-qualified syntax: `<Entity as sea_orm::EntityTrait>::Column`

Expected Behavior

Should be no error. I want to access everything of node table by Node (entity_crate::node::Entity).

Actual Behavior

Compile error: ambiguous associated type.

Reproduces How Often

Always.

Workarounds

To avoid this compile error, I just directly import entity_crate::node and use node::Column. A little ugly.

To find out the reason, I use cargo-expand in entity_crate to expand all macros, and I found two trait with associated type called Column: sea_orm::PrimaryKeyToColumn and sea_orm::entity::EntityTrait. And the Entity only impl sea_orm::entity::EntityTrait. However, even though sea_orm::PrimaryKeyToColumn is not imported, the ambiguous associated type error still occurs.

This is a problem about associated type. The code below also have ambiguous associated type compile error:

trait T1 {
    type Name;
}

mod private_mod {
    trait T2 {
        type Name;
    }
}

struct MyStruct {}

impl T1 for MyStruct {
    type Name = i32;
}

fn main() {
    let v: MyStruct::Name = 12;
}

Maybe rename the sea_orm::PrimaryKeyToColumn::Column would solve it.

Reproducible Example

Minimal reproducible example:

use sea_orm::prelude::*;
use sea_orm::sea_query;

// === node ===

#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "node")]
pub struct Model {
    #[sea_orm(primary_key, auto_increment = false)]
    pub id: String,
    #[sea_orm(unique)]
    pub peer_id: String,
    pub rpc_address: String,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}

impl ActiveModelBehavior for ActiveModel {}

// === alias of Entity ===

use Entity as Node;

// === access column ===

fn main() {
    let dup_conflict = sea_query::OnConflict::column(Node::Column::PeerId)
        .update_columns([
            Node::Column::RpcAddress,
        ])
        .to_owned();
}

Versions

sea-orm = "0.12"

sea-orm-cli version: 0.12.14

@tyt2y3
Copy link
Member

tyt2y3 commented Apr 14, 2024

This should not be a bug, because it's been this way since 0.1. As you already know, there are two workarounds:

  1. do node::Column
  2. do <Node as EntityTrait>::Column

But you've made an interesting observation, and the solution is right here! Nobody is using PrimaryKeyToColumn directly, as I imagine, so we can actually afford to break PrimaryKeyToColumn by renaming Column to something else. And now is probably the last time I'd change the Entity type system.

@tyt2y3
Copy link
Member

tyt2y3 commented Apr 23, 2024

PrimaryKeyToColumn by renaming Column to something else

Can you open a PR on this? I want to make this change

@Ayana-chan
Copy link
Author

I apologize for my significant mistake. Renaming can't solve this problem. Actually, this problem would never be solved.

Look at this code:

trait T1 {
    type Name;
}

struct MyStruct {}

impl T1 for MyStruct {
    type Name = i32;
}

fn main() {
    let v: MyStruct::Name = 12;
}

Just one trait and just one associate type, but also get:

Compiling playground v0.0.1 (/playground)
error[E0223]: ambiguous associated type
  --> src/main.rs:13:12
   |
13 |     let v: MyStruct::Name = 12;
   |            ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<MyStruct as T1>::Name`

For more information about this error, try `rustc --explain E0223`.
error: could not compile `playground` (bin "playground") due to 1 previous error

It can be seen that the ambiguous associated type error is unrelated to associate types with duplicate names. It's easy to understand: If Rust allows to access associate type without fully-qualified syntax, any lib user who define an associate type with duplicate names would cause a break inside the lib.

As a conclusion, perhaps accessing associate types from outside of the trait must use fully-qualified syntax like <MyStruct as T1>::Name. So this issue dosen't point out any improvement points.

@tyt2y3
Copy link
Member

tyt2y3 commented Apr 24, 2024

There was a discussion around this before, but I couldn't seem to find it.

@tyt2y3
Copy link
Member

tyt2y3 commented Apr 24, 2024

Found it rust-lang/rust#8995

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants