mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-03 05:13:35 +00:00
Lower ast::Ident to hir::Path when lowering RangePats
This commit is contained in:
parent
94b00c210c
commit
8956b1e1ba
9 changed files with 139 additions and 58 deletions
|
|
@ -1795,24 +1795,27 @@ impl ExprCollector<'_> {
|
||||||
p.and_then(|it| {
|
p.and_then(|it| {
|
||||||
let ptr = PatPtr::new(&it);
|
let ptr = PatPtr::new(&it);
|
||||||
match &it {
|
match &it {
|
||||||
ast::Pat::LiteralPat(it) => {
|
ast::Pat::LiteralPat(it) => Some(self.alloc_expr_from_pat(
|
||||||
// Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0)))
|
Expr::Literal(pat_literal_to_hir(it)?.0),
|
||||||
Some(self.alloc_expr_from_pat(
|
ptr,
|
||||||
Expr::Literal(pat_literal_to_hir(it)?.0),
|
)),
|
||||||
ptr,
|
ast::Pat::IdentPat(ident) => {
|
||||||
))
|
if ident.is_simple_ident() {
|
||||||
}
|
return ident
|
||||||
ast::Pat::IdentPat(_) => Some(self.missing_expr()),
|
.name()
|
||||||
ast::Pat::PathPat(p) => {
|
.and_then(|name| Some(name.as_name()))
|
||||||
if let Some(path) = p.path() {
|
.and_then(|hir_name| Some(Path::from(hir_name)))
|
||||||
if let Some(parsed) = self.parse_path(path) {
|
.and_then(|path| {
|
||||||
return Some(
|
Some(self.alloc_expr_from_pat(Expr::Path(path), ptr))
|
||||||
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,
|
_ => None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,7 @@ use itertools::Itertools;
|
||||||
use span::Edition;
|
use span::Edition;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
hir::{
|
hir::{Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement},
|
||||||
Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, LiteralOrConst, Movability,
|
|
||||||
Statement,
|
|
||||||
},
|
|
||||||
pretty::{print_generic_args, print_path, print_type_ref},
|
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) {
|
fn print_literal(&mut self, literal: &Literal) {
|
||||||
match literal {
|
match literal {
|
||||||
Literal::String(it) => w!(self, "{:?}", it),
|
Literal::String(it) => w!(self, "{:?}", it),
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
mod block;
|
mod block;
|
||||||
|
|
||||||
|
use base_db::Upcast;
|
||||||
use expect_test::{expect, Expect};
|
use expect_test::{expect, Expect};
|
||||||
use la_arena::RawIdx;
|
use la_arena::RawIdx;
|
||||||
use test_fixture::WithFixture;
|
use test_fixture::WithFixture;
|
||||||
|
use tracing::Instrument;
|
||||||
|
|
||||||
use crate::{test_db::TestDB, ModuleDefId};
|
use crate::{db::InternDatabase, test_db::TestDB, ModuleDefId};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
@ -446,7 +448,6 @@ fn foo() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn skip_skips_body() {
|
fn skip_skips_body() {
|
||||||
let (db, body, owner) = lower(
|
let (db, body, owner) = lower(
|
||||||
r#"
|
r#"
|
||||||
|
|
@ -461,7 +462,45 @@ async fn foo(a: (), b: i32) -> u32 {
|
||||||
.assert_eq(&printed);
|
.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(
|
let (db, body, owner) = lower(
|
||||||
r#"
|
r#"
|
||||||
pub const L: i32 = 6;
|
pub const L: i32 = 6;
|
||||||
|
|
@ -471,7 +510,7 @@ mod x {
|
||||||
const fn f(x: i32) -> i32 {
|
const fn f(x: i32) -> i32 {
|
||||||
match x {
|
match x {
|
||||||
-1..=5 => x * 10,
|
-1..=5 => x * 10,
|
||||||
L..=x::R => x * 100,
|
::std::i32::MIN..=x::R => x * 100,
|
||||||
_ => x,
|
_ => 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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> {
|
pub fn as_pat(self) -> Option<PatId> {
|
||||||
match self {
|
match self {
|
||||||
Self::PatId(v) => Some(v),
|
Self::PatId(v) => Some(v),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_pat(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::PatId(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stdx::impl_from!(ExprId, PatId for ExprOrPatId);
|
stdx::impl_from!(ExprId, PatId for ExprOrPatId);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ use hir_def::{
|
||||||
data::adt::{StructKind, VariantData},
|
data::adt::{StructKind, VariantData},
|
||||||
expr_store::{Body, HygieneId},
|
expr_store::{Body, HygieneId},
|
||||||
hir::{
|
hir::{
|
||||||
ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal,
|
ArithOp, Array, BinaryOp, BindingAnnotation, BindingId, ExprId, LabelId, Literal, MatchArm,
|
||||||
LiteralOrConst, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField,
|
Pat, PatId, RecordFieldPat, RecordLitField,
|
||||||
},
|
},
|
||||||
lang_item::{LangItem, LangItemTarget},
|
lang_item::{LangItem, LangItemTarget},
|
||||||
path::Path,
|
path::Path,
|
||||||
|
|
@ -1358,20 +1358,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_literal_or_const_to_operand(
|
fn lower_literal_or_const_to_operand(&mut self, ty: Ty, loc: &ExprId) -> Result<Operand> {
|
||||||
&mut self,
|
match dbg!(&self.body.exprs[*loc]) {
|
||||||
ty: Ty,
|
Expr::Literal(l) => self.lower_literal_to_operand(ty, l),
|
||||||
loc: &LiteralOrConst,
|
Expr::Path(c) => {
|
||||||
) -> 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"
|
|
||||||
),
|
|
||||||
};
|
|
||||||
let edition = self.edition();
|
let edition = self.edition();
|
||||||
let unresolved_name =
|
let unresolved_name =
|
||||||
|| MirLowerError::unresolved_path(self.db, c, edition, &self.body.types);
|
|| MirLowerError::unresolved_path(self.db, c, edition, &self.body.types);
|
||||||
|
|
@ -1379,7 +1369,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||||
.resolver
|
.resolver
|
||||||
.resolve_path_in_value_ns(self.db.upcast(), c, HygieneId::ROOT)
|
.resolve_path_in_value_ns(self.db.upcast(), c, HygieneId::ROOT)
|
||||||
.ok_or_else(unresolved_name)?;
|
.ok_or_else(unresolved_name)?;
|
||||||
match pr {
|
dbg!(match dbg!(pr) {
|
||||||
ResolveValueResult::ValueNs(v, _) => {
|
ResolveValueResult::ValueNs(v, _) => {
|
||||||
if let ValueNs::ConstId(c) = v {
|
if let ValueNs::ConstId(c) = v {
|
||||||
self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty)
|
self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty)
|
||||||
|
|
@ -1390,7 +1380,10 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
||||||
ResolveValueResult::Partial(_, _, _) => {
|
ResolveValueResult::Partial(_, _, _) => {
|
||||||
not_supported!("associated constants in range pattern")
|
not_supported!("associated constants in range pattern")
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
not_supported!("only `char` and numeric types are allowed in range patterns");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! MIR lowering for patterns
|
//! MIR lowering for patterns
|
||||||
|
|
||||||
use hir_def::{hir::LiteralOrConst, AssocItemId};
|
use hir_def::{hir::ExprId, AssocItemId};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mir::{
|
mir::{
|
||||||
|
|
@ -207,7 +207,7 @@ impl MirLowerCtx<'_> {
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
Pat::Range { start, end } => {
|
Pat::Range { start, end } => {
|
||||||
let mut add_check = |l: &LiteralOrConst, binop| -> Result<()> {
|
let mut add_check = |l: &ExprId, binop| -> Result<()> {
|
||||||
let lv =
|
let lv =
|
||||||
self.lower_literal_or_const_to_operand(self.infer[pattern].clone(), l)?;
|
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());
|
let else_target = *current_else.get_or_insert_with(|| self.new_basic_block());
|
||||||
|
|
@ -234,12 +234,10 @@ impl MirLowerCtx<'_> {
|
||||||
};
|
};
|
||||||
if mode == MatchingMode::Check {
|
if mode == MatchingMode::Check {
|
||||||
if let Some(start) = start {
|
if let Some(start) = start {
|
||||||
// TODO
|
add_check(start, BinOp::Le)?;
|
||||||
// add_check(start, BinOp::Le)?;
|
|
||||||
}
|
}
|
||||||
if let Some(end) = end {
|
if let Some(end) = end {
|
||||||
// TODO
|
add_check(end, BinOp::Ge)?;
|
||||||
// add_check(end, BinOp::Ge)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(current, current_else)
|
(current, current_else)
|
||||||
|
|
|
||||||
|
|
@ -1640,6 +1640,7 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> {
|
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);
|
let src = self.find_file(src.syntax()).with_value(src);
|
||||||
T::to_def(self, src)
|
T::to_def(self, src)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -347,7 +347,7 @@ impl SourceToDefCtx<'_, '_> {
|
||||||
&mut self,
|
&mut self,
|
||||||
src: InFile<&ast::IdentPat>,
|
src: InFile<&ast::IdentPat>,
|
||||||
) -> Option<(DefWithBodyId, BindingId)> {
|
) -> 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 (body, source_map) = self.db.body_with_source_map(container);
|
||||||
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())?;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ use hir::{
|
||||||
};
|
};
|
||||||
use span::Edition;
|
use span::Edition;
|
||||||
use stdx::{format_to, impl_from};
|
use stdx::{format_to, impl_from};
|
||||||
|
use syntax::ToSmolStr;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, AstNode},
|
ast::{self, AstNode},
|
||||||
match_ast, SyntaxKind, SyntaxNode, SyntaxToken,
|
match_ast, SyntaxKind, SyntaxNode, SyntaxToken,
|
||||||
|
|
@ -365,6 +366,7 @@ impl IdentClass {
|
||||||
sema: &Semantics<'_, RootDatabase>,
|
sema: &Semantics<'_, RootDatabase>,
|
||||||
node: &SyntaxNode,
|
node: &SyntaxNode,
|
||||||
) -> Option<IdentClass> {
|
) -> Option<IdentClass> {
|
||||||
|
dbg!(&node.to_smolstr());
|
||||||
match_ast! {
|
match_ast! {
|
||||||
match node {
|
match node {
|
||||||
ast::Name(name) => NameClass::classify(sema, &name).map(IdentClass::NameClass),
|
ast::Name(name) => NameClass::classify(sema, &name).map(IdentClass::NameClass),
|
||||||
|
|
@ -521,7 +523,7 @@ impl NameClass {
|
||||||
let definition = match_ast! {
|
let definition = match_ast! {
|
||||||
match parent {
|
match parent {
|
||||||
ast::Item(it) => classify_item(sema, it)?,
|
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::Rename(it) => classify_rename(sema, it)?,
|
||||||
ast::SelfParam(it) => Definition::Local(sema.to_def(&it)?),
|
ast::SelfParam(it) => Definition::Local(sema.to_def(&it)?),
|
||||||
ast::RecordField(it) => Definition::Field(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)));
|
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();
|
let pat_parent = ident_pat.syntax().parent();
|
||||||
if let Some(record_pat_field) = pat_parent.and_then(ast::RecordPatField::cast) {
|
if let Some(record_pat_field) = pat_parent.and_then(ast::RecordPatField::cast) {
|
||||||
if record_pat_field.name_ref().is_none() {
|
if record_pat_field.name_ref().is_none() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue