Auto merge of #17135 - Veykril:inline-const-scope, r=Veykril

fix: Fix expression scopes not being calculated for inline consts
This commit is contained in:
bors 2024-04-25 07:56:23 +00:00
commit 56bee2ddaf
7 changed files with 69 additions and 34 deletions

View file

@ -7,7 +7,7 @@ use crate::{
body::Body, body::Body,
db::DefDatabase, db::DefDatabase,
hir::{Binding, BindingId, Expr, ExprId, LabelId, Pat, PatId, Statement}, hir::{Binding, BindingId, Expr, ExprId, LabelId, Pat, PatId, Statement},
BlockId, DefWithBodyId, BlockId, ConstBlockId, DefWithBodyId,
}; };
pub type ScopeId = Idx<ScopeData>; pub type ScopeId = Idx<ScopeData>;
@ -46,7 +46,9 @@ pub struct ScopeData {
impl ExprScopes { impl ExprScopes {
pub(crate) fn expr_scopes_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> { pub(crate) fn expr_scopes_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<ExprScopes> {
let body = db.body(def); let body = db.body(def);
let mut scopes = ExprScopes::new(&body); let mut scopes = ExprScopes::new(&body, |const_block| {
db.lookup_intern_anonymous_const(const_block).root
});
scopes.shrink_to_fit(); scopes.shrink_to_fit();
Arc::new(scopes) Arc::new(scopes)
} }
@ -89,7 +91,10 @@ fn empty_entries(idx: usize) -> IdxRange<ScopeEntry> {
} }
impl ExprScopes { impl ExprScopes {
fn new(body: &Body) -> ExprScopes { fn new(
body: &Body,
resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy,
) -> ExprScopes {
let mut scopes = ExprScopes { let mut scopes = ExprScopes {
scopes: Arena::default(), scopes: Arena::default(),
scope_entries: Arena::default(), scope_entries: Arena::default(),
@ -100,7 +105,7 @@ impl ExprScopes {
scopes.add_bindings(body, root, self_param); scopes.add_bindings(body, root, self_param);
} }
scopes.add_params_bindings(body, root, &body.params); scopes.add_params_bindings(body, root, &body.params);
compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root); compute_expr_scopes(body.body_expr, body, &mut scopes, &mut root, resolve_const_block);
scopes scopes
} }
@ -183,35 +188,46 @@ fn compute_block_scopes(
body: &Body, body: &Body,
scopes: &mut ExprScopes, scopes: &mut ExprScopes,
scope: &mut ScopeId, scope: &mut ScopeId,
resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy,
) { ) {
for stmt in statements { for stmt in statements {
match stmt { match stmt {
Statement::Let { pat, initializer, else_branch, .. } => { Statement::Let { pat, initializer, else_branch, .. } => {
if let Some(expr) = initializer { if let Some(expr) = initializer {
compute_expr_scopes(*expr, body, scopes, scope); compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block);
} }
if let Some(expr) = else_branch { if let Some(expr) = else_branch {
compute_expr_scopes(*expr, body, scopes, scope); compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block);
} }
*scope = scopes.new_scope(*scope); *scope = scopes.new_scope(*scope);
scopes.add_pat_bindings(body, *scope, *pat); scopes.add_pat_bindings(body, *scope, *pat);
} }
Statement::Expr { expr, .. } => { Statement::Expr { expr, .. } => {
compute_expr_scopes(*expr, body, scopes, scope); compute_expr_scopes(*expr, body, scopes, scope, resolve_const_block);
} }
Statement::Item => (), Statement::Item => (),
} }
} }
if let Some(expr) = tail { if let Some(expr) = tail {
compute_expr_scopes(expr, body, scopes, scope); compute_expr_scopes(expr, body, scopes, scope, resolve_const_block);
} }
} }
fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: &mut ScopeId) { fn compute_expr_scopes(
expr: ExprId,
body: &Body,
scopes: &mut ExprScopes,
scope: &mut ScopeId,
resolve_const_block: impl (Fn(ConstBlockId) -> ExprId) + Copy,
) {
let make_label = let make_label =
|label: &Option<LabelId>| label.map(|label| (label, body.labels[label].name.clone())); |label: &Option<LabelId>| label.map(|label| (label, body.labels[label].name.clone()));
let compute_expr_scopes = |scopes: &mut ExprScopes, expr: ExprId, scope: &mut ScopeId| {
compute_expr_scopes(expr, body, scopes, scope, resolve_const_block)
};
scopes.set_scope(expr, *scope); scopes.set_scope(expr, *scope);
match &body[expr] { match &body[expr] {
Expr::Block { statements, tail, id, label } => { Expr::Block { statements, tail, id, label } => {
@ -219,53 +235,54 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
// Overwrite the old scope for the block expr, so that every block scope can be found // Overwrite the old scope for the block expr, so that every block scope can be found
// via the block itself (important for blocks that only contain items, no expressions). // via the block itself (important for blocks that only contain items, no expressions).
scopes.set_scope(expr, scope); scopes.set_scope(expr, scope);
compute_block_scopes(statements, *tail, body, scopes, &mut scope); compute_block_scopes(statements, *tail, body, scopes, &mut scope, resolve_const_block);
} }
Expr::Const(_) => { Expr::Const(id) => {
// FIXME: This is broken. let mut scope = scopes.root_scope();
compute_expr_scopes(scopes, resolve_const_block(*id), &mut scope);
} }
Expr::Unsafe { id, statements, tail } | Expr::Async { id, statements, tail } => { Expr::Unsafe { id, statements, tail } | Expr::Async { id, statements, tail } => {
let mut scope = scopes.new_block_scope(*scope, *id, None); let mut scope = scopes.new_block_scope(*scope, *id, None);
// Overwrite the old scope for the block expr, so that every block scope can be found // Overwrite the old scope for the block expr, so that every block scope can be found
// via the block itself (important for blocks that only contain items, no expressions). // via the block itself (important for blocks that only contain items, no expressions).
scopes.set_scope(expr, scope); scopes.set_scope(expr, scope);
compute_block_scopes(statements, *tail, body, scopes, &mut scope); compute_block_scopes(statements, *tail, body, scopes, &mut scope, resolve_const_block);
} }
Expr::Loop { body: body_expr, label } => { Expr::Loop { body: body_expr, label } => {
let mut scope = scopes.new_labeled_scope(*scope, make_label(label)); let mut scope = scopes.new_labeled_scope(*scope, make_label(label));
compute_expr_scopes(*body_expr, body, scopes, &mut scope); compute_expr_scopes(scopes, *body_expr, &mut scope);
} }
Expr::Closure { args, body: body_expr, .. } => { Expr::Closure { args, body: body_expr, .. } => {
let mut scope = scopes.new_scope(*scope); let mut scope = scopes.new_scope(*scope);
scopes.add_params_bindings(body, scope, args); scopes.add_params_bindings(body, scope, args);
compute_expr_scopes(*body_expr, body, scopes, &mut scope); compute_expr_scopes(scopes, *body_expr, &mut scope);
} }
Expr::Match { expr, arms } => { Expr::Match { expr, arms } => {
compute_expr_scopes(*expr, body, scopes, scope); compute_expr_scopes(scopes, *expr, scope);
for arm in arms.iter() { for arm in arms.iter() {
let mut scope = scopes.new_scope(*scope); let mut scope = scopes.new_scope(*scope);
scopes.add_pat_bindings(body, scope, arm.pat); scopes.add_pat_bindings(body, scope, arm.pat);
if let Some(guard) = arm.guard { if let Some(guard) = arm.guard {
scope = scopes.new_scope(scope); scope = scopes.new_scope(scope);
compute_expr_scopes(guard, body, scopes, &mut scope); compute_expr_scopes(scopes, guard, &mut scope);
} }
compute_expr_scopes(arm.expr, body, scopes, &mut scope); compute_expr_scopes(scopes, arm.expr, &mut scope);
} }
} }
&Expr::If { condition, then_branch, else_branch } => { &Expr::If { condition, then_branch, else_branch } => {
let mut then_branch_scope = scopes.new_scope(*scope); let mut then_branch_scope = scopes.new_scope(*scope);
compute_expr_scopes(condition, body, scopes, &mut then_branch_scope); compute_expr_scopes(scopes, condition, &mut then_branch_scope);
compute_expr_scopes(then_branch, body, scopes, &mut then_branch_scope); compute_expr_scopes(scopes, then_branch, &mut then_branch_scope);
if let Some(else_branch) = else_branch { if let Some(else_branch) = else_branch {
compute_expr_scopes(else_branch, body, scopes, scope); compute_expr_scopes(scopes, else_branch, scope);
} }
} }
&Expr::Let { pat, expr } => { &Expr::Let { pat, expr } => {
compute_expr_scopes(expr, body, scopes, scope); compute_expr_scopes(scopes, expr, scope);
*scope = scopes.new_scope(*scope); *scope = scopes.new_scope(*scope);
scopes.add_pat_bindings(body, *scope, pat); scopes.add_pat_bindings(body, *scope, pat);
} }
e => e.walk_child_exprs(|e| compute_expr_scopes(e, body, scopes, scope)), e => e.walk_child_exprs(|e| compute_expr_scopes(scopes, e, scope)),
}; };
} }

View file

@ -68,10 +68,10 @@ use crate::{
pub struct RawVisibilityId(u32); pub struct RawVisibilityId(u32);
impl RawVisibilityId { impl RawVisibilityId {
pub const PUB: Self = RawVisibilityId(u32::max_value()); pub const PUB: Self = RawVisibilityId(u32::MAX);
pub const PRIV_IMPLICIT: Self = RawVisibilityId(u32::max_value() - 1); pub const PRIV_IMPLICIT: Self = RawVisibilityId(u32::MAX - 1);
pub const PRIV_EXPLICIT: Self = RawVisibilityId(u32::max_value() - 2); pub const PRIV_EXPLICIT: Self = RawVisibilityId(u32::MAX - 2);
pub const PUB_CRATE: Self = RawVisibilityId(u32::max_value() - 3); pub const PUB_CRATE: Self = RawVisibilityId(u32::MAX - 3);
} }
impl fmt::Debug for RawVisibilityId { impl fmt::Debug for RawVisibilityId {

View file

@ -3664,3 +3664,21 @@ fn main() {
"#, "#,
); );
} }
#[test]
fn inline_const_expression() {
check(
r#"
fn main() {
let foo = 0;
const {
let bar = 1;
let unresolved = foo;
// ^^^^^^^^^^ type: {unknown}
let resolved = bar;
// ^^^^^^^^ type: i32
}
}
"#,
);
}

View file

@ -77,7 +77,7 @@ pub(crate) fn reorder_impl_items(acc: &mut Assists, ctx: &AssistContext<'_>) ->
ast::AssocItem::MacroCall(_) => None, ast::AssocItem::MacroCall(_) => None,
}; };
name.and_then(|n| ranks.get(&n.to_string()).copied()).unwrap_or(usize::max_value()) name.and_then(|n| ranks.get(&n.to_string()).copied()).unwrap_or(usize::MAX)
}) })
.collect(); .collect();

View file

@ -301,8 +301,8 @@ impl SymbolIndex {
} }
fn range_to_map_value(start: usize, end: usize) -> u64 { fn range_to_map_value(start: usize, end: usize) -> u64 {
debug_assert![start <= (std::u32::MAX as usize)]; debug_assert![start <= (u32::MAX as usize)];
debug_assert![end <= (std::u32::MAX as usize)]; debug_assert![end <= (u32::MAX as usize)];
((start as u64) << 32) | end as u64 ((start as u64) << 32) | end as u64
} }

View file

@ -285,7 +285,7 @@ where
impl Default for LruIndex { impl Default for LruIndex {
fn default() -> Self { fn default() -> Self {
Self { index: AtomicUsize::new(std::usize::MAX) } Self { index: AtomicUsize::new(usize::MAX) }
} }
} }
@ -299,11 +299,11 @@ impl LruIndex {
} }
fn clear(&self) { fn clear(&self) {
self.store(std::usize::MAX); self.store(usize::MAX);
} }
fn is_in_lru(&self) -> bool { fn is_in_lru(&self) -> bool {
self.load() != std::usize::MAX self.load() != usize::MAX
} }
} }

View file

@ -60,7 +60,7 @@ impl AtomicRevision {
/// Increment by 1, returning previous value. /// Increment by 1, returning previous value.
pub(crate) fn fetch_then_increment(&self) -> Revision { pub(crate) fn fetch_then_increment(&self) -> Revision {
let v = self.data.fetch_add(1, Ordering::SeqCst); let v = self.data.fetch_add(1, Ordering::SeqCst);
assert!(v != u32::max_value(), "revision overflow"); assert!(v != u32::MAX, "revision overflow");
Revision::from(v) Revision::from(v)
} }
} }