From c1fe505f2ba8b106acaa220bca7a6ceeb5a602e2 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 7 Jan 2025 22:57:40 +0100 Subject: [PATCH 01/10] Make Pat::Range's start and end Option --- crates/hir-def/src/body.rs | 10 ++-- crates/hir-def/src/body/lower.rs | 46 +++++++++++++------ crates/hir-def/src/body/pretty.rs | 4 +- crates/hir-def/src/hir.rs | 4 +- crates/hir-ty/src/diagnostics/expr.rs | 4 +- .../hir-ty/src/mir/lower/pattern_matching.rs | 6 ++- 6 files changed, 48 insertions(+), 26 deletions(-) diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs index de4392493063..7e35ca4958c3 100644 --- a/crates/hir-def/src/body.rs +++ b/crates/hir-def/src/body.rs @@ -133,9 +133,9 @@ pub struct BodySourceMap { // AST expressions can create patterns in destructuring assignments. Therefore, `ExprSource` can also map // to `PatId`, and `PatId` can also map to `ExprSource` (the other way around is unaffected). expr_map: FxHashMap, - expr_map_back: ArenaMap, + expr_map_back: ArenaMap, - pat_map: FxHashMap, + pat_map: FxHashMap, pat_map_back: ArenaMap, label_map: FxHashMap, @@ -738,12 +738,12 @@ impl Index for Body { impl BodySourceMap { pub fn expr_or_pat_syntax(&self, id: ExprOrPatId) -> Result { match id { - ExprOrPatId::ExprId(id) => self.expr_syntax(id).map(|it| it.map(AstPtr::wrap_left)), + ExprOrPatId::ExprId(id) => self.expr_syntax(id), ExprOrPatId::PatId(id) => self.pat_syntax(id), } } - pub fn expr_syntax(&self, expr: ExprId) -> Result { + pub fn expr_syntax(&self, expr: ExprId) -> Result { self.expr_map_back.get(expr).cloned().ok_or(SyntheticSyntax) } @@ -771,7 +771,7 @@ impl BodySourceMap { self.self_param } - pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option { + pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option { self.pat_map.get(&node.map(AstPtr::new)).cloned() } diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index 1327bb3ab59c..36053a026967 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -1716,23 +1716,32 @@ impl ExprCollector<'_> { self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| { this.collect_pat_opt(expanded_pat, binding_list) }); - self.source_map.pat_map.insert(src, pat); + self.source_map.pat_map.insert(src, pat.into()); return pat; } None => Pat::Missing, }, // FIXME: implement in a way that also builds source map and calculates assoc resolutions in type inference. ast::Pat::RangePat(p) => { - let mut range_part_lower = |p: Option| { - p.and_then(|it| match &it { - ast::Pat::LiteralPat(it) => { - Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0))) - } - pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => { - let subpat = self.collect_pat(pat.clone(), binding_list); - Some(Box::new(LiteralOrConst::Const(subpat))) + let mut range_part_lower = |p: Option| -> Option { + p.and_then(|it| { + let ptr = PatPtr::new(&it); + match &it { + ast::Pat::LiteralPat(it) => { + // Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0))) + Some(self.alloc_expr_from_pat( + Expr::Literal(pat_literal_to_hir(it)?.0), + ptr, + )) + } + pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => { + // let subpat = self.collect_pat(pat.clone(), binding_list); + // Some(Box::new(LiteralOrConst::Const(subpat))) + // TODO + Some(self.missing_expr()) + } + _ => None, } - _ => None, }) }; let start = range_part_lower(p.start()); @@ -1795,7 +1804,7 @@ impl ExprCollector<'_> { } }); if let Some(pat) = pat.left() { - self.source_map.pat_map.insert(src, pat); + self.source_map.pat_map.insert(src, pat.into()); } pat } @@ -2412,7 +2421,7 @@ impl ExprCollector<'_> { fn alloc_expr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId { let src = self.expander.in_file(ptr); let id = self.body.exprs.alloc(expr); - self.source_map.expr_map_back.insert(id, src); + self.source_map.expr_map_back.insert(id, src.map(AstPtr::wrap_left)); self.source_map.expr_map.insert(src, id.into()); id } @@ -2424,7 +2433,7 @@ impl ExprCollector<'_> { fn alloc_expr_desugared_with_ptr(&mut self, expr: Expr, ptr: ExprPtr) -> ExprId { let src = self.expander.in_file(ptr); let id = self.body.exprs.alloc(expr); - self.source_map.expr_map_back.insert(id, src); + self.source_map.expr_map_back.insert(id, src.map(AstPtr::wrap_left)); // We intentionally don't fill this as it could overwrite a non-desugared entry // self.source_map.expr_map.insert(src, id); id @@ -2448,11 +2457,20 @@ impl ExprCollector<'_> { self.source_map.pat_map_back.insert(id, src.map(AstPtr::wrap_left)); id } + + fn alloc_expr_from_pat(&mut self, expr: Expr, ptr: PatPtr) -> ExprId { + let src = self.expander.in_file(ptr); + let id = self.body.exprs.alloc(expr); + self.source_map.pat_map.insert(src, id.into()); + self.source_map.expr_map_back.insert(id, src.map(AstPtr::wrap_right)); + id + } + fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { let src = self.expander.in_file(ptr); let id = self.body.pats.alloc(pat); self.source_map.pat_map_back.insert(id, src.map(AstPtr::wrap_right)); - self.source_map.pat_map.insert(src, id); + self.source_map.pat_map.insert(src, id.into()); id } // FIXME: desugared pats don't have ptr, that's wrong and should be fixed somehow. diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs index 52b91b522a41..11b41f624082 100644 --- a/crates/hir-def/src/body/pretty.rs +++ b/crates/hir-def/src/body/pretty.rs @@ -656,11 +656,11 @@ impl Printer<'_> { } Pat::Range { start, end } => { if let Some(start) = start { - self.print_literal_or_const(start); + self.print_expr(*start); } w!(self, "..="); if let Some(end) = end { - self.print_literal_or_const(end); + self.print_expr(*end); } } Pat::Slice { prefix, slice, suffix } => { diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index 859634694302..bcba5c6a9cf7 100644 --- a/crates/hir-def/src/hir.rs +++ b/crates/hir-def/src/hir.rs @@ -574,8 +574,8 @@ pub enum Pat { ellipsis: bool, }, Range { - start: Option>, - end: Option>, + start: Option, + end: Option, }, Slice { prefix: Box<[PatId]>, diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs index 7f9f0c0de197..5e8f1619c42c 100644 --- a/crates/hir-ty/src/diagnostics/expr.rs +++ b/crates/hir-ty/src/diagnostics/expr.rs @@ -440,7 +440,9 @@ impl ExprValidator { return; }; let root = source_ptr.file_syntax(db.upcast()); - let ast::Expr::IfExpr(if_expr) = source_ptr.value.to_node(&root) else { + let either::Left(ast::Expr::IfExpr(if_expr)) = + source_ptr.value.to_node(&root) + else { return; }; let mut top_if_expr = if_expr; diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index 2ffea34c85a1..d78d15288adc 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -234,10 +234,12 @@ impl MirLowerCtx<'_> { }; if mode == MatchingMode::Check { if let Some(start) = start { - add_check(start, BinOp::Le)?; + // TODO + // add_check(start, BinOp::Le)?; } if let Some(end) = end { - add_check(end, BinOp::Ge)?; + // TODO + // add_check(end, BinOp::Ge)?; } } (current, current_else) From 7a78144502ed7cae87f4c2442ba4f58c2886db2b Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 8 Jan 2025 00:26:47 +0100 Subject: [PATCH 02/10] Make higher levels adapt Bodys exprs having ExprOrPatId values --- crates/hir/src/diagnostics.rs | 35 ++++++++++--------- crates/hir/src/has_source.rs | 4 +-- crates/hir/src/lib.rs | 7 ++-- crates/hir/src/semantics/source_to_def.rs | 2 +- crates/hir/src/source_analyzer.rs | 2 +- .../src/handlers/mismatched_arg_count.rs | 2 +- .../src/handlers/unresolved_field.rs | 7 ++-- .../src/handlers/unresolved_method.rs | 6 ++-- 8 files changed, 32 insertions(+), 33 deletions(-) diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index fc77d1889c88..8eec6497a1f7 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -6,6 +6,7 @@ use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_def::{ + body::ExprOrPatPtr, hir::ExprOrPatId, path::{hir_segment_to_ast_segment, ModPath}, type_ref::TypesSourceMap, @@ -115,14 +116,14 @@ diagnostics![ #[derive(Debug)] pub struct BreakOutsideOfLoop { - pub expr: InFile>, + pub expr: InFile>>, pub is_break: bool, pub bad_value_break: bool, } #[derive(Debug)] pub struct TypedHole { - pub expr: InFile>, + pub expr: InFile>>, pub expected: Type, } @@ -234,13 +235,13 @@ pub struct MismatchedTupleStructPatArgCount { #[derive(Debug)] pub struct ExpectedFunction { - pub call: InFile>, + pub call: InFile>>, pub found: Type, } #[derive(Debug)] pub struct UnresolvedField { - pub expr: InFile>, + pub expr: InFile>>, pub receiver: Type, pub name: Name, pub method_with_same_name_exists: bool, @@ -248,7 +249,7 @@ pub struct UnresolvedField { #[derive(Debug)] pub struct UnresolvedMethodCall { - pub expr: InFile>, + pub expr: InFile>>, pub receiver: Type, pub name: Name, pub field_with_same_name: Option, @@ -267,7 +268,7 @@ pub struct UnresolvedIdent { #[derive(Debug)] pub struct PrivateField { - pub expr: InFile>, + pub expr: InFile>>, pub field: Field, } @@ -296,7 +297,7 @@ pub struct ReplaceFilterMapNextWithFindMap { #[derive(Debug)] pub struct MismatchedArgCount { - pub call_expr: InFile>, + pub call_expr: InFile, pub expected: usize, pub found: usize, } @@ -389,13 +390,13 @@ pub struct RemoveUnnecessaryElse { #[derive(Debug)] pub struct CastToUnsized { - pub expr: InFile>, + pub expr: InFile>>, pub cast_ty: Type, } #[derive(Debug)] pub struct InvalidCast { - pub expr: InFile>, + pub expr: InFile>>, pub error: CastError, pub expr_ty: Type, pub cast_ty: Type, @@ -422,9 +423,7 @@ impl AnyDiagnostic { .collect(); let record = match record { - Either::Left(record_expr) => { - source_map.expr_syntax(record_expr).ok()?.map(AstPtr::wrap_left) - } + Either::Left(record_expr) => source_map.expr_syntax(record_expr).ok()?, Either::Right(record_pat) => source_map.pat_syntax(record_pat).ok()?, }; let file = record.file_id; @@ -468,7 +467,7 @@ impl AnyDiagnostic { return Some( ReplaceFilterMapNextWithFindMap { file: next_source_ptr.file_id, - next_expr: next_source_ptr.value, + next_expr: next_source_ptr.value.cast()?, } .into(), ); @@ -478,7 +477,9 @@ impl AnyDiagnostic { match source_map.expr_syntax(match_expr) { Ok(source_ptr) => { 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() { Some(scrut_expr) if match_expr.match_arm_list().is_some() => { return Some( @@ -555,7 +556,7 @@ impl AnyDiagnostic { 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).map(|it| it.map(AstPtr::wrap_left)), + ExprOrPatId::ExprId(expr) => expr_syntax(expr), ExprOrPatId::PatId(pat) => pat_syntax(pat), }; Some(match d { @@ -627,7 +628,7 @@ impl AnyDiagnostic { &InferenceDiagnostic::UnresolvedIdent { id } => { let node = match 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 .format_args_implicit_capture(id)? .map(|(node, range)| (node.wrap_left(), Some(range))), @@ -646,7 +647,7 @@ impl AnyDiagnostic { } &InferenceDiagnostic::MismatchedTupleStructPatArgCount { pat, expected, found } => { 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) => { let InFile { file_id, value } = pat_syntax(pat)?; diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index 82c90ac30101..a34b4980832c 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs @@ -248,7 +248,7 @@ impl HasSource for Param { let ast @ InFile { file_id, value } = source_map.expr_syntax(expr_id).ok()?; let root = db.parse_or_expand(file_id); match value.to_node(&root) { - ast::Expr::ClosureExpr(it) => it + Either::Left(ast::Expr::ClosureExpr(it)) => it .param_list()? .params() .nth(self.idx) @@ -301,7 +301,7 @@ impl HasSource for InlineAsmOperand { let root = src.file_syntax(db.upcast()); return src .map(|ast| match ast.to_node(&root) { - ast::Expr::AsmExpr(asm) => asm + Either::Left(ast::Expr::AsmExpr(asm)) => asm .asm_pieces() .filter_map(|it| match it { ast::AsmPiece::AsmOperandNamed(it) => Some(it), diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 4938478bb121..b3c19cba5c3a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1955,7 +1955,7 @@ impl DefWithBody { ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right), }; 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 })) => { // cast from Either -> Either<_, Pat> let Some(ptr) = AstPtr::try_from_raw(pat.syntax_node_ptr()) else { @@ -4540,10 +4540,7 @@ impl CaptureUsages { match span { mir::MirSpan::ExprId(expr) => { if let Ok(expr) = source_map.expr_syntax(expr) { - result.push(CaptureUsageSource { - is_ref, - source: expr.map(AstPtr::wrap_left), - }) + result.push(CaptureUsageSource { is_ref, source: expr }) } } mir::MirSpan::PatId(pat) => { diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index 3c9e7065c41d..29d3736bae72 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -352,7 +352,7 @@ impl SourceToDefCtx<'_, '_> { let src = src.cloned().map(ast::Pat::from); let pat_id = source_map.node_pat(src.as_ref())?; // 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)) } else { None diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index b699ccde4128..69310d3b034a 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -142,7 +142,7 @@ impl SourceAnalyzer { fn pat_id(&self, pat: &ast::Pat) -> Option { // FIXME: macros, see `expr_id` 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 { diff --git a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs index 7126617cdeed..0520bb3fe9b9 100644 --- a/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs +++ b/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs @@ -40,7 +40,7 @@ pub(crate) fn mismatched_arg_count( Diagnostic::new( DiagnosticCode::RustcHardError("E0107"), 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), ) } diff --git a/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/crates/ide-diagnostics/src/handlers/unresolved_field.rs index 4accd181ca43..dfb03eee732a 100644 --- a/crates/ide-diagnostics/src/handlers/unresolved_field.rs +++ b/crates/ide-diagnostics/src/handlers/unresolved_field.rs @@ -1,5 +1,6 @@ use std::iter; +use either::Either; use hir::{db::ExpandDatabase, Adt, FileRange, HasSource, HirDisplay, InFile, Struct, Union}; use ide_db::text_edit::TextEdit; use ide_db::{ @@ -41,7 +42,7 @@ pub(crate) fn unresolved_field( ), adjusted_display_range(ctx, d.expr, &|expr| { Some( - match expr { + match expr.left()? { ast::Expr::MethodCallExpr(it) => it.name_ref(), ast::Expr::FieldExpr(it) => it.name_ref(), _ => None, @@ -72,7 +73,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option, d: &hir::UnresolvedField) -> Option { // Get the FileRange of the invalid field access 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 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 fn method_fix( ctx: &DiagnosticsContext<'_>, - expr_ptr: &InFile>, + expr_ptr: &InFile>>, ) -> Option { let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id); let expr = expr_ptr.value.to_node(&root); diff --git a/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/crates/ide-diagnostics/src/handlers/unresolved_method.rs index 4ab649cc1628..dd1b593e8f6e 100644 --- a/crates/ide-diagnostics/src/handlers/unresolved_method.rs +++ b/crates/ide-diagnostics/src/handlers/unresolved_method.rs @@ -35,7 +35,7 @@ pub(crate) fn unresolved_method( ), adjusted_display_range(ctx, d.expr, &|expr| { Some( - match expr { + match expr.left()? { ast::Expr::MethodCallExpr(it) => it.name_ref(), ast::Expr::FieldExpr(it) => it.name_ref(), _ => None, @@ -85,7 +85,7 @@ fn field_fix( let expr_ptr = &d.expr; let root = ctx.sema.db.parse_or_expand(expr_ptr.file_id); 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) => { let FileRange { range, file_id } = 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 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 range = InFile::new(expr_ptr.file_id, call.syntax().text_range()) From 06a37cc411d2a6c1ca643eb993ff240eee7d2d82 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Wed, 8 Jan 2025 00:48:25 +0100 Subject: [PATCH 03/10] Add a test to monitor whats going on --- crates/hir-def/src/body/lower.rs | 17 ++++++++----- crates/hir-def/src/body/tests.rs | 43 ++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index 36053a026967..af849a6f0735 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -41,8 +41,8 @@ use crate::{ FormatPlaceholder, FormatSign, FormatTrait, }, Array, Binding, BindingAnnotation, BindingId, BindingProblems, CaptureBy, ClosureKind, - Expr, ExprId, Item, Label, LabelId, Literal, LiteralOrConst, MatchArm, Movability, - OffsetOf, Pat, PatId, RecordFieldPat, RecordLitField, Statement, + Expr, ExprId, Item, Label, LabelId, Literal, MatchArm, Movability, OffsetOf, Pat, PatId, + RecordFieldPat, RecordLitField, Statement, }, item_scope::BuiltinShadowMode, lang_item::LangItem, @@ -1734,10 +1734,15 @@ impl ExprCollector<'_> { ptr, )) } - pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => { - // let subpat = self.collect_pat(pat.clone(), binding_list); - // Some(Box::new(LiteralOrConst::Const(subpat))) - // TODO + ast::Pat::IdentPat(_) => Some(self.missing_expr()), + ast::Pat::PathPat(p) => { + if let Some(path) = p.path() { + if let Some(parsed) = self.parse_path(path) { + return Some( + self.alloc_expr_from_pat(Expr::Path(parsed), ptr), + ); + } + } Some(self.missing_expr()) } _ => None, diff --git a/crates/hir-def/src/body/tests.rs b/crates/hir-def/src/body/tests.rs index edc7c4c1f211..1e968725fbbb 100644 --- a/crates/hir-def/src/body/tests.rs +++ b/crates/hir-def/src/body/tests.rs @@ -459,3 +459,46 @@ async fn foo(a: (), b: i32) -> u32 { expect!["fn foo(�: (), �: i32) -> impl ::core::future::Future:: �"] .assert_eq(&printed); } + +fn abc() { + let (db, body, owner) = lower( + r#" +pub const L: i32 = 6; +mod x { + pub const R: i32 = 100; +} +const fn f(x: i32) -> i32 { + match x { + -1..=5 => x * 10, + L..=x::R => x * 100, + _ => x, + } +}"#, + ); + + for (pat_id, pat) in body.pats.iter() { + match pat { + Pat::Range { start, end } => { + let pretty = body.pretty_print_pat(&db, owner, pat_id, false, Edition::Edition2021); + eprintln!("RANGE {}", pretty); + + if let Some(start) = start { + eprintln!("START"); + let expr = body.exprs[*start].clone(); + dbg!(expr); + } else { + eprintln!("START is None"); + } + + if let Some(end) = end { + eprintln!("END"); + let expr = body.exprs[*end].clone(); + dbg!(expr); + } else { + eprintln!("END is None"); + } + } + _ => {} + } + } +} From d064cd28ac38f30c92fe281e302af1b65cc4fe57 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Sun, 19 Jan 2025 23:58:49 +0100 Subject: [PATCH 04/10] Lower ast::Ident to hir::Path when lowering RangePats --- crates/hir-def/src/body/lower.rs | 41 +++++---- crates/hir-def/src/body/pretty.rs | 12 +-- crates/hir-def/src/body/tests.rs | 84 ++++++++++++++++++- crates/hir-ty/src/mir/lower.rs | 29 +++---- .../hir-ty/src/mir/lower/pattern_matching.rs | 10 +-- 5 files changed, 122 insertions(+), 54 deletions(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index af849a6f0735..c39f3dad379d 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -1727,24 +1727,33 @@ impl ExprCollector<'_> { p.and_then(|it| { let ptr = PatPtr::new(&it); match &it { - ast::Pat::LiteralPat(it) => { - // Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0))) - Some(self.alloc_expr_from_pat( - Expr::Literal(pat_literal_to_hir(it)?.0), - ptr, - )) - } - ast::Pat::IdentPat(_) => Some(self.missing_expr()), - ast::Pat::PathPat(p) => { - if let Some(path) = p.path() { - if let Some(parsed) = self.parse_path(path) { - return Some( - self.alloc_expr_from_pat(Expr::Path(parsed), ptr), - ); - } + ast::Pat::LiteralPat(it) => Some(self.alloc_expr_from_pat( + Expr::Literal(pat_literal_to_hir(it)?.0), + ptr, + )), + ast::Pat::IdentPat(ident) => { + if ident.is_simple_ident() { + return ident + .name() + .and_then(|name| Some(name.as_name())) + .and_then(|hir_name| { + self.alloc_binding( + hir_name.clone(), + BindingAnnotation::Unannotated, + ); + Some(Path::from(hir_name)) + }) + .and_then(|path| { + Some(self.alloc_expr_from_pat(Expr::Path(path), ptr)) + }); } - Some(self.missing_expr()) + + None } + ast::Pat::PathPat(p) => p + .path() + .and_then(|path| self.parse_path(path)) + .map(|parsed| self.alloc_expr_from_pat(Expr::Path(parsed), ptr)), _ => None, } }) diff --git a/crates/hir-def/src/body/pretty.rs b/crates/hir-def/src/body/pretty.rs index 11b41f624082..d5562c859445 100644 --- a/crates/hir-def/src/body/pretty.rs +++ b/crates/hir-def/src/body/pretty.rs @@ -6,10 +6,7 @@ use itertools::Itertools; use span::Edition; use crate::{ - hir::{ - Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, LiteralOrConst, Movability, - Statement, - }, + hir::{Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement}, pretty::{print_generic_args, print_path, print_type_ref}, }; @@ -757,13 +754,6 @@ impl Printer<'_> { } } - fn print_literal_or_const(&mut self, literal_or_const: &LiteralOrConst) { - match literal_or_const { - LiteralOrConst::Literal(l) => self.print_literal(l), - LiteralOrConst::Const(c) => self.print_pat(*c), - } - } - fn print_literal(&mut self, literal: &Literal) { match literal { Literal::String(it) => w!(self, "{:?}", it), diff --git a/crates/hir-def/src/body/tests.rs b/crates/hir-def/src/body/tests.rs index 1e968725fbbb..c9e0a8933558 100644 --- a/crates/hir-def/src/body/tests.rs +++ b/crates/hir-def/src/body/tests.rs @@ -445,7 +445,6 @@ fn foo() { ); } -#[test] fn skip_skips_body() { let (db, body, owner) = lower( r#" @@ -460,7 +459,7 @@ async fn foo(a: (), b: i32) -> u32 { .assert_eq(&printed); } -fn abc() { +fn test1() { let (db, body, owner) = lower( r#" pub const L: i32 = 6; @@ -469,8 +468,46 @@ mod x { } const fn f(x: i32) -> i32 { match x { - -1..=5 => x * 10, L..=x::R => x * 100, + -1..=5 => x * 10, + _ => x, + } +}"#, + ); + + let pat = body + .pats + .iter() + .find_map(|pat| { + if let Pat::Range { .. } = pat.1 { + return Some(pat.1); + } + + None + }) + .unwrap(); + + match pat { + Pat::Range { start, end } => { + dbg!(&body.exprs[start.unwrap()]); + dbg!(&body.exprs[end.unwrap()]); + } + _ => {} + } +} + +#[test] +fn test2() { + let (db, body, owner) = lower( + r#" +pub const L: i32 = 6; +mod x { + pub const R: i32 = 100; +} +const fn f(x: i32) -> i32 { + match x { + -1..=5 => x * 10, + ::std::i32::MIN..=x::R => x * 100, _ => x, } }"#, @@ -502,3 +539,44 @@ const fn f(x: i32) -> i32 { } } } + +#[test] +fn test3() { + let (db, body, owner) = lower( + r#" +const A: u32 = 0; + +fn bar(v: u32) { + match v { + 0..=A => {} + _ => {} + } +}"#, + ); + + for (pat_id, pat) in body.pats.iter() { + match pat { + Pat::Range { start, end } => { + let pretty = body.pretty_print_pat(&db, owner, pat_id, false, Edition::Edition2021); + eprintln!("RANGE {}", pretty); + + if let Some(start) = start { + eprintln!("START"); + let expr = body.exprs[*start].clone(); + dbg!(expr); + } else { + eprintln!("START is None"); + } + + if let Some(end) = end { + eprintln!("END"); + let expr = body.exprs[*end].clone(); + dbg!(expr); + } else { + eprintln!("END is None"); + } + } + _ => {} + } + } +} diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index 1d1044df6e96..df39b4faad15 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -8,8 +8,8 @@ use hir_def::{ body::{Body, HygieneId}, data::adt::{StructKind, VariantData}, hir::{ - ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal, - LiteralOrConst, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField, + ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal, MatchArm, + Pat, PatId, RecordFieldPat, RecordLitField, }, lang_item::{LangItem, LangItemTarget}, path::Path, @@ -1358,20 +1358,10 @@ impl<'ctx> MirLowerCtx<'ctx> { Ok(()) } - fn lower_literal_or_const_to_operand( - &mut self, - ty: Ty, - loc: &LiteralOrConst, - ) -> Result { - match loc { - LiteralOrConst::Literal(l) => self.lower_literal_to_operand(ty, l), - LiteralOrConst::Const(c) => { - let c = match &self.body.pats[*c] { - Pat::Path(p) => p, - _ => not_supported!( - "only `char` and numeric types are allowed in range patterns" - ), - }; + fn lower_literal_or_const_to_operand(&mut self, ty: Ty, loc: &ExprId) -> Result { + match dbg!(&self.body.exprs[*loc]) { + Expr::Literal(l) => self.lower_literal_to_operand(ty, l), + Expr::Path(c) => { let edition = self.edition(); let unresolved_name = || MirLowerError::unresolved_path(self.db, c, edition, &self.body.types); @@ -1379,7 +1369,7 @@ impl<'ctx> MirLowerCtx<'ctx> { .resolver .resolve_path_in_value_ns(self.db.upcast(), c, HygieneId::ROOT) .ok_or_else(unresolved_name)?; - match pr { + dbg!(match dbg!(pr) { ResolveValueResult::ValueNs(v, _) => { if let ValueNs::ConstId(c) = v { self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty) @@ -1390,7 +1380,10 @@ impl<'ctx> MirLowerCtx<'ctx> { ResolveValueResult::Partial(_, _, _) => { not_supported!("associated constants in range pattern") } - } + }) + } + _ => { + not_supported!("only `char` and numeric types are allowed in range patterns"); } } } diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs index d78d15288adc..289175feefb1 100644 --- a/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -1,6 +1,6 @@ //! MIR lowering for patterns -use hir_def::{hir::LiteralOrConst, AssocItemId}; +use hir_def::{hir::ExprId, AssocItemId}; use crate::{ mir::{ @@ -207,7 +207,7 @@ impl MirLowerCtx<'_> { )? } Pat::Range { start, end } => { - let mut add_check = |l: &LiteralOrConst, binop| -> Result<()> { + let mut add_check = |l: &ExprId, binop| -> Result<()> { let lv = self.lower_literal_or_const_to_operand(self.infer[pattern].clone(), l)?; let else_target = *current_else.get_or_insert_with(|| self.new_basic_block()); @@ -234,12 +234,10 @@ impl MirLowerCtx<'_> { }; if mode == MatchingMode::Check { if let Some(start) = start { - // TODO - // add_check(start, BinOp::Le)?; + add_check(start, BinOp::Le)?; } if let Some(end) = end { - // TODO - // add_check(end, BinOp::Ge)?; + add_check(end, BinOp::Ge)?; } } (current, current_else) From 75365abc29849225992ea10f6c2447222717e2ce Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 18:49:16 +0100 Subject: [PATCH 05/10] Finish up --- crates/hir-def/src/body/lower.rs | 8 +------- crates/hir-def/src/body/tests.rs | 4 +++- crates/hir-def/src/hir.rs | 14 ++++++++++++++ crates/hir/src/semantics.rs | 1 + crates/hir/src/semantics/source_to_def.rs | 2 +- crates/ide-db/src/defs.rs | 6 ++++-- 6 files changed, 24 insertions(+), 11 deletions(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index c39f3dad379d..6b6417d17f92 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -1736,13 +1736,7 @@ impl ExprCollector<'_> { return ident .name() .and_then(|name| Some(name.as_name())) - .and_then(|hir_name| { - self.alloc_binding( - hir_name.clone(), - BindingAnnotation::Unannotated, - ); - Some(Path::from(hir_name)) - }) + .and_then(|hir_name| Some(Path::from(hir_name))) .and_then(|path| { Some(self.alloc_expr_from_pat(Expr::Path(path), ptr)) }); diff --git a/crates/hir-def/src/body/tests.rs b/crates/hir-def/src/body/tests.rs index c9e0a8933558..4efc71f4392a 100644 --- a/crates/hir-def/src/body/tests.rs +++ b/crates/hir-def/src/body/tests.rs @@ -1,9 +1,11 @@ mod block; +use base_db::Upcast; use expect_test::{expect, Expect}; use test_fixture::WithFixture; +use tracing::Instrument; -use crate::{test_db::TestDB, ModuleDefId}; +use crate::{db::InternDatabase, test_db::TestDB, ModuleDefId}; use super::*; diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index bcba5c6a9cf7..019f10a59552 100644 --- a/crates/hir-def/src/hir.rs +++ b/crates/hir-def/src/hir.rs @@ -58,12 +58,26 @@ impl ExprOrPatId { } } + pub fn is_expr(&self) -> bool { + match self { + Self::ExprId(_) => true, + _ => false, + } + } + pub fn as_pat(self) -> Option { match self { Self::PatId(v) => Some(v), _ => None, } } + + pub fn is_pat(&self) -> bool { + match self { + Self::PatId(_) => true, + _ => false, + } + } } stdx::impl_from!(ExprId, PatId for ExprOrPatId); diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 09470bed9cfb..d8a1a7939b2a 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -1640,6 +1640,7 @@ impl<'db> SemanticsImpl<'db> { } pub fn to_def(&self, src: &T) -> Option { + dbg!(std::any::type_name::()); let src = self.find_file(src.syntax()).with_value(src); T::to_def(self, src) } diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index 29d3736bae72..227a60bee242 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -347,7 +347,7 @@ impl SourceToDefCtx<'_, '_> { &mut self, src: InFile<&ast::IdentPat>, ) -> Option<(DefWithBodyId, BindingId)> { - let container = self.find_pat_or_label_container(src.syntax_ref())?; + let container = dbg!(self.find_pat_or_label_container(src.syntax_ref()))?; let (body, source_map) = self.db.body_with_source_map(container); let src = src.cloned().map(ast::Pat::from); let pat_id = source_map.node_pat(src.as_ref())?; diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index d12bda0816fd..00f190e86743 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -20,6 +20,7 @@ use hir::{ }; use span::Edition; use stdx::{format_to, impl_from}; +use syntax::ToSmolStr; use syntax::{ ast::{self, AstNode}, match_ast, SyntaxKind, SyntaxNode, SyntaxToken, @@ -365,6 +366,7 @@ impl IdentClass { sema: &Semantics<'_, RootDatabase>, node: &SyntaxNode, ) -> Option { + dbg!(&node.to_smolstr()); match_ast! { match node { ast::Name(name) => NameClass::classify(sema, &name).map(IdentClass::NameClass), @@ -521,7 +523,7 @@ impl NameClass { let definition = match_ast! { match parent { ast::Item(it) => classify_item(sema, it)?, - ast::IdentPat(it) => return classify_ident_pat(sema, it), + ast::IdentPat(it) => return dbg!(classify_ident_pat(sema, it)), ast::Rename(it) => classify_rename(sema, it)?, ast::SelfParam(it) => Definition::Local(sema.to_def(&it)?), ast::RecordField(it) => Definition::Field(sema.to_def(&it)?), @@ -574,7 +576,7 @@ impl NameClass { return Some(NameClass::ConstReference(Definition::from(def))); } - let local = sema.to_def(&ident_pat)?; + let local = dbg!(sema.to_def(&ident_pat))?; let pat_parent = ident_pat.syntax().parent(); if let Some(record_pat_field) = pat_parent.and_then(ast::RecordPatField::cast) { if record_pat_field.name_ref().is_none() { From 0fa0e1d9cb15e0eb7e8f78bc13fb6dc3123d4f10 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 18:53:37 +0100 Subject: [PATCH 06/10] make SourceAnalyzer::pat_id return ExprOrPatId Not all patterns are mapped to Pats. As such, it was necessary to change the ret type Option to Option --- crates/hir-def/src/body/tests.rs | 5 +---- crates/hir/src/source_analyzer.rs | 32 ++++++++++++++++--------------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/crates/hir-def/src/body/tests.rs b/crates/hir-def/src/body/tests.rs index 4efc71f4392a..7658b88e5fd8 100644 --- a/crates/hir-def/src/body/tests.rs +++ b/crates/hir-def/src/body/tests.rs @@ -1,11 +1,8 @@ mod block; -use base_db::Upcast; +use crate::{test_db::TestDB, ModuleDefId}; use expect_test::{expect, Expect}; use test_fixture::WithFixture; -use tracing::Instrument; - -use crate::{db::InternDatabase, test_db::TestDB, ModuleDefId}; use super::*; diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 69310d3b034a..a86e3e8f842c 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -18,7 +18,7 @@ use hir_def::{ scope::{ExprScopes, ScopeId}, Body, BodySourceMap, HygieneId, }, - hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat, PatId}, + hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat}, lang_item::LangItem, lower::LowerCtx, nameres::MacroSubNs, @@ -139,15 +139,15 @@ impl SourceAnalyzer { sm.node_expr(src.as_ref()) } - fn pat_id(&self, pat: &ast::Pat) -> Option { + fn pat_id(&self, pat: &ast::Pat) -> Option { // FIXME: macros, see `expr_id` let src = InFile { file_id: self.file_id, value: pat }; - self.body_source_map()?.node_pat(src).and_then(ExprOrPatId::as_pat) + self.body_source_map()?.node_pat(src) } fn binding_id_of_pat(&self, pat: &ast::IdentPat) -> Option { let pat_id = self.pat_id(&pat.clone().into())?; - if let Pat::Bind { id, .. } = self.body()?.pats[pat_id] { + if let Pat::Bind { id, .. } = self.body()?.pats[pat_id.as_pat()?] { Some(id) } else { None @@ -212,8 +212,10 @@ impl SourceAnalyzer { ) -> Option<(Type, Option)> { let pat_id = self.pat_id(pat)?; let infer = self.infer.as_ref()?; - let coerced = - infer.pat_adjustments.get(&pat_id).and_then(|adjusts| adjusts.last().cloned()); + let coerced = infer + .pat_adjustments + .get(&pat_id.as_pat()?) + .and_then(|adjusts| adjusts.last().cloned()); let ty = infer[pat_id].clone(); let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty); Some((mk_ty(ty), coerced.map(mk_ty))) @@ -248,7 +250,7 @@ impl SourceAnalyzer { ) -> Option { let id = self.pat_id(&pat.clone().into())?; let infer = self.infer.as_ref()?; - infer.binding_modes.get(id).map(|bm| match bm { + infer.binding_modes.get(id.as_pat()?).map(|bm| match bm { hir_ty::BindingMode::Move => BindingMode::Move, hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut), hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => { @@ -266,7 +268,7 @@ impl SourceAnalyzer { Some( infer .pat_adjustments - .get(&pat_id)? + .get(&pat_id.as_pat()?)? .iter() .map(|ty| Type::new_with_resolver(db, &self.resolver, ty.clone())) .collect(), @@ -649,10 +651,10 @@ impl SourceAnalyzer { let field_name = field.field_name()?.as_name(); let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?; let pat_id = self.pat_id(&record_pat.into())?; - let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id)?; + let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id.as_pat()?)?; let variant_data = variant.variant_data(db.upcast()); let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? }; - let (adt, subst) = self.infer.as_ref()?.type_of_pat.get(pat_id)?.as_adt()?; + let (adt, subst) = self.infer.as_ref()?.type_of_pat.get(pat_id.as_pat()?)?.as_adt()?; let field_ty = db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst); Some(( @@ -684,7 +686,7 @@ impl SourceAnalyzer { ) -> Option { let pat_id = self.pat_id(&pat.clone().into())?; let body = self.body()?; - let path = match &body[pat_id] { + let path = match &body[pat_id.as_pat()?] { Pat::Path(path) => path, _ => return None, }; @@ -783,7 +785,7 @@ impl SourceAnalyzer { prefer_value_ns = true; } else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) { let pat_id = self.pat_id(&path_pat.into())?; - if let Some((assoc, subs)) = infer.assoc_resolutions_for_pat(pat_id) { + if let Some((assoc, subs)) = infer.assoc_resolutions_for_pat(pat_id.as_pat()?) { let (assoc, subst) = match assoc { AssocItemId::ConstId(const_id) => { let (konst, subst) = @@ -807,7 +809,7 @@ impl SourceAnalyzer { return Some((PathResolution::Def(AssocItem::from(assoc).into()), Some(subst))); } if let Some(VariantId::EnumVariantId(variant)) = - infer.variant_resolution_for_pat(pat_id) + infer.variant_resolution_for_pat(pat_id.as_pat()?) { return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None)); } @@ -824,7 +826,7 @@ impl SourceAnalyzer { || parent().and_then(ast::TupleStructPat::cast).map(ast::Pat::from); if let Some(pat) = record_pat.or_else(tuple_struct_pat) { let pat_id = self.pat_id(&pat)?; - let variant_res_for_pat = infer.variant_resolution_for_pat(pat_id); + let variant_res_for_pat = infer.variant_resolution_for_pat(pat_id.as_pat()?); if let Some(VariantId::EnumVariantId(variant)) = variant_res_for_pat { return Some(( PathResolution::Def(ModuleDef::Variant(variant.into())), @@ -1043,7 +1045,7 @@ impl SourceAnalyzer { let body = self.body()?; let infer = self.infer.as_ref()?; - let pat_id = self.pat_id(&pattern.clone().into())?; + let pat_id = self.pat_id(&pattern.clone().into())?.as_pat()?; let substs = infer.type_of_pat[pat_id].as_adt()?.1; let (variant, missing_fields, _exhaustive) = From 7d3e36aaae060dd2fd6f7fc3dcb247baab8c4ad0 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 19:21:41 +0100 Subject: [PATCH 07/10] resolve_bind_pat_to_const does not early return if expr --- crates/hir-def/src/body/tests.rs | 112 +++++------------------------- crates/hir/src/source_analyzer.rs | 15 +++- 2 files changed, 28 insertions(+), 99 deletions(-) diff --git a/crates/hir-def/src/body/tests.rs b/crates/hir-def/src/body/tests.rs index 7658b88e5fd8..cf4c169e78cf 100644 --- a/crates/hir-def/src/body/tests.rs +++ b/crates/hir-def/src/body/tests.rs @@ -1,6 +1,6 @@ mod block; -use crate::{test_db::TestDB, ModuleDefId}; +use crate::{hir::MatchArm, test_db::TestDB, ModuleDefId}; use expect_test::{expect, Expect}; use test_fixture::WithFixture; @@ -458,8 +458,9 @@ async fn foo(a: (), b: i32) -> u32 { .assert_eq(&printed); } -fn test1() { - let (db, body, owner) = lower( +#[test] +fn range_bounds_are_hir_exprs() { + let (_, body, _) = lower( r#" pub const L: i32 = 6; mod x { @@ -467,115 +468,34 @@ mod x { } const fn f(x: i32) -> i32 { match x { - L..=x::R => x * 100, -1..=5 => x * 10, + L..=x::R => x * 100, _ => x, } }"#, ); - let pat = body - .pats + let mtch_arms = body + .exprs .iter() - .find_map(|pat| { - if let Pat::Range { .. } = pat.1 { - return Some(pat.1); + .find_map(|(_, expr)| { + if let Expr::Match { arms, .. } = expr { + return Some(arms); } None }) .unwrap(); - match pat { + let MatchArm { pat, .. } = mtch_arms[1]; + match body.pats[pat] { Pat::Range { start, end } => { - dbg!(&body.exprs[start.unwrap()]); - dbg!(&body.exprs[end.unwrap()]); - } - _ => {} - } -} - -#[test] -fn test2() { - let (db, body, owner) = lower( - r#" -pub const L: i32 = 6; -mod x { - pub const R: i32 = 100; -} -const fn f(x: i32) -> i32 { - match x { - -1..=5 => x * 10, - ::std::i32::MIN..=x::R => x * 100, - _ => x, - } -}"#, - ); + let hir_start = &body.exprs[start.unwrap()]; + let hir_end = &body.exprs[end.unwrap()]; - for (pat_id, pat) in body.pats.iter() { - match pat { - Pat::Range { start, end } => { - let pretty = body.pretty_print_pat(&db, owner, pat_id, false, Edition::Edition2021); - eprintln!("RANGE {}", pretty); - - if let Some(start) = start { - eprintln!("START"); - let expr = body.exprs[*start].clone(); - dbg!(expr); - } else { - eprintln!("START is None"); - } - - if let Some(end) = end { - eprintln!("END"); - let expr = body.exprs[*end].clone(); - dbg!(expr); - } else { - eprintln!("END is None"); - } - } - _ => {} + assert!(matches!(hir_start, Expr::Path { .. })); + assert!(matches!(hir_end, Expr::Path { .. })); } - } -} - -#[test] -fn test3() { - let (db, body, owner) = lower( - r#" -const A: u32 = 0; - -fn bar(v: u32) { - match v { - 0..=A => {} _ => {} } -}"#, - ); - - for (pat_id, pat) in body.pats.iter() { - match pat { - Pat::Range { start, end } => { - let pretty = body.pretty_print_pat(&db, owner, pat_id, false, Edition::Edition2021); - eprintln!("RANGE {}", pretty); - - if let Some(start) = start { - eprintln!("START"); - let expr = body.exprs[*start].clone(); - dbg!(expr); - } else { - eprintln!("START is None"); - } - - if let Some(end) = end { - eprintln!("END"); - let expr = body.exprs[*end].clone(); - dbg!(expr); - } else { - eprintln!("END is None"); - } - } - _ => {} - } - } } diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index a86e3e8f842c..37c7489c16d0 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -686,10 +686,19 @@ impl SourceAnalyzer { ) -> Option { let pat_id = self.pat_id(&pat.clone().into())?; let body = self.body()?; - let path = match &body[pat_id.as_pat()?] { - Pat::Path(path) => path, - _ => return None, + + let path = if pat_id.is_pat() { + match &body[pat_id.as_pat()?] { + Pat::Path(path) => path, + _ => return None, + } + } else { + match &body[pat_id.as_expr()?] { + Expr::Path(path) => path, + _ => return None, + } }; + let res = resolve_hir_path(db, &self.resolver, path, HygieneId::ROOT, TypesMap::EMPTY)?; match res { PathResolution::Def(def) => Some(def), From 30298e86f2d3f413ccd5e7ab98f9ff2cedf9510f Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 19:30:41 +0100 Subject: [PATCH 08/10] Remove dbg lines --- crates/hir/src/semantics.rs | 1 - crates/ide-db/src/defs.rs | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index d8a1a7939b2a..09470bed9cfb 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -1640,7 +1640,6 @@ impl<'db> SemanticsImpl<'db> { } pub fn to_def(&self, src: &T) -> Option { - dbg!(std::any::type_name::()); let src = self.find_file(src.syntax()).with_value(src); T::to_def(self, src) } diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs index 00f190e86743..d12bda0816fd 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -20,7 +20,6 @@ use hir::{ }; use span::Edition; use stdx::{format_to, impl_from}; -use syntax::ToSmolStr; use syntax::{ ast::{self, AstNode}, match_ast, SyntaxKind, SyntaxNode, SyntaxToken, @@ -366,7 +365,6 @@ impl IdentClass { sema: &Semantics<'_, RootDatabase>, node: &SyntaxNode, ) -> Option { - dbg!(&node.to_smolstr()); match_ast! { match node { ast::Name(name) => NameClass::classify(sema, &name).map(IdentClass::NameClass), @@ -523,7 +521,7 @@ impl NameClass { let definition = match_ast! { match parent { ast::Item(it) => classify_item(sema, it)?, - ast::IdentPat(it) => return dbg!(classify_ident_pat(sema, it)), + ast::IdentPat(it) => return classify_ident_pat(sema, it), ast::Rename(it) => classify_rename(sema, it)?, ast::SelfParam(it) => Definition::Local(sema.to_def(&it)?), ast::RecordField(it) => Definition::Field(sema.to_def(&it)?), @@ -576,7 +574,7 @@ impl NameClass { return Some(NameClass::ConstReference(Definition::from(def))); } - let local = dbg!(sema.to_def(&ident_pat))?; + let local = sema.to_def(&ident_pat)?; let pat_parent = ident_pat.syntax().parent(); if let Some(record_pat_field) = pat_parent.and_then(ast::RecordPatField::cast) { if record_pat_field.name_ref().is_none() { From 06dd82dc5adbb7acb95839b128ea693e27d58b62 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 21:14:16 +0100 Subject: [PATCH 09/10] Remove fixme and add a missing test attribute --- crates/hir-def/src/body/lower.rs | 1 - crates/hir-def/src/body/tests.rs | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index 6b6417d17f92..dc8f3daca5e7 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -1721,7 +1721,6 @@ impl ExprCollector<'_> { } None => Pat::Missing, }, - // FIXME: implement in a way that also builds source map and calculates assoc resolutions in type inference. ast::Pat::RangePat(p) => { let mut range_part_lower = |p: Option| -> Option { p.and_then(|it| { diff --git a/crates/hir-def/src/body/tests.rs b/crates/hir-def/src/body/tests.rs index cf4c169e78cf..760548517e56 100644 --- a/crates/hir-def/src/body/tests.rs +++ b/crates/hir-def/src/body/tests.rs @@ -444,6 +444,7 @@ fn foo() { ); } +#[test] fn skip_skips_body() { let (db, body, owner) = lower( r#" From b44c218bc0611be64ea97882c3a682b48744bc85 Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Tue, 21 Jan 2025 23:22:39 +0100 Subject: [PATCH 10/10] Fix clippy errors --- crates/hir-def/src/body/lower.rs | 8 ++++---- crates/hir-def/src/hir.rs | 10 ++-------- crates/hir-ty/src/mir/lower.rs | 6 +++--- crates/hir/src/semantics/source_to_def.rs | 2 +- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index dc8f3daca5e7..f5b9d8743336 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -1734,10 +1734,10 @@ impl ExprCollector<'_> { if ident.is_simple_ident() { return ident .name() - .and_then(|name| Some(name.as_name())) - .and_then(|hir_name| Some(Path::from(hir_name))) - .and_then(|path| { - Some(self.alloc_expr_from_pat(Expr::Path(path), ptr)) + .map(|name| name.as_name()) + .map(Path::from) + .map(|path| { + self.alloc_expr_from_pat(Expr::Path(path), ptr) }); } diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs index 019f10a59552..4290c0211060 100644 --- a/crates/hir-def/src/hir.rs +++ b/crates/hir-def/src/hir.rs @@ -59,10 +59,7 @@ impl ExprOrPatId { } pub fn is_expr(&self) -> bool { - match self { - Self::ExprId(_) => true, - _ => false, - } + matches!(self, Self::ExprId(_)) } pub fn as_pat(self) -> Option { @@ -73,10 +70,7 @@ impl ExprOrPatId { } pub fn is_pat(&self) -> bool { - match self { - Self::PatId(_) => true, - _ => false, - } + matches!(self, Self::PatId(_)) } } stdx::impl_from!(ExprId, PatId for ExprOrPatId); diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index df39b4faad15..680af629663f 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -1359,7 +1359,7 @@ impl<'ctx> MirLowerCtx<'ctx> { } fn lower_literal_or_const_to_operand(&mut self, ty: Ty, loc: &ExprId) -> Result { - match dbg!(&self.body.exprs[*loc]) { + match &self.body.exprs[*loc] { Expr::Literal(l) => self.lower_literal_to_operand(ty, l), Expr::Path(c) => { let edition = self.edition(); @@ -1369,7 +1369,7 @@ impl<'ctx> MirLowerCtx<'ctx> { .resolver .resolve_path_in_value_ns(self.db.upcast(), c, HygieneId::ROOT) .ok_or_else(unresolved_name)?; - dbg!(match dbg!(pr) { + match pr { ResolveValueResult::ValueNs(v, _) => { if let ValueNs::ConstId(c) = v { self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty) @@ -1380,7 +1380,7 @@ impl<'ctx> MirLowerCtx<'ctx> { ResolveValueResult::Partial(_, _, _) => { not_supported!("associated constants in range pattern") } - }) + } } _ => { not_supported!("only `char` and numeric types are allowed in range patterns"); diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs index 227a60bee242..29d3736bae72 100644 --- a/crates/hir/src/semantics/source_to_def.rs +++ b/crates/hir/src/semantics/source_to_def.rs @@ -347,7 +347,7 @@ impl SourceToDefCtx<'_, '_> { &mut self, src: InFile<&ast::IdentPat>, ) -> Option<(DefWithBodyId, BindingId)> { - let container = dbg!(self.find_pat_or_label_container(src.syntax_ref()))?; + let container = self.find_pat_or_label_container(src.syntax_ref())?; let (body, source_map) = self.db.body_with_source_map(container); let src = src.cloned().map(ast::Pat::from); let pat_id = source_map.node_pat(src.as_ref())?;