Skip to content

Commit 75337b6

Browse files
authored
Unrolled build for rust-lang#136835
Rollup merge of rust-lang#136835 - compiler-errors:contracts-span-hack, r=celinval Stop using span hack for contracts feature gating The contracts machinery is a pretty straightforward case of an *external* feature using a (perma-unstable) *internal* feature within its implementation. There's no reason why it needs to be implemented any differently than other features by using global span tracking hacks to change whether the internals are gated behind the `contracts` or `contracts_internals` feature gate -- for the case of macro expansions we already have `allow_internal_unstable` for exactly this situation. This PR changes the internal, perma-unstable AST syntax to use the `contracts_internals` gate always, and adjusts the macro expansion to use the right spans so that `allow_internal_unstable` works correctly. As a follow-up, there's really no reason to have `contracts` be a *compiler feature* since it's at this point fully a *library feature*; the only reason it's a compiler feature today is so we can mark it as incomplete, but that seems like a weak reason. I didn't do anything in this PR for this. r? ``@celinval``
2 parents c182ce9 + f78099e commit 75337b6

File tree

6 files changed

+17
-59
lines changed

6 files changed

+17
-59
lines changed

compiler/rustc_builtin_macros/src/contracts.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
#![allow(unused_imports, unused_variables)]
2-
31
use rustc_ast::token;
42
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
53
use rustc_errors::ErrorGuaranteed;
64
use rustc_expand::base::{AttrProcMacro, ExtCtxt};
75
use rustc_span::Span;
8-
use rustc_span::symbol::{Ident, Symbol, kw, sym};
6+
use rustc_span::symbol::{Ident, Symbol, kw};
97

108
pub(crate) struct ExpandRequires;
119

@@ -121,23 +119,19 @@ fn expand_contract_clause(
121119
}
122120
}
123121

124-
// Record the span as a contract attribute expansion.
125-
// This is used later to stop users from using the extended syntax directly
126-
// which is gated via `contracts_internals`.
127-
ecx.psess().contract_attribute_spans.push(attr_span);
128-
129122
Ok(new_tts)
130123
}
131124

132125
fn expand_requires_tts(
133-
_ecx: &mut ExtCtxt<'_>,
126+
ecx: &mut ExtCtxt<'_>,
134127
attr_span: Span,
135128
annotation: TokenStream,
136129
annotated: TokenStream,
137130
) -> Result<TokenStream, ErrorGuaranteed> {
138-
expand_contract_clause(_ecx, attr_span, annotated, |new_tts| {
131+
let feature_span = ecx.with_def_site_ctxt(attr_span);
132+
expand_contract_clause(ecx, attr_span, annotated, |new_tts| {
139133
new_tts.push_tree(TokenTree::Token(
140-
token::Token::from_ast_ident(Ident::new(kw::ContractRequires, attr_span)),
134+
token::Token::from_ast_ident(Ident::new(kw::ContractRequires, feature_span)),
141135
Spacing::Joint,
142136
));
143137
new_tts.push_tree(TokenTree::Token(
@@ -155,14 +149,15 @@ fn expand_requires_tts(
155149
}
156150

157151
fn expand_ensures_tts(
158-
_ecx: &mut ExtCtxt<'_>,
152+
ecx: &mut ExtCtxt<'_>,
159153
attr_span: Span,
160154
annotation: TokenStream,
161155
annotated: TokenStream,
162156
) -> Result<TokenStream, ErrorGuaranteed> {
163-
expand_contract_clause(_ecx, attr_span, annotated, |new_tts| {
157+
let feature_span = ecx.with_def_site_ctxt(attr_span);
158+
expand_contract_clause(ecx, attr_span, annotated, |new_tts| {
164159
new_tts.push_tree(TokenTree::Token(
165-
token::Token::from_ast_ident(Ident::new(kw::ContractEnsures, attr_span)),
160+
token::Token::from_ast_ident(Ident::new(kw::ContractEnsures, feature_span)),
166161
Spacing::Joint,
167162
));
168163
new_tts.push_tree(TokenTree::Delimited(

compiler/rustc_parse/src/parser/generics.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -302,26 +302,16 @@ 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::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::contracts_internals, span);
312-
}
313-
};
314-
315305
let requires = if self.eat_keyword_noexpect(exp!(ContractRequires).kw) {
306+
self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
316307
let precond = self.parse_expr()?;
317-
gate(precond.span);
318308
Some(precond)
319309
} else {
320310
None
321311
};
322312
let ensures = if self.eat_keyword_noexpect(exp!(ContractEnsures).kw) {
313+
self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
323314
let postcond = self.parse_expr()?;
324-
gate(postcond.span);
325315
Some(postcond)
326316
} else {
327317
None

compiler/rustc_session/src/parse.rs

-5
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,6 @@ pub struct ParseSess {
208208
pub config: Cfg,
209209
pub check_config: CheckCfg,
210210
pub edition: Edition,
211-
/// Places where contract attributes were expanded into unstable AST forms.
212-
/// This is used to allowlist those spans (so that we only check them against the feature
213-
/// gate for the externally visible interface, and not internal implmentation machinery).
214-
pub contract_attribute_spans: AppendOnlyVec<Span>,
215211
/// Places where raw identifiers were used. This is used to avoid complaining about idents
216212
/// clashing with keywords in new editions.
217213
pub raw_identifier_spans: AppendOnlyVec<Span>,
@@ -260,7 +256,6 @@ impl ParseSess {
260256
config: Cfg::default(),
261257
check_config: CheckCfg::default(),
262258
edition: ExpnId::root().expn_data().edition,
263-
contract_attribute_spans: Default::default(),
264259
raw_identifier_spans: Default::default(),
265260
bad_unicode_identifiers: Lock::new(Default::default()),
266261
source_map,

tests/ui/contracts/internal_machinery/internal-feature-gating.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
error[E0658]: contract internal machinery is for internal use only
2-
--> $DIR/internal-feature-gating.rs:16:45
2+
--> $DIR/internal-feature-gating.rs:16:28
33
|
44
LL | fn identity_1() -> i32 contract_requires(|| true) { 10 }
5-
| ^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^
66
|
77
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
88
= help: add `#![feature(contracts_internals)]` to the crate attributes to enable
99
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1010

1111
error[E0658]: contract internal machinery is for internal use only
12-
--> $DIR/internal-feature-gating.rs:18:44
12+
--> $DIR/internal-feature-gating.rs:18:28
1313
|
1414
LL | fn identity_2() -> i32 contract_ensures(|_| true) { 10 }
15-
| ^^^^^^^^^^
15+
| ^^^^^^^^^^^^^^^^
1616
|
1717
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
1818
= help: add `#![feature(contracts_internals)]` to the crate attributes to enable

tests/ui/feature-gates/feature-gate-contracts.rs

-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
#[core::contracts::requires(x > 0)]
44
pub fn requires_needs_it(x: i32) { }
55
//~^^ ERROR use of unstable library feature `contracts`
6-
//~^^^ ERROR contracts are incomplete
76

87
#[core::contracts::ensures(|ret| *ret > 0)]
98
pub fn ensures_needs_it() -> i32 { 10 }
109
//~^^ ERROR use of unstable library feature `contracts`
11-
//~^^^ ERROR contracts are incomplete

tests/ui/feature-gates/feature-gate-contracts.stderr

+2-22
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LL | #[core::contracts::requires(x > 0)]
99
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
1010

1111
error[E0658]: use of unstable library feature `contracts`
12-
--> $DIR/feature-gate-contracts.rs:8:3
12+
--> $DIR/feature-gate-contracts.rs:7:3
1313
|
1414
LL | #[core::contracts::ensures(|ret| *ret > 0)]
1515
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -18,26 +18,6 @@ LL | #[core::contracts::ensures(|ret| *ret > 0)]
1818
= help: add `#![feature(contracts)]` to the crate attributes to enable
1919
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
2020

21-
error[E0658]: contracts are incomplete
22-
--> $DIR/feature-gate-contracts.rs:3:1
23-
|
24-
LL | #[core::contracts::requires(x > 0)]
25-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26-
|
27-
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
28-
= help: add `#![feature(contracts)]` to the crate attributes to enable
29-
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
30-
31-
error[E0658]: contracts are incomplete
32-
--> $DIR/feature-gate-contracts.rs:8:1
33-
|
34-
LL | #[core::contracts::ensures(|ret| *ret > 0)]
35-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36-
|
37-
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
38-
= help: add `#![feature(contracts)]` to the crate attributes to enable
39-
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
40-
41-
error: aborting due to 4 previous errors
21+
error: aborting due to 2 previous errors
4222

4323
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)