Skip to content

Commit ddf5369

Browse files
committed
separate feature gates for the internal machinery that should never be user exposed versus the interface we want to ship externally eventually.
1 parent e8fa3bf commit ddf5369

File tree

17 files changed

+155
-19
lines changed

17 files changed

+155
-19
lines changed

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,8 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
563563
gate_all!(return_type_notation, "return type notation is experimental");
564564
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
565565
gate_all!(unsafe_fields, "`unsafe` fields are experimental");
566+
gate_all!(rustc_contracts, "contracts are experimental");
567+
gate_all!(rustc_contracts_internals, "contract internal machinery is for internal use only");
566568

567569
if !visitor.features.never_patterns() {
568570
if let Some(spans) = spans.get(&sym::never_patterns) {

compiler/rustc_builtin_macros/src/contracts.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl AttrProcMacro for ExpandEnsures {
3636
}
3737

3838
fn expand_injecting_circa_where_clause(
39-
_ecx: &mut ExtCtxt<'_>,
39+
ecx: &mut ExtCtxt<'_>,
4040
attr_span: Span,
4141
annotated: TokenStream,
4242
inject: impl FnOnce(&mut Vec<TokenTree>) -> Result<(), ErrorGuaranteed>,
@@ -122,6 +122,8 @@ fn expand_injecting_circa_where_clause(
122122
new_tts.push(tt.clone());
123123
}
124124

125+
ecx.psess().contract_attribute_spans.push(attr_span);
126+
125127
Ok(TokenStream::new(new_tts))
126128
}
127129

compiler/rustc_feature/src/unstable.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,10 @@ declare_features! (
598598
(unstable, return_type_notation, "1.70.0", Some(109417)),
599599
/// Allows `extern "rust-cold"`.
600600
(unstable, rust_cold_cc, "1.63.0", Some(97544)),
601+
/// Allows use of contracts attributes.
602+
(unstable, rustc_contracts, "CURRENT_RUSTC_VERSION", Some(133866)),
603+
/// Allows access to internal machinery used to implement contracts.
604+
(unstable, rustc_contracts_internals, "CURRENT_RUSTC_VERSION", Some(133866)),
601605
/// Allows use of x86 SHA512, SM3 and SM4 target-features and intrinsics
602606
(unstable, sha512_sm_x86, "1.82.0", Some(126624)),
603607
/// Allows the use of SIMD types in functions declared in `extern` blocks.

compiler/rustc_parse/src/parser/generics.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_ast::{
55
};
66
use rustc_errors::{Applicability, PResult};
77
use rustc_span::Span;
8-
use rustc_span::symbol::{Ident, kw};
8+
use rustc_span::symbol::{Ident, kw, sym};
99
use thin_vec::ThinVec;
1010

1111
use super::{ForceCollect, Parser, Trailing, UsePreAttrPos};
@@ -302,13 +302,26 @@ impl<'a> Parser<'a> {
302302
pub(super) fn parse_contract(
303303
&mut self,
304304
) -> PResult<'a, Option<rustc_ast::ptr::P<ast::FnContract>>> {
305+
let gate = |span| {
306+
if self.psess.contract_attribute_spans.contains(span) {
307+
// span was generated via a builtin contracts attribute, so gate as end-user visible
308+
self.psess.gated_spans.gate(sym::rustc_contracts, span);
309+
} else {
310+
// span was not generated via a builtin contracts attribute, so gate as internal machinery
311+
self.psess.gated_spans.gate(sym::rustc_contracts_internals, span);
312+
}
313+
};
305314
let requires = if self.eat_keyword(kw::RustcContractRequires) {
306-
Some(self.parse_expr()?)
315+
let precond = self.parse_expr()?;
316+
gate(precond.span);
317+
Some(precond)
307318
} else {
308319
None
309320
};
310321
let ensures = if self.eat_keyword(kw::RustcContractEnsures) {
311-
Some(self.parse_expr()?)
322+
let postcond = self.parse_expr()?;
323+
gate(postcond.span);
324+
Some(postcond)
312325
} else {
313326
None
314327
};

compiler/rustc_session/src/parse.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ pub struct ParseSess {
207207
pub config: Cfg,
208208
pub check_config: CheckCfg,
209209
pub edition: Edition,
210+
/// Places where contract attributes were expanded into unstable AST forms.
211+
/// This is used to allowlist those spans (so that we only check them against the feature
212+
/// gate for the externally visible interface, and not internal implmentation machinery).
213+
pub contract_attribute_spans: AppendOnlyVec<Span>,
210214
/// Places where raw identifiers were used. This is used to avoid complaining about idents
211215
/// clashing with keywords in new editions.
212216
pub raw_identifier_spans: AppendOnlyVec<Span>,
@@ -255,6 +259,7 @@ impl ParseSess {
255259
config: Cfg::default(),
256260
check_config: CheckCfg::default(),
257261
edition: ExpnId::root().expn_data().edition,
262+
contract_attribute_spans: Default::default(),
258263
raw_identifier_spans: Default::default(),
259264
bad_unicode_identifiers: Lock::new(Default::default()),
260265
source_map,

compiler/rustc_span/src/symbol.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,8 @@ symbols! {
16961696
rustc_const_stable,
16971697
rustc_const_stable_indirect,
16981698
rustc_const_unstable,
1699+
rustc_contracts,
1700+
rustc_contracts_internals,
16991701
rustc_conversion_suggestion,
17001702
rustc_deallocator,
17011703
rustc_def_path,

library/core/src/contracts.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub use crate::macros::builtin::contracts_requires as requires;
88
/// Emitted by rustc as a desugaring of `#[requires(PRED)] fn foo(x: X) { ... }`
99
/// into: `fn foo(x: X) { check_requires(|| PRED) ... }`
1010
#[cfg(not(bootstrap))]
11-
#[unstable(feature = "rustc_contracts", issue = "none" /* compiler-team#759 */)]
11+
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
1212
#[lang = "contract_check_requires"]
1313
#[track_caller]
1414
pub fn check_requires<C: FnOnce() -> bool>(c: C) {
@@ -21,7 +21,7 @@ pub fn check_requires<C: FnOnce() -> bool>(c: C) {
2121
/// into: `fn foo() { let _check = build_check_ensures(|ret| PRED) ... [return _check(R);] ... }`
2222
/// (including the implicit return of the tail expression, if any).
2323
#[cfg(not(bootstrap))]
24-
#[unstable(feature = "rustc_contracts", issue = "none" /* compiler-team#759 */)]
24+
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
2525
#[lang = "contract_build_check_ensures"]
2626
#[track_caller]
2727
pub fn build_check_ensures<Ret, C>(c: C) -> impl (FnOnce(Ret) -> Ret) + Copy

library/core/src/intrinsics/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4015,8 +4015,8 @@ pub const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize)
40154015
/// checking is turned on, so that we can specify contracts in libstd
40164016
/// and let an end user opt into turning them on.
40174017
#[cfg(not(bootstrap))]
4018-
#[rustc_const_unstable(feature = "rustc_contracts", issue = "none" /* compiler-team#759 */)]
4019-
#[unstable(feature = "rustc_contracts", issue = "none" /* compiler-team#759 */)]
4018+
#[rustc_const_unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
4019+
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
40204020
#[inline(always)]
40214021
#[rustc_intrinsic]
40224022
pub const fn contract_checks() -> bool {
@@ -4027,14 +4027,14 @@ pub const fn contract_checks() -> bool {
40274027
}
40284028

40294029
#[cfg(not(bootstrap))]
4030-
#[unstable(feature = "rustc_contracts", issue = "none" /* compiler-team#759 */)]
4030+
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
40314031
#[rustc_intrinsic]
40324032
pub fn contract_check_requires<C: FnOnce() -> bool>(c: C) -> bool {
40334033
c()
40344034
}
40354035

40364036
#[cfg(not(bootstrap))]
4037-
#[unstable(feature = "rustc_contracts", issue = "none" /* compiler-team#759 */)]
4037+
#[unstable(feature = "rustc_contracts_internals", issue = "133866" /* compiler-team#759 */)]
40384038
#[rustc_intrinsic]
40394039
pub fn contract_check_ensures<'a, Ret, C: FnOnce(&'a Ret) -> bool>(ret: &'a Ret, c: C) -> bool {
40404040
c(ret)

library/core/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ pub mod autodiff {
245245
}
246246

247247
#[cfg(not(bootstrap))]
248-
#[unstable(feature = "rustc_contracts", issue = "none")]
248+
#[unstable(feature = "rustc_contracts", issue = "133866")]
249249
pub mod contracts;
250250

251251
#[unstable(feature = "cfg_match", issue = "115585")]

library/core/src/macros/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,8 +1720,8 @@ pub(crate) mod builtin {
17201720
/// eventually parsed as a unary closure expression that is
17211721
/// invoked on a reference to the return value.
17221722
#[cfg(not(bootstrap))]
1723-
#[unstable(feature = "rustc_contracts", issue = "none")]
1724-
#[allow_internal_unstable(core_intrinsics)]
1723+
#[unstable(feature = "rustc_contracts", issue = "133866")]
1724+
#[allow_internal_unstable(rustc_contracts_internals)]
17251725
#[rustc_builtin_macro]
17261726
pub macro contracts_ensures($item:item) {
17271727
/* compiler built-in */
@@ -1733,8 +1733,8 @@ pub(crate) mod builtin {
17331733
/// eventually parsed as an boolean expression with access to the
17341734
/// function's formal parameters
17351735
#[cfg(not(bootstrap))]
1736-
#[unstable(feature = "rustc_contracts", issue = "none")]
1737-
#[allow_internal_unstable(core_intrinsics)]
1736+
#[unstable(feature = "rustc_contracts", issue = "133866")]
1737+
#[allow_internal_unstable(rustc_contracts_internals)]
17381738
#[rustc_builtin_macro]
17391739
pub macro contracts_requires($item:item) {
17401740
/* compiler built-in */

0 commit comments

Comments
 (0)