Skip to content

Commit e6276c8

Browse files
authored
Merge pull request #18555 from ChayimFriedman2/issue-17321
fix: Fix a bug when synthetic AST node were searched in the AST ID map and caused panics
2 parents a74c90b + b66bc91 commit e6276c8

File tree

3 files changed

+80
-4
lines changed

3 files changed

+80
-4
lines changed

crates/hir-def/src/lower.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use std::{cell::OnceCell, mem};
33

44
use hir_expand::{span_map::SpanMap, AstId, HirFileId, InFile};
5-
use span::{AstIdMap, AstIdNode};
5+
use span::{AstIdMap, AstIdNode, Edition, EditionedFileId, FileId, RealSpanMap};
66
use stdx::thin_vec::ThinVec;
77
use syntax::ast;
88
use triomphe::Arc;
@@ -63,6 +63,30 @@ impl<'a> LowerCtx<'a> {
6363
}
6464
}
6565

66+
/// Prepares a `LowerCtx` for synthetic AST that needs to be lowered. This is intended for IDE things.
67+
pub fn for_synthetic_ast(
68+
db: &'a dyn DefDatabase,
69+
ast_id_map: Arc<AstIdMap>,
70+
types_map: &'a mut TypesMap,
71+
types_source_map: &'a mut TypesSourceMap,
72+
) -> Self {
73+
let file_id = EditionedFileId::new(
74+
FileId::from_raw(EditionedFileId::MAX_FILE_ID),
75+
Edition::Edition2015,
76+
);
77+
LowerCtx {
78+
db,
79+
// Make up an invalid file id, so that if we will try to actually access it salsa will panic.
80+
file_id: file_id.into(),
81+
span_map: SpanMap::RealSpanMap(Arc::new(RealSpanMap::absolute(file_id))).into(),
82+
ast_id_map: ast_id_map.into(),
83+
impl_trait_bounds: Vec::new(),
84+
outer_impl_trait: false,
85+
types_map,
86+
types_source_map,
87+
}
88+
}
89+
6690
pub(crate) fn span_map(&self) -> &SpanMap {
6791
self.span_map.get_or_init(|| self.db.span_map(self.file_id))
6892
}

crates/hir/src/semantics.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,15 @@ use intern::Symbol;
3434
use itertools::Itertools;
3535
use rustc_hash::{FxHashMap, FxHashSet};
3636
use smallvec::{smallvec, SmallVec};
37-
use span::{EditionedFileId, FileId, HirFileIdRepr, SyntaxContextId};
37+
use span::{AstIdMap, EditionedFileId, FileId, HirFileIdRepr, SyntaxContextId};
3838
use stdx::TupleExt;
3939
use syntax::{
4040
algo::skip_trivia_token,
4141
ast::{self, HasAttrs as _, HasGenericParams, IsString as _},
4242
AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
4343
TextSize,
4444
};
45+
use triomphe::Arc;
4546

4647
use crate::{
4748
db::HirDatabase,
@@ -1973,10 +1974,16 @@ impl SemanticsScope<'_> {
19731974
/// Resolve a path as-if it was written at the given scope. This is
19741975
/// necessary a heuristic, as it doesn't take hygiene into account.
19751976
pub fn speculative_resolve(&self, ast_path: &ast::Path) -> Option<PathResolution> {
1977+
let root = ast_path.syntax().ancestors().last().unwrap();
1978+
let ast_id_map = Arc::new(AstIdMap::from_source(&root));
19761979
let (mut types_map, mut types_source_map) =
19771980
(TypesMap::default(), TypesSourceMap::default());
1978-
let mut ctx =
1979-
LowerCtx::new(self.db.upcast(), self.file_id, &mut types_map, &mut types_source_map);
1981+
let mut ctx = LowerCtx::for_synthetic_ast(
1982+
self.db.upcast(),
1983+
ast_id_map,
1984+
&mut types_map,
1985+
&mut types_source_map,
1986+
);
19801987
let path = Path::from_src(&mut ctx, ast_path.clone())?;
19811988
resolve_hir_path(
19821989
self.db,

crates/ide-assists/src/handlers/add_missing_impl_members.rs

+45
Original file line numberDiff line numberDiff line change
@@ -2318,4 +2318,49 @@ impl<'a> Test<'a, i32> for bool {
23182318
"#,
23192319
);
23202320
}
2321+
2322+
#[test]
2323+
fn issue_17321() {
2324+
check_assist(
2325+
add_missing_impl_members,
2326+
r#"
2327+
fn main() {}
2328+
2329+
mod other_file_1 {
2330+
pub const SOME_CONSTANT: usize = 8;
2331+
}
2332+
2333+
mod other_file_2 {
2334+
use crate::other_file_1::SOME_CONSTANT;
2335+
2336+
pub trait Trait {
2337+
type Iter: Iterator<Item = [u8; SOME_CONSTANT]>;
2338+
}
2339+
}
2340+
2341+
pub struct MyStruct;
2342+
2343+
impl other_file_2::Trait for MyStruct$0 {}"#,
2344+
r#"
2345+
fn main() {}
2346+
2347+
mod other_file_1 {
2348+
pub const SOME_CONSTANT: usize = 8;
2349+
}
2350+
2351+
mod other_file_2 {
2352+
use crate::other_file_1::SOME_CONSTANT;
2353+
2354+
pub trait Trait {
2355+
type Iter: Iterator<Item = [u8; SOME_CONSTANT]>;
2356+
}
2357+
}
2358+
2359+
pub struct MyStruct;
2360+
2361+
impl other_file_2::Trait for MyStruct {
2362+
$0type Iter;
2363+
}"#,
2364+
);
2365+
}
23212366
}

0 commit comments

Comments
 (0)