Question on Associated Type

The Ast has an associated type AstClass, which is defined with trait NodeClass. But I can' get the code work when I want to return EditErr, with Class.

fn main(){
let v = vec![Json::True];
let mut node = Dag{
    arena : &v,
    status:false,
}; 
}

trait NodeClass {
}

enum Class{
    T,
    F,
}

impl NodeClass for Class{}

trait Ast<'arena> {
    type AstClass: NodeClass;
}

enum Json {
    True,
    False,
}

enum EditErr{
    BadNode{
        class: Class,
    }
}

enum EditSuccess{
    GoodNode,
}

type EditResult = Result<EditSuccess, EditErr>;

impl <'arena> Ast<'arena> for Json{
    type AstClass = Class;
}

struct Dag <'arena, Node: Ast<'arena>> {
    arena: &'arena Vec<Node>,
    status: bool
}


impl<'arena, Node:Ast<'arena>> Dag <'arena, Node>{
    fn edit(&mut self)-> EditResult{
        if !self.status{
        //return Err(EditErr::BadNode{class : Node::AstClass::T});
        return Err(EditErr::BadNode{class : self.arean[0]::AstClass::T});
        
        }
        return Ok(EditSuccess::GoodNode);
    }
}

The code doesn't compile.
playgroud

The problem you have is that Ast::AstClass is constrained to the NodeClass trait, which doesn’t provide a useful interface. The compiler is trying to ensure that Dag::edit will work with any future type that implements Ast. That type might have picked something other than Class to be its NodeClass.

The simplest, but most restrictive, fix is to require AstClass=Class. This will have the compiler reject any attempt to call edit when that’s not true:


impl<'arena, Node: Ast<'arena, AstClass = Class>> Dag<'arena, Node> {
    fn edit(&mut self) -> EditResult {
        if !self.status {
            return Err(EditErr::BadNode {
                class: Node::AstClass::T,
            });
        }
        return Ok(EditSuccess::GoodNode);
    }
}

(Playground)

1 Like

This is the solution I was looking for. Big thank!