"Overflow evaluating the requirement" only happens in release build but not debug build

⚓ rust    📅 2025-06-05    👤 surdeus    👁️ 1      

surdeus

I encountered an "overflow evaluating the requirement" error only when building in release mode but not in debug mode. Here is the minimal reproducible example (Rust playground):

// This demonstrates a Rust compiler bug where the same code:
// - Compiles and runs successfully in debug mode
// - Fails with infinite recursion error E0275 in release mode

pub struct LeafNode;

pub enum Node {
    Leaf(LeafNode),
    Internal(InternalNode),
}

pub struct InternalNode;

pub trait NodeTrait {
    type T;

    type InternalNodeType: InternalNodeTrait<T = Self::T>;

    fn internal_node(&self) -> Option<&Self::InternalNodeType>;
}

pub trait InternalNodeTrait: NodeTrait {
    type NodeType: NodeTrait<T = Self::T>;

    fn children(&self) -> impl Iterator<Item = Self::NodeType>;
}

impl NodeTrait for Node {
    type T = f64;
    type InternalNodeType = InternalNode;

    fn internal_node(&self) -> Option<&Self::InternalNodeType> {
        match self {
            Node::Leaf(_) => None,
            Node::Internal(p) => Some(p),
        }
    }
}

impl NodeTrait for InternalNode {
    type T = f64;
    type InternalNodeType = InternalNode;

    fn internal_node(&self) -> Option<&Self::InternalNodeType> {
        Some(self)
    }
}

impl InternalNodeTrait for InternalNode {
    type NodeType = Node;

    fn children(&self) -> impl Iterator<Item = Self::NodeType> {
        std::iter::empty()
    }
}

// --- TREE SIZE TRAITS (THE BUG TRIGGER) ---

pub trait TreeSize {
    /// Convert to a geo_types [`Geometry`].
    fn size(&self) -> usize;
}

pub trait SubTreeSize {
    fn subtree_size(&self) -> usize;
}

impl<N: NodeTrait<T = f64>> TreeSize for N {
    fn size(&self) -> usize {
        match self.internal_node() {
            Some(gc) => gc.subtree_size(),
            None => 1,
        }
    }
}

impl<N: InternalNodeTrait<T = f64>> SubTreeSize for N {
    fn subtree_size(&self) -> usize {
        let mut size = 0;
        for node in self.children() {
            size += node.size();
        }
        size
    }
}

pub fn tree_size(node: impl NodeTrait<T = f64>) -> usize {
    node.size()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_to_geometry() {
        let node = Node::Leaf(LeafNode);
        
        // This works in debug mode but fails with infinite recursion in release mode
        println!("{:?}", tree_size(node));
    }
}

Switching "optimization level" to debug in the Rust playground and test again, the problem suddenly went away.

The original problem I met was when working with the georust/geo crate, where NodeTrait corresponds to GeometryTrait and InternalNodeTrait corresponds to GeometryCollectionTrait. I renamed the traits for broader audience to get better understanding.

Is this build error in release mode caused by a compiler bug? Or do I need to avoid any possibility of recursion in associated types?

2 posts - 1 participant

Read full topic

🏷️ rust_feed