diff --git a/crates/hir-analysis/src/lib.rs b/crates/hir-analysis/src/lib.rs index 1a4109f38..ca66ede92 100644 --- a/crates/hir-analysis/src/lib.rs +++ b/crates/hir-analysis/src/lib.rs @@ -5,10 +5,10 @@ pub struct Jar( // Functions for import/name resolutions. name_resolution::resolve_path_early_impl, name_resolution::resolve_imports, - name_resolution::diagnostics::NameResolutionDiagAccumulator, - name_resolution::diagnostics::ImportResolutionDiagAccumulator, + name_resolution::diagnostics::NameResolutionDiagAccumulator<'_>, + name_resolution::diagnostics::ImportResolutionDiagAccumulator<'_>, name_resolution::traits_in_scope::available_traits_in_scope_impl, - name_resolution::traits_in_scope::TraitScope, + name_resolution::traits_in_scope::TraitScope<'_>, // Type system. ty::ty_def::TyId, ty::ty_def::ty_kind, diff --git a/crates/hir-analysis/src/name_resolution/diagnostics.rs b/crates/hir-analysis/src/name_resolution/diagnostics.rs index 80466dd5c..0f1f76e8b 100644 --- a/crates/hir-analysis/src/name_resolution/diagnostics.rs +++ b/crates/hir-analysis/src/name_resolution/diagnostics.rs @@ -12,44 +12,44 @@ use super::NameRes; use crate::HirAnalysisDb; #[salsa::accumulator] -pub struct NameResolutionDiagAccumulator(pub(super) NameResDiag); +pub struct NameResolutionDiagAccumulator<'db>(pub(super) NameResDiag<'db>); #[salsa::accumulator] -pub struct ImportResolutionDiagAccumulator(pub(super) NameResDiag); +pub struct ImportResolutionDiagAccumulator<'db>(pub(super) NameResDiag<'db>); #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum NameResDiag { +pub enum NameResDiag<'db> { /// The definition conflicts with other definitions. - Conflict(IdentId, Vec), + Conflict(IdentId<'db>, Vec>), /// The name is not found. - NotFound(DynLazySpan, IdentId), + NotFound(DynLazySpan<'db>, IdentId<'db>), /// The resolved name is not visible. - Invisible(DynLazySpan, IdentId, Option), + Invisible(DynLazySpan<'db>, IdentId<'db>, Option>), /// The resolved name is ambiguous. - Ambiguous(DynLazySpan, IdentId, Vec), + Ambiguous(DynLazySpan<'db>, IdentId<'db>, Vec>), /// The name is found, but it can't be used as a middle segment of a path. - InvalidPathSegment(DynLazySpan, IdentId, Option), + InvalidPathSegment(DynLazySpan<'db>, IdentId<'db>, Option>), /// The name is found but belongs to a different name domain other than the /// Type. - ExpectedType(DynLazySpan, IdentId, NameRes), + ExpectedType(DynLazySpan<'db>, IdentId<'db>, NameRes<'db>), /// The name is found but belongs to a different name domain other than the /// trait. - ExpectedTrait(DynLazySpan, IdentId, NameRes), + ExpectedTrait(DynLazySpan<'db>, IdentId<'db>, NameRes<'db>), /// The name is found but belongs to a different name domain other than the /// value. - ExpectedValue(DynLazySpan, IdentId, NameRes), + ExpectedValue(DynLazySpan<'db>, IdentId<'db>, NameRes<'db>), } -impl NameResDiag { +impl<'db> NameResDiag<'db> { /// Returns the top-level module where the diagnostic is located. - pub fn top_mod(&self, db: &dyn HirAnalysisDb) -> TopLevelMod { + pub fn top_mod(&self, db: &'db dyn HirAnalysisDb) -> TopLevelMod<'db> { match self { Self::Conflict(_, conflicts) => conflicts .iter() @@ -67,26 +67,26 @@ impl NameResDiag { } pub(crate) fn invisible( - span: DynLazySpan, - name: IdentId, - invisible_span: Option, + span: DynLazySpan<'db>, + name: IdentId<'db>, + invisible_span: Option>, ) -> Self { Self::Invisible(span, name, invisible_span) } - pub(super) fn conflict(name: IdentId, conflict_with: Vec) -> Self { + pub(super) fn conflict(name: IdentId<'db>, conflict_with: Vec>) -> Self { Self::Conflict(name, conflict_with) } - pub(super) fn not_found(span: DynLazySpan, ident: IdentId) -> Self { + pub(super) fn not_found(span: DynLazySpan<'db>, ident: IdentId<'db>) -> Self { Self::NotFound(span, ident) } pub(super) fn ambiguous( - db: &dyn HirAnalysisDb, - span: DynLazySpan, - ident: IdentId, - cands: Vec, + db: &'db dyn HirAnalysisDb, + span: DynLazySpan<'db>, + ident: IdentId<'db>, + cands: Vec>, ) -> Self { let cands = cands .into_iter() @@ -96,10 +96,10 @@ impl NameResDiag { } pub(super) fn invalid_use_path_segment( - db: &dyn HirAnalysisDb, - span: DynLazySpan, - ident: IdentId, - found: NameRes, + db: &'db dyn HirAnalysisDb, + span: DynLazySpan<'db>, + ident: IdentId<'db>, + found: NameRes<'db>, ) -> Self { let found = found.kind.name_span(db); Self::InvalidPathSegment(span, ident, found) @@ -280,7 +280,7 @@ impl NameResDiag { } } -impl DiagnosticVoucher for NameResDiag { +impl<'db> DiagnosticVoucher for NameResDiag<'db> { fn error_code(&self) -> GlobalErrorCode { GlobalErrorCode::new(DiagnosticPass::NameResolution, self.local_code()) } diff --git a/crates/hir-analysis/src/name_resolution/import_resolver.rs b/crates/hir-analysis/src/name_resolution/import_resolver.rs index 8d3b2c1bf..b4a83d2a8 100644 --- a/crates/hir-analysis/src/name_resolution/import_resolver.rs +++ b/crates/hir-analysis/src/name_resolution/import_resolver.rs @@ -24,31 +24,31 @@ pub(crate) struct ImportResolver<'db> { db: &'db dyn HirAnalysisDb, /// The ingot that is being resolved. - ingot: IngotId, + ingot: IngotId<'db>, /// The set of imports that have been resolved. - resolved_imports: IntermediateResolvedImports, + resolved_imports: IntermediateResolvedImports<'db>, /// The uses that have resolution is work in progress. - intermediate_uses: FxHashMap>, + intermediate_uses: FxHashMap, VecDeque>>, /// The errors that have been accumulated during the import resolution. - accumulated_errors: Vec, + accumulated_errors: Vec>, /// The number of imported resolutions. /// This is used to judge if a import resolution doesn't change in each /// iteration of fixed point calculation. /// This check rely on the fact that the number of resolutions is /// monotonically increasing. - num_imported_res: FxHashMap, + num_imported_res: FxHashMap, usize>, /// The set of imports that are suspicious to be ambiguous. /// In this case, the use will turns out to be ambiguous after the import /// resolution reaches the fixed point. - suspicious_imports: FxHashSet, + suspicious_imports: FxHashSet>, } impl<'db> ImportResolver<'db> { - pub(crate) fn new(db: &'db dyn HirAnalysisDb, ingot: IngotId) -> Self { + pub(crate) fn new(db: &'db dyn HirAnalysisDb, ingot: IngotId<'db>) -> Self { Self { db, ingot, @@ -60,7 +60,7 @@ impl<'db> ImportResolver<'db> { } } - pub(crate) fn resolve_imports(mut self) -> (ResolvedImports, Vec) { + pub(crate) fn resolve_imports(mut self) -> (ResolvedImports<'db>, Vec>) { self.initialize_i_uses(); let mut changed = true; @@ -147,7 +147,10 @@ impl<'db> ImportResolver<'db> { /// /// The second value of the returned tuple indicates whether the resolution /// is progressed from the passed `IntermediateUse`. - fn resolve_i_use(&mut self, i_use: IntermediateUse) -> (Option, bool) { + fn resolve_i_use( + &mut self, + i_use: IntermediateUse<'db>, + ) -> (Option>, bool) { if i_use.is_glob(self.db) { self.resolve_glob(i_use) } else { @@ -156,7 +159,10 @@ impl<'db> ImportResolver<'db> { } /// Try to resolve the given named `IntermediateUse`. - fn resolve_named(&mut self, i_use: IntermediateUse) -> (Option, bool) { + fn resolve_named( + &mut self, + i_use: IntermediateUse<'db>, + ) -> (Option>, bool) { let Some(i_use_res) = self.resolve_base_path(i_use.clone()) else { return (None, true); }; @@ -186,7 +192,10 @@ impl<'db> ImportResolver<'db> { /// /// The second value of the returned tuple indicates whether the resolution /// is progressed from the passed `IntermediateUse`. - fn resolve_glob(&mut self, i_use: IntermediateUse) -> (Option, bool) { + fn resolve_glob( + &mut self, + i_use: IntermediateUse<'db>, + ) -> (Option>, bool) { let (base_path_resolved, changed) = { if i_use.is_base_resolved(self.db) { (i_use, false) @@ -278,7 +287,10 @@ impl<'db> ImportResolver<'db> { /// is unchanged. /// - `None` if the error happens during the resolution, the error is /// accumulated in the function. - fn resolve_base_path(&mut self, mut i_use: IntermediateUse) -> Option { + fn resolve_base_path( + &mut self, + mut i_use: IntermediateUse<'db>, + ) -> Option> { let mut changed = false; if i_use.is_base_resolved(self.db) { return Some(IUseResolution::BasePath(i_use)); @@ -320,7 +332,7 @@ impl<'db> ImportResolver<'db> { /// is unchanged. /// - `None` if the error happens during the resolution, the error is /// accumulated in the function. - fn resolve_segment(&mut self, i_use: &IntermediateUse) -> Option { + fn resolve_segment(&mut self, i_use: &IntermediateUse<'db>) -> Option> { // The segment is syntactically invalid. We can't perform name resolution // anymore. // We don't need to report the error here because the parser should have already @@ -428,7 +440,7 @@ impl<'db> ImportResolver<'db> { } /// Returns `true` if the given `IntermediateUse` reaches the fixed point. - fn try_finalize_named_use(&mut self, i_use: IntermediateUse) -> bool { + fn try_finalize_named_use(&mut self, i_use: IntermediateUse<'db>) -> bool { debug_assert!(i_use.is_base_resolved(self.db)); let bucket = match self.resolve_segment(&i_use) { @@ -480,7 +492,7 @@ impl<'db> ImportResolver<'db> { // the external ingot, so this ambiguity is inherent in import resolution. // As a result, we need to add additional verification to check this kind of // ambiguity. - fn verify_ambiguity(&mut self, use_: Use) { + fn verify_ambiguity(&mut self, use_: Use<'db>) { let i_use = IntermediateUse::new(self.db, use_); let first_segment_ident = i_use.current_segment_ident(self.db).unwrap(); @@ -517,7 +529,7 @@ impl<'db> ImportResolver<'db> { } } - fn register_error(&mut self, i_use: &IntermediateUse, err: NameResolutionError) { + fn register_error(&mut self, i_use: &IntermediateUse<'db>, err: NameResolutionError<'db>) { self.suspicious_imports.remove(&i_use.use_); match err { @@ -569,7 +581,10 @@ impl<'db> ImportResolver<'db> { /// Makes a query for the current segment of the intermediate use to be /// resolved. - fn make_query(&self, i_use: &IntermediateUse) -> NameResolutionResult { + fn make_query( + &self, + i_use: &IntermediateUse<'db>, + ) -> NameResolutionResult<'db, NameQuery<'db>> { let Some(seg_name) = i_use.current_segment_ident(self.db) else { return Err(NameResolutionError::Invalid); }; @@ -664,35 +679,35 @@ impl<'db> ImportResolver<'db> { } #[derive(Clone, Debug, Default, PartialEq, Eq)] -pub struct ResolvedImports { - pub named_resolved: FxHashMap, - pub glob_resolved: FxHashMap, - pub unnamed_resolved: FxHashMap>, +pub struct ResolvedImports<'db> { + pub named_resolved: FxHashMap, NamedImportSet<'db>>, + pub glob_resolved: FxHashMap, GlobImportSet<'db>>, + pub unnamed_resolved: FxHashMap, Vec>>, } -pub(super) trait Importer { +pub(super) trait Importer<'db> { fn named_imports<'a>( &'a self, - db: &'a dyn HirAnalysisDb, - scope: ScopeId, - ) -> Option<&'a NamedImportSet>; + db: &'db dyn HirAnalysisDb, + scope: ScopeId<'db>, + ) -> Option<&'a NamedImportSet<'db>>; fn glob_imports<'a>( &'a self, - db: &'a dyn HirAnalysisDb, - scope: ScopeId, - ) -> Option<&'a GlobImportSet>; + db: &'db dyn HirAnalysisDb, + scope: ScopeId<'db>, + ) -> Option<&'a GlobImportSet<'db>>; } #[derive(Debug, Clone, Copy, Default)] pub(super) struct DefaultImporter; -impl Importer for DefaultImporter { +impl<'db> Importer<'db> for DefaultImporter { fn named_imports<'a>( &'a self, - db: &'a dyn HirAnalysisDb, - scope: ScopeId, - ) -> Option<&'a NamedImportSet> { + db: &'db dyn HirAnalysisDb, + scope: ScopeId<'db>, + ) -> Option<&'a NamedImportSet<'db>> { resolved_imports_for_scope(db, scope) .named_resolved .get(&scope) @@ -700,30 +715,32 @@ impl Importer for DefaultImporter { fn glob_imports<'a>( &'a self, - db: &'a dyn HirAnalysisDb, - scope: ScopeId, - ) -> Option<&'a GlobImportSet> { + db: &'db dyn HirAnalysisDb, + scope: ScopeId<'db>, + ) -> Option<&'a GlobImportSet<'db>> { resolved_imports_for_scope(db, scope) .glob_resolved .get(&scope) } } -pub type NamedImportSet = FxHashMap; +pub type NamedImportSet<'db> = FxHashMap, NameResBucket<'db>>; #[derive(Clone, Debug, Default, PartialEq, Eq)] -pub struct GlobImportSet { - imported: FxHashMap>>, +pub struct GlobImportSet<'db> { + imported: FxHashMap, FxHashMap, Vec>>>, } -impl GlobImportSet { +impl<'db> GlobImportSet<'db> { /// Returns imported resolutions for the given `name`. - pub fn name_res_for(&self, name: IdentId) -> impl Iterator { + pub fn name_res_for(&self, name: IdentId<'db>) -> impl Iterator> { self.imported .values() .flat_map(move |v| v.get(&name).into_iter().flatten()) } - pub fn iter(&self) -> impl Iterator>)> { + pub fn iter( + &self, + ) -> impl Iterator, &FxHashMap, Vec>>)> { self.imported.iter() } } @@ -746,15 +763,15 @@ impl ScopeState { } #[derive(Clone, Debug, PartialEq, Eq, Hash)] -struct IntermediateUse { - use_: Use, - current_res: Option, - original_scope: ScopeId, +struct IntermediateUse<'db> { + use_: Use<'db>, + current_res: Option>, + original_scope: ScopeId<'db>, unresolved_from: usize, } -impl IntermediateUse { - fn new(db: &dyn HirAnalysisDb, use_: Use) -> Self { +impl<'db> IntermediateUse<'db> { + fn new(db: &'db dyn HirAnalysisDb, use_: Use<'db>) -> Self { let scope = ScopeId::from_item(use_.into()) .lex_parent(db.as_hir_db()) .unwrap(); @@ -767,7 +784,7 @@ impl IntermediateUse { } /// Returns the scope that the current resolution is pointed to. - fn current_scope(&self) -> Option { + fn current_scope(&self) -> Option> { if let Some(current_res) = self.current_res.as_ref() { match current_res.kind { NameResKind::Scope(scope) => Some(scope), @@ -787,7 +804,11 @@ impl IntermediateUse { /// for use path segment. # Panics /// - Panics if the the base path is already resolved. /// - Panics if the bucket is empty. - fn proceed(&self, db: &dyn HirAnalysisDb, bucket: NameResBucket) -> NameResolutionResult { + fn proceed( + &self, + db: &'db dyn HirAnalysisDb, + bucket: NameResBucket<'db>, + ) -> NameResolutionResult<'db, Self> { debug_assert!(!bucket.is_empty()); debug_assert!(!self.is_base_resolved(db)); @@ -812,7 +833,7 @@ impl IntermediateUse { } /// Returns the span of the current segment of the use. - fn current_segment_span(&self) -> DynLazySpan { + fn current_segment_span(&self) -> DynLazySpan<'db> { self.use_ .lazy_span() .path() @@ -820,7 +841,7 @@ impl IntermediateUse { .into() } - fn current_segment_ident(&self, db: &dyn HirAnalysisDb) -> Option { + fn current_segment_ident(&self, db: &'db dyn HirAnalysisDb) -> Option> { let segments = self .use_ .path(db.as_hir_db()) @@ -832,7 +853,7 @@ impl IntermediateUse { segment.ident() } - fn imported_name(&self, db: &dyn HirAnalysisDb) -> Option { + fn imported_name(&self, db: &'db dyn HirAnalysisDb) -> Option> { self.use_.imported_name(db.as_hir_db()) } @@ -861,28 +882,28 @@ impl IntermediateUse { } #[derive(Debug, Clone, PartialEq, Eq)] -enum IUseResolution { +enum IUseResolution<'db> { /// The all segments are resolved. - Full(NameResBucket), + Full(NameResBucket<'db>), /// The all path segments except the last one are resolved. - BasePath(IntermediateUse), + BasePath(IntermediateUse<'db>), /// The intermediate use was partially resolved, but still needs further /// resolution. - Partial(IntermediateUse), + Partial(IntermediateUse<'db>), /// There was no change to the intermediate use. - Unchanged(IntermediateUse), + Unchanged(IntermediateUse<'db>), } -struct IntermediateResolvedImports { - resolved_imports: ResolvedImports, - ingot: IngotId, +struct IntermediateResolvedImports<'db> { + resolved_imports: ResolvedImports<'db>, + ingot: IngotId<'db>, } -impl IntermediateResolvedImports { - fn new(ingot: IngotId) -> Self { +impl<'db> IntermediateResolvedImports<'db> { + fn new(ingot: IngotId<'db>) -> Self { Self { resolved_imports: ResolvedImports::default(), ingot, @@ -891,10 +912,10 @@ impl IntermediateResolvedImports { fn set_named_bucket( &mut self, - db: &dyn HirAnalysisDb, - i_use: &IntermediateUse, - mut bucket: NameResBucket, - ) -> NameResolutionResult<()> { + db: &'db dyn HirAnalysisDb, + i_use: &IntermediateUse<'db>, + mut bucket: NameResBucket<'db>, + ) -> NameResolutionResult<'db, ()> { let scope = i_use.original_scope; bucket.set_derivation(NameDerivation::NamedImported(i_use.use_)); @@ -952,8 +973,8 @@ impl IntermediateResolvedImports { fn set_glob_resolutions( &mut self, - i_use: &IntermediateUse, - mut resolutions: FxHashMap>, + i_use: &IntermediateUse<'db>, + mut resolutions: FxHashMap, Vec>>, ) { let scope = i_use.original_scope; for res in resolutions.values_mut().flatten() { @@ -969,12 +990,12 @@ impl IntermediateResolvedImports { } } -impl Importer for IntermediateResolvedImports { +impl<'db> Importer<'db> for IntermediateResolvedImports<'db> { fn named_imports<'a>( &'a self, - db: &'a dyn HirAnalysisDb, - scope: ScopeId, - ) -> Option<&'a NamedImportSet> { + db: &'db dyn HirAnalysisDb, + scope: ScopeId<'db>, + ) -> Option<&'a NamedImportSet<'db>> { if scope.top_mod(db.as_hir_db()).ingot(db.as_hir_db()) != self.ingot { resolved_imports_for_scope(db, scope) .named_resolved @@ -986,9 +1007,9 @@ impl Importer for IntermediateResolvedImports { fn glob_imports<'a>( &'a self, - db: &'a dyn HirAnalysisDb, - scope: ScopeId, - ) -> Option<&'a GlobImportSet> { + db: &'db dyn HirAnalysisDb, + scope: ScopeId<'db>, + ) -> Option<&'a GlobImportSet<'db>> { if scope.top_mod(db.as_hir_db()).ingot(db.as_hir_db()) != self.ingot { resolved_imports_for_scope(db, scope) .glob_resolved @@ -999,12 +1020,15 @@ impl Importer for IntermediateResolvedImports { } } -fn resolved_imports_for_scope(db: &dyn HirAnalysisDb, scope: ScopeId) -> &ResolvedImports { +fn resolved_imports_for_scope<'db>( + db: &'db dyn HirAnalysisDb, + scope: ScopeId<'db>, +) -> &'db ResolvedImports<'db> { let ingot = scope.ingot(db.as_hir_db()); super::resolve_imports(db, ingot) } -impl NameRes { +impl<'db> NameRes<'db> { /// Returns true if the bucket contains an resolution that is not in the /// same ingot as the current resolution of the `i_use`. fn is_external(&self, db: &dyn HirAnalysisDb, ingot: IngotId) -> bool { diff --git a/crates/hir-analysis/src/name_resolution/mod.rs b/crates/hir-analysis/src/name_resolution/mod.rs index bf98969a9..d30518c91 100644 --- a/crates/hir-analysis/src/name_resolution/mod.rs +++ b/crates/hir-analysis/src/name_resolution/mod.rs @@ -40,22 +40,22 @@ use crate::HirAnalysisDb; // Resolves the given path in the given scope. /// It's not necessary to report any error even if the `EarlyResolvedPath` /// contains some errors; it's always reported from [`PathAnalysisPass`]. -pub fn resolve_path_early( - db: &dyn HirAnalysisDb, - path: PathId, - scope: ScopeId, -) -> EarlyResolvedPath { +pub fn resolve_path_early<'db>( + db: &'db dyn HirAnalysisDb, + path: PathId<'db>, + scope: ScopeId<'db>, +) -> EarlyResolvedPath<'db> { resolve_segments_early(db, path.segments(db.as_hir_db()), scope) } /// Resolves the given path segments in the given scope. /// It's not necessary to report any error even if the `EarlyResolvedPath` /// contains some errors; it's always reported from [`PathAnalysisPass`]. -pub fn resolve_segments_early( - db: &dyn HirAnalysisDb, - segments: &[Partial], - scope: ScopeId, -) -> EarlyResolvedPath { +pub fn resolve_segments_early<'db>( + db: &'db dyn HirAnalysisDb, + segments: &[Partial>], + scope: ScopeId<'db>, +) -> EarlyResolvedPath<'db> { // Obtain cache store for the given scope. let cache_store = resolve_path_early_impl(db, scope.top_mod(db.as_hir_db())); let importer = DefaultImporter; @@ -77,7 +77,7 @@ pub fn resolve_segments_early( /// Resolves the given query. If you don't need to resolve customized queries, /// consider using [`resolve_path_early`] or [`resolve_segments_early`] instead. -pub fn resolve_query(db: &dyn HirAnalysisDb, query: NameQuery) -> NameResBucket { +pub fn resolve_query<'db>(db: &'db dyn HirAnalysisDb, query: NameQuery<'db>) -> NameResBucket<'db> { let importer = DefaultImporter; let mut name_resolver = name_resolver::NameResolver::new_no_cache(db, &importer); name_resolver.resolve_query(query) @@ -94,7 +94,7 @@ impl<'db> ImportAnalysisPass<'db> { Self { db } } - pub fn resolve_imports(&self, ingot: IngotId) -> &'db ResolvedImports { + pub fn resolve_imports(&self, ingot: IngotId<'db>) -> &'db ResolvedImports { resolve_imports(self.db, ingot) } } @@ -169,7 +169,10 @@ impl<'db> ModuleAnalysisPass for DefConflictAnalysisPass<'db> { } #[salsa::tracked(return_ref)] -pub fn resolve_imports(db: &dyn HirAnalysisDb, ingot: IngotId) -> ResolvedImports { +pub fn resolve_imports<'db>( + db: &'db dyn HirAnalysisDb, + ingot: IngotId<'db>, +) -> ResolvedImports<'db> { let resolver = import_resolver::ImportResolver::new(db, ingot); let (imports, diags) = resolver.resolve_imports(); for diag in diags { @@ -188,10 +191,10 @@ pub fn resolve_imports(db: &dyn HirAnalysisDb, ingot: IngotId) -> ResolvedImport /// - the path resolution errors at expression and statement level since it /// generally requires type analysis #[salsa::tracked(return_ref)] -pub(crate) fn resolve_path_early_impl( +pub(crate) fn resolve_path_early_impl<'db>( db: &dyn HirAnalysisDb, - top_mod: TopLevelMod, -) -> ResolvedQueryCacheStore { + top_mod: TopLevelMod<'db>, +) -> ResolvedQueryCacheStore<'db> { let importer = DefaultImporter; let mut visitor = EarlyPathVisitor::new(db, &importer); @@ -207,13 +210,13 @@ pub(crate) fn resolve_path_early_impl( struct EarlyPathVisitor<'db, 'a> { db: &'db dyn HirAnalysisDb, inner: name_resolver::NameResolver<'db, 'a>, - diags: Vec, - item_stack: Vec, + diags: Vec>, + item_stack: Vec>, path_ctxt: Vec, /// The set of scopes that have already been conflicted to avoid duplicate /// diagnostics. - already_conflicted: FxHashSet, + already_conflicted: FxHashSet>, } impl<'db, 'a> EarlyPathVisitor<'db, 'a> { @@ -231,10 +234,10 @@ impl<'db, 'a> EarlyPathVisitor<'db, 'a> { fn verify_path( &mut self, - path: PathId, + path: PathId<'db>, scope: ScopeId, - span: LazyPathSpan, - bucket: NameResBucket, + span: LazyPathSpan<'db>, + bucket: NameResBucket<'db>, ) { let path_kind = self.path_ctxt.last().unwrap(); let last_seg_idx = path.len(self.db.as_hir_db()) - 1; @@ -305,7 +308,7 @@ impl<'db, 'a> EarlyPathVisitor<'db, 'a> { } } - fn check_conflict(&mut self, scope: ScopeId) { + fn check_conflict(&mut self, scope: ScopeId<'db>) { if !self.already_conflicted.insert(scope) { return; } @@ -340,7 +343,7 @@ impl<'db, 'a> EarlyPathVisitor<'db, 'a> { }; } - fn make_query_for_conflict_check(&self, scope: ScopeId) -> Option { + fn make_query_for_conflict_check(&self, scope: ScopeId<'db>) -> Option> { let name = scope.name(self.db.as_hir_db())?; let directive = QueryDirective::new() .disallow_lex() @@ -352,8 +355,8 @@ impl<'db, 'a> EarlyPathVisitor<'db, 'a> { } } -impl<'db, 'a> Visitor for EarlyPathVisitor<'db, 'a> { - fn visit_item(&mut self, ctxt: &mut VisitorCtxt<'_, LazyItemSpan>, item: ItemKind) { +impl<'db, 'a> Visitor<'db> for EarlyPathVisitor<'db, 'a> { + fn visit_item(&mut self, ctxt: &mut VisitorCtxt<'db, LazyItemSpan<'db>>, item: ItemKind<'db>) { // We don't need to check use statements for conflicts because they are // already checked in import resolution. if matches!(item, ItemKind::Use(_)) { @@ -383,8 +386,8 @@ impl<'db, 'a> Visitor for EarlyPathVisitor<'db, 'a> { fn visit_trait_ref( &mut self, - ctxt: &mut VisitorCtxt<'_, LazyTraitRefSpan>, - trait_ref: TraitRefId, + ctxt: &mut VisitorCtxt<'db, LazyTraitRefSpan<'db>>, + trait_ref: TraitRefId<'db>, ) { self.path_ctxt.push(ExpectedPathKind::Trait); walk_trait_ref(self, ctxt, trait_ref); @@ -393,8 +396,8 @@ impl<'db, 'a> Visitor for EarlyPathVisitor<'db, 'a> { fn visit_field_def( &mut self, - ctxt: &mut VisitorCtxt<'_, LazyFieldDefSpan>, - field: &hir::hir_def::FieldDef, + ctxt: &mut VisitorCtxt<'db, LazyFieldDefSpan<'db>>, + field: &hir::hir_def::FieldDef<'db>, ) { let scope = ctxt.scope(); self.check_conflict(scope); @@ -403,8 +406,8 @@ impl<'db, 'a> Visitor for EarlyPathVisitor<'db, 'a> { fn visit_variant_def( &mut self, - ctxt: &mut VisitorCtxt<'_, LazyVariantDefSpan>, - variant: &hir::hir_def::VariantDef, + ctxt: &mut VisitorCtxt<'db, LazyVariantDefSpan<'db>>, + variant: &hir::hir_def::VariantDef<'db>, ) { let scope = ctxt.scope(); self.check_conflict(scope); @@ -413,8 +416,8 @@ impl<'db, 'a> Visitor for EarlyPathVisitor<'db, 'a> { fn visit_generic_param( &mut self, - ctxt: &mut VisitorCtxt<'_, LazyGenericParamSpan>, - param: &hir::hir_def::GenericParam, + ctxt: &mut VisitorCtxt<'db, LazyGenericParamSpan<'db>>, + param: &hir::hir_def::GenericParam<'db>, ) { let scope = ctxt.scope(); self.check_conflict(scope); @@ -423,15 +426,15 @@ impl<'db, 'a> Visitor for EarlyPathVisitor<'db, 'a> { fn visit_generic_arg_list( &mut self, - ctxt: &mut VisitorCtxt<'_, LazyGenericArgListSpan>, - args: GenericArgListId, + ctxt: &mut VisitorCtxt<'db, LazyGenericArgListSpan<'db>>, + args: GenericArgListId<'db>, ) { self.path_ctxt.push(ExpectedPathKind::Type); walk_generic_arg_list(self, ctxt, args); self.path_ctxt.pop(); } - fn visit_ty(&mut self, ctxt: &mut VisitorCtxt<'_, LazyTySpan>, ty: TypeId) { + fn visit_ty(&mut self, ctxt: &mut VisitorCtxt<'db, LazyTySpan<'db>>, ty: TypeId<'db>) { self.path_ctxt.push(ExpectedPathKind::Type); walk_ty(self, ctxt, ty); self.path_ctxt.pop(); @@ -439,7 +442,12 @@ impl<'db, 'a> Visitor for EarlyPathVisitor<'db, 'a> { // We don't need to run path analysis on patterns, statements and expressions in // early path resolution. - fn visit_pat(&mut self, ctxt: &mut VisitorCtxt<'_, LazyPatSpan>, pat: PatId, pat_data: &Pat) { + fn visit_pat( + &mut self, + ctxt: &mut VisitorCtxt<'db, LazyPatSpan<'db>>, + pat: PatId, + pat_data: &Pat<'db>, + ) { match pat_data { Pat::PathTuple { .. } | Pat::Record { .. } => { self.path_ctxt.push(ExpectedPathKind::Record) @@ -452,9 +460,9 @@ impl<'db, 'a> Visitor for EarlyPathVisitor<'db, 'a> { fn visit_expr( &mut self, - ctxt: &mut VisitorCtxt<'_, LazyExprSpan>, + ctxt: &mut VisitorCtxt<'db, LazyExprSpan<'db>>, expr: ExprId, - expr_data: &Expr, + expr_data: &Expr<'db>, ) { match expr_data { Expr::RecordInit(..) => { @@ -469,7 +477,7 @@ impl<'db, 'a> Visitor for EarlyPathVisitor<'db, 'a> { self.path_ctxt.pop(); } - fn visit_path(&mut self, ctxt: &mut VisitorCtxt<'_, LazyPathSpan>, path: PathId) { + fn visit_path(&mut self, ctxt: &mut VisitorCtxt<'db, LazyPathSpan<'db>>, path: PathId<'db>) { let scope = ctxt.scope(); let dummy_cache_store = ResolvedQueryCacheStore::no_cache(); diff --git a/crates/hir-analysis/src/name_resolution/name_resolver.rs b/crates/hir-analysis/src/name_resolution/name_resolver.rs index 4b56d5d87..56fdee199 100644 --- a/crates/hir-analysis/src/name_resolution/name_resolver.rs +++ b/crates/hir-analysis/src/name_resolution/name_resolver.rs @@ -26,17 +26,17 @@ use super::{ use crate::HirAnalysisDb; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct NameQuery { +pub struct NameQuery<'db> { /// The name to be resolved. - name: IdentId, + name: IdentId<'db>, /// The scope where the name is resolved. - scope: ScopeId, + scope: ScopeId<'db>, directive: QueryDirective, } -impl NameQuery { +impl<'db> NameQuery<'db> { /// Create a new name query with the default query directive. - pub fn new(name: IdentId, scope: ScopeId) -> Self { + pub fn new(name: IdentId<'db>, scope: ScopeId<'db>) -> Self { Self { name, scope, @@ -45,7 +45,11 @@ impl NameQuery { } /// Create a new name query with the given query directive. - pub fn with_directive(name: IdentId, scope: ScopeId, directive: QueryDirective) -> Self { + pub fn with_directive( + name: IdentId<'db>, + scope: ScopeId<'db>, + directive: QueryDirective, + ) -> Self { Self { name, scope, @@ -114,11 +118,11 @@ impl Default for QueryDirective { /// The results can contain more than one name resolutions which belong to /// different name domains. #[derive(Clone, Debug, Default, PartialEq, Eq)] -pub struct NameResBucket { - pub(super) bucket: FxHashMap>, +pub struct NameResBucket<'db> { + pub(super) bucket: FxHashMap>>, } -impl NameResBucket { +impl<'db> NameResBucket<'db> { /// Returns the number of resolutions in the bucket. pub fn len(&self) -> usize { self.iter().count() @@ -128,22 +132,22 @@ impl NameResBucket { self.len() == 0 } - pub fn iter(&self) -> impl Iterator { + pub fn iter(&self) -> impl Iterator> { self.bucket.values().filter_map(|res| res.as_ref().ok()) } - pub fn iter_mut(&mut self) -> impl Iterator { + pub fn iter_mut(&mut self) -> impl Iterator> { self.bucket.values_mut().filter_map(|res| res.as_mut().ok()) } - pub fn errors(&self) -> impl Iterator { + pub fn errors(&self) -> impl Iterator)> { self.bucket .iter() .filter_map(|(domain, res)| res.as_ref().err().map(|err| (*domain, err))) } /// Returns the resolution of the given `domain`. - pub fn pick(&self, domain: NameDomain) -> &NameResolutionResult { + pub fn pick(&self, domain: NameDomain) -> &NameResolutionResult<'db, NameRes<'db>> { for domain in domain.iter() { if let Some(res) = self.bucket.get(&domain) { return res; @@ -159,7 +163,7 @@ impl NameResBucket { } } - pub(super) fn merge(&mut self, bucket: &NameResBucket) { + pub(super) fn merge(&mut self, bucket: &NameResBucket<'db>) { for (domain, err) in bucket.errors() { if let Err(NameResolutionError::NotFound) = self.pick(domain) { self.bucket.insert(domain, Err(err.clone())); @@ -170,14 +174,14 @@ impl NameResBucket { } } - pub(super) fn set_derivation(&mut self, derivation: NameDerivation) { + pub(super) fn set_derivation(&mut self, derivation: NameDerivation<'db>) { for res in self.iter_mut() { res.derivation = derivation.clone(); } } /// Push the `res` into the set. - fn push(&mut self, res: &NameRes) { + fn push(&mut self, res: &NameRes<'db>) { for domain in res.domain.iter() { match self.bucket.entry(domain) { Entry::Occupied(mut e) => { @@ -232,17 +236,17 @@ impl NameResBucket { } } -impl IntoIterator for NameResBucket { - type Item = NameResolutionResult; - type IntoIter = IntoValues>; +impl<'db> IntoIterator for NameResBucket<'db> { + type Item = NameResolutionResult<'db, NameRes<'db>>; + type IntoIter = IntoValues>>; fn into_iter(self) -> Self::IntoIter { self.bucket.into_values() } } -impl From for NameResBucket { - fn from(res: NameRes) -> Self { +impl<'db> From> for NameResBucket<'db> { + fn from(res: NameRes<'db>) -> Self { let mut names = FxHashMap::default(); names.insert(res.domain, Ok(res)); Self { bucket: names } @@ -251,19 +255,19 @@ impl From for NameResBucket { /// The struct contains the lookup result of a name query. #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct NameRes { +pub struct NameRes<'db> { /// The kind of the resolution. - pub kind: NameResKind, + pub kind: NameResKind<'db>, /// The domain of the name resolution. pub domain: NameDomain, /// Where the resolution is derived from. (e.g, via `use` or item definition /// in the same scope). - pub derivation: NameDerivation, + pub derivation: NameDerivation<'db>, } -impl NameRes { +impl<'db> NameRes<'db> { /// Returns `true` if the name is visible from the given `scope`. - pub fn is_visible(&self, db: &dyn HirAnalysisDb, from: ScopeId) -> bool { + pub fn is_visible(&self, db: &'db dyn HirAnalysisDb, from: ScopeId<'db>) -> bool { let scope_or_use = match self.derivation { NameDerivation::Def | NameDerivation::Prim | NameDerivation::External => { match self.kind { @@ -302,7 +306,7 @@ impl NameRes { } } - pub fn trait_(&self) -> Option { + pub fn trait_(&self) -> Option> { match self.kind { NameResKind::Scope(ScopeId::Item(ItemKind::Trait(trait_))) => Some(trait_), _ => None, @@ -334,7 +338,7 @@ impl NameRes { /// Returns the scope of the name resolution if the name is not a builtin /// type. - pub fn scope(&self) -> Option { + pub fn scope(&self) -> Option> { match self.kind { NameResKind::Scope(scope) => Some(scope), NameResKind::Prim(_) => None, @@ -352,7 +356,7 @@ impl NameRes { } } - pub(super) fn derived_from(&self, db: &dyn HirAnalysisDb) -> Option { + pub(super) fn derived_from(&self, db: &'db dyn HirAnalysisDb) -> Option> { match self.derivation { NameDerivation::Def | NameDerivation::Prim | NameDerivation::External => { self.kind.name_span(db) @@ -374,9 +378,9 @@ impl NameRes { } pub(super) fn new_from_scope( - scope: ScopeId, + scope: ScopeId<'db>, domain: NameDomain, - derivation: NameDerivation, + derivation: NameDerivation<'db>, ) -> Self { Self { kind: scope.into(), @@ -406,22 +410,22 @@ impl NameRes { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, derive_more::From)] -pub enum NameResKind { +pub enum NameResKind<'db> { /// The name is resolved to a scope. - Scope(ScopeId), + Scope(ScopeId<'db>), /// The name is resolved to a primitive type. Prim(PrimTy), } -impl NameResKind { - pub fn name_span(self, db: &dyn HirAnalysisDb) -> Option { +impl<'db> NameResKind<'db> { + pub fn name_span(self, db: &'db dyn HirAnalysisDb) -> Option> { match self { NameResKind::Scope(scope) => scope.name_span(db.as_hir_db()), NameResKind::Prim(_) => None, } } - pub fn name(self, db: &dyn HirAnalysisDb) -> IdentId { + pub fn name(self, db: &'db dyn HirAnalysisDb) -> IdentId<'db> { match self { NameResKind::Scope(scope) => scope.name(db.as_hir_db()).unwrap(), NameResKind::Prim(prim) => prim.name(db.as_hir_db()), @@ -433,35 +437,35 @@ impl NameResKind { /// Name derivation is used to track the origin of a resolution, and to /// determine the shadowing rules. #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub enum NameDerivation { +pub enum NameDerivation<'db> { /// Derived from a definition in the current scope. Def, /// Derived from a named import in the current scope. - NamedImported(Use), + NamedImported(Use<'db>), /// Derived from a glob import in the current scope. - GlobImported(Use), + GlobImported(Use<'db>), /// Derived from lexical parent scope. - Lex(Box), + Lex(Box>), /// Derived from an external ingot. External, /// Derived from a builtin primitive. Prim, } -impl NameDerivation { +impl<'db> NameDerivation<'db> { fn lexed(&mut self) { let inner = mem::replace(self, NameDerivation::Def); *self = NameDerivation::Lex(Box::new(inner)); } } -impl PartialOrd for NameDerivation { +impl<'db> PartialOrd for NameDerivation<'db> { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for NameDerivation { +impl<'db> Ord for NameDerivation<'db> { fn cmp(&self, other: &Self) -> cmp::Ordering { match (self, other) { (NameDerivation::Def, NameDerivation::Def) => cmp::Ordering::Equal, @@ -495,12 +499,12 @@ impl Ord for NameDerivation { pub(crate) struct NameResolver<'db, 'a> { db: &'db dyn HirAnalysisDb, - importer: &'a dyn Importer, - cache_store: ResolvedQueryCacheStore, + importer: &'a dyn Importer<'db>, + cache_store: ResolvedQueryCacheStore<'db>, } impl<'db, 'a> NameResolver<'db, 'a> { - pub(super) fn new(db: &'db dyn HirAnalysisDb, importer: &'a dyn Importer) -> Self { + pub(super) fn new(db: &'db dyn HirAnalysisDb, importer: &'a dyn Importer<'db>) -> Self { Self { db, importer, @@ -508,7 +512,10 @@ impl<'db, 'a> NameResolver<'db, 'a> { } } - pub(super) fn new_no_cache(db: &'db dyn HirAnalysisDb, importer: &'a dyn Importer) -> Self { + pub(super) fn new_no_cache( + db: &'db dyn HirAnalysisDb, + importer: &'a dyn Importer<'db>, + ) -> Self { let cache_store = ResolvedQueryCacheStore { no_cache: true, ..Default::default() @@ -520,11 +527,11 @@ impl<'db, 'a> NameResolver<'db, 'a> { } } - pub(super) fn into_cache_store(self) -> ResolvedQueryCacheStore { + pub(super) fn into_cache_store(self) -> ResolvedQueryCacheStore<'db> { self.cache_store } - pub(crate) fn resolve_query(&mut self, query: NameQuery) -> NameResBucket { + pub(crate) fn resolve_query(&mut self, query: NameQuery<'db>) -> NameResBucket<'db> { let hir_db = self.db.as_hir_db(); // If the query is already resolved, return the cached result. if let Some(resolved) = self.cache_store.get(query) { @@ -542,7 +549,7 @@ impl<'db, 'a> NameResolver<'db, 'a> { // 1. Look for the name in the current scope. let mut found_scopes = FxHashSet::default(); for edge in query.scope.edges(hir_db) { - match edge.kind.propagate(&query) { + match edge.kind.propagate(self.db, &query) { PropagationResult::Terminated => { if found_scopes.insert(edge.dest) { let res = NameRes::new_from_scope( @@ -668,10 +675,10 @@ impl<'db, 'a> NameResolver<'db, 'a> { /// ``` pub(super) fn collect_all_resolutions_for_glob( &mut self, - target: ScopeId, - use_scope: ScopeId, - unresolved_named_imports: FxHashSet, - ) -> FxHashMap> { + target: ScopeId<'db>, + use_scope: ScopeId<'db>, + unresolved_named_imports: FxHashSet>, + ) -> FxHashMap, Vec>> { let mut res_collection: FxHashMap> = FxHashMap::default(); let mut found_domains: FxHashMap = FxHashMap::default(); let mut found_kinds: FxHashSet<(IdentId, NameResKind)> = FxHashSet::default(); @@ -754,14 +761,18 @@ impl<'db, 'a> NameResolver<'db, 'a> { } /// Finalize the query result and cache it to the cache store. - fn finalize_query_result(&mut self, query: NameQuery, bucket: NameResBucket) -> NameResBucket { + fn finalize_query_result( + &mut self, + query: NameQuery<'db>, + bucket: NameResBucket<'db>, + ) -> NameResBucket<'db> { self.cache_store.cache_result(query, bucket.clone()); bucket } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum NameResolutionError { +pub enum NameResolutionError<'db> { /// The name is not found. NotFound, @@ -770,21 +781,21 @@ pub enum NameResolutionError { Invalid, /// The name is found, but it's not visible from the reference site. - Invisible(Option), + Invisible(Option>), /// The name is found, but it's ambiguous. - Ambiguous(Vec), + Ambiguous(Vec>), /// The name is found, but it can't be used in the middle of a use path. - InvalidPathSegment(NameRes), + InvalidPathSegment(NameRes<'db>), /// The definition conflicts with other definitions. - Conflict(IdentId, Vec), + Conflict(IdentId<'db>, Vec>), } -pub type NameResolutionResult = Result; +pub type NameResolutionResult<'db, T> = Result>; -impl fmt::Display for NameResolutionError { +impl<'db> fmt::Display for NameResolutionError<'db> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { NameResolutionError::NotFound => write!(f, "name not found"), @@ -800,16 +811,16 @@ impl fmt::Display for NameResolutionError { } } -impl std::error::Error for NameResolutionError {} +impl<'db> std::error::Error for NameResolutionError<'db> {} #[derive(Default, Debug, PartialEq, Eq)] -pub(crate) struct ResolvedQueryCacheStore { - cache: FxHashMap, +pub(crate) struct ResolvedQueryCacheStore<'db> { + cache: FxHashMap, NameResBucket<'db>>, no_cache: bool, } -impl ResolvedQueryCacheStore { - pub(super) fn get(&self, query: NameQuery) -> Option<&NameResBucket> { +impl<'db> ResolvedQueryCacheStore<'db> { + pub(super) fn get(&self, query: NameQuery<'db>) -> Option<&NameResBucket<'db>> { self.cache.get(&query) } @@ -820,7 +831,7 @@ impl ResolvedQueryCacheStore { } } - fn cache_result(&mut self, query: NameQuery, result: NameResBucket) { + fn cache_result(&mut self, query: NameQuery<'db>, result: NameResBucket<'db>) { if self.no_cache { return; } @@ -884,7 +895,7 @@ impl Default for NameDomain { /// The propagator controls how the name query is propagated to the next scope. trait QueryPropagator { - fn propagate(self, query: &NameQuery) -> PropagationResult; + fn propagate(self, db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult; fn propagate_glob(self) -> PropagationResult; } @@ -900,7 +911,7 @@ enum PropagationResult { } impl QueryPropagator for LexEdge { - fn propagate(self, query: &NameQuery) -> PropagationResult { + fn propagate(self, _db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { if query.directive.allow_lex { PropagationResult::Continuation } else { @@ -913,8 +924,8 @@ impl QueryPropagator for LexEdge { } } -impl QueryPropagator for ModEdge { - fn propagate(self, query: &NameQuery) -> PropagationResult { +impl<'db> QueryPropagator for ModEdge<'db> { + fn propagate(self, _db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { if self.0 == query.name { PropagationResult::Terminated } else { @@ -927,8 +938,8 @@ impl QueryPropagator for ModEdge { } } -impl QueryPropagator for TypeEdge { - fn propagate(self, query: &NameQuery) -> PropagationResult { +impl<'db> QueryPropagator for TypeEdge<'db> { + fn propagate(self, _db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { if self.0 == query.name { PropagationResult::Terminated } else { @@ -941,8 +952,8 @@ impl QueryPropagator for TypeEdge { } } -impl QueryPropagator for TraitEdge { - fn propagate(self, query: &NameQuery) -> PropagationResult { +impl<'db> QueryPropagator for TraitEdge<'db> { + fn propagate(self, _db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { if self.0 == query.name { PropagationResult::Terminated } else { @@ -955,8 +966,8 @@ impl QueryPropagator for TraitEdge { } } -impl QueryPropagator for ValueEdge { - fn propagate(self, query: &NameQuery) -> PropagationResult { +impl<'db> QueryPropagator for ValueEdge<'db> { + fn propagate(self, _db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { if self.0 == query.name { PropagationResult::Terminated } else { @@ -969,8 +980,8 @@ impl QueryPropagator for ValueEdge { } } -impl QueryPropagator for GenericParamEdge { - fn propagate(self, query: &NameQuery) -> PropagationResult { +impl<'db> QueryPropagator for GenericParamEdge<'db> { + fn propagate(self, _db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { if self.0 == query.name { PropagationResult::Terminated } else { @@ -983,8 +994,8 @@ impl QueryPropagator for GenericParamEdge { } } -impl QueryPropagator for FieldEdge { - fn propagate(self, query: &NameQuery) -> PropagationResult { +impl<'db> QueryPropagator for FieldEdge<'db> { + fn propagate(self, _db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { if self.0 == query.name { PropagationResult::Terminated } else { @@ -997,8 +1008,8 @@ impl QueryPropagator for FieldEdge { } } -impl QueryPropagator for VariantEdge { - fn propagate(self, query: &NameQuery) -> PropagationResult { +impl<'db> QueryPropagator for VariantEdge<'db> { + fn propagate(self, _db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { if self.0 == query.name { PropagationResult::Terminated } else { @@ -1012,8 +1023,8 @@ impl QueryPropagator for VariantEdge { } impl QueryPropagator for SuperEdge { - fn propagate(self, query: &NameQuery) -> PropagationResult { - if query.name.is_super() { + fn propagate(self, db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { + if query.name.is_super(db.as_hir_db()) { PropagationResult::Terminated } else { PropagationResult::UnPropagated @@ -1026,8 +1037,8 @@ impl QueryPropagator for SuperEdge { } impl QueryPropagator for IngotEdge { - fn propagate(self, query: &NameQuery) -> PropagationResult { - if query.name.is_ingot() { + fn propagate(self, db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { + if query.name.is_ingot(db.as_hir_db()) { PropagationResult::Terminated } else { PropagationResult::UnPropagated @@ -1040,8 +1051,8 @@ impl QueryPropagator for IngotEdge { } impl QueryPropagator for SelfTyEdge { - fn propagate(self, query: &NameQuery) -> PropagationResult { - if query.name.is_self_ty() { + fn propagate(self, db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { + if query.name.is_self_ty(db.as_hir_db()) { PropagationResult::Terminated } else { PropagationResult::UnPropagated @@ -1054,8 +1065,8 @@ impl QueryPropagator for SelfTyEdge { } impl QueryPropagator for SelfEdge { - fn propagate(self, query: &NameQuery) -> PropagationResult { - if query.name.is_self() { + fn propagate(self, db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { + if query.name.is_self(db.as_hir_db()) { PropagationResult::Terminated } else { PropagationResult::UnPropagated @@ -1068,7 +1079,7 @@ impl QueryPropagator for SelfEdge { } impl QueryPropagator for AnonEdge { - fn propagate(self, _query: &NameQuery) -> PropagationResult { + fn propagate(self, _db: &dyn HirAnalysisDb, _query: &NameQuery) -> PropagationResult { PropagationResult::UnPropagated } @@ -1077,22 +1088,22 @@ impl QueryPropagator for AnonEdge { } } -impl QueryPropagator for EdgeKind { - fn propagate(self, query: &NameQuery) -> PropagationResult { +impl<'db> QueryPropagator for EdgeKind<'db> { + fn propagate(self, db: &dyn HirAnalysisDb, query: &NameQuery) -> PropagationResult { match self { - EdgeKind::Lex(edge) => edge.propagate(query), - EdgeKind::Mod(edge) => edge.propagate(query), - EdgeKind::Type(edge) => edge.propagate(query), - EdgeKind::Trait(edge) => edge.propagate(query), - EdgeKind::GenericParam(edge) => edge.propagate(query), - EdgeKind::Value(edge) => edge.propagate(query), - EdgeKind::Field(edge) => edge.propagate(query), - EdgeKind::Variant(edge) => edge.propagate(query), - EdgeKind::Super(edge) => edge.propagate(query), - EdgeKind::Ingot(edge) => edge.propagate(query), - EdgeKind::Self_(edge) => edge.propagate(query), - EdgeKind::SelfTy(edge) => edge.propagate(query), - EdgeKind::Anon(edge) => edge.propagate(query), + EdgeKind::Lex(edge) => edge.propagate(db, query), + EdgeKind::Mod(edge) => edge.propagate(db, query), + EdgeKind::Type(edge) => edge.propagate(db, query), + EdgeKind::Trait(edge) => edge.propagate(db, query), + EdgeKind::GenericParam(edge) => edge.propagate(db, query), + EdgeKind::Value(edge) => edge.propagate(db, query), + EdgeKind::Field(edge) => edge.propagate(db, query), + EdgeKind::Variant(edge) => edge.propagate(db, query), + EdgeKind::Super(edge) => edge.propagate(db, query), + EdgeKind::Ingot(edge) => edge.propagate(db, query), + EdgeKind::Self_(edge) => edge.propagate(db, query), + EdgeKind::SelfTy(edge) => edge.propagate(db, query), + EdgeKind::Anon(edge) => edge.propagate(db, query), } } diff --git a/crates/hir-analysis/src/name_resolution/path_resolver.rs b/crates/hir-analysis/src/name_resolution/path_resolver.rs index a7574e034..fe933eb99 100644 --- a/crates/hir-analysis/src/name_resolution/path_resolver.rs +++ b/crates/hir-analysis/src/name_resolution/path_resolver.rs @@ -1,5 +1,5 @@ #![allow(unused)] -use hir::hir_def::{kw, scope_graph::ScopeId, IdentId, Partial, PathId}; +use hir::hir_def::{scope_graph::ScopeId, IdentId, Partial, PathId}; use super::{ name_resolver::{ @@ -20,34 +20,34 @@ use crate::{ /// to a type, and the rest of the path depends on the type to resolve. /// Type/Trait context is needed to resolve the rest of the path. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum EarlyResolvedPath { - Full(NameResBucket), +pub enum EarlyResolvedPath<'db> { + Full(NameResBucket<'db>), /// The path is partially resolved; this means that the `resolved` is a type /// and the following segments depend on type to resolve. /// These unresolved parts are resolved in the later type inference and /// trait solving phases. Partial { - res: NameRes, + res: NameRes<'db>, unresolved_from: usize, }, } -pub(super) struct EarlyResolvedPathWithTrajectory { - pub(super) resolved: EarlyResolvedPath, +pub(super) struct EarlyResolvedPathWithTrajectory<'db> { + pub(super) resolved: EarlyResolvedPath<'db>, /// The trajectory of the resolution, which starts with the original scope /// of the resolution, then goes through the resolution of each segment. /// This trajectory doesn't include the final resolution of the path, which /// is stored in `resolved`. e.g., for the query `std::foo::Bar` from /// `crate::baz`, the trajectory is `crate::baz -> std -> foo`. - pub(super) trajectory: Vec, + pub(super) trajectory: Vec>, } -impl EarlyResolvedPathWithTrajectory { +impl<'db> EarlyResolvedPathWithTrajectory<'db> { pub(super) fn find_invisible_segment( &self, - db: &dyn HirAnalysisDb, - ) -> Option<(usize, &NameRes)> { + db: &'db dyn HirAnalysisDb, + ) -> Option<(usize, &NameRes<'db>)> { let original_scope = self.trajectory.first().unwrap().scope().unwrap(); for (i, res) in self.trajectory[1..].iter().enumerate() { if !res.is_visible(db, original_scope) { @@ -58,21 +58,21 @@ impl EarlyResolvedPathWithTrajectory { None } - pub(super) fn resolved_at(&self, index: usize) -> &NameRes { + pub(super) fn resolved_at(&self, index: usize) -> &NameRes<'db> { &self.trajectory[index] } } -pub type PathResolutionResult = Result; +pub type PathResolutionResult<'db, T> = Result>; #[derive(Debug, derive_more::Display, Clone, PartialEq, Eq, Hash, derive_more::Error)] #[display(fmt = "failed_at: {failed_at}, kind: {kind}")] -pub struct PathResolutionError { - pub(crate) kind: NameResolutionError, +pub struct PathResolutionError<'db> { + pub(crate) kind: NameResolutionError<'db>, pub(crate) failed_at: usize, } -impl PathResolutionError { - fn new(kind: NameResolutionError, failed_at: usize) -> Self { +impl<'db> PathResolutionError<'db> { + fn new(kind: NameResolutionError<'db>, failed_at: usize) -> Self { Self { kind, failed_at } } } @@ -80,14 +80,14 @@ impl PathResolutionError { pub(super) struct EarlyPathResolver<'db, 'a, 'b, 'c> { db: &'db dyn HirAnalysisDb, name_resolver: &'a mut NameResolver<'db, 'b>, - cache_store: &'c ResolvedQueryCacheStore, + cache_store: &'c ResolvedQueryCacheStore<'db>, } impl<'db, 'a, 'b, 'c> EarlyPathResolver<'db, 'a, 'b, 'c> { pub(super) fn new( db: &'db dyn HirAnalysisDb, name_resolver: &'a mut NameResolver<'db, 'b>, - cache_store: &'c ResolvedQueryCacheStore, + cache_store: &'c ResolvedQueryCacheStore<'db>, ) -> Self { Self { db, @@ -99,18 +99,18 @@ impl<'db, 'a, 'b, 'c> EarlyPathResolver<'db, 'a, 'b, 'c> { /// Resolves the given `path` in the given `scope`. pub(super) fn resolve_path( &mut self, - path: PathId, - scope: ScopeId, - ) -> PathResolutionResult { + path: PathId<'db>, + scope: ScopeId<'db>, + ) -> PathResolutionResult<'db, EarlyResolvedPathWithTrajectory<'db>> { self.resolve_segments(path.segments(self.db.as_hir_db()), scope) } /// Resolves the given `segments` in the given `scope`. pub(super) fn resolve_segments( &mut self, - segments: &[Partial], - scope: ScopeId, - ) -> PathResolutionResult { + segments: &[Partial>], + scope: ScopeId<'db>, + ) -> PathResolutionResult<'db, EarlyResolvedPathWithTrajectory<'db>> { let mut i_path = IntermediatePath::new(self.db, segments, scope); loop { match i_path.state(self.db) { @@ -128,7 +128,10 @@ impl<'db, 'a, 'b, 'c> EarlyPathResolver<'db, 'a, 'b, 'c> { } } - fn resolve_segment(&mut self, i_path: &mut IntermediatePath) -> PathResolutionResult<()> { + fn resolve_segment( + &mut self, + i_path: &mut IntermediatePath<'db, '_>, + ) -> PathResolutionResult<'db, ()> { let query = i_path.make_query(self.db)?; let bucket = self.resolve_query(query); i_path.proceed(bucket) @@ -136,13 +139,13 @@ impl<'db, 'a, 'b, 'c> EarlyPathResolver<'db, 'a, 'b, 'c> { fn resolve_last_segment( &mut self, - i_path: &IntermediatePath, - ) -> PathResolutionResult { + i_path: &IntermediatePath<'db, '_>, + ) -> PathResolutionResult<'db, NameResBucket<'db>> { let query = i_path.make_query(self.db)?; Ok(self.resolve_query(query)) } - fn resolve_query(&mut self, query: NameQuery) -> NameResBucket { + fn resolve_query(&mut self, query: NameQuery<'db>) -> NameResBucket<'db> { if let Some(bucket) = self.cache_store.get(query) { bucket.clone() } else { @@ -151,15 +154,19 @@ impl<'db, 'a, 'b, 'c> EarlyPathResolver<'db, 'a, 'b, 'c> { } } -struct IntermediatePath<'a> { - path: &'a [Partial], +struct IntermediatePath<'db, 'a> { + path: &'a [Partial>], idx: usize, - current_res: NameRes, - trajectory: Vec, + current_res: NameRes<'db>, + trajectory: Vec>, } -impl<'a> IntermediatePath<'a> { - fn new(db: &dyn HirAnalysisDb, path: &'a [Partial], scope: ScopeId) -> Self { +impl<'db, 'a> IntermediatePath<'db, 'a> { + fn new( + db: &'db dyn HirAnalysisDb, + path: &'a [Partial>], + scope: ScopeId<'db>, + ) -> Self { let domain = NameDomain::from_scope(db, scope); Self { path, @@ -182,7 +189,7 @@ impl<'a> IntermediatePath<'a> { } /// Make a `NameQuery` to resolve the current segment. - fn make_query(&self, db: &dyn HirAnalysisDb) -> PathResolutionResult { + fn make_query(&self, db: &'db dyn HirAnalysisDb) -> PathResolutionResult<'db, NameQuery<'db>> { debug_assert!(self.state(db) != IntermediatePathState::Partial); let Partial::Present(name) = self.path[self.idx] else { return Err(PathResolutionError::new( @@ -208,7 +215,7 @@ impl<'a> IntermediatePath<'a> { } /// Finalizes the `IntermediatePath` as a `EarlyResolvedPath::Partial`. - fn finalize_as_partial(self) -> EarlyResolvedPathWithTrajectory { + fn finalize_as_partial(self) -> EarlyResolvedPathWithTrajectory<'db> { let resolved = EarlyResolvedPath::Partial { res: self.current_res.clone(), unresolved_from: self.idx, @@ -225,7 +232,10 @@ impl<'a> IntermediatePath<'a> { } /// Finalizes the `IntermediatePath` as a `EarlyResolvedPath::Full`. - fn finalize_as_full(mut self, bucket: NameResBucket) -> EarlyResolvedPathWithTrajectory { + fn finalize_as_full( + mut self, + bucket: NameResBucket<'db>, + ) -> EarlyResolvedPathWithTrajectory<'db> { let resolved = EarlyResolvedPath::Full(bucket); let mut trajectory = self.trajectory; let current_res = self.current_res; @@ -240,7 +250,7 @@ impl<'a> IntermediatePath<'a> { /// Proceeds to the next segment with the given `bucket`. /// If the `bucket` doesn't contain proper resolution, then an error is /// returned. - fn proceed(&mut self, bucket: NameResBucket) -> PathResolutionResult<()> { + fn proceed(&mut self, bucket: NameResBucket<'db>) -> PathResolutionResult<'db, ()> { let next_res = match bucket.pick(NameDomain::TYPE) { Ok(res) => Ok(res.clone()), Err(NameResolutionError::NotFound) => { @@ -265,12 +275,12 @@ impl<'a> IntermediatePath<'a> { Ok(()) } - fn state(&self, db: &dyn HirAnalysisDb) -> IntermediatePathState { + fn state(&self, db: &'db dyn HirAnalysisDb) -> IntermediatePathState { debug_assert!(self.idx < self.path.len()); let should_partial = (self.current_res.is_type() || self.current_res.is_trait() - || self.starts_with(db, kw::SELF_TY)) + || self.starts_with(db, IdentId::make_self_ty(db.as_hir_db()))) && self.idx != 0; if (self.idx == self.path.len() - 1) && !should_partial { diff --git a/crates/hir-analysis/src/name_resolution/traits_in_scope.rs b/crates/hir-analysis/src/name_resolution/traits_in_scope.rs index bf7fdae4d..86f830077 100644 --- a/crates/hir-analysis/src/name_resolution/traits_in_scope.rs +++ b/crates/hir-analysis/src/name_resolution/traits_in_scope.rs @@ -4,17 +4,20 @@ use rustc_hash::FxHashSet; use crate::{name_resolution::resolve_imports, HirAnalysisDb}; /// Returns the all traits that are available in the given scope. -pub fn available_traits_in_scope(db: &dyn HirAnalysisDb, scope: ScopeId) -> &FxHashSet { +pub fn available_traits_in_scope<'db>( + db: &'db dyn HirAnalysisDb, + scope: ScopeId<'db>, +) -> &'db FxHashSet> { let scope_kind = TraitScopeKind::from_scope(db, scope); let trait_scope = TraitScope::new(db, scope_kind); available_traits_in_scope_impl(db, trait_scope) } #[salsa::tracked(return_ref)] -pub(crate) fn available_traits_in_scope_impl( - db: &dyn HirAnalysisDb, - t_scope: TraitScope, -) -> FxHashSet { +pub(crate) fn available_traits_in_scope_impl<'db>( + db: &'db dyn HirAnalysisDb, + t_scope: TraitScope<'db>, +) -> FxHashSet> { let mut traits = FxHashSet::default(); let scope = t_scope.inner(db).to_scope(); @@ -66,19 +69,19 @@ pub(crate) fn available_traits_in_scope_impl( } #[salsa::interned] -pub(crate) struct TraitScope { - inner: TraitScopeKind, +pub(crate) struct TraitScope<'db> { + inner: TraitScopeKind<'db>, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -enum TraitScopeKind { - TopLevelMod(TopLevelMod), - Module(Mod), - Block(Body, ExprId), +enum TraitScopeKind<'db> { + TopLevelMod(TopLevelMod<'db>), + Module(Mod<'db>), + Block(Body<'db>, ExprId), } -impl TraitScopeKind { - fn from_scope(db: &dyn HirAnalysisDb, mut scope: ScopeId) -> Self { +impl<'db> TraitScopeKind<'db> { + fn from_scope(db: &'db dyn HirAnalysisDb, mut scope: ScopeId<'db>) -> Self { loop { match scope { ScopeId::Item(item) => match item {