diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs
index 571721ed40c..6aac627729c 100644
--- a/src/librustc/back/rpath.rs
+++ b/src/librustc/back/rpath.rs
@@ -168,6 +168,7 @@ pub fn get_absolute_rpath(lib: &Path) -> Path {
     os::make_absolute(lib).dir_path()
 }
 
+#[cfg(stage0)]
 pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
     let install_prefix = env!("CFG_PREFIX");
 
@@ -179,6 +180,14 @@ pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
     os::make_absolute(&Path(install_prefix).push_rel(&tlib))
 }
 
+#[cfg(not(stage0))]
+pub fn get_install_prefix_rpath(target_triple: &str) -> Path {
+    let install_prefix = env!("CFG_PREFIX");
+
+    let tlib = filesearch::relative_target_lib_path(target_triple);
+    os::make_absolute(&Path(install_prefix).push_rel(&tlib))
+}
+
 pub fn minimize_rpaths(rpaths: &[Path]) -> ~[Path] {
     let mut set = HashSet::new();
     let mut minimized = ~[];
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 28c7df4b33a..e349502d143 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -578,6 +578,7 @@ pub fn build_target_config(sopts: @session::options,
     return target_cfg;
 }
 
+#[cfg(stage0)]
 pub fn host_triple() -> ~str {
     // Get the host triple out of the build environment. This ensures that our
     // idea of the host triple is the same as for the set of libraries we've
@@ -595,6 +596,19 @@ pub fn host_triple() -> ~str {
         };
 }
 
+#[cfg(not(stage0))]
+pub fn host_triple() -> ~str {
+    // Get the host triple out of the build environment. This ensures that our
+    // idea of the host triple is the same as for the set of libraries we've
+    // actually built.  We can't just take LLVM's host triple because they
+    // normalize all ix86 architectures to i386.
+    //
+    // Instead of grabbing the host triple (for the current host), we grab (at
+    // compile time) the target triple that this rustc is built with and
+    // calling that (at runtime) the host triple.
+    (env!("CFG_COMPILER_TRIPLE")).to_owned()
+}
+
 pub fn build_session_options(binary: @str,
                              matches: &getopts::Matches,
                              demitter: diagnostic::Emitter)
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index 2422be3960b..e18879464e8 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -186,6 +186,7 @@ fn get_rustpkg_lib_path_nearest() -> Result<Path, ~str> {
 
 // The name of the directory rustc expects libraries to be located.
 // On Unix should be "lib", on windows "bin"
+#[cfg(stage0)]
 pub fn libdir() -> ~str {
    let libdir = env!("CFG_LIBDIR");
    if libdir.is_empty() {
@@ -193,3 +194,8 @@ pub fn libdir() -> ~str {
    }
    libdir.to_owned()
 }
+
+#[cfg(not(stage0))]
+pub fn libdir() -> ~str {
+    (env!("CFG_LIBDIR")).to_owned()
+}
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index f55fdd22c9a..43953a50e15 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -4994,7 +4994,9 @@ impl Resolver {
                             if self.structs.contains(&class_id) => {
                         self.record_def(expr.id, definition);
                     }
-                    _ => {
+                    result => {
+                        debug!("(resolving expression) didn't find struct \
+                                def: %?", result);
                         self.session.span_err(
                             path.span,
                             fmt!("`%s` does not name a structure",
diff --git a/src/librustc/rustc.rs b/src/librustc/rustc.rs
index 5bc22db0ca1..369045500ad 100644
--- a/src/librustc/rustc.rs
+++ b/src/librustc/rustc.rs
@@ -117,6 +117,7 @@ mod std {
 }
 */
 
+#[cfg(stage0)]
 pub fn version(argv0: &str) {
     let mut vers = ~"unknown version";
     let env_vers = env!("CFG_VERSION");
@@ -125,6 +126,16 @@ pub fn version(argv0: &str) {
     printfln!("host: %s", host_triple());
 }
 
+#[cfg(not(stage0))]
+pub fn version(argv0: &str) {
+    let vers = match option_env!("CFG_VERSION") {
+        Some(vers) => vers,
+        None => "unknown version"
+    };
+    printfln!("%s %s", argv0, vers);
+    printfln!("host: %s", host_triple());
+}
+
 pub fn usage(argv0: &str) {
     let message = fmt!("Usage: %s [OPTIONS] INPUT", argv0);
     printfln!("%s\
diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs
index ee0ec664e1b..b5d97427baf 100644
--- a/src/libsyntax/ext/asm.rs
+++ b/src/libsyntax/ext/asm.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -59,7 +59,7 @@ pub fn expand_asm(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
         match state {
             Asm => {
                 asm = expr_to_str(cx, p.parse_expr(),
-                                  ~"inline assembly must be a string literal.");
+                                  "inline assembly must be a string literal.");
             }
             Outputs => {
                 while *p.token != token::EOF &&
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index dc20994b49f..1e696451701 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -148,7 +148,9 @@ pub fn syntax_expander_table() -> SyntaxEnv {
         intern(&"auto_decode"),
         @SE(ItemDecorator(ext::auto_encode::expand_auto_decode)));
     syntax_expanders.insert(intern(&"env"),
-                            builtin_normal_tt(ext::env::expand_syntax_ext));
+                            builtin_normal_tt(ext::env::expand_env));
+    syntax_expanders.insert(intern(&"option_env"),
+                            builtin_normal_tt(ext::env::expand_option_env));
     syntax_expanders.insert(intern("bytes"),
                             builtin_normal_tt(ext::bytes::expand_syntax_ext));
     syntax_expanders.insert(intern("concat_idents"),
@@ -313,7 +315,7 @@ impl ExtCtxt {
     }
 }
 
-pub fn expr_to_str(cx: @ExtCtxt, expr: @ast::expr, err_msg: ~str) -> @str {
+pub fn expr_to_str(cx: @ExtCtxt, expr: @ast::expr, err_msg: &str) -> @str {
     match expr.node {
       ast::expr_lit(l) => match l.node {
         ast::lit_str(s) => s,
@@ -538,8 +540,8 @@ mod test {
         a.insert (@"abc",@15);
         let m = MapChain::new(~a);
         m.insert (@"def",@16);
-        // FIXME: #4492 (ICE)  assert_eq!(m.find(&@"abc"),Some(@15));
-        //  ....               assert_eq!(m.find(&@"def"),Some(@16));
+        assert_eq!(m.find(&@"abc"),Some(@15));
+        assert_eq!(m.find(&@"def"),Some(@16));
         assert_eq!(*(m.find(&@"abc").unwrap()),15);
         assert_eq!(*(m.find(&@"def").unwrap()),16);
         let n = m.push_frame();
@@ -551,8 +553,8 @@ mod test {
         assert_eq!(*(n.find(&@"abc").unwrap()),15);
         assert_eq!(*(n.find(&@"def").unwrap()),17);
         // ... but m still has the old ones
-        // FIXME: #4492: assert_eq!(m.find(&@"abc"),Some(@15));
-        // FIXME: #4492: assert_eq!(m.find(&@"def"),Some(@16));
+        assert_eq!(m.find(&@"abc"),Some(@15));
+        assert_eq!(m.find(&@"def"),Some(@16));
         assert_eq!(*(m.find(&@"abc").unwrap()),15);
         assert_eq!(*(m.find(&@"def").unwrap()),16);
     }
diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs
index a6cb6155878..c9e01b0f0d5 100644
--- a/src/libsyntax/ext/env.rs
+++ b/src/libsyntax/ext/env.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -22,17 +22,35 @@ use ext::build::AstBuilder;
 
 use std::os;
 
-pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
+pub fn expand_option_env(ext_cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
     -> base::MacResult {
-
-    let var = get_single_str_from_tts(cx, sp, tts, "env!");
-
-    // FIXME (#2248): if this was more thorough it would manufacture an
-    // Option<str> rather than just an maybe-empty string.
+    let var = get_single_str_from_tts(ext_cx, sp, tts, "option_env!");
 
     let e = match os::getenv(var) {
-      None => cx.expr_str(sp, @""),
-      Some(s) => cx.expr_str(sp, s.to_managed())
+      None => quote_expr!(::std::option::None),
+      Some(s) => quote_expr!(::std::option::Some($s))
+    };
+    MRExpr(e)
+}
+
+pub fn expand_env(ext_cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
+    -> base::MacResult {
+    let exprs = get_exprs_from_tts(ext_cx, sp, tts);
+
+    if exprs.len() == 0 {
+        ext_cx.span_fatal(sp, "env! takes 1 or 2 arguments");
+    }
+
+    let var = expr_to_str(ext_cx, exprs[0], "expected string literal");
+    let msg = match exprs.len() {
+        1 => fmt!("Environment variable %s not defined", var).to_managed(),
+        2 => expr_to_str(ext_cx, exprs[1], "expected string literal"),
+        _ => ext_cx.span_fatal(sp, "env! takes 1 or 2 arguments")
+    };
+
+    let e = match os::getenv(var) {
+        None => ext_cx.span_fatal(sp, msg),
+        Some(s) => ext_cx.expr_str(sp, s.to_managed())
     };
     MRExpr(e)
 }
diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs
index 2dbf6887a21..008545c9729 100644
--- a/src/libsyntax/ext/fmt.rs
+++ b/src/libsyntax/ext/fmt.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -32,7 +32,7 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree])
     }
     let fmt =
         expr_to_str(cx, args[0],
-                    ~"first argument to fmt! must be a string literal.");
+                    "first argument to fmt! must be a string literal.");
     let fmtspan = args[0].span;
     debug!("Format string: %s", fmt);
     fn parse_fmt_err_(cx: @ExtCtxt, sp: span, msg: &str) -> ! {
diff --git a/src/test/compile-fail/extenv-arg-2-not-string-literal.rs b/src/test/compile-fail/extenv-arg-2-not-string-literal.rs
new file mode 100644
index 00000000000..c2362689721
--- /dev/null
+++ b/src/test/compile-fail/extenv-arg-2-not-string-literal.rs
@@ -0,0 +1,11 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() { env!("one", 10); } //~ ERROR: expected string literal
diff --git a/src/test/compile-fail/extenv-no-args.rs b/src/test/compile-fail/extenv-no-args.rs
index 7ff1357dcf3..afa47dbe744 100644
--- a/src/test/compile-fail/extenv-no-args.rs
+++ b/src/test/compile-fail/extenv-no-args.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,6 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: env! takes 1 argument
-
-fn main() { env!(); }
+fn main() { env!(); } //~ ERROR: env! takes 1 or 2 arguments
diff --git a/src/test/compile-fail/extenv-not-defined-custom.rs b/src/test/compile-fail/extenv-not-defined-custom.rs
new file mode 100644
index 00000000000..485b6c09f0a
--- /dev/null
+++ b/src/test/compile-fail/extenv-not-defined-custom.rs
@@ -0,0 +1,11 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() { env!("__HOPEFULLY_NOT_DEFINED__", "my error message"); } //~ ERROR: my error message
diff --git a/src/test/compile-fail/extenv-not-defined-default.rs b/src/test/compile-fail/extenv-not-defined-default.rs
new file mode 100644
index 00000000000..d7a543c045a
--- /dev/null
+++ b/src/test/compile-fail/extenv-not-defined-default.rs
@@ -0,0 +1,11 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() { env!("__HOPEFULLY_NOT_DEFINED__"); } //~ ERROR: Environment variable __HOPEFULLY_NOT_DEFINED__ not defined
diff --git a/src/test/compile-fail/extenv-not-string-literal.rs b/src/test/compile-fail/extenv-not-string-literal.rs
index 3f09f81b85b..07ce47a14d8 100644
--- a/src/test/compile-fail/extenv-not-string-literal.rs
+++ b/src/test/compile-fail/extenv-not-string-literal.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,6 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:requires a string
-
-fn main() { env!(10); }
+fn main() { env!(10, "two"); } //~ ERROR: expected string literal
diff --git a/src/test/compile-fail/extenv-too-many-args.rs b/src/test/compile-fail/extenv-too-many-args.rs
index b1b2001abc3..c6c4f0ec6b8 100644
--- a/src/test/compile-fail/extenv-too-many-args.rs
+++ b/src/test/compile-fail/extenv-too-many-args.rs
@@ -8,6 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: env! takes 1 argument
-
-fn main() { env!("one", "two"); }
+fn main() { env!("one", "two", "three"); } //~ ERROR: env! takes 1 or 2 arguments
diff --git a/src/test/compile-fail/extoption_env-no-args.rs b/src/test/compile-fail/extoption_env-no-args.rs
new file mode 100644
index 00000000000..fd56756584a
--- /dev/null
+++ b/src/test/compile-fail/extoption_env-no-args.rs
@@ -0,0 +1,11 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() { option_env!(); } //~ ERROR: option_env! takes 1 argument
diff --git a/src/test/compile-fail/extoption_env-not-string-literal.rs b/src/test/compile-fail/extoption_env-not-string-literal.rs
new file mode 100644
index 00000000000..10f6c34980e
--- /dev/null
+++ b/src/test/compile-fail/extoption_env-not-string-literal.rs
@@ -0,0 +1,11 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() { option_env!(10); } //~ ERROR: requires a string
diff --git a/src/test/compile-fail/extoption_env-too-many-args.rs b/src/test/compile-fail/extoption_env-too-many-args.rs
new file mode 100644
index 00000000000..b31e857c14e
--- /dev/null
+++ b/src/test/compile-fail/extoption_env-too-many-args.rs
@@ -0,0 +1,11 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() { option_env!("one", "two"); } //~ ERROR: option_env! takes 1 argument
diff --git a/src/test/run-pass/extoption_env-not-defined.rs b/src/test/run-pass/extoption_env-not-defined.rs
new file mode 100644
index 00000000000..412efcc25a8
--- /dev/null
+++ b/src/test/run-pass/extoption_env-not-defined.rs
@@ -0,0 +1,14 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let opt: Option<&'static str> = option_env!("__HOPEFULLY_DOESNT_EXIST__");
+    assert!(opt.is_none());
+}