From bb921fbe94f1864350431eed5750a006da174437 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sat, 28 Dec 2024 20:31:20 +0100 Subject: [PATCH] Show variance of parameters on hover --- crates/hir-ty/src/generics.rs | 8 ++++---- crates/hir-ty/src/lib.rs | 8 ++++---- crates/hir/src/lib.rs | 20 +++++++++++++++++-- crates/ide/src/hover/render.rs | 9 +++++++++ crates/ide/src/hover/tests.rs | 36 ++++++++++++++++++++++++++++++++-- 5 files changed, 69 insertions(+), 12 deletions(-) diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs index fe7541d237..abbf2a4f2e 100644 --- a/crates/hir-ty/src/generics.rs +++ b/crates/hir-ty/src/generics.rs @@ -26,14 +26,14 @@ use triomphe::Arc; use crate::{db::HirDatabase, lt_to_placeholder_idx, to_placeholder_idx, Interner, Substitution}; -pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { +pub fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def))); let params = db.generic_params(def); let has_trait_self_param = params.trait_self_param().is_some(); Generics { def, params, parent_generics, has_trait_self_param } } #[derive(Clone, Debug)] -pub(crate) struct Generics { +pub struct Generics { def: GenericDefId, params: Arc, parent_generics: Option>, @@ -153,7 +153,7 @@ impl Generics { (parent_len, self_param, type_params, const_params, impl_trait_params, lifetime_params) } - pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option { + pub fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option { self.find_type_or_const_param(param) } @@ -174,7 +174,7 @@ impl Generics { } } - pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option { + pub fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option { self.find_lifetime(lifetime) } diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index 88134f564c..3c18ea9281 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -24,7 +24,6 @@ extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis; mod builder; mod chalk_db; mod chalk_ext; -mod generics; mod infer; mod inhabitedness; mod interner; @@ -39,6 +38,7 @@ pub mod db; pub mod diagnostics; pub mod display; pub mod dyn_compatibility; +pub mod generics; pub mod lang_items; pub mod layout; pub mod method_resolution; @@ -89,10 +89,9 @@ pub use infer::{ PointerCast, }; pub use interner::Interner; -pub use lower::diagnostics::*; pub use lower::{ - associated_type_shorthand_candidates, ImplTraitLoweringMode, ParamLoweringMode, TyDefId, - TyLoweringContext, ValueTyDefId, + associated_type_shorthand_candidates, diagnostics::*, ImplTraitLoweringMode, ParamLoweringMode, + TyDefId, TyLoweringContext, ValueTyDefId, }; pub use mapping::{ from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, @@ -102,6 +101,7 @@ pub use mapping::{ pub use method_resolution::check_orphan_rules; pub use traits::TraitEnvironment; pub use utils::{all_super_traits, direct_super_traits, is_fn_unsafe_to_call}; +pub use variance::Variance; pub use chalk_ir::{ cast::Cast, diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index ac8a62ee85..f8af04302f 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -101,7 +101,6 @@ pub use crate::{ PathResolution, Semantics, SemanticsImpl, SemanticsScope, TypeInfo, VisibleTraits, }, }; -pub use hir_ty::method_resolution::TyFingerprint; // Be careful with these re-exports. // @@ -151,8 +150,9 @@ pub use { display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite}, dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode}, layout::LayoutError, + method_resolution::TyFingerprint, mir::{MirEvalError, MirLowerError}, - CastError, FnAbi, PointerCast, Safety, + CastError, FnAbi, PointerCast, Safety, Variance, }, // FIXME: Properly encapsulate mir hir_ty::{mir, Interner as ChalkTyInterner}, @@ -3957,6 +3957,22 @@ impl GenericParam { GenericParam::LifetimeParam(it) => it.id.parent.into(), } } + + pub fn variance(self, db: &dyn HirDatabase) -> Option { + let parent = match self { + GenericParam::TypeParam(it) => it.id.parent(), + // const parameters are always invariant + GenericParam::ConstParam(_) => return None, + GenericParam::LifetimeParam(it) => it.id.parent, + }; + let generics = hir_ty::generics::generics(db.upcast(), parent); + let index = match self { + GenericParam::TypeParam(it) => generics.type_or_const_param_idx(it.id.into())?, + GenericParam::ConstParam(_) => return None, + GenericParam::LifetimeParam(it) => generics.lifetime_idx(it.id)?, + }; + db.variances_of(parent)?.get(index).copied() + } } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 119a864eb9..d87c15154e 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -594,12 +594,21 @@ pub(super) fn definition( _ => None, }; + let variance_info = || match def { + Definition::GenericParam(it) => it.variance(db).as_ref().map(ToString::to_string), + _ => None, + }; + let mut extra = String::new(); if hovered_definition { if let Some(notable_traits) = render_notable_trait(db, notable_traits, edition) { extra.push_str("\n___\n"); extra.push_str(¬able_traits); } + if let Some(variance_info) = variance_info() { + extra.push_str("\n___\n"); + extra.push_str(&variance_info); + } if let Some(layout_info) = layout_info() { extra.push_str("\n___\n"); extra.push_str(&layout_info); diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index ed8cd64cdb..fe7f0c79f5 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -4721,7 +4721,7 @@ fn hover_type_param_sized_bounds() { //- minicore: sized trait Trait {} struct Foo(T); -impl Foo {} +impl Foo {} "#, expect![[r#" *T* @@ -4736,7 +4736,7 @@ impl Foo {} //- minicore: sized trait Trait {} struct Foo(T); -impl Foo {} +impl Foo {} "#, expect![[r#" *T* @@ -4764,6 +4764,10 @@ fn foo() {} ```rust T ``` + + --- + + invariant "#]], ); } @@ -4781,6 +4785,10 @@ fn foo() {} ```rust T ``` + + --- + + invariant "#]], ); } @@ -4798,6 +4806,10 @@ fn foo() {} ```rust T: ?Sized ``` + + --- + + invariant "#]], ); } @@ -4816,6 +4828,10 @@ fn foo() {} ```rust T: Trait ``` + + --- + + invariant "#]], ); } @@ -4834,6 +4850,10 @@ fn foo() {} ```rust T: Trait ``` + + --- + + invariant "#]], ); } @@ -4852,6 +4872,10 @@ fn foo() {} ```rust T: Trait + ?Sized ``` + + --- + + invariant "#]], ); } @@ -4869,6 +4893,10 @@ fn foo() {} ```rust T ``` + + --- + + invariant "#]], ); } @@ -4887,6 +4915,10 @@ fn foo() {} ```rust T: Trait ``` + + --- + + invariant "#]], ); }