Skip to content

Interpreter: Circular require with glob pattern causes double evaluation of constants #16627

@cyangle

Description

@cyangle

Description
When using require "path/**" in combination with a circular require back to the file containing the glob, the interpreter appears to re-evaluate the required files, causing constants to be instantiated multiple times. This results in object identity mismatches where a constant and a reference to that constant (e.g., stored in a class variable) point to different object instances.

This behavior differs from the compiler, which correctly handles the circular dependency and ensures files are only evaluated once.

Reproduction Steps

Create the following file structure:

common.cr

# The entry point that uses a glob require
require "./lib/**"

lib/circular.cr

# This circular require, combined with the glob in common.cr, triggers the bug
require "../common"

lib/schema.cr

class Schema
  def initialize(@name : String)
  end
end

# This constant will be instantiated TWICE by the interpreter due to the bug
MyDB = Schema.new("db")

lib/model.cr

class Model
  @@schema : Schema?

  def self.set_schema(schema)
    @@schema = schema
  end

  def self.schema
    @@schema.not_nil!
  end
end

# At this point, MyDB might be a different instance than what main sees
Model.set_schema(MyDB)

repro.cr

require "./common"

puts "Checking object identity..."
puts "Constant (MyDB) object_id: #{MyDB.object_id}"
puts "Class Var (Model.schema) object_id: #{Model.schema.object_id}"

if MyDB.object_id != Model.schema.object_id
  puts "❌ BUG REPRODUCED: Objects are different!"
  exit 1
else
  puts "✅ SUCCESS: Objects are the same."
end

Expected Behavior (Compiler)
Running with crystal run repro.cr (or build):

Checking object identity...
Constant (MyDB) object_id: 132575200268192
Class Var (Model.schema) object_id: 132575200268192
✅ SUCCESS: Objects are the same.

Actual Behavior (Interpreter)
Running with crystal i repro.cr:

Checking object identity...
Constant (MyDB) object_id: 123345412094208
Class Var (Model.schema) object_id: 123345412094240
❌ BUG REPRODUCED: Objects are different!

Environment

  • Crystal version: 1.20.0-dev
  • OS: Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions