From e6545cc647829091dd5aae5753bd4f5302becab6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 30 May 2019 14:05:35 +0300 Subject: [PATCH 1/5] add ModuleDef::BuiltInType --- crates/ra_hir/src/code_model.rs | 15 +++++++++++-- crates/ra_hir/src/lib.rs | 5 +++-- crates/ra_hir/src/ty/infer.rs | 3 ++- crates/ra_hir/src/ty/lower.rs | 36 ++++++++++++++++++++++++++----- crates/ra_hir/src/ty/primitive.rs | 12 +++++++++++ 5 files changed, 61 insertions(+), 10 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 69496b6242dd..3f77850dd313 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -9,7 +9,7 @@ use crate::{ type_ref::TypeRef, nameres::{ModuleScope, Namespace, ImportId, CrateModuleId}, expr::{Body, BodySourceMap, validation::ExprValidator}, - ty::{TraitRef, InferenceResult}, + ty::{TraitRef, InferenceResult, primitive::{IntTy, FloatTy}}, adt::{EnumVariantId, StructFieldId, VariantDef}, generics::HasGenericParams, docs::{Documentation, Docs, docs_from_ast}, @@ -75,6 +75,15 @@ pub struct Module { pub(crate) module_id: CrateModuleId, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum BuiltinType { + Char, + Bool, + Str, + Int(IntTy), + Float(FloatTy), +} + /// The defs which can be visible in the module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ModuleDef { @@ -89,6 +98,7 @@ pub enum ModuleDef { Static(Static), Trait(Trait), TypeAlias(TypeAlias), + BuiltinType(BuiltinType), } impl_froms!( ModuleDef: Module, @@ -100,7 +110,8 @@ impl_froms!( Const, Static, Trait, - TypeAlias + TypeAlias, + BuiltinType ); pub enum ModuleSource { diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index cb09c60f8abc..3e00eea26515 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -6,7 +6,7 @@ //! applied. So, the relation between syntax and HIR is many-to-one. macro_rules! impl_froms { - ($e:ident: $($v:ident), *) => { + ($e:ident: $($v:ident),*) => { $( impl From<$v> for $e { fn from(it: $v) -> $e { @@ -80,5 +80,6 @@ pub use self::code_model::{ Function, FnSignature, StructField, FieldSource, Static, Const, ConstSignature, - Trait, TypeAlias, MacroDef, Container + Trait, TypeAlias, MacroDef, Container, + BuiltinType, }; diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 7d8250292ef2..e8ae33eadcae 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -649,7 +649,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | TypableDef::Function(_) | TypableDef::Enum(_) | TypableDef::Const(_) - | TypableDef::Static(_) => (Ty::Unknown, None), + | TypableDef::Static(_) + | TypableDef::BuiltinType(_) => (Ty::Unknown, None), } } diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 7defa7a9b9eb..c4cef2d7ce65 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -10,7 +10,7 @@ use std::iter; use crate::{ Function, Struct, Union, StructField, Enum, EnumVariant, Path, ModuleDef, TypeAlias, Const, Static, - HirDatabase, + HirDatabase, BuiltinType, type_ref::TypeRef, name::KnownName, nameres::Namespace, @@ -66,7 +66,7 @@ impl Ty { pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Self { if let Some(name) = path.as_ident() { - // FIXME handle primitive type names in resolver as well? + // TODO: remove this if let Some(int_ty) = primitive::IntTy::from_type_name(name) { return Ty::simple(TypeCtor::Int(primitive::UncertainIntTy::Known(int_ty))); } else if let Some(float_ty) = primitive::FloatTy::from_type_name(name) { @@ -128,7 +128,7 @@ impl Ty { TypableDef::Enum(e) => Some(e.into()), TypableDef::EnumVariant(var) => Some(var.parent_enum(db).into()), TypableDef::TypeAlias(t) => Some(t.into()), - TypableDef::Const(_) | TypableDef::Static(_) => None, + TypableDef::Const(_) | TypableDef::Static(_) | TypableDef::BuiltinType(_) => None, }; substs_from_path_segment(db, resolver, segment, def_generic, false) } @@ -149,7 +149,8 @@ impl Ty { | TypableDef::Enum(_) | TypableDef::Const(_) | TypableDef::Static(_) - | TypableDef::TypeAlias(_) => last, + | TypableDef::TypeAlias(_) + | TypableDef::BuiltinType(_) => last, TypableDef::EnumVariant(_) => { // the generic args for an enum variant may be either specified // on the segment referring to the enum, or on the segment @@ -299,6 +300,7 @@ pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace (TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t), (TypableDef::Const(c), Namespace::Values) => type_for_const(db, c), (TypableDef::Static(c), Namespace::Values) => type_for_static(db, c), + (TypableDef::BuiltinType(t), Namespace::Types) => type_for_builtin(t), // 'error' cases: (TypableDef::Function(_), Namespace::Types) => Ty::Unknown, @@ -308,6 +310,7 @@ pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace (TypableDef::TypeAlias(_), Namespace::Values) => Ty::Unknown, (TypableDef::Const(_), Namespace::Types) => Ty::Unknown, (TypableDef::Static(_), Namespace::Types) => Ty::Unknown, + (TypableDef::BuiltinType(_), Namespace::Values) => Ty::Unknown, } } @@ -399,6 +402,17 @@ fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { Ty::from_hir(db, &resolver, signature.type_ref()) } +/// Build the declared type of a static. +fn type_for_builtin(def: BuiltinType) -> Ty { + Ty::simple(match def { + BuiltinType::Char => TypeCtor::Char, + BuiltinType::Bool => TypeCtor::Bool, + BuiltinType::Str => TypeCtor::Str, + BuiltinType::Int(ty) => TypeCtor::Int(ty.into()), + BuiltinType::Float(ty) => TypeCtor::Float(ty.into()), + }) +} + fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { let var_data = def.variant_data(db); let fields = match var_data.fields() { @@ -477,8 +491,19 @@ pub enum TypableDef { TypeAlias(TypeAlias), Const(Const), Static(Static), + BuiltinType(BuiltinType), } -impl_froms!(TypableDef: Function, Struct, Union, Enum, EnumVariant, TypeAlias, Const, Static); +impl_froms!( + TypableDef: Function, + Struct, + Union, + Enum, + EnumVariant, + TypeAlias, + Const, + Static, + BuiltinType +); impl From for Option { fn from(def: ModuleDef) -> Option { @@ -491,6 +516,7 @@ impl From for Option { ModuleDef::TypeAlias(t) => t.into(), ModuleDef::Const(v) => v.into(), ModuleDef::Static(v) => v.into(), + ModuleDef::BuiltinType(t) => t.into(), ModuleDef::Module(_) | ModuleDef::Trait(_) => return None, }; Some(res) diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs index b37326db7b36..e1ab16a6fb16 100644 --- a/crates/ra_hir/src/ty/primitive.rs +++ b/crates/ra_hir/src/ty/primitive.rs @@ -30,6 +30,12 @@ pub enum UncertainIntTy { Known(IntTy), } +impl From for UncertainIntTy { + fn from(ty: IntTy) -> Self { + UncertainIntTy::Known(ty) + } +} + impl fmt::Display for UncertainIntTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -45,6 +51,12 @@ pub enum UncertainFloatTy { Known(FloatTy), } +impl From for UncertainFloatTy { + fn from(ty: FloatTy) -> Self { + UncertainFloatTy::Known(ty) + } +} + impl fmt::Display for UncertainFloatTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { From 4e5b02966b068a9aecc9d47290e865b0d44ce9ce Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 30 May 2019 14:26:27 +0300 Subject: [PATCH 2/5] add list of builtin types --- crates/ra_hir/src/code_model.rs | 30 ++++++++++++++++++++++++++++-- crates/ra_hir/src/nameres.rs | 2 +- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 3f77850dd313..3053f5488e07 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -4,12 +4,12 @@ use ra_db::{CrateId, SourceRootId, Edition, FileId}; use ra_syntax::{ast::{self, NameOwner, TypeAscriptionOwner}, TreeArc}; use crate::{ - Name, AsName, AstId, Ty, HirFileId, Either, + Name, AsName, AstId, Ty, HirFileId, Either, KnownName, HirDatabase, DefDatabase, type_ref::TypeRef, nameres::{ModuleScope, Namespace, ImportId, CrateModuleId}, expr::{Body, BodySourceMap, validation::ExprValidator}, - ty::{TraitRef, InferenceResult, primitive::{IntTy, FloatTy}}, + ty::{TraitRef, InferenceResult, primitive::{IntTy, FloatTy, Signedness, IntBitness, FloatBitness}}, adt::{EnumVariantId, StructFieldId, VariantDef}, generics::HasGenericParams, docs::{Documentation, Docs, docs_from_ast}, @@ -84,6 +84,32 @@ pub enum BuiltinType { Float(FloatTy), } +impl BuiltinType { + #[rustfmt::skip] + pub(crate) const ALL: &'static [(KnownName, BuiltinType)] = &[ + (KnownName::Char, BuiltinType::Char), + (KnownName::Bool, BuiltinType::Bool), + (KnownName::Str, BuiltinType::Str), + + (KnownName::Isize, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::Xsize })), + (KnownName::I8, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X8 })), + (KnownName::I16, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X16 })), + (KnownName::I32, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X32 })), + (KnownName::I64, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X64 })), + (KnownName::I128, BuiltinType::Int(IntTy { signedness: Signedness::Signed, bitness: IntBitness::X128 })), + + (KnownName::Usize, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::Xsize })), + (KnownName::U8, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X8 })), + (KnownName::U16, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X16 })), + (KnownName::U32, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X32 })), + (KnownName::U64, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X64 })), + (KnownName::U128, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X128 })), + + (KnownName::F32, BuiltinType::Float(FloatTy { bitness: FloatBitness::X32 })), + (KnownName::F64, BuiltinType::Float(FloatTy { bitness: FloatBitness::X32 })), + ]; +} + /// The defs which can be visible in the module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ModuleDef { diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 42dcac332050..51a7b8b955b9 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -64,7 +64,7 @@ use ra_syntax::ast; use ra_prof::profile; use crate::{ - ModuleDef, Name, Crate, Module, MacroDef, + ModuleDef, Name, Crate, Module, MacroDef, KnownName, BuiltinType, DefDatabase, Path, PathKind, HirFileId, Trait, ids::MacroDefId, diagnostics::DiagnosticSink, From 97158f5c8a6dadf3bcf28601f739ab6b7c4464aa Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 30 May 2019 15:03:58 +0300 Subject: [PATCH 3/5] add built-in types to scopes --- Cargo.lock | 1 + crates/ra_hir/Cargo.toml | 1 + crates/ra_hir/src/code_model.rs | 2 +- crates/ra_hir/src/name.rs | 30 ++++++++++++++++++- crates/ra_hir/src/nameres.rs | 19 +++++++++--- .../ra_hir/src/nameres/tests/incremental.rs | 4 +-- crates/ra_hir/src/ty/lower.rs | 16 ---------- 7 files changed, 49 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b56586ac145b..e38fa0ff0bbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1084,6 +1084,7 @@ dependencies = [ "insta 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "join_to_string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_arena 0.1.0", "ra_db 0.1.0", diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index a86dfa6b2600..78808e72f0d7 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml @@ -13,6 +13,7 @@ parking_lot = "0.8.0" ena = "0.11" join_to_string = "0.1.3" either = "1.5.2" +once_cell = "0.2" ra_syntax = { path = "../ra_syntax" } ra_arena = { path = "../ra_arena" } diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 3053f5488e07..e3c76567468b 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -106,7 +106,7 @@ impl BuiltinType { (KnownName::U128, BuiltinType::Int(IntTy { signedness: Signedness::Unsigned, bitness: IntBitness::X128 })), (KnownName::F32, BuiltinType::Float(FloatTy { bitness: FloatBitness::X32 })), - (KnownName::F64, BuiltinType::Float(FloatTy { bitness: FloatBitness::X32 })), + (KnownName::F64, BuiltinType::Float(FloatTy { bitness: FloatBitness::X64 })), ]; } diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs index e3a82cf03f1f..e9003e00b3bd 100644 --- a/crates/ra_hir/src/name.rs +++ b/crates/ra_hir/src/name.rs @@ -123,7 +123,7 @@ impl AsName for ra_db::Dependency { // const ISIZE: Name = Name::new("isize") // ``` // but const-fn is not that powerful yet. -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum KnownName { Isize, I8, @@ -151,3 +151,31 @@ pub(crate) enum KnownName { MacroRules, } + +impl AsName for KnownName { + fn as_name(&self) -> Name { + let s = match self { + KnownName::Isize => "isize", + KnownName::I8 => "i8", + KnownName::I16 => "i16", + KnownName::I32 => "i32", + KnownName::I64 => "i64", + KnownName::I128 => "i128", + KnownName::Usize => "usize", + KnownName::U8 => "u8", + KnownName::U16 => "u16", + KnownName::U32 => "u32", + KnownName::U64 => "u64", + KnownName::U128 => "u128", + KnownName::F32 => "f32", + KnownName::F64 => "f64", + KnownName::Bool => "bool", + KnownName::Char => "char", + KnownName::Str => "str", + KnownName::SelfType => "Self", + KnownName::SelfParam => "self", + KnownName::MacroRules => "macro_rules", + }; + Name::new(s.into()) + } +} diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 51a7b8b955b9..aa26345b224d 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs @@ -62,9 +62,10 @@ use ra_db::{FileId, Edition}; use test_utils::tested_by; use ra_syntax::ast; use ra_prof::profile; +use once_cell::sync::Lazy; use crate::{ - ModuleDef, Name, Crate, Module, MacroDef, KnownName, BuiltinType, + ModuleDef, Name, Crate, Module, MacroDef, AsName, BuiltinType, DefDatabase, Path, PathKind, HirFileId, Trait, ids::MacroDefId, diagnostics::DiagnosticSink, @@ -140,12 +141,22 @@ pub struct ModuleScope { macros: FxHashMap, } +static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { + BuiltinType::ALL + .iter() + .map(|&(known_name, ty)| { + (known_name.as_name(), Resolution { def: PerNs::types(ty.into()), import: None }) + }) + .collect() +}); + impl ModuleScope { pub fn entries<'a>(&'a self) -> impl Iterator + 'a { - self.items.iter() + //FIXME: shadowing + self.items.iter().chain(BUILTIN_SCOPE.iter()) } pub fn get(&self, name: &Name) -> Option<&Resolution> { - self.items.get(name) + self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)) } pub fn traits<'a>(&'a self) -> impl Iterator + 'a { self.items.values().filter_map(|r| match r.def.take_types() { @@ -154,7 +165,7 @@ impl ModuleScope { }) } fn get_item_or_macro(&self, name: &Name) -> Option { - match (self.items.get(name), self.macros.get(name)) { + match (self.get(name), self.macros.get(name)) { (Some(item), _) if !item.def.is_none() => Some(Either::Left(item.def)), (_, Some(macro_)) => Some(Either::Right(*macro_)), _ => None, diff --git a/crates/ra_hir/src/nameres/tests/incremental.rs b/crates/ra_hir/src/nameres/tests/incremental.rs index 001f76ac3065..bc721f6e0aed 100644 --- a/crates/ra_hir/src/nameres/tests/incremental.rs +++ b/crates/ra_hir/src/nameres/tests/incremental.rs @@ -116,7 +116,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { let events = db.log_executed(|| { let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); let decls = module.declarations(&db); - assert_eq!(decls.len(), 1); + assert_eq!(decls.len(), 18); }); assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) } @@ -126,7 +126,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { let events = db.log_executed(|| { let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); let decls = module.declarations(&db); - assert_eq!(decls.len(), 1); + assert_eq!(decls.len(), 18); }); assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) } diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index c4cef2d7ce65..d2ba01826e8f 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -65,22 +65,6 @@ impl Ty { } pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Self { - if let Some(name) = path.as_ident() { - // TODO: remove this - if let Some(int_ty) = primitive::IntTy::from_type_name(name) { - return Ty::simple(TypeCtor::Int(primitive::UncertainIntTy::Known(int_ty))); - } else if let Some(float_ty) = primitive::FloatTy::from_type_name(name) { - return Ty::simple(TypeCtor::Float(primitive::UncertainFloatTy::Known(float_ty))); - } else if let Some(known) = name.as_known_name() { - match known { - KnownName::Bool => return Ty::simple(TypeCtor::Bool), - KnownName::Char => return Ty::simple(TypeCtor::Char), - KnownName::Str => return Ty::simple(TypeCtor::Str), - _ => {} - } - } - } - // Resolve the path (in type namespace) let resolution = resolver.resolve_path(db, path).take_types(); From c6ee9d681c7c745e95f19badef271fec34ec2e36 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 30 May 2019 15:14:11 +0300 Subject: [PATCH 4/5] add tests for primitive types --- crates/ra_hir/src/nameres/tests.rs | 1 + crates/ra_hir/src/nameres/tests/primitives.rs | 24 ++++++++++++++++ crates/ra_hir/src/ty/lower.rs | 3 +- crates/ra_hir/src/ty/primitive.rs | 28 ------------------- crates/ra_hir/src/ty/tests.rs | 18 ++++++++++++ 5 files changed, 44 insertions(+), 30 deletions(-) create mode 100644 crates/ra_hir/src/nameres/tests/primitives.rs diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index ffb627c02c5c..a15e62bbe620 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs @@ -1,6 +1,7 @@ mod macros; mod globs; mod incremental; +mod primitives; use std::sync::Arc; diff --git a/crates/ra_hir/src/nameres/tests/primitives.rs b/crates/ra_hir/src/nameres/tests/primitives.rs new file mode 100644 index 000000000000..734744835a39 --- /dev/null +++ b/crates/ra_hir/src/nameres/tests/primitives.rs @@ -0,0 +1,24 @@ +use super::*; + +#[test] +fn primitive_reexport() { + let map = def_map( + " + //- /lib.rs + mod foo; + use foo::int; + + //- /foo.rs + pub use i32 as int; + ", + ); + assert_snapshot_matches!(map, @r###" + ⋮crate + ⋮foo: t + ⋮int: t + ⋮ + ⋮crate::foo + ⋮int: t + "### + ); +} diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index d2ba01826e8f..71cd722345d2 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -12,7 +12,6 @@ use crate::{ Function, Struct, Union, StructField, Enum, EnumVariant, Path, ModuleDef, TypeAlias, Const, Static, HirDatabase, BuiltinType, type_ref::TypeRef, - name::KnownName, nameres::Namespace, resolve::{Resolver, Resolution}, path::{PathSegment, GenericArg}, @@ -22,7 +21,7 @@ use crate::{ generics::{WherePredicate, GenericDef}, ty::AdtDef, }; -use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef, GenericPredicate}; +use super::{Ty, FnSig, Substs, TypeCtor, TraitRef, GenericPredicate}; impl Ty { pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { diff --git a/crates/ra_hir/src/ty/primitive.rs b/crates/ra_hir/src/ty/primitive.rs index e1ab16a6fb16..62b75b764d73 100644 --- a/crates/ra_hir/src/ty/primitive.rs +++ b/crates/ra_hir/src/ty/primitive.rs @@ -1,7 +1,5 @@ use std::fmt; -use crate::{Name, KnownName}; - #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum Signedness { Signed, @@ -150,24 +148,6 @@ impl IntTy { } } - pub(crate) fn from_type_name(name: &Name) -> Option { - match name.as_known_name()? { - KnownName::Isize => Some(IntTy::isize()), - KnownName::I8 => Some(IntTy::i8()), - KnownName::I16 => Some(IntTy::i16()), - KnownName::I32 => Some(IntTy::i32()), - KnownName::I64 => Some(IntTy::i64()), - KnownName::I128 => Some(IntTy::i128()), - KnownName::Usize => Some(IntTy::usize()), - KnownName::U8 => Some(IntTy::u8()), - KnownName::U16 => Some(IntTy::u16()), - KnownName::U32 => Some(IntTy::u32()), - KnownName::U64 => Some(IntTy::u64()), - KnownName::U128 => Some(IntTy::u128()), - _ => None, - } - } - pub(crate) fn from_suffix(suffix: &str) -> Option { match suffix { "isize" => Some(IntTy::isize()), @@ -220,14 +200,6 @@ impl FloatTy { } } - pub(crate) fn from_type_name(name: &Name) -> Option { - match name.as_known_name()? { - KnownName::F32 => Some(FloatTy::f32()), - KnownName::F64 => Some(FloatTy::f64()), - _ => None, - } - } - pub(crate) fn from_suffix(suffix: &str) -> Option { match suffix { "f32" => Some(FloatTy::f32()), diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index da9aeec6dca3..c34e89af71fc 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -2717,6 +2717,24 @@ fn test() { (S {}).method()<|>; } assert_eq!(t, "{unknown}"); } +#[test] +fn shadowing_primitive() { + let t = type_at( + r#" +//- /main.rs +struct i32; +struct Foo; + +impl i32 { fn foo(&self) -> Foo { Foo } } + +fn main() { + let x: i32 = i32; + x.foo()<|>; +}"#, + ); + assert_eq!(t, "Foo"); +} + fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { let file = db.parse(pos.file_id).ok().unwrap(); let expr = algo::find_node_at_offset::(file.syntax(), pos.offset).unwrap(); From b6a854e161cc122e6d9ae12084b6a1d1f4d0f241 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 30 May 2019 16:10:07 +0300 Subject: [PATCH 5/5] update ra_ide_api to use builtins --- .../src/completion/complete_path.rs | 20 +++++ .../src/completion/completion_item.rs | 2 + .../ra_ide_api/src/completion/presentation.rs | 7 +- .../src/display/navigation_target.rs | 13 ++- crates/ra_ide_api/src/goto_definition.rs | 5 +- crates/ra_ide_api/src/marks.rs | 1 + crates/ra_ide_api/src/syntax_highlighting.rs | 88 ++++++++----------- crates/ra_lsp_server/src/conv.rs | 1 + 8 files changed, 82 insertions(+), 55 deletions(-) diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index c41752ae7fce..99da24142291 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs @@ -17,6 +17,12 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { hir::ModuleDef::Module(module) => { let module_scope = module.scope(ctx.db); for (name, res) in module_scope.entries() { + if let Some(hir::ModuleDef::BuiltinType(..)) = res.def.as_ref().take_types() { + if ctx.use_item_syntax.is_some() { + tested_by!(dont_complete_primitive_in_use); + continue; + } + } if Some(module) == ctx.module { if let Some(import) = res.import { if let Either::A(use_tree) = module.import_source(ctx.db, import) { @@ -88,6 +94,20 @@ mod tests { assert_eq!(completions.len(), 2); } + #[test] + fn dont_complete_primitive_in_use() { + covers!(dont_complete_primitive_in_use); + let completions = do_completion(r"use self::<|>;", CompletionKind::BuiltinType); + assert!(completions.is_empty()); + } + + #[test] + fn completes_primitives() { + let completions = + do_completion(r"fn main() { let _: <|> = 92; }", CompletionKind::BuiltinType); + assert_eq!(completions.len(), 17); + } + #[test] fn completes_mod_with_docs() { check_reference_completion( diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 6f1392231fa5..6f2a60640eb2 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs @@ -78,6 +78,7 @@ pub enum CompletionItemKind { Keyword, Module, Function, + BuiltinType, Struct, Enum, EnumVariant, @@ -102,6 +103,7 @@ pub(crate) enum CompletionKind { Magic, Snippet, Postfix, + BuiltinType, } #[derive(Debug, PartialEq, Eq, Copy, Clone)] diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs index 064d379a4fbd..d405161d63a3 100644 --- a/crates/ra_ide_api/src/completion/presentation.rs +++ b/crates/ra_ide_api/src/completion/presentation.rs @@ -57,6 +57,7 @@ impl Completions { } Some(it) => it, }; + let mut completion_kind = CompletionKind::Reference; let (kind, docs) = match def { Resolution::Def(Module(it)) => (CompletionItemKind::Module, it.docs(ctx.db)), Resolution::Def(Function(func)) => { @@ -70,6 +71,10 @@ impl Completions { Resolution::Def(Static(it)) => (CompletionItemKind::Static, it.docs(ctx.db)), Resolution::Def(Trait(it)) => (CompletionItemKind::Trait, it.docs(ctx.db)), Resolution::Def(TypeAlias(it)) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), + Resolution::Def(BuiltinType(..)) => { + completion_kind = CompletionKind::BuiltinType; + (CompletionItemKind::BuiltinType, None) + } Resolution::GenericParam(..) => (CompletionItemKind::TypeParam, None), Resolution::LocalBinding(..) => (CompletionItemKind::Binding, None), Resolution::SelfType(..) => ( @@ -77,7 +82,7 @@ impl Completions { None, ), }; - CompletionItem::new(CompletionKind::Reference, ctx.source_range(), local_name) + CompletionItem::new(completion_kind, ctx.source_range(), local_name) .kind(kind) .set_documentation(docs) .add_to(self) diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs index ae729614f786..e19c071b08a7 100644 --- a/crates/ra_ide_api/src/display/navigation_target.rs +++ b/crates/ra_ide_api/src/display/navigation_target.rs @@ -165,8 +165,11 @@ impl NavigationTarget { } } - pub(crate) fn from_def(db: &RootDatabase, module_def: hir::ModuleDef) -> NavigationTarget { - match module_def { + pub(crate) fn from_def( + db: &RootDatabase, + module_def: hir::ModuleDef, + ) -> Option { + let nav = match module_def { hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module), hir::ModuleDef::Function(func) => NavigationTarget::from_function(db, func), hir::ModuleDef::Struct(s) => { @@ -201,7 +204,11 @@ impl NavigationTarget { let (file_id, node) = e.source(db); NavigationTarget::from_named(file_id.original_file(db), &*node) } - } + hir::ModuleDef::BuiltinType(..) => { + return None; + } + }; + Some(nav) } pub(crate) fn from_impl_block( diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 4f8554625bbe..97b367115ca9 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs @@ -62,7 +62,10 @@ pub(crate) fn reference_definition( Some(Macro(mac)) => return Exact(NavigationTarget::from_macro_def(db, mac)), Some(FieldAccess(field)) => return Exact(NavigationTarget::from_field(db, field)), Some(AssocItem(assoc)) => return Exact(NavigationTarget::from_impl_item(db, assoc)), - Some(Def(def)) => return Exact(NavigationTarget::from_def(db, def)), + Some(Def(def)) => match NavigationTarget::from_def(db, def) { + Some(nav) => return Exact(nav), + None => return Approximate(vec![]), + }, Some(SelfType(ty)) => { if let Some((def_id, _)) = ty.as_adt() { return Exact(NavigationTarget::from_adt_def(db, def_id)); diff --git a/crates/ra_ide_api/src/marks.rs b/crates/ra_ide_api/src/marks.rs index cc894a7df3a7..9cb991de5ef5 100644 --- a/crates/ra_ide_api/src/marks.rs +++ b/crates/ra_ide_api/src/marks.rs @@ -6,4 +6,5 @@ test_utils::marks!( goto_definition_works_for_named_fields call_info_bad_offset dont_complete_current_use + dont_complete_primitive_in_use ); diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 4b24754a800b..3a04a51cd82e 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs @@ -30,14 +30,6 @@ fn is_control_keyword(kind: SyntaxKind) -> bool { } } -fn is_prim_type(node: &ast::NameRef) -> bool { - match node.text().as_str() { - "u8" | "i8" | "u16" | "i16" | "u32" | "i32" | "u64" | "i64" | "u128" | "i128" | "usize" - | "isize" | "f32" | "f64" | "bool" | "char" | "str" => true, - _ => false, - } -} - pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec { let _p = profile("highlight"); let source_file = db.parse(file_id).tree; @@ -71,51 +63,47 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec { if let Some(name_ref) = node.as_node().and_then(ast::NameRef::cast) { // FIXME: revisit this after #1340 - if is_prim_type(name_ref) { - "type" - } else { - use crate::name_ref_kind::{classify_name_ref, NameRefKind::*}; - use hir::{ModuleDef, ImplItem}; + use crate::name_ref_kind::{classify_name_ref, NameRefKind::*}; + use hir::{ModuleDef, ImplItem}; - // FIXME: try to reuse the SourceAnalyzers - let analyzer = - hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); - match classify_name_ref(db, &analyzer, name_ref) { - Some(Method(_)) => "function", - Some(Macro(_)) => "macro", - Some(FieldAccess(_)) => "field", - Some(AssocItem(ImplItem::Method(_))) => "function", - Some(AssocItem(ImplItem::Const(_))) => "constant", - Some(AssocItem(ImplItem::TypeAlias(_))) => "type", - Some(Def(ModuleDef::Module(_))) => "module", - Some(Def(ModuleDef::Function(_))) => "function", - Some(Def(ModuleDef::Struct(_))) => "type", - Some(Def(ModuleDef::Union(_))) => "type", - Some(Def(ModuleDef::Enum(_))) => "type", - Some(Def(ModuleDef::EnumVariant(_))) => "constant", - Some(Def(ModuleDef::Const(_))) => "constant", - Some(Def(ModuleDef::Static(_))) => "constant", - Some(Def(ModuleDef::Trait(_))) => "type", - Some(Def(ModuleDef::TypeAlias(_))) => "type", - Some(SelfType(_)) => "type", - Some(Pat(ptr)) => { - binding_hash = Some({ - let text = ptr - .syntax_node_ptr() - .to_node(&source_file.syntax()) - .text() - .to_smol_string(); - let shadow_count = - bindings_shadow_count.entry(text.clone()).or_default(); - calc_binding_hash(file_id, &text, *shadow_count) - }); + // FIXME: try to reuse the SourceAnalyzers + let analyzer = hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); + match classify_name_ref(db, &analyzer, name_ref) { + Some(Method(_)) => "function", + Some(Macro(_)) => "macro", + Some(FieldAccess(_)) => "field", + Some(AssocItem(ImplItem::Method(_))) => "function", + Some(AssocItem(ImplItem::Const(_))) => "constant", + Some(AssocItem(ImplItem::TypeAlias(_))) => "type", + Some(Def(ModuleDef::Module(_))) => "module", + Some(Def(ModuleDef::Function(_))) => "function", + Some(Def(ModuleDef::Struct(_))) => "type", + Some(Def(ModuleDef::Union(_))) => "type", + Some(Def(ModuleDef::Enum(_))) => "type", + Some(Def(ModuleDef::EnumVariant(_))) => "constant", + Some(Def(ModuleDef::Const(_))) => "constant", + Some(Def(ModuleDef::Static(_))) => "constant", + Some(Def(ModuleDef::Trait(_))) => "type", + Some(Def(ModuleDef::TypeAlias(_))) => "type", + Some(Def(ModuleDef::BuiltinType(_))) => "type", + Some(SelfType(_)) => "type", + Some(Pat(ptr)) => { + binding_hash = Some({ + let text = ptr + .syntax_node_ptr() + .to_node(&source_file.syntax()) + .text() + .to_smol_string(); + let shadow_count = + bindings_shadow_count.entry(text.clone()).or_default(); + calc_binding_hash(file_id, &text, *shadow_count) + }); - "variable" - } - Some(SelfParam(_)) => "type", - Some(GenericParam(_)) => "type", - None => "text", + "variable" } + Some(SelfParam(_)) => "type", + Some(GenericParam(_)) => "type", + None => "text", } } else { "text" diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index 50a12ddbc2b3..1b349d02a421 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs @@ -65,6 +65,7 @@ impl Conv for CompletionItemKind { CompletionItemKind::Struct => Struct, CompletionItemKind::Enum => Enum, CompletionItemKind::EnumVariant => EnumMember, + CompletionItemKind::BuiltinType => Struct, CompletionItemKind::Binding => Variable, CompletionItemKind::Field => Field, CompletionItemKind::Trait => Interface,