Express contracts as part of function header and lower it to the contract lang items
includes post-developed commit: do not suggest internal-only keywords as corrections to parse failures. includes post-developed commit: removed tabs that creeped in into rustfmt tool source code. includes post-developed commit, placating rustfmt self dogfooding. includes post-developed commit: add backquotes to prevent markdown checking from trying to treat an attr as a markdown hyperlink/ includes post-developed commit: fix lowering to keep contracts from being erroneously inherited by nested bodies (like closures). Rebase Conflicts: - compiler/rustc_parse/src/parser/diagnostics.rs - compiler/rustc_parse/src/parser/item.rs - compiler/rustc_span/src/hygiene.rs Remove contracts keywords from diagnostic messages
This commit is contained in:
parent
777def87d5
commit
38eff16d0a
27 changed files with 405 additions and 17 deletions
|
@ -297,6 +297,28 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Parses a rustc-internal fn contract
|
||||
/// (`rustc_contract_requires(WWW) rustc_contract_ensures(ZZZ)`)
|
||||
pub(super) fn parse_contract(
|
||||
&mut self,
|
||||
) -> PResult<'a, Option<rustc_ast::ptr::P<ast::FnContract>>> {
|
||||
let requires = if self.eat_keyword_noexpect(exp!(RustcContractRequires).kw) {
|
||||
Some(self.parse_expr()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let ensures = if self.eat_keyword_noexpect(exp!(RustcContractEnsures).kw) {
|
||||
Some(self.parse_expr()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if requires.is_none() && ensures.is_none() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(rustc_ast::ptr::P(ast::FnContract { requires, ensures })))
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses an optional where-clause.
|
||||
///
|
||||
/// ```ignore (only-for-syntax-highlight)
|
||||
|
|
|
@ -213,9 +213,12 @@ impl<'a> Parser<'a> {
|
|||
self.parse_use_item()?
|
||||
} else if self.check_fn_front_matter(check_pub, case) {
|
||||
// FUNCTION ITEM
|
||||
let (ident, sig, generics, body) =
|
||||
let (ident, sig, generics, contract, body) =
|
||||
self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
|
||||
(ident, ItemKind::Fn(Box::new(Fn { defaultness: def_(), sig, generics, body })))
|
||||
(
|
||||
ident,
|
||||
ItemKind::Fn(Box::new(Fn { defaultness: def_(), sig, generics, contract, body })),
|
||||
)
|
||||
} else if self.eat_keyword(exp!(Extern)) {
|
||||
if self.eat_keyword(exp!(Crate)) {
|
||||
// EXTERN CRATE
|
||||
|
@ -2372,7 +2375,7 @@ impl<'a> Parser<'a> {
|
|||
sig_lo: Span,
|
||||
vis: &Visibility,
|
||||
case: Case,
|
||||
) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
|
||||
) -> PResult<'a, (Ident, FnSig, Generics, Option<P<FnContract>>, Option<P<Block>>)> {
|
||||
let fn_span = self.token.span;
|
||||
let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn`
|
||||
let ident = self.parse_ident()?; // `foo`
|
||||
|
@ -2398,6 +2401,8 @@ impl<'a> Parser<'a> {
|
|||
// inside `parse_fn_body()`.
|
||||
let fn_params_end = self.prev_token.span.shrink_to_hi();
|
||||
|
||||
let contract = self.parse_contract()?;
|
||||
|
||||
generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
|
||||
|
||||
// `fn_params_end` is needed only when it's followed by a where clause.
|
||||
|
@ -2409,7 +2414,7 @@ impl<'a> Parser<'a> {
|
|||
let body =
|
||||
self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body, fn_params_end)?;
|
||||
let fn_sig_span = sig_lo.to(sig_hi);
|
||||
Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, body))
|
||||
Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, contract, body))
|
||||
}
|
||||
|
||||
/// Provide diagnostics when function body is not found
|
||||
|
|
|
@ -108,6 +108,8 @@ pub enum TokenType {
|
|||
KwRef,
|
||||
KwReturn,
|
||||
KwReuse,
|
||||
KwRustcContractEnsures,
|
||||
KwRustcContractRequires,
|
||||
KwSafe,
|
||||
KwSelfUpper,
|
||||
KwStatic,
|
||||
|
@ -242,6 +244,8 @@ impl TokenType {
|
|||
KwRef,
|
||||
KwReturn,
|
||||
KwReuse,
|
||||
KwRustcContractEnsures,
|
||||
KwRustcContractRequires,
|
||||
KwSafe,
|
||||
KwSelfUpper,
|
||||
KwStatic,
|
||||
|
@ -314,6 +318,8 @@ impl TokenType {
|
|||
TokenType::KwRef => Some(kw::Ref),
|
||||
TokenType::KwReturn => Some(kw::Return),
|
||||
TokenType::KwReuse => Some(kw::Reuse),
|
||||
TokenType::KwRustcContractEnsures => Some(kw::RustcContractEnsures),
|
||||
TokenType::KwRustcContractRequires => Some(kw::RustcContractRequires),
|
||||
TokenType::KwSafe => Some(kw::Safe),
|
||||
TokenType::KwSelfUpper => Some(kw::SelfUpper),
|
||||
TokenType::KwStatic => Some(kw::Static),
|
||||
|
@ -544,6 +550,8 @@ macro_rules! exp {
|
|||
(Ref) => { exp!(@kw, Ref, KwRef) };
|
||||
(Return) => { exp!(@kw, Return, KwReturn) };
|
||||
(Reuse) => { exp!(@kw, Reuse, KwReuse) };
|
||||
(RustcContractEnsures) => { exp!(@kw, RustcContractEnsures, KwRustcContractEnsures) };
|
||||
(RustcContractRequires) => { exp!(@kw, RustcContractRequires, KwRustcContractRequires) };
|
||||
(Safe) => { exp!(@kw, Safe, KwSafe) };
|
||||
(SelfUpper) => { exp!(@kw, SelfUpper, KwSelfUpper) };
|
||||
(Static) => { exp!(@kw, Static, KwStatic) };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue