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_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(
|
pub fn find_path_prefixed(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
item: ItemInNs,
|
item: ItemInNs,
|
||||||
@ -255,7 +257,7 @@ fn find_in_scope(
|
|||||||
item: ItemInNs,
|
item: ItemInNs,
|
||||||
) -> Option<Name> {
|
) -> Option<Name> {
|
||||||
def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
|
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, ...).
|
/// Data about a generic type parameter (to a function, struct, impl, ...).
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
pub struct TypeParamData {
|
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 name: Option<Name>,
|
||||||
pub default: Option<Interned<TypeRef>>,
|
pub default: Option<Interned<TypeRef>>,
|
||||||
pub provenance: TypeParamProvenance,
|
pub provenance: TypeParamProvenance,
|
||||||
|
@ -277,13 +277,43 @@ impl ItemScope {
|
|||||||
ItemInNs::Types(def) => self.types.iter().find_map(|(name, &(other_def, vis, i))| {
|
ItemInNs::Types(def) => self.types.iter().find_map(|(name, &(other_def, vis, i))| {
|
||||||
(other_def == def).then_some((name, vis, i.is_none()))
|
(other_def == def).then_some((name, vis, i.is_none()))
|
||||||
}),
|
}),
|
||||||
|
|
||||||
ItemInNs::Values(def) => self.values.iter().find_map(|(name, &(other_def, vis, i))| {
|
ItemInNs::Values(def) => self.values.iter().find_map(|(name, &(other_def, vis, i))| {
|
||||||
(other_def == def).then_some((name, vis, i.is_none()))
|
(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> + '_ {
|
pub(crate) fn traits(&self) -> impl Iterator<Item = TraitId> + '_ {
|
||||||
self.types
|
self.types
|
||||||
.values()
|
.values()
|
||||||
|
@ -9,6 +9,7 @@ use std::{
|
|||||||
|
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
use chalk_ir::{BoundVar, Safety, TyKind};
|
use chalk_ir::{BoundVar, Safety, TyKind};
|
||||||
|
use either::Either;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
data::adt::VariantData,
|
data::adt::VariantData,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
@ -1072,6 +1073,7 @@ impl HirDisplay for Ty {
|
|||||||
write_bounds_like_dyn_trait_with_prefix(
|
write_bounds_like_dyn_trait_with_prefix(
|
||||||
f,
|
f,
|
||||||
"impl",
|
"impl",
|
||||||
|
Either::Left(self),
|
||||||
bounds.skip_binders(),
|
bounds.skip_binders(),
|
||||||
SizedByDefault::Sized { anchor: krate },
|
SizedByDefault::Sized { anchor: krate },
|
||||||
)?;
|
)?;
|
||||||
@ -1087,6 +1089,7 @@ impl HirDisplay for Ty {
|
|||||||
write_bounds_like_dyn_trait_with_prefix(
|
write_bounds_like_dyn_trait_with_prefix(
|
||||||
f,
|
f,
|
||||||
"impl",
|
"impl",
|
||||||
|
Either::Left(self),
|
||||||
bounds.skip_binders(),
|
bounds.skip_binders(),
|
||||||
SizedByDefault::Sized { anchor: krate },
|
SizedByDefault::Sized { anchor: krate },
|
||||||
)?;
|
)?;
|
||||||
@ -1189,21 +1192,24 @@ impl HirDisplay for Ty {
|
|||||||
.generic_predicates(id.parent)
|
.generic_predicates(id.parent)
|
||||||
.iter()
|
.iter()
|
||||||
.map(|pred| pred.clone().substitute(Interner, &substs))
|
.map(|pred| pred.clone().substitute(Interner, &substs))
|
||||||
.filter(|wc| match &wc.skip_binders() {
|
.filter(|wc| match wc.skip_binders() {
|
||||||
WhereClause::Implemented(tr) => {
|
WhereClause::Implemented(tr) => {
|
||||||
&tr.self_type_parameter(Interner) == self
|
tr.self_type_parameter(Interner) == *self
|
||||||
}
|
}
|
||||||
WhereClause::AliasEq(AliasEq {
|
WhereClause::AliasEq(AliasEq {
|
||||||
alias: AliasTy::Projection(proj),
|
alias: AliasTy::Projection(proj),
|
||||||
ty: _,
|
ty: _,
|
||||||
}) => &proj.self_type_parameter(db) == self,
|
}) => proj.self_type_parameter(db) == *self,
|
||||||
_ => false,
|
WhereClause::AliasEq(_) => false,
|
||||||
|
WhereClause::TypeOutlives(to) => to.ty == *self,
|
||||||
|
WhereClause::LifetimeOutlives(_) => false,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let krate = id.parent.module(db.upcast()).krate();
|
let krate = id.parent.module(db.upcast()).krate();
|
||||||
write_bounds_like_dyn_trait_with_prefix(
|
write_bounds_like_dyn_trait_with_prefix(
|
||||||
f,
|
f,
|
||||||
"impl",
|
"impl",
|
||||||
|
Either::Left(self),
|
||||||
&bounds,
|
&bounds,
|
||||||
SizedByDefault::Sized { anchor: krate },
|
SizedByDefault::Sized { anchor: krate },
|
||||||
)?;
|
)?;
|
||||||
@ -1229,6 +1235,7 @@ impl HirDisplay for Ty {
|
|||||||
write_bounds_like_dyn_trait_with_prefix(
|
write_bounds_like_dyn_trait_with_prefix(
|
||||||
f,
|
f,
|
||||||
"dyn",
|
"dyn",
|
||||||
|
Either::Left(self),
|
||||||
&bounds,
|
&bounds,
|
||||||
SizedByDefault::NotSized,
|
SizedByDefault::NotSized,
|
||||||
)?;
|
)?;
|
||||||
@ -1252,6 +1259,7 @@ impl HirDisplay for Ty {
|
|||||||
write_bounds_like_dyn_trait_with_prefix(
|
write_bounds_like_dyn_trait_with_prefix(
|
||||||
f,
|
f,
|
||||||
"impl",
|
"impl",
|
||||||
|
Either::Left(self),
|
||||||
bounds.skip_binders(),
|
bounds.skip_binders(),
|
||||||
SizedByDefault::Sized { anchor: krate },
|
SizedByDefault::Sized { anchor: krate },
|
||||||
)?;
|
)?;
|
||||||
@ -1266,6 +1274,7 @@ impl HirDisplay for Ty {
|
|||||||
write_bounds_like_dyn_trait_with_prefix(
|
write_bounds_like_dyn_trait_with_prefix(
|
||||||
f,
|
f,
|
||||||
"impl",
|
"impl",
|
||||||
|
Either::Left(self),
|
||||||
bounds.skip_binders(),
|
bounds.skip_binders(),
|
||||||
SizedByDefault::Sized { anchor: krate },
|
SizedByDefault::Sized { anchor: krate },
|
||||||
)?;
|
)?;
|
||||||
@ -1468,6 +1477,7 @@ impl SizedByDefault {
|
|||||||
pub fn write_bounds_like_dyn_trait_with_prefix(
|
pub fn write_bounds_like_dyn_trait_with_prefix(
|
||||||
f: &mut HirFormatter<'_>,
|
f: &mut HirFormatter<'_>,
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
|
this: Either<&Ty, &Lifetime>,
|
||||||
predicates: &[QuantifiedWhereClause],
|
predicates: &[QuantifiedWhereClause],
|
||||||
default_sized: SizedByDefault,
|
default_sized: SizedByDefault,
|
||||||
) -> Result<(), HirDisplayError> {
|
) -> Result<(), HirDisplayError> {
|
||||||
@ -1476,7 +1486,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix(
|
|||||||
|| predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
|
|| predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
|
||||||
{
|
{
|
||||||
write!(f, " ")?;
|
write!(f, " ")?;
|
||||||
write_bounds_like_dyn_trait(f, predicates, default_sized)
|
write_bounds_like_dyn_trait(f, this, predicates, default_sized)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -1484,6 +1494,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix(
|
|||||||
|
|
||||||
fn write_bounds_like_dyn_trait(
|
fn write_bounds_like_dyn_trait(
|
||||||
f: &mut HirFormatter<'_>,
|
f: &mut HirFormatter<'_>,
|
||||||
|
this: Either<&Ty, &Lifetime>,
|
||||||
predicates: &[QuantifiedWhereClause],
|
predicates: &[QuantifiedWhereClause],
|
||||||
default_sized: SizedByDefault,
|
default_sized: SizedByDefault,
|
||||||
) -> Result<(), HirDisplayError> {
|
) -> 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 => {
|
WhereClause::AliasEq(alias_eq) if is_fn_trait => {
|
||||||
is_fn_trait = false;
|
is_fn_trait = false;
|
||||||
if !alias_eq.ty.is_unit() {
|
if !alias_eq.ty.is_unit() {
|
||||||
@ -1577,10 +1610,6 @@ fn write_bounds_like_dyn_trait(
|
|||||||
}
|
}
|
||||||
ty.hir_fmt(f)?;
|
ty.hir_fmt(f)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME implement these
|
|
||||||
WhereClause::LifetimeOutlives(_) => {}
|
|
||||||
WhereClause::TypeOutlives(_) => {}
|
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
@ -1612,10 +1612,10 @@ fn test(
|
|||||||
) {}
|
) {}
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
28..29 'a': impl Trait
|
28..29 'a': impl Trait + 'static
|
||||||
59..60 'b': impl Sized
|
59..60 'b': impl 'static
|
||||||
82..83 'c': impl Trait
|
82..83 'c': impl Trait
|
||||||
103..104 'd': impl Sized
|
103..104 'd': impl 'static
|
||||||
128..129 'e': impl ?Sized
|
128..129 'e': impl ?Sized
|
||||||
148..149 'f': impl Trait + ?Sized
|
148..149 'f': impl Trait + ?Sized
|
||||||
173..175 '{}': ()
|
173..175 '{}': ()
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
//! HirDisplay implementations for various hir types.
|
//! HirDisplay implementations for various hir types.
|
||||||
|
use either::Either;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
data::adt::{StructKind, VariantData},
|
data::adt::{StructKind, VariantData},
|
||||||
generics::{
|
generics::{
|
||||||
@ -13,7 +14,7 @@ use hir_ty::{
|
|||||||
write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
|
write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
|
||||||
HirFormatter, SizedByDefault,
|
HirFormatter, SizedByDefault,
|
||||||
},
|
},
|
||||||
Interner, TraitRefExt, WhereClause,
|
AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyKind, WhereClause,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -363,16 +364,52 @@ impl HirDisplay for TypeOrConstParam {
|
|||||||
|
|
||||||
impl HirDisplay for TypeParam {
|
impl HirDisplay for TypeParam {
|
||||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
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() {
|
if f.omit_verbose_types() {
|
||||||
return Ok(());
|
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 =
|
let sized_trait =
|
||||||
f.db.lang_item(krate, LangItem::Sized).and_then(|lang_item| lang_item.as_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() {
|
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();
|
let has_only_not_sized_bound = predicates.is_empty();
|
||||||
if !has_only_sized_bound || has_only_not_sized_bound {
|
if !has_only_sized_bound || has_only_not_sized_bound {
|
||||||
let default_sized = SizedByDefault::Sized { anchor: krate };
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1585,6 +1585,38 @@ mod bar {
|
|||||||
Foo;
|
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(
|
check(
|
||||||
r#"
|
r#"
|
||||||
//- minicore: sized
|
//- minicore: sized
|
||||||
@ -4051,7 +4050,7 @@ impl<T: 'static> Foo<T$0> {}
|
|||||||
*T*
|
*T*
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
T
|
T: 'static
|
||||||
```
|
```
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user