-
-
Notifications
You must be signed in to change notification settings - Fork 249
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
[WIP] support casting between pgnodes #1048
base: develop
Are you sure you want to change the base?
Conversation
Signed-off-by: Alex Chi <[email protected]>
Some things I'm not sure:
|
Do we need both And should that return a Result instead of an Option? Regarding the the blocklist you made, we identify those as a |
Thanks for the suggestion! I'm thinking of doing the code generation in another way: for PgCast, we should traverse on For the current blocklist,
These are all subclass of TupleTable but doesn't have a corresponding node tag. Their casting is done by looking into
We can either use a blocklist or change implement PgCast only on those with a corresponding node tag. In this way we can do the casting code generation programmatically. Also the current implementation might be counter-intuitive in some cases. For example, Therefore, besides the |
It corresponds with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would probably like us to have this but it needs some clarity of purpose.
// impl the PgNode trait for all nodes | ||
pgnode_impls.extend(quote! { | ||
impl pg_sys::seal::Sealed for #struct_name {} | ||
impl pg_sys::PgNode for #struct_name {} | ||
impl pg_sys::PgNode for #struct_name { | ||
const NODE_TAG: Option<NodeTag> = #node_tag; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't describe polymorphic types with a monomorphic tag like this.
fn cast_from(pg_node: &A) -> Self { | ||
Self::try_cast_from(pg_node).unwrap() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with Eric, we should just make it always-fallible and ditch this.
unsafe { | ||
let node = std::mem::transmute::<_, &Node>(pg_node); | ||
match B::NODE_TAG { | ||
Some(tag) => { | ||
if node.type_ == tag { | ||
Some(std::mem::transmute::<_, &B>(node)) | ||
} else { | ||
None | ||
} | ||
} | ||
None => None, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hrmmm. What "directionality" of casting is this intended to handle? Upcasting? Downcasting? Something else? I feel we should support checked casting, for sure, instead of just making people do pointer-casts, but I don't feel confident about what this is "for", basically.
// now we can finally iterate the Nodes and emit out Display impl | ||
for node_struct in nodes { | ||
let struct_name = &node_struct.struct_.ident; | ||
|
||
let node_tag = if !block_list.contains(struct_name.to_string().as_str()) { | ||
let node_tag = quote::format_ident!("NodeTag_T_{}", struct_name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I changed NodeTag to a real enum, so this would have to be
let node_tag = quote::format_ident!("NodeTag_T_{}", struct_name); | |
let node_tag = quote::format_ident!("NodeTag_T::{}", struct_name); |
// Though these structs looks like a node, they don't seem to have a corresponding [`NodeTag`]. | ||
// Also for `Node`, it doesn't have a node tag. | ||
let block_list = [ | ||
"Node", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why block Node, exactly?
The way forward is probably having each Node type implement a trait that has a function that can be called to determine if the cast is valid. |
This is slightly off, my apologies. It's more like an abstract Node type, which means that other Nodes can have it as their superclass. |
No description provided.