Skip to content

Commit 9606412

Browse files
committed
Auto merge of #147641 - cjgillot:liveness-cache-strings, r=estebank
Liveness: Cache the set of string constants for suggestions. Even on a slow diagnostic path, listing all the constants in MIR can be expensive, so cache it.
2 parents 0bbef55 + 727da8c commit 9606412

File tree

1 file changed

+40
-41
lines changed

1 file changed

+40
-41
lines changed

compiler/rustc_mir_transform/src/liveness.rs

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -164,45 +164,6 @@ fn is_capture(place: PlaceRef<'_>) -> bool {
164164
}
165165
}
166166

167-
/// Give a diagnostic when any of the string constants look like a naked format string that would
168-
/// interpolate our dead local.
169-
fn maybe_suggest_literal_matching_name(
170-
body: &Body<'_>,
171-
name: Symbol,
172-
) -> Vec<errors::UnusedVariableStringInterp> {
173-
struct LiteralFinder<'body, 'tcx> {
174-
body: &'body Body<'tcx>,
175-
name: String,
176-
name_colon: String,
177-
found: Vec<errors::UnusedVariableStringInterp>,
178-
}
179-
180-
impl<'tcx> Visitor<'tcx> for LiteralFinder<'_, 'tcx> {
181-
fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, loc: Location) {
182-
if let ty::Ref(_, ref_ty, _) = constant.ty().kind()
183-
&& ref_ty.kind() == &ty::Str
184-
{
185-
let rendered_constant = constant.const_.to_string();
186-
if rendered_constant.contains(&self.name)
187-
|| rendered_constant.contains(&self.name_colon)
188-
{
189-
let lit = self.body.source_info(loc).span;
190-
self.found.push(errors::UnusedVariableStringInterp { lit });
191-
}
192-
}
193-
}
194-
}
195-
196-
let mut finder = LiteralFinder {
197-
body,
198-
name: format!("{{{name}}}"),
199-
name_colon: format!("{{{name}:"),
200-
found: vec![],
201-
};
202-
finder.visit_body(body);
203-
finder.found
204-
}
205-
206167
/// Give a diagnostic when an unused variable may be a typo of a unit variant or a struct.
207168
fn maybe_suggest_unit_pattern_typo<'tcx>(
208169
tcx: TyCtxt<'tcx>,
@@ -879,6 +840,44 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
879840
fn report_fully_unused(&mut self) {
880841
let tcx = self.tcx;
881842

843+
// Give a diagnostic when any of the string constants look like a naked format string that
844+
// would interpolate our dead local.
845+
let mut string_constants_in_body = None;
846+
let mut maybe_suggest_literal_matching_name = |name: Symbol| {
847+
// Visiting MIR to enumerate string constants can be expensive, so cache the result.
848+
let string_constants_in_body = string_constants_in_body.get_or_insert_with(|| {
849+
struct LiteralFinder {
850+
found: Vec<(Span, String)>,
851+
}
852+
853+
impl<'tcx> Visitor<'tcx> for LiteralFinder {
854+
fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, _: Location) {
855+
if let ty::Ref(_, ref_ty, _) = constant.ty().kind()
856+
&& ref_ty.kind() == &ty::Str
857+
{
858+
let rendered_constant = constant.const_.to_string();
859+
self.found.push((constant.span, rendered_constant));
860+
}
861+
}
862+
}
863+
864+
let mut finder = LiteralFinder { found: vec![] };
865+
finder.visit_body(self.body);
866+
finder.found
867+
});
868+
869+
let brace_name = format!("{{{name}");
870+
string_constants_in_body
871+
.iter()
872+
.filter(|(_, rendered_constant)| {
873+
rendered_constant
874+
.split(&brace_name)
875+
.any(|c| matches!(c.chars().next(), Some('}' | ':')))
876+
})
877+
.map(|&(lit, _)| errors::UnusedVariableStringInterp { lit })
878+
.collect::<Vec<_>>()
879+
};
880+
882881
// First, report fully unused locals.
883882
for (index, place) in self.checked_places.iter() {
884883
if self.ever_live.contains(index) {
@@ -940,7 +939,7 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
940939
def_span,
941940
errors::UnusedVariable {
942941
name,
943-
string_interp: maybe_suggest_literal_matching_name(self.body, name),
942+
string_interp: maybe_suggest_literal_matching_name(name),
944943
sugg,
945944
},
946945
);
@@ -1030,7 +1029,7 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
10301029
spans,
10311030
errors::UnusedVariable {
10321031
name,
1033-
string_interp: maybe_suggest_literal_matching_name(self.body, name),
1032+
string_interp: maybe_suggest_literal_matching_name(name),
10341033
sugg,
10351034
},
10361035
);

0 commit comments

Comments
 (0)