about summary refs log tree commit diff
path: root/src/tools/rust-analyzer
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-04-06 08:18:23 +0000
committerGitHub <noreply@github.com>2025-04-06 08:18:23 +0000
commitd3d1f49f74fec0a5832f4bf79448e1809abe6999 (patch)
treea590f339ce5bc1055d76895e4b3faa14c3491308 /src/tools/rust-analyzer
parentb3e9af53f8514996812a9310226794700910de2b (diff)
parentf1ed314003a1b52218aef9779edda0a137750ffc (diff)
downloadrust-d3d1f49f74fec0a5832f4bf79448e1809abe6999.tar.gz
rust-d3d1f49f74fec0a5832f4bf79448e1809abe6999.zip
Merge pull request #19531 from Veykril/push-kxyrpznnllkx
fix: Fix `format_args` lowering for >=1.87
Diffstat (limited to 'src/tools/rust-analyzer')
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/lib.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs137
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/diagnostics.rs13
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs5
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs1
7 files changed, 129 insertions, 54 deletions
diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
index 83857cf2dd0..9fbeace76c1 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -303,6 +303,19 @@ pub struct CrateWorkspaceData {
     pub toolchain: Option<Version>,
 }
 
+impl CrateWorkspaceData {
+    pub fn is_atleast_187(&self) -> bool {
+        const VERSION_187: Version = Version {
+            major: 1,
+            minor: 87,
+            patch: 0,
+            pre: Prerelease::EMPTY,
+            build: BuildMetadata::EMPTY,
+        };
+        self.toolchain.as_ref().map_or(false, |v| *v >= VERSION_187)
+    }
+}
+
 fn toolchain_channel(db: &dyn RootQueryDb, krate: Crate) -> Option<ReleaseChannel> {
     krate.workspace_data(db).toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre))
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
index 2d6e8f037f2..1791a1c3175 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
@@ -2321,54 +2321,99 @@ impl ExprCollector<'_> {
             zero_pad,
             debug_hex,
         } = &placeholder.format_options;
-        let fill = self.alloc_expr_desugared(Expr::Literal(Literal::Char(fill.unwrap_or(' '))));
 
-        let align = {
-            let align = LangItem::FormatAlignment.ty_rel_path(
-                self.db,
-                self.krate,
-                match alignment {
-                    Some(FormatAlignment::Left) => Name::new_symbol_root(sym::Left.clone()),
-                    Some(FormatAlignment::Right) => Name::new_symbol_root(sym::Right.clone()),
-                    Some(FormatAlignment::Center) => Name::new_symbol_root(sym::Center.clone()),
-                    None => Name::new_symbol_root(sym::Unknown.clone()),
-                },
-            );
-            match align {
-                Some(path) => self.alloc_expr_desugared(Expr::Path(path)),
-                None => self.missing_expr(),
-            }
-        };
-        // This needs to match `Flag` in library/core/src/fmt/rt.rs.
-        let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
-            | (((sign == Some(FormatSign::Minus)) as u32) << 1)
-            | ((alternate as u32) << 2)
-            | ((zero_pad as u32) << 3)
-            | (((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4)
-            | (((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5);
-        let flags = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
-            flags as u128,
-            Some(BuiltinUint::U32),
-        )));
-        let precision = self.make_count(precision, argmap);
-        let width = self.make_count(width, argmap);
+        let precision_expr = self.make_count(precision, argmap);
+        let width_expr = self.make_count(width, argmap);
 
-        let format_placeholder_new = {
-            let format_placeholder_new = LangItem::FormatPlaceholder.ty_rel_path(
-                self.db,
-                self.krate,
-                Name::new_symbol_root(sym::new.clone()),
-            );
-            match format_placeholder_new {
-                Some(path) => self.alloc_expr_desugared(Expr::Path(path)),
-                None => self.missing_expr(),
-            }
-        };
-
-        self.alloc_expr_desugared(Expr::Call {
-            callee: format_placeholder_new,
-            args: Box::new([position, fill, align, flags, precision, width]),
-        })
+        if self.krate.workspace_data(self.db).is_atleast_187() {
+            // These need to match the constants in library/core/src/fmt/rt.rs.
+            let align = match alignment {
+                Some(FormatAlignment::Left) => 0,
+                Some(FormatAlignment::Right) => 1,
+                Some(FormatAlignment::Center) => 2,
+                None => 3,
+            };
+            // This needs to match `Flag` in library/core/src/fmt/rt.rs.
+            let flags = fill.unwrap_or(' ') as u32
+                | ((sign == Some(FormatSign::Plus)) as u32) << 21
+                | ((sign == Some(FormatSign::Minus)) as u32) << 22
+                | (alternate as u32) << 23
+                | (zero_pad as u32) << 24
+                | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 25
+                | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 26
+                | (width.is_some() as u32) << 27
+                | (precision.is_some() as u32) << 28
+                | align << 29
+                | 1 << 31; // Highest bit always set.
+            let flags = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
+                flags as u128,
+                Some(BuiltinUint::U32),
+            )));
+
+            let position = RecordLitField {
+                name: Name::new_symbol_root(sym::position.clone()),
+                expr: position,
+            };
+            let flags =
+                RecordLitField { name: Name::new_symbol_root(sym::flags.clone()), expr: flags };
+            let precision = RecordLitField {
+                name: Name::new_symbol_root(sym::precision.clone()),
+                expr: precision_expr,
+            };
+            let width = RecordLitField {
+                name: Name::new_symbol_root(sym::width.clone()),
+                expr: width_expr,
+            };
+            self.alloc_expr_desugared(Expr::RecordLit {
+                path: LangItem::FormatPlaceholder.path(self.db, self.krate).map(Box::new),
+                fields: Box::new([position, flags, precision, width]),
+                spread: None,
+            })
+        } else {
+            let format_placeholder_new = {
+                let format_placeholder_new = LangItem::FormatPlaceholder.ty_rel_path(
+                    self.db,
+                    self.krate,
+                    Name::new_symbol_root(sym::new.clone()),
+                );
+                match format_placeholder_new {
+                    Some(path) => self.alloc_expr_desugared(Expr::Path(path)),
+                    None => self.missing_expr(),
+                }
+            };
+            // This needs to match `Flag` in library/core/src/fmt/rt.rs.
+            let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
+                | (((sign == Some(FormatSign::Minus)) as u32) << 1)
+                | ((alternate as u32) << 2)
+                | ((zero_pad as u32) << 3)
+                | (((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4)
+                | (((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5);
+            let flags = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
+                flags as u128,
+                Some(BuiltinUint::U32),
+            )));
+            let fill = self.alloc_expr_desugared(Expr::Literal(Literal::Char(fill.unwrap_or(' '))));
+            let align = {
+                let align = LangItem::FormatAlignment.ty_rel_path(
+                    self.db,
+                    self.krate,
+                    match alignment {
+                        Some(FormatAlignment::Left) => Name::new_symbol_root(sym::Left.clone()),
+                        Some(FormatAlignment::Right) => Name::new_symbol_root(sym::Right.clone()),
+                        Some(FormatAlignment::Center) => Name::new_symbol_root(sym::Center.clone()),
+                        None => Name::new_symbol_root(sym::Unknown.clone()),
+                    },
+                );
+                match align {
+                    Some(path) => self.alloc_expr_desugared(Expr::Path(path)),
+                    None => self.missing_expr(),
+                }
+            };
+            self.alloc_expr_desugared(Expr::Call {
+                callee: format_placeholder_new,
+                args: Box::new([position, fill, align, flags, precision_expr, width_expr]),
+            })
+        }
     }
 
     /// Generate a hir expression for a format_args Count.
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 0bd605c18b4..0448ecd1ec4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -1534,10 +1534,6 @@ impl<'a> InferenceContext<'a> {
                 None => return (self.err_ty(), None),
             }
         };
-        let Some(mod_path) = path.mod_path() else {
-            never!("resolver should always resolve lang item paths");
-            return (self.err_ty(), None);
-        };
         return match resolution {
             TypeNs::AdtId(AdtId::StructId(strukt)) => {
                 let substs = path_ctx.substs_from_path(strukt.into(), true);
@@ -1567,6 +1563,10 @@ impl<'a> InferenceContext<'a> {
 
                 let Some(remaining_idx) = unresolved else {
                     drop(ctx);
+                    let Some(mod_path) = path.mod_path() else {
+                        never!("resolver should always resolve lang item paths");
+                        return (self.err_ty(), None);
+                    };
                     return self.resolve_variant_on_alias(ty, None, mod_path);
                 };
 
@@ -1630,6 +1630,10 @@ impl<'a> InferenceContext<'a> {
                 (ty, variant)
             }
             TypeNs::TypeAliasId(it) => {
+                let Some(mod_path) = path.mod_path() else {
+                    never!("resolver should always resolve lang item paths");
+                    return (self.err_ty(), None);
+                };
                 let substs = path_ctx.substs_from_path_segment(it.into(), true, None);
                 drop(ctx);
                 let ty = self.db.ty(it.into());
diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
index afa1f6dcc8f..651ec151d40 100644
--- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
@@ -570,10 +570,17 @@ impl AnyDiagnostic {
         source_map: &hir_def::expr_store::BodySourceMap,
     ) -> Option<AnyDiagnostic> {
         let expr_syntax = |expr| {
-            source_map.expr_syntax(expr).inspect_err(|_| stdx::never!("synthetic syntax")).ok()
+            source_map
+                .expr_syntax(expr)
+                .inspect_err(|_| stdx::never!("inference diagnostic in desugared expr"))
+                .ok()
+        };
+        let pat_syntax = |pat| {
+            source_map
+                .pat_syntax(pat)
+                .inspect_err(|_| stdx::never!("inference diagnostic in desugared pattern"))
+                .ok()
         };
-        let pat_syntax =
-            |pat| source_map.pat_syntax(pat).inspect_err(|_| stdx::never!("synthetic syntax")).ok();
         let expr_or_pat_syntax = |id| match id {
             ExprOrPatId::ExprId(expr) => expr_syntax(expr),
             ExprOrPatId::PatId(pat) => pat_syntax(pat),
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index 7d855cf4498..13b161e59d9 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -753,7 +753,7 @@ impl Analysis {
         frange: FileRange,
     ) -> Cancellable<Vec<Assist>> {
         let include_fixes = match &assist_config.allowed {
-            Some(it) => it.iter().any(|&it| it == AssistKind::QuickFix),
+            Some(it) => it.contains(&AssistKind::QuickFix),
             None => true,
         };
 
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index 4841f486591..a9ed1857de6 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -161,6 +161,7 @@ define_symbols! {
     bitxor_assign,
     bitxor,
     bool,
+    bootstrap,
     box_free,
     Box,
     boxed,
@@ -525,4 +526,8 @@ define_symbols! {
     ignore_flyimport,
     ignore_flyimport_methods,
     ignore_methods,
+    position,
+    flags,
+    precision,
+    width,
 }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index a0fb4a7d0fd..7a139ea0c4c 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -1664,6 +1664,7 @@ fn sysroot_to_crate_graph(
                         vec![
                             CfgAtom::Flag(sym::debug_assertions.clone()),
                             CfgAtom::Flag(sym::miri.clone()),
+                            CfgAtom::Flag(sym::bootstrap.clone()),
                         ],
                         vec![CfgAtom::Flag(sym::test.clone())],
                     ),