Skip to content

JRuby 9.1.0.0 define_method creates private methods in some cases where it should create public methods #3854

@jeremyevans

Description

@jeremyevans

Environment

Happens on both OpenBSD/amd64 and Windows, and I'm guessing affects all environments:

jruby 9.1.0.0 (2.3.0) 2016-05-02 a633c63 OpenJDK 64-Bit Server VM 25.72-b15 on 1.8.0_72-b15 +jit [OpenBSD-x86_64]
jruby 9.1.0.0 (2.3.0) 2016-05-02 a633c63 Java HotSpot(TM) 64-Bit Server VM 25.45-b02 on 1.8.0_45-b15 +jit [mswin32-x86_64]

Expected Behavior

$ jruby -e 'Object.send(:define_method, :a){1}; p Object.new.a'
1

Actual Behavior

$ jruby -e 'Object.send(:define_method, :a){1}; p Object.new.a'
NoMethodError: private method `a' called for #<Object:0x6e6c3152>
  <top> at -e:1

For reference:

$ ruby -ve 'Object.send(:define_method, :a){1}; p Object.new.a'
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-openbsd]
1

I believe ruby 2.3's define_method visibility is as follows:

  1. Private/Protected if define_method called inside a class/module definition after the private/protected keyword with the current class/module as the receiver .
  2. Public in all other cases.

This bug broke Sequel's connection pool specs.

If you want some useful test cases across different ruby versions, here you go:

$ for x in 18 19 20 21 22 23; do ruby$x -ve "class A; private; define_method(:a){1} end; p A.new.a"; done
ruby 1.8.7 (2013-06-27 patchlevel 374) [x86_64-openbsd]
-e:1: private method `a' called for #<A:0x1d46bffebc58> (NoMethodError)
ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-openbsd]
1
ruby 2.0.0p648 (2015-12-16 revision 53162) [x86_64-openbsd]
1
ruby 2.1.9p490 (2016-03-30 revision 54437) [x86_64-openbsd]
-e:1:in `<main>': private method `a' called for #<A:0x000f8255434d88> (NoMethodError)
ruby 2.2.5p319 (2016-04-26 revision 54774) [x86_64-openbsd]
-e:1:in `<main>': private method `a' called for #<A:0x0013bf54e5ea58> (NoMethodError)
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-openbsd]
-e:1:in `<main>': private method `a' called for #<A:0x000263d55ab1b8> (NoMethodError)

$ for x in 18 19 20 21 22 23; do ruby$x -ve "class A; protected; define_method(:a){1} end; p A.new.a"; done
ruby 1.8.7 (2013-06-27 patchlevel 374) [x86_64-openbsd]
-e:1: protected method `a' called for #<A:0x1d15870b1c60> (NoMethodError)
ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-openbsd]
1
ruby 2.0.0p648 (2015-12-16 revision 53162) [x86_64-openbsd]
1
ruby 2.1.9p490 (2016-03-30 revision 54437) [x86_64-openbsd]
-e:1:in `<main>': protected method `a' called for #<A:0x0019c33114f038> (NoMethodError)
ruby 2.2.5p319 (2016-04-26 revision 54774) [x86_64-openbsd]
-e:1:in `<main>': protected method `a' called for #<A:0x00095082494a40> (NoMethodError)
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-openbsd]
-e:1:in `<main>': protected method `a' called for #<A:0x0003f211243518> (NoMethodError)

$ for x in 18 19 20 21 22 23; do ruby$x -ve "class A; public; define_method(:a){1} end; p A.new.a"; done
ruby 1.8.7 (2013-06-27 patchlevel 374) [x86_64-openbsd]
1
ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-openbsd]
1
ruby 2.0.0p648 (2015-12-16 revision 53162) [x86_64-openbsd]
1
ruby 2.1.9p490 (2016-03-30 revision 54437) [x86_64-openbsd]
1
ruby 2.2.5p319 (2016-04-26 revision 54774) [x86_64-openbsd]
1
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-openbsd]
1

$ for x in 18 19 20 21 22 23; do ruby$x -ve "class A; private; A.send(:define_method, :a){1} end; p A.new.a"; done
ruby 1.8.7 (2013-06-27 patchlevel 374) [x86_64-openbsd]
-e:1: private method `a' called for #<A:0x16d03fa44bd0> (NoMethodError)
ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-openbsd]
1
ruby 2.0.0p648 (2015-12-16 revision 53162) [x86_64-openbsd]
1
ruby 2.1.9p490 (2016-03-30 revision 54437) [x86_64-openbsd]
-e:1:in `<main>': private method `a' called for #<A:0x00129e7b09e170> (NoMethodError)
ruby 2.2.5p319 (2016-04-26 revision 54774) [x86_64-openbsd]
-e:1:in `<main>': private method `a' called for #<A:0x000dad300e6c90> (NoMethodError)
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-openbsd]
-e:1:in `<main>': private method `a' called for #<A:0x000e91347b4b60> (NoMethodError)


$ for x in 18 19 20 21 22 23; do ruby$x -ve "Object.send(:define_method, :a){1}; p Object.new.a"; done
ruby 1.8.7 (2013-06-27 patchlevel 374) [x86_64-openbsd]
-e:1: private method `a' called for #<Object:0x18f26eebce08> (NoMethodError)
ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-openbsd]
1
ruby 2.0.0p648 (2015-12-16 revision 53162) [x86_64-openbsd]
1
ruby 2.1.9p490 (2016-03-30 revision 54437) [x86_64-openbsd]
1
ruby 2.2.5p319 (2016-04-26 revision 54774) [x86_64-openbsd]
1
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-openbsd]
1

$ for x in 18 19 20 21 22 23; do ruby$x -ve "a = Object.new; (class << a; self end).send(:define_method, :a){1}; p a.a"; done
ruby 1.8.7 (2013-06-27 patchlevel 374) [x86_64-openbsd]
1
ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-openbsd]
1
ruby 2.0.0p648 (2015-12-16 revision 53162) [x86_64-openbsd]
1
ruby 2.1.9p490 (2016-03-30 revision 54437) [x86_64-openbsd]
1
ruby 2.2.5p319 (2016-04-26 revision 54774) [x86_64-openbsd]
1
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-openbsd]
1

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions