diff --git a/crates/ruff_linter/src/checkers/ast/mod.rs b/crates/ruff_linter/src/checkers/ast/mod.rs
index 53a51485635f43..d91dcc25f95248 100644
--- a/crates/ruff_linter/src/checkers/ast/mod.rs
+++ b/crates/ruff_linter/src/checkers/ast/mod.rs
@@ -588,8 +588,10 @@ impl<'a> Visitor<'a> for Checker<'a> {
             Stmt::Global(ast::StmtGlobal { names, range: _ }) => {
                 if !self.semantic.scope_id.is_global() {
                     for name in names {
-                        if let Some(binding_id) = self.semantic.global_scope().get(name) {
-                            // Mark the binding in the global scope as "rebound" in the current scope.
+                        let binding_id = self.semantic.global_scope().get(name);
+
+                        // Mark the binding in the global scope as "rebound" in the current scope.
+                        if let Some(binding_id) = binding_id {
                             self.semantic
                                 .add_rebinding_scope(binding_id, self.semantic.scope_id);
                         }
@@ -597,7 +599,7 @@ impl<'a> Visitor<'a> for Checker<'a> {
                         // Add a binding to the current scope.
                         let binding_id = self.semantic.push_binding(
                             name.range(),
-                            BindingKind::Global,
+                            BindingKind::Global(binding_id),
                             BindingFlags::GLOBAL,
                         );
                         let scope = self.semantic.current_scope_mut();
@@ -609,7 +611,8 @@ impl<'a> Visitor<'a> for Checker<'a> {
                 if !self.semantic.scope_id.is_global() {
                     for name in names {
                         if let Some((scope_id, binding_id)) = self.semantic.nonlocal(name) {
-                            // Mark the binding as "used".
+                            // Mark the binding as "used", since the `nonlocal` requires an existing
+                            // binding.
                             self.semantic.add_local_reference(
                                 binding_id,
                                 ExprContext::Load,
@@ -624,7 +627,7 @@ impl<'a> Visitor<'a> for Checker<'a> {
                             // Add a binding to the current scope.
                             let binding_id = self.semantic.push_binding(
                                 name.range(),
-                                BindingKind::Nonlocal(scope_id),
+                                BindingKind::Nonlocal(binding_id, scope_id),
                                 BindingFlags::NONLOCAL,
                             );
                             let scope = self.semantic.current_scope_mut();
diff --git a/crates/ruff_linter/src/renamer.rs b/crates/ruff_linter/src/renamer.rs
index 811493777cc750..153e94d0053d9b 100644
--- a/crates/ruff_linter/src/renamer.rs
+++ b/crates/ruff_linter/src/renamer.rs
@@ -125,8 +125,8 @@ impl Renamer {
         let scope_id = scope.get_all(name).find_map(|binding_id| {
             let binding = semantic.binding(binding_id);
             match binding.kind {
-                BindingKind::Global => Some(ScopeId::global()),
-                BindingKind::Nonlocal(symbol_id) => Some(symbol_id),
+                BindingKind::Global(_) => Some(ScopeId::global()),
+                BindingKind::Nonlocal(_, scope_id) => Some(scope_id),
                 _ => None,
             }
         });
@@ -266,8 +266,8 @@ impl Renamer {
             | BindingKind::LoopVar
             | BindingKind::ComprehensionVar
             | BindingKind::WithItemVar
-            | BindingKind::Global
-            | BindingKind::Nonlocal(_)
+            | BindingKind::Global(_)
+            | BindingKind::Nonlocal(_, _)
             | BindingKind::ClassDefinition(_)
             | BindingKind::FunctionDefinition(_)
             | BindingKind::Deletion
diff --git a/crates/ruff_linter/src/rules/pandas_vet/helpers.rs b/crates/ruff_linter/src/rules/pandas_vet/helpers.rs
index efcc6634a9c4a8..13259c2946e440 100644
--- a/crates/ruff_linter/src/rules/pandas_vet/helpers.rs
+++ b/crates/ruff_linter/src/rules/pandas_vet/helpers.rs
@@ -48,8 +48,8 @@ pub(super) fn test_expression(expr: &Expr, semantic: &SemanticModel) -> Resoluti
                         | BindingKind::NamedExprAssignment
                         | BindingKind::LoopVar
                         | BindingKind::ComprehensionVar
-                        | BindingKind::Global
-                        | BindingKind::Nonlocal(_) => Resolution::RelevantLocal,
+                        | BindingKind::Global(_)
+                        | BindingKind::Nonlocal(_, _) => Resolution::RelevantLocal,
                         BindingKind::Import(import)
                             if matches!(import.qualified_name().segments(), ["pandas"]) =>
                         {
diff --git a/crates/ruff_linter/src/rules/pylint/rules/non_ascii_name.rs b/crates/ruff_linter/src/rules/pylint/rules/non_ascii_name.rs
index 2023c58ad14a81..1aaff45b863abc 100644
--- a/crates/ruff_linter/src/rules/pylint/rules/non_ascii_name.rs
+++ b/crates/ruff_linter/src/rules/pylint/rules/non_ascii_name.rs
@@ -54,8 +54,8 @@ pub(crate) fn non_ascii_name(binding: &Binding, locator: &Locator) -> Option<Dia
         BindingKind::LoopVar => Kind::LoopVar,
         BindingKind::ComprehensionVar => Kind::ComprenhensionVar,
         BindingKind::WithItemVar => Kind::WithItemVar,
-        BindingKind::Global => Kind::Global,
-        BindingKind::Nonlocal(_) => Kind::Nonlocal,
+        BindingKind::Global(_) => Kind::Global,
+        BindingKind::Nonlocal(_, _) => Kind::Nonlocal,
         BindingKind::ClassDefinition(_) => Kind::ClassDefinition,
         BindingKind::FunctionDefinition(_) => Kind::FunctionDefinition,
         BindingKind::BoundException => Kind::BoundException,
diff --git a/crates/ruff_python_semantic/src/binding.rs b/crates/ruff_python_semantic/src/binding.rs
index 287fcc8627b2d9..67236682f9d30c 100644
--- a/crates/ruff_python_semantic/src/binding.rs
+++ b/crates/ruff_python_semantic/src/binding.rs
@@ -470,14 +470,14 @@ pub enum BindingKind<'a> {
     /// def foo():
     ///     global x
     /// ```
-    Global,
+    Global(Option<BindingId>),
 
     /// A binding for a nonlocal variable, like `x` in:
     /// ```python
     /// def foo():
     ///     nonlocal x
     /// ```
-    Nonlocal(ScopeId),
+    Nonlocal(BindingId, ScopeId),
 
     /// A binding for a builtin, like `print` or `bool`.
     Builtin,
@@ -670,3 +670,14 @@ impl<'a, 'ast> Imported<'ast> for AnyImport<'a, 'ast> {
         }
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use crate::BindingKind;
+
+    #[test]
+    #[cfg(target_pointer_width = "64")]
+    fn size() {
+        assert!(std::mem::size_of::<BindingKind>() <= 24);
+    }
+}
diff --git a/crates/ruff_python_semantic/src/model.rs b/crates/ruff_python_semantic/src/model.rs
index 5bfa87821c1a1a..e567a5e936f845 100644
--- a/crates/ruff_python_semantic/src/model.rs
+++ b/crates/ruff_python_semantic/src/model.rs
@@ -540,6 +540,23 @@ impl<'a> SemanticModel<'a> {
                         return ReadResult::Resolved(binding_id);
                     }
 
+                    BindingKind::Global(Some(binding_id))
+                    | BindingKind::Nonlocal(binding_id, _) => {
+                        // Mark the shadowed binding as used.
+                        let reference_id = self.resolved_references.push(
+                            self.scope_id,
+                            self.node_id,
+                            ExprContext::Load,
+                            self.flags,
+                            name.range,
+                        );
+                        self.bindings[binding_id].references.push(reference_id);
+
+                        // Treat it as resolved.
+                        self.resolved_names.insert(name.into(), binding_id);
+                        return ReadResult::Resolved(binding_id);
+                    }
+
                     _ => {
                         // Otherwise, treat it as resolved.
                         self.resolved_names.insert(name.into(), binding_id);