Skip to content

Commit 2fb3e28

Browse files
committed
Merge main
2 parents 90d9508 + 5513c2b commit 2fb3e28

File tree

13 files changed

+119
-13
lines changed

13 files changed

+119
-13
lines changed

crates/flux-desugar/src/desugar.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ impl<'a, 'genv, 'tcx: 'genv> RustItemCtxt<'a, 'genv, 'tcx> {
481481
fn_sig: Option<&surface::FnSig>,
482482
) -> Result<(fhir::Generics<'genv>, fhir::FnSig<'genv>)> {
483483
let mut header = self.lift_fn_header();
484-
let (generics, decl) = if let Some(fn_sig) = fn_sig {
484+
let (generics, decl, expr) = if let Some(fn_sig) = fn_sig {
485485
self.fn_sig_scope = Some(fn_sig.node_id);
486486

487487
let mut requires = vec![];
@@ -510,18 +510,20 @@ impl<'a, 'genv, 'tcx: 'genv> RustItemCtxt<'a, 'genv, 'tcx> {
510510
span: fn_sig.span,
511511
lifted: false,
512512
};
513+
513514
// Fix up the span in asyncness
514515
if let surface::Async::Yes { span, .. } = fn_sig.asyncness {
515516
header.asyncness = hir::IsAsync::Async(span);
516517
}
517-
(generics, decl)
518+
let expr = fn_sig.no_panic.as_ref().map(|e| self.desugar_expr(e));
519+
(generics, decl, expr)
518520
} else {
519-
(self.lift_generics(), self.lift_fn_decl())
521+
(self.lift_generics(), self.lift_fn_decl(), None)
520522
};
521523
if config::dump_fhir() {
522524
dbg::dump_item_info(self.genv.tcx(), self.owner.local_id(), "fhir", decl).unwrap();
523525
}
524-
Ok((generics, fhir::FnSig { header, decl: self.genv.alloc(decl) }))
526+
Ok((generics, fhir::FnSig { header, decl: self.genv.alloc(decl), no_panic_if: expr }))
525527
}
526528

527529
fn desugar_fn_sig_refine_params(

crates/flux-desugar/src/desugar/lift.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ impl<'genv> RustItemCtxt<'_, 'genv, '_> {
542542

543543
fn lift_fn_sig(&mut self, fn_sig: hir::FnSig) -> fhir::FnSig<'genv> {
544544
let decl = self.lift_fn_decl_inner(fn_sig.span, fn_sig.decl);
545-
fhir::FnSig { header: fn_sig.header, decl: self.genv.alloc(decl) }
545+
fhir::FnSig { header: fn_sig.header, decl: self.genv.alloc(decl), no_panic_if: None }
546546
}
547547

548548
pub(crate) fn lift_foreign_item(

crates/flux-driver/src/collector/mod.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,9 @@ impl<'a, 'tcx> SpecCollector<'a, 'tcx> {
524524
("invariant", hir::AttrArgs::Delimited(dargs)) => {
525525
self.parse(dargs, ParseSess::parse_expr, FluxAttrKind::Invariant)?
526526
}
527+
("no_panic_if", hir::AttrArgs::Delimited(dargs)) => {
528+
self.parse(dargs, ParseSess::parse_expr, FluxAttrKind::NoPanicIf)?
529+
}
527530
("constant", hir::AttrArgs::Delimited(dargs)) => {
528531
self.parse(dargs, ParseSess::parse_constant_info, FluxAttrKind::Constant)?
529532
}
@@ -587,6 +590,16 @@ impl<'a, 'tcx> SpecCollector<'a, 'tcx> {
587590

588591
fn report_dups(&mut self, attrs: &FluxAttrs) -> Result {
589592
let mut err = None;
593+
594+
// look for a NoPanic and a NoPanicIf
595+
let has_no_panic_if = attrs.has_no_panic_if();
596+
if has_no_panic_if && let Some(no_panic_attr_span) = attrs.has_no_panic() {
597+
err.collect(self.errors.emit(errors::DuplicatedAttr {
598+
span: no_panic_attr_span,
599+
name: "NoPanic and NoPanicIf",
600+
}));
601+
}
602+
590603
for (name, dups) in attrs.dups() {
591604
for attr in dups {
592605
if attr.allow_dups() {
@@ -671,6 +684,7 @@ enum FluxAttrKind {
671684
ShouldFail,
672685
ExternSpec,
673686
NoPanic,
687+
NoPanicIf(surface::Expr),
674688
/// See `detachXX.rs`
675689
DetachedSpecs(surface::DetachedSpecs),
676690
}
@@ -741,7 +755,13 @@ impl FluxAttrs {
741755
}
742756

743757
fn fn_sig(&mut self) -> Option<surface::FnSig> {
744-
read_attr!(self, FnSig)
758+
let mut fn_sig = read_attr!(self, FnSig);
759+
// FIXME(nilehmann) the `no_panic_if` annotation should work even if there's no `flux::spec`
760+
// annotation or we should at least show an error.
761+
if let Some(fn_sig) = &mut fn_sig {
762+
fn_sig.no_panic = read_attr!(self, NoPanicIf);
763+
}
764+
fn_sig
745765
}
746766

747767
fn ty_alias(&mut self) -> Option<Box<surface::TyAlias>> {
@@ -756,6 +776,17 @@ impl FluxAttrs {
756776
read_attr!(self, Generics)
757777
}
758778

779+
fn has_no_panic(&self) -> Option<Span> {
780+
self.map
781+
.get(attr_name!(NoPanic))
782+
.and_then(|attrs| attrs.first())
783+
.map(|attr| attr.span)
784+
}
785+
786+
fn has_no_panic_if(&self) -> bool {
787+
read_flag!(self, NoPanicIf)
788+
}
789+
759790
fn trait_assoc_refts(&mut self) -> Vec<surface::TraitAssocReft> {
760791
read_attrs!(self, TraitAssocReft)
761792
.into_iter()
@@ -821,7 +852,8 @@ impl FluxAttrs {
821852
| FluxAttrKind::Variant(_)
822853
| FluxAttrKind::Invariant(_)
823854
| FluxAttrKind::ExternSpec
824-
| FluxAttrKind::DetachedSpecs(_) => continue,
855+
| FluxAttrKind::DetachedSpecs(_)
856+
| FluxAttrKind::NoPanicIf(_) => continue,
825857
};
826858
attrs.push(attr);
827859
}
@@ -856,6 +888,7 @@ impl FluxAttrKind {
856888
FluxAttrKind::ExternSpec => attr_name!(ExternSpec),
857889
FluxAttrKind::DetachedSpecs(_) => attr_name!(DetachedSpecs),
858890
FluxAttrKind::NoPanic => attr_name!(NoPanic),
891+
FluxAttrKind::NoPanicIf(_) => attr_name!(NoPanicIf),
859892
}
860893
}
861894
}

crates/flux-fhir-analysis/src/conv/mod.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,12 @@ impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
671671
env.push_layer(Layer::list(self.results(), late_bound_regions.len() as u32, &[]));
672672

673673
let body_id = self.tcx().hir_node_by_def_id(fn_id.local_id()).body_id();
674-
let no_panic = self.genv().no_panic(fn_id);
674+
675+
let no_panic = if let Some(e) = fn_sig.no_panic_if {
676+
self.conv_expr(&mut env, &e)?
677+
} else {
678+
if self.genv().no_panic(fn_id) { Expr::tt() } else { Expr::ff() }
679+
};
675680

676681
let fn_sig =
677682
self.conv_fn_decl(&mut env, header.safety(), header.abi, decl, body_id, no_panic)?;
@@ -986,7 +991,7 @@ impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
986991
abi: rustc_abi::ExternAbi,
987992
decl: &fhir::FnDecl,
988993
body_id: Option<BodyId>,
989-
no_panic: bool,
994+
no_panic: Expr,
990995
) -> QueryResult<rty::FnSig> {
991996
let mut requires = vec![];
992997
for req in decl.requires {
@@ -1015,7 +1020,7 @@ impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
10151020
requires.into(),
10161021
inputs.into(),
10171022
output,
1018-
if no_panic { Expr::tt() } else { Expr::ff() },
1023+
no_panic,
10191024
decl.lifted,
10201025
))
10211026
}
@@ -1260,7 +1265,7 @@ impl<'genv, 'tcx: 'genv, P: ConvPhase<'genv, 'tcx>> ConvCtxt<P> {
12601265
bare_fn.abi,
12611266
bare_fn.decl,
12621267
None,
1263-
false,
1268+
Expr::ff(),
12641269
)?;
12651270
let vars = bare_fn
12661271
.generic_params

crates/flux-middle/src/fhir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ pub struct Requires<'fhir> {
512512
pub struct FnSig<'fhir> {
513513
pub header: FnHeader,
514514
pub decl: &'fhir FnDecl<'fhir>,
515+
pub no_panic_if: Option<Expr<'fhir>>,
515516
}
516517

517518
#[derive(Clone, Copy)]

crates/flux-refineck/src/checker.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,10 @@ fn check_fn_subtyping(
312312
for requires in super_sig.requires() {
313313
infcx.assume_pred(requires);
314314
}
315+
infcx.check_pred(
316+
Expr::implies(super_sig.no_panic(), sub_sig.no_panic()),
317+
ConstrReason::Subtype(SubtypeReason::Input),
318+
);
315319
for (actual, formal) in iter::zip(actuals, sub_sig.inputs()) {
316320
let reason = ConstrReason::Subtype(SubtypeReason::Input);
317321
infcx.subtyping_with_env(&mut env, &actual, formal, reason)?;

crates/flux-syntax/src/parser/mod.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ enum SyntaxAttr {
5353
Hide,
5454
/// a `#[opaque]` attribute
5555
Opaque,
56+
/// A `#[no_panic_if(...)]` attribute
57+
NoPanicIf(Expr),
5658
}
5759

5860
#[derive(Default)]
@@ -92,6 +94,14 @@ impl ParsedAttrs {
9294
}
9395
}
9496

97+
fn no_panic_if(&mut self) -> Option<Expr> {
98+
let pos = self
99+
.syntax
100+
.iter()
101+
.position(|x| matches!(x, SyntaxAttr::NoPanicIf(_)))?;
102+
if let SyntaxAttr::NoPanicIf(expr) = self.syntax.remove(pos) { Some(expr) } else { None }
103+
}
104+
95105
fn invariant(&mut self) -> Option<Expr> {
96106
let pos = self
97107
.syntax
@@ -278,9 +288,10 @@ fn ident_path(cx: &mut ParseCtxt, ident: Ident) -> ExprPath {
278288

279289
fn parse_detached_fn_sig(
280290
cx: &mut ParseCtxt,
281-
attrs: ParsedAttrs,
291+
mut attrs: ParsedAttrs,
282292
) -> ParseResult<DetachedItem<FnSig>> {
283-
let fn_sig = parse_fn_sig(cx, token::Semi)?;
293+
let mut fn_sig = parse_fn_sig(cx, token::Semi)?;
294+
fn_sig.no_panic = attrs.no_panic_if();
284295
let span = fn_sig.span;
285296
let ident = fn_sig
286297
.ident
@@ -411,6 +422,10 @@ fn parse_attr(cx: &mut ParseCtxt, attrs: &mut ParsedAttrs) -> ParseResult {
411422
attrs
412423
.syntax
413424
.push(SyntaxAttr::Invariant(delimited(cx, Parenthesis, |cx| parse_expr(cx, true))?));
425+
} else if lookahead.advance_if(sym::no_panic_if) {
426+
attrs
427+
.syntax
428+
.push(SyntaxAttr::NoPanicIf(parse_expr(cx, true)?));
414429
} else {
415430
return Err(lookahead.into_error());
416431
};
@@ -768,6 +783,7 @@ pub(crate) fn parse_fn_sig<T: PeekExpected>(cx: &mut ParseCtxt, end: T) -> Parse
768783
output: FnOutput { returns, ensures, node_id: cx.next_node_id() },
769784
node_id: cx.next_node_id(),
770785
span: cx.mk_span(lo, hi),
786+
no_panic: None, // We attach the `no_panic` expr later
771787
})
772788
}
773789

crates/flux-syntax/src/surface.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ pub struct FnSig {
354354
/// source span
355355
pub span: Span,
356356
pub node_id: NodeId,
357+
pub no_panic: Option<Expr>,
357358
}
358359

359360
#[derive(Debug)]

crates/flux-syntax/src/surface/visit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,9 @@ pub fn walk_fn_sig<V: Visitor>(vis: &mut V, fn_sig: &FnSig) {
414414
vis.visit_expr(&requires.pred);
415415
}
416416
walk_list!(vis, visit_fn_input, &fn_sig.inputs);
417+
if let Some(no_panic_expr) = &fn_sig.no_panic {
418+
vis.visit_expr(no_panic_expr);
419+
}
417420
vis.visit_fn_output(&fn_sig.output);
418421
}
419422

crates/flux-syntax/src/symbols.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ symbols! {
2525
Set,
2626
int,
2727
no_panic,
28+
no_panic_if,
2829
ptr_size,
2930
real,
3031
}

0 commit comments

Comments
 (0)