From fa3071e4ee70a2b83120ffc8dccf6f482d04358a Mon Sep 17 00:00:00 2001 From: "Thomas E. Enebo" Date: Thu, 15 Feb 2024 13:28:25 -0500 Subject: [PATCH 1/4] Implement RuntimeError for overtaken cvars --- core/src/main/java/org/jruby/RubyModule.java | 6 ++++++ spec/tags/ruby/language/class_variable_tags.txt | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) delete mode 100644 spec/tags/ruby/language/class_variable_tags.txt diff --git a/core/src/main/java/org/jruby/RubyModule.java b/core/src/main/java/org/jruby/RubyModule.java index f58e3a8720b..7ed85c73c71 100644 --- a/core/src/main/java/org/jruby/RubyModule.java +++ b/core/src/main/java/org/jruby/RubyModule.java @@ -4602,13 +4602,19 @@ public IRubyObject getClassVarQuiet(String name) { assert IdUtil.isClassVariable(name); RubyModule module = this; RubyModule highest = null; + RubyModule lowest = null; do { if (module.hasClassVariable(name)) { highest = module; + if (lowest == null) lowest = module; } } while ((module = module.getSuperClass()) != null); + if (lowest != highest) { + throw getRuntime().newRuntimeError(str(getRuntime(), "class variable " + name + " of ", lowest, " is overtaken by ", highest)); + } + if (highest != null) return highest.fetchClassVariable(name); return null; diff --git a/spec/tags/ruby/language/class_variable_tags.txt b/spec/tags/ruby/language/class_variable_tags.txt deleted file mode 100644 index 8960545d44f..00000000000 --- a/spec/tags/ruby/language/class_variable_tags.txt +++ /dev/null @@ -1 +0,0 @@ -fails:Accessing a class variable raises a RuntimeError when a class variable is overtaken in an ancestor class From ed320c73484e44ef260bd7da4402907ecd286ad1 Mon Sep 17 00:00:00 2001 From: "Thomas E. Enebo" Date: Wed, 6 Mar 2024 15:56:29 -0500 Subject: [PATCH 2/4] Fixed some stuff but not enough --- core/src/main/java/org/jruby/RubyModule.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/jruby/RubyModule.java b/core/src/main/java/org/jruby/RubyModule.java index b6c25c111b5..ab45036d286 100644 --- a/core/src/main/java/org/jruby/RubyModule.java +++ b/core/src/main/java/org/jruby/RubyModule.java @@ -4619,7 +4619,13 @@ public IRubyObject getClassVarQuiet(String name) { } while ((module = module.getSuperClass()) != null); if (lowest != highest) { - throw getRuntime().newRuntimeError(str(getRuntime(), "class variable " + name + " of ", lowest, " is overtaken by ", highest)); + if (lowest.getOrigin().getRealModule() != highest.getOrigin().getRealModule()) { + throw getRuntime().newRuntimeError(str(getRuntime(), "class variable " + name + " of ", lowest, " is overtaken by ", highest)); + } + /* + if (!(lowest instanceof IncludedModule || lowest instanceof PrependedModule)) { + lowest.removeClassVariable(name); + }*/ } if (highest != null) return highest.fetchClassVariable(name); From 1e4bed1df1131072877ff8d990696a620da78229 Mon Sep 17 00:00:00 2001 From: "Thomas E. Enebo" Date: Tue, 30 Apr 2024 11:30:04 -0400 Subject: [PATCH 3/4] I think this will fix specs but this is probably underspecified so likely not totally right --- core/src/main/java/org/jruby/RubyModule.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/jruby/RubyModule.java b/core/src/main/java/org/jruby/RubyModule.java index ab45036d286..594751b900f 100644 --- a/core/src/main/java/org/jruby/RubyModule.java +++ b/core/src/main/java/org/jruby/RubyModule.java @@ -4619,8 +4619,10 @@ public IRubyObject getClassVarQuiet(String name) { } while ((module = module.getSuperClass()) != null); if (lowest != highest) { - if (lowest.getOrigin().getRealModule() != highest.getOrigin().getRealModule()) { - throw getRuntime().newRuntimeError(str(getRuntime(), "class variable " + name + " of ", lowest, " is overtaken by ", highest)); + if (!highest.isPrepended()) { + if (lowest.getOrigin().getRealModule() != highest.getOrigin().getRealModule()) { + throw getRuntime().newRuntimeError(str(getRuntime(), "class variable " + name + " of ", types(getRuntime(), lowest.getOrigin().getRealModule()), " is overtaken by ", types(getRuntime(), highest.getRealModule()))); + } } /* if (!(lowest instanceof IncludedModule || lowest instanceof PrependedModule)) { From 85ab4ab4316cdcebebd7a3b1a56e267247bbb580 Mon Sep 17 00:00:00 2001 From: "Thomas E. Enebo" Date: Tue, 30 Apr 2024 13:05:17 -0400 Subject: [PATCH 4/4] Introduce removal of cvars from classes when mismatched. Correct error to print out correct names when erroring --- core/src/main/java/org/jruby/RubyModule.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/jruby/RubyModule.java b/core/src/main/java/org/jruby/RubyModule.java index 594751b900f..8b9e026087e 100644 --- a/core/src/main/java/org/jruby/RubyModule.java +++ b/core/src/main/java/org/jruby/RubyModule.java @@ -4621,13 +4621,13 @@ public IRubyObject getClassVarQuiet(String name) { if (lowest != highest) { if (!highest.isPrepended()) { if (lowest.getOrigin().getRealModule() != highest.getOrigin().getRealModule()) { - throw getRuntime().newRuntimeError(str(getRuntime(), "class variable " + name + " of ", types(getRuntime(), lowest.getOrigin().getRealModule()), " is overtaken by ", types(getRuntime(), highest.getRealModule()))); + throw getRuntime().newRuntimeError(str(getRuntime(), "class variable " + name + " of ", + lowest.getOrigin(), " is overtaken by ", highest.getOrigin())); } + + if (lowest.isClass()) lowest.removeClassVariable(name); } - /* - if (!(lowest instanceof IncludedModule || lowest instanceof PrependedModule)) { - lowest.removeClassVariable(name); - }*/ + } if (highest != null) return highest.fetchClassVariable(name);