Skip to content

Commit 707be6b

Browse files
committed
Adjust display impls to respect lifetime bounds
1 parent 0927f86 commit 707be6b

File tree

8 files changed

+164
-24
lines changed

8 files changed

+164
-24
lines changed

crates/hir-def/src/find_path.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ pub fn find_path(
3030
find_path_inner(FindPathCtx { db, prefixed: None, prefer_no_std, prefer_prelude }, item, from)
3131
}
3232

33+
/// Find a path that can be used to refer to a certain item. This can depend on
34+
/// *from where* you're referring to the item, hence the `from` parameter.
3335
pub fn find_path_prefixed(
3436
db: &dyn DefDatabase,
3537
item: ItemInNs,
@@ -255,7 +257,7 @@ fn find_in_scope(
255257
item: ItemInNs,
256258
) -> Option<Name> {
257259
def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
258-
def_map[local_id].scope.name_of(item).map(|(name, _, _)| name.clone())
260+
def_map[local_id].scope.names_of(item, |name, _, _| Some(name.clone()))
259261
})
260262
}
261263

crates/hir-def/src/generics.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ use crate::{
2929
/// Data about a generic type parameter (to a function, struct, impl, ...).
3030
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
3131
pub struct TypeParamData {
32+
/// [`None`] only if the type ref is an [`TypeRef::ImplTrait`]. FIXME: Might be better to just
33+
/// make it always be a value, giving impl trait a special name.
3234
pub name: Option<Name>,
3335
pub default: Option<Interned<TypeRef>>,
3436
pub provenance: TypeParamProvenance,

crates/hir-def/src/item_scope.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,13 +277,43 @@ impl ItemScope {
277277
ItemInNs::Types(def) => self.types.iter().find_map(|(name, &(other_def, vis, i))| {
278278
(other_def == def).then_some((name, vis, i.is_none()))
279279
}),
280-
281280
ItemInNs::Values(def) => self.values.iter().find_map(|(name, &(other_def, vis, i))| {
282281
(other_def == def).then_some((name, vis, i.is_none()))
283282
}),
284283
}
285284
}
286285

286+
/// XXX: this is O(N) rather than O(1), try to not introduce new usages.
287+
pub(crate) fn names_of<T>(
288+
&self,
289+
item: ItemInNs,
290+
mut cb: impl FnMut(&Name, Visibility, bool) -> Option<T>,
291+
) -> Option<T> {
292+
match item {
293+
ItemInNs::Macros(def) => self
294+
.macros
295+
.iter()
296+
.filter_map(|(name, &(other_def, vis, i))| {
297+
(other_def == def).then_some((name, vis, i.is_none()))
298+
})
299+
.find_map(|(a, b, c)| cb(a, b, c)),
300+
ItemInNs::Types(def) => self
301+
.types
302+
.iter()
303+
.filter_map(|(name, &(other_def, vis, i))| {
304+
(other_def == def).then_some((name, vis, i.is_none()))
305+
})
306+
.find_map(|(a, b, c)| cb(a, b, c)),
307+
ItemInNs::Values(def) => self
308+
.values
309+
.iter()
310+
.filter_map(|(name, &(other_def, vis, i))| {
311+
(other_def == def).then_some((name, vis, i.is_none()))
312+
})
313+
.find_map(|(a, b, c)| cb(a, b, c)),
314+
}
315+
}
316+
287317
pub(crate) fn traits(&self) -> impl Iterator<Item = TraitId> + '_ {
288318
self.types
289319
.values()

crates/hir-ty/src/display.rs

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::{
99

1010
use base_db::CrateId;
1111
use chalk_ir::{BoundVar, Safety, TyKind};
12+
use either::Either;
1213
use hir_def::{
1314
data::adt::VariantData,
1415
db::DefDatabase,
@@ -1072,6 +1073,7 @@ impl HirDisplay for Ty {
10721073
write_bounds_like_dyn_trait_with_prefix(
10731074
f,
10741075
"impl",
1076+
Either::Left(self),
10751077
bounds.skip_binders(),
10761078
SizedByDefault::Sized { anchor: krate },
10771079
)?;
@@ -1087,6 +1089,7 @@ impl HirDisplay for Ty {
10871089
write_bounds_like_dyn_trait_with_prefix(
10881090
f,
10891091
"impl",
1092+
Either::Left(self),
10901093
bounds.skip_binders(),
10911094
SizedByDefault::Sized { anchor: krate },
10921095
)?;
@@ -1189,21 +1192,24 @@ impl HirDisplay for Ty {
11891192
.generic_predicates(id.parent)
11901193
.iter()
11911194
.map(|pred| pred.clone().substitute(Interner, &substs))
1192-
.filter(|wc| match &wc.skip_binders() {
1195+
.filter(|wc| match wc.skip_binders() {
11931196
WhereClause::Implemented(tr) => {
1194-
&tr.self_type_parameter(Interner) == self
1197+
tr.self_type_parameter(Interner) == *self
11951198
}
11961199
WhereClause::AliasEq(AliasEq {
11971200
alias: AliasTy::Projection(proj),
11981201
ty: _,
1199-
}) => &proj.self_type_parameter(db) == self,
1200-
_ => false,
1202+
}) => proj.self_type_parameter(db) == *self,
1203+
WhereClause::AliasEq(_) => false,
1204+
WhereClause::TypeOutlives(to) => to.ty == *self,
1205+
WhereClause::LifetimeOutlives(_) => false,
12011206
})
12021207
.collect::<Vec<_>>();
12031208
let krate = id.parent.module(db.upcast()).krate();
12041209
write_bounds_like_dyn_trait_with_prefix(
12051210
f,
12061211
"impl",
1212+
Either::Left(self),
12071213
&bounds,
12081214
SizedByDefault::Sized { anchor: krate },
12091215
)?;
@@ -1229,6 +1235,7 @@ impl HirDisplay for Ty {
12291235
write_bounds_like_dyn_trait_with_prefix(
12301236
f,
12311237
"dyn",
1238+
Either::Left(self),
12321239
&bounds,
12331240
SizedByDefault::NotSized,
12341241
)?;
@@ -1252,6 +1259,7 @@ impl HirDisplay for Ty {
12521259
write_bounds_like_dyn_trait_with_prefix(
12531260
f,
12541261
"impl",
1262+
Either::Left(self),
12551263
bounds.skip_binders(),
12561264
SizedByDefault::Sized { anchor: krate },
12571265
)?;
@@ -1266,6 +1274,7 @@ impl HirDisplay for Ty {
12661274
write_bounds_like_dyn_trait_with_prefix(
12671275
f,
12681276
"impl",
1277+
Either::Left(self),
12691278
bounds.skip_binders(),
12701279
SizedByDefault::Sized { anchor: krate },
12711280
)?;
@@ -1468,6 +1477,7 @@ impl SizedByDefault {
14681477
pub fn write_bounds_like_dyn_trait_with_prefix(
14691478
f: &mut HirFormatter<'_>,
14701479
prefix: &str,
1480+
this: Either<&Ty, &Lifetime>,
14711481
predicates: &[QuantifiedWhereClause],
14721482
default_sized: SizedByDefault,
14731483
) -> Result<(), HirDisplayError> {
@@ -1476,14 +1486,15 @@ pub fn write_bounds_like_dyn_trait_with_prefix(
14761486
|| predicates.is_empty() && matches!(default_sized, SizedByDefault::Sized { .. })
14771487
{
14781488
write!(f, " ")?;
1479-
write_bounds_like_dyn_trait(f, predicates, default_sized)
1489+
write_bounds_like_dyn_trait(f, this, predicates, default_sized)
14801490
} else {
14811491
Ok(())
14821492
}
14831493
}
14841494

14851495
fn write_bounds_like_dyn_trait(
14861496
f: &mut HirFormatter<'_>,
1497+
this: Either<&Ty, &Lifetime>,
14871498
predicates: &[QuantifiedWhereClause],
14881499
default_sized: SizedByDefault,
14891500
) -> Result<(), HirDisplayError> {
@@ -1541,6 +1552,28 @@ fn write_bounds_like_dyn_trait(
15411552
}
15421553
}
15431554
}
1555+
WhereClause::TypeOutlives(to) if Either::Left(&to.ty) == this => {
1556+
if !is_fn_trait && angle_open {
1557+
write!(f, ">")?;
1558+
angle_open = false;
1559+
}
1560+
if !first {
1561+
write!(f, " + ")?;
1562+
}
1563+
to.lifetime.hir_fmt(f)?;
1564+
}
1565+
WhereClause::TypeOutlives(_) => {}
1566+
WhereClause::LifetimeOutlives(lo) if Either::Right(&lo.a) == this => {
1567+
if !is_fn_trait && angle_open {
1568+
write!(f, ">")?;
1569+
angle_open = false;
1570+
}
1571+
if !first {
1572+
write!(f, " + ")?;
1573+
}
1574+
lo.b.hir_fmt(f)?;
1575+
}
1576+
WhereClause::LifetimeOutlives(_) => {}
15441577
WhereClause::AliasEq(alias_eq) if is_fn_trait => {
15451578
is_fn_trait = false;
15461579
if !alias_eq.ty.is_unit() {
@@ -1577,10 +1610,6 @@ fn write_bounds_like_dyn_trait(
15771610
}
15781611
ty.hir_fmt(f)?;
15791612
}
1580-
1581-
// FIXME implement these
1582-
WhereClause::LifetimeOutlives(_) => {}
1583-
WhereClause::TypeOutlives(_) => {}
15841613
}
15851614
first = false;
15861615
}

crates/hir-ty/src/tests/traits.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,10 +1612,10 @@ fn test(
16121612
) {}
16131613
"#,
16141614
expect![[r#"
1615-
28..29 'a': impl Trait
1616-
59..60 'b': impl Sized
1615+
28..29 'a': impl Trait + 'static
1616+
59..60 'b': impl 'static
16171617
82..83 'c': impl Trait
1618-
103..104 'd': impl Sized
1618+
103..104 'd': impl 'static
16191619
128..129 'e': impl ?Sized
16201620
148..149 'f': impl Trait + ?Sized
16211621
173..175 '{}': ()

crates/hir/src/display.rs

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! HirDisplay implementations for various hir types.
2+
use either::Either;
23
use hir_def::{
34
data::adt::{StructKind, VariantData},
45
generics::{
@@ -13,7 +14,7 @@ use hir_ty::{
1314
write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
1415
HirFormatter, SizedByDefault,
1516
},
16-
Interner, TraitRefExt, WhereClause,
17+
AliasEq, AliasTy, Interner, ProjectionTyExt, TraitRefExt, TyKind, WhereClause,
1718
};
1819

1920
use crate::{
@@ -363,16 +364,52 @@ impl HirDisplay for TypeOrConstParam {
363364

364365
impl HirDisplay for TypeParam {
365366
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
366-
write!(f, "{}", self.name(f.db).display(f.db.upcast()))?;
367+
let params = f.db.generic_params(self.id.parent());
368+
let param_data = &params.type_or_consts[self.id.local_id()];
369+
let substs = TyBuilder::placeholder_subst(f.db, self.id.parent());
370+
let krate = self.id.parent().krate(f.db).id;
371+
let ty =
372+
TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into())).intern(Interner);
373+
let predicates = f.db.generic_predicates(self.id.parent());
374+
let predicates = predicates
375+
.iter()
376+
.cloned()
377+
.map(|pred| pred.substitute(Interner, &substs))
378+
.filter(|wc| match wc.skip_binders() {
379+
WhereClause::Implemented(tr) => tr.self_type_parameter(Interner) == ty,
380+
WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), ty: _ }) => {
381+
proj.self_type_parameter(f.db) == ty
382+
}
383+
WhereClause::AliasEq(_) => false,
384+
WhereClause::TypeOutlives(to) => to.ty == ty,
385+
WhereClause::LifetimeOutlives(_) => false,
386+
})
387+
.collect::<Vec<_>>();
388+
389+
match param_data {
390+
TypeOrConstParamData::TypeParamData(p) => match p.provenance {
391+
TypeParamProvenance::TypeParamList | TypeParamProvenance::TraitSelf => {
392+
write!(f, "{}", p.name.clone().unwrap().display(f.db.upcast()))?
393+
}
394+
TypeParamProvenance::ArgumentImplTrait => {
395+
return write_bounds_like_dyn_trait_with_prefix(
396+
f,
397+
"impl",
398+
Either::Left(&ty),
399+
&predicates,
400+
SizedByDefault::Sized { anchor: krate },
401+
);
402+
}
403+
},
404+
TypeOrConstParamData::ConstParamData(p) => {
405+
write!(f, "{}", p.name.display(f.db.upcast()))?;
406+
}
407+
}
408+
367409
if f.omit_verbose_types() {
368410
return Ok(());
369411
}
370412

371-
let bounds = f.db.generic_predicates_for_param(self.id.parent(), self.id.into(), None);
372-
let substs = TyBuilder::placeholder_subst(f.db, self.id.parent());
373-
let predicates: Vec<_> =
374-
bounds.iter().cloned().map(|b| b.substitute(Interner, &substs)).collect();
375-
let krate = self.id.parent().krate(f.db).id;
376413
let sized_trait =
377414
f.db.lang_item(krate, LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
378415
let has_only_sized_bound = predicates.iter().all(move |pred| match pred.skip_binders() {
@@ -382,7 +419,16 @@ impl HirDisplay for TypeParam {
382419
let has_only_not_sized_bound = predicates.is_empty();
383420
if !has_only_sized_bound || has_only_not_sized_bound {
384421
let default_sized = SizedByDefault::Sized { anchor: krate };
385-
write_bounds_like_dyn_trait_with_prefix(f, ":", &predicates, default_sized)?;
422+
write_bounds_like_dyn_trait_with_prefix(
423+
f,
424+
":",
425+
Either::Left(
426+
&hir_ty::TyKind::Placeholder(hir_ty::to_placeholder_idx(f.db, self.id.into()))
427+
.intern(Interner),
428+
),
429+
&predicates,
430+
default_sized,
431+
)?;
386432
}
387433
Ok(())
388434
}

crates/ide-assists/src/handlers/auto_import.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,6 +1585,38 @@ mod bar {
15851585
Foo;
15861586
}
15871587
}
1588+
"#,
1589+
);
1590+
}
1591+
1592+
#[test]
1593+
fn local_inline_import_has_alias() {
1594+
// FIXME
1595+
check_assist_not_applicable(
1596+
auto_import,
1597+
r#"
1598+
struct S<T>(T);
1599+
use S as IoResult;
1600+
1601+
mod foo {
1602+
pub fn bar() -> S$0<()> {}
1603+
}
1604+
"#,
1605+
);
1606+
}
1607+
1608+
#[test]
1609+
fn alias_local() {
1610+
// FIXME
1611+
check_assist_not_applicable(
1612+
auto_import,
1613+
r#"
1614+
struct S<T>(T);
1615+
use S as IoResult;
1616+
1617+
mod foo {
1618+
pub fn bar() -> IoResult$0<()> {}
1619+
}
15881620
"#,
15891621
);
15901622
}

crates/ide/src/hover/tests.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4040,7 +4040,6 @@ impl<T> Foo<T$0> {}
40404040
```
40414041
"#]],
40424042
);
4043-
// lifetimes bounds arent being tracked yet
40444043
check(
40454044
r#"
40464045
//- minicore: sized
@@ -4051,7 +4050,7 @@ impl<T: 'static> Foo<T$0> {}
40514050
*T*
40524051
40534052
```rust
4054-
T
4053+
T: 'static
40554054
```
40564055
"#]],
40574056
);

0 commit comments

Comments
 (0)