Skip to content

Commit 5eb8f45

Browse files
committed
Use new -Zmaximal-hir-to-mir-coverage flag on nightly-2022-12-07
1 parent 60a2462 commit 5eb8f45

File tree

15 files changed

+147
-287
lines changed

15 files changed

+147
-287
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jobs:
4949
- uses: actions/checkout@v1
5050
- uses: actions-rs/toolchain@v1
5151
with:
52-
toolchain: nightly-2022-11-07
52+
toolchain: nightly-2022-12-07
5353
components: rust-src, rustc-dev, llvm-tools-preview
5454
target: ${{ matrix.target }}
5555
profile: minimal

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ If rustup fails, especially with an error like "could not rename downloaded file
179179
To solve the issue, go to the command line and run:
180180

181181
```
182-
rustup toolchain install nightly-2022-11-07 -c rust-src -c rustc-dev -c llvm-tools-preview
182+
rustup toolchain install nightly-2022-12-07 -c rust-src -c rustc-dev -c llvm-tools-preview
183183
```
184184

185185
Then go back to VSCode and click "Continue" to let Flowistry continue installing.

crates/flowistry/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@
3838
associated_type_defaults, // for crate::indexed::Indexed
3939
min_specialization, // for rustc_index::newtype_index
4040
type_alias_impl_trait, // for impl Trait in trait definition, eg crate::mir::utils
41-
trait_alias,
41+
trait_alias,
4242
)]
4343
#![allow(
4444
clippy::single_match,
4545
clippy::needless_lifetimes,
4646
clippy::needless_return,
4747
clippy::len_zero,
48-
clippy::len_without_is_empty,
48+
clippy::len_without_is_empty
4949
)]
5050

5151
extern crate either;

crates/flowistry/src/mir/aliases.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ use crate::{
3232
indexed::{
3333
impls::{
3434
build_location_arg_domain, LocationOrArgDomain, LocationOrArgIndex, PlaceSet,
35-
}, ToIndex,
35+
},
36+
ToIndex,
3637
},
3738
mir::utils::{self, MutabilityExt, PlaceExt},
3839
timer::elapsed,
@@ -524,7 +525,7 @@ impl<'a, 'tcx> Aliases<'a, 'tcx> {
524525

525526
/// Returns all [direct](PlaceExt::is_direct) places that are reachable from `place`
526527
/// and can be used at the provided level of [`Mutability`].
527-
///
528+
///
528529
/// For example, if `x = 0` and `y = (0, &x)`, then `reachable_values(y, Mutability::Not)`
529530
/// is `{y, y.0, y.1, x}`. With `Mutability::Mut`, then the output is `{y, y.0, y.1}` (no `x`).
530531
pub fn reachable_values(

crates/flowistry/src/mir/utils.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use either::Either;
1313
use log::{trace, warn};
1414
use rustc_data_structures::fx::{FxHashMap as HashMap, FxHashSet as HashSet};
1515
use rustc_graphviz as dot;
16-
use rustc_hir::def_id::DefId;
16+
use rustc_hir::{def_id::DefId, HirId};
1717
use rustc_infer::infer::TyCtxtInferExt;
1818
use rustc_middle::{
1919
mir::{
@@ -31,7 +31,7 @@ use rustc_span::{
3131
source_map::SourceMap, BytePos, Pos, Span, SpanData, Symbol, SyntaxContext,
3232
};
3333
use rustc_target::abi::VariantIdx;
34-
use rustc_trait_selection::infer::InferCtxtExt;
34+
use rustc_trait_selection::traits::NormalizeExt;
3535
use smallvec::SmallVec;
3636

3737
use crate::{
@@ -250,7 +250,7 @@ pub fn location_to_string(location: LocationOrArg, body: &Body<'_>) -> String {
250250
}
251251

252252
/// MIR pass to remove instructions not important for Flowistry.
253-
///
253+
///
254254
/// This pass helps reduce the number of intermediates during dataflow analysis, which
255255
/// reduces memory usage.
256256
pub struct SimplifyMir;
@@ -527,7 +527,8 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
527527
let place = tcx.erase_regions(*self);
528528
let infcx = tcx.infer_ctxt().build();
529529
let place = infcx
530-
.partially_normalize_associated_types_in(ObligationCause::dummy(), param_env, place)
530+
.at(&ObligationCause::dummy(), param_env)
531+
.normalize(place)
531532
.value;
532533

533534
let projection = place
@@ -770,7 +771,7 @@ pub trait BodyExt<'tcx> {
770771
Self: 'a;
771772

772773
/// Returns all the locations of [`TerminatorKind::Return`] instructions in a body.
773-
fn all_returns(&self) -> Self::AllReturnsIter<'_>;
774+
fn all_returns<'a>(&'a self) -> Self::AllReturnsIter<'a>;
774775

775776
type AllLocationsIter<'a>: Iterator<Item = Location>
776777
where
@@ -787,10 +788,22 @@ pub trait BodyExt<'tcx> {
787788
fn debug_info_name_map(&self) -> HashMap<Local, Symbol>;
788789

789790
fn to_string(&self, tcx: TyCtxt<'tcx>) -> Result<String>;
791+
792+
/// Returns the HirId corresponding to a MIR location.
793+
///
794+
/// You **MUST** use the `-Zmaximize-hir-to-mir-mapping` flag for this
795+
/// function to work.
796+
fn location_to_hir_id(&self, location: Location) -> HirId;
797+
798+
fn source_info_to_hir_id(&self, info: &SourceInfo) -> HirId;
790799
}
791800

801+
// https://github.com/rust-lang/rust/issues/66551#issuecomment-629815002
802+
pub trait Captures<'a> {}
803+
impl<'a, T> Captures<'a> for T {}
804+
792805
impl<'tcx> BodyExt<'tcx> for Body<'tcx> {
793-
type AllReturnsIter<'a> = impl Iterator<Item = Location> + 'a where Self: 'a ;
806+
type AllReturnsIter<'a> = impl Iterator<Item = Location> + Captures<'tcx> + 'a where Self: 'a;
794807
fn all_returns(&self) -> Self::AllReturnsIter<'_> {
795808
self
796809
.basic_blocks
@@ -804,7 +817,7 @@ impl<'tcx> BodyExt<'tcx> for Body<'tcx> {
804817
})
805818
}
806819

807-
type AllLocationsIter<'a> = impl Iterator<Item = Location> + 'a where Self: 'a;
820+
type AllLocationsIter<'a> = impl Iterator<Item = Location> + Captures<'tcx> + 'a where Self: 'a;
808821
fn all_locations(&self) -> Self::AllLocationsIter<'_> {
809822
self
810823
.basic_blocks
@@ -842,6 +855,17 @@ impl<'tcx> BodyExt<'tcx> for Body<'tcx> {
842855
write_mir_fn(tcx, self, &mut |_, _| Ok(()), &mut buffer)?;
843856
Ok(String::from_utf8(buffer)?)
844857
}
858+
859+
fn location_to_hir_id(&self, location: Location) -> HirId {
860+
let source_info = self.source_info(location);
861+
self.source_info_to_hir_id(source_info)
862+
}
863+
864+
fn source_info_to_hir_id(&self, info: &SourceInfo) -> HirId {
865+
let scope = &self.source_scopes[info.scope];
866+
let local_data = scope.local_data.as_ref().assert_crate_local();
867+
local_data.lint_root
868+
}
845869
}
846870

847871
/// Extension trait for [`Span`].
Lines changed: 50 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
use hir::LoopSource;
2-
use log::trace;
1+
use hir::{HirId, LoopSource};
32
use rustc_hir::{
43
self as hir,
54
intravisit::{self, Visitor as HirVisitor},
6-
Expr, ExprKind, MatchSource, Node, Param, Stmt,
5+
ExprKind, MatchSource, Node,
76
};
8-
use rustc_span::{BytePos, Span, SpanData};
7+
use rustc_span::{BytePos, Span};
98

109
use super::Spanner;
1110
use crate::mir::utils::SpanExt;
@@ -25,11 +24,17 @@ impl<'hir> HirVisitor<'hir> for ChildExprSpans {
2524
ExprKind::Block(..) => {
2625
intravisit::walk_expr(self, ex);
2726
}
28-
// The HIR span for a for-loop desugared to a match is *smaller*
29-
// than the span of its children. So we have to explicitly recurse
30-
// into the match arm instead of just taking the span for the match.
31-
// See `forloop_some_relevant` for where this matters.
32-
ExprKind::Match(_, arms, MatchSource::ForLoopDesugar) => {
27+
// ForLoopDesgar case:
28+
// The HIR span for a for-loop desugared to a match is *smaller*
29+
// than the span of its children. So we have to explicitly recurse
30+
// into the match arm instead of just taking the span for the match.
31+
// See `forloop_some_relevant` for where this matters.
32+
//
33+
// Normal case:
34+
// The SwitchInts for a normal match exclusively source-map to the patterns
35+
// in the arms, not the matched expression. So to make sure that `match e { .. }`
36+
// includes `e` when `match` is relevant, we exclude `e` from the child spans.
37+
ExprKind::Match(_, arms, MatchSource::ForLoopDesugar | MatchSource::Normal) => {
3338
for arm in arms {
3439
intravisit::walk_arm(self, arm);
3540
}
@@ -63,134 +68,64 @@ pub enum EnclosingHirSpans {
6368

6469
/// The spans of the node minus its children
6570
OuterOnly,
66-
71+
6772
/// No span
6873
None,
6974
}
7075

71-
#[derive(Clone, Debug)]
72-
pub struct HirSpannedNode<'hir> {
73-
pub full: SpanData,
74-
pub outer: Vec<Span>,
75-
pub node: hir::Node<'hir>,
76-
}
77-
78-
impl HirSpannedNode<'_> {
79-
pub fn get_spans(&self, span_type: EnclosingHirSpans) -> Vec<Span> {
80-
match span_type {
81-
EnclosingHirSpans::OuterOnly => self.outer.clone(),
82-
EnclosingHirSpans::Full => vec![self.full.span()],
83-
EnclosingHirSpans::None => Vec::new(),
84-
}
85-
}
86-
}
87-
88-
pub struct HirSpanCollector<'a, 'hir, 'tcx>(pub &'a mut Spanner<'hir, 'tcx>);
89-
9076
macro_rules! try_span {
9177
($self:expr, $span:expr) => {
92-
match $span.as_local($self.0.item_span) {
93-
Some(span) if !$self.0.invalid_span(span) => span,
78+
match $span.as_local($self.item_span) {
79+
Some(span) if !$self.invalid_span(span) => span,
9480
_ => {
95-
return;
81+
return None;
9682
}
9783
}
9884
};
9985
}
10086

101-
fn expr_to_string(ex: &Expr) -> String {
102-
rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_expr(ex))
103-
}
104-
105-
impl<'hir> HirVisitor<'hir> for HirSpanCollector<'_, 'hir, '_> {
106-
fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
107-
intravisit::walk_expr(self, expr);
108-
109-
let span = try_span!(self, expr.span);
110-
111-
let inner_spans = match expr.kind {
112-
ExprKind::Loop(_, _, loop_source, header) => match loop_source {
113-
LoopSource::ForLoop | LoopSource::While => {
114-
vec![expr.span.trim_start(header).unwrap_or(expr.span)]
115-
}
116-
LoopSource::Loop => {
117-
vec![expr.span.with_lo(expr.span.lo() + BytePos(4))]
87+
impl<'tcx> Spanner<'tcx> {
88+
pub fn hir_spans(&self, id: HirId, mode: EnclosingHirSpans) -> Option<Vec<Span>> {
89+
let hir = self.tcx.hir();
90+
let span = try_span!(self, hir.span(id));
91+
let inner_spans = match hir.get(id) {
92+
Node::Expr(expr) => match expr.kind {
93+
ExprKind::Loop(_, _, loop_source, header) => match loop_source {
94+
LoopSource::ForLoop | LoopSource::While => {
95+
vec![expr.span.trim_start(header).unwrap_or(expr.span)]
96+
}
97+
98+
LoopSource::Loop => vec![expr.span.with_lo(expr.span.lo() + BytePos(4))],
99+
},
100+
ExprKind::Break(..) => return None,
101+
_ => {
102+
let mut visitor = ChildExprSpans {
103+
spans: Vec::new(),
104+
item_span: self.item_span,
105+
};
106+
intravisit::walk_expr(&mut visitor, expr);
107+
108+
visitor.spans
118109
}
119110
},
120-
ExprKind::Break(..) => {
121-
return;
122-
}
123-
_ => {
111+
Node::Stmt(stmt) => {
124112
let mut visitor = ChildExprSpans {
125113
spans: Vec::new(),
126-
item_span: self.0.item_span,
114+
item_span: self.item_span,
127115
};
128-
intravisit::walk_expr(&mut visitor, expr);
116+
intravisit::walk_stmt(&mut visitor, stmt);
129117
visitor.spans
130118
}
131-
};
132-
133-
let mut outer_spans = span.subtract(inner_spans.clone());
134-
135-
// In an expression `match e { .. }` the span of `e` is only stored in a `FakeRead`,
136-
// so we have to ensure that the span of the HIR match includes the matched expression.
137-
if let ExprKind::Match(matched, _, _) = expr.kind {
138-
outer_spans.push(matched.span);
139-
}
140-
141-
trace!(
142-
"Expr:\n{}\nhas span: {:?}\nand inner spans: {:?}\nand outer spans: {:?}",
143-
expr_to_string(expr),
144-
span,
145-
inner_spans,
146-
outer_spans
147-
);
148-
149-
if outer_spans.is_empty() {
150-
return;
151-
}
152-
153-
self.0.hir_spans.push(HirSpannedNode {
154-
full: span.data(),
155-
outer: outer_spans,
156-
node: Node::Expr(expr),
157-
});
158-
}
159-
160-
fn visit_stmt(&mut self, stmt: &'hir Stmt<'hir>) {
161-
intravisit::walk_stmt(self, stmt);
162-
163-
let span = try_span!(self, stmt.span);
164-
165-
let mut visitor = ChildExprSpans {
166-
spans: Vec::new(),
167-
item_span: self.0.item_span,
168-
};
169-
intravisit::walk_stmt(&mut visitor, stmt);
170-
let outer_spans = span.subtract(visitor.spans);
171-
172-
self.0.hir_spans.push(HirSpannedNode {
173-
full: span.data(),
174-
outer: outer_spans,
175-
node: Node::Stmt(stmt),
176-
});
177-
}
178-
179-
fn visit_param(&mut self, param: &'hir Param<'hir>) {
180-
intravisit::walk_param(self, param);
181-
182-
let span = match param.span.as_local(self.0.item_span) {
183-
Some(span) if !self.0.invalid_span(span) => span,
119+
Node::Param(_param) => vec![],
184120
_ => {
185-
return;
121+
return None;
186122
}
187123
};
188124

189-
// TODO: more precise outer spans
190-
self.0.hir_spans.push(HirSpannedNode {
191-
full: span.data(),
192-
outer: vec![span],
193-
node: Node::Param(param),
194-
});
125+
Some(match mode {
126+
EnclosingHirSpans::Full => vec![span],
127+
EnclosingHirSpans::OuterOnly => span.subtract(inner_spans),
128+
EnclosingHirSpans::None => vec![],
129+
})
195130
}
196131
}

crates/flowistry/src/source_map/mir_span.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@ pub struct MirSpannedPlace<'tcx> {
2525
pub locations: SmallVec<[LocationOrArg; 1]>,
2626
}
2727

28-
pub struct MirSpanCollector<'a, 'hir, 'tcx>(
29-
pub &'a mut Spanner<'hir, 'tcx>,
30-
pub &'a Body<'tcx>,
31-
);
28+
pub struct MirSpanCollector<'a, 'tcx>(pub &'a mut Spanner<'tcx>, pub &'a Body<'tcx>);
3229

3330
macro_rules! try_span {
3431
($self:expr, $span:expr) => {
@@ -41,7 +38,7 @@ macro_rules! try_span {
4138
};
4239
}
4340

44-
impl<'tcx> MirVisitor<'tcx> for MirSpanCollector<'_, '_, 'tcx> {
41+
impl<'tcx> MirVisitor<'tcx> for MirSpanCollector<'_, 'tcx> {
4542
fn visit_body(&mut self, body: &Body<'tcx>) {
4643
self.super_body(body);
4744

0 commit comments

Comments
 (0)