about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--src/libcore/option.rs4
-rw-r--r--src/libcore/ptr/mod.rs4
-rw-r--r--src/librustc/session/config.rs65
-rw-r--r--src/librustc_codegen_llvm/back/lto.rs4
-rw-r--r--src/librustc_driver/lib.rs2
-rw-r--r--src/librustc_errors/emitter.rs5
-rw-r--r--src/librustc_interface/Cargo.toml1
-rw-r--r--src/librustc_interface/interface.rs63
-rw-r--r--src/librustc_interface/lib.rs3
-rw-r--r--src/librustc_interface/tests.rs (renamed from src/librustc/session/config/tests.rs)78
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/test.rs2
-rw-r--r--src/libstd/ffi/c_str.rs26
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/test/ui/consts/miri_unleashed/non_const_fn.rs13
-rw-r--r--src/test/ui/consts/miri_unleashed/non_const_fn.stderr29
-rw-r--r--src/test/ui/issues/issue-17546.stderr4
18 files changed, 187 insertions, 120 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f6cfec308b2..b51095d4290 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3556,6 +3556,7 @@ dependencies = [
  "rustc_plugin_impl",
  "rustc_privacy",
  "rustc_resolve",
+ "rustc_target",
  "rustc_traits",
  "rustc_typeck",
  "serialize",
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 47e3a0d2167..09d4076c7fb 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -64,7 +64,7 @@
 //!
 //! fn check_optional(optional: Option<Box<i32>>) {
 //!     match optional {
-//!         Some(ref p) => println!("has value {}", p),
+//!         Some(p) => println!("has value {}", p),
 //!         None => println!("has no value"),
 //!     }
 //! }
@@ -83,7 +83,7 @@
 //! let msg = Some("howdy");
 //!
 //! // Take a reference to the contained string
-//! if let Some(ref m) = msg {
+//! if let Some(m) = &msg {
 //!     println!("{}", *m);
 //! }
 //!
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index 93391918595..3cc0a1cd75e 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -188,7 +188,7 @@ unsafe fn real_drop_in_place<T: ?Sized>(to_drop: &mut T) {
 /// let p: *const i32 = ptr::null();
 /// assert!(p.is_null());
 /// ```
-#[inline]
+#[inline(always)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
 pub const fn null<T>() -> *const T { 0 as *const T }
@@ -203,7 +203,7 @@ pub const fn null<T>() -> *const T { 0 as *const T }
 /// let p: *mut i32 = ptr::null_mut();
 /// assert!(p.is_null());
 /// ```
-#[inline]
+#[inline(always)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_promotable]
 pub const fn null_mut<T>() -> *mut T { 0 as *mut T }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 675e3bbd002..651f9393a31 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -7,24 +7,19 @@ use crate::session::{early_error, early_warn, Session};
 use crate::session::search_paths::SearchPath;
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_data_structures::sync::Lrc;
 
 use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
 use rustc_target::spec::{Target, TargetTriple};
 
 use syntax;
-use syntax::ast::{self, IntTy, UintTy, MetaItemKind};
+use syntax::ast::{self, IntTy, UintTy};
 use syntax::source_map::{FileName, FilePathMapping};
 use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION};
-use syntax::parse::new_parser_from_source_str;
-use syntax::parse::token;
-use syntax::sess::ParseSess;
 use syntax::symbol::{sym, Symbol};
 use syntax::feature_gate::UnstableFeatures;
-use syntax::source_map::SourceMap;
 
 use errors::emitter::HumanReadableErrorType;
-use errors::{ColorConfig, FatalError, Handler, SourceMapperDyn};
+use errors::{ColorConfig, FatalError, Handler};
 
 use getopts;
 
@@ -1854,59 +1849,6 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
     opts
 }
 
-struct NullEmitter;
-
-impl errors::emitter::Emitter for NullEmitter {
-    fn emit_diagnostic(&mut self, _: &errors::Diagnostic) {}
-    fn source_map(&self) -> Option<&Lrc<SourceMapperDyn>> { None }
-}
-
-// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
-pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> {
-    syntax::with_default_globals(move || {
-        let cfg = cfgspecs.into_iter().map(|s| {
-
-            let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
-            let handler = Handler::with_emitter(false, None, Box::new(NullEmitter));
-            let sess = ParseSess::with_span_handler(handler, cm);
-            let filename = FileName::cfg_spec_source_code(&s);
-            let mut parser = new_parser_from_source_str(&sess, filename, s.to_string());
-
-            macro_rules! error {($reason: expr) => {
-                early_error(ErrorOutputType::default(),
-                            &format!(concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s));
-            }}
-
-            match &mut parser.parse_meta_item() {
-                Ok(meta_item) if parser.token == token::Eof => {
-                    if meta_item.path.segments.len() != 1 {
-                        error!("argument key must be an identifier");
-                    }
-                    match &meta_item.kind {
-                        MetaItemKind::List(..) => {
-                            error!(r#"expected `key` or `key="value"`"#);
-                        }
-                        MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
-                            error!("argument value must be a string");
-                        }
-                        MetaItemKind::NameValue(..) | MetaItemKind::Word => {
-                            let ident = meta_item.ident().expect("multi-segment cfg key");
-                            return (ident.name, meta_item.value_str());
-                        }
-                    }
-                }
-                Ok(..) => {}
-                Err(err) => err.cancel(),
-            }
-
-            error!(r#"expected `key` or `key="value"`"#);
-        }).collect::<ast::CrateConfig>();
-        cfg.into_iter().map(|(a, b)| {
-            (a.to_string(), b.map(|b| b.to_string()))
-        }).collect()
-    })
-}
-
 pub fn get_cmd_lint_options(matches: &getopts::Matches,
                             error_format: ErrorOutputType)
                             -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
@@ -2877,6 +2819,3 @@ mod dep_tracking {
         }
     }
 }
-
-#[cfg(test)]
-mod tests;
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index 7437b1e3c8a..b3be3d09f17 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -53,9 +53,7 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
 
     let symbol_filter = &|&(ref name, level): &(String, SymbolExportLevel)| {
         if level.is_below_threshold(export_threshold) {
-            let mut bytes = Vec::with_capacity(name.len() + 1);
-            bytes.extend(name.bytes());
-            Some(CString::new(bytes).unwrap())
+            Some(CString::new(name.as_str()).unwrap())
         } else {
             None
         }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index f33cb4e215d..bfcbec8b78f 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -167,7 +167,7 @@ pub fn run_compiler(
     };
 
     let sopts = config::build_session_options(&matches);
-    let cfg = config::parse_cfgspecs(matches.opt_strs("cfg"));
+    let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg"));
 
     let mut dummy_config = |sopts, cfg, diagnostic_output| {
         let mut config = interface::Config {
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 1e486786f68..e3b55a14133 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -12,7 +12,7 @@ use Destination::*;
 use syntax_pos::{SourceFile, Span, MultiSpan};
 
 use crate::{
-    Level, CodeSuggestion, Diagnostic, SubDiagnostic,
+    Level, CodeSuggestion, Diagnostic, SubDiagnostic, pluralise,
     SuggestionStyle, SourceMapper, SourceMapperDyn, DiagnosticId,
 };
 use crate::Level::Error;
@@ -1572,7 +1572,8 @@ impl EmitterWriter {
             }
         }
         if suggestions.len() > MAX_SUGGESTIONS {
-            let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS);
+            let others = suggestions.len() - MAX_SUGGESTIONS;
+            let msg = format!("and {} other candidate{}", others, pluralise!(others));
             buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle);
         } else if notice_capitalization {
             let msg = "notice the capitalization difference";
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index 7a0d931ca73..0d8d765a572 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -27,6 +27,7 @@ rustc_codegen_utils = { path = "../librustc_codegen_utils" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
 rustc_passes = { path = "../librustc_passes" }
+rustc_target = { path = "../librustc_target" }
 rustc_typeck = { path = "../librustc_typeck" }
 rustc_lint = { path = "../librustc_lint" }
 rustc_errors = { path = "../librustc_errors" }
diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs
index b26bd75c974..5e1ad3e61dd 100644
--- a/src/librustc_interface/interface.rs
+++ b/src/librustc_interface/interface.rs
@@ -3,7 +3,8 @@ use crate::util;
 pub use crate::passes::BoxedResolver;
 
 use rustc::lint;
-use rustc::session::config::{self, Input};
+use rustc::session::early_error;
+use rustc::session::config::{self, Input, ErrorOutputType};
 use rustc::session::{DiagnosticOutput, Session};
 use rustc::util::common::ErrorReported;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
@@ -14,9 +15,13 @@ use rustc_metadata::cstore::CStore;
 use std::path::PathBuf;
 use std::result;
 use std::sync::{Arc, Mutex};
-use syntax;
-use syntax::source_map::{FileLoader, SourceMap};
+use syntax::{self, parse};
+use syntax::ast::{self, MetaItemKind};
+use syntax::parse::token;
+use syntax::source_map::{FileName, FilePathMapping, FileLoader, SourceMap};
+use syntax::sess::ParseSess;
 use syntax_pos::edition;
+use rustc_errors::{Diagnostic, emitter::Emitter, Handler, SourceMapperDyn};
 
 pub type Result<T> = result::Result<T, ErrorReported>;
 
@@ -60,6 +65,58 @@ impl Compiler {
     }
 }
 
+/// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.
+pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String>)> {
+    struct NullEmitter;
+    impl Emitter for NullEmitter {
+        fn emit_diagnostic(&mut self, _: &Diagnostic) {}
+        fn source_map(&self) -> Option<&Lrc<SourceMapperDyn>> { None }
+    }
+
+    syntax::with_default_globals(move || {
+        let cfg = cfgspecs.into_iter().map(|s| {
+
+            let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+            let handler = Handler::with_emitter(false, None, Box::new(NullEmitter));
+            let sess = ParseSess::with_span_handler(handler, cm);
+            let filename = FileName::cfg_spec_source_code(&s);
+            let mut parser = parse::new_parser_from_source_str(&sess, filename, s.to_string());
+
+            macro_rules! error {($reason: expr) => {
+                early_error(ErrorOutputType::default(),
+                            &format!(concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s));
+            }}
+
+            match &mut parser.parse_meta_item() {
+                Ok(meta_item) if parser.token == token::Eof => {
+                    if meta_item.path.segments.len() != 1 {
+                        error!("argument key must be an identifier");
+                    }
+                    match &meta_item.kind {
+                        MetaItemKind::List(..) => {
+                            error!(r#"expected `key` or `key="value"`"#);
+                        }
+                        MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
+                            error!("argument value must be a string");
+                        }
+                        MetaItemKind::NameValue(..) | MetaItemKind::Word => {
+                            let ident = meta_item.ident().expect("multi-segment cfg key");
+                            return (ident.name, meta_item.value_str());
+                        }
+                    }
+                }
+                Ok(..) => {}
+                Err(err) => err.cancel(),
+            }
+
+            error!(r#"expected `key` or `key="value"`"#);
+        }).collect::<ast::CrateConfig>();
+        cfg.into_iter().map(|(a, b)| {
+            (a.to_string(), b.map(|b| b.to_string()))
+        }).collect()
+    })
+}
+
 /// The compiler configuration
 pub struct Config {
     /// Command line options
diff --git a/src/librustc_interface/lib.rs b/src/librustc_interface/lib.rs
index 6be36e9b900..53baf6556fb 100644
--- a/src/librustc_interface/lib.rs
+++ b/src/librustc_interface/lib.rs
@@ -18,3 +18,6 @@ pub mod util;
 mod proc_macro_decls;
 
 pub use interface::{run_compiler, Config};
+
+#[cfg(test)]
+mod tests;
diff --git a/src/librustc/session/config/tests.rs b/src/librustc_interface/tests.rs
index 061bbdc307f..7a57605da58 100644
--- a/src/librustc/session/config/tests.rs
+++ b/src/librustc_interface/tests.rs
@@ -1,25 +1,24 @@
-use getopts;
-use crate::lint;
-use crate::middle::cstore;
-use crate::session::config::{
-    build_configuration,
-    build_session_options,
-    to_crate_config,
-    parse_cfgspecs,
-};
-use crate::session::config::{LtoCli, LinkerPluginLto, SwitchWithOptPath, ExternEntry};
-use crate::session::build_session;
-use crate::session::search_paths::SearchPath;
+extern crate getopts;
+
+use crate::interface::parse_cfgspecs;
+
+use rustc::lint;
+use rustc::middle::cstore;
+use rustc::session::config::{build_configuration, build_session_options, to_crate_config};
+use rustc::session::config::{LtoCli, LinkerPluginLto, SwitchWithOptPath, ExternEntry};
+use rustc::session::config::{Externs, OutputType, OutputTypes, SymbolManglingVersion};
+use rustc::session::config::{rustc_optgroups, Options, ErrorOutputType, Passes};
+use rustc::session::build_session;
+use rustc::session::search_paths::SearchPath;
 use std::collections::{BTreeMap, BTreeSet};
 use std::iter::FromIterator;
 use std::path::PathBuf;
-use super::{Externs, OutputType, OutputTypes, SymbolManglingVersion};
 use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel};
 use syntax::symbol::sym;
 use syntax::edition::{Edition, DEFAULT_EDITION};
 use syntax;
-use super::Options;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::{ColorConfig, emitter::HumanReadableErrorType, registry};
 
 pub fn build_session_options_and_crate_config(
     matches: &getopts::Matches,
@@ -30,22 +29,23 @@ pub fn build_session_options_and_crate_config(
     )
 }
 
-impl ExternEntry {
-    fn new_public<S: Into<String>,
-                  I: IntoIterator<Item = Option<S>>>(locations: I) -> ExternEntry {
-        let locations: BTreeSet<_> = locations.into_iter().map(|o| o.map(|s| s.into()))
-            .collect();
-
-        ExternEntry {
-            locations,
-            is_private_dep: false
-        }
+fn new_public_extern_entry<S, I>(locations: I) -> ExternEntry
+where
+    S: Into<String>,
+    I: IntoIterator<Item = Option<S>>,
+{
+    let locations: BTreeSet<_> = locations.into_iter().map(|o| o.map(|s| s.into()))
+        .collect();
+
+    ExternEntry {
+        locations,
+        is_private_dep: false
     }
 }
 
 fn optgroups() -> getopts::Options {
     let mut opts = getopts::Options::new();
-    for group in super::rustc_optgroups() {
+    for group in rustc_optgroups() {
         (group.apply)(&mut opts);
     }
     return opts;
@@ -63,7 +63,7 @@ fn test_switch_implies_cfg_test() {
             Ok(m) => m,
             Err(f) => panic!("test_switch_implies_cfg_test: {}", f),
         };
-        let registry = errors::registry::Registry::new(&[]);
+        let registry = registry::Registry::new(&[]);
         let (sessopts, cfg) = build_session_options_and_crate_config(matches);
         let sess = build_session(sessopts, None, registry);
         let cfg = build_configuration(&sess, to_crate_config(cfg));
@@ -81,7 +81,7 @@ fn test_switch_implies_cfg_test_unless_cfg_test() {
             Ok(m) => m,
             Err(f) => panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f),
         };
-        let registry = errors::registry::Registry::new(&[]);
+        let registry = registry::Registry::new(&[]);
         let (sessopts, cfg) = build_session_options_and_crate_config(matches);
         let sess = build_session(sessopts, None, registry);
         let cfg = build_configuration(&sess, to_crate_config(cfg));
@@ -95,7 +95,7 @@ fn test_switch_implies_cfg_test_unless_cfg_test() {
 fn test_can_print_warnings() {
     syntax::with_default_globals(|| {
         let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap();
-        let registry = errors::registry::Registry::new(&[]);
+        let registry = registry::Registry::new(&[]);
         let (sessopts, _) = build_session_options_and_crate_config(&matches);
         let sess = build_session(sessopts, None, registry);
         assert!(!sess.diagnostic().can_emit_warnings());
@@ -105,7 +105,7 @@ fn test_can_print_warnings() {
         let matches = optgroups()
             .parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()])
             .unwrap();
-        let registry = errors::registry::Registry::new(&[]);
+        let registry = registry::Registry::new(&[]);
         let (sessopts, _) = build_session_options_and_crate_config(&matches);
         let sess = build_session(sessopts, None, registry);
         assert!(sess.diagnostic().can_emit_warnings());
@@ -113,7 +113,7 @@ fn test_can_print_warnings() {
 
     syntax::with_default_globals(|| {
         let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap();
-        let registry = errors::registry::Registry::new(&[]);
+        let registry = registry::Registry::new(&[]);
         let (sessopts, _) = build_session_options_and_crate_config(&matches);
         let sess = build_session(sessopts, None, registry);
         assert!(sess.diagnostic().can_emit_warnings());
@@ -172,33 +172,33 @@ fn test_externs_tracking_hash_different_construction_order() {
     v1.externs = Externs::new(mk_map(vec![
         (
             String::from("a"),
-            ExternEntry::new_public(vec![Some("b"), Some("c")])
+            new_public_extern_entry(vec![Some("b"), Some("c")])
         ),
         (
             String::from("d"),
-            ExternEntry::new_public(vec![Some("e"), Some("f")])
+            new_public_extern_entry(vec![Some("e"), Some("f")])
         ),
     ]));
 
     v2.externs = Externs::new(mk_map(vec![
         (
             String::from("d"),
-            ExternEntry::new_public(vec![Some("e"), Some("f")])
+            new_public_extern_entry(vec![Some("e"), Some("f")])
         ),
         (
             String::from("a"),
-            ExternEntry::new_public(vec![Some("b"), Some("c")])
+            new_public_extern_entry(vec![Some("b"), Some("c")])
         ),
     ]));
 
     v3.externs = Externs::new(mk_map(vec![
         (
             String::from("a"),
-            ExternEntry::new_public(vec![Some("b"), Some("c")])
+            new_public_extern_entry(vec![Some("b"), Some("c")])
         ),
         (
             String::from("d"),
-            ExternEntry::new_public(vec![Some("f"), Some("e")])
+            new_public_extern_entry(vec![Some("f"), Some("e")])
         ),
     ]));
 
@@ -282,9 +282,9 @@ fn test_search_paths_tracking_hash_different_order() {
     let mut v3 = Options::default();
     let mut v4 = Options::default();
 
-    const JSON: super::ErrorOutputType = super::ErrorOutputType::Json {
+    const JSON: ErrorOutputType = ErrorOutputType::Json {
         pretty: false,
-        json_rendered: super::HumanReadableErrorType::Default(super::ColorConfig::Never),
+        json_rendered: HumanReadableErrorType::Default(ColorConfig::Never),
     };
 
     // Reference
@@ -455,7 +455,7 @@ fn test_codegen_options_tracking_hash() {
     opts.cg.codegen_units = Some(42);
     assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
 
-    opts.cg.remark = super::Passes::Some(vec![String::from("pass1"), String::from("pass2")]);
+    opts.cg.remark = Passes::Some(vec![String::from("pass1"), String::from("pass2")]);
     assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
 
     opts.cg.save_temps = true;
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 00265caa965..2337ec5a52c 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -329,7 +329,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
 
     let config = interface::Config {
         opts: sessopts,
-        crate_cfg: config::parse_cfgspecs(cfgs),
+        crate_cfg: interface::parse_cfgspecs(cfgs),
         input,
         input_path: cpath,
         output_file: None,
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 0be6340df96..01b897ab364 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -67,7 +67,7 @@ pub fn run(options: Options) -> i32 {
     cfgs.push("doctest".to_owned());
     let config = interface::Config {
         opts: sessopts,
-        crate_cfg: config::parse_cfgspecs(cfgs),
+        crate_cfg: interface::parse_cfgspecs(cfgs),
         input,
         input_path: None,
         output_file: None,
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 483f2ba52ec..6dcda986310 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -327,7 +327,31 @@ impl CString {
     /// [`NulError`]: struct.NulError.html
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
-        Self::_new(t.into())
+        trait SpecIntoVec {
+            fn into_vec(self) -> Vec<u8>;
+        }
+        impl<T: Into<Vec<u8>>> SpecIntoVec for T {
+            default fn into_vec(self) -> Vec<u8> {
+                self.into()
+            }
+        }
+        // Specialization for avoiding reallocation.
+        impl SpecIntoVec for &'_ [u8] {
+            fn into_vec(self) -> Vec<u8> {
+                let mut v = Vec::with_capacity(self.len() + 1);
+                v.extend(self);
+                v
+            }
+        }
+        impl SpecIntoVec for &'_ str {
+            fn into_vec(self) -> Vec<u8> {
+                let mut v = Vec::with_capacity(self.len() + 1);
+                v.extend(self.as_bytes());
+                v
+            }
+        }
+
+        Self::_new(SpecIntoVec::into_vec(t))
     }
 
     fn _new(bytes: Vec<u8>) -> Result<CString, NulError> {
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index af6cb656444..50a1226cc1d 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -297,6 +297,7 @@
 #![feature(slice_concat_ext)]
 #![feature(slice_internals)]
 #![feature(slice_patterns)]
+#![feature(specialization)]
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(stdsimd)]
diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.rs b/src/test/ui/consts/miri_unleashed/non_const_fn.rs
new file mode 100644
index 00000000000..e1ac4306575
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/non_const_fn.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Zunleash-the-miri-inside-of-you
+#![warn(const_err)]
+
+// A test demonstrating that we prevent calling non-const fn during CTFE.
+
+fn foo() {}
+
+const C: () = foo(); //~ WARN: skipping const checks
+//~^ WARN any use of this value will cause an error
+
+fn main() {
+    println!("{:?}", C); //~ ERROR: evaluation of constant expression failed
+}
diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
new file mode 100644
index 00000000000..7a574b34304
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
@@ -0,0 +1,29 @@
+warning: skipping const checks
+  --> $DIR/non_const_fn.rs:8:15
+   |
+LL | const C: () = foo();
+   |               ^^^^^
+
+warning: any use of this value will cause an error
+  --> $DIR/non_const_fn.rs:8:15
+   |
+LL | const C: () = foo();
+   | --------------^^^^^-
+   |               |
+   |               calling non-const function `foo`
+   |
+note: lint level defined here
+  --> $DIR/non_const_fn.rs:2:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
+error[E0080]: evaluation of constant expression failed
+  --> $DIR/non_const_fn.rs:12:22
+   |
+LL |     println!("{:?}", C);
+   |                      ^ referenced constant has errors
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr
index 4a0fb186e49..291086d4f69 100644
--- a/src/test/ui/issues/issue-17546.stderr
+++ b/src/test/ui/issues/issue-17546.stderr
@@ -27,7 +27,7 @@ LL |     use std::prelude::v1::Result;
    |
 LL |     use std::result::Result;
    |
-     and 1 other candidates
+     and 1 other candidate
 
 error[E0573]: expected type, found variant `Result`
   --> $DIR/issue-17546.rs:28:13
@@ -44,7 +44,7 @@ LL | use std::prelude::v1::Result;
    |
 LL | use std::result::Result;
    |
-     and 1 other candidates
+     and 1 other candidate
 
 error[E0573]: expected type, found variant `NoResult`
   --> $DIR/issue-17546.rs:33:15