rust-lang/rust · critical

forbidden edge {:?} -> {:?} created

Error message

forbidden edge {:?} -> {:?} created

What it means

Only under `debug_assertions`: when a task records a read edge in the dep graph (graph.rs:538), rustc checks it against a declared `forbidden_edge` set. Creating an edge the dep-graph ordering rules forbid is an internal invariant violation, so the debug build panics with the offending source→target pair. Release builds skip the check.

Source

Thrown at compiler/rustc_middle/src/dep_graph/graph.rs:538

                        panic_on_forbidden_read(data, dep_node_index)
                    }
                };
                let task_deps = &mut *task_deps;

                if cfg!(debug_assertions) {
                    data.current.total_read_count.fetch_add(1, Ordering::Relaxed);
                }

                let new_read = task_deps.reads.insert(dep_node_index, &data.read_recorder_pool);
                if new_read {
                    #[cfg(debug_assertions)]
                    {
                        if let Some(target) = task_deps.node
                            && let Some(ref forbidden_edge) = data.current.forbidden_edge
                        {
                            let src = forbidden_edge.index_to_node.lock()[&dep_node_index];
                            if forbidden_edge.test(&src, &target) {
                                panic!("forbidden edge {:?} -> {:?} created", src, target)
                            }
                        }
                    }
                } else if cfg!(debug_assertions) {
                    data.current.total_duplicate_read_count.fetch_add(1, Ordering::Relaxed);
                }
            })
        }
    }

    /// This encodes a side effect by creating a node with an unique index and associating
    /// it with the node, for use in the next session.
    #[inline]
    pub fn record_diagnostic<'tcx>(&self, tcx: TyCtxt<'tcx>, diagnostic: &DiagInner) {
        if let Some(ref data) = self.data {
            read_deps(|task_deps| match task_deps {
                TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return,
                TaskDepsRef::Forbid | TaskDepsRef::Allow(..) => {

View on GitHub (pinned to 22057b88b0)

Solutions

  1. If you are not developing rustc, switch to a release/stable rustc — the assertion is debug-only and the underlying behavior is otherwise allowed.
  2. If developing rustc, inspect the src/target dep-node kinds of the reported edge and verify the query's TaskDeps/dep-graph ordering is correct.
  3. Reproduce minimally and file a rustc internal-compiler-error issue with the edge and the query call stack.
Defensive patterns

Strategy: validation

Validate before calling

// Before inserting a dependency edge, confirm the (from,to) pair is
// one the graph's policy actually permits.
fn assert_edge_allowed(
    g: &DepGraph,
    from: DepNodeIndex,
    to: DepNodeIndex,
) -> Result<(), String> {
    if g.is_edge_allowed(from, to) {
        Ok(())
    } else {
        Err(format!("forbidden edge {:?} -> {:?}", from, to))
    }
}

Type guard

fn is_allowed_edge(g: &DepGraph, from: DepNodeIndex, to: DepNodeIndex) -> bool {
    g.is_edge_allowed(from, to)
}

Prevention

When it happens

Trigger: Running a debug build of rustc (or a dev build with assertions on) where a query records a dependency the dep-graph model says must not exist — i.e. a compiler-internal bug in query dependency tracking. Never reached in release/user builds.

Common situations: Hacking on rustc itself with a debug build; running rustc tests under debug assertions; very rarely via a debug-built rustdoc or tool. End users on release builds never see it.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/06153050529c7436.json. Report an issue: GitHub.