Skip to content

Commit

Permalink
Make consts local
Browse files Browse the repository at this point in the history
  • Loading branch information
JustusAdam committed Jul 22, 2024
1 parent 0b796a0 commit 09750d5
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 83 deletions.
90 changes: 64 additions & 26 deletions crates/paralegal-flow/src/ann/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
use crate::{
ann::{Annotation, MarkerAnnotation},
args::{Args, MarkerControl},
consts,
discover::AttrMatchT,
sym_vec,
utils::{
resolve::expect_resolve_string_to_def_id, AsFnAndArgs, InstanceExt, IntoDefId, IntoHirId,
resolve::expect_resolve_string_to_def_id, AsFnAndArgs, InstanceExt, IntoDefId,
MetaItemMatch, TyCtxtExt, TyExt,
},
Either, HashMap, HashSet,
Expand All @@ -25,6 +26,7 @@ use flowistry_pdg_construction::{
utils::{try_monomorphize, try_resolve_function},
};
use paralegal_spdg::Identifier;
use rustc_span::Symbol;
use rustc_utils::cache::Cache;

use rustc_ast::Attribute;
Expand All @@ -37,8 +39,40 @@ use rustc_middle::{

use std::rc::Rc;

use super::parse::Symbols;

type ExternalMarkers = HashMap<DefId, Vec<MarkerAnnotation>>;

/// These are pseudo-constants that are used to match annotations. In theory
/// they never change but they use [`Symbol`] inside, which is only valid so
/// long as the rustc `SESSION_GLOBALS` are live so we need to calculate them
/// afresh in `new`.
struct Markers {
/// This will match the annotation `#[paralegal_flow::label(...)]` when using
/// [`MetaItemMatch::match_extract`](crate::utils::MetaItemMatch::match_extract)
label_marker: AttrMatchT,
/// This will match the annotation `#[paralegal_flow::marker(...)]` when using
/// [`MetaItemMatch::match_extract`](crate::utils::MetaItemMatch::match_extract)
marker_marker: AttrMatchT,
/// This will match the annotation `#[paralegal_flow::output_types(...)]` when using
/// [`MetaItemMatch::match_extract`](crate::utils::MetaItemMatch::match_extract)
otype_marker: AttrMatchT,
/// This will match the annotation `#[paralegal_flow::exception(...)]` when using
/// [`MetaItemMatch::match_extract`](crate::utils::MetaItemMatch::match_extract)
exception_marker: AttrMatchT,
}

impl Default for Markers {
fn default() -> Self {
Markers {
label_marker: sym_vec!["paralegal_flow", "label"],
marker_marker: sym_vec!["paralegal_flow", "marker"],
otype_marker: sym_vec!["paralegal_flow", "output_types"],
exception_marker: sym_vec!["paralegal_flow", "exception"],
}
}
}

/// The marker context is a database which can be queried as to whether
/// functions or types carry markers, whether markers are reachable in bodies,
/// etc.
Expand Down Expand Up @@ -466,6 +500,8 @@ pub struct MarkerDatabase<'tcx> {
/// Configuration options
_config: &'static MarkerControl,
type_markers: Cache<ty::Ty<'tcx>, Box<TypeMarkers>>,
markers: Markers,
symbols: Symbols,
}

impl<'tcx> MarkerDatabase<'tcx> {
Expand All @@ -478,16 +514,16 @@ impl<'tcx> MarkerDatabase<'tcx> {
reachable_markers: Default::default(),
_config: args.marker_control(),
type_markers: Default::default(),
markers: Markers::default(),
symbols: Default::default(),
}
}

/// Retrieve and parse the local annotations for this item.
pub fn retrieve_local_annotations_for(&mut self, def_id: LocalDefId) {
let tcx = self.tcx;
let hir = tcx.hir();
let id = def_id.force_into_hir_id(tcx);
for a in hir.attrs(id) {
match try_parse_annotation(tcx, a) {
for a in tcx.get_attrs_unchecked(def_id.to_def_id()) {
match self.try_parse_annotation(a) {
Ok(anns) => {
let mut anns = anns.peekable();
if anns.peek().is_some() {
Expand All @@ -503,27 +539,29 @@ impl<'tcx> MarkerDatabase<'tcx> {
}
}
}
}

fn try_parse_annotation(
tcx: TyCtxt,
a: &Attribute,
) -> Result<impl Iterator<Item = Annotation>, String> {
use crate::ann::parse::{ann_match_fn, match_exception, otype_ann_match};
let one = |a| Either::Left(Some(a));
let ann = if let Some(i) = a.match_get_ref(&consts::MARKER_MARKER) {
one(Annotation::Marker(ann_match_fn(i)?))
} else if let Some(i) = a.match_get_ref(&consts::LABEL_MARKER) {
warn!("The `paralegal_flow::label` annotation is deprecated, use `paralegal_flow::marker` instead");
one(Annotation::Marker(ann_match_fn(i)?))
} else if let Some(i) = a.match_get_ref(&consts::OTYPE_MARKER) {
Either::Right(otype_ann_match(i, tcx)?.into_iter().map(Annotation::OType))
} else if let Some(i) = a.match_get_ref(&consts::EXCEPTION_MARKER) {
one(Annotation::Exception(match_exception(i)?))
} else {
Either::Left(None)
};
Ok(ann.into_iter())
fn try_parse_annotation(
&self,
a: &Attribute,
) -> Result<impl Iterator<Item = Annotation>, String> {
let consts = &self.markers;
let tcx = self.tcx;
use crate::ann::parse::{ann_match_fn, match_exception, otype_ann_match};
let one = |a| Either::Left(Some(a));
let ann = if let Some(i) = a.match_get_ref(&consts.marker_marker) {
one(Annotation::Marker(ann_match_fn(&self.symbols, i)?))
} else if let Some(i) = a.match_get_ref(&consts.label_marker) {
warn!("The `paralegal_flow::label` annotation is deprecated, use `paralegal_flow::marker` instead");
one(Annotation::Marker(ann_match_fn(&self.symbols, i)?))
} else if let Some(i) = a.match_get_ref(&consts.otype_marker) {
Either::Right(otype_ann_match(i, tcx)?.into_iter().map(Annotation::OType))
} else if let Some(i) = a.match_get_ref(&consts.exception_marker) {
one(Annotation::Exception(match_exception(&self.symbols, i)?))
} else {
Either::Left(None)
};
Ok(ann.into_iter())
}
}

type RawExternalMarkers = HashMap<String, Vec<crate::ann::MarkerAnnotation>>;
Expand Down
45 changes: 37 additions & 8 deletions crates/paralegal-flow/src/ann/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use super::{
ExceptionAnnotation, MarkerAnnotation, MarkerRefinement, MarkerRefinementKind, VerificationHash,
};
use crate::{
consts, utils,
utils,
utils::{write_sep, Print, TinyBitSet},
Symbol,
};
Expand All @@ -28,6 +28,28 @@ pub extern crate nom;

use nom::{error::Error, Parser};

pub struct Symbols {
/// The symbol `arguments` which we use for refinement in a `#[paralegal_flow::marker(...)]`
/// annotation.
arg_sym: Symbol,
/// The symbol `return` which we use for refinement in a `#[paralegal_flow::marker(...)]`
/// annotation.
return_sym: Symbol,
/// The symbol `verification_hash` which we use for refinement in a
/// `#[paralegal_flow::exception(...)]` annotation.
verification_hash_sym: Symbol,
}

impl Default for Symbols {
fn default() -> Self {
Self {
arg_sym: Symbol::intern("arguments"),
return_sym: Symbol::intern("return"),
verification_hash_sym: Symbol::intern("verification_hash"),
}
}
}

/// Just a newtype-wrapper for `CursorRef` so we can implement traits on it
/// (specifically [`nom::InputLength`]).
///
Expand Down Expand Up @@ -248,14 +270,17 @@ pub(crate) fn otype_ann_match(ann: &ast::AttrArgs, tcx: TyCtxt) -> Result<Vec<De
}

/// Parser for an [`ExceptionAnnotation`]
pub(crate) fn match_exception(ann: &rustc_ast::AttrArgs) -> Result<ExceptionAnnotation, String> {
pub(crate) fn match_exception(
symbols: &Symbols,
ann: &rustc_ast::AttrArgs,
) -> Result<ExceptionAnnotation, String> {
use rustc_ast::*;
match ann {
ast::AttrArgs::Delimited(dargs) => {
let p = |i| {
let (i, verification_hash) = nom::combinator::opt(nom::sequence::preceded(
nom::sequence::tuple((
assert_identifier(*consts::VERIFICATION_HASH_SYM),
assert_identifier(symbols.verification_hash_sym),
assert_token(TokenKind::Eq),
)),
lit(token::LitKind::Str, |s| {
Expand All @@ -278,21 +303,21 @@ pub(crate) fn match_exception(ann: &rustc_ast::AttrArgs) -> Result<ExceptionAnno
/// Is not guaranteed to consume the entire input if does not match. You may
/// want to call [`nom::combinator::eof`] afterwards to guarantee all input has
/// been consumed.
fn refinements_parser(i: I) -> R<MarkerRefinement> {
fn refinements_parser<'a>(symbols: &Symbols, i: I<'a>) -> R<'a, MarkerRefinement> {
nom::combinator::map_res(
// nom::multi::separated_list0(
// assert_token(TokenKind::Comma),
nom::branch::alt((
nom::sequence::preceded(
nom::sequence::tuple((
assert_identifier(*consts::ARG_SYM),
assert_identifier(symbols.arg_sym),
assert_token(TokenKind::Eq),
)),
nom::combinator::map(tiny_bitset, MarkerRefinementKind::Argument),
),
nom::combinator::value(
MarkerRefinementKind::Return,
assert_identifier(*consts::RETURN_SYM),
assert_identifier(symbols.return_sym),
),
)),
//),
Expand All @@ -305,15 +330,19 @@ fn refinements_parser(i: I) -> R<MarkerRefinement> {
}

/// Parser for a [`LabelAnnotation`]
pub(crate) fn ann_match_fn(ann: &rustc_ast::AttrArgs) -> Result<MarkerAnnotation, String> {
pub(crate) fn ann_match_fn(
symbols: &Symbols,
ann: &rustc_ast::AttrArgs,
) -> Result<MarkerAnnotation, String> {
use rustc_ast::*;
use token::*;
match ann {
ast::AttrArgs::Delimited(dargs) => {
let p = |i| {
let (i, label) = identifier(i)?;
let (i, cont) = nom::combinator::opt(assert_token(TokenKind::Comma))(i)?;
let (i, refinement) = nom::combinator::cond(cont.is_some(), refinements_parser)(i)?;
let (i, refinement) =
nom::combinator::cond(cont.is_some(), |c| refinements_parser(symbols, c))(i)?;
let (_, _) = nom::combinator::eof(i)?;
Ok(MarkerAnnotation {
marker: Identifier::new(label),
Expand Down
36 changes: 0 additions & 36 deletions crates/paralegal-flow/src/consts.rs

This file was deleted.

10 changes: 8 additions & 2 deletions crates/paralegal-flow/src/discover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
//!
//! Essentially this discovers all local `paralegal_flow::*` annotations.

use crate::{ana::SPDGGenerator, ann::db::MarkerDatabase, consts, desc::*, stats::Stats, utils::*};
use crate::{
ana::SPDGGenerator, ann::db::MarkerDatabase, desc::*, stats::Stats, sym_vec, utils::*,
};

use rustc_hir::{
def_id::LocalDefId,
Expand Down Expand Up @@ -37,6 +39,9 @@ pub struct CollectingVisitor<'tcx> {
stats: Stats,

pub marker_ctx: MarkerDatabase<'tcx>,
/// This will match the annotation `#[paralegal_flow::analyze]` when using
/// [`MetaItemMatch::match_extract`](crate::utils::MetaItemMatch::match_extract)
analyze_marker: AttrMatchT,
}

/// A function we will be targeting to analyze with
Expand Down Expand Up @@ -77,6 +82,7 @@ impl<'tcx> CollectingVisitor<'tcx> {
functions_to_analyze,
marker_ctx: MarkerDatabase::init(tcx, opts),
stats,
analyze_marker: sym_vec!["paralegal_flow", "analyze"],
}
}

Expand All @@ -102,7 +108,7 @@ impl<'tcx> CollectingVisitor<'tcx> {
.hir()
.attrs(self.tcx.local_def_id_to_hir_id(ident))
.iter()
.any(|a| a.matches_path(&consts::ANALYZE_MARKER))
.any(|a| a.matches_path(&self.analyze_marker))
}
}

Expand Down
1 change: 0 additions & 1 deletion crates/paralegal-flow/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ mod stats;
//mod sah;
#[macro_use]
pub mod utils;
pub mod consts;
#[cfg(feature = "test")]
pub mod test_utils;

Expand Down
16 changes: 6 additions & 10 deletions crates/paralegal-flow/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ extern crate rustc_middle;
extern crate rustc_span;

use hir::def_id::DefId;
use rustc_utils::mir::borrowck_facts;

use crate::{
desc::{Identifier, ProgramDescription},
Expand Down Expand Up @@ -230,6 +229,11 @@ impl InlineTestBuilder {

args.setup_logging();

println!(
"Starting test from thread {:?}",
std::thread::current().id()
);

rustc_utils::test_utils::CompileBuilder::new(&self.input)
.with_args(
[
Expand All @@ -242,20 +246,12 @@ impl InlineTestBuilder {
.map(ToOwned::to_owned),
)
.compile(move |result| {
println!(
"MIR cache before test has {} entries",
borrowck_facts::MIR_BODIES.with(|b| b.len())
);
let tcx = result.tcx;
let memo = crate::Callbacks::new(Box::leak(Box::new(args)));
let pdg = memo.run(tcx).unwrap();
let graph = PreFrg::from_description(pdg);
let cref = graph.ctrl(&self.ctrl_name);
check(cref);
println!(
"MIR cache after test has {} entries",
borrowck_facts::MIR_BODIES.with(|b| b.len())
);
});
}
}
Expand Down Expand Up @@ -354,7 +350,7 @@ impl PreFrg {
use_rustc(|| {
let desc = ProgramDescription::canonical_read(format!(
"{dir}/{}",
crate::consts::FLOW_GRAPH_OUT_NAME
paralegal_spdg::FLOW_GRAPH_OUT_NAME
))
.unwrap();
Self::from_description(desc)
Expand Down

0 comments on commit 09750d5

Please sign in to comment.