Auto merge of #148241 - matthiaskrgr:rollup-4lsapc2, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - rust-lang/rust#144444 (Contract variable declarations) - rust-lang/rust#147281 (Make diagnostics clearer for binop-related errors in foreign crates) - rust-lang/rust#148131 (Skip parameter attribute deduction for MIR with `spread_arg`) - rust-lang/rust#148224 (bootstrap: `ensure(doc::Std)` no longer opens a browser) - rust-lang/rust#148226 (Bootstrap update) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
@@ -3680,6 +3680,9 @@ pub struct TraitImplHeader {
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)]
|
||||
pub struct FnContract {
|
||||
/// Declarations of variables accessible both in the `requires` and
|
||||
/// `ensures` clauses.
|
||||
pub declarations: ThinVec<Stmt>,
|
||||
pub requires: Option<Box<Expr>>,
|
||||
pub ensures: Option<Box<Expr>>,
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
hir::Block { hir_id, stmts, expr, rules, span: self.lower_span(b.span), targeted_by_break }
|
||||
}
|
||||
|
||||
fn lower_stmts(
|
||||
pub(super) fn lower_stmts(
|
||||
&mut self,
|
||||
mut ast_stmts: &[Stmt],
|
||||
) -> (&'hir [hir::Stmt<'hir>], Option<&'hir hir::Expr<'hir>>) {
|
||||
|
||||
@@ -18,6 +18,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
body: impl FnOnce(&mut Self) -> rustc_hir::Expr<'hir>,
|
||||
contract: &rustc_ast::FnContract,
|
||||
) -> rustc_hir::Expr<'hir> {
|
||||
// The order in which things are lowered is important! I.e to
|
||||
// refer to variables in contract_decls from postcond/precond,
|
||||
// we must lower it first!
|
||||
let contract_decls = self.lower_stmts(&contract.declarations).0;
|
||||
|
||||
match (&contract.requires, &contract.ensures) {
|
||||
(Some(req), Some(ens)) => {
|
||||
// Lower the fn contract, which turns:
|
||||
@@ -27,6 +32,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
// into:
|
||||
//
|
||||
// let __postcond = if contract_checks {
|
||||
// CONTRACT_DECLARATIONS;
|
||||
// contract_check_requires(PRECOND);
|
||||
// Some(|ret_val| POSTCOND)
|
||||
// } else {
|
||||
@@ -45,8 +51,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
let precond = self.lower_precond(req);
|
||||
let postcond_checker = self.lower_postcond_checker(ens);
|
||||
|
||||
let contract_check =
|
||||
self.lower_contract_check_with_postcond(Some(precond), postcond_checker);
|
||||
let contract_check = self.lower_contract_check_with_postcond(
|
||||
contract_decls,
|
||||
Some(precond),
|
||||
postcond_checker,
|
||||
);
|
||||
|
||||
let wrapped_body =
|
||||
self.wrap_body_with_contract_check(body, contract_check, postcond_checker.span);
|
||||
@@ -68,15 +77,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
// let ret = { body };
|
||||
//
|
||||
// if contract_checks {
|
||||
// CONTRACT_DECLARATIONS;
|
||||
// contract_check_ensures(__postcond, ret)
|
||||
// } else {
|
||||
// ret
|
||||
// }
|
||||
// }
|
||||
|
||||
let postcond_checker = self.lower_postcond_checker(ens);
|
||||
let contract_check =
|
||||
self.lower_contract_check_with_postcond(None, postcond_checker);
|
||||
self.lower_contract_check_with_postcond(contract_decls, None, postcond_checker);
|
||||
|
||||
let wrapped_body =
|
||||
self.wrap_body_with_contract_check(body, contract_check, postcond_checker.span);
|
||||
@@ -91,12 +100,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
//
|
||||
// {
|
||||
// if contracts_checks {
|
||||
// CONTRACT_DECLARATIONS;
|
||||
// contract_requires(PRECOND);
|
||||
// }
|
||||
// body
|
||||
// }
|
||||
let precond = self.lower_precond(req);
|
||||
let precond_check = self.lower_contract_check_just_precond(precond);
|
||||
let precond_check = self.lower_contract_check_just_precond(contract_decls, precond);
|
||||
|
||||
let body = self.arena.alloc(body(self));
|
||||
|
||||
@@ -145,9 +155,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
fn lower_contract_check_just_precond(
|
||||
&mut self,
|
||||
contract_decls: &'hir [rustc_hir::Stmt<'hir>],
|
||||
precond: rustc_hir::Stmt<'hir>,
|
||||
) -> rustc_hir::Stmt<'hir> {
|
||||
let stmts = self.arena.alloc_from_iter([precond].into_iter());
|
||||
let stmts = self
|
||||
.arena
|
||||
.alloc_from_iter(contract_decls.into_iter().map(|d| *d).chain([precond].into_iter()));
|
||||
|
||||
let then_block_stmts = self.block_all(precond.span, stmts, None);
|
||||
let then_block = self.arena.alloc(self.expr_block(&then_block_stmts));
|
||||
@@ -164,10 +177,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
|
||||
fn lower_contract_check_with_postcond(
|
||||
&mut self,
|
||||
contract_decls: &'hir [rustc_hir::Stmt<'hir>],
|
||||
precond: Option<rustc_hir::Stmt<'hir>>,
|
||||
postcond_checker: &'hir rustc_hir::Expr<'hir>,
|
||||
) -> &'hir rustc_hir::Expr<'hir> {
|
||||
let stmts = self.arena.alloc_from_iter(precond.into_iter());
|
||||
let stmts = self
|
||||
.arena
|
||||
.alloc_from_iter(contract_decls.into_iter().map(|d| *d).chain(precond.into_iter()));
|
||||
let span = match precond {
|
||||
Some(precond) => precond.span,
|
||||
None => postcond_checker.span,
|
||||
|
||||
@@ -17,7 +17,7 @@ impl AttrProcMacro for ExpandRequires {
|
||||
annotation: TokenStream,
|
||||
annotated: TokenStream,
|
||||
) -> Result<TokenStream, ErrorGuaranteed> {
|
||||
expand_requires_tts(ecx, span, annotation, annotated)
|
||||
expand_contract_clause_tts(ecx, span, annotation, annotated, kw::ContractRequires)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ impl AttrProcMacro for ExpandEnsures {
|
||||
annotation: TokenStream,
|
||||
annotated: TokenStream,
|
||||
) -> Result<TokenStream, ErrorGuaranteed> {
|
||||
expand_ensures_tts(ecx, span, annotation, annotated)
|
||||
expand_contract_clause_tts(ecx, span, annotation, annotated, kw::ContractEnsures)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,42 +130,17 @@ fn expand_contract_clause(
|
||||
Ok(new_tts)
|
||||
}
|
||||
|
||||
fn expand_requires_tts(
|
||||
fn expand_contract_clause_tts(
|
||||
ecx: &mut ExtCtxt<'_>,
|
||||
attr_span: Span,
|
||||
annotation: TokenStream,
|
||||
annotated: TokenStream,
|
||||
clause_keyword: rustc_span::Symbol,
|
||||
) -> Result<TokenStream, ErrorGuaranteed> {
|
||||
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(
|
||||
token::Token::from_ast_ident(Ident::new(kw::ContractRequires, feature_span)),
|
||||
Spacing::Joint,
|
||||
));
|
||||
new_tts.push_tree(TokenTree::Token(
|
||||
token::Token::new(token::TokenKind::OrOr, attr_span),
|
||||
Spacing::Alone,
|
||||
));
|
||||
new_tts.push_tree(TokenTree::Delimited(
|
||||
DelimSpan::from_single(attr_span),
|
||||
DelimSpacing::new(Spacing::JointHidden, Spacing::JointHidden),
|
||||
token::Delimiter::Brace,
|
||||
annotation,
|
||||
));
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn expand_ensures_tts(
|
||||
ecx: &mut ExtCtxt<'_>,
|
||||
attr_span: Span,
|
||||
annotation: TokenStream,
|
||||
annotated: TokenStream,
|
||||
) -> Result<TokenStream, ErrorGuaranteed> {
|
||||
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(
|
||||
token::Token::from_ast_ident(Ident::new(kw::ContractEnsures, feature_span)),
|
||||
token::Token::from_ast_ident(Ident::new(clause_keyword, feature_span)),
|
||||
Spacing::Joint,
|
||||
));
|
||||
new_tts.push_tree(TokenTree::Delimited(
|
||||
|
||||
@@ -102,9 +102,9 @@ declare_features! (
|
||||
/// Allows deriving traits as per `SmartPointer` specification
|
||||
(removed, derive_smart_pointer, "1.84.0", Some(123430), Some("replaced by `CoercePointee`"), 131284),
|
||||
/// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
|
||||
(removed, doc_auto_cfg, "CURRENT_RUSTC_VERSION", Some(43781), Some("merged into `doc_cfg`"), 138907),
|
||||
(removed, doc_auto_cfg, "1.92.0", Some(43781), Some("merged into `doc_cfg`"), 138907),
|
||||
/// Allows `#[doc(cfg_hide(...))]`.
|
||||
(removed, doc_cfg_hide, "CURRENT_RUSTC_VERSION", Some(43781), Some("merged into `doc_cfg`"), 138907),
|
||||
(removed, doc_cfg_hide, "1.92.0", Some(43781), Some("merged into `doc_cfg`"), 138907),
|
||||
/// Allows using `#[doc(keyword = "...")]`.
|
||||
(removed, doc_keyword, "1.58.0", Some(51315),
|
||||
Some("merged into `#![feature(rustdoc_internals)]`"), 90420),
|
||||
|
||||
@@ -3046,46 +3046,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
foreign_preds.sort_by_key(|pred: &&ty::TraitPredicate<'_>| pred.trait_ref.to_string());
|
||||
let foreign_def_ids = foreign_preds
|
||||
.iter()
|
||||
.filter_map(|pred| match pred.self_ty().kind() {
|
||||
ty::Adt(def, _) => Some(def.did()),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<FxIndexSet<_>>();
|
||||
let mut foreign_spans: MultiSpan = foreign_def_ids
|
||||
.iter()
|
||||
.filter_map(|def_id| {
|
||||
let span = self.tcx.def_span(*def_id);
|
||||
if span.is_dummy() { None } else { Some(span) }
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
for pred in &foreign_preds {
|
||||
if let ty::Adt(def, _) = pred.self_ty().kind() {
|
||||
foreign_spans.push_span_label(
|
||||
self.tcx.def_span(def.did()),
|
||||
format!("not implement `{}`", pred.trait_ref.print_trait_sugared()),
|
||||
);
|
||||
|
||||
for pred in foreign_preds {
|
||||
let ty = pred.self_ty();
|
||||
let ty::Adt(def, _) = ty.kind() else { continue };
|
||||
let span = self.tcx.def_span(def.did());
|
||||
if span.is_dummy() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if foreign_spans.primary_span().is_some() {
|
||||
let msg = if let [foreign_pred] = foreign_preds.as_slice() {
|
||||
format!(
|
||||
"the foreign item type `{}` doesn't implement `{}`",
|
||||
foreign_pred.self_ty(),
|
||||
foreign_pred.trait_ref.print_trait_sugared()
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"the foreign item type{} {} implement required trait{} for this \
|
||||
operation to be valid",
|
||||
pluralize!(foreign_def_ids.len()),
|
||||
if foreign_def_ids.len() > 1 { "don't" } else { "doesn't" },
|
||||
pluralize!(foreign_preds.len()),
|
||||
)
|
||||
};
|
||||
err.span_note(foreign_spans, msg);
|
||||
let mut mspan: MultiSpan = span.into();
|
||||
mspan.push_span_label(span, format!("`{ty}` is defined in another crate"));
|
||||
err.span_note(
|
||||
mspan,
|
||||
format!("`{ty}` does not implement `{}`", pred.trait_ref.print_trait_sugared()),
|
||||
);
|
||||
}
|
||||
|
||||
let preds: Vec<_> = errors
|
||||
|
||||
@@ -135,7 +135,7 @@ impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeInclusive<I> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "nightly", not(bootstrap)))]
|
||||
#[cfg(feature = "nightly")]
|
||||
impl<I: Idx, T> IntoSliceIdx<I, [T]> for core::range::RangeToInclusive<I> {
|
||||
type Output = core::range::RangeToInclusive<usize>;
|
||||
#[inline]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))]
|
||||
#![cfg_attr(bootstrap, feature(new_zeroed_alloc))]
|
||||
#![cfg_attr(feature = "nightly", allow(internal_features))]
|
||||
#![cfg_attr(feature = "nightly", feature(extend_one, step_trait, test))]
|
||||
#![cfg_attr(feature = "nightly", feature(new_range_api))]
|
||||
|
||||
@@ -195,6 +195,11 @@ pub(super) fn deduced_param_attrs<'tcx>(
|
||||
|
||||
// Grab the optimized MIR. Analyze it to determine which arguments have been mutated.
|
||||
let body: &Body<'tcx> = tcx.optimized_mir(def_id);
|
||||
// Arguments spread at ABI level are currently unsupported.
|
||||
if body.spread_arg.is_some() {
|
||||
return &[];
|
||||
}
|
||||
|
||||
let mut deduce = DeduceParamAttrs::new(body);
|
||||
deduce.visit_body(body);
|
||||
tracing::trace!(?deduce.usage);
|
||||
|
||||
@@ -4036,6 +4036,30 @@ impl<'a> Parser<'a> {
|
||||
self.mk_expr(span, ExprKind::Err(guar))
|
||||
}
|
||||
|
||||
pub(crate) fn mk_unit_expr(&self, span: Span) -> Box<Expr> {
|
||||
self.mk_expr(span, ExprKind::Tup(Default::default()))
|
||||
}
|
||||
|
||||
pub(crate) fn mk_closure_expr(&self, span: Span, body: Box<Expr>) -> Box<Expr> {
|
||||
self.mk_expr(
|
||||
span,
|
||||
ast::ExprKind::Closure(Box::new(ast::Closure {
|
||||
binder: rustc_ast::ClosureBinder::NotPresent,
|
||||
constness: rustc_ast::Const::No,
|
||||
movability: rustc_ast::Movability::Movable,
|
||||
capture_clause: rustc_ast::CaptureBy::Ref,
|
||||
coroutine_kind: None,
|
||||
fn_decl: Box::new(rustc_ast::FnDecl {
|
||||
inputs: Default::default(),
|
||||
output: rustc_ast::FnRetTy::Default(span),
|
||||
}),
|
||||
fn_arg_span: span,
|
||||
fn_decl_span: span,
|
||||
body,
|
||||
})),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create expression span ensuring the span of the parent node
|
||||
/// is larger than the span of lhs and rhs, including the attributes.
|
||||
fn mk_expr_sp(&self, lhs: &Box<Expr>, lhs_span: Span, op_span: Span, rhs_span: Span) -> Span {
|
||||
|
||||
@@ -312,25 +312,48 @@ impl<'a> Parser<'a> {
|
||||
/// Parses an experimental fn contract
|
||||
/// (`contract_requires(WWW) contract_ensures(ZZZ)`)
|
||||
pub(super) fn parse_contract(&mut self) -> PResult<'a, Option<Box<ast::FnContract>>> {
|
||||
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()?;
|
||||
Some(precond)
|
||||
let (declarations, requires) = self.parse_contract_requires()?;
|
||||
let ensures = self.parse_contract_ensures()?;
|
||||
|
||||
if requires.is_none() && ensures.is_none() {
|
||||
Ok(None)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let ensures = if self.eat_keyword_noexpect(exp!(ContractEnsures).kw) {
|
||||
Ok(Some(Box::new(ast::FnContract { declarations, requires, ensures })))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_contract_requires(
|
||||
&mut self,
|
||||
) -> PResult<'a, (ThinVec<rustc_ast::Stmt>, Option<Box<rustc_ast::Expr>>)> {
|
||||
Ok(if self.eat_keyword_noexpect(exp!(ContractRequires).kw) {
|
||||
self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
|
||||
let mut decls_and_precond = self.parse_block()?;
|
||||
|
||||
let precond = match decls_and_precond.stmts.pop() {
|
||||
Some(precond) => match precond.kind {
|
||||
rustc_ast::StmtKind::Expr(expr) => expr,
|
||||
// Insert dummy node that will be rejected by typechecker to
|
||||
// avoid reinventing an error
|
||||
_ => self.mk_unit_expr(decls_and_precond.span),
|
||||
},
|
||||
None => self.mk_unit_expr(decls_and_precond.span),
|
||||
};
|
||||
let precond = self.mk_closure_expr(precond.span, precond);
|
||||
let decls = decls_and_precond.stmts;
|
||||
(decls, Some(precond))
|
||||
} else {
|
||||
(Default::default(), None)
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_contract_ensures(&mut self) -> PResult<'a, Option<Box<rustc_ast::Expr>>> {
|
||||
Ok(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()?;
|
||||
Some(postcond)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if requires.is_none() && ensures.is_none() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(Box::new(ast::FnContract { requires, ensures })))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Parses an optional where-clause.
|
||||
|
||||
@@ -300,7 +300,7 @@ impl<T> Box<T> {
|
||||
/// [zeroed]: mem::MaybeUninit::zeroed
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[inline]
|
||||
#[stable(feature = "new_zeroed_alloc", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "new_zeroed_alloc", since = "1.92.0")]
|
||||
#[must_use]
|
||||
pub fn new_zeroed() -> Box<mem::MaybeUninit<T>> {
|
||||
Self::new_zeroed_in(Global)
|
||||
@@ -692,7 +692,7 @@ impl<T> Box<[T]> {
|
||||
///
|
||||
/// [zeroed]: mem::MaybeUninit::zeroed
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "new_zeroed_alloc", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "new_zeroed_alloc", since = "1.92.0")]
|
||||
#[must_use]
|
||||
pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit<T>]> {
|
||||
unsafe { RawVec::with_capacity_zeroed(len).into_box(len) }
|
||||
|
||||
@@ -284,7 +284,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> {
|
||||
/// assert_eq!(entry.key(), &"poneyland");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "btree_entry_insert", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "btree_entry_insert", since = "1.92.0")]
|
||||
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, A> {
|
||||
match self {
|
||||
Occupied(mut entry) => {
|
||||
@@ -394,7 +394,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> {
|
||||
/// }
|
||||
/// assert_eq!(map["poneyland"], 37);
|
||||
/// ```
|
||||
#[stable(feature = "btree_entry_insert", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "btree_entry_insert", since = "1.92.0")]
|
||||
pub fn insert_entry(mut self, value: V) -> OccupiedEntry<'a, K, V, A> {
|
||||
let handle = match self.handle {
|
||||
None => {
|
||||
|
||||
@@ -529,7 +529,7 @@ impl<T> Rc<T> {
|
||||
///
|
||||
/// [zeroed]: mem::MaybeUninit::zeroed
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "new_zeroed_alloc", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "new_zeroed_alloc", since = "1.92.0")]
|
||||
#[must_use]
|
||||
pub fn new_zeroed() -> Rc<mem::MaybeUninit<T>> {
|
||||
unsafe {
|
||||
@@ -1057,7 +1057,7 @@ impl<T> Rc<[T]> {
|
||||
///
|
||||
/// [zeroed]: mem::MaybeUninit::zeroed
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[stable(feature = "new_zeroed_alloc", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "new_zeroed_alloc", since = "1.92.0")]
|
||||
#[must_use]
|
||||
pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
|
||||
unsafe {
|
||||
|
||||
@@ -536,7 +536,7 @@ impl<T> Arc<T> {
|
||||
/// [zeroed]: mem::MaybeUninit::zeroed
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[inline]
|
||||
#[stable(feature = "new_zeroed_alloc", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "new_zeroed_alloc", since = "1.92.0")]
|
||||
#[must_use]
|
||||
pub fn new_zeroed() -> Arc<mem::MaybeUninit<T>> {
|
||||
unsafe {
|
||||
@@ -1205,7 +1205,7 @@ impl<T> Arc<[T]> {
|
||||
/// [zeroed]: mem::MaybeUninit::zeroed
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[inline]
|
||||
#[stable(feature = "new_zeroed_alloc", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "new_zeroed_alloc", since = "1.92.0")]
|
||||
#[must_use]
|
||||
pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
|
||||
unsafe {
|
||||
|
||||
@@ -1382,11 +1382,8 @@ macro_rules! nonzero_integer_signedness_dependent_impls {
|
||||
#[doc = concat!("let three = NonZero::new(3", stringify!($Int), ").unwrap();")]
|
||||
/// assert_eq!(three.div_ceil(two), two);
|
||||
/// ```
|
||||
#[stable(feature = "unsigned_nonzero_div_ceil", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(
|
||||
feature = "unsigned_nonzero_div_ceil",
|
||||
since = "CURRENT_RUSTC_VERSION"
|
||||
)]
|
||||
#[stable(feature = "unsigned_nonzero_div_ceil", since = "1.92.0")]
|
||||
#[rustc_const_stable(feature = "unsigned_nonzero_div_ceil", since = "1.92.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
|
||||
@@ -194,8 +194,8 @@ impl<'a> Location<'a> {
|
||||
/// `std::source_location::file_name`, both of which return a nul-terminated `const char*`.
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[stable(feature = "file_with_nul", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "file_with_nul", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "file_with_nul", since = "1.92.0")]
|
||||
#[rustc_const_stable(feature = "file_with_nul", since = "1.92.0")]
|
||||
pub const fn file_as_c_str(&self) -> &'a CStr {
|
||||
let filename = self.filename.as_ptr();
|
||||
|
||||
|
||||
@@ -3629,7 +3629,7 @@ impl<T> [T] {
|
||||
/// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
|
||||
/// ```
|
||||
#[stable(feature = "slice_rotate", since = "1.26.0")]
|
||||
#[rustc_const_stable(feature = "const_slice_rotate", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "const_slice_rotate", since = "1.92.0")]
|
||||
pub const fn rotate_left(&mut self, mid: usize) {
|
||||
assert!(mid <= self.len());
|
||||
let k = self.len() - mid;
|
||||
@@ -3675,7 +3675,7 @@ impl<T> [T] {
|
||||
/// assert_eq!(a, ['a', 'e', 'b', 'c', 'd', 'f']);
|
||||
/// ```
|
||||
#[stable(feature = "slice_rotate", since = "1.26.0")]
|
||||
#[rustc_const_stable(feature = "const_slice_rotate", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "const_slice_rotate", since = "1.92.0")]
|
||||
pub const fn rotate_right(&mut self, k: usize) {
|
||||
assert!(k <= self.len());
|
||||
let mid = self.len() - k;
|
||||
|
||||
@@ -565,7 +565,7 @@ impl Iterator for EncodeWide<'_> {
|
||||
#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")]
|
||||
impl FusedIterator for EncodeWide<'_> {}
|
||||
|
||||
#[stable(feature = "encode_wide_debug", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "encode_wide_debug", since = "1.92.0")]
|
||||
impl fmt::Debug for EncodeWide<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
struct CodeUnit(u16);
|
||||
|
||||
@@ -379,7 +379,7 @@ impl Extend<TokenStream> for TokenStream {
|
||||
macro_rules! extend_items {
|
||||
($($item:ident)*) => {
|
||||
$(
|
||||
#[stable(feature = "token_stream_extend_tt_items", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "token_stream_extend_tt_items", since = "1.92.0")]
|
||||
impl Extend<$item> for TokenStream {
|
||||
fn extend<T: IntoIterator<Item = $item>>(&mut self, iter: T) {
|
||||
self.extend(iter.into_iter().map(TokenTree::$item));
|
||||
|
||||
@@ -859,7 +859,7 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
|
||||
/// # let final_check = rw.read().unwrap();
|
||||
/// # assert_eq!(*final_check, 3);
|
||||
/// ```
|
||||
#[stable(feature = "rwlock_downgrade", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "rwlock_downgrade", since = "1.92.0")]
|
||||
pub fn downgrade(s: Self) -> RwLockReadGuard<'rwlock, T> {
|
||||
let lock = s.lock;
|
||||
|
||||
|
||||
@@ -709,12 +709,12 @@ impl Step for Std {
|
||||
if builder.paths.iter().any(|path| path.ends_with("library")) {
|
||||
// For `x.py doc library --open`, open `std` by default.
|
||||
let index = out.join("std").join("index.html");
|
||||
builder.open_in_browser(index);
|
||||
builder.maybe_open_in_browser::<Self>(index);
|
||||
} else {
|
||||
for requested_crate in crates {
|
||||
if STD_PUBLIC_CRATES.iter().any(|&k| k == requested_crate) {
|
||||
let index = out.join(requested_crate).join("index.html");
|
||||
builder.open_in_browser(index);
|
||||
builder.maybe_open_in_browser::<Self>(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ pub struct Finder {
|
||||
// Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap).
|
||||
const STAGE0_MISSING_TARGETS: &[&str] = &[
|
||||
// just a dummy comment so the list doesn't get onelined
|
||||
"x86_64-unknown-motor",
|
||||
];
|
||||
|
||||
/// Minimum version threshold for libstdc++ required when using prebuilt LLVM
|
||||
|
||||
1044
src/stage0
1044
src/stage0
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@
|
||||
#![feature(derive_coerce_pointee)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(iter_advance_by)]
|
||||
#![cfg_attr(not(bootstrap), feature(duration_from_nanos_u128))]
|
||||
#![feature(duration_from_nanos_u128)]
|
||||
// Configure clippy and other lints
|
||||
#![allow(
|
||||
clippy::collapsible_else_if,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//@ revisions: LLVM21 LLVM20
|
||||
//@ [LLVM21] min-llvm-version: 21
|
||||
//@ [LLVM20] max-llvm-major-version: 20
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
#![feature(custom_mir, core_intrinsics, unboxed_closures)]
|
||||
#![crate_type = "lib"]
|
||||
extern crate core;
|
||||
use core::intrinsics::mir::*;
|
||||
@@ -170,3 +170,11 @@ pub fn not_captured_return_place() -> [u8; 80] {
|
||||
pub fn captured_return_place() -> [u8; 80] {
|
||||
black_box([0u8; 80])
|
||||
}
|
||||
|
||||
// Arguments spread at ABI level are unsupported.
|
||||
//
|
||||
// CHECK-LABEL: @spread_arg(
|
||||
// CHECK-NOT: readonly
|
||||
// CHECK-SAME: )
|
||||
#[no_mangle]
|
||||
pub extern "rust-call" fn spread_arg(_: (Big, Big, Big)) {}
|
||||
|
||||
@@ -6,10 +6,10 @@ LL | let k = i + j;
|
||||
| |
|
||||
| Vec<R>
|
||||
|
|
||||
note: the foreign item type `Vec<R>` doesn't implement `Add`
|
||||
note: `Vec<R>` does not implement `Add`
|
||||
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Add`
|
||||
= note: `Vec<R>` is defined in another crate
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ LL | let z: isize = a.x + b.y;
|
||||
| |
|
||||
| Box<isize>
|
||||
|
|
||||
note: the foreign item type `Box<isize>` doesn't implement `Add`
|
||||
note: `Box<isize>` does not implement `Add`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Add`
|
||||
= note: `Box<isize>` is defined in another crate
|
||||
|
||||
error[E0369]: cannot add `Box<isize>` to `Box<isize>`
|
||||
--> $DIR/autoderef-box-no-add.rs:31:33
|
||||
@@ -20,11 +20,11 @@ LL | let answer: isize = forty.a + two.a;
|
||||
| |
|
||||
| Box<isize>
|
||||
|
|
||||
note: the foreign item type `Box<isize>` doesn't implement `Add`
|
||||
note: `Box<isize>` does not implement `Add`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Add`
|
||||
= note: `Box<isize>` is defined in another crate
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ note: an implementation of `PartialEq` might be missing for `T1`
|
||||
|
|
||||
LL | struct T1;
|
||||
| ^^^^^^^^^ must implement `PartialEq`
|
||||
note: the foreign item type `std::io::Error` doesn't implement `PartialEq`
|
||||
note: `std::io::Error` does not implement `PartialEq`
|
||||
--> $SRC_DIR/std/src/io/error.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
= note: `std::io::Error` is defined in another crate
|
||||
help: consider annotating `T1` with `#[derive(PartialEq)]`
|
||||
|
|
||||
LL + #[derive(PartialEq)]
|
||||
@@ -29,13 +29,14 @@ LL | (Error::new(ErrorKind::Other, "2"), thread::current())
|
||||
LL | == (Error::new(ErrorKind::Other, "2"), thread::current());
|
||||
| ^^ ------------------------------------------------------ (std::io::Error, Thread)
|
||||
|
|
||||
note: the foreign item types don't implement required traits for this operation to be valid
|
||||
--> $SRC_DIR/std/src/io/error.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
note: `Thread` does not implement `PartialEq`
|
||||
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
= note: `Thread` is defined in another crate
|
||||
note: `std::io::Error` does not implement `PartialEq`
|
||||
--> $SRC_DIR/std/src/io/error.rs:LL:COL
|
||||
|
|
||||
= note: `std::io::Error` is defined in another crate
|
||||
|
||||
error[E0369]: binary operation `==` cannot be applied to type `(std::io::Error, Thread, T1, T2)`
|
||||
--> $DIR/binary-op-not-allowed-issue-125631.rs:14:9
|
||||
@@ -52,13 +53,14 @@ LL | struct T1;
|
||||
| ^^^^^^^^^ must implement `PartialEq`
|
||||
LL | struct T2;
|
||||
| ^^^^^^^^^ must implement `PartialEq`
|
||||
note: the foreign item types don't implement required traits for this operation to be valid
|
||||
--> $SRC_DIR/std/src/io/error.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
note: `Thread` does not implement `PartialEq`
|
||||
--> $SRC_DIR/std/src/thread/mod.rs:LL:COL
|
||||
|
|
||||
= note: not implement `PartialEq`
|
||||
= note: `Thread` is defined in another crate
|
||||
note: `std::io::Error` does not implement `PartialEq`
|
||||
--> $SRC_DIR/std/src/io/error.rs:LL:COL
|
||||
|
|
||||
= note: `std::io::Error` is defined in another crate
|
||||
help: consider annotating `T1` with `#[derive(PartialEq)]`
|
||||
|
|
||||
LL + #[derive(PartialEq)]
|
||||
|
||||
@@ -6,10 +6,10 @@ LL | fn main() { let x = "a".to_string() ^ "b".to_string(); }
|
||||
| |
|
||||
| String
|
||||
|
|
||||
note: the foreign item type `String` doesn't implement `BitXor`
|
||||
note: `String` does not implement `BitXor`
|
||||
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
||||
|
|
||||
= note: not implement `BitXor`
|
||||
= note: `String` is defined in another crate
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//@ run-pass
|
||||
#![feature(contracts)]
|
||||
//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
|
||||
|
||||
extern crate core;
|
||||
use core::contracts::requires;
|
||||
|
||||
#[requires(*x = 0; true)]
|
||||
fn buggy_add(x: &mut u32, y: u32) {
|
||||
*x = *x + y;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut x = 10;
|
||||
buggy_add(&mut x, 100);
|
||||
assert_eq!(x, 110);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/contracts-disabled-side-effect-declarations.rs:2:12
|
||||
|
|
||||
LL | #![feature(contracts)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
extern crate core;
|
||||
use core::contracts::ensures;
|
||||
|
||||
#[ensures({*x = 0; |_ret| true})]
|
||||
#[ensures(*x = 0; |_ret| true)]
|
||||
fn buggy_add(x: &mut u32, y: u32) {
|
||||
*x = *x + y;
|
||||
}
|
||||
|
||||
19
tests/ui/contracts/declared-vars-referring-to-params.rs
Normal file
19
tests/ui/contracts/declared-vars-referring-to-params.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
//@ run-pass
|
||||
//@ compile-flags: -Zcontract-checks=yes
|
||||
#![feature(contracts)]
|
||||
//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
|
||||
|
||||
extern crate core;
|
||||
use core::contracts::{ensures, requires};
|
||||
|
||||
// checks that variable declarations are lowered properly, with the ability to
|
||||
// access function parameters
|
||||
#[requires(let y = 2 * x; true)]
|
||||
#[ensures(move |ret| { *ret == y })]
|
||||
fn foo(x: u32) -> u32 {
|
||||
x * 2
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(1);
|
||||
}
|
||||
11
tests/ui/contracts/declared-vars-referring-to-params.stderr
Normal file
11
tests/ui/contracts/declared-vars-referring-to-params.stderr
Normal file
@@ -0,0 +1,11 @@
|
||||
warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/declared-vars-referring-to-params.rs:3:12
|
||||
|
|
||||
LL | #![feature(contracts)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
17
tests/ui/contracts/declared-vars-used-in-ensures.rs
Normal file
17
tests/ui/contracts/declared-vars-used-in-ensures.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
//@ run-pass
|
||||
//@ compile-flags: -Zcontract-checks=yes
|
||||
#![feature(contracts)]
|
||||
//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
|
||||
|
||||
extern crate core;
|
||||
use core::contracts::{ensures, requires};
|
||||
|
||||
#[requires(let y = 1; true)]
|
||||
#[ensures(move |_ret| { y == 1 })]
|
||||
fn foo(x: u32) -> u32 {
|
||||
x * 2
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(1);
|
||||
}
|
||||
11
tests/ui/contracts/declared-vars-used-in-ensures.stderr
Normal file
11
tests/ui/contracts/declared-vars-used-in-ensures.stderr
Normal file
@@ -0,0 +1,11 @@
|
||||
warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/declared-vars-used-in-ensures.rs:3:12
|
||||
|
|
||||
LL | #![feature(contracts)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
//@ run-pass
|
||||
//@ compile-flags: -Zcontract-checks=yes
|
||||
#![feature(contracts)]
|
||||
//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
|
||||
|
||||
extern crate core;
|
||||
use core::contracts::{ensures, requires};
|
||||
|
||||
// checks that variable declarations are lowered properly, with the ability to
|
||||
// refer to them *both* in requires and ensures
|
||||
#[requires(let y = 2 * x; y > 0)]
|
||||
#[ensures(move |ret| { *ret == y })]
|
||||
fn foo(x: u32) -> u32 {
|
||||
x * 2
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(1);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/declared-vars-used-in-requires-and-ensures.rs:3:12
|
||||
|
|
||||
LL | #![feature(contracts)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
#![feature(contracts_internals)]
|
||||
|
||||
fn nest(x: Baz) -> i32
|
||||
contract_requires(|| x.baz > 0)
|
||||
contract_ensures(|ret| *ret > 100)
|
||||
contract_requires { x.baz > 0 }
|
||||
contract_ensures { |ret| *ret > 100 }
|
||||
{
|
||||
loop {
|
||||
return x.baz + 50;
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
#![feature(contracts_internals)]
|
||||
|
||||
fn tail(x: Baz) -> i32
|
||||
contract_requires(|| x.baz > 0)
|
||||
contract_ensures(|ret| *ret > 100)
|
||||
contract_requires { x.baz > 0 }
|
||||
contract_ensures { |ret| *ret > 100 }
|
||||
{
|
||||
x.baz + 50
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#![feature(contracts_internals)]
|
||||
|
||||
fn outer() -> i32
|
||||
contract_ensures(|ret| *ret > 0)
|
||||
contract_ensures { |ret| *ret > 0 }
|
||||
{
|
||||
let inner_closure = || -> i32 { 0 };
|
||||
inner_closure();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
struct Outer { outer: std::cell::Cell<i32> }
|
||||
|
||||
fn outer(x: Outer)
|
||||
contract_requires(|| x.outer.get() > 0)
|
||||
contract_requires { x.outer.get() > 0 }
|
||||
{
|
||||
let inner_closure = || { };
|
||||
x.outer.set(0);
|
||||
|
||||
@@ -11,8 +11,8 @@ fn main() {
|
||||
//~^ ERROR use of unstable library feature `contracts_internals`
|
||||
|
||||
// ast extensions are guarded by contracts_internals feature gate
|
||||
fn identity_1() -> i32 contract_requires(|| true) { 10 }
|
||||
fn identity_1() -> i32 contract_requires { true } { 10 }
|
||||
//~^ ERROR contract internal machinery is for internal use only
|
||||
fn identity_2() -> i32 contract_ensures(|_| true) { 10 }
|
||||
fn identity_2() -> i32 contract_ensures { |_| true } { 10 }
|
||||
//~^ ERROR contract internal machinery is for internal use only
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
error[E0658]: contract internal machinery is for internal use only
|
||||
--> $DIR/internal-feature-gating.rs:14: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
|
||||
@@ -11,7 +11,7 @@ LL | fn identity_1() -> i32 contract_requires(|| true) { 10 }
|
||||
error[E0658]: contract internal machinery is for internal use only
|
||||
--> $DIR/internal-feature-gating.rs:16: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
|
||||
|
||||
24
tests/ui/contracts/internal_machinery/lowering/basics.rs
Normal file
24
tests/ui/contracts/internal_machinery/lowering/basics.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
//@ run-pass
|
||||
#![feature(contracts, cfg_contract_checks, contracts_internals, core_intrinsics)]
|
||||
//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
|
||||
|
||||
extern crate core;
|
||||
|
||||
// we check here if the "lowered" program behaves as expected before
|
||||
// implementing the actual lowering in the compiler
|
||||
|
||||
fn foo(x: u32) -> u32 {
|
||||
let post = {
|
||||
let y = 2 * x;
|
||||
// call contract_check_requires here to avoid borrow checker issues
|
||||
// with variables declared in contract requires
|
||||
core::intrinsics::contract_check_requires(|| y > 0);
|
||||
Some(core::contracts::build_check_ensures(move |ret| *ret == y))
|
||||
};
|
||||
|
||||
core::intrinsics::contract_check_ensures(post, { 2 * x })
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(1);
|
||||
}
|
||||
11
tests/ui/contracts/internal_machinery/lowering/basics.stderr
Normal file
11
tests/ui/contracts/internal_machinery/lowering/basics.stderr
Normal file
@@ -0,0 +1,11 @@
|
||||
warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/basics.rs:2:12
|
||||
|
|
||||
LL | #![feature(contracts, cfg_contract_checks, contracts_internals, core_intrinsics)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
18
tests/ui/contracts/requires-bool-expr-with-semicolon.rs
Normal file
18
tests/ui/contracts/requires-bool-expr-with-semicolon.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
//@ dont-require-annotations: NOTE
|
||||
//@ compile-flags: -Zcontract-checks=yes
|
||||
#![feature(contracts)]
|
||||
//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
|
||||
|
||||
extern crate core;
|
||||
use core::contracts::requires;
|
||||
|
||||
#[requires(true;)]
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
//~| NOTE expected `bool`, found `()`
|
||||
fn foo(x: u32) -> u32 {
|
||||
x * 2
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(1);
|
||||
}
|
||||
18
tests/ui/contracts/requires-bool-expr-with-semicolon.stderr
Normal file
18
tests/ui/contracts/requires-bool-expr-with-semicolon.stderr
Normal file
@@ -0,0 +1,18 @@
|
||||
warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/requires-bool-expr-with-semicolon.rs:3:12
|
||||
|
|
||||
LL | #![feature(contracts)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/requires-bool-expr-with-semicolon.rs:9:1
|
||||
|
|
||||
LL | #[requires(true;)]
|
||||
| ^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
18
tests/ui/contracts/requires-no-final-expression.rs
Normal file
18
tests/ui/contracts/requires-no-final-expression.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
//@ dont-require-annotations: NOTE
|
||||
//@ compile-flags: -Zcontract-checks=yes
|
||||
#![feature(contracts)]
|
||||
//~^ WARN the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes [incomplete_features]
|
||||
|
||||
extern crate core;
|
||||
use core::contracts::requires;
|
||||
|
||||
#[requires(let y = 1;)]
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
//~| NOTE expected `bool`, found `()`
|
||||
fn foo(x: u32) -> u32 {
|
||||
x * 2
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo(1);
|
||||
}
|
||||
18
tests/ui/contracts/requires-no-final-expression.stderr
Normal file
18
tests/ui/contracts/requires-no-final-expression.stderr
Normal file
@@ -0,0 +1,18 @@
|
||||
warning: the feature `contracts` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/requires-no-final-expression.rs:3:12
|
||||
|
|
||||
LL | #![feature(contracts)]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #128044 <https://github.com/rust-lang/rust/issues/128044> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/requires-no-final-expression.rs:9:1
|
||||
|
|
||||
LL | #[requires(let y = 1;)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
@@ -6,11 +6,11 @@ LL | LinkedList::new() += 1;
|
||||
| |
|
||||
| cannot use `+=` on type `LinkedList<_>`
|
||||
|
|
||||
note: the foreign item type `LinkedList<_>` doesn't implement `AddAssign<{integer}>`
|
||||
note: `LinkedList<_>` does not implement `AddAssign<{integer}>`
|
||||
--> $SRC_DIR/alloc/src/collections/linked_list.rs:LL:COL
|
||||
::: $SRC_DIR/alloc/src/collections/linked_list.rs:LL:COL
|
||||
|
|
||||
= note: not implement `AddAssign<{integer}>`
|
||||
= note: `LinkedList<_>` is defined in another crate
|
||||
|
||||
error[E0067]: invalid left-hand side of assignment
|
||||
--> $DIR/E0067.rs:4:23
|
||||
|
||||
@@ -6,11 +6,11 @@ LL | println!("{}", x + 1);
|
||||
| |
|
||||
| Box<isize>
|
||||
|
|
||||
note: the foreign item type `Box<isize>` doesn't implement `Add<{integer}>`
|
||||
note: `Box<isize>` does not implement `Add<{integer}>`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Add<{integer}>`
|
||||
= note: `Box<isize>` is defined in another crate
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ LL | fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3;
|
||||
| |
|
||||
| Vec<isize>
|
||||
|
|
||||
note: the foreign item type `Vec<isize>` doesn't implement `Mul<{integer}>`
|
||||
note: `Vec<isize>` does not implement `Mul<{integer}>`
|
||||
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Mul<{integer}>`
|
||||
= note: `Vec<isize>` is defined in another crate
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
@@ -19,10 +19,10 @@ LL | x.lock().unwrap() += 1;
|
||||
| |
|
||||
| cannot use `+=` on type `std::sync::MutexGuard<'_, usize>`
|
||||
|
|
||||
note: the foreign item type `std::sync::MutexGuard<'_, usize>` doesn't implement `AddAssign<{integer}>`
|
||||
note: `std::sync::MutexGuard<'_, usize>` does not implement `AddAssign<{integer}>`
|
||||
--> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL
|
||||
|
|
||||
= note: not implement `AddAssign<{integer}>`
|
||||
= note: `std::sync::MutexGuard<'_, usize>` is defined in another crate
|
||||
help: `+=` can be used on `usize` if you dereference the left-hand side
|
||||
|
|
||||
LL | *x.lock().unwrap() += 1;
|
||||
@@ -51,10 +51,10 @@ LL | y += 1;
|
||||
| |
|
||||
| cannot use `+=` on type `std::sync::MutexGuard<'_, usize>`
|
||||
|
|
||||
note: the foreign item type `std::sync::MutexGuard<'_, usize>` doesn't implement `AddAssign<{integer}>`
|
||||
note: `std::sync::MutexGuard<'_, usize>` does not implement `AddAssign<{integer}>`
|
||||
--> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL
|
||||
|
|
||||
= note: not implement `AddAssign<{integer}>`
|
||||
= note: `std::sync::MutexGuard<'_, usize>` is defined in another crate
|
||||
help: `+=` can be used on `usize` if you dereference the left-hand side
|
||||
|
|
||||
LL | *y += 1;
|
||||
|
||||
@@ -4,10 +4,10 @@ error[E0600]: cannot apply unary operator `-` to type `String`
|
||||
LL | -"foo".to_string();
|
||||
| ^^^^^^^^^^^^^^^^^^ cannot apply unary operator `-`
|
||||
|
|
||||
note: the foreign item type `String` doesn't implement `Neg`
|
||||
note: `String` does not implement `Neg`
|
||||
--> $SRC_DIR/alloc/src/string.rs:LL:COL
|
||||
|
|
||||
= note: not implement `Neg`
|
||||
= note: `String` is defined in another crate
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
||||
Reference in New Issue
Block a user