Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir/src/display.rs35
-rw-r--r--crates/hir_ty/src/lower.rs12
-rw-r--r--crates/ide/src/hover.rs175
3 files changed, 201 insertions, 21 deletions
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index dff4372738..4ef7d399de 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -5,16 +5,19 @@ use hir_def::{
type_ref::{TypeBound, TypeRef},
AdtId, GenericDefId,
};
-use hir_ty::display::{
- write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
- HirFormatter, SizedByDefault,
+use hir_ty::{
+ display::{
+ 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 crate::{
- Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam,
- Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union, Variant,
+ Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasCrate, HasVisibility,
+ LifetimeParam, Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union,
+ Variant,
};
impl HirDisplay for Function {
@@ -234,12 +237,24 @@ impl HirDisplay for GenericParam {
impl HirDisplay for TypeParam {
fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
write!(f, "{}", self.name(f.db))?;
+ if f.omit_verbose_types() {
+ return Ok(());
+ }
+
let bounds = f.db.generic_predicates_for_param(self.id);
let substs = TyBuilder::type_params_subst(f.db, self.id.parent);
- let predicates =
- bounds.iter().cloned().map(|b| b.substitute(&Interner, &substs)).collect::<Vec<_>>();
- if !(predicates.is_empty() || f.omit_verbose_types()) {
- let default_sized = SizedByDefault::Sized { anchor: self.module(f.db).krate().id };
+ 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, "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)?;
}
Ok(())
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index ad45a29346..13785e3a6c 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -1024,7 +1024,7 @@ pub(crate) fn generic_predicates_for_param_query(
let ctx =
TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
let generics = generics(db.upcast(), param_id.parent);
- resolver
+ let mut predicates: Vec<_> = resolver
.where_predicates_in_scope()
// we have to filter out all other predicates *first*, before attempting to lower them
.filter(|pred| match pred {
@@ -1038,7 +1038,15 @@ pub(crate) fn generic_predicates_for_param_query(
WherePredicate::Lifetime { .. } => false,
})
.flat_map(|pred| ctx.lower_where_predicate(pred, true).map(|p| make_binders(&generics, p)))
- .collect()
+ .collect();
+
+ let subst = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
+ let explicitly_unsized_tys = ctx.unsized_types.into_inner();
+ let implicitly_sized_predicates =
+ implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &subst, &resolver)
+ .map(|p| make_binders(&generics, crate::wrap_empty_binders(p)));
+ predicates.extend(implicitly_sized_predicates);
+ predicates.into()
}
pub(crate) fn generic_predicates_for_param_recover(
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 62a322f976..68b75f3ffc 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -3564,20 +3564,21 @@ fn foo() {
r#"
//- minicore: sized
struct Foo<T>(T);
-trait Copy {}
-trait Clone {}
-impl<T: Copy + Clone> Foo<T$0> where T: Sized {}
+trait TraitA {}
+trait TraitB {}
+impl<T: TraitA + TraitB> Foo<T$0> where T: Sized {}
"#,
expect![[r#"
*T*
```rust
- T: Copy + Clone
+ T: TraitA + TraitB
```
"#]],
);
check(
r#"
+//- minicore: sized
struct Foo<T>(T);
impl<T> Foo<T$0> {}
"#,
@@ -3592,6 +3593,7 @@ impl<T> Foo<T$0> {}
// lifetimes bounds arent being tracked yet
check(
r#"
+//- minicore: sized
struct Foo<T>(T);
impl<T: 'static> Foo<T$0> {}
"#,
@@ -3606,25 +3608,180 @@ impl<T: 'static> Foo<T$0> {}
}
#[test]
- fn hover_type_param_not_sized() {
+ fn hover_type_param_sized_bounds() {
+ // implicit `: Sized` bound
check(
r#"
//- minicore: sized
+trait Trait {}
struct Foo<T>(T);
-trait Copy {}
-trait Clone {}
-impl<T: Copy + Clone> Foo<T$0> where T: ?Sized {}
+impl<T: Trait> Foo<T$0> {}
+"#,
+ expect![[r#"
+ *T*
+
+ ```rust
+ T: Trait
+ ```
+ "#]],
+ );
+ check(
+ r#"
+//- minicore: sized
+trait Trait {}
+struct Foo<T>(T);
+impl<T: Trait + ?Sized> Foo<T$0> {}
"#,
expect![[r#"
*T*
```rust
- T: Copy + Clone + ?Sized
+ T: Trait + ?Sized
```
"#]],
);
}
+ 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]
fn hover_const_param() {
check(