Auto merge of #16684 - Veykril:synthetic-fmt-args, r=Veykril

fix: Don't panic on synthetic syntax in inference diagnostics

Temporary fix for https://github.com/rust-lang/rust-analyzer/issues/16682

We ought to rethink how we attach diagnostics to things, as IDs don't work for `format_args` like that!
This commit is contained in:
bors 2024-02-26 16:47:57 +00:00
commit 1d3558bfe1
2 changed files with 33 additions and 17 deletions

View file

@ -518,8 +518,12 @@ impl AnyDiagnostic {
d: &InferenceDiagnostic, d: &InferenceDiagnostic,
source_map: &hir_def::body::BodySourceMap, source_map: &hir_def::body::BodySourceMap,
) -> Option<AnyDiagnostic> { ) -> Option<AnyDiagnostic> {
let expr_syntax = |expr| source_map.expr_syntax(expr).expect("unexpected synthetic"); let expr_syntax = |expr| {
let pat_syntax = |pat| source_map.pat_syntax(pat).expect("unexpected synthetic"); source_map.expr_syntax(expr).inspect_err(|_| tracing::error!("synthetic syntax")).ok()
};
let pat_syntax = |pat| {
source_map.pat_syntax(pat).inspect_err(|_| tracing::error!("synthetic syntax")).ok()
};
Some(match d { Some(match d {
&InferenceDiagnostic::NoSuchField { field: expr, private } => { &InferenceDiagnostic::NoSuchField { field: expr, private } => {
let expr_or_pat = match expr { let expr_or_pat = match expr {
@ -533,23 +537,23 @@ impl AnyDiagnostic {
NoSuchField { field: expr_or_pat, private }.into() NoSuchField { field: expr_or_pat, private }.into()
} }
&InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => { &InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {
MismatchedArgCount { call_expr: expr_syntax(call_expr), expected, found }.into() MismatchedArgCount { call_expr: expr_syntax(call_expr)?, expected, found }.into()
} }
&InferenceDiagnostic::PrivateField { expr, field } => { &InferenceDiagnostic::PrivateField { expr, field } => {
let expr = expr_syntax(expr); let expr = expr_syntax(expr)?;
let field = field.into(); let field = field.into();
PrivateField { expr, field }.into() PrivateField { expr, field }.into()
} }
&InferenceDiagnostic::PrivateAssocItem { id, item } => { &InferenceDiagnostic::PrivateAssocItem { id, item } => {
let expr_or_pat = match id { let expr_or_pat = match id {
ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), ExprOrPatId::ExprId(expr) => expr_syntax(expr)?.map(AstPtr::wrap_left),
ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), ExprOrPatId::PatId(pat) => pat_syntax(pat)?.map(AstPtr::wrap_right),
}; };
let item = item.into(); let item = item.into();
PrivateAssocItem { expr_or_pat, item }.into() PrivateAssocItem { expr_or_pat, item }.into()
} }
InferenceDiagnostic::ExpectedFunction { call_expr, found } => { InferenceDiagnostic::ExpectedFunction { call_expr, found } => {
let call_expr = expr_syntax(*call_expr); let call_expr = expr_syntax(*call_expr)?;
ExpectedFunction { call: call_expr, found: Type::new(db, def, found.clone()) } ExpectedFunction { call: call_expr, found: Type::new(db, def, found.clone()) }
.into() .into()
} }
@ -559,7 +563,7 @@ impl AnyDiagnostic {
name, name,
method_with_same_name_exists, method_with_same_name_exists,
} => { } => {
let expr = expr_syntax(*expr); let expr = expr_syntax(*expr)?;
UnresolvedField { UnresolvedField {
expr, expr,
name: name.clone(), name: name.clone(),
@ -575,7 +579,7 @@ impl AnyDiagnostic {
field_with_same_name, field_with_same_name,
assoc_func_with_same_name, assoc_func_with_same_name,
} => { } => {
let expr = expr_syntax(*expr); let expr = expr_syntax(*expr)?;
UnresolvedMethodCall { UnresolvedMethodCall {
expr, expr,
name: name.clone(), name: name.clone(),
@ -589,29 +593,28 @@ impl AnyDiagnostic {
} }
&InferenceDiagnostic::UnresolvedAssocItem { id } => { &InferenceDiagnostic::UnresolvedAssocItem { id } => {
let expr_or_pat = match id { let expr_or_pat = match id {
ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), ExprOrPatId::ExprId(expr) => expr_syntax(expr)?.map(AstPtr::wrap_left),
ExprOrPatId::PatId(pat) => pat_syntax(pat).map(AstPtr::wrap_right), ExprOrPatId::PatId(pat) => pat_syntax(pat)?.map(AstPtr::wrap_right),
}; };
UnresolvedAssocItem { expr_or_pat }.into() UnresolvedAssocItem { expr_or_pat }.into()
} }
&InferenceDiagnostic::UnresolvedIdent { expr } => { &InferenceDiagnostic::UnresolvedIdent { expr } => {
let expr = expr_syntax(expr); let expr = expr_syntax(expr)?;
UnresolvedIdent { expr }.into() UnresolvedIdent { expr }.into()
} }
&InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break, bad_value_break } => { &InferenceDiagnostic::BreakOutsideOfLoop { expr, is_break, bad_value_break } => {
let expr = expr_syntax(expr); let expr = expr_syntax(expr)?;
BreakOutsideOfLoop { expr, is_break, bad_value_break }.into() BreakOutsideOfLoop { expr, is_break, bad_value_break }.into()
} }
InferenceDiagnostic::TypedHole { expr, expected } => { InferenceDiagnostic::TypedHole { expr, expected } => {
let expr = expr_syntax(*expr); let expr = expr_syntax(*expr)?;
TypedHole { expr, expected: Type::new(db, def, expected.clone()) }.into() TypedHole { expr, expected: Type::new(db, def, expected.clone()) }.into()
} }
&InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => { &InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => {
let expr_or_pat = match pat { let expr_or_pat = match pat {
ExprOrPatId::ExprId(expr) => expr_syntax(expr).map(AstPtr::wrap_left), ExprOrPatId::ExprId(expr) => expr_syntax(expr)?.map(AstPtr::wrap_left),
ExprOrPatId::PatId(pat) => { ExprOrPatId::PatId(pat) => {
let InFile { file_id, value } = let InFile { file_id, value } = pat_syntax(pat)?;
source_map.pat_syntax(pat).expect("unexpected synthetic");
// cast from Either<Pat, SelfParam> -> Either<_, Pat> // cast from Either<Pat, SelfParam> -> Either<_, Pat>
let ptr = AstPtr::try_from_raw(value.syntax_node_ptr())?; let ptr = AstPtr::try_from_raw(value.syntax_node_ptr())?;

View file

@ -20,6 +20,19 @@ pub(crate) fn unresolved_ident(
mod tests { mod tests {
use crate::tests::check_diagnostics; use crate::tests::check_diagnostics;
// FIXME: This should show a diagnostic
#[test]
fn feature() {
check_diagnostics(
r#"
//- minicore: fmt
fn main() {
format_args!("{unresolved}");
}
"#,
)
}
#[test] #[test]
fn missing() { fn missing() {
check_diagnostics( check_diagnostics(