mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 12:04:43 +00:00 
			
		
		
		
	Merge pull request #19531 from Veykril/push-kxyrpznnllkx
fix: Fix `format_args` lowering for >=1.87
This commit is contained in:
		
						commit
						7e00f91a72
					
				
					 7 changed files with 128 additions and 53 deletions
				
			
		|  | @ -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)) | ||||
| } | ||||
|  |  | |||
|  | @ -2321,8 +2321,78 @@ impl ExprCollector<'_> { | |||
|             zero_pad, | ||||
|             debug_hex, | ||||
|         } = &placeholder.format_options; | ||||
|         let fill = self.alloc_expr_desugared(Expr::Literal(Literal::Char(fill.unwrap_or(' ')))); | ||||
| 
 | ||||
|         let precision_expr = self.make_count(precision, argmap); | ||||
|         let width_expr = self.make_count(width, argmap); | ||||
| 
 | ||||
|         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, | ||||
|  | @ -2339,37 +2409,12 @@ impl ExprCollector<'_> { | |||
|                     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 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]), | ||||
|                 args: Box::new([position, fill, align, flags, precision_expr, width_expr]), | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// Generate a hir expression for a format_args Count.
 | ||||
|     ///
 | ||||
|  |  | |||
|  | @ -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()); | ||||
|  |  | |||
|  | @ -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), | ||||
|  |  | |||
|  | @ -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, | ||||
|         }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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, | ||||
| } | ||||
|  |  | |||
|  | @ -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())], | ||||
|                     ), | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Wirth
						Lukas Wirth