Skip to content

Commit 4f76515

Browse files
committed
In ReadUserKeywordsHashNode check the hash matches the descriptor
1 parent 3d2603d commit 4f76515

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

src/main/java/org/truffleruby/language/arguments/ReadUserKeywordsHashNode.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,44 @@
1010
package org.truffleruby.language.arguments;
1111

1212
import org.truffleruby.core.hash.RubyHash;
13+
import org.truffleruby.core.hash.library.HashStoreLibrary;
14+
import org.truffleruby.core.symbol.RubySymbol;
1315
import org.truffleruby.language.RubyBaseNode;
1416

1517
import com.oracle.truffle.api.frame.VirtualFrame;
1618
import com.oracle.truffle.api.profiles.ConditionProfile;
1719

1820
public final class ReadUserKeywordsHashNode extends RubyBaseNode {
1921

20-
private final ConditionProfile keywordArgumentsProfile = ConditionProfile.create();
22+
@Child protected HashStoreLibrary hashStoreLibrary;
2123

22-
public ReadUserKeywordsHashNode() {
23-
}
24+
private final ConditionProfile keywordArgumentsProfile = ConditionProfile.create();
2425

2526
public RubyHash execute(VirtualFrame frame) {
2627
final ArgumentsDescriptor descriptor = RubyArguments.getDescriptor(frame);
2728
if (keywordArgumentsProfile.profile(descriptor instanceof KeywordArgumentsDescriptor)) {
2829
final RubyHash keywords = (RubyHash) RubyArguments.getLastArgument(frame);
2930
assert !keywords.empty();
31+
assert assertHashMatchesDescriptor(keywords, (KeywordArgumentsDescriptor) descriptor);
3032
return keywords;
3133
} else {
3234
return null;
3335
}
3436
}
37+
38+
/** Verify that all keywords the descriptor claims should be in the hash, are in fact in the hash. **/
39+
private boolean assertHashMatchesDescriptor(RubyHash hash, KeywordArgumentsDescriptor descriptor) {
40+
if (hashStoreLibrary == null) {
41+
hashStoreLibrary = insert(HashStoreLibrary.createDispatched());
42+
}
43+
44+
for (String keyword : descriptor.getKeywords()) {
45+
final RubySymbol symbol = getSymbol(keyword);
46+
final Object value = hashStoreLibrary.lookupOrDefault(hash.store, null, hash, symbol, (f, h, k) -> null);
47+
assert value != null : "descriptor claims " + keyword +
48+
" was a passed keyword argument but it's not in the hash";
49+
}
50+
return true;
51+
}
52+
3553
}

0 commit comments

Comments
 (0)