mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-29 02:52:11 +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>,
|
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> {
|
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))
|
krate.workspace_data(db).toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2321,54 +2321,99 @@ impl ExprCollector<'_> {
|
||||||
zero_pad,
|
zero_pad,
|
||||||
debug_hex,
|
debug_hex,
|
||||||
} = &placeholder.format_options;
|
} = &placeholder.format_options;
|
||||||
let fill = self.alloc_expr_desugared(Expr::Literal(Literal::Char(fill.unwrap_or(' '))));
|
|
||||||
|
|
||||||
let align = {
|
let precision_expr = self.make_count(precision, argmap);
|
||||||
let align = LangItem::FormatAlignment.ty_rel_path(
|
let width_expr = self.make_count(width, argmap);
|
||||||
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 format_placeholder_new = {
|
if self.krate.workspace_data(self.db).is_atleast_187() {
|
||||||
let format_placeholder_new = LangItem::FormatPlaceholder.ty_rel_path(
|
// These need to match the constants in library/core/src/fmt/rt.rs.
|
||||||
self.db,
|
let align = match alignment {
|
||||||
self.krate,
|
Some(FormatAlignment::Left) => 0,
|
||||||
Name::new_symbol_root(sym::new.clone()),
|
Some(FormatAlignment::Right) => 1,
|
||||||
);
|
Some(FormatAlignment::Center) => 2,
|
||||||
match format_placeholder_new {
|
None => 3,
|
||||||
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 = 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 {
|
let position = RecordLitField {
|
||||||
callee: format_placeholder_new,
|
name: Name::new_symbol_root(sym::position.clone()),
|
||||||
args: Box::new([position, fill, align, flags, precision, width]),
|
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.
|
/// Generate a hir expression for a format_args Count.
|
||||||
|
|
|
||||||
|
|
@ -1534,10 +1534,6 @@ impl<'a> InferenceContext<'a> {
|
||||||
None => return (self.err_ty(), None),
|
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 {
|
return match resolution {
|
||||||
TypeNs::AdtId(AdtId::StructId(strukt)) => {
|
TypeNs::AdtId(AdtId::StructId(strukt)) => {
|
||||||
let substs = path_ctx.substs_from_path(strukt.into(), true);
|
let substs = path_ctx.substs_from_path(strukt.into(), true);
|
||||||
|
|
@ -1567,6 +1563,10 @@ impl<'a> InferenceContext<'a> {
|
||||||
|
|
||||||
let Some(remaining_idx) = unresolved else {
|
let Some(remaining_idx) = unresolved else {
|
||||||
drop(ctx);
|
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);
|
return self.resolve_variant_on_alias(ty, None, mod_path);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1630,6 +1630,10 @@ impl<'a> InferenceContext<'a> {
|
||||||
(ty, variant)
|
(ty, variant)
|
||||||
}
|
}
|
||||||
TypeNs::TypeAliasId(it) => {
|
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);
|
let substs = path_ctx.substs_from_path_segment(it.into(), true, None);
|
||||||
drop(ctx);
|
drop(ctx);
|
||||||
let ty = self.db.ty(it.into());
|
let ty = self.db.ty(it.into());
|
||||||
|
|
|
||||||
|
|
@ -570,10 +570,17 @@ impl AnyDiagnostic {
|
||||||
source_map: &hir_def::expr_store::BodySourceMap,
|
source_map: &hir_def::expr_store::BodySourceMap,
|
||||||
) -> Option<AnyDiagnostic> {
|
) -> Option<AnyDiagnostic> {
|
||||||
let expr_syntax = |expr| {
|
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 {
|
let expr_or_pat_syntax = |id| match id {
|
||||||
ExprOrPatId::ExprId(expr) => expr_syntax(expr),
|
ExprOrPatId::ExprId(expr) => expr_syntax(expr),
|
||||||
ExprOrPatId::PatId(pat) => pat_syntax(pat),
|
ExprOrPatId::PatId(pat) => pat_syntax(pat),
|
||||||
|
|
|
||||||
|
|
@ -753,7 +753,7 @@ impl Analysis {
|
||||||
frange: FileRange,
|
frange: FileRange,
|
||||||
) -> Cancellable<Vec<Assist>> {
|
) -> Cancellable<Vec<Assist>> {
|
||||||
let include_fixes = match &assist_config.allowed {
|
let include_fixes = match &assist_config.allowed {
|
||||||
Some(it) => it.iter().any(|&it| it == AssistKind::QuickFix),
|
Some(it) => it.contains(&AssistKind::QuickFix),
|
||||||
None => true,
|
None => true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,7 @@ define_symbols! {
|
||||||
bitxor_assign,
|
bitxor_assign,
|
||||||
bitxor,
|
bitxor,
|
||||||
bool,
|
bool,
|
||||||
|
bootstrap,
|
||||||
box_free,
|
box_free,
|
||||||
Box,
|
Box,
|
||||||
boxed,
|
boxed,
|
||||||
|
|
@ -525,4 +526,8 @@ define_symbols! {
|
||||||
ignore_flyimport,
|
ignore_flyimport,
|
||||||
ignore_flyimport_methods,
|
ignore_flyimport_methods,
|
||||||
ignore_methods,
|
ignore_methods,
|
||||||
|
position,
|
||||||
|
flags,
|
||||||
|
precision,
|
||||||
|
width,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1664,6 +1664,7 @@ fn sysroot_to_crate_graph(
|
||||||
vec![
|
vec![
|
||||||
CfgAtom::Flag(sym::debug_assertions.clone()),
|
CfgAtom::Flag(sym::debug_assertions.clone()),
|
||||||
CfgAtom::Flag(sym::miri.clone()),
|
CfgAtom::Flag(sym::miri.clone()),
|
||||||
|
CfgAtom::Flag(sym::bootstrap.clone()),
|
||||||
],
|
],
|
||||||
vec![CfgAtom::Flag(sym::test.clone())],
|
vec![CfgAtom::Flag(sym::test.clone())],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue