Skip to content

Commit 217cf52

Browse files
committed
Rust: address extractor review comments
- Own `Translator`'s path as `String`, dropping the `'a` lifetime - Route `reconstruct_format_args_expansion` bailouts through an `Option` helper using `?` - Reword `format_args` doc comments to state the AST-parity goal - Use `PartialEq` `if` instead of `let else` in `split_arguments` - Drop stale duplicate/toolchain-version comments
1 parent 6ec597f commit 217cf52

4 files changed

Lines changed: 49 additions & 74 deletions

File tree

‎rust/extractor/src/translate/base.rs‎

Lines changed: 39 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use ra_ap_syntax_bridge::{
2222
DocCommentDesugarMode, syntax_node_to_token_tree, token_tree_to_syntax_node,
2323
};
2424

25-
impl Emission<ast::Item> for Translator<'_, '_> {
25+
impl Emission<ast::Item> for Translator<'_> {
2626
fn pre_emit(&mut self, node: &ast::Item) -> Option<Label<generated::Item>> {
2727
self.item_pre_emit(node).map(Into::into)
2828
}
@@ -32,7 +32,7 @@ impl Emission<ast::Item> for Translator<'_, '_> {
3232
}
3333
}
3434

35-
impl Emission<ast::AssocItem> for Translator<'_, '_> {
35+
impl Emission<ast::AssocItem> for Translator<'_> {
3636
fn pre_emit(&mut self, node: &ast::AssocItem) -> Option<Label<generated::AssocItem>> {
3737
self.item_pre_emit(&node.clone().into()).map(Into::into)
3838
}
@@ -42,7 +42,7 @@ impl Emission<ast::AssocItem> for Translator<'_, '_> {
4242
}
4343
}
4444

45-
impl Emission<ast::ExternItem> for Translator<'_, '_> {
45+
impl Emission<ast::ExternItem> for Translator<'_> {
4646
fn pre_emit(&mut self, node: &ast::ExternItem) -> Option<Label<generated::ExternItem>> {
4747
self.item_pre_emit(&node.clone().into()).map(Into::into)
4848
}
@@ -52,7 +52,7 @@ impl Emission<ast::ExternItem> for Translator<'_, '_> {
5252
}
5353
}
5454

55-
impl Emission<ast::Meta> for Translator<'_, '_> {
55+
impl Emission<ast::Meta> for Translator<'_> {
5656
fn pre_emit(&mut self, _node: &ast::Meta) -> Option<Label<generated::Meta>> {
5757
self.macro_context_depth += 1;
5858
None
@@ -63,43 +63,43 @@ impl Emission<ast::Meta> for Translator<'_, '_> {
6363
}
6464
}
6565

66-
impl Emission<ast::Fn> for Translator<'_, '_> {
66+
impl Emission<ast::Fn> for Translator<'_> {
6767
fn post_emit(&mut self, node: &ast::Fn, label: Label<generated::Function>) {
6868
self.emit_function_has_implementation(node, label);
6969
}
7070
}
7171

72-
impl Emission<ast::Struct> for Translator<'_, '_> {
72+
impl Emission<ast::Struct> for Translator<'_> {
7373
fn post_emit(&mut self, node: &ast::Struct, label: Label<generated::Struct>) {
7474
self.emit_derive_expansion(node, label);
7575
}
7676
}
7777

78-
impl Emission<ast::Enum> for Translator<'_, '_> {
78+
impl Emission<ast::Enum> for Translator<'_> {
7979
fn post_emit(&mut self, node: &ast::Enum, label: Label<generated::Enum>) {
8080
self.emit_derive_expansion(node, label);
8181
}
8282
}
8383

84-
impl Emission<ast::Union> for Translator<'_, '_> {
84+
impl Emission<ast::Union> for Translator<'_> {
8585
fn post_emit(&mut self, node: &ast::Union, label: Label<generated::Union>) {
8686
self.emit_derive_expansion(node, label);
8787
}
8888
}
8989

90-
impl Emission<ast::PathSegment> for Translator<'_, '_> {
90+
impl Emission<ast::PathSegment> for Translator<'_> {
9191
fn post_emit(&mut self, node: &ast::PathSegment, label: Label<generated::PathSegment>) {
9292
self.extract_types_from_path_segment(node, label);
9393
}
9494
}
9595

96-
impl Emission<ast::Const> for Translator<'_, '_> {
96+
impl Emission<ast::Const> for Translator<'_> {
9797
fn post_emit(&mut self, node: &ast::Const, label: Label<generated::Const>) {
9898
self.emit_const_has_implementation(node, label);
9999
}
100100
}
101101

102-
impl Emission<ast::MacroCall> for Translator<'_, '_> {
102+
impl Emission<ast::MacroCall> for Translator<'_> {
103103
fn post_emit(&mut self, node: &ast::MacroCall, label: Label<generated::MacroCall>) {
104104
self.extract_macro_call_expanded(node, label);
105105
}
@@ -123,12 +123,9 @@ pub enum SourceKind {
123123
Library,
124124
}
125125

126-
// `'a` is the (short) lifetime of the borrowed `path`, `'db` the lifetime of the borrowed
127-
// `Semantics`/database. They must stay separate: `Semantics<'db>` is invariant over `'db`, so
128-
// coupling it to the shorter `'a` fails to type-check.
129-
pub struct Translator<'a, 'db> {
126+
pub struct Translator<'db> {
130127
pub trap: TrapFile,
131-
path: &'a str,
128+
path: String,
132129
label: Label<generated::File>,
133130
line_index: LineIndex,
134131
file_id: Option<EditionedFileId>,
@@ -147,18 +144,18 @@ const UNKNOWN_LOCATION: (LineCol, LineCol) =
147144

148145
const DIAGNOSTIC_LIMIT_PER_FILE: usize = 100;
149146

150-
impl<'a, 'db> Translator<'a, 'db> {
147+
impl<'db> Translator<'db> {
151148
pub fn new(
152149
trap: TrapFile,
153-
path: &'a str,
150+
path: &str,
154151
label: Label<generated::File>,
155152
line_index: LineIndex,
156153
semantic_info: Option<&FileSemanticInformation<'db>>,
157154
source_kind: SourceKind,
158-
) -> Translator<'a, 'db> {
155+
) -> Translator<'db> {
159156
Translator {
160157
trap,
161-
path,
158+
path: path.to_owned(),
162159
label,
163160
line_index,
164161
file_id: semantic_info.map(|i| i.file_id),
@@ -464,9 +461,6 @@ impl<'a, 'db> Translator<'a, 'db> {
464461
}
465462
} else if self.semantics.is_some() {
466463
if self.reconstruct_format_args_expansion(mcall, label) {
467-
// `rustc <1.94` sysroots no longer expand the format-family macros; we
468-
// reconstruct their real expansion (a `FormatArgsExpr`, wrapped in the
469-
// callee that carries flow and the sink models) so both are preserved.
470464
return;
471465
}
472466
// let's not spam warnings if we don't have semantics, we already emitted one
@@ -806,23 +800,20 @@ impl<'a, 'db> Translator<'a, 'db> {
806800
mcall: &ast::MacroCall,
807801
label: Label<generated::MacroCall>,
808802
) -> bool {
809-
let Some(name) = mcall
810-
.path()
811-
.and_then(|p| p.segment())
812-
.and_then(|s| s.name_ref())
813-
.map(|n| n.text().to_string())
814-
else {
815-
return false;
816-
};
817-
let Some(wrap) = format_args::Wrap::for_macro(&name) else {
818-
return false;
819-
};
820-
let Some(tt_node) = mcall.token_tree() else {
821-
return false;
822-
};
823-
let Some(semantics) = self.semantics else {
824-
return false;
825-
};
803+
self.try_reconstruct_format_args_expansion(mcall, label)
804+
.is_some()
805+
}
806+
807+
/// Attempts to reconstruct and emit a format-family macro expansion.
808+
fn try_reconstruct_format_args_expansion(
809+
&mut self,
810+
mcall: &ast::MacroCall,
811+
label: Label<generated::MacroCall>,
812+
) -> Option<()> {
813+
let name = mcall.path()?.segment()?.name_ref()?.text().to_string();
814+
let wrap = format_args::Wrap::for_macro(&name)?;
815+
let tt_node = mcall.token_tree()?;
816+
let semantics = self.semantics?;
826817
let db = semantics.db;
827818
let file_id = semantics.hir_file_for(mcall.syntax());
828819
let span_map = file_id.span_map(db);
@@ -833,39 +824,25 @@ impl<'a, 'db> Translator<'a, 'db> {
833824
call_site,
834825
DocCommentDesugarMode::ProcMacro,
835826
);
836-
let Some(output) = format_args::reconstruct(wrap, &input, call_site) else {
837-
return false;
838-
};
827+
let output = format_args::reconstruct(wrap, &input, call_site)?;
839828

840-
let Some(edition) = self.file_id.map(|f| f.edition(db)) else {
841-
return false;
842-
};
829+
let edition = self.file_id.map(|f| f.edition(db))?;
843830
let (parsed, output_span_map) =
844831
token_tree_to_syntax_node(&output, TopEntryPoint::Expr, &mut |_| edition);
845832
let root = parsed.syntax_node();
846-
let Some(expr) =
847-
ast::Expr::cast(root.clone()).or_else(|| root.descendants().find_map(ast::Expr::cast))
848-
else {
849-
return false;
850-
};
833+
let expr =
834+
ast::Expr::cast(root.clone()).or_else(|| root.descendants().find_map(ast::Expr::cast))?;
851835
// Sanity check: the parsed expression must contain the reconstructed
852836
// `FormatArgsExpr` (either directly, or wrapped in the callee above).
853-
if expr
854-
.syntax()
837+
expr.syntax()
855838
.descendants()
856-
.find_map(ast::FormatArgsExpr::cast)
857-
.is_none()
858-
{
859-
return false;
860-
}
839+
.find_map(ast::FormatArgsExpr::cast)?;
861840
let previous = self.builtin_derive_span_map.replace(output_span_map);
862841
let emitted = self.emit_expr(&expr);
863842
self.builtin_derive_span_map = previous;
864-
let Some(value) = emitted else {
865-
return false;
866-
};
843+
let value = emitted?;
867844
generated::MacroCall::emit_macro_call_expansion(label, value.into(), &mut self.trap.writer);
868-
true
845+
Some(())
869846
}
870847

871848
pub(crate) fn emit_derive_expansion(

‎rust/extractor/src/translate/format_args.rs‎

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22
//!
33
//! On `rustc <1.94` sysroots the format-family macros (`format!`, `println!`,
44
//! `write!`, `panic!`, ...) no longer resolve, so `expand_macro_call` returns `None`
5-
//! and we get a bare unexpanded `MacroCall` with no flow through it (flow is modeled
6-
//! on the `FormatArgsExpr` node, and the security sinks are keyed on the wrapping
7-
//! callee). The syntactic lowering of these macros is a pure, sysroot-independent
8-
//! transform, so we rebuild the same token tree the real (>=1.94) expansion has and
9-
//! parse it ourselves.
5+
//! and we get a bare unexpanded `MacroCall`. The syntactic lowering of these macros
6+
//! is a pure, sysroot-independent transform, so we rebuild the same token tree the
7+
//! real (>=1.94) expansion produces and parse it ourselves, giving pre-1.94
8+
//! toolchains the same AST as newer ones.
109
//!
1110
//! This module owns the pure token-tree construction; [`super::base::Translator`]
1211
//! handles parsing the result and emitting it as the macro expansion.
@@ -16,9 +15,8 @@ use ra_ap_hir_expand::tt;
1615
use ra_ap_span::Span;
1716

1817
/// How a format-family macro wraps its `format_args!`. We rebuild the same shape the
19-
/// real (>=1.94) expansion has, so that both dataflow and the sink models keyed on
20-
/// the wrapping callee keep working on older toolchains.
21-
#[derive(Clone, Copy)]
18+
/// real (>=1.94) expansion has, so older toolchains get the same AST.
19+
#[derive(Clone, Copy, PartialEq, Eq)]
2220
pub(crate) enum Wrap {
2321
/// `format_args!` and friends are themselves the `FormatArgsExpr`.
2422
Bare,
@@ -87,9 +85,9 @@ fn split_arguments<'a>(
8785
wrap: Wrap,
8886
input: &'a tt::TopSubtree,
8987
) -> Option<(Option<tt::TokenTreesView<'a>>, tt::TokenTreesView<'a>)> {
90-
let Wrap::WriteMethod = wrap else {
88+
if wrap != Wrap::WriteMethod {
9189
return Some((None, input.view().token_trees()));
92-
};
90+
}
9391
let mut iter = input.view().iter();
9492
let start = iter.savepoint();
9593
let mut found_comma = false;

‎rust/extractor/src/translate/generated.rs‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎rust/ql/test/library-tests/format-macros-legacy/rust-toolchain.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# a std that carries the new lowering (roughly >= 1.94). On older toolchains the
55
# format-family macros (`format!`, `println!`, `write!`, ...) fail to expand, so
66
# the extractor reconstructs the `FormatArgsExpr` itself. This test exercises that
7-
# reconstruction path, which the default 1.95 test toolchain never hits.
7+
# reconstruction path, which the default test toolchain never hits.
88
#
99
# Any toolchain named here must also be pre-installed in `../setup.sh`, otherwise
1010
# the parallel QL tests race on `rustup` auto-install.

0 commit comments

Comments
 (0)