diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 4d4ba50bd4a..500cc24db21 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -785,12 +785,12 @@ impl RustcOptGroup {
         self.stability == OptionStability::Stable
     }
 
-    fn stable(g: getopts::OptGroup) -> RustcOptGroup {
+    pub fn stable(g: getopts::OptGroup) -> RustcOptGroup {
         RustcOptGroup { opt_group: g, stability: OptionStability::Stable }
     }
 
     #[allow(dead_code)] // currently we have no "truly unstable" options
-    fn unstable(g: getopts::OptGroup) -> RustcOptGroup {
+    pub fn unstable(g: getopts::OptGroup) -> RustcOptGroup {
         RustcOptGroup { opt_group: g, stability: OptionStability::Unstable }
     }
 
@@ -926,33 +926,32 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
 pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
     let mut opts = rustc_short_optgroups();
     opts.extend_from_slice(&[
-        opt::multi_s("", "extern", "Specify where an external rust library is \
-                                located",
-                 "NAME=PATH"),
+        opt::multi_s("", "extern", "Specify where an external rust library is located",
+                     "NAME=PATH"),
         opt::opt_s("", "sysroot", "Override the system root", "PATH"),
         opt::multi_ubnr("Z", "", "Set internal debugging options", "FLAG"),
         opt::opt_ubnr("", "error-format",
                       "How errors and other messages are produced",
                       "human|json"),
         opt::opt_s("", "color", "Configure coloring of output:
-            auto   = colorize, if output goes to a tty (default);
-            always = always colorize output;
-            never  = never colorize output", "auto|always|never"),
+                                 auto   = colorize, if output goes to a tty (default);
+                                 always = always colorize output;
+                                 never  = never colorize output", "auto|always|never"),
 
         opt::flagopt_ubnr("", "pretty",
-                   "Pretty-print the input instead of compiling;
-                   valid types are: `normal` (un-annotated source),
-                   `expanded` (crates expanded), or
-                   `expanded,identified` (fully parenthesized, AST nodes with IDs).",
-                 "TYPE"),
+                          "Pretty-print the input instead of compiling;
+                           valid types are: `normal` (un-annotated source),
+                           `expanded` (crates expanded), or
+                           `expanded,identified` (fully parenthesized, AST nodes with IDs).",
+                          "TYPE"),
         opt::flagopt_ubnr("", "unpretty",
-                     "Present the input source, unstable (and less-pretty) variants;
-                      valid types are any of the types for `--pretty`, as well as:
-                      `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
-                      `everybody_loops` (all function bodies replaced with `loop {}`),
-                      `hir` (the HIR), `hir,identified`, or
-                      `hir,typed` (HIR with types for each node).",
-                     "TYPE"),
+                          "Present the input source, unstable (and less-pretty) variants;
+                           valid types are any of the types for `--pretty`, as well as:
+                           `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
+                           `everybody_loops` (all function bodies replaced with `loop {}`),
+                           `hir` (the HIR), `hir,identified`, or
+                           `hir,typed` (HIR with types for each node).",
+                          "TYPE"),
 
         // new options here should **not** use the `_ubnr` functions, all new
         // unstable options should use the short variants to indicate that they
@@ -1263,7 +1262,6 @@ pub fn get_unstable_features_setting() -> UnstableFeatures {
 }
 
 pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> {
-
     let mut crate_types: Vec<CrateType> = Vec::new();
     for unparsed_crate_type in &list_list {
         for part in unparsed_crate_type.split(',') {
@@ -1287,6 +1285,72 @@ pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateTy
     return Ok(crate_types);
 }
 
+pub mod nightly_options {
+    use getopts;
+    use syntax::feature_gate::UnstableFeatures;
+    use super::{ErrorOutputType, OptionStability, RustcOptGroup, get_unstable_features_setting};
+    use session::{early_error, early_warn};
+
+    pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
+        is_nightly_build() && matches.opt_strs("Z").iter().any(|x| *x == "unstable-options")
+    }
+
+    fn is_nightly_build() -> bool {
+        match get_unstable_features_setting() {
+            UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
+            _ => false,
+        }
+    }
+
+    pub fn check_nightly_options(matches: &getopts::Matches, flags: &[RustcOptGroup]) {
+        let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options");
+        let really_allows_unstable_options = match get_unstable_features_setting() {
+            UnstableFeatures::Disallow => false,
+            _ => true,
+        };
+
+        for opt in flags.iter() {
+            if opt.stability == OptionStability::Stable {
+                continue
+            }
+            let opt_name = if opt.opt_group.long_name.is_empty() {
+                &opt.opt_group.short_name
+            } else {
+                &opt.opt_group.long_name
+            };
+            if !matches.opt_present(opt_name) {
+                continue
+            }
+            if opt_name != "Z" && !has_z_unstable_option {
+                early_error(ErrorOutputType::default(),
+                            &format!("the `-Z unstable-options` flag must also be passed to enable \
+                                      the flag `{}`",
+                                     opt_name));
+            }
+            if really_allows_unstable_options {
+                continue
+            }
+            match opt.stability {
+                OptionStability::Unstable => {
+                    let msg = format!("the option `{}` is only accepted on the \
+                                       nightly compiler", opt_name);
+                    early_error(ErrorOutputType::default(), &msg);
+                }
+                OptionStability::UnstableButNotReally => {
+                    let msg = format!("the option `{}` is is unstable and should \
+                                       only be used on the nightly compiler, but \
+                                       it is currently accepted for backwards \
+                                       compatibility; this will soon change, \
+                                       see issue #31847 for more details",
+                                      opt_name);
+                    early_warn(ErrorOutputType::default(), &msg);
+                }
+                OptionStability::Stable => {}
+            }
+        }
+    }
+}
+
 impl fmt::Display for CrateType {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 3444b770cc8..091e39b4b12 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -68,7 +68,7 @@ use rustc_save_analysis as save;
 use rustc_trans::back::link;
 use rustc::session::{config, Session, build_session, CompileResult};
 use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
-use rustc::session::config::{get_unstable_features_setting, OptionStability};
+use rustc::session::config::{get_unstable_features_setting, nightly_options};
 use rustc::middle::cstore::CrateStore;
 use rustc::lint::Lint;
 use rustc::lint;
@@ -89,7 +89,7 @@ use std::str;
 use std::sync::{Arc, Mutex};
 use std::thread;
 
-use rustc::session::{early_error, early_warn};
+use rustc::session::early_error;
 
 use syntax::ast;
 use syntax::parse::{self, PResult};
@@ -910,51 +910,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
     //   (unstable option being used on stable)
     // * If we're a historically stable-but-should-be-unstable option then we
     //   emit a warning that we're going to turn this into an error soon.
-    let has_z_unstable_options = matches.opt_strs("Z")
-                                        .iter()
-                                        .any(|x| *x == "unstable-options");
-    let really_allows_unstable_options = match get_unstable_features_setting() {
-        UnstableFeatures::Disallow => false,
-        _ => true,
-    };
-    for opt in config::rustc_optgroups() {
-        if opt.stability == OptionStability::Stable {
-            continue
-        }
-        let opt_name = if opt.opt_group.long_name.is_empty() {
-            &opt.opt_group.short_name
-        } else {
-            &opt.opt_group.long_name
-        };
-        if !matches.opt_present(opt_name) {
-            continue
-        }
-        if opt_name != "Z" && !has_z_unstable_options {
-            let msg = format!("the `-Z unstable-options` flag must also be \
-                               passed to enable the flag `{}`", opt_name);
-            early_error(ErrorOutputType::default(), &msg);
-        }
-        if really_allows_unstable_options {
-            continue
-        }
-        match opt.stability {
-            OptionStability::Unstable => {
-                let msg = format!("the option `{}` is only accepted on the \
-                                   nightly compiler", opt_name);
-                early_error(ErrorOutputType::default(), &msg);
-            }
-            OptionStability::UnstableButNotReally => {
-                let msg = format!("the option `{}` is is unstable and should \
-                                   only be used on the nightly compiler, but \
-                                   it is currently accepted for backwards \
-                                   compatibility; this will soon change, \
-                                   see issue #31847 for more details",
-                                  opt_name);
-                early_warn(ErrorOutputType::default(), &msg);
-            }
-            OptionStability::Stable => {}
-        }
-    }
+    nightly_options::check_nightly_options(&matches, &config::rustc_optgroups());
 
     if matches.opt_present("h") || matches.opt_present("help") {
         // Only show unstable options in --help if we *really* accept unstable
@@ -962,12 +918,11 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
         // the stable channel of Rust which was accidentally allowed
         // historically.
         usage(matches.opt_present("verbose"),
-              has_z_unstable_options && really_allows_unstable_options);
+              nightly_options::is_unstable_enabled(&matches));
         return None;
     }
 
     // Don't handle -W help here, because we might first load plugins.
-
     let r = matches.opt_strs("Z");
     if r.iter().any(|x| *x == "help") {
         describe_debug_flags();
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index f5749d647dd..f7e071a0515 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -433,10 +433,6 @@ pub fn run(mut krate: clean::Crate,
             krate: krate.name.clone(),
             playground_url: "".to_string(),
         },
-        include_sources: true,
-        local_sources: HashMap::new(),
-        render_redirect_pages: false,
-        issue_tracker_base_url: None,
         css_file_extension: css_file_extension,
     };
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index d5b2f2bb83e..87950947596 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -65,10 +65,8 @@ use std::sync::mpsc::channel;
 use externalfiles::ExternalHtml;
 use serialize::Decodable;
 use serialize::json::{self, Json};
-use rustc::session::early_error;
 use rustc::session::search_paths::SearchPaths;
-use rustc::session::config::{get_unstable_features_setting, ErrorOutputType};
-use syntax::feature_gate::UnstableFeatures;
+use rustc::session::config::{ErrorOutputType, RustcOptGroup, nightly_options};
 
 // reexported from `clean` so it can be easily updated with the mod itself
 pub use clean::SCHEMA_VERSION;
@@ -143,86 +141,87 @@ pub fn main() {
     process::exit(res as i32);
 }
 
-pub fn opts() -> Vec<getopts::OptGroup> {
+fn stable(g: getopts::OptGroup) -> RustcOptGroup { RustcOptGroup::stable(g) }
+fn unstable(g: getopts::OptGroup) -> RustcOptGroup { RustcOptGroup::unstable(g) }
+
+pub fn opts() -> Vec<RustcOptGroup> {
     use getopts::*;
     vec!(
-        optflag("h", "help", "show this help message"),
-        optflag("V", "version", "print rustdoc's version"),
-        optflag("v", "verbose", "use verbose output"),
-        optopt("r", "input-format", "the input type of the specified file",
-               "[rust|json]"),
-        optopt("w", "output-format", "the output type to write",
-               "[html|json]"),
-        optopt("o", "output", "where to place the output", "PATH"),
-        optopt("", "crate-name", "specify the name of this crate", "NAME"),
-        optmulti("L", "library-path", "directory to add to crate search path",
-                 "DIR"),
-        optmulti("", "cfg", "pass a --cfg to rustc", ""),
-        optmulti("", "extern", "pass an --extern to rustc", "NAME=PATH"),
-        optmulti("", "plugin-path", "directory to load plugins from", "DIR"),
-        optmulti("", "passes", "list of passes to also run, you might want \
-                                to pass it multiple times; a value of `list` \
-                                will print available passes",
-                 "PASSES"),
-        optmulti("", "plugins", "space separated list of plugins to also load",
-                 "PLUGINS"),
-        optflag("", "no-defaults", "don't run the default passes"),
-        optflag("", "test", "run code examples as tests"),
-        optmulti("", "test-args", "arguments to pass to the test runner",
-                 "ARGS"),
-        optopt("", "target", "target triple to document", "TRIPLE"),
-        optmulti("", "markdown-css", "CSS files to include via <link> in a rendered Markdown file",
-                 "FILES"),
-        optmulti("", "html-in-header",
-                 "files to include inline in the <head> section of a rendered Markdown file \
-                 or generated documentation",
-                 "FILES"),
-        optmulti("", "html-before-content",
-                 "files to include inline between <body> and the content of a rendered \
-                 Markdown file or generated documentation",
-                 "FILES"),
-        optmulti("", "html-after-content",
-                 "files to include inline between the content and </body> of a rendered \
-                 Markdown file or generated documentation",
-                 "FILES"),
-        optopt("", "markdown-playground-url",
-               "URL to send code snippets to", "URL"),
-        optflag("", "markdown-no-toc", "don't include table of contents"),
-        optopt("e", "extend-css",
-               "to redefine some css rules with a given file to generate doc with your \
-                own theme", "PATH"),
-        optmulti("Z", "", "internal and debugging options (only on nightly build)", "FLAG"),
+        stable(optflag("h", "help", "show this help message")),
+        stable(optflag("V", "version", "print rustdoc's version")),
+        stable(optflag("v", "verbose", "use verbose output")),
+        stable(optopt("r", "input-format", "the input type of the specified file",
+                      "[rust|json]")),
+        stable(optopt("w", "output-format", "the output type to write",
+                      "[html|json]")),
+        stable(optopt("o", "output", "where to place the output", "PATH")),
+        stable(optopt("", "crate-name", "specify the name of this crate", "NAME")),
+        stable(optmulti("L", "library-path", "directory to add to crate search path",
+                        "DIR")),
+        stable(optmulti("", "cfg", "pass a --cfg to rustc", "")),
+        stable(optmulti("", "extern", "pass an --extern to rustc", "NAME=PATH")),
+        stable(optmulti("", "plugin-path", "directory to load plugins from", "DIR")),
+        stable(optmulti("", "passes",
+                        "list of passes to also run, you might want \
+                         to pass it multiple times; a value of `list` \
+                         will print available passes",
+                        "PASSES")),
+        stable(optmulti("", "plugins", "space separated list of plugins to also load",
+                        "PLUGINS")),
+        stable(optflag("", "no-defaults", "don't run the default passes")),
+        stable(optflag("", "test", "run code examples as tests")),
+        stable(optmulti("", "test-args", "arguments to pass to the test runner",
+                        "ARGS")),
+        stable(optopt("", "target", "target triple to document", "TRIPLE")),
+        stable(optmulti("", "markdown-css",
+                        "CSS files to include via <link> in a rendered Markdown file",
+                        "FILES")),
+        stable(optmulti("", "html-in-header",
+                        "files to include inline in the <head> section of a rendered Markdown file \
+                         or generated documentation",
+                        "FILES")),
+        stable(optmulti("", "html-before-content",
+                        "files to include inline between <body> and the content of a rendered \
+                         Markdown file or generated documentation",
+                        "FILES")),
+        stable(optmulti("", "html-after-content",
+                        "files to include inline between the content and </body> of a rendered \
+                         Markdown file or generated documentation",
+                        "FILES")),
+        stable(optopt("", "markdown-playground-url",
+                      "URL to send code snippets to", "URL")),
+        stable(optflag("", "markdown-no-toc", "don't include table of contents")),
+        unstable(optopt("e", "extend-css",
+                        "to redefine some css rules with a given file to generate doc with your \
+                         own theme", "PATH")),
+        unstable(optmulti("Z", "",
+                          "internal and debugging options (only on nightly build)", "FLAG")),
     )
 }
 
 pub fn usage(argv0: &str) {
     println!("{}",
              getopts::usage(&format!("{} [options] <input>", argv0),
-                            &opts()));
-}
-
-fn check_unstable_flag_enabled(nightly_build: bool, has_z_unstable_options: bool,
-                               flag_name: &str) {
-    // check if unstable for --extend-css option
-    let e = if !nightly_build {
-        format!("the option `{}` is only accepted on the nightly compiler", flag_name)
-    } else if !has_z_unstable_options {
-        format!("the `-Z unstable-options` flag must also be passed to enable the flag `{}`",
-                flag_name)
-    } else {
-        return
-    };
-    early_error(ErrorOutputType::default(), &e)
+                            &opts().into_iter()
+                                   .map(|x| x.opt_group)
+                                   .collect::<Vec<getopts::OptGroup>>()));
 }
 
 pub fn main_args(args: &[String]) -> isize {
-    let matches = match getopts::getopts(&args[1..], &opts()) {
+    let all_groups: Vec<getopts::OptGroup> = opts()
+                                             .into_iter()
+                                             .map(|x| x.opt_group)
+                                             .collect();
+    let matches = match getopts::getopts(&args[1..], &all_groups) {
         Ok(m) => m,
         Err(err) => {
             println!("{}", err);
             return 1;
         }
     };
+    // Check for unstable options.
+    nightly_options::check_nightly_options(&matches, &opts());
+
     if matches.opt_present("h") || matches.opt_present("help") {
         usage(&args[0]);
         return 0;
@@ -277,24 +276,7 @@ pub fn main_args(args: &[String]) -> isize {
     let css_file_extension = matches.opt_str("e").map(|s| PathBuf::from(&s));
     let cfgs = matches.opt_strs("cfg");
 
-    // we now check if unstable options are allowed and if we're in a nightly build
-    let mut has_z_unstable_options = false;
-    for flag in matches.opt_strs("Z").iter() {
-        if *flag != "unstable-options" {
-            println!("Unknown flag for `Z` option: {}", flag);
-            return 1;
-        } else {
-            has_z_unstable_options = true;
-        }
-    }
-    let nightly_build = get_unstable_features_setting();
-    let nightly_build = match nightly_build {
-                            UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
-                            _ => false,
-                        };
-
     if let Some(ref p) = css_file_extension {
-        check_unstable_flag_enabled(nightly_build, has_z_unstable_options, "extend-css");
         if !p.is_file() {
             println!("{}", "--extend-css option must take a css file as input");
             return 1;