Skip to content

Commit

Permalink
Add DynLazySpan
Browse files Browse the repository at this point in the history
  • Loading branch information
Y-Nak committed Apr 19, 2023
1 parent 9fca850 commit 6c70a1f
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 0 deletions.
9 changes: 9 additions & 0 deletions crates/hir/src/hir_def/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ pub enum Partial<T> {
Absent,
}

impl<T> Partial<T> {
pub fn unwrap(&self) -> &T {
match self {
Self::Present(value) => value,
Self::Absent => panic!("unwrap called on absent value"),
}
}
}

impl<T> Default for Partial<T> {
fn default() -> Self {
Self::Absent
Expand Down
35 changes: 35 additions & 0 deletions crates/hir/src/span/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,38 @@ impl ChainInitiator for ExprRoot {
ResolvedOrigin::resolve(db, top_mod, origin)
}
}

#[cfg(test)]
mod tests {
use crate::{
hir_def::{Body, Expr, Stmt},
test_db::TestDb,
};
use common::Upcast;

#[test]
fn aug_assign() {
let mut db = TestDb::default();

let text = r#" {
fn foo(mut x: i32) {
x += 1
}
}"#;

let body: Body = db.expect_item::<Body>(text);
let bin_expr = match body.stmts(db.upcast()).values().next().unwrap().unwrap() {
Stmt::Assign(_, rhs) => *rhs,
_ => unreachable!(),
};
let (lhs, rhs) = match body.exprs(db.upcast())[bin_expr].unwrap() {
Expr::Bin(lhs, rhs, _) => (lhs, rhs),
_ => unreachable!(),
};

let top_mod = body.top_mod(db.upcast());
assert_eq!("x += 1", db.text_at(top_mod, &bin_expr.lazy_span(body)));
assert_eq!("x", db.text_at(top_mod, &lhs.lazy_span(body)));
assert_eq!("1", db.text_at(top_mod, &rhs.lazy_span(body)));
}
}
14 changes: 14 additions & 0 deletions crates/hir/src/span/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ pub mod use_tree;

mod transition;

/// This struct represents a dynamic lazy span, which can be converted from all
/// types that implement [`LazySpan`] in this module. We want to avoid `dyn
/// LazySpan` usage because it doesn't implement `Clone` and `Eq` which leads to
/// a lot of difficulties in salsa integration
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct DynLazySpan(SpanTransitionChain);
impl LazySpan for DynLazySpan {
fn resolve(&self, db: &dyn crate::SpannedHirDb) -> Span {
self.0.resolve(db)
}
}

/// The trait provides a way to extract [`Span`](common::diagnostics::Span) from
/// types which don't have a span information directly, but can be resolved into
/// a span lazily.
Expand Down Expand Up @@ -170,4 +182,6 @@ impl AugAssignDesugared {

use transition::define_lazy_span_node;

use self::transition::SpanTransitionChain;

define_lazy_span_node!(LazySpanAtom);
13 changes: 13 additions & 0 deletions crates/hir/src/span/transition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ use super::{
type_alias_ast, use_ast, AugAssignDesugared, DesugaredOrigin, HirOrigin, LazySpan,
};

/// This type represents function from the hir origin to another hir origin to
/// identify the span of HIR node. `LazyTransitionFn` is regarded as a closure
/// that takes a `HirOrigin` and [`LazyArg`], `LazyArg` is considered as
/// captured variables.
/// The reason why we use `LazyTransitionFn` instead of `dyn
/// Fn` is that we want to make all types that use `LazyTransitionFn` to be
/// `Clone` and `Eq`.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub(crate) struct LazyTransitionFn {
pub(super) f: fn(ResolvedOrigin, LazyArg) -> ResolvedOrigin,
Expand Down Expand Up @@ -320,6 +327,12 @@ macro_rules! define_lazy_span_node {
self.0.resolve(db)
}
}

impl From<$name> for crate::span::DynLazySpan {
fn from(val: $name) -> Self {
Self(val.0)
}
}
};
}

Expand Down

0 comments on commit 6c70a1f

Please sign in to comment.