Skip to content

Commit

Permalink
Merge pull request #76 from Unparalleled-Calvin/main
Browse files Browse the repository at this point in the history
 Feat: use annotate-snippets to display error messages
  • Loading branch information
hxuhack authored Nov 17, 2024
2 parents a32584e + a9febfb commit 8a9cbf6
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 69 deletions.
77 changes: 50 additions & 27 deletions rap/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ regex = "1.11.1"
once_cell = "1.20.1"
walkdir = "2"
cargo_metadata = "0.18"
annotate-snippets = "0.11.4"

[features]
backtraces = ["snafu/backtraces", "snafu/backtraces-impl-backtrace-crate"]
Expand Down
2 changes: 1 addition & 1 deletion rap/src/analysis/core/dataflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl<'tcx> DataFlow<'tcx> {

fn build_graph(&self, def_id: DefId) -> Graph {
let body: &Body = self.tcx.optimized_mir(def_id);
let mut graph = Graph::new(def_id, body.arg_count, body.local_decls.len());
let mut graph = Graph::new(def_id, body.span, body.arg_count, body.local_decls.len());
let basic_blocks = &body.basic_blocks;
for basic_block_data in basic_blocks.iter() {
for statement in basic_block_data.statements.iter() {
Expand Down
4 changes: 3 additions & 1 deletion rap/src/analysis/core/dataflow/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,18 @@ pub type GraphNodes = IndexVec<Local, GraphNode>;
pub type GraphEdges = IndexVec<EdgeIdx, GraphEdge>;
pub struct Graph {
pub def_id: DefId,
pub span: Span,
pub argc: usize,
pub nodes: GraphNodes, //constsis of locals in mir and newly created markers
pub edges: GraphEdges,
pub n_locals: usize,
}

impl Graph {
pub fn new(def_id: DefId, argc: usize, n_locals: usize) -> Self {
pub fn new(def_id: DefId, span: Span, argc: usize, n_locals: usize) -> Self {
Self {
def_id,
span,
argc,
nodes: GraphNodes::from_elem_n(GraphNode::new(), n_locals),
edges: GraphEdges::new(),
Expand Down
48 changes: 29 additions & 19 deletions rap/src/analysis/opt/checking/bounds_checking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ use crate::analysis::core::dataflow::graph::{
AggKind, DFSStatus, Direction, Graph, GraphEdge, GraphNode, NodeOp,
};
use crate::analysis::utils::def_path::DefPath;
use crate::rap_warn;
use crate::utils::log::underline_span_in_the_line;
use crate::utils::log::{
relative_pos_range, span_to_filename, span_to_line_number, span_to_source_code,
};
use annotate_snippets::{Level, Renderer, Snippet};

static DEFPATHS: OnceCell<DefPaths> = OnceCell::new();

Expand Down Expand Up @@ -117,21 +119,29 @@ pub fn check(graph: &Graph, tcx: &TyCtxt) {
}

fn report_bug(graph: &Graph, upperbound_node_idx: Local, index_record: &Vec<Local>) {
rap_warn!(
"Unnecessary bounds checkings detected in function {:?}.
Index is upperbounded at:
{}
Checked at:
{}
",
graph.def_id,
underline_span_in_the_line(graph.nodes[upperbound_node_idx].span),
index_record
.iter()
.map(|node_idx| {
underline_span_in_the_line(graph.nodes[*node_idx].span) // buggy, what about multiple index in the same line?
})
.collect::<Vec<String>>()
.join("\n")
);
let upperbound_span = graph.nodes[upperbound_node_idx].span;
let code_source = span_to_source_code(graph.span);
let filename = span_to_filename(upperbound_span);
let mut snippet = Snippet::source(&code_source)
.line_start(span_to_line_number(graph.span))
.origin(&filename)
.fold(true)
.annotation(
Level::Info
.span(relative_pos_range(graph.span, upperbound_span))
.label("Index is upperbounded."),
);
for node_idx in index_record {
let index_span = graph.nodes[*node_idx].span;
snippet = snippet.annotation(
Level::Error
.span(relative_pos_range(graph.span, index_span))
.label("Checked here."),
);
}
let message = Level::Warning
.title("Unnecessary bounds checkings detected")
.snippet(snippet);
let renderer = Renderer::styled();
println!("{}", renderer.render(message));
}
47 changes: 26 additions & 21 deletions rap/src/utils/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use fern::colors::{Color, ColoredLevelConfig};
use fern::{self, Dispatch};
use log::LevelFilter;
use rustc_span::source_map::get_source_map;
use rustc_span::{Pos, Span};
use rustc_span::{FileNameDisplayPreference, Pos, Span};
use std::ops::Range;

fn log_level() -> LevelFilter {
if let Ok(s) = std::env::var("RAP_LOG") {
Expand Down Expand Up @@ -86,25 +87,29 @@ pub fn rap_error_and_exit(msg: impl AsRef<str>) -> ! {
std::process::exit(1)
}

pub fn underline_span_in_the_line(span: Span) -> String {
fn compose_underline(line_span: Span, span: Span) -> String {
let line_len = (line_span.hi() - line_span.lo()).to_u32();
let line_start_pos = line_span.lo();
let lo = (span.lo() - line_start_pos).to_u32();
let hi = (span.hi() - line_start_pos).to_u32();
(0..line_len)
.map(|i| if i >= lo && i < hi { '^' } else { ' ' })
.collect()
}
#[inline]
pub fn span_to_source_code(span: Span) -> String {
get_source_map().unwrap().span_to_snippet(span).unwrap()
}

#[inline]
pub fn span_to_filename(span: Span) -> String {
get_source_map()
.unwrap()
.span_to_filename(span)
.display(FileNameDisplayPreference::Local)
.to_string()
}

#[inline]
pub fn span_to_line_number(span: Span) -> usize {
get_source_map().unwrap().lookup_char_pos(span.lo()).line
}

let source_map = get_source_map().unwrap();
let line_span = source_map.span_extend_to_line(span);
let line = source_map.span_to_snippet(line_span).unwrap();
let underline = compose_underline(line_span, span);
format!(
"{}\n{}\n{}",
source_map.span_to_diagnostic_string(span),
line,
underline
)
#[inline]
pub fn relative_pos_range(span: Span, sub_span: Span) -> Range<usize> {
let start_pos = span.lo();
let lo = (sub_span.lo() - start_pos).to_usize();
let hi = (sub_span.hi() - start_pos).to_usize();
lo..hi
}

0 comments on commit 8a9cbf6

Please sign in to comment.