Adjust display impls to respect lifetime bounds
This commit is contained in:
parent
0927f86247
commit
707be6b99c
@ -30,6 +30,8 @@ pub fn find_path(
|
||||
find_path_inner(FindPathCtx { db, prefixed: None, prefer_no_std, prefer_prelude }, item, from)
|
||||
}
|
||||
|
||||
/// Find a path that can be used to refer to a certain item. This can depend on
|
||||
/// *from where* you're referring to the item, hence the `from` parameter.
|
||||
pub fn find_path_prefixed(
|
||||
db: &dyn DefDatabase,
|
||||
item: ItemInNs,
|
||||
@ -255,7 +257,7 @@ fn find_in_scope(
|
||||
item: ItemInNs,
|
||||
) -> Option<Name> {
|
||||
def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
|
||||
def_map[local_id].scope.name_of(item).map(|(name, _, _)| name.clone())
|
||||
def_map[local_id].scope.names_of(item, |name, _, _| Some(name.clone()))
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,8 @@ use crate::{
|
||||
/// Data about a generic type parameter (to a function, struct, impl, ...).
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct TypeParamData {
|
||||
/// [`None`] only if the type ref is an [`TypeRef::ImplTrait`]. FIXME: Might be better to just
|
||||
/// make it always be a value, giving impl trait a special name.
|
||||
pub name: Option<Name>,
|
||||
pub default: Option<Interned<TypeRef>>,
|
||||
pub provenance: TypeParamProvenance,
|
||||
|
@ -277,13 +277,43 @@ impl ItemScope {
|
||||
ItemInNs::Types(def) => self.types.iter().find_map(|(name, &(other_def, vis, i))| {
|
||||
(other_def == def).then_some((name, vis, i.is_none()))
|
||||
}),
|
||||
|
||||
ItemInNs::Values(def) => self.values.iter().find_map(|(name, &(other_def, vis, i))| {
|
||||
(other_def == def).then_some((name, vis, i.is_none()))
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// XXX: this is O(N) rather than O(1), try to not introduce new usages.
|
||||
pub(crate) fn names_of<T>(
|
||||
&self,
|
||||
item: ItemInNs,
|
||||
mut cb: impl FnMut(&Name, Visibility, bool) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
match item {
|
||||
ItemInNs::Macros(def) => self
|
||||
.macros
|
||||
.iter()
|
||||
.filter_map(|(name, &(other_def, vis, i))| {
|
||||
(other_def == def).then_some((name, vis, i.is_none()))
|
||||
})
|
||||
.find_map(|(a, b, c)| cb(a, b, c)),
|
||||
ItemInNs::Types(def) => self
|
||||
.types
|
||||
.iter()
|
||||
.filter_map(|(name, &(other_def, vis, i))| {
|
||||
(other_def == def).then_some((name, vis, i.is_none()))
|
||||
})
|
||||
.find_map(|(a, b, c)| cb(a, b, c)),
|
||||
ItemInNs::Values(def) => self
|
||||
.values
|
||||
.iter()
|
||||
.filter_map(|(name, &(other_def, vis, i))| {
|
||||
(other_def == def).then_some((name, vis, i.is_none()))
|
||||
})
|
||||
.find_map(|(a, b, c)| cb(a, b, c)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn traits(&self) -> impl Iterator<Item = TraitId> + '_ {
|
||||
self.types
|
||||
.values()
|
||||
|
@ -9,6 +9,7 @@ use std::{
|
||||
|
||||
use base_db::CrateId;
|
||||
use chalk_ir::{BoundVar, Safety, TyKind};
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
data::adt::VariantData,
|
||||
db::DefDatabase,
|
||||
@ -1072,6 +1073,7 @@ impl HirDisplay for Ty {
|
||||
write_bounds_like_dyn_trait_with_prefix(
|
||||
f,
|
||||
"impl",
|
||||
Either::Left(self),
|
||||
bounds.skip_binders(),
|
||||
SizedByDefault::Sized { anchor: krate },
|
||||
)?;
|
||||
@ -1087,6 +1089,7 @@ impl HirDisplay for Ty {
|
||||
write_bounds_like_dyn_trait_with_prefix(
|
||||
f,
|
||||
"impl",
|
||||
Either::Left(self),
|
||||
bounds.skip_binders(),
|
||||
SizedByDefault::Sized { anchor: krate },
|
||||
)?;
|
||||
@ -1189,21 +1192,24 @@ impl HirDisplay for Ty {
|
||||
.generic_predicates(id.parent)
|
||||
.iter()
|
||||
.map(|pred| pred.clone().substitute(Interner, &substs))
|
||||
.filter(|wc| match &wc.skip_binders() {
|
||||
.filter(|wc| match wc.skip_binders() {
|
||||
WhereClause::Implemented(tr) => {
|
||||
&tr.self_type_parameter(Interner) == self
|
||||
tr.self_type_parameter(Interner) == *self
|
||||
}
|
||||
WhereClause::AliasEq(AliasEq {
|
||||
alias: AliasTy::Projection(proj),
|
||||
ty: _,
|
||||
}) => &proj.self_type_parameter(db) == self,
|
||||
_ => false,
|
||||
}) => proj.self_type_parameter(db) == *self,
|
||||
WhereClause::AliasEq(_) => false,
|
||||
WhereClause::TypeOutlives(to) => to.ty == *self,
|
||||
WhereClause::LifetimeOutlives(_) => false,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let krate = id.parent.module(db.upcast()).krate();
|
||||
write_bounds_like_dyn_trait_with_prefix(
|
||||
f,
|
||||
"impl",
|
||||
Either::Left(self),
|
||||
&bounds,
|
||||
SizedByDefault::Sized { anchor: krate },
|
||||
)?;
|
||||
@ -1229,6 +1235,7 @@ impl HirDisplay for Ty {
|
||||
write_bounds_like_dyn_trait_with_prefix(
|
||||
f,
|
||||
"dyn",
|
||||
Either::Left(self),
|
||||
&bounds,
|
||||
SizedByDefault::NotSized,
|
||||
)?;
|
||||
@ -1252,6 +1259,7 @@ impl HirDisplay for Ty {
|
||||
write_bounds_like_dyn_trait_with_prefix(
|
||||
f,
|
||||
"impl",
|
||||
Either::Left(self),
|
||||
bounds.skip_binders(),
|
||||
SizedByDefault::Sized { anchor: krate },
|
||||
)?;
|
||||
@ -1266,6 +1274,7 @@ impl HirDisplay for Ty {
|
||||
write_bounds_like_dyn_trait_with_prefix(
|
||||
f,
|
||||
"impl",
|
||||
Either::Left(self),
|
||||
bounds.skip_binders(),
|
||||
SizedByDefault::Sized { anchor: krate },
|
||||
)?;
|
||||
@ -1468,6 +1477,7 @@ impl SizedByDefault {
|
||||
pub fn write_bounds_like_dyn_trait_with_prefix(
|
||||
f: &mut HirFormatter<'_>,
|
||||
prefix: &str,
|
||||
this: Either<&Ty, &Lifetime>,
|
||||
predicates: &[QuantifiedWhereClause],
|
||||
default_sized: SizedByDefault,
|
||||
) -> Result<(), HirDisplayError> {
|
||||
@ -1476,7 +1486,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix(
|
||||
|| predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
|
||||
{
|
||||
write!(f, " ")?;
|
||||
write_bounds_like_dyn_trait(f, predicates, default_sized)
|
||||
write_bounds_like_dyn_trait(f, this, predicates, default_sized)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@ -1484,6 +1494,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix(
|
||||
|
||||
fn write_bounds_like_dyn_trait(
|
||||
f: &mut HirFormatter<'_>,
|
||||
this: Either<&Ty, &Lifetime>,
|
||||
predicates: &[QuantifiedWhereClause],
|
||||
default_sized: SizedByDefault,
|
||||
) -> Result<(), HirDisplayError> {
|
||||
@ -1541,6 +1552,28 @@ fn write_bounds_like_dyn_trait(
|
||||
}
|
||||
}
|
||||
}
|
||||
WhereClause::TypeOutlives(to) if Either::Left(&to.ty) == this => {
|
||||
if !is_fn_trait && angle_open {
|
||||
write!(f, ">")?;
|
||||
angle_open = false;
|
||||
}
|
||||
if !first {
|
||||
write!(f, " + ")?;
|
||||
}
|
||||
to.lifetime.hir_fmt(f)?;
|
||||
}
|
||||
WhereClause::TypeOutlives(_) => {}
|
||||
WhereClause::LifetimeOutlives(lo) if Either::Right(&lo.a) == this => {
|
||||
if !is_fn_trait && angle_open {
|
||||
write!(f, ">")?;
|
||||
angle_open = false;
|
||||
}
|
||||
if !first {
|
||||
write!(f, " + ")?;
|
||||
}
|
||||
lo.b.hir_fmt(f)?;
|
||||
}
|
||||
WhereClause::LifetimeOutlives(_) => {}
|
||||
WhereClause::AliasEq(alias_eq) if is_fn_trait => {
|
||||
is_fn_trait = false;
|
||||
if !alias_eq.ty.is_unit() {
|
||||
@ -1577,10 +1610,6 @@ fn write_bounds_like_dyn_trait(
|
||||
}
|
||||
ty.hir_fmt(f)?;
|
||||
}
|
||||
|
||||
// FIXME implement these
|
||||
WhereClause::LifetimeOutlives(_) => {}
|
||||
WhereClause::TypeOutlives(_) => {}
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
@ -1612,10 +1612,10 @@ fn test(
|
||||
) {}
|
||||
"#,
|
||||
expect![[r#"
|
||||
28..29 'a': impl Trait
|
||||
59..60 'b': impl Sized
|
||||
28..29 'a': impl Trait + 'static
|
||||
59..60 'b': impl 'static
|
||||
82..83 'c': impl Trait
|
||||
103..104 'd': impl Sized
|
||||
103..104 'd': impl 'static
|
||||
128..129 'e': impl ?Sized
|
||||
148..149 'f': impl Trait + ?Sized
|
||||
173..175 '{}': ()
|
||||
|
@ -1,4 +1,5 @@
|
||||
//! HirDisplay implementations for various hir types.
|
||||
use either::Either;
|
||||
use hir_def::{
|
||||
data::adt::{StructKind, VariantData},
|
||||
generics::{
|
||||
@ -13,7 +14,7 @@ use hir_ty::{
|
||||
write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
|
||||
HirFormatter, SizedByDefault,
|
||||
},
|
||||
Interner, TraitRefExt, WhereClause,
|
||||
AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyKind, WhereClause,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -363,16 +364,52 @@ impl HirDisplay for TypeOrConstParam {
|
||||
|
||||
impl HirDisplay for TypeParam {
|
||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
|
||||
let params = f.db.generic_params(self.id.parent());
|
||||
let param_data = ¶ms.type_or_consts[self.id.local_id()];
|
||||
let substs = TyBuilder::placeholder_subst(f.db, self.id.parent());
|
||||
let krate = self.id.parent().krate(f.db).id;
|
||||
let ty =
|
||||
TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into())).intern(Interner);
|
||||
let predicates = f.db.generic_predicates(self.id.parent());
|
||||
let predicates = predicates
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|pred| pred.substitute(Interner, &substs))
|
||||
.filter(|wc| match wc.skip_binders() {
|
||||
WhereClause::Implemented(tr) => tr.self_type_parameter(Interner) == ty,
|
||||
WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), ty: _ }) => {
|
||||
proj.self_type_parameter(f.db) == ty
|
||||
}
|
||||
WhereClause::AliasEq(_) => false,
|
||||
WhereClause::TypeOutlives(to) => to.ty == ty,
|
||||
WhereClause::LifetimeOutlives(_) => false,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
match param_data {
|
||||
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
|
||||
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
|
||||
write!(f, "{}", p.name.clone().unwrap().display(f.db.upcast()))?
|
||||
}
|
||||
TypeParamProvenance::ArgumentImplTrait => {
|
||||
return write_bounds_like_dyn_trait_with_prefix(
|
||||
f,
|
||||
"impl",
|
||||
Either::Left(&ty),
|
||||
&predicates,
|
||||
SizedByDefault::Sized { anchor: krate },
|
||||
);
|
||||
}
|
||||
},
|
||||
TypeOrConstParamData::ConstParamData(p) => {
|
||||
write!(f, "{}", p.name.display(f.db.upcast()))?;
|
||||
}
|
||||
}
|
||||
|
||||
if f.omit_verbose_types() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let bounds = f.db.generic_predicates_for_param(self.id.parent(), self.id.into(), None);
|
||||
let substs = TyBuilder::placeholder_subst(f.db, self.id.parent());
|
||||
let predicates: Vec<_> =
|
||||
bounds.iter().cloned().map(|b| b.substitute(Interner, &substs)).collect();
|
||||
let krate = self.id.parent().krate(f.db).id;
|
||||
let sized_trait =
|
||||
f.db.lang_item(krate, LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
|
||||
let has_only_sized_bound = predicates.iter().all(move |pred| match pred.skip_binders() {
|
||||
@ -382,7 +419,16 @@ impl HirDisplay for TypeParam {
|
||||
let has_only_not_sized_bound = predicates.is_empty();
|
||||
if !has_only_sized_bound || has_only_not_sized_bound {
|
||||
let default_sized = SizedByDefault::Sized { anchor: krate };
|
||||
write_bounds_like_dyn_trait_with_prefix(f, ":", &predicates, default_sized)?;
|
||||
write_bounds_like_dyn_trait_with_prefix(
|
||||
f,
|
||||
":",
|
||||
Either::Left(
|
||||
&hir_ty::TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into()))
|
||||
.intern(Interner),
|
||||
),
|
||||
&predicates,
|
||||
default_sized,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1585,6 +1585,38 @@ mod bar {
|
||||
Foo;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn local_inline_import_has_alias() {
|
||||
// FIXME
|
||||
check_assist_not_applicable(
|
||||
auto_import,
|
||||
r#"
|
||||
struct S<T>(T);
|
||||
use S as IoResult;
|
||||
|
||||
mod foo {
|
||||
pub fn bar() -> S$0<()> {}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alias_local() {
|
||||
// FIXME
|
||||
check_assist_not_applicable(
|
||||
auto_import,
|
||||
r#"
|
||||
struct S<T>(T);
|
||||
use S as IoResult;
|
||||
|
||||
mod foo {
|
||||
pub fn bar() -> IoResult$0<()> {}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -4040,7 +4040,6 @@ impl<T> Foo<T$0> {}
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
// lifetimes bounds arent being tracked yet
|
||||
check(
|
||||
r#"
|
||||
//- minicore: sized
|
||||
@ -4051,7 +4050,7 @@ impl<T: 'static> Foo<T$0> {}
|
||||
*T*
|
||||
|
||||
```rust
|
||||
T
|
||||
T: 'static
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user