Lower ast::Ident to hir::Path when lowering RangePats

This commit is contained in:
Ali Bektas 2025-01-19 23:58:49 +01:00
parent 94b00c210c
commit 8956b1e1ba
9 changed files with 139 additions and 58 deletions

View file

@ -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(
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))
});
}
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
}
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,
}
})

View file

@ -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),

View file

@ -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");
}
}
_ => {}
}
}
}

View file

@ -55,12 +55,26 @@ impl ExprOrPatId {
}
}
pub fn is_expr(&self) -> bool {
match self {
Self::ExprId(_) => true,
_ => false,
}
}
pub fn as_pat(self) -> Option<PatId> {
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);

View file

@ -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<Operand> {
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<Operand> {
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");
}
}
}

View file

@ -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)

View file

@ -1640,6 +1640,7 @@ impl<'db> SemanticsImpl<'db> {
}
pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> {
dbg!(std::any::type_name::<T>());
let src = self.find_file(src.syntax()).with_value(src);
T::to_def(self, src)
}

View file

@ -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())?;

View file

@ -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<IdentClass> {
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() {