Skip to content

Commit

Permalink
[Truffle] Allow reopening of private module/classes when visible
Browse files Browse the repository at this point in the history
  • Loading branch information
pitr-ch committed Dec 4, 2016
1 parent 2fdd735 commit 2d33ba6
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 10 deletions.
4 changes: 0 additions & 4 deletions spec/truffle/tags/language/constants_tags.txt
@@ -1,7 +1,3 @@
fails:Constant resolution within a singleton class (class << obj) uses its own namespace for each object
fails:Constant resolution within a singleton class (class << obj) uses its own namespace for nested modules
fails:Constant resolution within a singleton class (class << obj) allows nested modules to have proper resolution
fails:Module#private_constant marked constants in a module can be reopened as a module where constant is not private
fails:Module#private_constant marked constants in a module can be reopened as a class where constant is not private
fails:Module#private_constant marked constants in a class can be reopened as a module where constant is not private
fails:Module#private_constant marked constants in a class can be reopened as a class where constant is not private
Expand Up @@ -10,6 +10,7 @@
package org.jruby.truffle.language.objects;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
Expand All @@ -23,6 +24,7 @@
import org.jruby.truffle.language.RubyConstant;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.WarnNode;
import org.jruby.truffle.language.arguments.RubyArguments;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.loader.RequireNode;

Expand All @@ -38,7 +40,9 @@ public abstract class LookupForExistingModuleNode extends RubyNode {
public RubyConstant lookupForExistingModule(VirtualFrame frame, String name, DynamicObject lexicalParent,
@Cached("createBinaryProfile()") ConditionProfile autoloadProfile,
@Cached("createBinaryProfile()") ConditionProfile warnProfile) {
RubyConstant constant = deepConstantSearch(name, lexicalParent);
final LexicalScope lexicalScope = RubyArguments.getMethod(frame).getSharedMethodInfo().getLexicalScope();
RubyConstant constant = deepConstantSearch(name,
lexicalScope, lexicalParent);

if (warnProfile.profile(constant != null && constant.isDeprecated())) {
warnDeprecatedConstant(frame, name);
Expand All @@ -55,7 +59,7 @@ public RubyConstant lookupForExistingModule(VirtualFrame frame, String name, Dyn

Layouts.MODULE.getFields(lexicalParent).removeConstant(getContext(), this, name);
getRequireNode().executeRequire(frame, StringOperations.getString((DynamicObject) constant.getValue()));
final RubyConstant autoConstant = deepConstantSearch(name, lexicalParent);
final RubyConstant autoConstant = deepConstantSearch(name, lexicalScope, lexicalParent);

if (warnProfile.profile(constant != null && constant.isDeprecated())) {
warnDeprecatedConstant(frame, name);
Expand All @@ -67,8 +71,8 @@ public RubyConstant lookupForExistingModule(VirtualFrame frame, String name, Dyn
return constant;
}

@CompilerDirectives.TruffleBoundary(throwsControlFlowException = true)
private RubyConstant deepConstantSearch(String name, DynamicObject lexicalParent) {
@TruffleBoundary(throwsControlFlowException = true)
private RubyConstant deepConstantSearch(String name, LexicalScope lexicalScope, DynamicObject lexicalParent) {
RubyConstant constant = Layouts.MODULE.getFields(lexicalParent).getConstant(name);

final DynamicObject objectClass = getContext().getCoreLibrary().getObjectClass();
Expand All @@ -83,8 +87,10 @@ private RubyConstant deepConstantSearch(String name, DynamicObject lexicalParent
}
}

if (constant != null && !constant.isVisibleTo(getContext(), LexicalScope.NONE, lexicalParent)) {
throw new RaiseException(getContext().getCoreExceptions().nameErrorPrivateConstant(lexicalParent, name, this));
if (constant != null && !(constant.isVisibleTo(getContext(), lexicalScope, lexicalScope.getLiveModule()) ||
constant.isVisibleTo(getContext(), LexicalScope.NONE, lexicalParent))) {
throw new RaiseException(getContext().getCoreExceptions().
nameErrorPrivateConstant(lexicalParent, name, this));
}

return constant;
Expand Down

0 comments on commit 2d33ba6

Please sign in to comment.