mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Fix opaque generics
The parent generics were incorrectly not considered for TAIT. I'm not convinced we should follow rustc here, also there are items (opaques) with more than 1 parent (opaque -> fn/type alias -> impl/trait) and I'm not sure we properly account for that in all places, but for now I left it as-is. Also fix a bug where lifetimes' indices were incorrect when there is a self param (they started from 0 instead of 1).
This commit is contained in:
parent
e6cd085099
commit
03173a7ec7
@ -12,7 +12,7 @@ use hir_def::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use intern::Symbol;
|
use intern::{Symbol, sym};
|
||||||
use la_arena::Arena;
|
use la_arena::Arena;
|
||||||
use rustc_type_ir::inherent::Ty as _;
|
use rustc_type_ir::inherent::Ty as _;
|
||||||
use triomphe::Arc;
|
use triomphe::Arc;
|
||||||
@ -24,18 +24,13 @@ use super::{Const, EarlyParamRegion, ErrorGuaranteed, ParamConst, Region, Solver
|
|||||||
use super::{DbInterner, GenericArg};
|
use super::{DbInterner, GenericArg};
|
||||||
|
|
||||||
pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
|
pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
|
||||||
let mk_lt = |(index, (_, lt)): (usize, (_, &LifetimeParamData))| {
|
let mk_lt = |index, lt: &LifetimeParamData| {
|
||||||
let name = lt.name.symbol().clone();
|
let name = lt.name.symbol().clone();
|
||||||
let index = index as u32;
|
|
||||||
let kind = GenericParamDefKind::Lifetime;
|
let kind = GenericParamDefKind::Lifetime;
|
||||||
GenericParamDef { name, index, kind }
|
GenericParamDef { name, index, kind }
|
||||||
};
|
};
|
||||||
let mk_ty = |len_lt, (index, p): (usize, &TypeOrConstParamData)| {
|
let mk_ty = |index, p: &TypeOrConstParamData| {
|
||||||
let name = p
|
let name = p.name().map(|n| n.symbol().clone()).unwrap_or_else(|| sym::MISSING_NAME);
|
||||||
.name()
|
|
||||||
.map(|n| n.symbol().clone())
|
|
||||||
.unwrap_or_else(|| Name::missing().symbol().clone());
|
|
||||||
let index = (len_lt + index) as u32;
|
|
||||||
let kind = match p {
|
let kind = match p {
|
||||||
TypeOrConstParamData::TypeParamData(_) => GenericParamDefKind::Type,
|
TypeOrConstParamData::TypeParamData(_) => GenericParamDefKind::Type,
|
||||||
TypeOrConstParamData::ConstParamData(_) => GenericParamDefKind::Const,
|
TypeOrConstParamData::ConstParamData(_) => GenericParamDefKind::Const,
|
||||||
@ -43,33 +38,25 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
|
|||||||
GenericParamDef { name, index, kind }
|
GenericParamDef { name, index, kind }
|
||||||
};
|
};
|
||||||
let own_params_for_generic_params = |params: &GenericParams| {
|
let own_params_for_generic_params = |params: &GenericParams| {
|
||||||
if params.trait_self_param().is_some() {
|
let mut result = Vec::with_capacity(params.len());
|
||||||
let len_lt = params.len_lifetimes() + 1;
|
let mut type_and_consts = params.iter_type_or_consts();
|
||||||
params
|
let mut index = 0;
|
||||||
.iter_type_or_consts()
|
if let Some(self_param) = params.trait_self_param() {
|
||||||
.take(1)
|
result.push(mk_ty(0, ¶ms[self_param]));
|
||||||
.enumerate()
|
type_and_consts.next();
|
||||||
.map(|t| mk_ty(0, (t.0, t.1.1)))
|
index += 1;
|
||||||
.chain(params.iter_lt().enumerate().map(mk_lt))
|
|
||||||
.chain(
|
|
||||||
params
|
|
||||||
.iter_type_or_consts()
|
|
||||||
.skip(1)
|
|
||||||
.enumerate()
|
|
||||||
.map(|t| mk_ty(len_lt, (t.0, t.1.1))),
|
|
||||||
)
|
|
||||||
.collect()
|
|
||||||
} else {
|
|
||||||
let len_lt = params.len_lifetimes();
|
|
||||||
params
|
|
||||||
.iter_lt()
|
|
||||||
.enumerate()
|
|
||||||
.map(mk_lt)
|
|
||||||
.chain(
|
|
||||||
params.iter_type_or_consts().enumerate().map(|t| mk_ty(len_lt, (t.0, t.1.1))),
|
|
||||||
)
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
result.extend(params.iter_lt().map(|(_, data)| {
|
||||||
|
let lt = mk_lt(index, data);
|
||||||
|
index += 1;
|
||||||
|
lt
|
||||||
|
}));
|
||||||
|
result.extend(type_and_consts.map(|(_, data)| {
|
||||||
|
let ty = mk_ty(index, data);
|
||||||
|
index += 1;
|
||||||
|
ty
|
||||||
|
}));
|
||||||
|
result
|
||||||
};
|
};
|
||||||
|
|
||||||
let (parent, own_params) = match (def.try_into(), def) {
|
let (parent, own_params) = match (def.try_into(), def) {
|
||||||
@ -82,12 +69,9 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
|
|||||||
// The opaque type itself does not have generics - only the parent function
|
// The opaque type itself does not have generics - only the parent function
|
||||||
(Some(GenericDefId::FunctionId(function_id)), vec![])
|
(Some(GenericDefId::FunctionId(function_id)), vec![])
|
||||||
}
|
}
|
||||||
crate::ImplTraitId::TypeAliasImplTrait(type_alias_id, _) => (
|
crate::ImplTraitId::TypeAliasImplTrait(type_alias_id, _) => {
|
||||||
None,
|
(Some(type_alias_id.into()), Vec::new())
|
||||||
own_params_for_generic_params(
|
}
|
||||||
&db.generic_params(GenericDefId::TypeAliasId(type_alias_id)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
crate::ImplTraitId::AsyncBlockTypeImplTrait(def, _) => {
|
crate::ImplTraitId::AsyncBlockTypeImplTrait(def, _) => {
|
||||||
let param = TypeOrConstParamData::TypeParamData(TypeParamData {
|
let param = TypeOrConstParamData::TypeParamData(TypeParamData {
|
||||||
name: None,
|
name: None,
|
||||||
@ -95,7 +79,7 @@ pub(crate) fn generics(db: &dyn HirDatabase, def: SolverDefId) -> Generics {
|
|||||||
provenance: TypeParamProvenance::TypeParamList,
|
provenance: TypeParamProvenance::TypeParamList,
|
||||||
});
|
});
|
||||||
// Yes, there is a parent but we don't include it in the generics
|
// Yes, there is a parent but we don't include it in the generics
|
||||||
(None, vec![mk_ty(0, (0, ¶m))])
|
(None, vec![mk_ty(0, ¶m)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -685,7 +685,6 @@ pub fn explicit_item_bounds<'db>(
|
|||||||
LifetimeElisionKind::AnonymousReportError,
|
LifetimeElisionKind::AnonymousReportError,
|
||||||
);
|
);
|
||||||
|
|
||||||
let trait_args = GenericArgs::identity_for_item(interner, trait_.into());
|
|
||||||
let item_args = GenericArgs::identity_for_item(interner, def_id);
|
let item_args = GenericArgs::identity_for_item(interner, def_id);
|
||||||
let interner_ty = Ty::new_projection_from_args(interner, def_id, item_args);
|
let interner_ty = Ty::new_projection_from_args(interner, def_id, item_args);
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
mod new_solver;
|
||||||
|
|
||||||
use expect_test::expect;
|
use expect_test::expect;
|
||||||
|
|
||||||
use super::{check_infer, check_no_mismatches, check_types};
|
use super::{check_infer, check_no_mismatches, check_types};
|
||||||
|
26
crates/hir-ty/src/tests/regression/new_solver.rs
Normal file
26
crates/hir-ty/src/tests/regression/new_solver.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use expect_test::expect;
|
||||||
|
|
||||||
|
use super::check_infer;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn opaque_generics() {
|
||||||
|
check_infer(
|
||||||
|
r#"
|
||||||
|
//- minicore: iterator
|
||||||
|
pub struct Grid {}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a Grid {
|
||||||
|
type Item = &'a ();
|
||||||
|
|
||||||
|
type IntoIter = impl Iterator<Item = &'a ()>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
150..154 'self': &'a Grid
|
||||||
|
174..181 '{ }': impl Iterator<Item = &'a ()>
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user