mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 14:51:48 +00:00
⬆️ rust-analyzer
This commit is contained in:
parent
31519bb394
commit
3e358a6827
74 changed files with 2091 additions and 951 deletions
|
@ -6,7 +6,7 @@
|
|||
//!
|
||||
//! This usually involves resolving names, collecting generic arguments etc.
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
cell::{Cell, RefCell, RefMut},
|
||||
iter,
|
||||
sync::Arc,
|
||||
};
|
||||
|
@ -330,26 +330,26 @@ impl<'a> TyLoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
TypeRef::Macro(macro_call) => {
|
||||
let (expander, recursion_start) = {
|
||||
let mut expander = self.expander.borrow_mut();
|
||||
if expander.is_some() {
|
||||
(Some(expander), false)
|
||||
} else {
|
||||
*expander = Some(Expander::new(
|
||||
self.db.upcast(),
|
||||
macro_call.file_id,
|
||||
self.resolver.module(),
|
||||
));
|
||||
(Some(expander), true)
|
||||
let (mut expander, recursion_start) = {
|
||||
match RefMut::filter_map(self.expander.borrow_mut(), Option::as_mut) {
|
||||
Ok(expander) => (expander, false),
|
||||
Err(expander) => (
|
||||
RefMut::map(expander, |it| {
|
||||
it.insert(Expander::new(
|
||||
self.db.upcast(),
|
||||
macro_call.file_id,
|
||||
self.resolver.module(),
|
||||
))
|
||||
}),
|
||||
true,
|
||||
),
|
||||
}
|
||||
};
|
||||
let ty = if let Some(mut expander) = expander {
|
||||
let expander_mut = expander.as_mut().unwrap();
|
||||
let ty = {
|
||||
let macro_call = macro_call.to_node(self.db.upcast());
|
||||
match expander_mut.enter_expand::<ast::Type>(self.db.upcast(), macro_call) {
|
||||
match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call) {
|
||||
Ok(ExpandResult { value: Some((mark, expanded)), .. }) => {
|
||||
let ctx =
|
||||
LowerCtx::new(self.db.upcast(), expander_mut.current_file_id());
|
||||
let ctx = LowerCtx::new(self.db.upcast(), expander.current_file_id());
|
||||
let type_ref = TypeRef::from_ast(&ctx, expanded);
|
||||
|
||||
drop(expander);
|
||||
|
@ -364,8 +364,6 @@ impl<'a> TyLoweringContext<'a> {
|
|||
}
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if recursion_start {
|
||||
*self.expander.borrow_mut() = None;
|
||||
|
@ -479,7 +477,14 @@ impl<'a> TyLoweringContext<'a> {
|
|||
TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into()))
|
||||
}
|
||||
ParamLoweringMode::Variable => {
|
||||
let idx = generics.param_idx(param_id.into()).expect("matching generics");
|
||||
let idx = match generics.param_idx(param_id.into()) {
|
||||
None => {
|
||||
never!("no matching generics");
|
||||
return (TyKind::Error.intern(Interner), None);
|
||||
}
|
||||
Some(idx) => idx,
|
||||
};
|
||||
|
||||
TyKind::BoundVar(BoundVar::new(self.in_binders, idx))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use base_db::{
|
|||
};
|
||||
use hir_def::{db::DefDatabase, ModuleId};
|
||||
use hir_expand::db::AstDatabase;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use stdx::hash::{NoHashHashMap, NoHashHashSet};
|
||||
use syntax::TextRange;
|
||||
use test_utils::extract_annotations;
|
||||
|
||||
|
@ -80,7 +80,7 @@ impl FileLoader for TestDB {
|
|||
fn resolve_path(&self, path: AnchoredPath<'_>) -> Option<FileId> {
|
||||
FileLoaderDelegate(self).resolve_path(path)
|
||||
}
|
||||
fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
|
||||
fn relevant_crates(&self, file_id: FileId) -> Arc<NoHashHashSet<CrateId>> {
|
||||
FileLoaderDelegate(self).relevant_crates(file_id)
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ impl TestDB {
|
|||
self.module_for_file_opt(file_id).unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn extract_annotations(&self) -> FxHashMap<FileId, Vec<(TextRange, String)>> {
|
||||
pub(crate) fn extract_annotations(&self) -> NoHashHashMap<FileId, Vec<(TextRange, String)>> {
|
||||
let mut files = Vec::new();
|
||||
let crate_graph = self.crate_graph();
|
||||
for krate in crate_graph.iter() {
|
||||
|
|
|
@ -1526,6 +1526,34 @@ unsafe impl Storage for InlineStorage {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gat_crash_3() {
|
||||
// FIXME: This test currently crashes rust analyzer in a debug build but not in a
|
||||
// release build (i.e. for the user). With the assumption that tests will always be run
|
||||
// in debug mode, we catch the unwind and expect that it panicked. See the
|
||||
// [`crate::utils::generics`] function for more information.
|
||||
cov_mark::check!(ignore_gats);
|
||||
std::panic::catch_unwind(|| {
|
||||
check_no_mismatches(
|
||||
r#"
|
||||
trait Collection {
|
||||
type Item;
|
||||
type Member<T>: Collection<Item = T>;
|
||||
fn add(&mut self, value: Self::Item) -> Result<(), Self::Error>;
|
||||
}
|
||||
struct ConstGen<T, const N: usize> {
|
||||
data: [T; N],
|
||||
}
|
||||
impl<T, const N: usize> Collection for ConstGen<T, N> {
|
||||
type Item = T;
|
||||
type Member<U> = ConstGen<U, N>;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
})
|
||||
.expect_err("must panic");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cfgd_out_self_param() {
|
||||
cov_mark::check!(cfgd_out_self_param);
|
||||
|
|
|
@ -176,10 +176,19 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
|
|||
let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
|
||||
if parent_generics.is_some() && matches!(def, GenericDefId::TypeAliasId(_)) {
|
||||
let params = db.generic_params(def);
|
||||
let parent_params = &parent_generics.as_ref().unwrap().params;
|
||||
let has_consts =
|
||||
params.iter().any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_)));
|
||||
return if has_consts {
|
||||
// XXX: treat const generic associated types as not existing to avoid crashes (#11769)
|
||||
let parent_has_consts =
|
||||
parent_params.iter().any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_)));
|
||||
return if has_consts || parent_has_consts {
|
||||
// XXX: treat const generic associated types as not existing to avoid crashes
|
||||
// (#11769)
|
||||
//
|
||||
// Note: Also crashes when the parent has const generics (also even if the GAT
|
||||
// doesn't use them), see `tests::regression::gat_crash_3` for an example.
|
||||
// Avoids that by disabling GATs when the parent (i.e. `impl` block) has
|
||||
// const generics (#12193).
|
||||
//
|
||||
// Chalk expects the inner associated type's parameters to come
|
||||
// *before*, not after the trait's generics as we've always done it.
|
||||
|
@ -264,12 +273,8 @@ impl Generics {
|
|||
|
||||
fn find_param(&self, param: TypeOrConstParamId) -> Option<(usize, &TypeOrConstParamData)> {
|
||||
if param.parent == self.def {
|
||||
let (idx, (_local_id, data)) = self
|
||||
.params
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_, (idx, _))| *idx == param.local_id)
|
||||
.unwrap();
|
||||
let (idx, (_local_id, data)) =
|
||||
self.params.iter().enumerate().find(|(_, (idx, _))| *idx == param.local_id)?;
|
||||
let parent_len = self.parent_generics().map_or(0, Generics::len);
|
||||
Some((parent_len + idx, data))
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue