diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 53899da183a3a..3b290e5a12919 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -262,6 +262,15 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option None, // only existed in 18 ("arm", "fp16") => Some(LLVMFeature::new("fullfp16")), + // NVPTX targets added in LLVM 20 + ("nvptx64", "sm_100") if get_version().0 < 20 => None, + ("nvptx64", "sm_100a") if get_version().0 < 20 => None, + ("nvptx64", "sm_101") if get_version().0 < 20 => None, + ("nvptx64", "sm_101a") if get_version().0 < 20 => None, + ("nvptx64", "sm_120") if get_version().0 < 20 => None, + ("nvptx64", "sm_120a") if get_version().0 < 20 => None, + ("nvptx64", "ptx86") if get_version().0 < 20 => None, + ("nvptx64", "ptx87") if get_version().0 < 20 => None, // Filter out features that are not supported by the current LLVM version ("loongarch64", "div32" | "lam-bh" | "lamcas" | "ld-seq-sa" | "scq") if get_version().0 < 20 => @@ -324,15 +333,12 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option TargetConfig { - // Add base features for the target. - // We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below. - // The reason is that if LLVM considers a feature implied but we do not, we don't want that to - // show up in `cfg`. That way, `cfg` is entirely under our control -- except for the handling of - // the target CPU, that is still expanded to target features (with all their implied features) - // by LLVM. let target_machine = create_informational_target_machine(sess, true); let (unstable_target_features, target_features) = cfg_target_feature(sess, |feature| { + // This closure determines whether the target CPU has the feature according to LLVM. We do + // *not* consider the `-Ctarget-feature`s here, as that will be handled later in + // `cfg_target_feature`. if let Some(feat) = to_llvm_features(sess, feature) { // All the LLVM features this expands to must be enabled. for llvm_feature in feat { diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index d984156c674c7..7e4341a823667 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -197,7 +197,10 @@ fn parse_rust_feature_flag<'a>( /// 2nd component of the return value, respectively). /// /// `target_base_has_feature` should check whether the given feature (a Rust feature name!) is -/// enabled in the "base" target machine, i.e., without applying `-Ctarget-feature`. +/// enabled in the "base" target machine, i.e., without applying `-Ctarget-feature`. Note that LLVM +/// may consider features to be implied that we do not and vice-versa. We want `cfg` to be entirely +/// consistent with Rust feature implications, and thus only consult LLVM to expand the target CPU +/// to target features. /// /// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled elsewhere. pub fn cfg_target_feature( @@ -211,7 +214,15 @@ pub fn cfg_target_feature( .rust_target_features() .iter() .filter(|(feature, _, _)| target_base_has_feature(feature)) - .map(|(feature, _, _)| Symbol::intern(feature)) + .flat_map(|(base_feature, _, _)| { + // Expand the direct base feature into all transitively-implied features. Note that we + // cannot simply use the `implied` field of the tuple since that only contains + // directly-implied features. + // + // Iteration order is irrelevant because we're collecting into an `UnordSet`. + #[allow(rustc::potential_query_instability)] + sess.target.implied_target_features(base_feature).into_iter().map(|f| Symbol::intern(f)) + }) .collect(); // Add enabled and remove disabled features. diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 3840cdf757507..8ace560d85d16 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -1,6 +1,7 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] +#![cfg_attr(bootstrap, feature(strict_overflow_ops))] #![doc(rust_logo)] #![feature(array_try_map)] #![feature(assert_matches)] @@ -10,7 +11,6 @@ #![feature(never_type)] #![feature(rustdoc_internals)] #![feature(slice_ptr_get)] -#![feature(strict_overflow_ops)] #![feature(trait_alias)] #![feature(try_blocks)] #![feature(unqualified_local_imports)] diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 1303b3317e05a..266a940b05459 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -327,6 +327,7 @@ declare_features! ( (unstable, m68k_target_feature, "1.85.0", Some(134328)), (unstable, mips_target_feature, "1.27.0", Some(44839)), (unstable, movrs_target_feature, "1.88.0", Some(137976)), + (unstable, nvptx_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)), (unstable, powerpc_target_feature, "1.27.0", Some(44839)), (unstable, prfchw_target_feature, "1.78.0", Some(44839)), (unstable, riscv_target_feature, "1.45.0", Some(44839)), diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index 2a5a34cdc6e94..464f4fc34b966 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs @@ -434,7 +434,7 @@ fn emit_mismatch_diagnostic<'tcx>( lints::MismatchedLifetimeSyntaxesSuggestion::Mixed { implicit_suggestions, explicit_anonymous_suggestions, - tool_only: false, + optional_alternative: false, } }); @@ -455,7 +455,10 @@ fn emit_mismatch_diagnostic<'tcx>( let implicit_suggestion = should_suggest_implicit.then(|| { let suggestions = make_implicit_suggestions(&suggest_change_to_implicit); - lints::MismatchedLifetimeSyntaxesSuggestion::Implicit { suggestions, tool_only: false } + lints::MismatchedLifetimeSyntaxesSuggestion::Implicit { + suggestions, + optional_alternative: false, + } }); tracing::debug!( @@ -508,7 +511,7 @@ fn build_mismatch_suggestion( lints::MismatchedLifetimeSyntaxesSuggestion::Explicit { lifetime_name, suggestions, - tool_only: false, + optional_alternative: false, } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index ef63c0dee8c2e..ac6147b163125 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3292,7 +3292,7 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSynta diag.subdiagnostic(s); for mut s in suggestions { - s.make_tool_only(); + s.make_optional_alternative(); diag.subdiagnostic(s); } } @@ -3303,33 +3303,33 @@ impl<'a, G: EmissionGuarantee> LintDiagnostic<'a, G> for MismatchedLifetimeSynta pub(crate) enum MismatchedLifetimeSyntaxesSuggestion { Implicit { suggestions: Vec, - tool_only: bool, + optional_alternative: bool, }, Mixed { implicit_suggestions: Vec, explicit_anonymous_suggestions: Vec<(Span, String)>, - tool_only: bool, + optional_alternative: bool, }, Explicit { lifetime_name: String, suggestions: Vec<(Span, String)>, - tool_only: bool, + optional_alternative: bool, }, } impl MismatchedLifetimeSyntaxesSuggestion { - fn make_tool_only(&mut self) { + fn make_optional_alternative(&mut self) { use MismatchedLifetimeSyntaxesSuggestion::*; - let tool_only = match self { - Implicit { tool_only, .. } | Mixed { tool_only, .. } | Explicit { tool_only, .. } => { - tool_only - } + let optional_alternative = match self { + Implicit { optional_alternative, .. } + | Mixed { optional_alternative, .. } + | Explicit { optional_alternative, .. } => optional_alternative, }; - *tool_only = true; + *optional_alternative = true; } } @@ -3337,22 +3337,40 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { fn add_to_diag(self, diag: &mut Diag<'_, G>) { use MismatchedLifetimeSyntaxesSuggestion::*; - let style = |tool_only| { - if tool_only { SuggestionStyle::CompletelyHidden } else { SuggestionStyle::ShowAlways } + let style = |optional_alternative| { + if optional_alternative { + SuggestionStyle::CompletelyHidden + } else { + SuggestionStyle::ShowAlways + } + }; + + let applicability = |optional_alternative| { + // `cargo fix` can't handle more than one fix for the same issue, + // so hide alternative suggestions from it by marking them as maybe-incorrect + if optional_alternative { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + } }; match self { - Implicit { suggestions, tool_only } => { + Implicit { suggestions, optional_alternative } => { let suggestions = suggestions.into_iter().map(|s| (s, String::new())).collect(); diag.multipart_suggestion_with_style( fluent::lint_mismatched_lifetime_syntaxes_suggestion_implicit, suggestions, - Applicability::MaybeIncorrect, - style(tool_only), + applicability(optional_alternative), + style(optional_alternative), ); } - Mixed { implicit_suggestions, explicit_anonymous_suggestions, tool_only } => { + Mixed { + implicit_suggestions, + explicit_anonymous_suggestions, + optional_alternative, + } => { let message = if implicit_suggestions.is_empty() { fluent::lint_mismatched_lifetime_syntaxes_suggestion_mixed_only_paths } else { @@ -3368,12 +3386,12 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { diag.multipart_suggestion_with_style( message, suggestions, - Applicability::MaybeIncorrect, - style(tool_only), + applicability(optional_alternative), + style(optional_alternative), ); } - Explicit { lifetime_name, suggestions, tool_only } => { + Explicit { lifetime_name, suggestions, optional_alternative } => { diag.arg("lifetime_name", lifetime_name); let msg = diag.eagerly_translate( fluent::lint_mismatched_lifetime_syntaxes_suggestion_explicit, @@ -3382,8 +3400,8 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { diag.multipart_suggestion_with_style( msg, suggestions, - Applicability::MaybeIncorrect, - style(tool_only), + applicability(optional_alternative), + style(optional_alternative), ); } } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 3b84c6b611016..9a5d7e725c980 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2839,7 +2839,7 @@ declare_lint! { /// [issue #79813]: https://github.com/rust-lang/rust/issues/79813 /// [future-incompatible]: ../index.md#future-incompatible-lints pub SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, - Warn, + Deny, "trailing semicolon in macro body used as expression", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::FutureReleaseError, diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 069b684ad09bb..fe62c3bc33fd4 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -171,6 +171,11 @@ fn main() { let cxxflags = output(&mut cmd); let mut cfg = cc::Build::new(); cfg.warnings(false); + + // Prevent critical warnings when we're compiling from rust-lang/rust CI + if std::env::var_os("CI").is_some() { + cfg.warnings_into_errors(true); + } for flag in cxxflags.split_whitespace() { // Ignore flags like `-m64` when we're doing a cross build if is_crossed && flag.starts_with("-m") { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d54175548e30e..752a335571821 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1512,6 +1512,7 @@ symbols! { not, notable_trait, note, + nvptx_target_feature, object_safe_for_dispatch, of, off, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index b2af99228fe6d..297d9ed84c504 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -517,6 +517,71 @@ const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; +const NVPTX_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("sm_20", Unstable(sym::nvptx_target_feature), &[]), + ("sm_21", Unstable(sym::nvptx_target_feature), &["sm_20"]), + ("sm_30", Unstable(sym::nvptx_target_feature), &["sm_21"]), + ("sm_32", Unstable(sym::nvptx_target_feature), &["sm_30"]), + ("sm_35", Unstable(sym::nvptx_target_feature), &["sm_32"]), + ("sm_37", Unstable(sym::nvptx_target_feature), &["sm_35"]), + ("sm_50", Unstable(sym::nvptx_target_feature), &["sm_37"]), + ("sm_52", Unstable(sym::nvptx_target_feature), &["sm_50"]), + ("sm_53", Unstable(sym::nvptx_target_feature), &["sm_52"]), + ("sm_60", Unstable(sym::nvptx_target_feature), &["sm_53"]), + ("sm_61", Unstable(sym::nvptx_target_feature), &["sm_60"]), + ("sm_62", Unstable(sym::nvptx_target_feature), &["sm_61"]), + ("sm_70", Unstable(sym::nvptx_target_feature), &["sm_62"]), + ("sm_72", Unstable(sym::nvptx_target_feature), &["sm_70"]), + ("sm_75", Unstable(sym::nvptx_target_feature), &["sm_72"]), + ("sm_80", Unstable(sym::nvptx_target_feature), &["sm_75"]), + ("sm_86", Unstable(sym::nvptx_target_feature), &["sm_80"]), + ("sm_87", Unstable(sym::nvptx_target_feature), &["sm_86"]), + ("sm_89", Unstable(sym::nvptx_target_feature), &["sm_87"]), + ("sm_90", Unstable(sym::nvptx_target_feature), &["sm_89"]), + ("sm_90a", Unstable(sym::nvptx_target_feature), &["sm_90"]), + // tidy-alphabetical-end + // tidy-alphabetical-start + ("sm_100", Unstable(sym::nvptx_target_feature), &["sm_90"]), + ("sm_100a", Unstable(sym::nvptx_target_feature), &["sm_100"]), + ("sm_101", Unstable(sym::nvptx_target_feature), &["sm_100"]), + ("sm_101a", Unstable(sym::nvptx_target_feature), &["sm_101"]), + ("sm_120", Unstable(sym::nvptx_target_feature), &["sm_101"]), + ("sm_120a", Unstable(sym::nvptx_target_feature), &["sm_120"]), + // tidy-alphabetical-end + // tidy-alphabetical-start + ("ptx32", Unstable(sym::nvptx_target_feature), &[]), + ("ptx40", Unstable(sym::nvptx_target_feature), &["ptx32"]), + ("ptx41", Unstable(sym::nvptx_target_feature), &["ptx40"]), + ("ptx42", Unstable(sym::nvptx_target_feature), &["ptx41"]), + ("ptx43", Unstable(sym::nvptx_target_feature), &["ptx42"]), + ("ptx50", Unstable(sym::nvptx_target_feature), &["ptx43"]), + ("ptx60", Unstable(sym::nvptx_target_feature), &["ptx50"]), + ("ptx61", Unstable(sym::nvptx_target_feature), &["ptx60"]), + ("ptx62", Unstable(sym::nvptx_target_feature), &["ptx61"]), + ("ptx63", Unstable(sym::nvptx_target_feature), &["ptx62"]), + ("ptx64", Unstable(sym::nvptx_target_feature), &["ptx63"]), + ("ptx65", Unstable(sym::nvptx_target_feature), &["ptx64"]), + ("ptx70", Unstable(sym::nvptx_target_feature), &["ptx65"]), + ("ptx71", Unstable(sym::nvptx_target_feature), &["ptx70"]), + ("ptx72", Unstable(sym::nvptx_target_feature), &["ptx71"]), + ("ptx73", Unstable(sym::nvptx_target_feature), &["ptx72"]), + ("ptx74", Unstable(sym::nvptx_target_feature), &["ptx73"]), + ("ptx75", Unstable(sym::nvptx_target_feature), &["ptx74"]), + ("ptx76", Unstable(sym::nvptx_target_feature), &["ptx75"]), + ("ptx77", Unstable(sym::nvptx_target_feature), &["ptx76"]), + ("ptx78", Unstable(sym::nvptx_target_feature), &["ptx77"]), + ("ptx80", Unstable(sym::nvptx_target_feature), &["ptx78"]), + ("ptx81", Unstable(sym::nvptx_target_feature), &["ptx80"]), + ("ptx82", Unstable(sym::nvptx_target_feature), &["ptx81"]), + ("ptx83", Unstable(sym::nvptx_target_feature), &["ptx82"]), + ("ptx84", Unstable(sym::nvptx_target_feature), &["ptx83"]), + ("ptx85", Unstable(sym::nvptx_target_feature), &["ptx84"]), + ("ptx86", Unstable(sym::nvptx_target_feature), &["ptx85"]), + ("ptx87", Unstable(sym::nvptx_target_feature), &["ptx86"]), + // tidy-alphabetical-end +]; + static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("a", Stable, &["zaamo", "zalrsc"]), @@ -782,6 +847,7 @@ pub fn all_rust_features() -> impl Iterator { .chain(HEXAGON_FEATURES.iter()) .chain(POWERPC_FEATURES.iter()) .chain(MIPS_FEATURES.iter()) + .chain(NVPTX_FEATURES.iter()) .chain(RISCV_FEATURES.iter()) .chain(WASM_FEATURES.iter()) .chain(BPF_FEATURES.iter()) @@ -847,6 +913,7 @@ impl Target { "x86" | "x86_64" => X86_FEATURES, "hexagon" => HEXAGON_FEATURES, "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_FEATURES, + "nvptx64" => NVPTX_FEATURES, "powerpc" | "powerpc64" => POWERPC_FEATURES, "riscv32" | "riscv64" => RISCV_FEATURES, "wasm32" | "wasm64" => WASM_FEATURES, @@ -873,7 +940,7 @@ impl Target { "sparc" | "sparc64" => SPARC_FEATURES_FOR_CORRECT_VECTOR_ABI, "hexagon" => HEXAGON_FEATURES_FOR_CORRECT_VECTOR_ABI, "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_FEATURES_FOR_CORRECT_VECTOR_ABI, - "bpf" | "m68k" => &[], // no vector ABI + "nvptx64" | "bpf" | "m68k" => &[], // no vector ABI "csky" => CSKY_FEATURES_FOR_CORRECT_VECTOR_ABI, // FIXME: for some tier3 targets, we are overly cautious and always give warnings // when passing args in vector registers. diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 3c33f4b136844..d5bce6ad233e9 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -195,6 +195,7 @@ #![feature(hexagon_target_feature)] #![feature(loongarch_target_feature)] #![feature(mips_target_feature)] +#![feature(nvptx_target_feature)] #![feature(powerpc_target_feature)] #![feature(riscv_target_feature)] #![feature(rtm_target_feature)] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 10efb8aff4a56..bd2f7445612a7 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -469,17 +469,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -560,17 +559,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_unsigned(2), 3);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_unsigned(3);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -611,17 +609,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).strict_sub(1), ", stringify!($SelfT), "::MIN + 1);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub(3);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -702,17 +699,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub_unsigned(2), -1);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MIN + 2).strict_sub_unsigned(3);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -753,17 +749,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.strict_mul(1), ", stringify!($SelfT), "::MAX);")] /// ``` /// /// The following panics because of overflow: /// /// ``` should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -855,24 +850,22 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div(-1), ", stringify!($Max), ");")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div(-1);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -924,24 +917,22 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).strict_div_euclid(-1), ", stringify!($Max), ");")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_div_euclid(-1);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1092,24 +1083,22 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem(2), 1);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem(-1);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1160,24 +1149,22 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_rem_euclid(2), 1);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_rem_euclid(-1);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1249,17 +1236,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_neg(), -5);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_neg();")] /// - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1306,17 +1292,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0x1", stringify!($SelfT), ".strict_shl(129);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1422,17 +1407,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(128);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1542,17 +1526,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").strict_abs(), 5);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.strict_abs();")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1612,17 +1595,16 @@ macro_rules! int_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(8", stringify!($SelfT), ".strict_pow(2), 64);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 5a41a302916a8..a89832615baec 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -538,17 +538,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).strict_add(1), ", stringify!($SelfT), "::MAX - 1);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add(3);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -630,22 +629,20 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_add_signed(2), 3);")] /// ``` /// /// The following panic because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_add_signed(-2);")] /// ``` /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX - 2).strict_add_signed(3);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -695,17 +692,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".strict_sub(1), 0);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0", stringify!($SelfT), ".strict_sub(1);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -817,22 +813,20 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".strict_sub_signed(2), 1);")] /// ``` /// /// The following panic because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_sub_signed(2);")] /// ``` /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX).strict_sub_signed(-1);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -932,17 +926,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".strict_mul(1), 5);")] /// ``` /// /// The following panics because of overflow: /// /// ``` should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_mul(2);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1029,17 +1022,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div(10), 10);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div(0);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1085,16 +1077,15 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_div_euclid(10), 10);")] /// ``` /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = (1", stringify!($SelfT), ").strict_div_euclid(0);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1239,17 +1230,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem(10), 0);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem(0);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1296,17 +1286,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".strict_rem_euclid(10), 0);")] /// ``` /// /// The following panics because of division by zero: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 5", stringify!($SelfT), ".strict_rem_euclid(0);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline(always)] @@ -1568,17 +1557,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".strict_neg(), 0);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_neg();")] /// - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1625,17 +1613,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(0x1", stringify!($SelfT), ".strict_shl(4), 0x10);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shl(129);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1741,17 +1728,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(0x10", stringify!($SelfT), ".strict_shr(4), 0x1);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = 0x10", stringify!($SelfT), ".strict_shr(129);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1867,17 +1853,16 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(strict_overflow_ops)] #[doc = concat!("assert_eq!(2", stringify!($SelfT), ".strict_pow(5), 32);")] /// ``` /// /// The following panics because of overflow: /// /// ```should_panic - /// #![feature(strict_overflow_ops)] #[doc = concat!("let _ = ", stringify!($SelfT), "::MAX.strict_pow(2);")] /// ``` - #[unstable(feature = "strict_overflow_ops", issue = "118260")] + #[stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "strict_overflow_ops", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 26661b20c12d6..7489a8bb6e74b 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -187,6 +187,80 @@ impl ControlFlow { } } + /// Converts the `ControlFlow` into an `Result` which is `Ok` if the + /// `ControlFlow` was `Break` and `Err` if otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(control_flow_ok)] + /// + /// use std::ops::ControlFlow; + /// + /// struct TreeNode { + /// value: T, + /// left: Option>>, + /// right: Option>>, + /// } + /// + /// impl TreeNode { + /// fn find<'a>(&'a self, mut predicate: impl FnMut(&T) -> bool) -> Result<&'a T, ()> { + /// let mut f = |t: &'a T| -> ControlFlow<&'a T> { + /// if predicate(t) { + /// ControlFlow::Break(t) + /// } else { + /// ControlFlow::Continue(()) + /// } + /// }; + /// + /// self.traverse_inorder(&mut f).break_ok() + /// } + /// + /// fn traverse_inorder<'a, B>( + /// &'a self, + /// f: &mut impl FnMut(&'a T) -> ControlFlow, + /// ) -> ControlFlow { + /// if let Some(left) = &self.left { + /// left.traverse_inorder(f)?; + /// } + /// f(&self.value)?; + /// if let Some(right) = &self.right { + /// right.traverse_inorder(f)?; + /// } + /// ControlFlow::Continue(()) + /// } + /// + /// fn leaf(value: T) -> Option>> { + /// Some(Box::new(Self { + /// value, + /// left: None, + /// right: None, + /// })) + /// } + /// } + /// + /// let node = TreeNode { + /// value: 0, + /// left: TreeNode::leaf(1), + /// right: Some(Box::new(TreeNode { + /// value: -1, + /// left: TreeNode::leaf(5), + /// right: TreeNode::leaf(2), + /// })), + /// }; + /// + /// let res = node.find(|val: &i32| *val > 3); + /// assert_eq!(res, Ok(&5)); + /// ``` + #[inline] + #[unstable(feature = "control_flow_ok", issue = "140266")] + pub fn break_ok(self) -> Result { + match self { + ControlFlow::Continue(c) => Err(c), + ControlFlow::Break(b) => Ok(b), + } + } + /// Maps `ControlFlow` to `ControlFlow` by applying a function /// to the break value in case it exists. #[inline] @@ -218,6 +292,79 @@ impl ControlFlow { } } + /// Converts the `ControlFlow` into an `Result` which is `Ok` if the + /// `ControlFlow` was `Continue` and `Err` if otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(control_flow_ok)] + /// + /// use std::ops::ControlFlow; + /// + /// struct TreeNode { + /// value: T, + /// left: Option>>, + /// right: Option>>, + /// } + /// + /// impl TreeNode { + /// fn validate(&self, f: &mut impl FnMut(&T) -> ControlFlow) -> Result<(), B> { + /// self.traverse_inorder(f).continue_ok() + /// } + /// + /// fn traverse_inorder(&self, f: &mut impl FnMut(&T) -> ControlFlow) -> ControlFlow { + /// if let Some(left) = &self.left { + /// left.traverse_inorder(f)?; + /// } + /// f(&self.value)?; + /// if let Some(right) = &self.right { + /// right.traverse_inorder(f)?; + /// } + /// ControlFlow::Continue(()) + /// } + /// + /// fn leaf(value: T) -> Option>> { + /// Some(Box::new(Self { + /// value, + /// left: None, + /// right: None, + /// })) + /// } + /// } + /// + /// let node = TreeNode { + /// value: 0, + /// left: TreeNode::leaf(1), + /// right: Some(Box::new(TreeNode { + /// value: -1, + /// left: TreeNode::leaf(5), + /// right: TreeNode::leaf(2), + /// })), + /// }; + /// + /// let res = node.validate(&mut |val| { + /// if *val < 0 { + /// return ControlFlow::Break("negative value detected"); + /// } + /// + /// if *val > 4 { + /// return ControlFlow::Break("too big value detected"); + /// } + /// + /// ControlFlow::Continue(()) + /// }); + /// assert_eq!(res, Err("too big value detected")); + /// ``` + #[inline] + #[unstable(feature = "control_flow_ok", issue = "140266")] + pub fn continue_ok(self) -> Result { + match self { + ControlFlow::Continue(c) => Ok(c), + ControlFlow::Break(b) => Err(b), + } + } + /// Maps `ControlFlow` to `ControlFlow` by applying a function /// to the continue value in case it exists. #[inline] diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 0a9c0c61c9584..a0c594d2d5961 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -22,6 +22,7 @@ #![feature(const_ref_cell)] #![feature(const_result_trait_fn)] #![feature(const_trait_impl)] +#![feature(control_flow_ok)] #![feature(core_float_math)] #![feature(core_intrinsics)] #![feature(core_intrinsics_fallbacks)] diff --git a/library/coretests/tests/ops/control_flow.rs b/library/coretests/tests/ops/control_flow.rs index eacfd63a6c48f..1df6599ac4a5a 100644 --- a/library/coretests/tests/ops/control_flow.rs +++ b/library/coretests/tests/ops/control_flow.rs @@ -16,3 +16,15 @@ fn control_flow_discriminants_match_result() { discriminant_value(&Result::::Ok(3)), ); } + +#[test] +fn control_flow_break_ok() { + assert_eq!(ControlFlow::::Break('b').break_ok(), Ok('b')); + assert_eq!(ControlFlow::::Continue(3).break_ok(), Err(3)); +} + +#[test] +fn control_flow_continue_ok() { + assert_eq!(ControlFlow::::Break('b').continue_ok(), Err('b')); + assert_eq!(ControlFlow::::Continue(3).continue_ok(), Ok(3)); +} diff --git a/src/doc/book b/src/doc/book index b2d1a0821e12a..3e9dc46aa563c 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit b2d1a0821e12a676b496d61891b8e3d374a8e832 +Subproject commit 3e9dc46aa563ca0c53ec826c41b05f10c5915925 diff --git a/src/doc/reference b/src/doc/reference index 1f45bd41fa6c1..1be151c051a08 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 1f45bd41fa6c17b7c048ed6bfe5f168c4311206a +Subproject commit 1be151c051a082b542548c62cafbcb055fa8944f diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index e386be5f44af7..bd1279cdc9865 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit e386be5f44af711854207c11fdd61bb576270b04 +Subproject commit bd1279cdc9865bfff605e741fb76a0b2f07314a7 diff --git a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md index 106ec562bfc79..36598982481bf 100644 --- a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md +++ b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md @@ -10,6 +10,46 @@ platform. [@RDambrosio016](https://github.com/RDambrosio016) [@kjetilkjeka](https://github.com/kjetilkjeka) +## Requirements + +This target is `no_std` and will typically be built with crate-type `cdylib` and `-C linker-flavor=llbc`, which generates PTX. +The necessary components for this workflow are: + +- `rustup toolchain add nightly` +- `rustup component add llvm-tools --toolchain nightly` +- `rustup component add llvm-bitcode-linker --toolchain nightly` + +There are two options for using the core library: + +- `rustup component add rust-src --toolchain nightly` and build using `-Z build-std=core`. +- `rustup target add nvptx64-nvidia-cuda --toolchain nightly` + +### Target and features + +It is generally necessary to specify the target, such as `-C target-cpu=sm_89`, because the default is very old. This implies two target features: `sm_89` and `ptx78` (and all preceding features within `sm_*` and `ptx*`). Rust will default to using the oldest PTX version that supports the target processor (see [this table](https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#release-notes-ptx-release-history)), which maximizes driver compatibility. +One can use `-C target-feature=+ptx80` to choose a later PTX version without changing the target (the default in this case, `ptx78`, requires CUDA driver version 11.8, while `ptx80` would require driver version 12.0). +Later PTX versions may allow more efficient code generation. + +Although Rust follows LLVM in representing `ptx*` and `sm_*` as target features, they should be thought of as having crate granularity, set via (either via `-Ctarget-cpu` and optionally `-Ctarget-feature`). +While the compiler accepts `#[target_feature(enable = "ptx80", enable = "sm_89")]`, it is not supported, may not behave as intended, and may become erroneous in the future. + +## Building Rust kernels + +A `no_std` crate containing one or more functions with `extern "ptx-kernel"` can be compiled to PTX using a command like the following. + +```console +$ RUSTFLAGS='-Ctarget-cpu=sm_89' cargo +nightly rustc --target=nvptx64-nvidia-cuda -Zbuild-std=core --crate-type=cdylib -- -Clinker-flavor=llbc -Zunstable-options +``` + +Intrinsics in `core::arch::nvptx` may use `#[cfg(target_feature = "...")]`, thus it's necessary to use `-Zbuild-std=core` with appropriate `RUSTFLAGS`. The following components are needed for this workflow: + +```console +$ rustup component add rust-src --toolchain nightly +$ rustup component add llvm-tools --toolchain nightly +$ rustup component add llvm-bitcode-linker --toolchain nightly +``` + + $DIR/warn-semicolon-in-expressions-from-macros.rs:6:13 +error: trailing semicolon in macro used in expression position + --> $DIR/warn-semicolon-in-expressions-from-macros.rs:5:13 | LL | true; | ^ @@ -9,14 +9,14 @@ LL | _ => foo!() | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 - = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `#[deny(semicolon_in_expressions_from_macros)]` on by default + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: 1 warning emitted +error: aborting due to 1 previous error Future incompatibility report: Future breakage diagnostic: -warning: trailing semicolon in macro used in expression position - --> $DIR/warn-semicolon-in-expressions-from-macros.rs:6:13 +error: trailing semicolon in macro used in expression position + --> $DIR/warn-semicolon-in-expressions-from-macros.rs:5:13 | LL | true; | ^ @@ -26,6 +26,6 @@ LL | _ => foo!() | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 - = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `#[deny(semicolon_in_expressions_from_macros)]` on by default + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/macros/lint-trailing-macro-call.rs b/tests/ui/macros/lint-trailing-macro-call.rs index 78b861f1df17a..25fa91062c434 100644 --- a/tests/ui/macros/lint-trailing-macro-call.rs +++ b/tests/ui/macros/lint-trailing-macro-call.rs @@ -1,12 +1,10 @@ -//@ check-pass -// // Ensures that we properly lint // a removed 'expression' resulting from a macro // in trailing expression position macro_rules! expand_it { () => { - #[cfg(false)] 25; //~ WARN trailing semicolon in macro + #[cfg(false)] 25; //~ ERROR trailing semicolon in macro //~| WARN this was previously } } diff --git a/tests/ui/macros/lint-trailing-macro-call.stderr b/tests/ui/macros/lint-trailing-macro-call.stderr index 223b85e112ed6..3fd1ea813459f 100644 --- a/tests/ui/macros/lint-trailing-macro-call.stderr +++ b/tests/ui/macros/lint-trailing-macro-call.stderr @@ -1,5 +1,5 @@ -warning: trailing semicolon in macro used in expression position - --> $DIR/lint-trailing-macro-call.rs:9:25 +error: trailing semicolon in macro used in expression position + --> $DIR/lint-trailing-macro-call.rs:7:25 | LL | #[cfg(false)] 25; | ^ @@ -11,14 +11,14 @@ LL | expand_it!() = note: for more information, see issue #79813 = note: macro invocations at the end of a block are treated as expressions = note: to ignore the value produced by the macro, add a semicolon after the invocation of `expand_it` - = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default - = note: this warning originates in the macro `expand_it` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `#[deny(semicolon_in_expressions_from_macros)]` on by default + = note: this error originates in the macro `expand_it` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: 1 warning emitted +error: aborting due to 1 previous error Future incompatibility report: Future breakage diagnostic: -warning: trailing semicolon in macro used in expression position - --> $DIR/lint-trailing-macro-call.rs:9:25 +error: trailing semicolon in macro used in expression position + --> $DIR/lint-trailing-macro-call.rs:7:25 | LL | #[cfg(false)] 25; | ^ @@ -30,6 +30,6 @@ LL | expand_it!() = note: for more information, see issue #79813 = note: macro invocations at the end of a block are treated as expressions = note: to ignore the value produced by the macro, add a semicolon after the invocation of `expand_it` - = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default - = note: this warning originates in the macro `expand_it` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `#[deny(semicolon_in_expressions_from_macros)]` on by default + = note: this error originates in the macro `expand_it` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/macros/macro-context.rs b/tests/ui/macros/macro-context.rs index a31470263a0a5..e1c24ba8b5705 100644 --- a/tests/ui/macros/macro-context.rs +++ b/tests/ui/macros/macro-context.rs @@ -6,7 +6,7 @@ macro_rules! m { //~| ERROR macro expansion ignores `;` //~| ERROR cannot find type `i` in this scope //~| ERROR cannot find value `i` in this scope - //~| WARN trailing semicolon in macro + //~| ERROR trailing semicolon in macro //~| WARN this was previously } diff --git a/tests/ui/macros/macro-context.stderr b/tests/ui/macros/macro-context.stderr index 4820a43f00c79..6b49c05f360da 100644 --- a/tests/ui/macros/macro-context.stderr +++ b/tests/ui/macros/macro-context.stderr @@ -64,7 +64,7 @@ LL | let i = m!(); | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: trailing semicolon in macro used in expression position +error: trailing semicolon in macro used in expression position --> $DIR/macro-context.rs:3:15 | LL | () => ( i ; typeof ); @@ -75,15 +75,15 @@ LL | let i = m!(); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 - = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default - = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `#[deny(semicolon_in_expressions_from_macros)]` on by default + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 7 previous errors Some errors have detailed explanations: E0412, E0425. For more information about an error, try `rustc --explain E0412`. Future incompatibility report: Future breakage diagnostic: -warning: trailing semicolon in macro used in expression position +error: trailing semicolon in macro used in expression position --> $DIR/macro-context.rs:3:15 | LL | () => ( i ; typeof ); @@ -94,6 +94,6 @@ LL | let i = m!(); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 - = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default - = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `#[deny(semicolon_in_expressions_from_macros)]` on by default + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/macros/macro-in-expression-context.fixed b/tests/ui/macros/macro-in-expression-context.fixed index 7c830707ffd9d..52e1b429e48ac 100644 --- a/tests/ui/macros/macro-in-expression-context.fixed +++ b/tests/ui/macros/macro-in-expression-context.fixed @@ -3,12 +3,12 @@ macro_rules! foo { () => { assert_eq!("A", "A"); - //~^ WARN trailing semicolon in macro + //~^ ERROR trailing semicolon in macro //~| WARN this was previously //~| NOTE macro invocations at the end of a block //~| NOTE to ignore the value produced by the macro //~| NOTE for more information - //~| NOTE `#[warn(semicolon_in_expressions_from_macros)]` on by default + //~| NOTE `#[deny(semicolon_in_expressions_from_macros)]` on by default assert_eq!("B", "B"); } //~^^ ERROR macro expansion ignores `assert_eq` and any tokens following diff --git a/tests/ui/macros/macro-in-expression-context.rs b/tests/ui/macros/macro-in-expression-context.rs index da95017aa5f74..5c560e78dad4c 100644 --- a/tests/ui/macros/macro-in-expression-context.rs +++ b/tests/ui/macros/macro-in-expression-context.rs @@ -3,12 +3,12 @@ macro_rules! foo { () => { assert_eq!("A", "A"); - //~^ WARN trailing semicolon in macro + //~^ ERROR trailing semicolon in macro //~| WARN this was previously //~| NOTE macro invocations at the end of a block //~| NOTE to ignore the value produced by the macro //~| NOTE for more information - //~| NOTE `#[warn(semicolon_in_expressions_from_macros)]` on by default + //~| NOTE `#[deny(semicolon_in_expressions_from_macros)]` on by default assert_eq!("B", "B"); } //~^^ ERROR macro expansion ignores `assert_eq` and any tokens following diff --git a/tests/ui/macros/macro-in-expression-context.stderr b/tests/ui/macros/macro-in-expression-context.stderr index 43419f2678c22..b04348d701089 100644 --- a/tests/ui/macros/macro-in-expression-context.stderr +++ b/tests/ui/macros/macro-in-expression-context.stderr @@ -13,7 +13,7 @@ help: you might be missing a semicolon here LL | foo!(); | + -warning: trailing semicolon in macro used in expression position +error: trailing semicolon in macro used in expression position --> $DIR/macro-in-expression-context.rs:5:29 | LL | assert_eq!("A", "A"); @@ -26,13 +26,13 @@ LL | foo!() = note: for more information, see issue #79813 = note: macro invocations at the end of a block are treated as expressions = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo` - = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `#[deny(semicolon_in_expressions_from_macros)]` on by default + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors Future incompatibility report: Future breakage diagnostic: -warning: trailing semicolon in macro used in expression position +error: trailing semicolon in macro used in expression position --> $DIR/macro-in-expression-context.rs:5:29 | LL | assert_eq!("A", "A"); @@ -45,6 +45,6 @@ LL | foo!() = note: for more information, see issue #79813 = note: macro invocations at the end of a block are treated as expressions = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo` - = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `#[deny(semicolon_in_expressions_from_macros)]` on by default + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 9244a98d82fdf..81ed8b3de760f 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -6,6 +6,7 @@ // gate-test-arm_target_feature // gate-test-hexagon_target_feature // gate-test-mips_target_feature +// gate-test-nvptx_target_feature // gate-test-wasm_target_feature // gate-test-adx_target_feature // gate-test-cmpxchg16b_target_feature diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index 32d60ce438227..3e9374be73db8 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `x87` is currently unstable - --> $DIR/gate.rs:29:18 + --> $DIR/gate.rs:30:18 | LL | #[target_feature(enable = "x87")] | ^^^^^^^^^^^^^^ diff --git a/tests/ui/target-feature/implied-features-nvptx.rs b/tests/ui/target-feature/implied-features-nvptx.rs new file mode 100644 index 0000000000000..1550c99f67a8d --- /dev/null +++ b/tests/ui/target-feature/implied-features-nvptx.rs @@ -0,0 +1,28 @@ +//@ assembly-output: ptx-linker +//@ compile-flags: --crate-type cdylib -C target-cpu=sm_80 -Z unstable-options -Clinker-flavor=llbc +//@ only-nvptx64 +//@ build-pass +#![no_std] +#![allow(dead_code)] + +#[panic_handler] +pub fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +// -Ctarget-cpu=sm_80 directly enables sm_80 and ptx70 +#[cfg(not(all(target_feature = "sm_80", target_feature = "ptx70")))] +compile_error!("direct target features not enabled"); + +// -Ctarget-cpu=sm_80 implies all earlier sm_* and ptx* features. +#[cfg(not(all( + target_feature = "sm_60", + target_feature = "sm_70", + target_feature = "ptx50", + target_feature = "ptx60", +)))] +compile_error!("implied target features not enabled"); + +// -Ctarget-cpu=sm_80 implies all earlier sm_* and ptx* features. +#[cfg(target_feature = "ptx71")] +compile_error!("sm_80 requires only ptx70, but ptx71 enabled");