diff --git a/.rubocop_rspec_base.yml b/.rubocop_rspec_base.yml
index 3b202c05ac..90bfed89ad 100644
--- a/.rubocop_rspec_base.yml
+++ b/.rubocop_rspec_base.yml
@@ -1,4 +1,4 @@
-# This file was generated on 2018-04-05T18:41:15+10:00 from the rspec-dev repo.
+# This file was generated on 2019-07-24T15:33:48+02:00 from the rspec-dev repo.
 # DO NOT modify it by hand as your changes will get lost the next time it is generated.
 
 # This file contains defaults for RSpec projects. Individual projects
diff --git a/.travis.yml b/.travis.yml
index 8a3ebf0d00..3234a82a6c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,15 +1,15 @@
-# This file was generated on 2018-04-05T18:41:15+10:00 from the rspec-dev repo.
+# This file was generated on 2019-07-24T15:33:48+02:00 from the rspec-dev repo.
 # DO NOT modify it by hand as your changes will get lost the next time it is generated.
 
+# In order to install old Rubies, we need to use old Ubuntu distibution.
+dist: trusty
 language: ruby
-sudo: false
 email: false
 cache:
   directories:
     - ../bundle
 before_install:
-  - gem update --system # https://github.com/travis-ci/travis-ci/issues/8978#issuecomment-354036443
-  - gem install bundler
+  - "script/update_rubygems_and_install_bundler"
   - unset _JAVA_OPTIONS
   - "script/clone_all_rspec_repos"
 bundler_args: "--binstubs --standalone --without documentation --path ../bundle"
@@ -21,9 +21,10 @@ rvm:
   - 2.0.0
   - 2.1
   - 2.2.10
-  - 2.3.7
-  - 2.4.4
-  - 2.5.1
+  - 2.3.8
+  - 2.4.6
+  - 2.5.5
+  - 2.6.2
   - ruby-head
   - ree
   - rbx-3
@@ -40,7 +41,6 @@ matrix:
     - rvm: jruby-head
     - rvm: ruby-head
     - rvm: rbx-3
-    - rvm: ruby-2.6.0-preview1
   fast_finish: true
 branches:
   only:
diff --git a/BUILD_DETAIL.md b/BUILD_DETAIL.md
index d11034aa88..6089b8d067 100644
--- a/BUILD_DETAIL.md
+++ b/BUILD_DETAIL.md
@@ -40,7 +40,7 @@ The spec suite performs a couple extra checks that are worth noting:
   available for use in any context, we want to minimize how many bits of the standard
   library we load and use. Otherwise, RSpec's use of part of the standard library could
   mask a problem where a gem author forgets to load a part of the standard library they
-  rely on. The spec suite contains a spec that defines a whitelist of allowed loaded
+  rely on. The spec suite contains a spec that defines a list of allowed loaded
   stdlibs.
 
 In addition, we use [SimpleCov](https://github.com/colszowka/simplecov)
diff --git a/Changelog.md b/Changelog.md
index b394573338..4ec1b85d3a 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,47 @@
+### 3.9.0 / 2019-10-07
+[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.8.2...v3.9.0)
+
+Enhancements:
+* Improve the handling of errors during loading support files, if a file
+  errors before loading specs, RSpec will now skip loading the specs.
+  (David Rodríguez, #2568)
+* Add support for --example-matches to run examples by regular expression.
+  (Sam Joseph, Matt Rider, @okothkongo1, #2586)
+* Add `did_you_mean` suggestions for file names encountering a `LoadError`
+  outside of examples. (@obromios, #2601)
+* Add a minimalist quick fix style formatter, only outputs failures as
+  `file:line:message`. (Romain Tartière, #2614)
+* Convert string number values to integer when used for `RSpec::Configuration#fail_fast`
+  (Viktor Fonic, #2634)
+* Issue warning when invalid values are used for `RSpec::Configuration#fail_fast`
+  (Viktor Fonic, #2634)
+* Add support for running the Rake task in a clean environment.
+  (Jon Rowe, #2632)
+* Indent messages by there example group / example in the documentation formatter.
+  (Samuel Williams, #2649)
+
+### 3.8.2 / 2019-06-29
+[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.8.1...v3.8.2)
+
+Bug Fixes:
+
+* Fix `config.define_derived_metadata` so that cascades are not triggered
+  until metadata has been assigned to the example or example group
+  (Myron Marston, #2635).
+
+### 3.8.1 / 2019-06-13
+[Full Changelog](http://github.com/rspec/rspec-core/compare/v3.8.0...v3.8.1)
+
+Bug Fixes:
+
+* Handle RSpec description(s) with japanese chars in CP932 encoded files.
+  (Benoit Tigeot, #2575)
+* When defining `let` methods that overwrite an existing method, prevent
+  a warning being issued by removing the old definition. (Jon Rowe, #2593)
+* Prevent warning on Ruby 2.6.0-rc1 (Keiji Yoshimi, #2582)
+* Fix `config.define_derived_metadata` so that it supports cascades.
+  (Myron Marston, #2630).
+
 ### 3.8.0 / 2018-08-04
 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.7.1...v3.8.0)
 
diff --git a/Gemfile b/Gemfile
index bf9c3ca4cc..b6618befeb 100644
--- a/Gemfile
+++ b/Gemfile
@@ -32,14 +32,27 @@ if RUBY_VERSION < '2.0.0' || RUBY_ENGINE == 'java'
   gem 'json', '< 2.0.0'
 end
 
-if RUBY_VERSION < '2.0.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/)
-  gem 'ffi', '< 1.9.15' # allow ffi to be installed on older rubies on windows
-elsif RUBY_VERSION < '1.9'
+if RUBY_VERSION < '2.2.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/)
+  gem 'ffi', '< 1.10'
+elsif RUBY_VERSION < '2.0'
   gem 'ffi', '< 1.9.19' # ffi dropped Ruby 1.8 support in 1.9.19
+else
+  gem 'ffi', '~> 1.11.0'
+end
+
+if RUBY_VERSION < '2.2.0' && !!(RbConfig::CONFIG['host_os'] =~ /cygwin|mswin|mingw|bccwin|wince|emx/)
+  gem "childprocess", "< 1.0.0"
 end
 
 platforms :jruby do
-  gem "jruby-openssl"
+  if RUBY_VERSION < '1.9.0'
+    # Pin jruby-openssl on older J Ruby
+    gem "jruby-openssl", "< 0.10.0"
+    # Pin child-process on older J Ruby
+    gem "childprocess", "< 1.0.0"
+  else
+    gem "jruby-openssl"
+  end
 end
 
 gem 'simplecov', '~> 0.8'
@@ -51,4 +64,12 @@ end
 
 gem 'test-unit', '~> 3.0' if RUBY_VERSION.to_f >= 2.2
 
+# Version 5.12 of minitest requires Ruby 2.4
+if RUBY_VERSION < '2.4.0'
+  gem 'minitest', '< 5.12.0'
+end
+
+
+gem 'contracts', '< 0.16' if RUBY_VERSION < '1.9.0'
+
 eval File.read('Gemfile-custom') if File.exist?('Gemfile-custom')
diff --git a/README.md b/README.md
index 6093066873..16edc3a8c7 100644
--- a/README.md
+++ b/README.md
@@ -19,20 +19,6 @@ RSpec repos as well. Add the following to your `Gemfile`:
 end
 ```
 
-## Contributing
-
-Once you've set up the environment, you'll need to cd into the working
-directory of whichever repo you want to work in. From there you can run the
-specs and cucumber features, and make patches.
-
-NOTE: You do not need to use rspec-dev to work on a specific RSpec repo. You
-can treat each RSpec repo as an independent project.
-
-* [Build details](BUILD_DETAIL.md)
-* [Code of Conduct](CODE_OF_CONDUCT.md)
-* [Detailed contributing guide](CONTRIBUTING.md)
-* [Development setup guide](DEVELOPMENT.md)
-
 ## Basic Structure
 
 RSpec uses the words "describe" and "it" so we can express concepts like a conversation:
@@ -67,7 +53,7 @@ context of an _instance_ of that class.
 
 ## Nested Groups
 
-You can also declare nested nested groups using the `describe` or `context`
+You can also declare nested groups using the `describe` or `context`
 methods:
 
 ```ruby
@@ -376,6 +362,20 @@ Finished in 0.000379 seconds
 1 example, 0 failures
 ```
 
+## Contributing
+
+Once you've set up the environment, you'll need to cd into the working
+directory of whichever repo you want to work in. From there you can run the
+specs and cucumber features, and make patches.
+
+NOTE: You do not need to use rspec-dev to work on a specific RSpec repo. You
+can treat each RSpec repo as an independent project.
+
+* [Build details](BUILD_DETAIL.md)
+* [Code of Conduct](CODE_OF_CONDUCT.md)
+* [Detailed contributing guide](CONTRIBUTING.md)
+* [Development setup guide](DEVELOPMENT.md)
+
 ## Also see
 
 * [https://github.com/rspec/rspec](https://github.com/rspec/rspec)
diff --git a/appveyor.yml b/appveyor.yml
index b8001cfa3f..09b2eef238 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-# This file was generated on 2018-04-05T18:41:15+10:00 from the rspec-dev repo.
+# This file was generated on 2019-07-24T15:33:48+02:00 from the rspec-dev repo.
 # DO NOT modify it by hand as your changes will get lost the next time it is generated.
 
 version: "{build}"
@@ -33,9 +33,10 @@ test_script:
 
 environment:
   matrix:
-    - ruby_version: 193
     - ruby_version: 200
     - ruby_version: 21
     - ruby_version: 22
     - ruby_version: 23-x64
     - ruby_version: 24-x64
+    - ruby_version: 25-x64
+    - ruby_version: 26-x64
diff --git a/features/README.md b/features/README.md
index a18810863e..1169a54fe2 100644
--- a/features/README.md
+++ b/features/README.md
@@ -1,6 +1,6 @@
 rspec-core provides the structure for RSpec code examples:
 
-    describe Account do
+    RSpec.describe Account do
       it "has a balance of zero when first opened" do
         # example code goes here - for more on the
         # code inside the examples, see rspec-expectations
diff --git a/features/command_line/example_matches_name_option.feature b/features/command_line/example_matches_name_option.feature
new file mode 100644
index 0000000000..de80b3cf30
--- /dev/null
+++ b/features/command_line/example_matches_name_option.feature
@@ -0,0 +1,131 @@
+Feature: `--example-matches` option
+
+  Use the `--example-matches` (or `-E`) option to filter examples by name using REGEX.
+
+  The argument is matched against the full description of the example, which is
+  the concatenation of descriptions of the group (including any nested groups)
+  and the example.
+
+  This allows you to run a single uniquely named example, all examples with
+  similar names, all the examples in a uniquely named group, etc, etc.
+
+  You can also use the option more than once to specify multiple example
+  matches.
+
+  Note: description-less examples that have generated descriptions (typical when using the [one-liner syntax](../subject/one-liner-syntax)) cannot be directly filtered with this option, because it is necessary to execute the example to generate the description, so RSpec is unable to use the not-yet-generated description to decide whether or not to execute an example. You can, of course, pass part of a group's description to select all examples defined in the group (including those that have no description).
+
+  Background:
+    Given a file named "first_spec.rb" with:
+      """ruby
+      RSpec.describe "first group" do
+        it "first" do; end
+        it "first example in first group" do; end
+        it "second example in first group" do; end
+      end
+      """
+    And a file named "second_spec.rb" with:
+      """ruby
+      RSpec.describe "second group" do
+        it "first example in second group" do; end
+        it "second example in second group" do; end
+      end
+      """
+    And a file named "third_spec.rb" with:
+      """ruby
+      RSpec.describe "third group" do
+        it "first example in third group" do; end
+        context "group of nest" do
+          it "first example in nested group" do; end
+          it "second example in nested group" do; end
+          it "third example in nested_group with underscore" do; end
+        end
+      end
+      """
+    And a file named "fourth_spec.rb" with:
+      """ruby
+      RSpec.describe Array do
+        describe "#length" do
+          it "is the number of items" do
+            expect(Array.new([1,2,3]).length).to eq 3
+          end
+        end
+      end
+      """
+
+  Scenario: No matches
+    When I run `rspec . --example-matches nothing_like_this`
+    Then the process should succeed even though no examples were run
+
+  Scenario: Match on one word
+    When I run `rspec . --example-matches example`
+    Then the examples should all pass
+
+  Scenario: One match in each context
+    When I run `rspec . --example-matches 'first example'`
+    Then the examples should all pass
+
+  Scenario: One match in one file using just the example name
+    When I run `rspec . --example-matches 'first example in first group'`
+    Then the examples should all pass
+
+  Scenario: One match in one file using the example name and the group name
+    When I run `rspec . --example-matches 'first group first example in first group'`
+    Then the examples should all pass
+
+  Scenario: All examples in one group
+    When I run `rspec . --example-matches 'first group'`
+    Then the examples should all pass
+
+  Scenario: One match in one file with group name
+    When I run `rspec . --example-matches 'second group first example'`
+    Then the examples should all pass
+
+  Scenario: All examples in one group including examples in nested groups
+    When I run `rspec . --example-matches 'third group'`
+    Then the examples should all pass
+
+  Scenario: Match using `ClassName#method_name` form
+    When I run `rspec . --example-matches 'Array#length'`
+    Then the examples should all pass
+
+  Scenario: Match only matching regex
+    When I run `rspec . --example-matches "first$" --format d`
+    Then the examples should all pass
+    And the output should contain all of these:
+      | first |
+    And the output should not contain any of these:
+      | first example in first group                |
+      | second example in first group               |
+      | first example in second group               |
+      | second example in second group              |
+      | first example in third group                |
+      | nested group first example in nested group  |
+      | nested group second example in nested group |
+
+  # https://regex101.com/r/RABd8Q/2
+  Scenario: Match only matching regex with word boundarries
+    When I run `rspec . --example-matches "nested[^_]" --format d`
+    Then the examples should all pass
+    And the output should contain all of these:
+      | first example in nested group  |
+      | second example in nested group |
+    And the output should not contain any of these:
+      | first example in first group   |
+      | second example in first group  |
+      | first example in second group  |
+      | second example in second group |
+      | first example in third group   |
+      | third example in nested_group  |
+
+  Scenario: Multiple applications of example name option
+    When I run `rspec . --example-matches 'first group' --example-matches 'second group' --format d`
+    Then the examples should all pass
+    And the output should contain all of these:
+      | first example in first group   |
+      | second example in first group  |
+      | first example in second group  |
+      | second example in second group |
+    And the output should not contain any of these:
+      | first example in third group                |
+      | nested group first example in nested group  |
+      | nested group second example in nested group |
diff --git a/features/command_line/line_number_appended_to_path.feature b/features/command_line/line_number_appended_to_path.feature
index 32b70f2311..8ba778a143 100644
--- a/features/command_line/line_number_appended_to_path.feature
+++ b/features/command_line/line_number_appended_to_path.feature
@@ -155,5 +155,5 @@ Feature: line number appended to file path
   Scenario: Matching one-liners
     When I run `rspec one_liner_spec.rb:3 --format doc`
     Then the examples should all pass
-    Then the output should contain "should be > 8"
-    But the output should not contain "should be < 10"
+    Then the output should contain "is expected to be > 8"
+    But the output should not contain "is expected to be < 10"
diff --git a/features/command_line/tag.feature b/features/command_line/tag.feature
index 1f819392f4..2c74c1d0e9 100644
--- a/features/command_line/tag.feature
+++ b/features/command_line/tag.feature
@@ -17,7 +17,8 @@ Feature: `--tag` option
   `:name => 'bar'`.
 
   To be compatible with the Cucumber syntax, tags can optionally start with an
-  `@` symbol, which will be ignored.
+  `@` symbol, which will be ignored as part of the tag, e.g. `--tag @focus` is
+  treated the same as `--tag focus` and is expanded to `:focus => true`.
 
   Background:
     Given a file named "tagged_spec.rb" with:
diff --git a/features/example_groups/shared_context.feature b/features/example_groups/shared_context.feature
index 61f64ecb44..7bea9c31d4 100644
--- a/features/example_groups/shared_context.feature
+++ b/features/example_groups/shared_context.feature
@@ -133,7 +133,7 @@ Feature: shared context
           expect(shared_method).to eq("it works")
         end
 
-        it "inherits metadata form the included context due to the matching metadata", :include_shared => true do |ex|
+        it "inherits metadata from the included context due to the matching metadata", :include_shared => true do |ex|
           expect(ex.metadata).to include(:shared_context => :metadata)
         end
       end
diff --git a/features/formatters/configurable_colors.feature b/features/formatters/configurable_colors.feature
index 2a3d4ce822..366ad461d9 100644
--- a/features/formatters/configurable_colors.feature
+++ b/features/formatters/configurable_colors.feature
@@ -12,7 +12,7 @@ Feature: Configurable colors
   Colors are specified as symbols. Options are `:black`, `:red`, `:green`,
   `:yellow`, `:blue`, `:magenta`, `:cyan`, and `:white`.
 
-  @ansi
+  @keep-ansi-escape-sequences
   Scenario: Customizing the failure color
     Given a file named "custom_failure_color_spec.rb" with:
       """ruby
diff --git a/features/hooks/around_hooks.feature b/features/hooks/around_hooks.feature
index 99a76d9224..748210c938 100644
--- a/features/hooks/around_hooks.feature
+++ b/features/hooks/around_hooks.feature
@@ -17,6 +17,9 @@ Feature: `around` hooks
   **WARNING:** Mock frameworks are set up and torn down within the context of
   running the example. You cannot interact with them directly in `around` hooks.
 
+  **WARNING:** `around` hooks will execute *after* any `before` hooks, and *before*
+  any `after` hooks regardless of the context they were defined in.
+
   Scenario: Use the example as a proc within the block passed to `around()`
     Given a file named "example_spec.rb" with:
       """ruby
diff --git a/features/hooks/before_and_after_hooks.feature b/features/hooks/before_and_after_hooks.feature
index c1c9159e67..6110a9819e 100644
--- a/features/hooks/before_and_after_hooks.feature
+++ b/features/hooks/before_and_after_hooks.feature
@@ -29,6 +29,9 @@ Feature: `before` and `after` hooks
 
   **WARNING:** Mocks are only supported in `before(:example)`.
 
+  **WARNING:** `around` hooks will execute *after* any `before` hooks, and *before*
+  any `after` hooks regardless of the context they were defined in.
+
   Note: the `:example` and `:context` scopes are also available as `:each` and
   `:all`, respectively. Use whichever you prefer.
 
diff --git a/features/metadata/described_class.feature b/features/metadata/described_class.feature
index 3a4c176cdd..b494f5d4d6 100644
--- a/features/metadata/described_class.feature
+++ b/features/metadata/described_class.feature
@@ -1,17 +1,20 @@
 Feature: described class
 
-  If the first argument to the outermost example group is a class, the class is
-  exposed to each example via the `described_class()` method.
+  If the first argument to an example group is a class, the class is exposed to
+  each example in that example group via the `described_class()` method.
 
   Scenario: Access the described class from the example
     Given a file named "spec/example_spec.rb" with:
       """ruby
       RSpec.describe Fixnum do
-        it "is available as described_class" do
-          expect(described_class).to eq(Fixnum)
+        describe 'inner' do
+          describe String do
+            it "is available as described_class" do
+              expect(described_class).to eq(String)
+            end
+          end
         end
       end
       """
     When I run `rspec spec/example_spec.rb`
     Then the example should pass
-
diff --git a/features/step_definitions/additional_cli_steps.rb b/features/step_definitions/additional_cli_steps.rb
index e041899e34..0a63b62fda 100644
--- a/features/step_definitions/additional_cli_steps.rb
+++ b/features/step_definitions/additional_cli_steps.rb
@@ -4,7 +4,7 @@
 
 Then /^the output should contain all of these:$/ do |table|
   table.raw.flatten.each do |string|
-    assert_partial_output(string, all_output)
+    expect(all_output).to include(string)
   end
 end
 
@@ -28,11 +28,6 @@
   step %q{the exit status should be 0}
 end
 
-Then /^it should pass with "(.*?)"$/ do |string|
-  step %Q{the output should contain "#{string}"}
-  step %q{the exit status should be 0}
-end
-
 Then /^the example(?:s)? should(?: all)? fail$/ do
   step %q{the output should not contain "0 examples"}
   step %q{the output should not contain "0 failures"}
@@ -98,24 +93,23 @@
 end
 
 Given /^I have a brand new project with no files$/ do
-  in_current_dir do
+  cd('.') do
     expect(Dir["**/*"]).to eq([])
   end
 end
 
 Given /^I have run `([^`]*)`$/ do |cmd|
-  fail_on_error = true
-  run_simple(unescape(cmd), fail_on_error)
+  run_command_and_stop(sanitize_text(cmd), :fail_on_error => true)
 end
 
 Given(/^a vendored gem named "(.*?)" containing a file named "(.*?)" with:$/) do |gem_name, file_name, file_contents|
   gem_dir = "vendor/#{gem_name}-1.2.3"
   step %Q{a file named "#{gem_dir}/#{file_name}" with:}, file_contents
-  set_env('RUBYOPT', ENV['RUBYOPT'] + " -I#{gem_dir}/lib")
+  set_environment_variable('RUBYOPT', ENV['RUBYOPT'] + " -I#{gem_dir}/lib")
 end
 
 When "I accept the recommended settings by removing `=begin` and `=end` from `spec/spec_helper.rb`" do
-  in_current_dir do
+  cd('.') do
     spec_helper = File.read("spec/spec_helper.rb")
     expect(spec_helper).to include("=begin", "=end")
 
@@ -138,7 +132,7 @@
 end
 
 When(/^I fix "(.*?)" by replacing "(.*?)" with "(.*?)"$/) do |file_name, original, replacement|
-  in_current_dir do
+  cd('.') do
     contents = File.read(file_name)
     expect(contents).to include(original)
     fixed = contents.sub(original, replacement)
@@ -146,12 +140,8 @@
   end
 end
 
-Then(/^it should fail with "(.*?)"$/) do |snippet|
-  assert_failing_with(snippet)
-end
-
 Given(/^I have not configured `example_status_persistence_file_path`$/) do
-  in_current_dir do
+  cd('.') do
     return unless File.exist?("spec/spec_helper.rb")
     return unless File.read("spec/spec_helper.rb").include?("example_status_persistence_file_path")
     File.open("spec/spec_helper.rb", "w") { |f| f.write("") }
@@ -173,10 +163,10 @@
 end
 
 Then(/^bisect should (succeed|fail) with output like:$/) do |succeed, expected_output|
-  last_process = only_processes.last
+  last_process = all_commands.last
   expected_status = succeed == "succeed" ? 0 : 1
-  expect(last_exit_status).to eq(expected_status),
-    "Expected exit status of #{expected_status} but got #{last_exit_status} \n\n" \
+  expect(last_process.exit_status).to eq(expected_status),
+    "Expected exit status of #{expected_status} but got #{last_process.exit_status} \n\n" \
     "Output:\n\n#{last_process.stdout}"
 
   expected = normalize_durations(expected_output)
@@ -191,7 +181,7 @@
 end
 
 When(/^I run `([^`]+)` and abort in the middle with ctrl\-c$/) do |cmd|
-  set_env('RUBYOPT', ENV['RUBYOPT'] + " -r#{File.expand_path("../../support/send_sigint_during_bisect.rb", __FILE__)}")
+  set_environment_variable('RUBYOPT', ENV['RUBYOPT'] + " -r#{File.expand_path("../../support/send_sigint_during_bisect.rb", __FILE__)}")
   step "I run `#{cmd}`"
 end
 
@@ -218,19 +208,21 @@
   # - "Nested" group listed (it should be the outer group)
   # - The example group class name is listed (it should be the location)
 
-  expect(all_output).not_to match(/nested/i)
-  expect(all_output).not_to match(/inf/i)
-  expect(all_output).not_to match(/\b0 examples/i)
+  output = all_output
+
+  expect(output).not_to match(/nested/i)
+  expect(output).not_to match(/inf/i)
+  expect(output).not_to match(/\b0 examples/i)
 
   seconds = '\d+(?:\.\d+)? seconds'
 
-  expect(all_output).to match(
+  expect(output).to match(
     %r{Top 1 slowest example groups?:\n\s+slow before context hook\n\s+#{seconds} average \(#{seconds} / 1 example\) \./spec/example_spec\.rb:1}
   )
 end
 
 Given(/^I have changed `([^`]+)` to `([^`]+)` in "(.*?)"$/) do |old_code, new_code, file_name|
-  in_current_dir do
+  cd('.') do
     file_content = File.read(file_name)
     expect(file_content).to include(old_code)
     new_file_content = file_content.sub(old_code, new_code)
diff --git a/features/step_definitions/core_standalone_steps.rb b/features/step_definitions/core_standalone_steps.rb
index f847cb8575..60669883fd 100644
--- a/features/step_definitions/core_standalone_steps.rb
+++ b/features/step_definitions/core_standalone_steps.rb
@@ -2,13 +2,13 @@
   if RUBY_VERSION.to_f >= 1.9 # --disable-gems is invalid on 1.8.7
     # Ensure the gem versions of rspec-mocks and rspec-expectations
     # won't be loaded if available on the developers machine.
-    set_env('RUBYOPT', ENV['RUBYOPT'] + ' --disable-gems')
+    set_environment_variable('RUBYOPT', ENV['RUBYOPT'] + ' --disable-gems')
   end
 
   # This will make `require_expect_syntax_in_aruba_specs.rb` (loaded
   # automatically when the specs run) remove rspec-mocks and
   # rspec-expectations from the load path.
-  set_env('REMOVE_OTHER_RSPEC_LIBS_FROM_LOAD_PATH', 'true')
+  set_environment_variable('REMOVE_OTHER_RSPEC_LIBS_FROM_LOAD_PATH', 'true')
 end
 
 Given(/^rspec-expectations is not installed$/) do
diff --git a/features/subject/implicit_subject.feature b/features/subject/implicit_subject.feature
index 2d46929783..8e6c333fc0 100644
--- a/features/subject/implicit_subject.feature
+++ b/features/subject/implicit_subject.feature
@@ -1,7 +1,8 @@
 Feature: implicitly defined subject
 
-  If the first argument to the outermost example group is a class, an instance
-  of that class is exposed to each example via the `subject` method.
+  If the first argument to an example group is a class, an instance of that
+  class is exposed to each example in that example group via the `subject`
+  method.
 
   While the examples below demonstrate how `subject` can be used as a
   user-facing concept, we recommend that you reserve it for support of custom
diff --git a/features/subject/one_liner_syntax.feature b/features/subject/one_liner_syntax.feature
index d8a1d0e150..70a2df876b 100644
--- a/features/subject/one_liner_syntax.feature
+++ b/features/subject/one_liner_syntax.feature
@@ -46,8 +46,8 @@ Feature: One-liner syntax
        """
        Array
          when first created
-           should be empty
-           should be empty
+           is expected to be empty
+           is expected to be empty
        """
 
   Scenario: Explicit subject
@@ -68,6 +68,6 @@ Feature: One-liner syntax
        """
        Array
          with 3 items
-           should not be empty
-           should not be empty
+           is expected not to be empty
+           is expected not to be empty
        """
diff --git a/features/support/env.rb b/features/support/env.rb
index 3484b775c0..01400a3f67 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -2,7 +2,7 @@
 
 Before do
   # Force ids to be printed unquoted for consistency
-  set_env('SHELL', '/usr/bin/bash')
+  set_environment_variable('SHELL', '/usr/bin/bash')
 
   if RUBY_PLATFORM =~ /java/ || defined?(Rubinius)
     @aruba_timeout_seconds = 120
@@ -12,13 +12,21 @@
 end
 
 Aruba.configure do |config|
-  config.before_cmd do |cmd|
-    set_env('JRUBY_OPTS', "-X-C #{ENV['JRUBY_OPTS']}") # disable JIT since these processes are so short lived
+  config.before(:command) do |cmd|
+    set_environment_variable('JRUBY_OPTS', "-X-C #{ENV['JRUBY_OPTS']}") # disable JIT since these processes are so short lived
   end
 end if RUBY_PLATFORM == 'java'
 
 Aruba.configure do |config|
-  config.before_cmd do |cmd|
-    set_env('RBXOPT', "-Xint=true #{ENV['RBXOPT']}") # disable JIT since these processes are so short lived
+  config.before(:command) do |cmd|
+    set_environment_variable('RBXOPT', "-Xint=true #{ENV['RBXOPT']}") # disable JIT since these processes are so short lived
   end
 end if defined?(Rubinius)
+
+module ArubaHelpers
+  def all_output
+    all_commands.map { |c| c.output }.join("\n")
+  end
+end
+
+World(ArubaHelpers)
diff --git a/features/support/require_expect_syntax_in_aruba_specs.rb b/features/support/require_expect_syntax_in_aruba_specs.rb
index e37958d94c..5bd2519093 100644
--- a/features/support/require_expect_syntax_in_aruba_specs.rb
+++ b/features/support/require_expect_syntax_in_aruba_specs.rb
@@ -1,11 +1,11 @@
 if defined?(Cucumber)
   require 'shellwords'
   Before('~@allow-should-syntax', '~@with-clean-spec-opts') do
-    set_env('SPEC_OPTS', "-r#{Shellwords.escape(__FILE__)}")
+    set_environment_variable('SPEC_OPTS', "-r#{Shellwords.escape(__FILE__)}")
   end
 
   Before('@oneliner-should') do
-    set_env('ALLOW_ONELINER_SHOULD', 'true')
+    set_environment_variable('ALLOW_ONELINER_SHOULD', 'true')
   end
 else
   if ENV['REMOVE_OTHER_RSPEC_LIBS_FROM_LOAD_PATH']
diff --git a/lib/rspec/core.rb b/lib/rspec/core.rb
index f492a21f0b..2f10014b2e 100644
--- a/lib/rspec/core.rb
+++ b/lib/rspec/core.rb
@@ -139,6 +139,7 @@ def self.world
   module Core
     autoload :ExampleStatusPersister, "rspec/core/example_status_persister"
     autoload :Profiler,               "rspec/core/profiler"
+    autoload :DidYouMean,             "rspec/core/did_you_mean"
 
     # @private
     # This avoids issues with reporting time caused by examples that
diff --git a/lib/rspec/core/bisect/server.rb b/lib/rspec/core/bisect/server.rb
index 7db9adf42a..73f02998cf 100644
--- a/lib/rspec/core/bisect/server.rb
+++ b/lib/rspec/core/bisect/server.rb
@@ -33,7 +33,7 @@ def capture_run_results(files_or_directories_to_run=[], expected_failures=[])
 
         def start
           # Only allow remote DRb requests from this machine.
-          DRb.install_acl ACL.new(%w[ deny all allow localhost allow 127.0.0.1 ])
+          DRb.install_acl ACL.new(%w[ deny all allow localhost allow 127.0.0.1 allow ::1 ])
 
           # We pass `nil` as the first arg to allow it to pick a DRb port.
           @drb = DRb.start_service(nil, self)
diff --git a/lib/rspec/core/configuration.rb b/lib/rspec/core/configuration.rb
index 89caeccbcb..8bc099ce2b 100644
--- a/lib/rspec/core/configuration.rb
+++ b/lib/rspec/core/configuration.rb
@@ -202,10 +202,33 @@ def only_failures_but_not_configured?
         only_failures? && !example_status_persistence_file_path
       end
 
-      # @macro add_setting
+      # @macro define_reader
       # If specified, indicates the number of failures required before cleaning
-      # up and exit (default: `nil`).
-      add_setting :fail_fast
+      # up and exit (default: `nil`). Can also be `true` to fail and exit on first
+      # failure
+      define_reader :fail_fast
+
+      # @see fail_fast
+      def fail_fast=(value)
+        case value
+        when true, 'true'
+          @fail_fast = true
+        when false, 'false', 0
+          @fail_fast = false
+        when nil
+          @fail_fast = nil
+        else
+          @fail_fast = value.to_i
+
+          if value.to_i == 0
+            # TODO: in RSpec 4, consider raising an error here.
+            RSpec.warning "Cannot set `RSpec.configuration.fail_fast`" \
+              " to `#{value.inspect}`. Only `true`, `false`, `nil` and integers" \
+              " are valid values."
+            @fail_fast = true
+          end
+        end
+      end
 
       # @macro add_setting
       # Prints the formatter output of your suite without running any
@@ -1106,7 +1129,7 @@ def spec_files_with_failures
       #
       #   # This lets you do this:
       #
-      #   describe Thing do
+      #   RSpec.describe Thing do
       #     pending "does something" do
       #       thing = Thing.new
       #     end
@@ -1114,7 +1137,7 @@ def spec_files_with_failures
       #
       #   # ... which is the equivalent of
       #
-      #   describe Thing do
+      #   RSpec.describe Thing do
       #     it "does something", :pending => true do
       #       thing = Thing.new
       #     end
@@ -1167,7 +1190,7 @@ def alias_example_group_to(new_name, *args)
       #
       #   # allows the user to include a shared example group like:
       #
-      #   describe Entity do
+      #   RSpec.describe Entity do
       #     it_has_behavior 'sortability' do
       #       let(:sortable) { Entity.new }
       #     end
@@ -1718,7 +1741,7 @@ def raise_on_warning=(value)
       #     rspec.expose_current_running_example_as :example
       #   end
       #
-      #   describe MyClass do
+      #   RSpec.describe MyClass do
       #     before do
       #       # `example` can be used here because of the above config.
       #       do_something if example.metadata[:type] == "foo"
@@ -1855,9 +1878,28 @@ def when_first_matching_example_defined(*filters)
 
       # @private
       def apply_derived_metadata_to(metadata)
-        @derived_metadata_blocks.items_for(metadata).each do |block|
-          block.call(metadata)
+        already_run_blocks = Set.new
+
+        # We loop and attempt to re-apply metadata blocks to support cascades
+        # (e.g. where a derived bit of metadata triggers the application of
+        # another piece of derived metadata, etc)
+        #
+        # We limit our looping to 200 times as a way to detect infinitely recursing derived metadata blocks.
+        # It's hard to imagine a valid use case for a derived metadata cascade greater than 200 iterations.
+        200.times do
+          return if @derived_metadata_blocks.items_for(metadata).all? do |block|
+            already_run_blocks.include?(block).tap do |skip_block|
+              block.call(metadata) unless skip_block
+              already_run_blocks << block
+            end
+          end
         end
+
+        # If we got here, then `@derived_metadata_blocks.items_for(metadata).all?` never returned
+        # `true` above and we treat this as an attempt to recurse infinitely. It's better to fail
+        # with a clear # error than hang indefinitely, which is what would happen if we didn't limit
+        # the looping above.
+        raise SystemStackError, "Attempted to recursively derive metadata indefinitely."
       end
 
       # Defines a `before` hook. See {Hooks#before} for full docs.
@@ -2032,6 +2074,11 @@ def bisect_runner_class
 
       def load_file_handling_errors(method, file)
         __send__(method, file)
+      rescue LoadError => ex
+        relative_file = Metadata.relative_path(file)
+        suggestions = DidYouMean.new(relative_file).call
+        reporter.notify_non_example_exception(ex, "An error occurred while loading #{relative_file}.#{suggestions}")
+        RSpec.world.wants_to_quit = true
       rescue Support::AllExceptionsExceptOnesWeMustNotRescue => ex
         relative_file = Metadata.relative_path(file)
         reporter.notify_non_example_exception(ex, "An error occurred while loading #{relative_file}.")
diff --git a/lib/rspec/core/did_you_mean.rb b/lib/rspec/core/did_you_mean.rb
new file mode 100644
index 0000000000..07daea966d
--- /dev/null
+++ b/lib/rspec/core/did_you_mean.rb
@@ -0,0 +1,46 @@
+module RSpec
+  module Core
+    # @private
+    # Wrapper around Ruby's `DidYouMean::SpellChecker` when available to provide file name suggestions.
+    class DidYouMean
+      attr_reader :relative_file_name
+
+      def initialize(relative_file_name)
+        @relative_file_name = relative_file_name
+      end
+
+      if defined?(::DidYouMean::SpellChecker)
+        # provide probable suggestions
+        def call
+          checker = ::DidYouMean::SpellChecker.new(:dictionary => Dir["spec/**/*.rb"])
+          probables = checker.correct(relative_file_name.sub('./', ''))[0..2]
+          return '' unless probables.any?
+
+          formats probables
+        end
+      else
+        # return a hint if API for ::DidYouMean::SpellChecker not supported
+        def call
+          "\nHint: Install the `did_you_mean` gem in order to provide suggestions for similarly named files."
+        end
+      end
+
+      private
+
+      def formats(probables)
+        rspec_format = probables.map { |s, _| "rspec ./#{s}" }
+        red_font(top_and_tail rspec_format)
+      end
+
+      def top_and_tail(rspec_format)
+        spaces = ' ' * 20
+        rspec_format.insert(0, ' - Did you mean?').join("\n#{spaces}") + "\n"
+      end
+
+      def red_font(mytext)
+        colorizer = ::RSpec::Core::Formatters::ConsoleCodes
+        colorizer.wrap mytext, :failure
+      end
+    end
+  end
+end
diff --git a/lib/rspec/core/example.rb b/lib/rspec/core/example.rb
index e4706aea52..ffa54a5ca7 100644
--- a/lib/rspec/core/example.rb
+++ b/lib/rspec/core/example.rb
@@ -203,10 +203,13 @@ def initialize(example_group_class, description, user_metadata, example_block=ni
           description, example_block
         )
 
+        config = RSpec.configuration
+        config.apply_derived_metadata_to(@metadata)
+
         # This should perhaps be done in `Metadata::ExampleHash.create`,
         # but the logic there has no knowledge of `RSpec.world` and we
         # want to keep it that way. It's easier to just assign it here.
-        @metadata[:last_run_status] = RSpec.configuration.last_run_statuses[id]
+        @metadata[:last_run_status] = config.last_run_statuses[id]
 
         @example_group_instance = @exception = nil
         @clock = RSpec::Core::Time
diff --git a/lib/rspec/core/example_group.rb b/lib/rspec/core/example_group.rb
index 3bd48b170e..05f4fa7596 100644
--- a/lib/rspec/core/example_group.rb
+++ b/lib/rspec/core/example_group.rb
@@ -7,7 +7,7 @@ module Core
     # ExampleGroup and {Example} are the main structural elements of
     # rspec-core. Consider this example:
     #
-    #     describe Thing do
+    #     RSpec.describe Thing do
     #       it "does something" do
     #       end
     #     end
@@ -90,7 +90,7 @@ def self.description
       # Returns the class or module passed to the `describe` method (or alias).
       # Returns nil if the subject is not a class or module.
       # @example
-      #     describe Thing do
+      #     RSpec.describe Thing do
       #       it "does something" do
       #         described_class == Thing
       #       end
@@ -424,11 +424,15 @@ def self.set_it_up(description, args, registration_collection, &example_group_bl
           superclass.method(:next_runnable_index_for),
           description, *args, &example_group_block
         )
+
+        config = RSpec.configuration
+        config.apply_derived_metadata_to(@metadata)
+
         ExampleGroups.assign_const(self)
 
         @currently_executing_a_context_hook = false
 
-        RSpec.configuration.configure_group(self)
+        config.configure_group(self)
       end
 
       # @private
diff --git a/lib/rspec/core/formatters.rb b/lib/rspec/core/formatters.rb
index bc51b6d27b..7a412a1a1c 100644
--- a/lib/rspec/core/formatters.rb
+++ b/lib/rspec/core/formatters.rb
@@ -74,6 +74,7 @@ module RSpec::Core::Formatters
   autoload :JsonFormatter,            'rspec/core/formatters/json_formatter'
   autoload :BisectDRbFormatter,       'rspec/core/formatters/bisect_drb_formatter'
   autoload :ExceptionPresenter,       'rspec/core/formatters/exception_presenter'
+  autoload :FailureListFormatter,     'rspec/core/formatters/failure_list_formatter'
 
   # Register the formatter class
   # @param formatter_class [Class] formatter class to register
@@ -212,6 +213,8 @@ def built_in_formatter(key)
         JsonFormatter
       when 'bisect-drb'
         BisectDRbFormatter
+      when 'f', 'failures'
+        FailureListFormatter
       end
     end
 
diff --git a/lib/rspec/core/formatters/documentation_formatter.rb b/lib/rspec/core/formatters/documentation_formatter.rb
index 263c64a6db..f64919c29c 100644
--- a/lib/rspec/core/formatters/documentation_formatter.rb
+++ b/lib/rspec/core/formatters/documentation_formatter.rb
@@ -6,12 +6,19 @@ module Core
     module Formatters
       # @private
       class DocumentationFormatter < BaseTextFormatter
-        Formatters.register self, :example_group_started, :example_group_finished,
+        Formatters.register self, :example_started, :example_group_started, :example_group_finished,
                             :example_passed, :example_pending, :example_failed
 
         def initialize(output)
           super
           @group_level = 0
+
+          @example_running = false
+          @messages = []
+        end
+
+        def example_started(_notification)
+          @example_running = true
         end
 
         def example_group_started(notification)
@@ -27,19 +34,44 @@ def example_group_finished(_notification)
 
         def example_passed(passed)
           output.puts passed_output(passed.example)
+
+          flush_messages
+          @example_running = false
         end
 
         def example_pending(pending)
           output.puts pending_output(pending.example,
                                      pending.example.execution_result.pending_message)
+
+          flush_messages
+          @example_running = false
         end
 
         def example_failed(failure)
           output.puts failure_output(failure.example)
+
+          flush_messages
+          @example_running = false
+        end
+
+        def message(notification)
+          if @example_running
+            @messages << notification.message
+          else
+            output.puts "#{current_indentation}#{notification.message}"
+          end
         end
 
       private
 
+        def flush_messages
+          @messages.each do |message|
+            output.puts "#{current_indentation(1)}#{message}"
+          end
+
+          @messages.clear
+        end
+
         def passed_output(example)
           ConsoleCodes.wrap("#{current_indentation}#{example.description.strip}", :success)
         end
@@ -61,8 +93,8 @@ def next_failure_index
           @next_failure_index += 1
         end
 
-        def current_indentation
-          '  ' * @group_level
+        def current_indentation(offset=0)
+          '  ' * (@group_level + offset)
         end
       end
     end
diff --git a/lib/rspec/core/formatters/exception_presenter.rb b/lib/rspec/core/formatters/exception_presenter.rb
index 155c99702c..9ad6503e17 100644
--- a/lib/rspec/core/formatters/exception_presenter.rb
+++ b/lib/rspec/core/formatters/exception_presenter.rb
@@ -81,7 +81,7 @@ def fully_formatted(failure_number, colorizer=::RSpec::Core::Formatters::Console
 
         def fully_formatted_lines(failure_number, colorizer)
           lines = [
-            description,
+            encoded_description(description),
             detail_formatter.call(example, colorizer),
             formatted_message_and_backtrace(colorizer),
             extra_detail_formatter.call(failure_number, colorizer),
@@ -244,6 +244,17 @@ def formatted_message_and_backtrace(colorizer)
           end
         end
 
+        if  String.method_defined?(:encoding)
+          def encoded_description(description)
+            return if description.nil?
+            encoded_string(description)
+          end
+        else # for 1.8.7
+          def encoded_description(description)
+            description
+          end
+        end
+
         def exception_backtrace
           exception.backtrace || []
         end
diff --git a/lib/rspec/core/formatters/failure_list_formatter.rb b/lib/rspec/core/formatters/failure_list_formatter.rb
new file mode 100644
index 0000000000..a071dfe82f
--- /dev/null
+++ b/lib/rspec/core/formatters/failure_list_formatter.rb
@@ -0,0 +1,23 @@
+RSpec::Support.require_rspec_core "formatters/base_formatter"
+
+module RSpec
+  module Core
+    module Formatters
+      # @private
+      class FailureListFormatter < BaseFormatter
+        Formatters.register self, :example_failed, :dump_profile, :message
+
+        def example_failed(failure)
+          output.puts "#{failure.example.location}:#{failure.example.description}"
+        end
+
+        # Discard profile and messages
+        #
+        # These outputs are not really relevant in the context of this failure
+        # list formatter.
+        def dump_profile(_profile); end
+        def message(_message); end
+      end
+    end
+  end
+end
diff --git a/lib/rspec/core/hooks.rb b/lib/rspec/core/hooks.rb
index a5024ce57b..56c0be852d 100644
--- a/lib/rspec/core/hooks.rb
+++ b/lib/rspec/core/hooks.rb
@@ -60,7 +60,8 @@ module Hooks
       #     before(:example)  # Declared in the current group.
       #
       # If more than one `before` is declared within any one scope, they are run
-      # in the order in which they are declared.
+      # in the order in which they are declared. Any `around` hooks will execute
+      # later than any `before` hook regardless of scope.
       #
       # ### Conditions
       #
@@ -74,11 +75,11 @@ module Hooks
       #       end
       #     end
       #
-      #     describe Something, :authorized => true do
+      #     RSpec.describe Something, :authorized => true do
       #       # The before hook will run in before each example in this group.
       #     end
       #
-      #     describe SomethingElse do
+      #     RSpec.describe SomethingElse do
       #       it "does something", :authorized => true do
       #         # The before hook will run before this example.
       #       end
@@ -159,7 +160,7 @@ module Hooks
       #
       # @example before(:example) declared in an {ExampleGroup}
       #
-      #     describe Thing do
+      #     RSpec.describe Thing do
       #       before(:example) do
       #         @thing = Thing.new
       #       end
@@ -171,7 +172,7 @@ module Hooks
       #
       # @example before(:context) declared in an {ExampleGroup}
       #
-      #     describe Parser do
+      #     RSpec.describe Parser do
       #       before(:context) do
       #         File.open(file_to_parse, 'w') do |f|
       #           f.write <<-CONTENT
@@ -261,7 +262,8 @@ def prepend_before(*args, &block)
       #
       # This is the reverse of the order in which `before` hooks are run.
       # Similarly, if more than one `after` is declared within any one scope,
-      # they are run in reverse order of that in which they are declared.
+      # they are run in reverse order of that in which they are declared. Also
+      # `around` hooks will all have run before any after hooks are invoked.
       #
       # @note The `:example` and `:context` scopes are also available as
       #       `:each` and `:all`, respectively. Use whichever you prefer.
@@ -329,6 +331,12 @@ def append_after(*args, &block)
       #     around(:example) {|ex| Database.transaction(&ex)}
       #     around(:example) {|ex| FakeFS(&ex)}
       #
+      # ### Order
+      #
+      # All `around` hooks execute immediately surrounding an example, this means
+      # that all `before` hooks will have run and no `after` hooks will have run yet.
+      #
+      # They are not a synonym for `before`/`after`.
       def around(*args, &block)
         hooks.register :prepend, :around, *args, &block
       end
diff --git a/lib/rspec/core/memoized_helpers.rb b/lib/rspec/core/memoized_helpers.rb
index 7875989648..771c12d716 100644
--- a/lib/rspec/core/memoized_helpers.rb
+++ b/lib/rspec/core/memoized_helpers.rb
@@ -10,7 +10,7 @@ module MemoizedHelpers
       # @note `subject` was contributed by Joe Ferris to support the one-liner
       #   syntax embraced by shoulda matchers:
       #
-      #       describe Widget do
+      #       RSpec.describe Widget do
       #         it { is_expected.to validate_presence_of(:name) }
       #         # or
       #         it { should validate_presence_of(:name) }
@@ -23,7 +23,7 @@ module MemoizedHelpers
       # @example
       #
       #   # Explicit declaration of subject.
-      #   describe Person do
+      #   RSpec.describe Person do
       #     subject { Person.new(:birthdate => 19.years.ago) }
       #     it "should be eligible to vote" do
       #       subject.should be_eligible_to_vote
@@ -32,7 +32,7 @@ module MemoizedHelpers
       #   end
       #
       #   # Implicit subject => { Person.new }.
-      #   describe Person do
+      #   RSpec.describe Person do
       #     it "should be eligible to vote" do
       #       subject.should be_eligible_to_vote
       #       # ^ ^ explicit reference to subject not recommended
@@ -40,7 +40,7 @@ module MemoizedHelpers
       #   end
       #
       #   # One-liner syntax - expectation is set on the subject.
-      #   describe Person do
+      #   RSpec.describe Person do
       #     it { is_expected.to be_eligible_to_vote }
       #     # or
       #     it { should be_eligible_to_vote }
@@ -67,7 +67,7 @@ def subject
       #
       # @example
       #
-      #   describe Person do
+      #   RSpec.describe Person do
       #     it { should be_eligible_to_vote }
       #   end
       #
@@ -86,7 +86,7 @@ def should(matcher=nil, message=nil)
       #
       # @example
       #
-      #   describe Person do
+      #   RSpec.describe Person do
       #     it { should_not be_eligible_to_vote }
       #   end
       #
@@ -270,7 +270,7 @@ module ClassMethods
         #
         # @example
         #
-        #   describe Thing do
+        #   RSpec.describe Thing do
         #     let(:thing) { Thing.new }
         #
         #     it "does something" do
@@ -288,7 +288,26 @@ def let(name, &block)
           raise(
             "#let or #subject called with a reserved name #initialize"
           ) if :initialize == name
-          MemoizedHelpers.module_for(self).__send__(:define_method, name, &block)
+          our_module = MemoizedHelpers.module_for(self)
+
+          # If we have a module clash in our helper module
+          # then we need to remove it to prevent a warning.
+          #
+          # Note we do not check ancestor modules (see: `instance_methods(false)`)
+          # as we can override them.
+          if our_module.instance_methods(false).include?(name)
+            our_module.__send__(:remove_method, name)
+          end
+          our_module.__send__(:define_method, name, &block)
+
+          # If we have a module clash in the example module
+          # then we need to remove it to prevent a warning.
+          #
+          # Note we do not check ancestor modules (see: `instance_methods(false)`)
+          # as we can override them.
+          if instance_methods(false).include?(name)
+            remove_method(name)
+          end
 
           # Apply the memoization. The method has been defined in an ancestor
           # module so we can use `super` here to get the value.
@@ -323,7 +342,7 @@ def let(name, &block)
         #     end
         #   end
         #
-        #   describe Thing do
+        #   RSpec.describe Thing do
         #     after(:example) { Thing.reset_count }
         #
         #     context "using let" do
@@ -379,13 +398,13 @@ def let!(name, &block)
         #
         # @example
         #
-        #   describe CheckingAccount, "with $50" do
+        #   RSpec.describe CheckingAccount, "with $50" do
         #     subject { CheckingAccount.new(Money.new(50, :USD)) }
         #     it { is_expected.to have_a_balance_of(Money.new(50, :USD)) }
         #     it { is_expected.not_to be_overdrawn }
         #   end
         #
-        #   describe CheckingAccount, "with a non-zero starting balance" do
+        #   RSpec.describe CheckingAccount, "with a non-zero starting balance" do
         #     subject(:account) { CheckingAccount.new(Money.new(50, :USD)) }
         #     it { is_expected.not_to be_overdrawn }
         #     it "has a balance equal to the starting balance" do
@@ -433,7 +452,7 @@ def subject(name=nil, &block)
         #     end
         #   end
         #
-        #   describe Thing do
+        #   RSpec.describe Thing do
         #     after(:example) { Thing.reset_count }
         #
         #     context "using subject" do
diff --git a/lib/rspec/core/metadata.rb b/lib/rspec/core/metadata.rb
index 5b1044db7b..5e0d7e2bdb 100644
--- a/lib/rspec/core/metadata.rb
+++ b/lib/rspec/core/metadata.rb
@@ -7,7 +7,7 @@ module Core
     # In addition to metadata that is used internally, this also stores
     # user-supplied metadata, e.g.
     #
-    #     describe Something, :type => :ui do
+    #     RSpec.describe Something, :type => :ui do
     #       it "does something", :slow => true do
     #         # ...
     #       end
@@ -136,7 +136,6 @@ def populate
 
           populate_location_attributes
           metadata.update(user_metadata)
-          RSpec.configuration.apply_derived_metadata_to(metadata)
         end
 
       private
@@ -169,7 +168,7 @@ def file_path_and_line_number_from(backtrace)
         end
 
         def description_separator(parent_part, child_part)
-          if parent_part.is_a?(Module) && child_part =~ /^(#|::|\.)/
+          if parent_part.is_a?(Module) && /^(?:#|::|\.)/.match(child_part.to_s)
             ''.freeze
           else
             ' '.freeze
diff --git a/lib/rspec/core/option_parser.rb b/lib/rspec/core/option_parser.rb
index fd2e645b22..8855f3f8ab 100644
--- a/lib/rspec/core/option_parser.rb
+++ b/lib/rspec/core/option_parser.rb
@@ -37,6 +37,7 @@ def parse(source=nil)
     # rubocop:disable Metrics/AbcSize
     # rubocop:disable CyclomaticComplexity
     # rubocop:disable PerceivedComplexity
+    # rubocop:disable Metrics/BlockLength
     def parser(options)
       OptionParser.new do |parser|
         parser.summary_width = 34
@@ -111,6 +112,7 @@ def parser(options)
                   '  [d]ocumentation (group and example names)',
                   '  [h]tml',
                   '  [j]son',
+                  '  [f]ailures ("file:line:reason", suitable for editors integration)',
                   '  custom formatter class name') do |o|
           options[:formatters] ||= []
           options[:formatters] << [o]
@@ -226,6 +228,11 @@ def parser(options)
           (options[:full_description] ||= []) << Regexp.compile(Regexp.escape(o))
         end
 
+        parser.on('-E', '--example-matches REGEX', "Run examples whose full nested names match REGEX (may be",
+                  "  used more than once)") do |o|
+          (options[:full_description] ||= []) << Regexp.compile(o)
+        end
+
         parser.on('-t', '--tag TAG[:VALUE]',
                   'Run examples with the specified tag, or exclude examples',
                   'by adding ~ before the tag.',
@@ -288,6 +295,7 @@ def parser(options)
         end
       end
     end
+    # rubocop:enable Metrics/BlockLength
     # rubocop:enable Metrics/AbcSize
     # rubocop:enable MethodLength
     # rubocop:enable CyclomaticComplexity
diff --git a/lib/rspec/core/rake_task.rb b/lib/rspec/core/rake_task.rb
index ad321a9ac3..7f01eab4f3 100644
--- a/lib/rspec/core/rake_task.rb
+++ b/lib/rspec/core/rake_task.rb
@@ -45,6 +45,21 @@ class RakeTask < ::Rake::TaskLib
       # A message to print to stderr when there are failures.
       attr_accessor :failure_message
 
+      if RUBY_VERSION < "1.9.0" || Support::Ruby.jruby?
+        # Run RSpec with a clean (empty) environment is not supported
+        def with_clean_environment=(_value)
+          raise ArgumentError, "Running in a clean environment is not supported on Ruby versions before 1.9.0"
+        end
+
+        # Run RSpec with a clean (empty) environment is not supported
+        def with_clean_environment
+          false
+        end
+      else
+        # Run RSpec with a clean (empty) environment.
+        attr_accessor :with_clean_environment
+      end
+
       # Use verbose output. If this is set to true, the task will print the
       # executed spec command to stdout. Defaults to `true`.
       attr_accessor :verbose
@@ -76,7 +91,12 @@ def run_task(verbose)
         command = spec_command
         puts command if verbose
 
-        return if system(command)
+        if with_clean_environment
+          return if system({}, command, :unsetenv_others => true)
+        else
+          return if system(command)
+        end
+
         puts failure_message if failure_message
 
         return unless fail_on_error
diff --git a/lib/rspec/core/reporter.rb b/lib/rspec/core/reporter.rb
index 41135ecad7..a016d0f860 100644
--- a/lib/rspec/core/reporter.rb
+++ b/lib/rspec/core/reporter.rb
@@ -77,6 +77,14 @@ def report(expected_example_count)
       end
     end
 
+    # @param exit_code [Integer] the exit_code to be return by the reporter
+    #
+    # Reports a run that exited early without having run any examples.
+    #
+    def exit_early(exit_code)
+      report(0) { exit_code }
+    end
+
     # @private
     def start(expected_example_count, time=RSpec::Core::Time.now)
       @start = time
diff --git a/lib/rspec/core/runner.rb b/lib/rspec/core/runner.rb
index 5090ec0326..862511a293 100644
--- a/lib/rspec/core/runner.rb
+++ b/lib/rspec/core/runner.rb
@@ -84,6 +84,8 @@ def initialize(options, configuration=RSpec.configuration, world=RSpec.world)
       # @param out [IO] output stream
       def run(err, out)
         setup(err, out)
+        return @configuration.reporter.exit_early(@configuration.failure_exit_code) if RSpec.world.wants_to_quit
+
         run_specs(@world.ordered_example_groups).tap do
           persist_example_statuses
         end
@@ -95,7 +97,10 @@ def run(err, out)
       # @param out [IO] output stream
       def setup(err, out)
         configure(err, out)
+        return if RSpec.world.wants_to_quit
+
         @configuration.load_spec_files
+      ensure
         @world.announce_filters
       end
 
diff --git a/lib/rspec/core/shared_example_group.rb b/lib/rspec/core/shared_example_group.rb
index f91889f3a1..b6ced2cc1f 100644
--- a/lib/rspec/core/shared_example_group.rb
+++ b/lib/rspec/core/shared_example_group.rb
@@ -76,7 +76,7 @@ module SharedExampleGroup
       #     end
       #   end
       #
-      #   describe Account do
+      #   RSpec.describe Account do
       #     it_behaves_like "auditable" do
       #       let(:auditable) { Account.new }
       #     end
diff --git a/lib/rspec/core/version.rb b/lib/rspec/core/version.rb
index 2ef5742cf3..bee778649b 100644
--- a/lib/rspec/core/version.rb
+++ b/lib/rspec/core/version.rb
@@ -3,7 +3,7 @@ module Core
     # Version information for RSpec Core.
     module Version
       # Current version of RSpec Core, in semantic versioning format.
-      STRING = '3.8.0'
+      STRING = '3.9.0'
     end
   end
 end
diff --git a/maintenance-branch b/maintenance-branch
index 8b25206ff9..efd24c79cb 100644
--- a/maintenance-branch
+++ b/maintenance-branch
@@ -1 +1 @@
-master
\ No newline at end of file
+3-9-maintenance
diff --git a/rspec-core.gemspec b/rspec-core.gemspec
index f4a44789ad..a778f04dde 100644
--- a/rspec-core.gemspec
+++ b/rspec-core.gemspec
@@ -13,6 +13,14 @@ Gem::Specification.new do |s|
   s.summary     = "rspec-core-#{RSpec::Core::Version::STRING}"
   s.description = "BDD for Ruby. RSpec runner and example groups."
 
+  s.metadata = {
+    'bug_tracker_uri'   => 'https://github.com/rspec/rspec-core/issues',
+    'changelog_uri'     => "https://github.com/rspec/rspec-core/blob/v#{s.version}/Changelog.md",
+    'documentation_uri' => 'https://rspec.info/documentation/',
+    'mailing_list_uri'  => 'https://groups.google.com/forum/#!forum/rspec',
+    'source_code_uri'   => 'https://github.com/rspec/rspec-core',
+  }
+
   s.files            = `git ls-files -- lib/*`.split("\n")
   s.files           += %w[README.md LICENSE.md Changelog.md .yardopts .document]
   s.test_files       = []
@@ -39,7 +47,7 @@ Gem::Specification.new do |s|
 
   s.add_development_dependency "cucumber", "~> 1.3"
   s.add_development_dependency "minitest", "~> 5.3"
-  s.add_development_dependency "aruba",    "~> 0.6.2" # 0.7 is broken on ruby 1.8.7
+  s.add_development_dependency "aruba",    "~> 0.14.9"
 
   s.add_development_dependency "coderay",  "~> 1.1.1"
 
diff --git a/script/clone_all_rspec_repos b/script/clone_all_rspec_repos
index 654f4ca957..1a8a5a1e23 100755
--- a/script/clone_all_rspec_repos
+++ b/script/clone_all_rspec_repos
@@ -1,5 +1,5 @@
 #!/bin/bash
-# This file was generated on 2018-04-05T18:41:15+10:00 from the rspec-dev repo.
+# This file was generated on 2019-07-24T15:33:48+02:00 from the rspec-dev repo.
 # DO NOT modify it by hand as your changes will get lost the next time it is generated.
 
 set -e
diff --git a/script/functions.sh b/script/functions.sh
index dac19e6fb5..c519731d6a 100644
--- a/script/functions.sh
+++ b/script/functions.sh
@@ -1,4 +1,4 @@
-# This file was generated on 2018-04-05T18:41:15+10:00 from the rspec-dev repo.
+# This file was generated on 2019-07-24T15:33:48+02:00 from the rspec-dev repo.
 # DO NOT modify it by hand as your changes will get lost the next time it is generated.
 
 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
@@ -19,7 +19,7 @@ fi
 
 function clone_repo {
   if [ ! -d $1 ]; then # don't clone if the dir is already there
-    travis_retry eval "git clone git://github.com/rspec/$1 --depth 1 --branch $MAINTENANCE_BRANCH"
+    travis_retry eval "git clone https://github.com/rspec/$1 --depth 1 --branch $MAINTENANCE_BRANCH"
   fi;
 }
 
diff --git a/script/predicate_functions.sh b/script/predicate_functions.sh
index 47d8d3813b..91a68f74bf 100644
--- a/script/predicate_functions.sh
+++ b/script/predicate_functions.sh
@@ -1,4 +1,4 @@
-# This file was generated on 2018-04-05T18:41:15+10:00 from the rspec-dev repo.
+# This file was generated on 2019-07-24T15:33:48+02:00 from the rspec-dev repo.
 # DO NOT modify it by hand as your changes will get lost the next time it is generated.
 
 function is_mri {
@@ -57,6 +57,14 @@ function is_mri_2plus {
   fi
 }
 
+function is_ruby_23_plus {
+  if ruby -e "exit(RUBY_VERSION.to_f >= 2.3)"; then
+    return 0
+  else
+    return 1
+  fi
+}
+
 function rspec_support_compatible {
   if [ "$MAINTENANCE_BRANCH" != "2-99-maintenance" ] && [ "$MAINTENANCE_BRANCH" != "2-14-maintenance" ]; then
     return 0
diff --git a/script/run_build b/script/run_build
index 2054b039ee..e8896bf4ef 100755
--- a/script/run_build
+++ b/script/run_build
@@ -1,5 +1,5 @@
 #!/bin/bash
-# This file was generated on 2018-04-05T18:41:15+10:00 from the rspec-dev repo.
+# This file was generated on 2019-07-24T15:33:48+02:00 from the rspec-dev repo.
 # DO NOT modify it by hand as your changes will get lost the next time it is generated.
 
 set -e
diff --git a/script/travis_functions.sh b/script/travis_functions.sh
index 39025a480b..89db508ac6 100644
--- a/script/travis_functions.sh
+++ b/script/travis_functions.sh
@@ -1,4 +1,4 @@
-# This file was generated on 2018-04-05T18:41:15+10:00 from the rspec-dev repo.
+# This file was generated on 2019-07-24T15:33:48+02:00 from the rspec-dev repo.
 # DO NOT modify it by hand as your changes will get lost the next time it is generated.
 
 # Taken from:
diff --git a/script/update_rubygems_and_install_bundler b/script/update_rubygems_and_install_bundler
new file mode 100755
index 0000000000..069271e5a3
--- /dev/null
+++ b/script/update_rubygems_and_install_bundler
@@ -0,0 +1,15 @@
+#!/bin/bash
+# This file was generated on 2019-07-24T15:33:48+02:00 from the rspec-dev repo.
+# DO NOT modify it by hand as your changes will get lost the next time it is generated.
+
+set -e
+source script/functions.sh
+
+if is_ruby_23_plus; then
+  gem update --system
+  gem install bundler
+else
+  echo "Warning installing older versions of Rubygems / Bundler"
+  gem update --system '2.7.8'
+  gem install bundler -v '1.17.3'
+fi
diff --git a/spec/integration/bisect_runners_spec.rb b/spec/integration/bisect_runners_spec.rb
index dd022a7a31..46c04ae1e9 100644
--- a/spec/integration/bisect_runners_spec.rb
+++ b/spec/integration/bisect_runners_spec.rb
@@ -6,13 +6,13 @@
 module RSpec::Core
   RSpec.shared_examples_for "a bisect runner" do
     include_context "aruba support"
-    before { clean_current_dir }
+    before { setup_aruba }
 
     let(:shell_command) { Bisect::ShellCommand.new([]) }
 
     def with_runner(&block)
       handle_current_dir_change do
-        in_current_dir do
+        cd '.' do
           options = ConfigurationOptions.new(shell_command.original_cli_args)
           runner = Runner.new(options)
           output = StringIO.new
@@ -124,7 +124,7 @@ def with_runner(&block)
           runner.run(%w[ ./spec/a_spec.rb[1:1] ])
         end
 
-        in_current_dir do
+        cd '.' do
           expect(File.read('spec_helper_loads')).to eq(".")
         end
       end
diff --git a/spec/integration/fail_if_no_examples_spec.rb b/spec/integration/fail_if_no_examples_spec.rb
index 1a13b828db..d3469f8091 100644
--- a/spec/integration/fail_if_no_examples_spec.rb
+++ b/spec/integration/fail_if_no_examples_spec.rb
@@ -2,7 +2,7 @@
 
 RSpec.describe 'Fail if no examples' do
   include_context "aruba support"
-  before { clean_current_dir }
+  before { setup_aruba }
 
   context 'when 1 passing example' do
     def passing_example(fail_if_no_examples)
diff --git a/spec/integration/failed_line_detection_spec.rb b/spec/integration/failed_line_detection_spec.rb
index c80cfc6e0a..1d33235eba 100644
--- a/spec/integration/failed_line_detection_spec.rb
+++ b/spec/integration/failed_line_detection_spec.rb
@@ -2,7 +2,7 @@
 
 RSpec.describe 'Failed line detection' do
   include_context "aruba support"
-  before { clean_current_dir }
+  before { setup_aruba }
 
   it "finds the source of a failure in a spec file that is defined at the current directory instead of in the normal `spec` subdir" do
     write_file "the_spec.rb", "
@@ -32,7 +32,7 @@
       end
     "
 
-    file = in_current_dir { "#{Dir.pwd}/failing_spec.rb" }
+    file = cd('.') { "#{Dir.pwd}/failing_spec.rb" }
     load file
     run_command "passing_spec.rb"
 
diff --git a/spec/integration/filtering_spec.rb b/spec/integration/filtering_spec.rb
index 5877da74bf..e8421f2d6b 100644
--- a/spec/integration/filtering_spec.rb
+++ b/spec/integration/filtering_spec.rb
@@ -2,7 +2,7 @@
 
 RSpec.describe 'Filtering' do
   include_context "aruba support"
-  before { clean_current_dir }
+  before { setup_aruba }
 
   it 'prints a rerun command for shared examples in external files that works to rerun' do
     write_file "spec/support/shared_examples.rb", "
@@ -205,7 +205,7 @@ def run_rerun_command_for_failing_spec
       expect(last_cmd_stdout).to match(/3 examples, 0 failures/)
 
       # Using absolute paths...
-      spec_root = in_current_dir { File.expand_path("spec") }
+      spec_root = cd('.') { File.expand_path("spec") }
       run_command "#{spec_root}/file_1_spec.rb[1:1,1:3] #{spec_root}/file_2_spec.rb[1:2]"
       expect(last_cmd_stdout).to match(/3 examples, 0 failures/)
     end
diff --git a/spec/integration/order_spec.rb b/spec/integration/order_spec.rb
index a7bac40e68..f492971a45 100644
--- a/spec/integration/order_spec.rb
+++ b/spec/integration/order_spec.rb
@@ -131,7 +131,7 @@
   end
 
   describe '--order defined on CLI with --order rand in .rspec' do
-    after { remove_file '.rspec' }
+    after { remove '.rspec' }
 
     it "overrides --order rand with --order defined" do
       write_file '.rspec', '--order rand'
@@ -147,7 +147,7 @@
   end
 
   context 'when a custom order is configured' do
-    after { remove_file 'spec/custom_order_spec.rb' }
+    after { remove 'spec/custom_order_spec.rb' }
 
     before do
       write_file 'spec/custom_order_spec.rb', "
diff --git a/spec/integration/output_stream_spec.rb b/spec/integration/output_stream_spec.rb
index 16553ca56d..d83aff1baf 100644
--- a/spec/integration/output_stream_spec.rb
+++ b/spec/integration/output_stream_spec.rb
@@ -2,7 +2,7 @@
 
 RSpec.describe 'Output stream' do
   include_context 'aruba support'
-  before { clean_current_dir }
+  before { setup_aruba }
 
   context 'when a formatter set in a configure block' do
     it 'writes to the right output stream' do
@@ -21,7 +21,7 @@
 
       run_command ''
       expect(last_cmd_stdout).to be_empty
-      in_current_dir do
+      cd '.' do
         expect(File.read('saved_output')).to include('1 example, 0 failures')
       end
     end
@@ -42,7 +42,7 @@
 
       run_command ''
       expect(last_cmd_stdout).to be_empty
-      in_current_dir do
+      cd '.' do
         expect(File.read('saved_output')).to include('1 example, 0 failures')
       end
     end
@@ -64,7 +64,7 @@
 
       run_command ''
       expect(last_cmd_stdout).to be_empty
-      in_current_dir do
+      cd '.' do
         expect(File.read('saved_output')).to include('1 example, 0 failures')
       end
     end
diff --git a/spec/integration/persistence_failures_spec.rb b/spec/integration/persistence_failures_spec.rb
index d26a78a8e6..5c57e13a02 100644
--- a/spec/integration/persistence_failures_spec.rb
+++ b/spec/integration/persistence_failures_spec.rb
@@ -2,7 +2,7 @@
 
 RSpec.describe 'Persistence failures' do
   include_context "aruba support"
-  before { clean_current_dir }
+  before { setup_aruba }
 
   context "when `config.example_status_persistence_file_path` is configured" do
     context "to an invalid file path (e.g. spec/spec_helper.rb/examples.txt)" do
@@ -38,7 +38,7 @@
         "
 
         write_file_formatted "spec/examples.txt", ""
-        in_current_dir do
+        cd '.' do
           FileUtils.chmod 0000, "spec/examples.txt"
         end
       end
diff --git a/spec/integration/spec_file_load_errors_spec.rb b/spec/integration/spec_file_load_errors_spec.rb
index 98347b3cfe..2e017504ee 100644
--- a/spec/integration/spec_file_load_errors_spec.rb
+++ b/spec/integration/spec_file_load_errors_spec.rb
@@ -18,14 +18,10 @@
   end
 
   before do
-    # get out of `aruba` sub-dir so that `filter_gems_from_backtrace 'aruba'`
-    # below does not filter out our spec file.
-    expect(dirs.pop).to eq "aruba"
-
-    clean_current_dir
+    setup_aruba
 
     RSpec.configure do |c|
-      c.filter_gems_from_backtrace "aruba"
+      c.filter_gems_from_backtrace "gems/aruba"
       c.backtrace_exclusion_patterns << %r{/rspec-core/spec/} << %r{rspec_with_simplecov}
       c.failure_exit_code = failure_exit_code
     end
@@ -54,6 +50,35 @@
     EOS
   end
 
+  it 'prints a single error when it happens on --require files' do
+    write_file_formatted "helper_with_error.rb", "raise 'boom'"
+
+    write_file_formatted "1_spec.rb", "
+      RSpec.describe 'A broken spec file that will raise when loaded' do
+        raise 'kaboom'
+      end
+    "
+
+    run_command "--require ./helper_with_error 1_spec.rb"
+    expect(last_cmd_exit_status).to eq(failure_exit_code)
+    output = normalize_durations(last_cmd_stdout)
+    expect(output).to eq unindent(<<-EOS)
+
+      An error occurred while loading ./helper_with_error.
+      Failure/Error: raise 'boom'
+
+      RuntimeError:
+        boom
+      # ./helper_with_error.rb:1#{spec_line_suffix}
+      No examples found.
+
+
+      Finished in n.nnnn seconds (files took n.nnnn seconds to load)
+      0 examples, 0 failures, 1 error occurred outside of examples
+
+    EOS
+  end
+
   it 'nicely handles load-time errors in user spec files' do
     write_file_formatted "1_spec.rb", "
       boom
diff --git a/spec/integration/suite_hooks_errors_spec.rb b/spec/integration/suite_hooks_errors_spec.rb
index 631e881c5b..b4c711cd62 100644
--- a/spec/integration/suite_hooks_errors_spec.rb
+++ b/spec/integration/suite_hooks_errors_spec.rb
@@ -18,14 +18,10 @@
   end
 
   before do
-    # get out of `aruba` sub-dir so that `filter_gems_from_backtrace 'aruba'`
-    # below does not filter out our spec file.
-    expect(dirs.pop).to eq "aruba"
-
-    clean_current_dir
+    setup_aruba
 
     RSpec.configure do |c|
-      c.filter_gems_from_backtrace "aruba"
+      c.filter_gems_from_backtrace "gems/aruba"
       c.backtrace_exclusion_patterns << %r{/rspec-core/spec/} << %r{rspec_with_simplecov}
       c.failure_exit_code = failure_exit_code
     end
diff --git a/spec/rspec/core/configuration_spec.rb b/spec/rspec/core/configuration_spec.rb
index 77e165b23e..74ef6bbcdf 100644
--- a/spec/rspec/core/configuration_spec.rb
+++ b/spec/rspec/core/configuration_spec.rb
@@ -41,6 +41,87 @@ module RSpec::Core
       end
     end
 
+    describe "#fail_fast=" do
+      context 'when true' do
+        it 'is set to true' do
+          config.fail_fast = true
+          expect(config.fail_fast).to eq true
+        end
+      end
+
+      context "when 'true'" do
+        it 'is set to true' do
+          config.fail_fast = 'true'
+          expect(config.fail_fast).to eq true
+        end
+      end
+
+      context "when false" do
+        it 'is set to false' do
+          config.fail_fast = false
+          expect(config.fail_fast).to eq false
+        end
+      end
+
+      context "when 'false'" do
+        it 'is set to false' do
+          config.fail_fast = 'false'
+          expect(config.fail_fast).to eq false
+        end
+      end
+
+      context "when 0" do
+        it 'is set to false' do
+          config.fail_fast = 0
+          expect(config.fail_fast).to eq false
+        end
+      end
+
+      context "when integer number" do
+        it 'is set to number' do
+          config.fail_fast = 5
+          expect(config.fail_fast).to eq 5
+        end
+      end
+
+      context "when floating point number" do
+        it 'is set to integer number' do
+          config.fail_fast = 5.9
+          expect(config.fail_fast).to eq 5
+        end
+      end
+
+      context "when string represeting an integer number" do
+        it 'is set to number' do
+          config.fail_fast = '5'
+          expect(config.fail_fast).to eq 5
+        end
+      end
+
+      context "when nil" do
+        it 'is nil' do
+          config.fail_fast = nil
+          expect(config.fail_fast).to eq nil
+        end
+      end
+
+      context "when unrecognized value" do
+        before do
+          allow(RSpec).to receive(:warning)
+        end
+
+        it 'prints warning' do
+          config.fail_fast = 'yes'
+          expect(RSpec).to have_received(:warning).with(/Cannot set `RSpec.configuration.fail_fast`/i)
+        end
+
+        it 'is set to true' do
+          config.fail_fast = 'yes'
+          expect(config.fail_fast).to eq true
+        end
+      end
+    end
+
     describe 'fail_if_no_examples' do
       it 'defaults to false' do
         expect(RSpec::Core::Configuration.new.fail_if_no_examples).to be(false)
@@ -1819,6 +1900,42 @@ def exclude?(line)
         expect(group.metadata).to include(:b1_desc => "bar (block 1)", :b2_desc => "bar (block 1) (block 2)")
       end
 
+      it 'supports cascades of derived metadata, but avoids re-running derived metadata blocks that have already been applied' do
+        RSpec.configure do |c|
+          c.define_derived_metadata(:foo1) { |m| m[:foo2] = (m[:foo2] || 0) + 1 }
+          c.define_derived_metadata(:foo2) { |m| m[:foo3] = (m[:foo3] || 0) + 1 }
+          c.define_derived_metadata(:foo3) { |m| m[:foo1] += 1 }
+        end
+
+        group = RSpec.describe("bar", :foo1 => 0)
+        expect(group.metadata).to include(:foo1 => 1, :foo2 => 1, :foo3 => 1)
+
+        ex = RSpec.describe("My group").example("foo", :foo1 => 0)
+        expect(ex.metadata).to include(:foo1 => 1, :foo2 => 1, :foo3 => 1)
+      end
+
+      it 'does not allow a derived metadata cascade to recurse infinitely' do
+        RSpec.configure do |c|
+          counter = 1
+          derive_next_metadata = lambda do |outer_meta|
+            tag = :"foo#{counter += 1}"
+            outer_meta[tag] = true
+
+            c.define_derived_metadata(tag) do |inner_meta|
+              derive_next_metadata.call(inner_meta)
+            end
+          end
+
+          c.define_derived_metadata(:foo1) do |meta|
+            derive_next_metadata.call(meta)
+          end
+        end
+
+        expect {
+          RSpec.describe("group", :foo1)
+        }.to raise_error(SystemStackError)
+      end
+
       it "derives metadata before the group or example blocks are eval'd so their logic can depend on the derived metadata" do
         RSpec.configure do |c|
           c.define_derived_metadata(:foo) do |metadata|
diff --git a/spec/rspec/core/did_you_mean_spec.rb b/spec/rspec/core/did_you_mean_spec.rb
new file mode 100644
index 0000000000..6ed6217e5c
--- /dev/null
+++ b/spec/rspec/core/did_you_mean_spec.rb
@@ -0,0 +1,37 @@
+module RSpec
+  module Core
+    RSpec.describe DidYouMean do
+      describe '#call' do
+        context "when `DidYouMean::SpellChecker` is available", :skip => !defined?(::DidYouMean::SpellChecker) do
+          context 'Success' do
+            let(:name) { './spec/rspec/core/did_you_mean_spec.rb' }
+            it 'returns a useful suggestion' do
+              expect(DidYouMean.new(name[0..-2]).call).to include name
+            end
+            context 'numerous possibilities' do
+              it 'returns a small number of suggestions' do
+                name = './spec/rspec/core/drb_spec.r'
+                suggestions = DidYouMean.new(name).call
+                expect(suggestions.split("\n").size).to eq 4
+              end
+            end
+          end
+          context 'No suitable suggestions' do
+            it 'returns empty string' do
+              name = './' + 'x' * 50
+              expect(DidYouMean.new(name).call).to eq ''
+            end
+          end
+        end
+        context "when `DidYouMean::SpellChecker` is not available", :unless => defined?(::DidYouMean::SpellChecker) do
+          describe 'Success' do
+            let(:name) { './spec/rspec/core/did_you_mean_spec.rb' }
+            it 'returns a hint' do
+              expect(DidYouMean.new(name[0..-2]).call).to include 'Hint:'
+            end
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/spec/rspec/core/example_spec.rb b/spec/rspec/core/example_spec.rb
index 5bba1d5627..81a7cec4a7 100644
--- a/spec/rspec/core/example_spec.rb
+++ b/spec/rspec/core/example_spec.rb
@@ -187,13 +187,13 @@ def assert(val)
       it "uses the matcher-generated description" do
         example_group.example { expect(5).to eq(5) }
         example_group.run
-        expect(example_group.examples.first.description).to eq("should eq 5")
+        expect(example_group.examples.first.description).to eq("is expected to eq 5")
       end
 
       it "uses the matcher-generated description in the full description" do
         example_group.example { expect(5).to eq(5) }
         example_group.run
-        expect(example_group.examples.first.full_description).to eq("group description should eq 5")
+        expect(example_group.examples.first.full_description).to eq("group description is expected to eq 5")
       end
 
       it "uses the file and line number if there is no matcher-generated description" do
@@ -213,7 +213,7 @@ def assert(val)
         it "still uses the matcher-generated description if a matcher ran" do
           example = example_group.example { pending; expect(4).to eq(5) }
           example_group.run
-          expect(example.description).to eq("should eq 5")
+          expect(example.description).to eq("is expected to eq 5")
         end
 
         it "uses the file and line number of the example if no matcher ran" do
@@ -232,7 +232,7 @@ def assert(val)
             after { raise "boom" }
           end.run
 
-          expect(ex.description).to eq("should eq 2")
+          expect(ex.description).to eq("is expected to eq 2")
         end
       end
 
@@ -268,7 +268,7 @@ def assert(val)
             after { expect(true).to eq(true) }
           end.run
 
-          expect(ex).to pass.and have_attributes(:description => "should be nil")
+          expect(ex).to pass.and have_attributes(:description => "is expected to be nil")
         end
       end
     end
@@ -279,7 +279,7 @@ def assert(val)
       it "uses the matcher-generated description" do
         example_group.example { expect(5).to eq(5) }
         example_group.run
-        expect(example_group.examples.first.description).to eq("should eq 5")
+        expect(example_group.examples.first.description).to eq("is expected to eq 5")
       end
 
       it "uses the file and line number if there is no matcher-generated description" do
diff --git a/spec/rspec/core/formatters/documentation_formatter_spec.rb b/spec/rspec/core/formatters/documentation_formatter_spec.rb
index d58a5f1635..2ae487fb7c 100644
--- a/spec/rspec/core/formatters/documentation_formatter_spec.rb
+++ b/spec/rspec/core/formatters/documentation_formatter_spec.rb
@@ -81,6 +81,36 @@ def execution_result(values)
 ")
     end
 
+    it "can output indented messages from within example group" do
+      root = RSpec.describe("root")
+      root.example("example") {|example| example.reporter.message("message")}
+
+      root.run(reporter)
+
+      expect(formatter_output.string).to eql("
+root
+  example
+    message
+")
+    end
+
+    it "can output indented messages" do
+      root = RSpec.describe("root")
+      context = root.describe("nested")
+      context.example("example") {}
+
+      root.run(reporter)
+
+      reporter.message("message")
+
+      expect(formatter_output.string).to eql("
+root
+  nested
+    example
+message
+")
+    end
+
     it "strips whitespace for each row" do
       group = RSpec.describe(" root ")
       context1 = group.describe(" nested ")
diff --git a/spec/rspec/core/formatters/exception_presenter_spec.rb b/spec/rspec/core/formatters/exception_presenter_spec.rb
index 602abffb72..347524cc26 100644
--- a/spec/rspec/core/formatters/exception_presenter_spec.rb
+++ b/spec/rspec/core/formatters/exception_presenter_spec.rb
@@ -94,6 +94,23 @@ module RSpec::Core
         EOS
       end
 
+      if String.method_defined?(:encoding) && !RSpec::Support::OS.windows?
+        it 'allows the caller to add encoded description' do
+          the_presenter = Formatters::ExceptionPresenter.new(exception, example,
+                                                             :description => "ジ".encode("CP932"))
+
+          expect(the_presenter.fully_formatted(1)).to eq(<<-EOS.gsub(/^ +\|/, ''))
+          |
+          |  1) ジ
+          |     Failure/Error: # The failure happened here!#{ encoding_check }
+          |
+          |       Boom
+          |       Bam
+          |     # ./spec/rspec/core/formatters/exception_presenter_spec.rb:#{line_num}
+          EOS
+        end
+      end
+
       it 'allows the caller to omit the description' do
         the_presenter = Formatters::ExceptionPresenter.new(exception, example,
                                                        :detail_formatter => Proc.new { "Detail!" },
diff --git a/spec/rspec/core/formatters/failure_list_formatter_spec.rb b/spec/rspec/core/formatters/failure_list_formatter_spec.rb
new file mode 100644
index 0000000000..54c5c3996d
--- /dev/null
+++ b/spec/rspec/core/formatters/failure_list_formatter_spec.rb
@@ -0,0 +1,19 @@
+require 'rspec/core/formatters/failure_list_formatter'
+
+module RSpec::Core::Formatters
+  RSpec.describe FailureListFormatter do
+    include FormatterSupport
+
+    it 'produces the expected full output' do
+      output = run_example_specs_with_formatter('failures')
+      expect(output).to eq(<<-EOS.gsub(/^\s+\|/, ''))
+        |./spec/rspec/core/resources/formatter_specs.rb:4:is marked as pending but passes
+        |./spec/rspec/core/resources/formatter_specs.rb:36:fails
+        |./spec/rspec/core/resources/formatter_specs.rb:40:fails twice
+        |./spec/rspec/core/resources/formatter_specs.rb:47:fails with a backtrace that has no file
+        |./spec/rspec/core/resources/formatter_specs.rb:53:fails with a backtrace containing an erb file
+        |./spec/rspec/core/resources/formatter_specs.rb:71:raises
+      EOS
+    end
+  end
+end
diff --git a/spec/rspec/core/option_parser_spec.rb b/spec/rspec/core/option_parser_spec.rb
index ca7d8ce4a0..73084ec9cf 100644
--- a/spec/rspec/core/option_parser_spec.rb
+++ b/spec/rspec/core/option_parser_spec.rb
@@ -216,6 +216,16 @@ module RSpec::Core
       end
     end
 
+    %w[--example-matches -E].each do |option|
+      describe option do
+        it "does not escape the arg" do
+          options = Parser.parse([option, 'this (and that)\b'])
+          expect(options[:full_description].length).to eq(1)
+          expect(/this (and that)\b/).to eq(options[:full_description].first)
+        end
+      end
+    end
+
     %w[--pattern -P].each do |option|
       describe option do
         it "sets the filename pattern" do
diff --git a/spec/rspec/core/pending_example_spec.rb b/spec/rspec/core/pending_example_spec.rb
index 5e2f25ed4a..06cbaf52c9 100644
--- a/spec/rspec/core/pending_example_spec.rb
+++ b/spec/rspec/core/pending_example_spec.rb
@@ -150,7 +150,7 @@
           end
         end.run
 
-        expect(ex.description).to eq('should eq "gnirts"')
+        expect(ex.description).to eq('is expected to eq "gnirts"')
       end
     end
 
diff --git a/spec/rspec/core/rake_task_spec.rb b/spec/rspec/core/rake_task_spec.rb
index 5261aad0f8..06a28e7f6b 100644
--- a/spec/rspec/core/rake_task_spec.rb
+++ b/spec/rspec/core/rake_task_spec.rb
@@ -148,6 +148,24 @@ def silence_output(&block)
       end
     end
 
+    context "with_clean_environment is set" do
+      it "removes the environment variables", :if => RUBY_VERSION >= '1.9.0', :unless => RSpec::Support::Ruby.jruby? do
+        with_env_vars 'MY_ENV' => 'ABC' do
+          if RSpec::Support::OS.windows?
+            essential_shell_variables = /\["ANSICON", "ANSICON_DEF", "HOME", "TMPDIR", "USER"\]/
+          else
+            essential_shell_variables = /\["PWD"(?:, "SHLVL")?(?:, "_")?(?:, "__CF_USER_TEXT_ENCODING")?\]/
+          end
+
+          expect {
+            task.with_clean_environment = true
+            task.ruby_opts = '-e "puts \"Environment: #{ENV.keys}\""'
+            task.run_task false
+          }.to avoid_outputting.to_stderr.and output(essential_shell_variables).to_stdout_from_any_process
+        end
+      end
+    end
+
     def loaded_files
       args = Shellwords.split(spec_command)
       args -= [task.class::RUBY, "-S", task.rspec_path]
diff --git a/spec/rspec/core/reporter_spec.rb b/spec/rspec/core/reporter_spec.rb
index 1c8579cd43..16e4822681 100644
--- a/spec/rspec/core/reporter_spec.rb
+++ b/spec/rspec/core/reporter_spec.rb
@@ -160,6 +160,21 @@ module RSpec::Core
       end
     end
 
+    describe "#exit_early" do
+      it "returns the passed exit code" do
+        expect(reporter.exit_early(42)).to eq(42)
+      end
+
+      it "sends a complete cycle of notifications" do
+        formatter = double("formatter")
+        %w[seed start start_dump dump_pending dump_failures dump_summary seed close].map(&:to_sym).each do |message|
+          reporter.register_listener formatter, message
+          expect(formatter).to receive(message).ordered
+        end
+        reporter.exit_early(42)
+      end
+    end
+
     describe "#report" do
       it "supports one arg (count)" do
         reporter.report(1) {}
diff --git a/spec/rspec/core/shared_context_spec.rb b/spec/rspec/core/shared_context_spec.rb
index dfd11b7b80..67218f2418 100644
--- a/spec/rspec/core/shared_context_spec.rb
+++ b/spec/rspec/core/shared_context_spec.rb
@@ -66,6 +66,19 @@
     expect(group.new.foo).to eq('foo')
   end
 
+  it 'supports overriding let without warnings' do
+    shared = Module.new do
+      extend RSpec::SharedContext
+      let(:foo) { 'foo' }
+    end
+    group = RSpec.describe do
+      include shared
+      let(:foo) { 'bar' }
+    end
+
+    expect(group.new.foo).to eq('bar')
+  end
+
   it "supports let when applied to an individual example via metadata" do
     shared = Module.new do
       extend RSpec::SharedContext
diff --git a/spec/rspec/core/shared_example_group_spec.rb b/spec/rspec/core/shared_example_group_spec.rb
index 3bf96d1079..6b897c395e 100644
--- a/spec/rspec/core/shared_example_group_spec.rb
+++ b/spec/rspec/core/shared_example_group_spec.rb
@@ -286,6 +286,21 @@ def self.bar; 'bar'; end
               expect(host_ex_metadata[:foo]).to eq :host
               expect(shared_ex_metadata[:foo]).to eq :shared
             end
+
+            it "applies metadata from the shared group to the including group, when the shared group itself is loaded and included via metadata" do
+              RSpec.configure do |config|
+                config.when_first_matching_example_defined(:controller) do
+                  define_top_level_shared_group("controller support", :capture_logging) { }
+
+                  config.include_context "controller support", :controller
+                end
+              end
+
+              group = RSpec.describe("group", :controller)
+              ex = group.it
+
+              expect(ex.metadata).to include(:controller => true, :capture_logging => true)
+            end
           end
 
           context "when the group is included via `config.include_context` and matching metadata" do
diff --git a/spec/support/aruba_support.rb b/spec/support/aruba_support.rb
index 93f34210dc..55050370f6 100644
--- a/spec/support/aruba_support.rb
+++ b/spec/support/aruba_support.rb
@@ -20,10 +20,10 @@ def run_command(cmd)
 
     # So that `RSpec.warning` will go to temp_stderr.
     allow(::Kernel).to receive(:warn) { |msg| temp_stderr.puts(msg) }
-    cmd_parts = Shellwords.split(cmd)
+    cmd_parts = ["--no-profile"] + Shellwords.split(cmd)
 
     handle_current_dir_change do
-      in_current_dir do
+      cd '.' do
         @last_cmd_exit_status = RSpec::Core::Runner.run(cmd_parts, temp_stderr, temp_stdout)
       end
     end
diff --git a/spec/support/formatter_support.rb b/spec/support/formatter_support.rb
index d9bc01a3ef..529d9fb2a6 100644
--- a/spec/support/formatter_support.rb
+++ b/spec/support/formatter_support.rb
@@ -25,7 +25,7 @@ def run_rspec_with_formatter(formatter, options={})
     spec_order = options[:seed] ? ["--seed", options[:seed].to_s] : ["--order", "defined"]
 
     options = RSpec::Core::ConfigurationOptions.new([
-      "--format", formatter, *(spec_order + extra_options)
+      "--no-profile", "--format", formatter, *(spec_order + extra_options)
     ])
 
     err, out = StringIO.new, StringIO.new