Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22861 from Veykril/lukaswirth/push-ksslunmzoxpt
Record expressions in types in ExprScope
Lukas Wirth 3 weeks ago
parent cb6d600 · parent 25d80d1 · commit 7558038
-rw-r--r--crates/hir-def/src/expr_store.rs3
-rw-r--r--crates/hir-def/src/expr_store/scope.rs77
2 files changed, 73 insertions, 7 deletions
diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs
index fdb3296b17..52859a5efb 100644
--- a/crates/hir-def/src/expr_store.rs
+++ b/crates/hir-def/src/expr_store.rs
@@ -154,9 +154,6 @@ struct ExpressionOnlyStore {
/// and it does not bother us because we use this list for two things: constructing `ExprScopes`, which
/// works fine with nested exprs, and retrieving inference results, and we copy the inner const's inference
/// into the outer const.
- // FIXME: Array repeat is not problematic indeed, but this could still break with exprs in types,
- // which we do not visit for `ExprScopes` (they're fine for inference though). We either need to visit them,
- // or use a more complicated search.
expr_roots: SmallVec<[ExprRoot; 1]>,
}
diff --git a/crates/hir-def/src/expr_store/scope.rs b/crates/hir-def/src/expr_store/scope.rs
index 3ce0ed44da..d6568b8cfe 100644
--- a/crates/hir-def/src/expr_store/scope.rs
+++ b/crates/hir-def/src/expr_store/scope.rs
@@ -5,12 +5,13 @@ use la_arena::{Arena, ArenaMap, Idx, IdxRange, RawIdx};
use crate::{
BlockId, DefWithBodyId, ExpressionStoreOwnerId, GenericDefId, VariantId,
- expr_store::{Body, ExpressionStore, HygieneId, body::Param},
+ expr_store::{Body, ExpressionStore, HygieneId, StoreVisitor, body::Param},
hir::{
Array, Binding, BindingId, Expr, ExprId, Item, LabelId, Pat, PatId, Statement,
generics::GenericParams,
},
signatures::VariantFields,
+ type_ref::TypeRefId,
};
pub type ScopeId = Idx<ScopeData>;
@@ -274,6 +275,42 @@ impl ExprScopes {
}
}
+struct ExprScopeVisitor<'a> {
+ store: &'a ExpressionStore,
+ scopes: &'a mut ExprScopes,
+ scope: &'a mut ScopeId,
+ const_scope: &'a mut ScopeId,
+}
+
+impl StoreVisitor for ExprScopeVisitor<'_> {
+ fn on_expr(&mut self, expr: ExprId) {
+ compute_expr_scopes(expr, self.store, self.scopes, self.scope, self.const_scope);
+ }
+
+ fn on_anon_const_expr(&mut self, expr: ExprId) {
+ let mut scope = *self.const_scope;
+ compute_expr_scopes(expr, self.store, self.scopes, &mut scope, self.const_scope);
+ }
+
+ fn on_pat(&mut self, pat: PatId) {
+ self.store.visit_pat_children(pat, &mut *self);
+ }
+
+ fn on_type(&mut self, ty: TypeRefId) {
+ self.store.visit_type_ref_children(ty, &mut *self);
+ }
+}
+
+fn compute_type_scopes(
+ ty: TypeRefId,
+ store: &ExpressionStore,
+ scopes: &mut ExprScopes,
+ const_scope: &mut ScopeId,
+) {
+ let mut scope = *const_scope;
+ ExprScopeVisitor { store, scopes, scope: &mut scope, const_scope }.on_type(ty);
+}
+
fn compute_block_scopes(
statements: &[Statement],
tail: Option<ExprId>,
@@ -284,7 +321,10 @@ fn compute_block_scopes(
) {
for stmt in statements {
match stmt {
- Statement::Let { pat, initializer, else_branch, .. } => {
+ Statement::Let { pat, initializer, else_branch, type_ref } => {
+ if let Some(type_ref) = type_ref {
+ compute_type_scopes(*type_ref, store, scopes, const_scope);
+ }
if let Some(expr) = initializer {
compute_expr_scopes(*expr, store, scopes, scope, const_scope);
}
@@ -362,7 +402,21 @@ fn compute_expr_scopes(
let mut scope = scopes.new_labeled_scope(*scope, *label);
compute_expr_scopes(scopes, *body_expr, &mut scope, const_scope);
}
- Expr::Closure { args, body: body_expr, .. } => {
+ Expr::Closure {
+ args,
+ arg_types,
+ ret_type,
+ body: body_expr,
+ capture_by: _,
+ closure_kind: _,
+ } => {
+ arg_types
+ .iter()
+ .flatten()
+ .for_each(|type_ref| compute_type_scopes(*type_ref, store, scopes, const_scope));
+ if let Some(type_ref) = ret_type {
+ compute_type_scopes(*type_ref, store, scopes, const_scope);
+ }
let mut scope = scopes.new_scope(*scope);
args.iter().for_each(|arg| scopes.add_pat_bindings(store, scope, *arg));
compute_expr_scopes(scopes, *body_expr, &mut scope, const_scope);
@@ -392,7 +446,9 @@ fn compute_expr_scopes(
*scope = scopes.new_scope(*scope);
scopes.add_pat_bindings(store, *scope, pat);
}
- _ => store.walk_child_exprs(expr, |e| compute_expr_scopes(scopes, e, scope, const_scope)),
+ _ => {
+ store.visit_expr_children(expr, ExprScopeVisitor { store, scopes, scope, const_scope })
+ }
};
}
@@ -465,6 +521,19 @@ mod tests {
}
#[test]
+ fn type_anon_const_scope() {
+ do_check(
+ r#"
+fn f(param: usize) {
+ let local = 0;
+ let _: [(); $0] = [];
+}
+"#,
+ &["param"],
+ );
+ }
+
+ #[test]
fn test_lambda_scope() {
do_check(
r"