diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index b7f78288b2b62..dccac26e07e69 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -658,7 +658,7 @@ pub const fn must_use(value: T) -> T { /// } /// } /// ``` -#[unstable(feature = "likely_unlikely", issue = "136873")] +#[unstable(feature = "likely_unlikely", issue = "151619")] #[inline(always)] pub const fn likely(b: bool) -> bool { crate::intrinsics::likely(b) @@ -708,7 +708,7 @@ pub const fn likely(b: bool) -> bool { /// } /// } /// ``` -#[unstable(feature = "likely_unlikely", issue = "136873")] +#[unstable(feature = "likely_unlikely", issue = "151619")] #[inline(always)] pub const fn unlikely(b: bool) -> bool { crate::intrinsics::unlikely(b) @@ -717,6 +717,10 @@ pub const fn unlikely(b: bool) -> bool { /// Hints to the compiler that given path is cold, i.e., unlikely to be taken. The compiler may /// choose to optimize paths that are not cold at the expense of paths that are cold. /// +/// Note that like all hints, the exact effect to codegen is not guaranteed. Using `cold_path` +/// can actually *decrease* performance if the branch is called more than expected. It is advisable +/// to perform benchmarks to tell if this function is useful. +/// /// # Examples /// /// ``` @@ -741,6 +745,38 @@ pub const fn unlikely(b: bool) -> bool { /// } /// } /// ``` +/// +/// This can also be used to implement `likely` and `unlikely` helpers to hint the condition rather +/// than the branch: +/// +/// ``` +/// #![feature(cold_path)] +/// use core::hint::cold_path; +/// +/// #[inline(always)] +/// pub const fn likely(b: bool) -> bool { +/// if !b { +/// cold_path(); +/// } +/// b +/// } +/// +/// #[inline(always)] +/// pub const fn unlikely(b: bool) -> bool { +/// if b { +/// cold_path(); +/// } +/// b +/// } +/// +/// fn foo(x: i32) { +/// if likely(x > 0) { +/// println!("this branch is likely to be taken"); +/// } else { +/// println!("this branch is unlikely to be taken"); +/// } +/// } +/// ``` #[unstable(feature = "cold_path", issue = "136873")] #[inline(always)] pub const fn cold_path() { diff --git a/src/tools/compiletest/src/directives/auxiliary.rs b/src/tools/compiletest/src/directives/auxiliary.rs index 1d5b7926a8e34..14cbab640eb6b 100644 --- a/src/tools/compiletest/src/directives/auxiliary.rs +++ b/src/tools/compiletest/src/directives/auxiliary.rs @@ -25,6 +25,13 @@ pub struct AuxCrate { pub path: String, } +/// The value of a `proc-macro` directive. +#[derive(Clone, Debug, Default)] +pub(crate) struct ProcMacro { + /// With `proc-macro: bar.rs` this will be `bar.rs`. + pub path: String, +} + /// Properties parsed from `aux-*` test directives. #[derive(Clone, Debug, Default)] pub(crate) struct AuxProps { @@ -37,7 +44,7 @@ pub(crate) struct AuxProps { /// to build and pass with the `--extern` flag. pub(crate) crates: Vec, /// Same as `builds`, but for proc-macros. - pub(crate) proc_macros: Vec, + pub(crate) proc_macros: Vec, /// Similar to `builds`, but also uses the resulting dylib as a /// `-Zcodegen-backend` when compiling the test file. pub(crate) codegen_backend: Option, @@ -53,7 +60,7 @@ impl AuxProps { .chain(builds.iter().map(String::as_str)) .chain(bins.iter().map(String::as_str)) .chain(crates.iter().map(|c| c.path.as_str())) - .chain(proc_macros.iter().map(String::as_str)) + .chain(proc_macros.iter().map(|p| p.path.as_str())) .chain(codegen_backend.iter().map(String::as_str)) } } @@ -74,8 +81,8 @@ pub(super) fn parse_and_update_aux( config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string()); config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string()); config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate); - config - .push_name_value_directive(ln, PROC_MACRO, &mut aux.proc_macros, |r| r.trim().to_string()); + config.push_name_value_directive(ln, PROC_MACRO, &mut aux.proc_macros, parse_proc_macro); + if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) { aux.codegen_backend = Some(r.trim().to_owned()); } @@ -99,3 +106,7 @@ fn parse_aux_crate(r: String) -> AuxCrate { AuxCrate { extern_modifiers: modifiers, name, path } } + +fn parse_proc_macro(r: String) -> ProcMacro { + ProcMacro { path: r.trim().to_string() } +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index dfbe84d5da721..2bfb73f05d169 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1298,13 +1298,13 @@ impl<'test> TestCx<'test> { } for proc_macro in &self.props.aux.proc_macros { - self.build_auxiliary(proc_macro, &aux_dir, Some(AuxType::ProcMacro)); - let crate_name = path_to_crate_name(proc_macro); + self.build_auxiliary(&proc_macro.path, &aux_dir, Some(AuxType::ProcMacro)); + let crate_name = path_to_crate_name(&proc_macro.path); add_extern( rustc, None, // `extern_modifiers` &crate_name, - proc_macro, + &proc_macro.path, AuxType::ProcMacro, ); }