diff --git a/language/reserved_keywords.rb b/language/reserved_keywords.rb
new file mode 100644
index 000000000..ed0f851e1
--- /dev/null
+++ b/language/reserved_keywords.rb
@@ -0,0 +1,159 @@
+require_relative '../spec_helper'
+
+describe "Ruby's reserved keywords" do
+  # Copied from Prism::Translation::Ripper
+  keywords = %w[
+    alias
+    and
+    begin
+    BEGIN
+    break
+    case
+    class
+    def
+    defined?
+    do
+    else
+    elsif
+    end
+    END
+    ensure
+    false
+    for
+    if
+    in
+    module
+    next
+    nil
+    not
+    or
+    redo
+    rescue
+    retry
+    return
+    self
+    super
+    then
+    true
+    undef
+    unless
+    until
+    when
+    while
+    yield
+    __ENCODING__
+    __FILE__
+    __LINE__
+  ]
+
+  keywords.each do |kw|
+    describe "keyword '#{kw}'" do
+      it "can't be used as local variable name" do
+        -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
+            #{kw} = "a local variable named '#{kw}'"
+        RUBY
+      end
+
+      invalid_ivar_names = ["defined?"]
+
+      if invalid_ivar_names.include?(kw)
+        it "can't be used as an instance variable name" do
+          -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
+            @#{kw} = "an instance variable named '#{kw}'"
+          RUBY
+        end
+      else
+        it "can be used as an instance variable name" do
+          result = eval <<~RUBY
+            @#{kw} = "an instance variable named '#{kw}'"
+            @#{kw}
+          RUBY
+
+          result.should == "an instance variable named '#{kw}'"
+        end
+      end
+
+      invalid_class_var_names = ["defined?"]
+
+      if invalid_class_var_names.include?(kw)
+        it "can't be used as a class variable name" do
+          -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
+            class C
+              @@#{kw} = "a class variable named '#{kw}'"
+            end
+          RUBY
+        end
+      else
+        it "can be used as a class variable name" do
+          result = eval <<~RUBY
+            class C
+              @@#{kw} = "a class variable named '#{kw}'"
+              @@#{kw}
+            end
+          RUBY
+
+          result.should == "a class variable named '#{kw}'"
+        end
+      end
+
+      invalid_global_var_names = ["defined?"]
+
+      if invalid_global_var_names.include?(kw)
+        it "can't be used as a global variable name" do
+          -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
+            $#{kw} = "a global variable named '#{kw}'"
+          RUBY
+        end
+      else
+        it "can be used as a global variable name" do
+          result = eval <<~RUBY
+            $#{kw} = "a global variable named '#{kw}'"
+            $#{kw}
+          RUBY
+
+          result.should == "a global variable named '#{kw}'"
+        end
+      end
+
+      it "can't be used as a positional parameter name" do
+        -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
+          def x(#{kw}); end
+        RUBY
+      end
+
+      invalid_kw_param_names = ["BEGIN","END","defined?"]
+
+      if invalid_kw_param_names.include?(kw)
+        it "can't be used a keyword parameter name" do
+          -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
+            def self.m(#{kw}:); end
+          RUBY
+        end
+      else
+        it "can be used a keyword parameter name" do
+          result = eval <<~RUBY
+            def self.m(#{kw}:)
+              binding.local_variable_get(:#{kw})
+            end
+
+            m(#{kw}: "an argument to '#{kw}'")
+          RUBY
+
+          result.should == "an argument to '#{kw}'"
+        end
+      end
+
+      it "can be used as a method name" do
+        result = eval <<~RUBY
+          def self.#{kw}
+            "a method named '#{kw}'"
+          end
+
+          send(:#{kw})
+        RUBY
+
+        result.should == "a method named '#{kw}'"
+      end
+    end
+  end
+end
diff --git a/spec_helper.rb b/spec_helper.rb
index af1c38587..cfbbdfc38 100644
--- a/spec_helper.rb
+++ b/spec_helper.rb
@@ -36,3 +36,13 @@ def report_on_exception=(value)
   ARGV.unshift $0
   MSpecRun.main
 end
+
+# Evaluates the given Ruby source in a temporary Module, to prevent
+# the surrounding context from being polluted with the new methods.
+def sandboxed_eval(ruby_src)
+  Module.new do
+    # Allows instance methods defined by `ruby_src` to be called directly.
+    extend self
+  end
+  .class_eval(ruby_src)
+end