]> git.lizzy.rs Git - rust.git/commitdiff
Make remaining item data queries use item tree
authorJonas Schievink <jonas.schievink@ferrous-systems.com>
Mon, 22 Jun 2020 14:41:10 +0000 (16:41 +0200)
committerJonas Schievink <jonas.schievink@ferrous-systems.com>
Wed, 24 Jun 2020 14:53:16 +0000 (16:53 +0200)
crates/ra_hir_def/src/data.rs
crates/ra_hir_def/src/item_tree.rs
crates/ra_hir_def/src/item_tree/lower.rs
crates/ra_hir_def/src/item_tree/tests.rs
crates/ra_hir_def/src/visibility.rs

index 697fde3d21a24bf5417c1f3fd0fd9b956a58b0e4..921253c42d601edd3a889e5ab1a24be61895d178 100644 (file)
@@ -2,23 +2,16 @@
 
 use std::sync::Arc;
 
-use hir_expand::{
-    hygiene::Hygiene,
-    name::{name, AsName, Name},
-    InFile,
-};
+use hir_expand::{name::Name, InFile};
 use ra_prof::profile;
-use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, TypeBoundsOwner, VisibilityOwner};
+use ra_syntax::ast;
 
 use crate::{
     attr::Attrs,
     body::Expander,
-    body::LowerCtx,
     db::DefDatabase,
     item_tree::{AssocItem, ItemTreeId, ModItem},
-    path::{path, AssociatedTypeBinding, GenericArgs, Path},
-    src::HasSource,
-    type_ref::{Mutability, TypeBound, TypeRef},
+    type_ref::{TypeBound, TypeRef},
     visibility::RawVisibility,
     AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
     Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
@@ -40,82 +33,27 @@ pub struct FunctionData {
 impl FunctionData {
     pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> {
         let loc = func.lookup(db);
-        let src = loc.source(db);
-        let ctx = LowerCtx::new(db, src.file_id);
-        let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
-        let mut params = Vec::new();
-        let mut has_self_param = false;
-        if let Some(param_list) = src.value.param_list() {
-            if let Some(self_param) = param_list.self_param() {
-                let self_type = if let Some(type_ref) = self_param.ascribed_type() {
-                    TypeRef::from_ast(&ctx, type_ref)
-                } else {
-                    let self_type = TypeRef::Path(name![Self].into());
-                    match self_param.kind() {
-                        ast::SelfParamKind::Owned => self_type,
-                        ast::SelfParamKind::Ref => {
-                            TypeRef::Reference(Box::new(self_type), Mutability::Shared)
-                        }
-                        ast::SelfParamKind::MutRef => {
-                            TypeRef::Reference(Box::new(self_type), Mutability::Mut)
-                        }
-                    }
-                };
-                params.push(self_type);
-                has_self_param = true;
-            }
-            for param in param_list.params() {
-                let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
-                params.push(type_ref);
-            }
-        }
-        let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id));
-
-        let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
-            TypeRef::from_ast(&ctx, type_ref)
-        } else {
-            TypeRef::unit()
-        };
-
-        let ret_type = if src.value.async_token().is_some() {
-            let future_impl = desugar_future_path(ret_type);
-            let ty_bound = TypeBound::Path(future_impl);
-            TypeRef::ImplTrait(vec![ty_bound])
-        } else {
-            ret_type
-        };
-
-        let is_unsafe = src.value.unsafe_token().is_some();
-
-        let vis_default = RawVisibility::default_for_container(loc.container);
-        let visibility =
-            RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility()));
-
-        let sig =
-            FunctionData { name, params, ret_type, has_self_param, is_unsafe, visibility, attrs };
-        Arc::new(sig)
+        let item_tree = db.item_tree(loc.id.file_id);
+        let func = &item_tree[loc.id.value];
+
+        Arc::new(FunctionData {
+            name: func.name.clone(),
+            params: func.params.clone(),
+            ret_type: func.ret_type.clone(),
+            attrs: func.attrs.clone(),
+            has_self_param: func.has_self_param,
+            is_unsafe: func.is_unsafe,
+            visibility: func.visibility.clone(),
+        })
     }
 }
 
-fn desugar_future_path(orig: TypeRef) -> Path {
-    let path = path![core::future::Future];
-    let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect();
-    let mut last = GenericArgs::empty();
-    last.bindings.push(AssociatedTypeBinding {
-        name: name![Output],
-        type_ref: Some(orig),
-        bounds: Vec::new(),
-    });
-    generic_args.push(Some(Arc::new(last)));
-
-    Path::from_known_path(path, generic_args)
-}
-
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct TypeAliasData {
     pub name: Name,
     pub type_ref: Option<TypeRef>,
     pub visibility: RawVisibility,
+    /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
     pub bounds: Vec<TypeBound>,
 }
 
@@ -125,22 +63,15 @@ pub(crate) fn type_alias_data_query(
         typ: TypeAliasId,
     ) -> Arc<TypeAliasData> {
         let loc = typ.lookup(db);
-        let node = loc.source(db);
-        let name = node.value.name().map_or_else(Name::missing, |n| n.as_name());
-        let lower_ctx = LowerCtx::new(db, node.file_id);
-        let type_ref = node.value.type_ref().map(|it| TypeRef::from_ast(&lower_ctx, it));
-        let vis_default = RawVisibility::default_for_container(loc.container);
-        let visibility = RawVisibility::from_ast_with_default(
-            db,
-            vis_default,
-            node.as_ref().map(|n| n.visibility()),
-        );
-        let bounds = if let Some(bound_list) = node.value.type_bound_list() {
-            bound_list.bounds().map(|it| TypeBound::from_ast(&lower_ctx, it)).collect()
-        } else {
-            Vec::new()
-        };
-        Arc::new(TypeAliasData { name, type_ref, visibility, bounds })
+        let item_tree = db.item_tree(loc.id.file_id);
+        let typ = &item_tree[loc.id.value];
+
+        Arc::new(TypeAliasData {
+            name: typ.name.clone(),
+            type_ref: typ.type_ref.clone(),
+            visibility: typ.visibility.clone(),
+            bounds: typ.bounds.clone(),
+        })
     }
 }
 
@@ -238,22 +169,14 @@ pub struct ConstData {
 impl ConstData {
     pub(crate) fn const_data_query(db: &dyn DefDatabase, konst: ConstId) -> Arc<ConstData> {
         let loc = konst.lookup(db);
-        let node = loc.source(db);
-        let vis_default = RawVisibility::default_for_container(loc.container);
-        Arc::new(ConstData::new(db, vis_default, node))
-    }
+        let item_tree = db.item_tree(loc.id.file_id);
+        let konst = &item_tree[loc.id.value];
 
-    fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>(
-        db: &dyn DefDatabase,
-        vis_default: RawVisibility,
-        node: InFile<N>,
-    ) -> ConstData {
-        let ctx = LowerCtx::new(db, node.file_id);
-        let name = node.value.name().map(|n| n.as_name());
-        let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
-        let visibility =
-            RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility()));
-        ConstData { name, type_ref, visibility }
+        Arc::new(ConstData {
+            name: konst.name.clone(),
+            type_ref: konst.type_ref.clone(),
+            visibility: konst.visibility.clone(),
+        })
     }
 }
 
@@ -267,19 +190,16 @@ pub struct StaticData {
 
 impl StaticData {
     pub(crate) fn static_data_query(db: &dyn DefDatabase, konst: StaticId) -> Arc<StaticData> {
-        let node = konst.lookup(db).source(db);
-        let ctx = LowerCtx::new(db, node.file_id);
-
-        let name = node.value.name().map(|n| n.as_name());
-        let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
-        let mutable = node.value.mut_token().is_some();
-        let visibility = RawVisibility::from_ast_with_default(
-            db,
-            RawVisibility::private(),
-            node.map(|n| n.visibility()),
-        );
-
-        Arc::new(StaticData { name, type_ref, visibility, mutable })
+        let node = konst.lookup(db);
+        let item_tree = db.item_tree(node.id.file_id);
+        let statik = &item_tree[node.id.value];
+
+        Arc::new(StaticData {
+            name: Some(statik.name.clone()),
+            type_ref: statik.type_ref.clone(),
+            visibility: statik.visibility.clone(),
+            mutable: statik.mutable,
+        })
     }
 }
 
index 9a5dd701eb6ce322d221c251ed60f1559712bff8..c35d6329521b9e76b56eff50ae551a9998229999 100644 (file)
@@ -349,6 +349,7 @@ pub struct Function {
     pub visibility: RawVisibility,
     pub generic_params: GenericParams,
     pub has_self_param: bool,
+    pub is_unsafe: bool,
     pub params: Vec<TypeRef>,
     pub ret_type: TypeRef,
     pub ast_id: FileAstId<ast::FnDef>,
@@ -408,6 +409,7 @@ pub struct Const {
 pub struct Static {
     pub name: Name,
     pub visibility: RawVisibility,
+    pub mutable: bool,
     pub type_ref: TypeRef,
     pub ast_id: FileAstId<ast::StaticDef>,
 }
@@ -436,6 +438,8 @@ pub struct Impl {
 pub struct TypeAlias {
     pub name: Name,
     pub visibility: RawVisibility,
+    /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
+    pub bounds: Vec<TypeBound>,
     pub generic_params: GenericParams,
     pub type_ref: Option<TypeRef>,
     pub ast_id: FileAstId<ast::TypeAliasDef>,
index f2b8a941822ea50ee60189c4ee2cf7caf714178b..42af8bb5e5ca96d08da2d46bfa83835871210ecf 100644 (file)
@@ -36,6 +36,7 @@ pub(super) struct Ctx {
     source_ast_id_map: Arc<AstIdMap>,
     body_ctx: crate::body::LowerCtx,
     inner_items: Vec<ModItem>,
+    forced_visibility: Option<RawVisibility>,
 }
 
 impl Ctx {
@@ -47,6 +48,7 @@ pub(super) fn new(db: &dyn DefDatabase, hygiene: Hygiene, file: HirFileId) -> Se
             source_ast_id_map: db.ast_id_map(file),
             body_ctx: crate::body::LowerCtx::new(db, file),
             inner_items: Vec::new(),
+            forced_visibility: None,
         }
     }
 
@@ -117,6 +119,7 @@ fn lower_mod_item(&mut self, item: &ast::ModuleItem, inner: bool) -> Option<ModI
     }
 
     fn collect_inner_items(&mut self, container: &SyntaxNode) {
+        let forced_vis = self.forced_visibility.take();
         let mut inner_items = mem::replace(&mut self.tree.inner_items, FxHashMap::default());
         inner_items.extend(
             container.descendants().skip(1).filter_map(ast::ModuleItem::cast).filter_map(|item| {
@@ -125,6 +128,7 @@ fn collect_inner_items(&mut self, container: &SyntaxNode) {
             }),
         );
         self.tree.inner_items = inner_items;
+        self.forced_visibility = forced_vis;
     }
 
     fn lower_assoc_item(&mut self, item: &ast::ModuleItem) -> Option<AssocItem> {
@@ -304,6 +308,7 @@ fn lower_function(&mut self, func: &ast::FnDef) -> Option<FileItemTreeId<Functio
             visibility,
             generic_params: GenericParams::default(),
             has_self_param,
+            is_unsafe: func.unsafe_token().is_some(),
             params,
             ret_type,
             ast_id,
@@ -320,9 +325,10 @@ fn lower_type_alias(
         let name = type_alias.name()?.as_name();
         let type_ref = type_alias.type_ref().map(|it| self.lower_type_ref(&it));
         let visibility = self.lower_visibility(type_alias);
+        let bounds = self.lower_type_bounds(type_alias);
         let generic_params = self.lower_generic_params(GenericsOwner::TypeAlias, type_alias);
         let ast_id = self.source_ast_id_map.ast_id(type_alias);
-        let res = TypeAlias { name, visibility, generic_params, type_ref, ast_id };
+        let res = TypeAlias { name, visibility, bounds, generic_params, type_ref, ast_id };
         Some(id(self.tree.type_aliases.alloc(res)))
     }
 
@@ -330,8 +336,9 @@ fn lower_static(&mut self, static_: &ast::StaticDef) -> Option<FileItemTreeId<St
         let name = static_.name()?.as_name();
         let type_ref = self.lower_type_ref_opt(static_.ascribed_type());
         let visibility = self.lower_visibility(static_);
+        let mutable = static_.mut_token().is_some();
         let ast_id = self.source_ast_id_map.ast_id(static_);
-        let res = Static { name, visibility, type_ref, ast_id };
+        let res = Static { name, visibility, mutable, type_ref, ast_id };
         Some(id(self.tree.statics.alloc(res)))
     }
 
@@ -376,12 +383,14 @@ fn lower_trait(&mut self, trait_def: &ast::TraitDef) -> Option<FileItemTreeId<Tr
         let generic_params = self.lower_generic_params(GenericsOwner::Trait(trait_def), trait_def);
         let auto = trait_def.auto_token().is_some();
         let items = trait_def.item_list().map(|list| {
-            list.items()
-                .flat_map(|item| {
-                    self.collect_inner_items(item.syntax());
-                    self.lower_assoc_item(&item)
-                })
-                .collect()
+            self.with_inherited_visibility(visibility.clone(), |this| {
+                list.items()
+                    .flat_map(|item| {
+                        this.collect_inner_items(item.syntax());
+                        this.lower_assoc_item(&item)
+                    })
+                    .collect()
+            })
         });
         let ast_id = self.source_ast_id_map.ast_id(trait_def);
         let res = Trait {
@@ -549,11 +558,23 @@ fn lower_generic_params(
         generics
     }
 
+    fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> {
+        if let Some(bound_list) = node.type_bound_list() {
+            bound_list.bounds().map(|it| TypeBound::from_ast(&self.body_ctx, it)).collect()
+        } else {
+            Vec::new()
+        }
+    }
+
     fn lower_attrs(&self, item: &impl ast::AttrsOwner) -> Attrs {
         Attrs::new(item, &self.hygiene)
     }
     fn lower_visibility(&self, item: &impl ast::VisibilityOwner) -> RawVisibility {
-        RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene)
+        if let Some(vis) = self.forced_visibility.as_ref() {
+            vis.clone()
+        } else {
+            RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene)
+        }
     }
     fn lower_type_ref(&self, type_ref: &ast::TypeRef) -> TypeRef {
         TypeRef::from_ast(&self.body_ctx, type_ref.clone())
@@ -562,6 +583,18 @@ fn lower_type_ref_opt(&self, type_ref: Option<ast::TypeRef>) -> TypeRef {
         TypeRef::from_ast_opt(&self.body_ctx, type_ref)
     }
 
+    /// Forces the visibility `vis` to be used for all items lowered during execution of `f`.
+    fn with_inherited_visibility<R>(
+        &mut self,
+        vis: RawVisibility,
+        f: impl FnOnce(&mut Self) -> R,
+    ) -> R {
+        let old = mem::replace(&mut self.forced_visibility, Some(vis));
+        let res = f(self);
+        self.forced_visibility = old;
+        res
+    }
+
     fn next_field_idx(&self) -> Idx<Field> {
         Idx::from_raw(RawId::from(self.tree.fields.len() as u32))
     }
index b60e6cbb0c06328705bb648defdc9a99122c1d7d..1db1ce7a9aeed90353bd8d3ccc139e72f6dba77a 100644 (file)
@@ -204,7 +204,7 @@ fn end<W: Write>() {
 
 inner items:
 FileAstId::<ra_syntax::ast::generated::nodes::ModuleItem>(2):
-- Function { name: Name(Text("end")), attrs: Attrs { entries: None }, visibility: Module(ModPath { kind: Super(0), segments: [] }), generic_params: GenericParams { types: Arena { len: 1, data: [TypeParamData { name: Some(Name(Text("W"))), default: None, provenance: TypeParamList }] }, where_predicates: [WherePredicate { target: TypeRef(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("W"))] }, generic_args: [None] })), bound: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Write"))] }, generic_args: [None] }) }] }, has_self_param: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
+- Function { name: Name(Text("end")), attrs: Attrs { entries: None }, visibility: Module(ModPath { kind: Super(0), segments: [] }), generic_params: GenericParams { types: Arena { len: 1, data: [TypeParamData { name: Some(Name(Text("W"))), default: None, provenance: TypeParamList }] }, where_predicates: [WherePredicate { target: TypeRef(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("W"))] }, generic_args: [None] })), bound: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Write"))] }, generic_args: [None] }) }] }, has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
     "###);
 }
 
index 1482d3be04da0610288e2bd5932143b452223696..8136cb50ccfefa35f7b05cba88ddb966668ac47f 100644 (file)
@@ -6,7 +6,7 @@
 use crate::{
     db::DefDatabase,
     path::{ModPath, PathKind},
-    AssocContainerId, ModuleId,
+    ModuleId,
 };
 
 /// Visibility of an item, not yet resolved.
@@ -25,25 +25,6 @@ pub(crate) const fn private() -> RawVisibility {
         RawVisibility::Module(path)
     }
 
-    pub(crate) fn default_for_container(container_id: AssocContainerId) -> Self {
-        match container_id {
-            AssocContainerId::TraitId(_) => RawVisibility::Public,
-            _ => RawVisibility::private(),
-        }
-    }
-
-    pub(crate) fn from_ast_with_default(
-        db: &dyn DefDatabase,
-        default: RawVisibility,
-        node: InFile<Option<ast::Visibility>>,
-    ) -> RawVisibility {
-        Self::from_ast_with_hygiene_and_default(
-            node.value,
-            default,
-            &Hygiene::new(db.upcast(), node.file_id),
-        )
-    }
-
     pub(crate) fn from_ast(
         db: &dyn DefDatabase,
         node: InFile<Option<ast::Visibility>>,