Make higher levels adapt Bodys exprs having ExprOrPatId values

This commit is contained in:
Ali Bektas 2025-01-08 00:26:47 +01:00
parent 06097c3388
commit d8779b4a0e
8 changed files with 32 additions and 33 deletions

View file

@ -6,6 +6,7 @@
use cfg::{CfgExpr, CfgOptions}; use cfg::{CfgExpr, CfgOptions};
use either::Either; use either::Either;
use hir_def::{ use hir_def::{
body::ExprOrPatPtr,
hir::ExprOrPatId, hir::ExprOrPatId,
path::{hir_segment_to_ast_segment, ModPath}, path::{hir_segment_to_ast_segment, ModPath},
type_ref::TypesSourceMap, type_ref::TypesSourceMap,
@ -115,14 +116,14 @@ diagnostics![
#[derive(Debug)] #[derive(Debug)]
pub struct BreakOutsideOfLoop { pub struct BreakOutsideOfLoop {
pub expr: InFile<AstPtr<ast::Expr>>, pub expr: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
pub is_break: bool, pub is_break: bool,
pub bad_value_break: bool, pub bad_value_break: bool,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct TypedHole { pub struct TypedHole {
pub expr: InFile<AstPtr<ast::Expr>>, pub expr: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
pub expected: Type, pub expected: Type,
} }
@ -234,13 +235,13 @@ pub struct MismatchedTupleStructPatArgCount {
#[derive(Debug)] #[derive(Debug)]
pub struct ExpectedFunction { pub struct ExpectedFunction {
pub call: InFile<AstPtr<ast::Expr>>, pub call: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
pub found: Type, pub found: Type,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct UnresolvedField { pub struct UnresolvedField {
pub expr: InFile<AstPtr<ast::Expr>>, pub expr: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
pub receiver: Type, pub receiver: Type,
pub name: Name, pub name: Name,
pub method_with_same_name_exists: bool, pub method_with_same_name_exists: bool,
@ -248,7 +249,7 @@ pub struct UnresolvedField {
#[derive(Debug)] #[derive(Debug)]
pub struct UnresolvedMethodCall { pub struct UnresolvedMethodCall {
pub expr: InFile<AstPtr<ast::Expr>>, pub expr: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
pub receiver: Type, pub receiver: Type,
pub name: Name, pub name: Name,
pub field_with_same_name: Option<Type>, pub field_with_same_name: Option<Type>,
@ -267,7 +268,7 @@ pub struct UnresolvedIdent {
#[derive(Debug)] #[derive(Debug)]
pub struct PrivateField { pub struct PrivateField {
pub expr: InFile<AstPtr<ast::Expr>>, pub expr: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
pub field: Field, pub field: Field,
} }
@ -302,7 +303,7 @@ pub struct ReplaceFilterMapNextWithFindMap {
#[derive(Debug)] #[derive(Debug)]
pub struct MismatchedArgCount { pub struct MismatchedArgCount {
pub call_expr: InFile<AstPtr<ast::Expr>>, pub call_expr: InFile<ExprOrPatPtr>,
pub expected: usize, pub expected: usize,
pub found: usize, pub found: usize,
} }
@ -395,13 +396,13 @@ pub struct RemoveUnnecessaryElse {
#[derive(Debug)] #[derive(Debug)]
pub struct CastToUnsized { pub struct CastToUnsized {
pub expr: InFile<AstPtr<ast::Expr>>, pub expr: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
pub cast_ty: Type, pub cast_ty: Type,
} }
#[derive(Debug)] #[derive(Debug)]
pub struct InvalidCast { pub struct InvalidCast {
pub expr: InFile<AstPtr<ast::Expr>>, pub expr: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
pub error: CastError, pub error: CastError,
pub expr_ty: Type, pub expr_ty: Type,
pub cast_ty: Type, pub cast_ty: Type,
@ -428,9 +429,7 @@ impl AnyDiagnostic {
.collect(); .collect();
let record = match record { let record = match record {
Either::Left(record_expr) => { Either::Left(record_expr) => source_map.expr_syntax(record_expr).ok()?,
source_map.expr_syntax(record_expr).ok()?.map(AstPtr::wrap_left)
}
Either::Right(record_pat) => source_map.pat_syntax(record_pat).ok()?, Either::Right(record_pat) => source_map.pat_syntax(record_pat).ok()?,
}; };
let file = record.file_id; let file = record.file_id;
@ -474,7 +473,7 @@ impl AnyDiagnostic {
return Some( return Some(
ReplaceFilterMapNextWithFindMap { ReplaceFilterMapNextWithFindMap {
file: next_source_ptr.file_id, file: next_source_ptr.file_id,
next_expr: next_source_ptr.value, next_expr: next_source_ptr.value.cast()?,
} }
.into(), .into(),
); );
@ -484,7 +483,9 @@ impl AnyDiagnostic {
match source_map.expr_syntax(match_expr) { match source_map.expr_syntax(match_expr) {
Ok(source_ptr) => { Ok(source_ptr) => {
let root = source_ptr.file_syntax(db.upcast()); let root = source_ptr.file_syntax(db.upcast());
if let ast::Expr::MatchExpr(match_expr) = &source_ptr.value.to_node(&root) { if let Either::Left(ast::Expr::MatchExpr(match_expr)) =
&source_ptr.value.to_node(&root)
{
match match_expr.expr() { match match_expr.expr() {
Some(scrut_expr) if match_expr.match_arm_list().is_some() => { Some(scrut_expr) if match_expr.match_arm_list().is_some() => {
return Some( return Some(
@ -561,7 +562,7 @@ impl AnyDiagnostic {
let pat_syntax = let pat_syntax =
|pat| source_map.pat_syntax(pat).inspect_err(|_| stdx::never!("synthetic syntax")).ok(); |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).map(|it| it.map(AstPtr::wrap_left)), ExprOrPatId::ExprId(expr) => expr_syntax(expr),
ExprOrPatId::PatId(pat) => pat_syntax(pat), ExprOrPatId::PatId(pat) => pat_syntax(pat),
}; };
Some(match d { Some(match d {
@ -633,7 +634,7 @@ impl AnyDiagnostic {
&InferenceDiagnostic::UnresolvedIdent { id } => { &InferenceDiagnostic::UnresolvedIdent { id } => {
let node = match id { let node = match id {
ExprOrPatId::ExprId(id) => match source_map.expr_syntax(id) { ExprOrPatId::ExprId(id) => match source_map.expr_syntax(id) {
Ok(syntax) => syntax.map(|it| (it.wrap_left(), None)), Ok(syntax) => syntax.map(|it| (it, None)),
Err(SyntheticSyntax) => source_map Err(SyntheticSyntax) => source_map
.format_args_implicit_capture(id)? .format_args_implicit_capture(id)?
.map(|(node, range)| (node.wrap_left(), Some(range))), .map(|(node, range)| (node.wrap_left(), Some(range))),
@ -652,7 +653,7 @@ impl AnyDiagnostic {
} }
&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)?,
ExprOrPatId::PatId(pat) => { ExprOrPatId::PatId(pat) => {
let InFile { file_id, value } = pat_syntax(pat)?; let InFile { file_id, value } = pat_syntax(pat)?;

View file

@ -248,7 +248,7 @@ impl HasSource for Param {
let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?; let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?;
let root = db.parse_or_expand(file_id); let root = db.parse_or_expand(file_id);
match value.to_node(&root) { match value.to_node(&root) {
ast::Expr::ClosureExpr(it) => it Either::Left(ast::Expr::ClosureExpr(it)) => it
.param_list()? .param_list()?
.params() .params()
.nth(self.idx) .nth(self.idx)
@ -301,7 +301,7 @@ impl HasSource for InlineAsmOperand {
let root = src.file_syntax(db.upcast()); let root = src.file_syntax(db.upcast());
return src return src
.map(|ast| match ast.to_node(&root) { .map(|ast| match ast.to_node(&root) {
ast::Expr::AsmExpr(asm) => asm Either::Left(ast::Expr::AsmExpr(asm)) => asm
.asm_pieces() .asm_pieces()
.filter_map(|it| match it { .filter_map(|it| match it {
ast::AsmPiece::AsmOperandNamed(it) => Some(it), ast::AsmPiece::AsmOperandNamed(it) => Some(it),

View file

@ -1957,7 +1957,7 @@ impl DefWithBody {
ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right), ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right),
}; };
let expr_or_pat = match expr_or_pat { let expr_or_pat = match expr_or_pat {
Ok(Either::Left(expr)) => expr.map(AstPtr::wrap_left), Ok(Either::Left(expr)) => expr,
Ok(Either::Right(InFile { file_id, value: pat })) => { Ok(Either::Right(InFile { file_id, value: pat })) => {
// cast from Either<Pat, SelfParam> -> Either<_, Pat> // cast from Either<Pat, SelfParam> -> Either<_, Pat>
let Some(ptr) = AstPtr::try_from_raw(pat.syntax_node_ptr()) else { let Some(ptr) = AstPtr::try_from_raw(pat.syntax_node_ptr()) else {
@ -4592,10 +4592,7 @@ impl CaptureUsages {
match span { match span {
mir::MirSpan::ExprId(expr) => { mir::MirSpan::ExprId(expr) => {
if let Ok(expr) = source_map.expr_syntax(expr) { if let Ok(expr) = source_map.expr_syntax(expr) {
result.push(CaptureUsageSource { result.push(CaptureUsageSource { is_ref, source: expr })
is_ref,
source: expr.map(AstPtr::wrap_left),
})
} }
} }
mir::MirSpan::PatId(pat) => { mir::MirSpan::PatId(pat) => {

View file

@ -352,7 +352,7 @@ impl SourceToDefCtx<'_, '_> {
let src = src.cloned().map(ast::Pat::from); let src = src.cloned().map(ast::Pat::from);
let pat_id = source_map.node_pat(src.as_ref())?; let pat_id = source_map.node_pat(src.as_ref())?;
// the pattern could resolve to a constant, verify that this is not the case // the pattern could resolve to a constant, verify that this is not the case
if let crate::Pat::Bind { id, .. } = body[pat_id] { if let crate::Pat::Bind { id, .. } = body[pat_id.as_pat()?] {
Some((container, id)) Some((container, id))
} else { } else {
None None

View file

@ -142,7 +142,7 @@ impl SourceAnalyzer {
fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> { fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> {
// FIXME: macros, see `expr_id` // FIXME: macros, see `expr_id`
let src = InFile { file_id: self.file_id, value: pat }; let src = InFile { file_id: self.file_id, value: pat };
self.body_source_map()?.node_pat(src) self.body_source_map()?.node_pat(src).and_then(ExprOrPatId::as_pat)
} }
fn binding_id_of_pat(&self, pat: &ast::IdentPat) -> Option<BindingId> { fn binding_id_of_pat(&self, pat: &ast::IdentPat) -> Option<BindingId> {

View file

@ -40,7 +40,7 @@ pub(crate) fn mismatched_arg_count(
Diagnostic::new( Diagnostic::new(
DiagnosticCode::RustcHardError("E0107"), DiagnosticCode::RustcHardError("E0107"),
message, message,
invalid_args_range(ctx, d.call_expr.map(AstPtr::wrap_left), d.expected, d.found), invalid_args_range(ctx, d.call_expr, d.expected, d.found),
) )
} }

View file

@ -1,5 +1,6 @@
use std::iter; use std::iter;
use either::Either;
use hir::{db::ExpandDatabase, Adt, FileRange, HasSource, HirDisplay, InFile, Struct, Union}; use hir::{db::ExpandDatabase, Adt, FileRange, HasSource, HirDisplay, InFile, Struct, Union};
use ide_db::text_edit::TextEdit; use ide_db::text_edit::TextEdit;
use ide_db::{ use ide_db::{
@ -41,7 +42,7 @@ pub(crate) fn unresolved_field(
), ),
adjusted_display_range(ctx, d.expr, &|expr| { adjusted_display_range(ctx, d.expr, &|expr| {
Some( Some(
match expr { match expr.left()? {
ast::Expr::MethodCallExpr(it) => it.name_ref(), ast::Expr::MethodCallExpr(it) => it.name_ref(),
ast::Expr::FieldExpr(it) => it.name_ref(), ast::Expr::FieldExpr(it) => it.name_ref(),
_ => None, _ => None,
@ -72,7 +73,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option<Vec<A
fn field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option<Assist> { fn field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option<Assist> {
// Get the FileRange of the invalid field access // Get the FileRange of the invalid field access
let root = ctx.sema.db.parse_or_expand(d.expr.file_id); let root = ctx.sema.db.parse_or_expand(d.expr.file_id);
let expr = d.expr.value.to_node(&root); let expr = d.expr.value.to_node(&root).left()?;
let error_range = ctx.sema.original_range_opt(expr.syntax())?; let error_range = ctx.sema.original_range_opt(expr.syntax())?;
let field_name = d.name.as_str(); let field_name = d.name.as_str();
@ -263,7 +264,7 @@ fn record_field_layout(
// FIXME: We should fill out the call here, move the cursor and trigger signature help // FIXME: We should fill out the call here, move the cursor and trigger signature help
fn method_fix( fn method_fix(
ctx: &DiagnosticsContext<'_>, ctx: &DiagnosticsContext<'_>,
expr_ptr: &InFile<AstPtr<ast::Expr>>, expr_ptr: &InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
) -> Option<Assist> { ) -> Option<Assist> {
let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id); let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id);
let expr = expr_ptr.value.to_node(&root); let expr = expr_ptr.value.to_node(&root);

View file

@ -35,7 +35,7 @@ pub(crate) fn unresolved_method(
), ),
adjusted_display_range(ctx, d.expr, &|expr| { adjusted_display_range(ctx, d.expr, &|expr| {
Some( Some(
match expr { match expr.left()? {
ast::Expr::MethodCallExpr(it) => it.name_ref(), ast::Expr::MethodCallExpr(it) => it.name_ref(),
ast::Expr::FieldExpr(it) => it.name_ref(), ast::Expr::FieldExpr(it) => it.name_ref(),
_ => None, _ => None,
@ -85,7 +85,7 @@ fn field_fix(
let expr_ptr = &d.expr; let expr_ptr = &d.expr;
let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id); let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id);
let expr = expr_ptr.value.to_node(&root); let expr = expr_ptr.value.to_node(&root);
let (file_id, range) = match expr { let (file_id, range) = match expr.left()? {
ast::Expr::MethodCallExpr(mcall) => { ast::Expr::MethodCallExpr(mcall) => {
let FileRange { range, file_id } = let FileRange { range, file_id } =
ctx.sema.original_range_opt(mcall.receiver()?.syntax())?; ctx.sema.original_range_opt(mcall.receiver()?.syntax())?;
@ -117,7 +117,7 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -
let expr_ptr = &d.expr; let expr_ptr = &d.expr;
let root = db.parse_or_expand(expr_ptr.file_id); let root = db.parse_or_expand(expr_ptr.file_id);
let expr: ast::Expr = expr_ptr.value.to_node(&root); let expr: ast::Expr = expr_ptr.value.to_node(&root).left()?;
let call = ast::MethodCallExpr::cast(expr.syntax().clone())?; let call = ast::MethodCallExpr::cast(expr.syntax().clone())?;
let range = InFile::new(expr_ptr.file_id, call.syntax().text_range()) let range = InFile::new(expr_ptr.file_id, call.syntax().text_range())