diff options
20 files changed, 210 insertions, 28 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 80b99f94485..a3af942a10f 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -548,6 +548,8 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(pin_ergonomics, "pinned reference syntax is experimental"); gate_all!(unsafe_fields, "`unsafe` fields are experimental"); gate_all!(unsafe_binders, "unsafe binder types are experimental"); + gate_all!(rustc_contracts, "contracts are experimental"); + gate_all!(rustc_contracts_internals, "contract internal machinery is for internal use only"); if !visitor.features.never_patterns() { if let Some(spans) = spans.get(&sym::never_patterns) { diff --git a/compiler/rustc_builtin_macros/src/contracts.rs b/compiler/rustc_builtin_macros/src/contracts.rs index d269287b555..be7f276cdaa 100644 --- a/compiler/rustc_builtin_macros/src/contracts.rs +++ b/compiler/rustc_builtin_macros/src/contracts.rs @@ -36,17 +36,17 @@ impl AttrProcMacro for ExpandEnsures { } fn expand_injecting_circa_where_clause( - _ecx: &mut ExtCtxt<'_>, + ecx: &mut ExtCtxt<'_>, attr_span: Span, annotated: TokenStream, inject: impl FnOnce(&mut Vec<TokenTree>) -> Result<(), ErrorGuaranteed>, ) -> Result<TokenStream, ErrorGuaranteed> { let mut new_tts = Vec::with_capacity(annotated.len()); - let mut cursor = annotated.into_trees(); + let mut cursor = annotated.iter(); // Find the `fn name<G,...>(x:X,...)` and inject the AST contract forms right after // the formal parameters (and return type if any). - while let Some(tt) = cursor.next_ref() { + while let Some(tt) = cursor.next() { new_tts.push(tt.clone()); if let TokenTree::Token(tok, _) = tt && tok.is_ident_named(kw::Fn) @@ -58,7 +58,7 @@ fn expand_injecting_circa_where_clause( // Found the `fn` keyword, now find the formal parameters. // // FIXME: can this fail if you have parentheticals in a generics list, like `fn foo<F: Fn(X) -> Y>` ? - while let Some(tt) = cursor.next_ref() { + while let Some(tt) = cursor.next() { new_tts.push(tt.clone()); if let TokenTree::Delimited(_, _, token::Delimiter::Parenthesis, _) = tt { @@ -81,7 +81,7 @@ fn expand_injecting_circa_where_clause( // parse the type expression itself. But rather than try to fix things with hacks like that, // time might be better spent extending the attribute expander to suport tt-annotation atop // ast-annotated, which would be an elegant way to sidestep all of this. - let mut opt_next_tt = cursor.next_ref(); + let mut opt_next_tt = cursor.next(); while let Some(next_tt) = opt_next_tt { if let TokenTree::Token(tok, _) = next_tt && tok.is_ident_named(kw::Where) @@ -97,8 +97,7 @@ fn expand_injecting_circa_where_clause( // for anything else, transcribe the tt and keep looking. new_tts.push(next_tt.clone()); - opt_next_tt = cursor.next_ref(); - continue; + opt_next_tt = cursor.next(); } // At this point, we've transcribed everything from the `fn` through the formal parameter list @@ -118,10 +117,15 @@ fn expand_injecting_circa_where_clause( if let Some(tt) = opt_next_tt { new_tts.push(tt.clone()); } - while let Some(tt) = cursor.next_ref() { + while let Some(tt) = cursor.next() { new_tts.push(tt.clone()); } + // Record the span as a contract attribute expansion. + // This is used later to stop users from using the extended syntax directly + // which is gated via `rustc_contracts_internals`. + ecx.psess().contract_attribute_spans.push(attr_span); + Ok(TokenStream::new(new_tts)) } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 08a5e22db3a..57bcd8c5eca 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -608,6 +608,10 @@ declare_features! ( (unstable, return_type_notation, "1.70.0", Some(109417)), /// Allows `extern "rust-cold"`. (unstable, rust_cold_cc, "1.63.0", Some(97544)), + /// Allows use of contracts attributes. + (unstable, rustc_contracts, "CURRENT_RUSTC_VERSION", Some(133866)), + /// Allows access to internal machinery used to implement contracts. + (unstable, rustc_contracts_internals, "CURRENT_RUSTC_VERSION", Some(133866)), /// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics (unstable, sha512_sm_x86, "1.82.0", Some(126624)), /// Allows the use of SIMD types in functions declared in `extern` blocks. diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index d5ac8d1588d..14b949dbc3d 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -4,7 +4,7 @@ use rustc_ast::{ WhereClause, token, }; use rustc_errors::{Applicability, PResult}; -use rustc_span::{Ident, Span, kw}; +use rustc_span::{Ident, Span, kw, sym}; use thin_vec::ThinVec; use super::{ForceCollect, Parser, Trailing, UsePreAttrPos}; @@ -302,13 +302,27 @@ impl<'a> Parser<'a> { pub(super) fn parse_contract( &mut self, ) -> PResult<'a, Option<rustc_ast::ptr::P<ast::FnContract>>> { + let gate = |span| { + if self.psess.contract_attribute_spans.contains(span) { + // span was generated via a builtin contracts attribute, so gate as end-user visible + self.psess.gated_spans.gate(sym::rustc_contracts, span); + } else { + // span was not generated via a builtin contracts attribute, so gate as internal machinery + self.psess.gated_spans.gate(sym::rustc_contracts_internals, span); + } + }; + let requires = if self.eat_keyword_noexpect(exp!(RustcContractRequires).kw) { - Some(self.parse_expr()?) + let precond = self.parse_expr()?; + gate(precond.span); + Some(precond) } else { None }; let ensures = if self.eat_keyword_noexpect(exp!(RustcContractEnsures).kw) { - Some(self.parse_expr()?) + let postcond = self.parse_expr()?; + gate(postcond.span); + Some(postcond) } else { None }; diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 81ae06602cd..abfd3efc611 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -207,6 +207,10 @@ pub struct ParseSess { pub config: Cfg, pub check_config: CheckCfg, pub edition: Edition, + /// Places where contract attributes were expanded into unstable AST forms. + /// This is used to allowlist those spans (so that we only check them against the feature + /// gate for the externally visible interface, and not internal implmentation machinery). + pub contract_attribute_spans: AppendOnlyVec<Span>, /// Places where raw identifiers were used. This is used to avoid complaining about idents /// clashing with keywords in new editions. pub raw_identifier_spans: AppendOnlyVec<Span>, @@ -255,6 +259,7 @@ impl ParseSess { config: Cfg::default(), check_config: CheckCfg::default(), edition: ExpnId::root().expn_data().edition, + contract_attribute_spans: Default::default(), raw_identifier_spans: Default::default(), bad_unicode_identifiers: Lock::new(Default::default()), source_map, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 43bc69e6e7c..ea2ce5475c2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1716,6 +1716,8 @@ symbols! { rustc_const_stable, rustc_const_stable_indirect, rustc_const_unstable, + rustc_contracts, + rustc_contracts_internals, rustc_conversion_suggestion, rustc_deallocator, rustc_def_path, diff --git a/library/core/src/contracts.rs b/library/core/src/contracts.rs index 3efd2df0a38..b155dbc213e 100644 --- a/library/core/src/contracts.rs +++ b/library/core/src/contracts.rs @@ -8,7 +8,7 @@ pub use crate::macros::builtin::contracts_requires as requires; /// Emitted by rustc as a desugaring of `#[requires(PRED)] fn foo(x: X) { ... }` /// into: `fn foo(x: X) { check_requires(|| PRED) ... }` #[cfg(not(bootstrap))] -#[unstable(feature = "rustc_contracts", issue = "none" /* compiler-team#759 */)] +#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)] #[lang = "contract_check_requires"] #[track_caller] pub fn check_requires<C: FnOnce() -> bool>(c: C) { @@ -21,7 +21,7 @@ pub fn check_requires<C: FnOnce() -> bool>(c: C) { /// into: `fn foo() { let _check = build_check_ensures(|ret| PRED) ... [return _check(R);] ... }` /// (including the implicit return of the tail expression, if any). #[cfg(not(bootstrap))] -#[unstable(feature = "rustc_contracts", issue = "none" /* compiler-team#759 */)] +#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)] #[lang = "contract_build_check_ensures"] #[track_caller] pub fn build_check_ensures<Ret, C>(c: C) -> impl (FnOnce(Ret) -> Ret) + Copy diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index beea0996775..a7f0f09f0c6 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -4051,8 +4051,8 @@ pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) /// checking is turned on, so that we can specify contracts in libstd /// and let an end user opt into turning them on. #[cfg(not(bootstrap))] -#[rustc_const_unstable(feature = "rustc_contracts", issue = "none" /* compiler-team#759 */)] -#[unstable(feature = "rustc_contracts", issue = "none" /* compiler-team#759 */)] +#[rustc_const_unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)] +#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)] #[inline(always)] #[rustc_intrinsic] pub const fn contract_checks() -> bool { @@ -4063,14 +4063,14 @@ pub const fn contract_checks() -> bool { } #[cfg(not(bootstrap))] -#[unstable(feature = "rustc_contracts", issue = "none" /* compiler-team#759 */)] +#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)] #[rustc_intrinsic] pub fn contract_check_requires<C: FnOnce() -> bool>(c: C) -> bool { c() } #[cfg(not(bootstrap))] -#[unstable(feature = "rustc_contracts", issue = "none" /* compiler-team#759 */)] +#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)] #[rustc_intrinsic] pub fn contract_check_ensures<'a, Ret, C: FnOnce(&'a Ret) -> bool>(ret: &'a Ret, c: C) -> bool { c(ret) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a31cca5d425..6a0051244f0 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -248,7 +248,7 @@ pub mod autodiff { } #[cfg(not(bootstrap))] -#[unstable(feature = "rustc_contracts", issue = "none")] +#[unstable(feature = "rustc_contracts", issue = "133866")] pub mod contracts; #[unstable(feature = "cfg_match", issue = "115585")] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 1a5d2973dfc..cb37530e90d 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1783,8 +1783,8 @@ pub(crate) mod builtin { /// eventually parsed as a unary closure expression that is /// invoked on a reference to the return value. #[cfg(not(bootstrap))] - #[unstable(feature = "rustc_contracts", issue = "none")] - #[allow_internal_unstable(core_intrinsics)] + #[unstable(feature = "rustc_contracts", issue = "133866")] + #[allow_internal_unstable(rustc_contracts_internals)] #[rustc_builtin_macro] pub macro contracts_ensures($item:item) { /* compiler built-in */ @@ -1796,8 +1796,8 @@ pub(crate) mod builtin { /// eventually parsed as an boolean expression with access to the /// function's formal parameters #[cfg(not(bootstrap))] - #[unstable(feature = "rustc_contracts", issue = "none")] - #[allow_internal_unstable(core_intrinsics)] + #[unstable(feature = "rustc_contracts", issue = "133866")] + #[allow_internal_unstable(rustc_contracts_internals)] #[rustc_builtin_macro] pub macro contracts_requires($item:item) { /* compiler built-in */ diff --git a/tests/ui/contracts/contract-ast-extensions-nest.rs b/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs index ed137c4a986..d95ccd4f7b9 100644 --- a/tests/ui/contracts/contract-ast-extensions-nest.rs +++ b/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs @@ -16,7 +16,7 @@ //@ [chk_fail_pre] compile-flags: -Zcontract-checks=yes //@ [chk_fail_post] compile-flags: -Zcontract-checks=yes -#![feature(rustc_contracts)] +#![feature(rustc_contracts_internals)] fn nest(x: Baz) -> i32 rustc_contract_requires(|| x.baz > 0) diff --git a/tests/ui/contracts/contract-ast-extensions-tail.rs b/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs index b501c3faaed..636a595e06a 100644 --- a/tests/ui/contracts/contract-ast-extensions-tail.rs +++ b/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs @@ -16,7 +16,7 @@ //@ [chk_fail_pre] compile-flags: -Zcontract-checks=yes //@ [chk_fail_post] compile-flags: -Zcontract-checks=yes -#![feature(rustc_contracts)] +#![feature(rustc_contracts_internals)] fn tail(x: Baz) -> i32 rustc_contract_requires(|| x.baz > 0) diff --git a/tests/ui/contracts/contract-intrinsics.rs b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs index 6e3565baf7a..2e1be01e7ca 100644 --- a/tests/ui/contracts/contract-intrinsics.rs +++ b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs @@ -2,7 +2,7 @@ //@ revisions: yes no none //@ [yes] compile-flags: -Zcontract-checks=yes //@ [no] compile-flags: -Zcontract-checks=no -#![feature(cfg_contract_checks, rustc_contracts, core_intrinsics)] +#![feature(cfg_contract_checks, rustc_contracts_internals, core_intrinsics)] fn main() { #[cfg(none)] // default: disabled diff --git a/tests/ui/contracts/contract-lang-items.rs b/tests/ui/contracts/internal_machinery/contract-lang-items.rs index 1dbf71722fd..5af467485b1 100644 --- a/tests/ui/contracts/contract-lang-items.rs +++ b/tests/ui/contracts/internal_machinery/contract-lang-items.rs @@ -16,7 +16,8 @@ //@ [chk_fail_pre] compile-flags: -Zcontract-checks=yes //@ [chk_fail_post] compile-flags: -Zcontract-checks=yes -#![feature(rustc_contracts)] +#![feature(rustc_contracts)] // to access core::contracts +#![feature(rustc_contracts_internals)] // to access check_requires lang item fn foo(x: Baz) -> i32 { core::contracts::check_requires(|| x.baz > 0); diff --git a/tests/ui/contracts/contracts-lowering-ensures-is-not-inherited-when-nesting.rs b/tests/ui/contracts/internal_machinery/contracts-lowering-ensures-is-not-inherited-when-nesting.rs index 069f26e6796..0b0151c6df7 100644 --- a/tests/ui/contracts/contracts-lowering-ensures-is-not-inherited-when-nesting.rs +++ b/tests/ui/contracts/internal_machinery/contracts-lowering-ensures-is-not-inherited-when-nesting.rs @@ -1,6 +1,6 @@ //@ run-pass //@ compile-flags: -Zcontract-checks=yes -#![feature(rustc_contracts)] +#![feature(rustc_contracts_internals)] fn outer() -> i32 rustc_contract_ensures(|ret| *ret > 0) diff --git a/tests/ui/contracts/contracts-lowering-requires-is-not-inherited-when-nesting.rs b/tests/ui/contracts/internal_machinery/contracts-lowering-requires-is-not-inherited-when-nesting.rs index fbee8277a96..79c50a18f70 100644 --- a/tests/ui/contracts/contracts-lowering-requires-is-not-inherited-when-nesting.rs +++ b/tests/ui/contracts/internal_machinery/contracts-lowering-requires-is-not-inherited-when-nesting.rs @@ -1,6 +1,6 @@ //@ run-pass //@ compile-flags: -Zcontract-checks=yes -#![feature(rustc_contracts)] +#![feature(rustc_contracts_internals)] struct Outer { outer: std::cell::Cell<i32> } diff --git a/tests/ui/contracts/internal_machinery/internal-feature-gating.rs b/tests/ui/contracts/internal_machinery/internal-feature-gating.rs new file mode 100644 index 00000000000..7b5f1767942 --- /dev/null +++ b/tests/ui/contracts/internal_machinery/internal-feature-gating.rs @@ -0,0 +1,23 @@ +// gate-test-rustc_contracts_internals + +fn main() { + // intrinsics are guarded by rustc_contracts_internals feature gate. + core::intrinsics::contract_checks(); + //~^ ERROR use of unstable library feature `rustc_contracts_internals` + core::intrinsics::contract_check_requires(|| true); + //~^ ERROR use of unstable library feature `rustc_contracts_internals` + core::intrinsics::contract_check_ensures(&1, |_|true); + //~^ ERROR use of unstable library feature `rustc_contracts_internals` + + // lang items are guarded by rustc_contracts_internals feature gate. + core::contracts::check_requires(|| true); + //~^ ERROR use of unstable library feature `rustc_contracts_internals` + core::contracts::build_check_ensures(|_: &()| true); + //~^ ERROR use of unstable library feature `rustc_contracts_internals` + + // ast extensions are guarded by rustc_contracts_internals feature gate + fn identity_1() -> i32 rustc_contract_requires(|| true) { 10 } + //~^ ERROR contract internal machinery is for internal use only + fn identity_2() -> i32 rustc_contract_ensures(|_| true) { 10 } + //~^ ERROR contract internal machinery is for internal use only +} diff --git a/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr b/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr new file mode 100644 index 00000000000..2acd03b9a35 --- /dev/null +++ b/tests/ui/contracts/internal_machinery/internal-feature-gating.stderr @@ -0,0 +1,73 @@ +error[E0658]: contract internal machinery is for internal use only + --> $DIR/internal-feature-gating.rs:19:51 + | +LL | fn identity_1() -> i32 rustc_contract_requires(|| true) { 10 } + | ^^^^^^^^^ + | + = note: see issue #133866 <https://github.com/rust-lang/rust/issues/133866> for more information + = help: add `#![feature(rustc_contracts_internals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: contract internal machinery is for internal use only + --> $DIR/internal-feature-gating.rs:21:50 + | +LL | fn identity_2() -> i32 rustc_contract_ensures(|_| true) { 10 } + | ^^^^^^^^^^ + | + = note: see issue #133866 <https://github.com/rust-lang/rust/issues/133866> for more information + = help: add `#![feature(rustc_contracts_internals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `rustc_contracts_internals` + --> $DIR/internal-feature-gating.rs:5:5 + | +LL | core::intrinsics::contract_checks(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #133866 <https://github.com/rust-lang/rust/issues/133866> for more information + = help: add `#![feature(rustc_contracts_internals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `rustc_contracts_internals` + --> $DIR/internal-feature-gating.rs:7:5 + | +LL | core::intrinsics::contract_check_requires(|| true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #133866 <https://github.com/rust-lang/rust/issues/133866> for more information + = help: add `#![feature(rustc_contracts_internals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `rustc_contracts_internals` + --> $DIR/internal-feature-gating.rs:9:5 + | +LL | core::intrinsics::contract_check_ensures(&1, |_|true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #133866 <https://github.com/rust-lang/rust/issues/133866> for more information + = help: add `#![feature(rustc_contracts_internals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `rustc_contracts_internals` + --> $DIR/internal-feature-gating.rs:13:5 + | +LL | core::contracts::check_requires(|| true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #133866 <https://github.com/rust-lang/rust/issues/133866> for more information + = help: add `#![feature(rustc_contracts_internals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `rustc_contracts_internals` + --> $DIR/internal-feature-gating.rs:15:5 + | +LL | core::contracts::build_check_ensures(|_: &()| true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #133866 <https://github.com/rust-lang/rust/issues/133866> for more information + = help: add `#![feature(rustc_contracts_internals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-rustc-contracts.rs b/tests/ui/feature-gates/feature-gate-rustc-contracts.rs new file mode 100644 index 00000000000..d4249c252cd --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustc-contracts.rs @@ -0,0 +1,11 @@ +#![crate_type = "lib"] + +#[core::contracts::requires(x > 0)] +pub fn requires_needs_it(x: i32) { } +//~^^ ERROR use of unstable library feature `rustc_contracts` +//~^^^ ERROR contracts are experimental + +#[core::contracts::ensures(|ret| *ret > 0)] +pub fn ensures_needs_it() -> i32 { 10 } +//~^^ ERROR use of unstable library feature `rustc_contracts` +//~^^^ ERROR contracts are experimental diff --git a/tests/ui/feature-gates/feature-gate-rustc-contracts.stderr b/tests/ui/feature-gates/feature-gate-rustc-contracts.stderr new file mode 100644 index 00000000000..eb7777a4a51 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-rustc-contracts.stderr @@ -0,0 +1,43 @@ +error[E0658]: use of unstable library feature `rustc_contracts` + --> $DIR/feature-gate-rustc-contracts.rs:3:3 + | +LL | #[core::contracts::requires(x > 0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #133866 <https://github.com/rust-lang/rust/issues/133866> for more information + = help: add `#![feature(rustc_contracts)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `rustc_contracts` + --> $DIR/feature-gate-rustc-contracts.rs:8:3 + | +LL | #[core::contracts::ensures(|ret| *ret > 0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #133866 <https://github.com/rust-lang/rust/issues/133866> for more information + = help: add `#![feature(rustc_contracts)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: contracts are experimental + --> $DIR/feature-gate-rustc-contracts.rs:3:1 + | +LL | #[core::contracts::requires(x > 0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #133866 <https://github.com/rust-lang/rust/issues/133866> for more information + = help: add `#![feature(rustc_contracts)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: contracts are experimental + --> $DIR/feature-gate-rustc-contracts.rs:8:1 + | +LL | #[core::contracts::ensures(|ret| *ret > 0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #133866 <https://github.com/rust-lang/rust/issues/133866> for more information + = help: add `#![feature(rustc_contracts)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. |
