fix: Type param hover shows correct sized bounds.

This commit is contained in:
Dawer 2021-09-10 20:48:39 +05:00
parent 9ce3c075ad
commit dfb15292c2
2 changed files with 165 additions and 10 deletions

View file

@ -5,16 +5,19 @@ use hir_def::{
type_ref::{TypeBound, TypeRef}, type_ref::{TypeBound, TypeRef},
AdtId, GenericDefId, AdtId, GenericDefId,
}; };
use hir_ty::display::{ use hir_ty::{
write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError, display::{
HirFormatter, SizedByDefault, write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
HirFormatter, SizedByDefault,
},
Interner, TraitRefExt, WhereClause,
}; };
use hir_ty::Interner;
use syntax::ast::{self, NameOwner}; use syntax::ast::{self, NameOwner};
use crate::{ use crate::{
Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam, Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasCrate, HasVisibility,
Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union, Variant, LifetimeParam, Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union,
Variant,
}; };
impl HirDisplay for Function { impl HirDisplay for Function {
@ -234,12 +237,24 @@ impl HirDisplay for GenericParam {
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))?; write!(f, "{}", self.name(f.db))?;
if f.omit_verbose_types() {
return Ok(());
}
let bounds = f.db.generic_predicates_for_param(self.id); let bounds = f.db.generic_predicates_for_param(self.id);
let substs = TyBuilder::type_params_subst(f.db, self.id.parent); let substs = TyBuilder::type_params_subst(f.db, self.id.parent);
let predicates = let predicates: Vec<_> =
bounds.iter().cloned().map(|b| b.substitute(&Interner, &substs)).collect::<Vec<_>>(); bounds.iter().cloned().map(|b| b.substitute(&Interner, &substs)).collect();
if !(predicates.is_empty() || f.omit_verbose_types()) { let krate = self.id.parent.krate(f.db).id;
let default_sized = SizedByDefault::Sized { anchor: self.module(f.db).krate().id }; let sized_trait =
f.db.lang_item(krate, "sized".into()).and_then(|lang_item| lang_item.as_trait());
let has_only_sized_bound = predicates.iter().all(move |pred| match pred.skip_binders() {
WhereClause::Implemented(it) => Some(it.hir_trait_id()) == sized_trait,
_ => false,
});
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(":", &predicates, default_sized, f)?; write_bounds_like_dyn_trait_with_prefix(":", &predicates, default_sized, f)?;
} }
Ok(()) Ok(())

View file

@ -3596,6 +3596,146 @@ impl<T: Trait + ?Sized> Foo<T$0> {}
); );
} }
mod type_param_sized_bounds {
use super::*;
#[test]
fn single_implicit() {
check(
r#"
//- minicore: sized
fn foo<T$0>() {}
"#,
expect![[r#"
*T*
```rust
T
```
"#]],
);
}
#[test]
fn single_explicit() {
check(
r#"
//- minicore: sized
fn foo<T$0: Sized>() {}
"#,
expect![[r#"
*T*
```rust
T
```
"#]],
);
}
#[test]
fn single_relaxed() {
check(
r#"
//- minicore: sized
fn foo<T$0: ?Sized>() {}
"#,
expect![[r#"
*T*
```rust
T: ?Sized
```
"#]],
);
}
#[test]
fn multiple_implicit() {
check(
r#"
//- minicore: sized
trait Trait {}
fn foo<T$0: Trait>() {}
"#,
expect![[r#"
*T*
```rust
T: Trait
```
"#]],
);
}
#[test]
fn multiple_explicit() {
check(
r#"
//- minicore: sized
trait Trait {}
fn foo<T$0: Trait + Sized>() {}
"#,
expect![[r#"
*T*
```rust
T: Trait
```
"#]],
);
}
#[test]
fn multiple_relaxed() {
check(
r#"
//- minicore: sized
trait Trait {}
fn foo<T$0: Trait + ?Sized>() {}
"#,
expect![[r#"
*T*
```rust
T: Trait + ?Sized
```
"#]],
);
}
#[test]
fn mixed() {
check(
r#"
//- minicore: sized
fn foo<T$0: ?Sized + Sized + Sized>() {}
"#,
expect![[r#"
*T*
```rust
T
```
"#]],
);
check(
r#"
//- minicore: sized
trait Trait {}
fn foo<T$0: Sized + ?Sized + Sized + Trait>() {}
"#,
expect![[r#"
*T*
```rust
T: Trait
```
"#]],
);
}
}
#[test] #[test]
fn hover_const_param() { fn hover_const_param() {
check( check(