mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
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
This commit is contained in:
commit
e6276c8b64
@ -2,7 +2,7 @@
|
|||||||
use std::{cell::OnceCell, mem};
|
use std::{cell::OnceCell, mem};
|
||||||
|
|
||||||
use hir_expand::{span_map::SpanMap, AstId, HirFileId, InFile};
|
use hir_expand::{span_map::SpanMap, AstId, HirFileId, InFile};
|
||||||
use span::{AstIdMap, AstIdNode};
|
use span::{AstIdMap, AstIdNode, Edition, EditionedFileId, FileId, RealSpanMap};
|
||||||
use stdx::thin_vec::ThinVec;
|
use stdx::thin_vec::ThinVec;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
@ -63,6 +63,30 @@ impl<'a> LowerCtx<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Prepares a `LowerCtx` for synthetic AST that needs to be lowered. This is intended for IDE things.
|
||||||
|
pub fn for_synthetic_ast(
|
||||||
|
db: &'a dyn DefDatabase,
|
||||||
|
ast_id_map: Arc<AstIdMap>,
|
||||||
|
types_map: &'a mut TypesMap,
|
||||||
|
types_source_map: &'a mut TypesSourceMap,
|
||||||
|
) -> Self {
|
||||||
|
let file_id = EditionedFileId::new(
|
||||||
|
FileId::from_raw(EditionedFileId::MAX_FILE_ID),
|
||||||
|
Edition::Edition2015,
|
||||||
|
);
|
||||||
|
LowerCtx {
|
||||||
|
db,
|
||||||
|
// Make up an invalid file id, so that if we will try to actually access it salsa will panic.
|
||||||
|
file_id: file_id.into(),
|
||||||
|
span_map: SpanMap::RealSpanMap(Arc::new(RealSpanMap::absolute(file_id))).into(),
|
||||||
|
ast_id_map: ast_id_map.into(),
|
||||||
|
impl_trait_bounds: Vec::new(),
|
||||||
|
outer_impl_trait: false,
|
||||||
|
types_map,
|
||||||
|
types_source_map,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn span_map(&self) -> &SpanMap {
|
pub(crate) fn span_map(&self) -> &SpanMap {
|
||||||
self.span_map.get_or_init(|| self.db.span_map(self.file_id))
|
self.span_map.get_or_init(|| self.db.span_map(self.file_id))
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ use intern::Symbol;
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use span::{EditionedFileId, FileId, HirFileIdRepr, SyntaxContextId};
|
use span::{AstIdMap, EditionedFileId, FileId, HirFileIdRepr, SyntaxContextId};
|
||||||
use stdx::TupleExt;
|
use stdx::TupleExt;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
algo::skip_trivia_token,
|
algo::skip_trivia_token,
|
||||||
@ -42,6 +42,7 @@ use syntax::{
|
|||||||
AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
|
AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
|
||||||
TextSize,
|
TextSize,
|
||||||
};
|
};
|
||||||
|
use triomphe::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
@ -1973,10 +1974,16 @@ impl SemanticsScope<'_> {
|
|||||||
/// Resolve a path as-if it was written at the given scope. This is
|
/// Resolve a path as-if it was written at the given scope. This is
|
||||||
/// necessary a heuristic, as it doesn't take hygiene into account.
|
/// necessary a heuristic, as it doesn't take hygiene into account.
|
||||||
pub fn speculative_resolve(&self, ast_path: &ast::Path) -> Option<PathResolution> {
|
pub fn speculative_resolve(&self, ast_path: &ast::Path) -> Option<PathResolution> {
|
||||||
|
let root = ast_path.syntax().ancestors().last().unwrap();
|
||||||
|
let ast_id_map = Arc::new(AstIdMap::from_source(&root));
|
||||||
let (mut types_map, mut types_source_map) =
|
let (mut types_map, mut types_source_map) =
|
||||||
(TypesMap::default(), TypesSourceMap::default());
|
(TypesMap::default(), TypesSourceMap::default());
|
||||||
let mut ctx =
|
let mut ctx = LowerCtx::for_synthetic_ast(
|
||||||
LowerCtx::new(self.db.upcast(), self.file_id, &mut types_map, &mut types_source_map);
|
self.db.upcast(),
|
||||||
|
ast_id_map,
|
||||||
|
&mut types_map,
|
||||||
|
&mut types_source_map,
|
||||||
|
);
|
||||||
let path = Path::from_src(&mut ctx, ast_path.clone())?;
|
let path = Path::from_src(&mut ctx, ast_path.clone())?;
|
||||||
resolve_hir_path(
|
resolve_hir_path(
|
||||||
self.db,
|
self.db,
|
||||||
|
@ -2318,4 +2318,49 @@ impl<'a> Test<'a, i32> for bool {
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_17321() {
|
||||||
|
check_assist(
|
||||||
|
add_missing_impl_members,
|
||||||
|
r#"
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
mod other_file_1 {
|
||||||
|
pub const SOME_CONSTANT: usize = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod other_file_2 {
|
||||||
|
use crate::other_file_1::SOME_CONSTANT;
|
||||||
|
|
||||||
|
pub trait Trait {
|
||||||
|
type Iter: Iterator<Item = [u8; SOME_CONSTANT]>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MyStruct;
|
||||||
|
|
||||||
|
impl other_file_2::Trait for MyStruct$0 {}"#,
|
||||||
|
r#"
|
||||||
|
fn main() {}
|
||||||
|
|
||||||
|
mod other_file_1 {
|
||||||
|
pub const SOME_CONSTANT: usize = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod other_file_2 {
|
||||||
|
use crate::other_file_1::SOME_CONSTANT;
|
||||||
|
|
||||||
|
pub trait Trait {
|
||||||
|
type Iter: Iterator<Item = [u8; SOME_CONSTANT]>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MyStruct;
|
||||||
|
|
||||||
|
impl other_file_2::Trait for MyStruct {
|
||||||
|
$0type Iter;
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user