mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-08-04 18:58:41 +00:00
fix: Fix format_args
lowering for >=1.87
This commit is contained in:
parent
55c8cdeafb
commit
e7ce86ddea
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,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(),
|
||||
}
|
||||
};
|
||||
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),
|
||||
)));
|
||||
|
||||
self.alloc_expr_desugared(Expr::Call {
|
||||
callee: format_placeholder_new,
|
||||
args: Box::new([position, fill, align, flags, precision, width]),
|
||||
})
|
||||
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.
|
||||
|
|
|
@ -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