Unnamed repository; edit this file 'description' to name the repository.
Hookup semantics
| -rw-r--r-- | crates/hir/src/semantics.rs | 28 | ||||
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 82 | ||||
| -rw-r--r-- | crates/ide/src/syntax_highlighting/test_data/highlight_general.html | 2 | ||||
| -rw-r--r-- | crates/ide/src/syntax_highlighting/tests.rs | 2 |
4 files changed, 80 insertions, 34 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index c816fe967c..a231f4aff5 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -2149,7 +2149,7 @@ impl<'db> SemanticsImpl<'db> { node: InFile<&SyntaxNode>, offset: Option<TextSize>, // replace this, just make the inference result a `LazyCell` - infer_body: bool, + infer: bool, ) -> Option<SourceAnalyzer<'db>> { let _p = tracing::info_span!("SemanticsImpl::analyze_impl").entered(); @@ -2157,7 +2157,7 @@ impl<'db> SemanticsImpl<'db> { let resolver = match container { ChildContainer::DefWithBodyId(def) => { - return Some(if infer_body { + return Some(if infer { SourceAnalyzer::new_for_body(self.db, def, node, offset) } else { SourceAnalyzer::new_for_body_no_infer(self.db, def, node, offset) @@ -2167,16 +2167,32 @@ impl<'db> SemanticsImpl<'db> { return Some(SourceAnalyzer::new_variant_body(self.db, def, node, offset)); } ChildContainer::TraitId(it) => { - return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)); + return Some(if infer { + SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset) + } else { + SourceAnalyzer::new_generic_def_no_infer(self.db, it.into(), node, offset) + }); } ChildContainer::ImplId(it) => { - return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)); + return Some(if infer { + SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset) + } else { + SourceAnalyzer::new_generic_def_no_infer(self.db, it.into(), node, offset) + }); } ChildContainer::EnumId(it) => { - return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset)); + return Some(if infer { + SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset) + } else { + SourceAnalyzer::new_generic_def_no_infer(self.db, it.into(), node, offset) + }); } ChildContainer::GenericDefId(it) => { - return Some(SourceAnalyzer::new_generic_def(self.db, it, node, offset)); + return Some(if infer { + SourceAnalyzer::new_generic_def(self.db, it, node, offset) + } else { + SourceAnalyzer::new_generic_def_no_infer(self.db, it, node, offset) + }); } ChildContainer::ModuleId(it) => it.resolver(self.db), }; diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 18929f8209..ad7aea3918 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -17,7 +17,7 @@ use hir_def::{ path::Path, scope::{ExprScopes, ScopeId}, }, - hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat, PatId}, + hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat, PatId, generics::GenericParams}, lang_item::LangItems, nameres::MacroSubNs, resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope}, @@ -92,7 +92,9 @@ pub(crate) enum BodyOrSig<'db> { def: GenericDefId, store: Arc<ExpressionStore>, source_map: Arc<ExpressionStoreSourceMap>, - // infer: Option<Arc<InferenceResult>>, + infer: Option<&'db InferenceResult>, + #[expect(dead_code)] + generics: Arc<GenericParams>, }, } @@ -147,14 +149,46 @@ impl<'db> SourceAnalyzer<'db> { pub(crate) fn new_generic_def( db: &'db dyn HirDatabase, def: GenericDefId, - InFile { file_id, .. }: InFile<&SyntaxNode>, - _offset: Option<TextSize>, + node: InFile<&SyntaxNode>, + offset: Option<TextSize>, ) -> SourceAnalyzer<'db> { - let (_params, store, source_map) = db.generic_params_and_store_and_source_map(def); - let resolver = def.resolver(db); + Self::new_generic_def_(db, def, node, offset, Some(InferenceResult::for_signature(db, def))) + } + + pub(crate) fn new_generic_def_no_infer( + db: &'db dyn HirDatabase, + def: GenericDefId, + node: InFile<&SyntaxNode>, + offset: Option<TextSize>, + ) -> SourceAnalyzer<'db> { + Self::new_generic_def_(db, def, node, offset, None) + } + + pub(crate) fn new_generic_def_( + db: &'db dyn HirDatabase, + def: GenericDefId, + node @ InFile { file_id, .. }: InFile<&SyntaxNode>, + offset: Option<TextSize>, + infer: Option<&'db InferenceResult>, + ) -> SourceAnalyzer<'db> { + let (generics, store, source_map) = db.generic_params_and_store_and_source_map(def); + let scopes = db.expr_scopes(def.into()); + let scope = match offset { + None => scope_for(db, &scopes, &source_map, node), + Some(offset) => { + debug_assert!( + node.text_range().contains_inclusive(offset), + "{:?} not in {:?}", + offset, + node.text_range() + ); + scope_for_offset(db, &scopes, &source_map, node.file_id, offset) + } + }; + let resolver = resolver_for_scope(db, def, scope); SourceAnalyzer { resolver, - body_or_sig: Some(BodyOrSig::Sig { def, store, source_map }), + body_or_sig: Some(BodyOrSig::Sig { def, store, source_map, generics, infer }), file_id, } } @@ -197,17 +231,8 @@ impl<'db> SourceAnalyzer<'db> { fn infer(&self) -> Option<&InferenceResult> { self.body_or_sig.as_ref().and_then(|it| match it { - BodyOrSig::Sig { .. } => None, BodyOrSig::VariantFields { .. } => None, - BodyOrSig::Body { infer, .. } => infer.as_deref(), - }) - } - - fn body(&self) -> Option<&Body> { - self.body_or_sig.as_ref().and_then(|it| match it { - BodyOrSig::Sig { .. } => None, - BodyOrSig::VariantFields { .. } => None, - BodyOrSig::Body { body, .. } => Some(&**body), + BodyOrSig::Sig { infer, .. } | BodyOrSig::Body { infer, .. } => infer.as_deref(), }) } @@ -232,11 +257,13 @@ impl<'db> SourceAnalyzer<'db> { } fn trait_environment(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> { - self.param_and( - self.body_() - .map(|(def, ..)| def) - .map_or_else(ParamEnv::empty, |def| db.trait_environment_for_body(def)), - ) + self.param_and(self.body_or_sig.as_ref().map_or_else(ParamEnv::empty, |body_or_sig| { + match *body_or_sig { + BodyOrSig::Body { def, .. } => db.trait_environment_for_body(def), + BodyOrSig::VariantFields { .. } => ParamEnv::empty(), + BodyOrSig::Sig { def, .. } => db.trait_environment(def), + } + })) } pub(crate) fn expr_id(&self, expr: ast::Expr) -> Option<ExprOrPatId> { @@ -371,7 +398,10 @@ impl<'db> SourceAnalyzer<'db> { db: &'db dyn HirDatabase, _param: &ast::SelfParam, ) -> Option<Type<'db>> { - let binding = self.body()?.self_param?; + let binding = match self.body_or_sig.as_ref()? { + BodyOrSig::Sig { .. } | BodyOrSig::VariantFields { .. } => return None, + BodyOrSig::Body { body, .. } => body.self_param?, + }; let ty = self.infer()?.binding_ty(binding); Some(Type::new_with_resolver(db, &self.resolver, ty)) } @@ -1526,7 +1556,7 @@ impl<'db> SourceAnalyzer<'db> { fn scope_for( db: &dyn HirDatabase, scopes: &ExprScopes, - source_map: &BodySourceMap, + source_map: &ExpressionStoreSourceMap, node: InFile<&SyntaxNode>, ) -> Option<ScopeId> { node.ancestors_with_macros(db) @@ -1545,7 +1575,7 @@ fn scope_for( fn scope_for_offset( db: &dyn HirDatabase, scopes: &ExprScopes, - source_map: &BodySourceMap, + source_map: &ExpressionStoreSourceMap, from_file: HirFileId, offset: TextSize, ) -> Option<ScopeId> { @@ -1579,7 +1609,7 @@ fn scope_for_offset( fn adjust( db: &dyn HirDatabase, scopes: &ExprScopes, - source_map: &BodySourceMap, + source_map: &ExpressionStoreSourceMap, expr_range: TextRange, from_file: HirFileId, offset: TextSize, diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/crates/ide/src/syntax_highlighting/test_data/highlight_general.html index c6dbc435c0..1184739cc2 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_general.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_general.html @@ -105,7 +105,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="keyword control">loop</span> <span class="brace">{</span><span class="brace">}</span> <span class="brace">}</span> -<span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="angle"><</span><span class="keyword const">const</span> <span class="const_param const declaration">FOO</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="angle">></span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">usize</span> <span class="brace">{</span> +<span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="angle"><</span><span class="keyword const">const</span> <span class="const_param const declaration">FOO</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="angle">></span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">usize</span> <span class="keyword">where</span> <span class="bracket">[</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="const_param const">FOO</span><span class="bracket">]</span><span class="colon">:</span> <span class="trait default_library library">Sized</span> <span class="brace">{</span> <span class="function">const_param</span><span class="operator">::</span><span class="angle"><</span><span class="brace">{</span> <span class="const_param const">FOO</span> <span class="brace">}</span><span class="angle">></span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="const_param const">FOO</span> <span class="brace">}</span> diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index c6aebd0b0c..aecd1d3fdb 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -210,7 +210,7 @@ fn never() -> ! { loop {} } -fn const_param<const FOO: usize>() -> usize { +fn const_param<const FOO: usize>() -> usize where [(); FOO]: Sized { const_param::<{ FOO }>(); FOO } |