From 050c63a054bf29dbfc6161fb1ec12d89a319a87e Mon Sep 17 00:00:00 2001 From: Ali Bektas Date: Sun, 19 Jan 2025 23:58:49 +0100 Subject: [PATCH] Lower ast::Ident to hir::Path when lowering RangePats --- .../crates/hir-def/src/expr_store/lower.rs | 35 ++++---- .../crates/hir-def/src/expr_store/pretty.rs | 12 +-- .../crates/hir-def/src/expr_store/tests.rs | 88 ++++++++++++++++++- .../rust-analyzer/crates/hir-def/src/hir.rs | 14 +++ .../crates/hir-ty/src/mir/lower.rs | 29 +++--- .../hir-ty/src/mir/lower/pattern_matching.rs | 10 +-- .../rust-analyzer/crates/hir/src/semantics.rs | 1 + .../crates/hir/src/semantics/source_to_def.rs | 2 +- .../rust-analyzer/crates/ide-db/src/defs.rs | 6 +- 9 files changed, 139 insertions(+), 58 deletions(-) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index 3f3beb21858c..e4fcf949d914 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -1795,24 +1795,27 @@ 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| 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/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs index c28cfb24529c..82ad756dc2c6 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/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/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs index 5ce9a67f9b6c..893645604418 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests.rs @@ -1,10 +1,12 @@ mod block; +use base_db::Upcast; use expect_test::{expect, Expect}; use la_arena::RawIdx; use test_fixture::WithFixture; +use tracing::Instrument; -use crate::{test_db::TestDB, ModuleDefId}; +use crate::{db::InternDatabase, test_db::TestDB, ModuleDefId}; use super::*; @@ -446,7 +448,6 @@ fn foo() { ); } -#[test] fn skip_skips_body() { let (db, body, owner) = lower( r#" @@ -461,7 +462,45 @@ 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; +mod x { + pub const R: i32 = 100; +} +const fn f(x: i32) -> i32 { + match x { + 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; @@ -471,7 +510,7 @@ mod x { const fn f(x: i32) -> i32 { match x { -1..=5 => x * 10, - L..=x::R => x * 100, + ::std::i32::MIN..=x::R => x * 100, _ => x, } }"#, @@ -503,3 +542,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/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs index a964512beb2d..6aca610a9387 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs @@ -55,12 +55,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/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index cc6ed122af4b..69b3b9c02a0c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -8,8 +8,8 @@ use hir_def::{ data::adt::{StructKind, VariantData}, expr_store::{Body, HygieneId}, 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/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs index d78d15288adc..289175feefb1 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/src/tools/rust-analyzer/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) diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 882a27182f01..90c6e7e7b3b4 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index 29d3736bae72..227a60bee242 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index bad536080567..c45cb4294f0d 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/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() {