From b0e29318291fd200e9e7a8527952007dc0baa29d Mon Sep 17 00:00:00 2001 From: lzoghbi Date: Thu, 30 May 2024 00:56:15 -0700 Subject: [PATCH] cleanup CanonicalType --- src/ident.rs | 109 +++++++----------------------- src/resolution/hacky_resolver.rs | 16 ++--- src/resolution/name_resolution.rs | 2 +- src/resolution/util.rs | 108 ++--------------------------- 4 files changed, 35 insertions(+), 200 deletions(-) diff --git a/src/ident.rs b/src/ident.rs index 97d7ae8..c5e8ddf 100644 --- a/src/ident.rs +++ b/src/ident.rs @@ -327,120 +327,57 @@ impl CanonicalPath { #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Default)] pub enum TypeKind { RawPointer, - Callable(CallableKind), - DynTrait, - Generic, UnionFld, StaticMut, Function, #[default] - // Default case. Types that we have fully resolved - // and do not need extra information about. + // Default case for types that we + // don't need extra information about. Plain, } -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum CallableKind { - Closure, - FnPtr, - FnOnce, - Other, + +impl Display for TypeKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s = match self { + TypeKind::RawPointer => "raw pointer", + TypeKind::UnionFld => "union field", + TypeKind::StaticMut => "mutable static", + TypeKind::Function => "function", + TypeKind::Plain => "plain", + }; + write!(f, "{}", s) + } } /// Type representing a type identifier. #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Default)] -pub struct CanonicalType { - ty: String, - ty_kind: TypeKind, - trait_bounds: Vec, -} +pub struct CanonicalType(TypeKind); + impl Display for CanonicalType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.ty.fmt(f) + self.0.fmt(f) } } impl CanonicalType { - fn char_ok(c: char) -> bool { - c.is_ascii_alphanumeric() || "_-&*+#|!=',;:<>()[]{}? ".contains(c) - } - - pub fn invariant(&self) -> bool { - self.ty.chars().all(Self::char_ok) - } - - pub fn check_invariant(&self) { - if !self.invariant() { - warn!("failed invariant! on CanonicalType {}", self); - } - } - - pub fn new(s: &str) -> Self { - Self::new_owned_string(s.to_string()) - } - - pub fn new_owned_string(s: String) -> Self { - Self::new_owned(s, vec![], Default::default()) - } - - pub fn new_owned(s: String, b: Vec, k: TypeKind) -> Self { - let result = Self { ty: s, trait_bounds: b, ty_kind: k }; - result.check_invariant(); - result - } - - pub fn as_str(&self) -> &str { - self.ty.as_str() - } - - pub fn add_trait_bound(&mut self, trait_bound: CanonicalPath) { - self.trait_bounds.push(trait_bound) - } - - pub fn get_trait_bounds(&self) -> &Vec { - &self.trait_bounds + pub fn new(k: TypeKind) -> Self { + Self(k) } pub fn is_raw_ptr(&self) -> bool { - matches!(self.ty_kind, TypeKind::RawPointer) - } - - pub fn is_callable(&self) -> bool { - matches!(&self.ty_kind, TypeKind::Callable(_)) - } - - pub fn is_dyn_trait(&self) -> bool { - matches!(self.ty_kind, TypeKind::DynTrait) - } - - pub fn is_generic(&self) -> bool { - matches!(self.ty_kind, TypeKind::Generic) - } - - pub fn is_closure(&self) -> bool { - matches!(&self.ty_kind, TypeKind::Callable(crate::ident::CallableKind::Closure)) + matches!(self.0, TypeKind::RawPointer) } pub fn is_union_field(&self) -> bool { - matches!(self.ty_kind, TypeKind::UnionFld) + matches!(self.0, TypeKind::UnionFld) } pub fn is_mut_static(&self) -> bool { - matches!(self.ty_kind, TypeKind::StaticMut) + matches!(self.0, TypeKind::StaticMut) } pub fn is_function(&self) -> bool { - matches!(self.ty_kind, TypeKind::Function) - } - - pub fn is_fn_ptr(&self) -> bool { - matches!(&self.ty_kind, TypeKind::Callable(crate::ident::CallableKind::FnPtr)) - } - - pub fn get_callable_kind(&self) -> Option { - if let TypeKind::Callable(kind) = &self.ty_kind { - return Some(kind.clone()); - } - None + matches!(self.0, TypeKind::Function) } } diff --git a/src/resolution/hacky_resolver.rs b/src/resolution/hacky_resolver.rs index cb7ea35..72c115d 100644 --- a/src/resolution/hacky_resolver.rs +++ b/src/resolution/hacky_resolver.rs @@ -163,8 +163,8 @@ impl<'a> Resolve<'a> for HackyResolver<'a> { Self::aggregate_path(self.filepath, &self.lookup_path_vec(p)) } - fn resolve_path_type(&self, p: &'a syn::Path) -> CanonicalType { - Self::aggregate_path_type(&self.lookup_path_vec(p)) + fn resolve_path_type(&self, _: &'a syn::Path) -> CanonicalType { + CanonicalType::new(Default::default()) } fn resolve_def(&self, i: &'a syn::Ident) -> CanonicalPath { @@ -199,8 +199,8 @@ impl<'a> Resolve<'a> for HackyResolver<'a> { CanonicalPath::new_owned(format!("UNKNOWN_FIELD::{}", i), src_loc) } - fn resolve_field_type(&self, i: &syn::Ident) -> CanonicalType { - CanonicalType::new_owned_string(format!("UNKNOWN_TYPE::{}", i)) + fn resolve_field_type(&self, _: &syn::Ident) -> CanonicalType { + CanonicalType::new(Default::default()) } fn resolve_field_index(&self, idx: &'a syn::Index) -> CanonicalPath { @@ -467,12 +467,4 @@ impl<'a> HackyResolver<'a> { } CanonicalPath::from_path(result, SrcLoc::from_span(fp, &span)) } - - fn aggregate_path_type(p: &[&'a syn::Ident]) -> CanonicalType { - let mut result = IdentPath::new_empty(); - for &i in p { - result.push_ident(&ident_from_syn(i)); - } - CanonicalType::new_owned_string(result.to_string()) - } } diff --git a/src/resolution/name_resolution.rs b/src/resolution/name_resolution.rs index 0b389bf..e940cf8 100644 --- a/src/resolution/name_resolution.rs +++ b/src/resolution/name_resolution.rs @@ -294,7 +294,7 @@ impl<'a> ResolverImpl<'a> { let token = self.token(i, s)?; let def = self.find_def(&token)?; - get_canonical_type(&self.sems, self.db, &def) + get_canonical_type(self.db, &def) } pub fn is_ffi(&self, s: SrcLoc, i: Ident) -> Result { diff --git a/src/resolution/util.rs b/src/resolution/util.rs index 14e83c0..ca8bae0 100644 --- a/src/resolution/util.rs +++ b/src/resolution/util.rs @@ -5,8 +5,8 @@ use ra_ap_hir_expand::InFile; use crate::ident::{CanonicalPath, CanonicalType, Ident, TypeKind}; use ra_ap_hir::{ - Adt, AsAssocItem, AssocItemContainer, DefWithBody, GenericParam, HasSource, - HirDisplay, Module, ModuleSource, Semantics, VariantDef, + Adt, AsAssocItem, AssocItemContainer, DefWithBody, GenericParam, HasSource, Module, + ModuleSource, Semantics, VariantDef, }; use ra_ap_hir_expand::name::AsName; @@ -206,32 +206,12 @@ fn get_container_name( container_names } -// Get the fully resolved type of a definition. -// e.g in pub fn test() -> Option<&(dyn Error + 'static)> { None } -// the type of function 'test' is core::option::Option<&dyn core::error::Error> +/// Type resolution pub(super) fn get_canonical_type( - sems: &Semantics, db: &RootDatabase, def: &Definition, ) -> Result { - let mut type_defs: Vec = Vec::new(); - let mut trait_bounds: Vec = Vec::new(); let mut ty_kind = TypeKind::Plain; - let mut type_; - - let mut push = |d| { - if !type_defs.contains(&d) { - type_defs.push(d); - } - }; - - let mut resolve_bounds = |tr| { - if let Some(b) = canonical_path(sems, db, &tr) { - if !trait_bounds.contains(&b) { - trait_bounds.push(b); - } - } - }; let ty = match def { Definition::Adt(it) => Some(it.ty(db)), @@ -256,92 +236,18 @@ pub(super) fn get_canonical_type( } Some(it.ty(db)) } - Definition::GenericParam(GenericParam::TypeParam(it)) => { - it.trait_bounds(db).into_iter().for_each(|it| resolve_bounds(it.into())); - Some(it.ty(db)) - } + Definition::GenericParam(GenericParam::TypeParam(it)) => Some(it.ty(db)), Definition::GenericParam(GenericParam::ConstParam(it)) => Some(it.ty(db)), - Definition::Variant(_) => { - match canonical_path(sems, db, def) { - Some(cp) => { - return Ok(CanonicalType::new_owned( - cp.as_str().to_string(), - vec![], - ty_kind, - )) - } - None => { - return Err(anyhow!( - "Could not resolve type for definition {:?}", - def.name(db) - )) - } - }; - } + Definition::Variant(_) => return Ok(CanonicalType::new(ty_kind)), _ => None, - }; - - if ty.is_none() - /*|| (ty.is_some() && ty.clone().unwrap().contains_unknown())*/ - { - return Err(anyhow!("Could not resolve type for definition {:?}", def.name(db))); } + .ok_or_else(|| anyhow!("Could not resolve type for definition {:?}", def.name(db)))?; - let ty = ty.unwrap(); - if ty.impls_fnonce(db) { - // impls_fnonce can be used in RA to check if a type is callable. - // FnOnce is a supertait of FnMut and Fn, so any callable type - // implements at least FnOnce. - // TODO: More sophisticated checks are needed to precisely - // determine which trait is actually implemented. - ty_kind = TypeKind::Callable(crate::ident::CallableKind::FnOnce) - } - if ty.is_closure() { - ty_kind = TypeKind::Callable(crate::ident::CallableKind::Closure) - } - if ty.is_fn() { - ty_kind = TypeKind::Callable(crate::ident::CallableKind::FnPtr) - } if ty.is_raw_ptr() { ty_kind = TypeKind::RawPointer } - if ty.as_dyn_trait().is_some() { - ty_kind = TypeKind::DynTrait - } - if ty.as_type_param(db).is_some() { - ty_kind = TypeKind::Generic - } - - // Get the type as it is displayed by rust-analyzer - type_ = ty.display(db).to_string(); - - // Walk type and gather all Enums, Structs, Unions, - // or Traits it contains to fully resolve them - ty.walk(db, |t| { - if let Some(adt) = t.as_adt() { - push(adt.into()); - } else if let Some(trait_) = t.as_dyn_trait() { - push(trait_.into()); - } else if let Some(traits) = t.as_impl_traits(db) { - traits.for_each(|it| push(it.into())); - } else if let Some(trait_) = t.as_associated_type_parent_trait(db) { - push(trait_.into()); - } - }); - - // Resolve types. - // e.g 'Option' resolves to 'core::option::Option'. - type_defs.into_iter().for_each(|it| { - type_ = canonical_path(sems, db, &it).map_or(type_.clone(), |cp| { - type_.replace( - name_to_string(it.name(db).expect("Definition should a have name")) - .as_str(), - cp.as_str(), - ) - }) - }); - Ok(CanonicalType::new_owned(type_, trait_bounds, ty_kind)) + Ok(CanonicalType::new(ty_kind)) } /// Get source node from the original source