What is the difference between dg.function.copy_u('h','m') and dg.function.copy_u('h','e')?

I’m confused by the following two message functions:
message_func1 = dgl.function.copy_u(‘h’, ‘m’)
message_func2 = dgl.function.copy_u(‘h’, ‘e’)
I understand that, the first one will only generate mesages, while the second one will generate both messages AND edge features (called ‘e’). Am I right?

The document tells the message function will return messages OR edge features. So when return messages and when return edge feature? thanks.

def edge_udf(edges):
edges : EdgeBatch
A batch of edges.

dict[str, tensor]
    The messages or edge features generated. It maps a message/feature name to the
    corresponding messages/features of all edges in the batch. The order of the
    messages/features is the same as the order of the edges in the input argument.

No, they are actually the same. Just in the reduce function, the message is stored in node.mailbox by node.mailbox['m'] or node.mailbox['e']

Basically the message is the same as the edge data. But in the update_all function, the intermediate message will be considered as cache, and will be removed after the full update_all process