Skip to content

Strange behavior happens when using try_detach_insert_subtree() for the root node of a tree

I want to use Node::try_detach_insert_subtree() to insert a whole tree to another tree.
However, if I use try_detach_insert_subtree() for the root node of a tree, a strange behavior happens.

See below for details.

Example 1: it not works

use dendron::{InsertAs, Node};

fn main() {
    // (1)
    let node0 = Node::new_tree("0");
    let grant0 = node0.tree().grant_hierarchy_edit().unwrap();
    let node0_0 = node0.create_as_last_child(&grant0, "0-0");

    // (2)
    let node1 = Node::new_tree("1");
    let grant1 = node1.tree().grant_hierarchy_edit().unwrap();

    let node1_1 = node1.create_as_last_child(&grant1, "1-1");
    let _node1_1_1 = node1_1.create_as_last_child(&grant1, "1-1-1");

    // There are two trees.
    //
    //  (1)
    //  0
    //  `-- 0-0
    //
    //  (2)
    //  1
    //  `-- 1-1
    //      `-- 1-1-1

    println!("(1)");
    println!("{}", &node0.tree().debug_pretty_print());
    println!("");

    println!("(2)");
    println!("{}", &node1.tree().debug_pretty_print());
    println!("");

    let node0_0_hot = &node0_0.bundle_new_hierarchy_edit_grant().unwrap();

    node1
        .try_detach_insert_subtree(&grant1, InsertAs::LastChildOf(&node0_0_hot))
        .expect("creating valid hierarchy");

    println!("[Actual]");
    println!("{}", &node1.tree().debug_pretty_print());
    println!("");

    // [I expected]
    //  0
    //  `-- 0-0
    //      `-- 1
    //          `-- 1-1
    //              `-- 1-1-1

    // [Actual]
    // 0
    // `-- 0-0
    //     `-- 1
    //
    // (Where 1-1 subtree has gone to!?)

    // Pass. node1 says it has children.
    assert!(node1.has_children());

    // Pass. node1 says it has a child.
    assert_eq!(node1.num_children(), 1);

    // Panics. Though node1.has_children() is true, node1.first_child() panics!
    assert_eq!(*node1.first_child().unwrap().borrow_data(), "1-1");
}

Example 2: it works

use dendron::{InsertAs, Node};

fn main() {
    // (1)
    let node0 = Node::new_tree("0");
    let grant0 = node0.tree().grant_hierarchy_edit().unwrap();
    let node0_0 = node0.create_as_last_child(&grant0, "0-0");

    // (2)
    let dummy_root = Node::new_tree("dummy"); // differ from first example
    let grant1 = dummy_root.tree().grant_hierarchy_edit().unwrap(); // differ from first example
    let node1 = dummy_root.create_as_last_child(&grant1, "1"); // differ from first example

    let node1_1 = node1.create_as_last_child(&grant1, "1-1");
    let _node1_1_1 = node1_1.create_as_last_child(&grant1, "1-1-1");

    // There are two trees.
    //
    //  (1)
    //  0
    //  `-- 0-0
    //
    //  (2)
    //  dummy
    //  `--1
    //      `-- 1-1
    //          `-- 1-1-1

    println!("(1)");
    println!("{}", &node0.tree().debug_pretty_print());
    println!("");

    println!("(2)");
    println!("{}", &node1.tree().debug_pretty_print());
    println!("");

    let node0_0_hot = &node0_0.bundle_new_hierarchy_edit_grant().unwrap();

    node1
        .try_detach_insert_subtree(&grant1, InsertAs::LastChildOf(&node0_0_hot))
        .expect("creating valid hierarchy");

    println!("[Actual]");
    println!("{}", &node1.tree().debug_pretty_print());
    println!("");

    // [I expected]
    //  0
    //  `-- 0-0
    //      `-- 1
    //          `-- 1-1
    //              `-- 1-1-1

    // [Actual: OK!]
    //  0
    //  `-- 0-0
    //      `-- 1
    //          `-- 1-1
    //              `-- 1-1-1

    // Pass. node1 says it has children.
    assert!(node1.has_children());

    // Pass. node1 says it has a child.
    assert_eq!(node1.num_children(), 1);

    // Pass!
    assert_eq!(*node1.first_child().unwrap().borrow_data(), "1-1");
}