Skip to content

Commit 634c0ae

Browse files
committed
[GR-17457] Fix frozen check for attr_writer
PullRequest: truffleruby/2419
2 parents fbdf6a7 + 694f7c0 commit 634c0ae

File tree

4 files changed

+44
-15
lines changed

4 files changed

+44
-15
lines changed

spec/ruby/core/module/attr_accessor_spec.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,20 @@ class TrueClass
3333
attr_accessor :spec_attr_accessor
3434
end
3535

36-
-> { true.spec_attr_accessor = "a" }.should raise_error(RuntimeError)
36+
-> { true.spec_attr_accessor = "a" }.should raise_error(FrozenError)
37+
end
38+
39+
it "raises FrozenError if the receiver if frozen" do
40+
c = Class.new do
41+
attr_accessor :foo
42+
end
43+
obj = c.new
44+
obj.foo = 1
45+
obj.foo.should == 1
46+
47+
obj.freeze
48+
-> { obj.foo = 42 }.should raise_error(FrozenError)
49+
obj.foo.should == 1
3750
end
3851

3952
it "converts non string/symbol names to strings using to_str" do

spec/ruby/core/module/attr_writer_spec.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,17 @@ class TrueClass
2929
attr_writer :spec_attr_writer
3030
end
3131

32-
-> { true.spec_attr_writer = "a" }.should raise_error(RuntimeError)
32+
-> { true.spec_attr_writer = "a" }.should raise_error(FrozenError)
33+
end
34+
35+
it "raises FrozenError if the receiver if frozen" do
36+
c = Class.new do
37+
attr_writer :foo
38+
end
39+
obj = c.new
40+
obj.freeze
41+
42+
-> { obj.foo = 42 }.should raise_error(FrozenError)
3343
end
3444

3545
it "converts non string/symbol names to strings using to_str" do

src/main/java/org/truffleruby/language/objects/WriteInstanceVariableNode.java

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,17 @@
1919

2020
import com.oracle.truffle.api.CompilerDirectives;
2121
import com.oracle.truffle.api.frame.VirtualFrame;
22-
import com.oracle.truffle.api.profiles.ConditionProfile;
22+
import org.truffleruby.language.library.RubyLibrary;
2323

2424
public class WriteInstanceVariableNode extends RubyContextSourceNode implements AssignableNode {
2525

2626
private final String name;
2727

2828
@Child private RubyNode receiver;
29+
@Child private RubyLibrary rubyLibrary;
2930
@Child private RubyNode rhs;
3031
@Child private WriteObjectFieldNode writeNode;
3132

32-
private final ConditionProfile objectProfile = ConditionProfile.create();
33-
3433
public WriteInstanceVariableNode(String name, RubyNode receiver, RubyNode rhs) {
3534
this.name = name;
3635
this.receiver = receiver;
@@ -52,23 +51,31 @@ public void assign(VirtualFrame frame, Object value) {
5251
}
5352

5453
private void write(Object object, Object value) {
55-
if (objectProfile.profile(object instanceof RubyDynamicObject)) {
56-
if (writeNode == null) {
57-
CompilerDirectives.transferToInterpreterAndInvalidate();
58-
writeNode = insert(WriteObjectFieldNode.create());
59-
}
60-
61-
writeNode.execute((RubyDynamicObject) object, name, value);
62-
} else {
54+
if (getRubyLibrary().isFrozen(object)) {
6355
throw new RaiseException(getContext(), coreExceptions().frozenError(object, this));
6456
}
57+
58+
if (writeNode == null) {
59+
CompilerDirectives.transferToInterpreterAndInvalidate();
60+
writeNode = insert(WriteObjectFieldNode.create());
61+
}
62+
63+
writeNode.execute((RubyDynamicObject) object, name, value);
6564
}
6665

6766
@Override
6867
public Object isDefined(VirtualFrame frame, RubyLanguage language, RubyContext context) {
6968
return coreStrings().ASSIGNMENT.createInstance(context);
7069
}
7170

71+
private RubyLibrary getRubyLibrary() {
72+
if (rubyLibrary == null) {
73+
CompilerDirectives.transferToInterpreterAndInvalidate();
74+
rubyLibrary = insert(RubyLibrary.getFactory().createDispatched(getRubyLibraryCacheLimit()));
75+
}
76+
return rubyLibrary;
77+
}
78+
7279
@Override
7380
public AssignableNode toAssignableNode() {
7481
this.rhs = null;

src/main/java/org/truffleruby/parser/BodyTranslator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,8 +1916,7 @@ public RubyNode visitInstAsgnNode(InstAsgnParseNode node) {
19161916
rhs = node.getValueNode().accept(this);
19171917
}
19181918

1919-
RubyNode self = new SelfNode(environment.getFrameDescriptor());
1920-
self = TypeNodes.CheckFrozenNode.create(self);
1919+
final RubyNode self = new SelfNode(environment.getFrameDescriptor());
19211920
final RubyNode ret = new WriteInstanceVariableNode(name, self, rhs);
19221921
ret.unsafeSetSourceSection(sourceSection);
19231922
return addNewlineIfNeeded(node, ret);

0 commit comments

Comments
 (0)