Skip to content

Rollup of 12 pull requests #136849

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 26 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
bb4c9d2
Improved named region errors
compiler-errors Feb 4, 2025
82b32ba
stabilize `NonZero::count_ones`
WaffleLapkin Feb 6, 2025
ac31e95
library: doc: core::alloc::Allocator: trivial typo fix
safinaskar Feb 7, 2025
53f9852
rustc_target: Add the fp16 target feature for AArch32
mrkajetanp Feb 7, 2025
8ea20c8
Improve examples for file locking
benschulz Feb 7, 2025
5f29273
rustc_codegen_llvm: Mark items as pub(crate) outside of the llvm module
dpaoliello Feb 8, 2025
bce3d64
fix i686-unknown-hurd-gnu x87 footnote
RalfJung Feb 10, 2025
d32cd29
Fix platform support table for i686-unknown-uefi
ehuss Feb 10, 2025
28164e3
Stop using span hack for contracts feature gating
compiler-errors Feb 10, 2025
f78099e
Fix imports, remove attrs for unused_*
compiler-errors Feb 10, 2025
4f18560
Don't ICE when failing to lower contracts for associated impl items
compiler-errors Feb 10, 2025
4898753
add test for const type_id misoptimization
Feb 11, 2025
c1da4f1
fix ensure_monomorphic_enough
Feb 10, 2025
593c88f
Fix long lines which rustfmt fails to format
thaliaarchi Feb 5, 2025
3f02105
Rollup merge of #136559 - compiler-errors:resolve-regions-for-type-te…
jhpratt Feb 11, 2025
0cb377c
Rollup merge of #136606 - thaliaarchi:format-long-lines, r=ibraheemdev
jhpratt Feb 11, 2025
7a6592d
Rollup merge of #136663 - WaffleLapkin:count-non-zero-ones, r=cuviper
jhpratt Feb 11, 2025
5fb4f2e
Rollup merge of #136672 - safinaskar:alloc-2025-02-07-09-10, r=cuviper
jhpratt Feb 11, 2025
2715d4f
Rollup merge of #136704 - benschulz:patch-1, r=ibraheemdev
jhpratt Feb 11, 2025
1c5a78f
Rollup merge of #136721 - dpaoliello:cleanllvm2, r=Zalathar
jhpratt Feb 11, 2025
3ea8208
Rollup merge of #136813 - mrkajetanp:aarch32-fp16-target-feature, r=d…
jhpratt Feb 11, 2025
9c5831d
Rollup merge of #136830 - RalfJung:hurd-x87-footnote, r=Noratrieb
jhpratt Feb 11, 2025
0132aec
Rollup merge of #136832 - ehuss:fix-platform-table, r=compiler-errors
jhpratt Feb 11, 2025
180f749
Rollup merge of #136835 - compiler-errors:contracts-span-hack, r=celi…
jhpratt Feb 11, 2025
79ee905
Rollup merge of #136837 - compiler-errors:contracts-body-lowering, r=…
jhpratt Feb 11, 2025
57be4a3
Rollup merge of #136839 - lukas-code:actually-monomorphic-enough, r=c…
jhpratt Feb 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,16 +379,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
})
}

/// Create an `ExprKind::Ret` that is preceded by a call to check contract ensures clause.
/// Create an `ExprKind::Ret` that is optionally wrapped by a call to check
/// a contract ensures clause, if it exists.
fn checked_return(&mut self, opt_expr: Option<&'hir hir::Expr<'hir>>) -> hir::ExprKind<'hir> {
let checked_ret = if let Some(Some((span, fresh_ident))) =
self.contract.as_ref().map(|c| c.ensures.as_ref().map(|e| (e.expr.span, e.fresh_ident)))
{
let expr = opt_expr.unwrap_or_else(|| self.expr_unit(span));
Some(self.inject_ensures_check(expr, span, fresh_ident.0, fresh_ident.2))
} else {
opt_expr
};
let checked_ret =
if let Some((check_span, check_ident, check_hir_id)) = self.contract_ensures {
let expr = opt_expr.unwrap_or_else(|| self.expr_unit(check_span));
Some(self.inject_ensures_check(expr, check_span, check_ident, check_hir_id))
} else {
opt_expr
};
hir::ExprKind::Ret(checked_ret)
}

Expand Down Expand Up @@ -1090,7 +1090,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
} else {
None
};
let body_id = this.lower_fn_body(decl, |this| {
// FIXME(contracts): Support contracts on closures?
let body_id = this.lower_fn_body(decl, None, |this| {
this.coroutine_kind = coroutine_kind;
let e = this.lower_expr_mut(body);
coroutine_kind = this.coroutine_kind;
Expand Down
166 changes: 80 additions & 86 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,36 +211,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
..
}) => {
self.with_new_scopes(*fn_sig_span, |this| {
assert!(this.contract.is_none());
if let Some(contract) = contract {
let requires = contract.requires.clone();
let ensures = contract.ensures.clone();
let ensures = ensures.map(|ens| {
// FIXME: this needs to be a fresh (or illegal) identifier to prevent
// accidental capture of a parameter or global variable.
let checker_ident: Ident =
Ident::from_str_and_span("__ensures_checker", ens.span);
let (checker_pat, checker_hir_id) = this.pat_ident_binding_mode_mut(
ens.span,
checker_ident,
hir::BindingMode::NONE,
);

crate::FnContractLoweringEnsures {
expr: ens,
fresh_ident: (checker_ident, checker_pat, checker_hir_id),
}
});

// Note: `with_new_scopes` will reinstall the outer
// item's contract (if any) after its callback finishes.
this.contract.replace(crate::FnContractLoweringInfo {
span,
requires,
ensures,
});
}

// Note: we don't need to change the return type from `T` to
// `impl Future<Output = T>` here because lower_body
// only cares about the input argument patterns in the function
Expand All @@ -254,6 +224,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
coroutine_kind,
body.as_deref(),
attrs,
contract.as_deref(),
);

let itctx = ImplTraitContext::Universal;
Expand Down Expand Up @@ -803,6 +774,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
(generics, kind, expr.is_some())
}
AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => {
// FIXME(contracts): Deny contract here since it won't apply to
// any impl method or callees.
let names = self.lower_fn_params_to_names(&sig.decl);
let (generics, sig) = self.lower_method_sig(
generics,
Expand All @@ -814,7 +787,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
}
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), .. }) => {
AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), contract, .. }) => {
let body_id = self.lower_maybe_coroutine_body(
sig.span,
i.span,
Expand All @@ -823,6 +796,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig.header.coroutine_kind,
Some(body),
attrs,
contract.as_deref(),
);
let (generics, sig) = self.lower_method_sig(
generics,
Expand Down Expand Up @@ -931,7 +905,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ImplItemKind::Const(ty, body)
},
),
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
AssocItemKind::Fn(box Fn { sig, generics, body, contract, .. }) => {
let body_id = self.lower_maybe_coroutine_body(
sig.span,
i.span,
Expand All @@ -940,6 +914,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
sig.header.coroutine_kind,
body.as_deref(),
attrs,
contract.as_deref(),
);
let (generics, sig) = self.lower_method_sig(
generics,
Expand Down Expand Up @@ -1088,72 +1063,89 @@ impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn lower_fn_body(
&mut self,
decl: &FnDecl,
contract: Option<&FnContract>,
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
) -> hir::BodyId {
self.lower_body(|this| {
let params =
this.arena.alloc_from_iter(decl.inputs.iter().map(|x| this.lower_param(x)));
let result = body(this);

let opt_contract = this.contract.take();

// Optionally lower the fn contract, which turns:
//
// { body }
// ==>
// { contract_requires(PRECOND); { body } }
let Some(contract) = opt_contract else { return (params, result) };
let result_ref = this.arena.alloc(result);
let lit_unit = |this: &mut LoweringContext<'_, 'hir>| {
this.expr(contract.span, hir::ExprKind::Tup(&[]))
};

let precond: hir::Stmt<'hir> = if let Some(req) = contract.requires {
let lowered_req = this.lower_expr_mut(&req);
let precond = this.expr_call_lang_item_fn_mut(
req.span,
hir::LangItem::ContractCheckRequires,
&*arena_vec![this; lowered_req],
);
this.stmt_expr(req.span, precond)
} else {
let u = lit_unit(this);
this.stmt_expr(contract.span, u)
};

let (postcond_checker, result) = if let Some(ens) = contract.ensures {
let crate::FnContractLoweringEnsures { expr: ens, fresh_ident } = ens;
let lowered_ens: hir::Expr<'hir> = this.lower_expr_mut(&ens);
let postcond_checker = this.expr_call_lang_item_fn(
ens.span,
hir::LangItem::ContractBuildCheckEnsures,
&*arena_vec![this; lowered_ens],
);
let checker_binding_pat = fresh_ident.1;
(
this.stmt_let_pat(
//
// into:
//
// { contract_requires(PRECOND); let __postcond = |ret_val| POSTCOND; postcond({ body }) }
if let Some(contract) = contract {
let precond = if let Some(req) = &contract.requires {
// Lower the precondition check intrinsic.
let lowered_req = this.lower_expr_mut(&req);
let precond = this.expr_call_lang_item_fn_mut(
req.span,
hir::LangItem::ContractCheckRequires,
&*arena_vec![this; lowered_req],
);
Some(this.stmt_expr(req.span, precond))
} else {
None
};
let (postcond, body) = if let Some(ens) = &contract.ensures {
let ens_span = this.lower_span(ens.span);
// Set up the postcondition `let` statement.
let check_ident: Ident =
Ident::from_str_and_span("__ensures_checker", ens_span);
let (checker_pat, check_hir_id) = this.pat_ident_binding_mode_mut(
ens_span,
check_ident,
hir::BindingMode::NONE,
);
let lowered_ens = this.lower_expr_mut(&ens);
let postcond_checker = this.expr_call_lang_item_fn(
ens_span,
hir::LangItem::ContractBuildCheckEnsures,
&*arena_vec![this; lowered_ens],
);
let postcond = this.stmt_let_pat(
None,
ens.span,
ens_span,
Some(postcond_checker),
this.arena.alloc(checker_binding_pat),
this.arena.alloc(checker_pat),
hir::LocalSource::Contract,
),
this.inject_ensures_check(result_ref, ens.span, fresh_ident.0, fresh_ident.2),
)
} else {
let u = lit_unit(this);
(this.stmt_expr(contract.span, u), &*result_ref)
};
);

let block = this.block_all(
contract.span,
arena_vec![this; precond, postcond_checker],
Some(result),
);
(params, this.expr_block(block))
// Install contract_ensures so we will intercept `return` statements,
// then lower the body.
this.contract_ensures = Some((ens_span, check_ident, check_hir_id));
let body = this.arena.alloc(body(this));

// Finally, inject an ensures check on the implicit return of the body.
let body = this.inject_ensures_check(body, ens_span, check_ident, check_hir_id);
(Some(postcond), body)
} else {
let body = &*this.arena.alloc(body(this));
(None, body)
};
// Flatten the body into precond, then postcond, then wrapped body.
let wrapped_body = this.block_all(
body.span,
this.arena.alloc_from_iter([precond, postcond].into_iter().flatten()),
Some(body),
);
(params, this.expr_block(wrapped_body))
} else {
(params, body(this))
}
})
}

fn lower_fn_body_block(&mut self, decl: &FnDecl, body: &Block) -> hir::BodyId {
self.lower_fn_body(decl, |this| this.lower_block_expr(body))
fn lower_fn_body_block(
&mut self,
decl: &FnDecl,
body: &Block,
contract: Option<&FnContract>,
) -> hir::BodyId {
self.lower_fn_body(decl, contract, |this| this.lower_block_expr(body))
}

pub(super) fn lower_const_body(&mut self, span: Span, expr: Option<&Expr>) -> hir::BodyId {
Expand All @@ -1179,12 +1171,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
coroutine_kind: Option<CoroutineKind>,
body: Option<&Block>,
attrs: &'hir [hir::Attribute],
contract: Option<&FnContract>,
) -> hir::BodyId {
let Some(body) = body else {
// Functions without a body are an error, except if this is an intrinsic. For those we
// create a fake body so that the entire rest of the compiler doesn't have to deal with
// this as a special case.
return self.lower_fn_body(decl, |this| {
return self.lower_fn_body(decl, contract, |this| {
if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic) {
let span = this.lower_span(span);
let empty_block = hir::Block {
Expand All @@ -1209,8 +1202,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
};
let Some(coroutine_kind) = coroutine_kind else {
// Typical case: not a coroutine.
return self.lower_fn_body_block(decl, body);
return self.lower_fn_body_block(decl, body, contract);
};
// FIXME(contracts): Support contracts on async fn.
self.lower_body(|this| {
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
decl,
Expand Down
21 changes: 4 additions & 17 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,6 @@ mod path;

rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

#[derive(Debug, Clone)]
struct FnContractLoweringInfo<'hir> {
pub span: Span,
pub requires: Option<ast::ptr::P<ast::Expr>>,
pub ensures: Option<FnContractLoweringEnsures<'hir>>,
}

#[derive(Debug, Clone)]
struct FnContractLoweringEnsures<'hir> {
expr: ast::ptr::P<ast::Expr>,
fresh_ident: (Ident, hir::Pat<'hir>, HirId),
}

struct LoweringContext<'a, 'hir> {
tcx: TyCtxt<'hir>,
resolver: &'a mut ResolverAstLowering,
Expand All @@ -114,7 +101,7 @@ struct LoweringContext<'a, 'hir> {
/// Collect items that were created by lowering the current owner.
children: Vec<(LocalDefId, hir::MaybeOwner<'hir>)>,

contract: Option<FnContractLoweringInfo<'hir>>,
contract_ensures: Option<(Span, Ident, HirId)>,

coroutine_kind: Option<hir::CoroutineKind>,

Expand Down Expand Up @@ -164,7 +151,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
bodies: Vec::new(),
attrs: SortedMap::default(),
children: Vec::default(),
contract: None,
contract_ensures: None,
current_hir_id_owner: hir::CRATE_OWNER_ID,
item_local_id_counter: hir::ItemLocalId::ZERO,
ident_and_label_to_local_id: Default::default(),
Expand Down Expand Up @@ -851,15 +838,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let was_in_loop_condition = self.is_in_loop_condition;
self.is_in_loop_condition = false;

let old_contract = self.contract.take();
let old_contract = self.contract_ensures.take();

let catch_scope = self.catch_scope.take();
let loop_scope = self.loop_scope.take();
let ret = f(self);
self.catch_scope = catch_scope;
self.loop_scope = loop_scope;

self.contract = old_contract;
self.contract_ensures = old_contract;

self.is_in_loop_condition = was_in_loop_condition;

Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/region_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,13 +316,16 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let type_test_span = type_test.span;

if let Some(lower_bound_region) = lower_bound_region {
let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
let generic_ty = self.regioncx.name_regions(
self.infcx.tcx,
type_test.generic_kind.to_ty(self.infcx.tcx),
);
let origin = RelateParamBound(type_test_span, generic_ty, None);
self.buffer_error(self.infcx.err_ctxt().construct_generic_bound_failure(
self.body.source.def_id().expect_local(),
type_test_span,
Some(origin),
type_test.generic_kind,
self.regioncx.name_regions(self.infcx.tcx, type_test.generic_kind),
lower_bound_region,
));
} else {
Expand Down
Loading
Loading