Stop using span hack for contracts feature gating
This commit is contained in:
parent
8c04e39595
commit
28164e3c04
6 changed files with 17 additions and 57 deletions
|
@ -4,8 +4,8 @@ use rustc_ast::token;
|
||||||
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
|
use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_expand::base::{AttrProcMacro, ExtCtxt};
|
use rustc_expand::base::{AttrProcMacro, ExtCtxt};
|
||||||
use rustc_span::Span;
|
|
||||||
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
||||||
|
use rustc_span::{DesugaringKind, Span};
|
||||||
|
|
||||||
pub(crate) struct ExpandRequires;
|
pub(crate) struct ExpandRequires;
|
||||||
|
|
||||||
|
@ -121,23 +121,19 @@ fn expand_contract_clause(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 `contracts_internals`.
|
|
||||||
ecx.psess().contract_attribute_spans.push(attr_span);
|
|
||||||
|
|
||||||
Ok(new_tts)
|
Ok(new_tts)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_requires_tts(
|
fn expand_requires_tts(
|
||||||
_ecx: &mut ExtCtxt<'_>,
|
ecx: &mut ExtCtxt<'_>,
|
||||||
attr_span: Span,
|
attr_span: Span,
|
||||||
annotation: TokenStream,
|
annotation: TokenStream,
|
||||||
annotated: TokenStream,
|
annotated: TokenStream,
|
||||||
) -> Result<TokenStream, ErrorGuaranteed> {
|
) -> Result<TokenStream, ErrorGuaranteed> {
|
||||||
expand_contract_clause(_ecx, attr_span, annotated, |new_tts| {
|
let feature_span = ecx.with_def_site_ctxt(attr_span);
|
||||||
|
expand_contract_clause(ecx, attr_span, annotated, |new_tts| {
|
||||||
new_tts.push_tree(TokenTree::Token(
|
new_tts.push_tree(TokenTree::Token(
|
||||||
token::Token::from_ast_ident(Ident::new(kw::ContractRequires, attr_span)),
|
token::Token::from_ast_ident(Ident::new(kw::ContractRequires, feature_span)),
|
||||||
Spacing::Joint,
|
Spacing::Joint,
|
||||||
));
|
));
|
||||||
new_tts.push_tree(TokenTree::Token(
|
new_tts.push_tree(TokenTree::Token(
|
||||||
|
@ -155,14 +151,15 @@ fn expand_requires_tts(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_ensures_tts(
|
fn expand_ensures_tts(
|
||||||
_ecx: &mut ExtCtxt<'_>,
|
ecx: &mut ExtCtxt<'_>,
|
||||||
attr_span: Span,
|
attr_span: Span,
|
||||||
annotation: TokenStream,
|
annotation: TokenStream,
|
||||||
annotated: TokenStream,
|
annotated: TokenStream,
|
||||||
) -> Result<TokenStream, ErrorGuaranteed> {
|
) -> Result<TokenStream, ErrorGuaranteed> {
|
||||||
expand_contract_clause(_ecx, attr_span, annotated, |new_tts| {
|
let feature_span = ecx.with_def_site_ctxt(attr_span);
|
||||||
|
expand_contract_clause(ecx, attr_span, annotated, |new_tts| {
|
||||||
new_tts.push_tree(TokenTree::Token(
|
new_tts.push_tree(TokenTree::Token(
|
||||||
token::Token::from_ast_ident(Ident::new(kw::ContractEnsures, attr_span)),
|
token::Token::from_ast_ident(Ident::new(kw::ContractEnsures, feature_span)),
|
||||||
Spacing::Joint,
|
Spacing::Joint,
|
||||||
));
|
));
|
||||||
new_tts.push_tree(TokenTree::Delimited(
|
new_tts.push_tree(TokenTree::Delimited(
|
||||||
|
|
|
@ -302,26 +302,16 @@ impl<'a> Parser<'a> {
|
||||||
pub(super) fn parse_contract(
|
pub(super) fn parse_contract(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> PResult<'a, Option<rustc_ast::ptr::P<ast::FnContract>>> {
|
) -> 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::contracts, span);
|
|
||||||
} else {
|
|
||||||
// span was not generated via a builtin contracts attribute, so gate as internal machinery
|
|
||||||
self.psess.gated_spans.gate(sym::contracts_internals, span);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let requires = if self.eat_keyword_noexpect(exp!(ContractRequires).kw) {
|
let requires = if self.eat_keyword_noexpect(exp!(ContractRequires).kw) {
|
||||||
|
self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
|
||||||
let precond = self.parse_expr()?;
|
let precond = self.parse_expr()?;
|
||||||
gate(precond.span);
|
|
||||||
Some(precond)
|
Some(precond)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let ensures = if self.eat_keyword_noexpect(exp!(ContractEnsures).kw) {
|
let ensures = if self.eat_keyword_noexpect(exp!(ContractEnsures).kw) {
|
||||||
|
self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
|
||||||
let postcond = self.parse_expr()?;
|
let postcond = self.parse_expr()?;
|
||||||
gate(postcond.span);
|
|
||||||
Some(postcond)
|
Some(postcond)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -208,10 +208,6 @@ pub struct ParseSess {
|
||||||
pub config: Cfg,
|
pub config: Cfg,
|
||||||
pub check_config: CheckCfg,
|
pub check_config: CheckCfg,
|
||||||
pub edition: Edition,
|
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
|
/// Places where raw identifiers were used. This is used to avoid complaining about idents
|
||||||
/// clashing with keywords in new editions.
|
/// clashing with keywords in new editions.
|
||||||
pub raw_identifier_spans: AppendOnlyVec<Span>,
|
pub raw_identifier_spans: AppendOnlyVec<Span>,
|
||||||
|
@ -260,7 +256,6 @@ impl ParseSess {
|
||||||
config: Cfg::default(),
|
config: Cfg::default(),
|
||||||
check_config: CheckCfg::default(),
|
check_config: CheckCfg::default(),
|
||||||
edition: ExpnId::root().expn_data().edition,
|
edition: ExpnId::root().expn_data().edition,
|
||||||
contract_attribute_spans: Default::default(),
|
|
||||||
raw_identifier_spans: Default::default(),
|
raw_identifier_spans: Default::default(),
|
||||||
bad_unicode_identifiers: Lock::new(Default::default()),
|
bad_unicode_identifiers: Lock::new(Default::default()),
|
||||||
source_map,
|
source_map,
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
error[E0658]: contract internal machinery is for internal use only
|
error[E0658]: contract internal machinery is for internal use only
|
||||||
--> $DIR/internal-feature-gating.rs:16:45
|
--> $DIR/internal-feature-gating.rs:16:28
|
||||||
|
|
|
|
||||||
LL | fn identity_1() -> i32 contract_requires(|| true) { 10 }
|
LL | fn identity_1() -> i32 contract_requires(|| true) { 10 }
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
||||||
= help: add `#![feature(contracts_internals)]` to the crate attributes to enable
|
= help: add `#![feature(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
|
= 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
|
error[E0658]: contract internal machinery is for internal use only
|
||||||
--> $DIR/internal-feature-gating.rs:18:44
|
--> $DIR/internal-feature-gating.rs:18:28
|
||||||
|
|
|
|
||||||
LL | fn identity_2() -> i32 contract_ensures(|_| true) { 10 }
|
LL | fn identity_2() -> i32 contract_ensures(|_| true) { 10 }
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
||||||
= help: add `#![feature(contracts_internals)]` to the crate attributes to enable
|
= help: add `#![feature(contracts_internals)]` to the crate attributes to enable
|
||||||
|
|
|
@ -3,9 +3,7 @@
|
||||||
#[core::contracts::requires(x > 0)]
|
#[core::contracts::requires(x > 0)]
|
||||||
pub fn requires_needs_it(x: i32) { }
|
pub fn requires_needs_it(x: i32) { }
|
||||||
//~^^ ERROR use of unstable library feature `contracts`
|
//~^^ ERROR use of unstable library feature `contracts`
|
||||||
//~^^^ ERROR contracts are incomplete
|
|
||||||
|
|
||||||
#[core::contracts::ensures(|ret| *ret > 0)]
|
#[core::contracts::ensures(|ret| *ret > 0)]
|
||||||
pub fn ensures_needs_it() -> i32 { 10 }
|
pub fn ensures_needs_it() -> i32 { 10 }
|
||||||
//~^^ ERROR use of unstable library feature `contracts`
|
//~^^ ERROR use of unstable library feature `contracts`
|
||||||
//~^^^ ERROR contracts are incomplete
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ LL | #[core::contracts::requires(x > 0)]
|
||||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
= 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 `contracts`
|
error[E0658]: use of unstable library feature `contracts`
|
||||||
--> $DIR/feature-gate-contracts.rs:8:3
|
--> $DIR/feature-gate-contracts.rs:7:3
|
||||||
|
|
|
|
||||||
LL | #[core::contracts::ensures(|ret| *ret > 0)]
|
LL | #[core::contracts::ensures(|ret| *ret > 0)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -18,26 +18,6 @@ LL | #[core::contracts::ensures(|ret| *ret > 0)]
|
||||||
= help: add `#![feature(contracts)]` to the crate attributes to enable
|
= help: add `#![feature(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
|
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||||
|
|
||||||
error[E0658]: contracts are incomplete
|
error: aborting due to 2 previous errors
|
||||||
--> $DIR/feature-gate-contracts.rs:3:1
|
|
||||||
|
|
|
||||||
LL | #[core::contracts::requires(x > 0)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
|
||||||
= help: add `#![feature(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 incomplete
|
|
||||||
--> $DIR/feature-gate-contracts.rs:8:1
|
|
||||||
|
|
|
||||||
LL | #[core::contracts::ensures(|ret| *ret > 0)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
|
||||||
= help: add `#![feature(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`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue