]> git.lizzy.rs Git - rust.git/commitdiff
Merge branch 'refs/heads/master' into feature/granular-scopes
authorOmer Ben-Amram <omerbenamram@gmail.com>
Sat, 14 Dec 2019 15:29:30 +0000 (17:29 +0200)
committerOmer Ben-Amram <omerbenamram@gmail.com>
Sat, 14 Dec 2019 15:29:30 +0000 (17:29 +0200)
29 files changed:
crates/ra_assists/src/assists/add_new.rs
crates/ra_batch/src/lib.rs
crates/ra_hir/src/code_model.rs
crates/ra_hir/src/source_binder.rs
crates/ra_hir_def/src/body/lower.rs
crates/ra_hir_def/src/builtin_type.rs
crates/ra_hir_def/src/data.rs
crates/ra_hir_def/src/generics.rs
crates/ra_hir_def/src/nameres/collector.rs
crates/ra_hir_def/src/path.rs
crates/ra_hir_def/src/resolver.rs
crates/ra_hir_expand/src/builtin_derive.rs
crates/ra_hir_expand/src/builtin_macro.rs
crates/ra_hir_expand/src/name.rs
crates/ra_hir_ty/src/autoderef.rs
crates/ra_hir_ty/src/expr.rs
crates/ra_hir_ty/src/infer.rs
crates/ra_hir_ty/src/infer/expr.rs
crates/ra_hir_ty/src/tests/traits.rs
crates/ra_hir_ty/src/traits/builtin.rs
crates/ra_hir_ty/src/utils.rs
crates/ra_lsp_server/src/config.rs
crates/ra_lsp_server/src/conv.rs
crates/ra_lsp_server/src/main_loop.rs
crates/ra_project_model/src/cargo_workspace.rs
crates/ra_project_model/src/lib.rs
editors/code/package.json
editors/code/src/config.ts
editors/code/src/server.ts

index d340cac8fdf6fe648553515f0d9aa52c58e9e24d..b2f946fac36b144413f2ddc9954f3c9cce08ed8e 100644 (file)
@@ -139,43 +139,40 @@ fn find_struct_impl(
 
     let struct_ty = {
         let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() };
-        hir::Struct::from_source(db, src).unwrap().ty(db)
+        hir::Struct::from_source(db, src)?.ty(db)
     };
 
-    let mut found_new_fn = false;
-
-    let block = module.descendants().filter_map(ast::ImplBlock::cast).find(|impl_blk| {
-        if found_new_fn {
-            return false;
-        }
-
+    let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| {
         let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() };
-        let blk = hir::ImplBlock::from_source(db, src).unwrap();
+        let blk = hir::ImplBlock::from_source(db, src)?;
 
         let same_ty = blk.target_ty(db) == struct_ty;
         let not_trait_impl = blk.target_trait(db).is_none();
 
         if !(same_ty && not_trait_impl) {
-            return false;
+            None
+        } else {
+            Some(impl_blk)
         }
-
-        found_new_fn = has_new_fn(impl_blk);
-        true
     });
 
-    if found_new_fn {
-        None
-    } else {
-        Some(block)
+    if let Some(ref impl_blk) = block {
+        if has_new_fn(impl_blk) {
+            return None;
+        }
     }
+
+    Some(block)
 }
 
 fn has_new_fn(imp: &ast::ImplBlock) -> bool {
     if let Some(il) = imp.item_list() {
         for item in il.impl_items() {
             if let ast::ImplItem::FnDef(f) = item {
-                if f.name().unwrap().text().eq_ignore_ascii_case("new") {
-                    return true;
+                if let Some(name) = f.name() {
+                    if name.text().eq_ignore_ascii_case("new") {
+                        return true;
+                    }
                 }
             }
         }
index 2c9645c00a3c430b623ed0b3f2ebce72f46d84ee..7744ba85a2402ccfbb63fa45b6bbed466e6f7f30 100644 (file)
@@ -22,7 +22,7 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
 
 pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap<SourceRootId, PackageRoot>)> {
     let root = std::env::current_dir()?.join(root);
-    let ws = ProjectWorkspace::discover(root.as_ref())?;
+    let ws = ProjectWorkspace::discover(root.as_ref(), &Default::default())?;
     let project_roots = ws.to_roots();
     let (sender, receiver) = unbounded();
     let sender = Box::new(move |t| sender.send(t).unwrap());
index c705d16302bfe3267a1d66994bfaf097a016f0fb..7850ea9a7124a48bc33d476eccd60eb408a31712 100644 (file)
@@ -17,7 +17,7 @@
 };
 use hir_expand::{
     diagnostics::DiagnosticSink,
-    name::{self, AsName},
+    name::{name, AsName},
     MacroDefId,
 };
 use hir_ty::{
@@ -723,7 +723,7 @@ pub fn name(self, db: &impl HirDatabase) -> Option<Name> {
     }
 
     pub fn is_self(self, db: &impl HirDatabase) -> bool {
-        self.name(db) == Some(name::SELF_PARAM)
+        self.name(db) == Some(name![self])
     }
 
     pub fn is_mut(self, db: &impl HirDatabase) -> bool {
index d3cc5c423e0646efa2af87cde6c3de22c4539abf..f82242c3a05a2190321c16bdb66551b2eb48afa2 100644 (file)
@@ -15,7 +15,7 @@
     },
     expr::{ExprId, PatId},
     nameres::ModuleSource,
-    path::known,
+    path::path,
     resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
     AssocItemId, DefWithBodyId,
 };
@@ -418,7 +418,7 @@ pub fn iterate_path_candidates<T>(
     /// Checks that particular type `ty` implements `std::future::Future`.
     /// This function is used in `.await` syntax completion.
     pub fn impls_future(&self, db: &impl HirDatabase, ty: Type) -> bool {
-        let std_future_path = known::std_future_future();
+        let std_future_path = path![std::future::Future];
 
         let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) {
             Some(it) => it.into(),
index cc068ff94fcb0fe242e4e8e4c956abacb1765ddd..61193b4d8040827e49fc742de0a2f60fb505cb35 100644 (file)
@@ -2,7 +2,7 @@
 //! representation.
 
 use either::Either;
-use hir_expand::name::{self, AsName, Name};
+use hir_expand::name::{name, AsName, Name};
 use ra_arena::Arena;
 use ra_syntax::{
     ast::{
@@ -68,7 +68,7 @@ fn collect(
                 let ptr = AstPtr::new(&self_param);
                 let param_pat = self.alloc_pat(
                     Pat::Bind {
-                        name: name::SELF_PARAM,
+                        name: name![self],
                         mode: BindingAnnotation::Unannotated,
                         subpat: None,
                     },
index 5e815714434ff3fdf381ce94f757846351743154..d14901a9b49f8b809094d0d78f6c4b49d982c2b7 100644 (file)
@@ -5,7 +5,7 @@
 
 use std::fmt;
 
-use hir_expand::name::{self, Name};
+use hir_expand::name::{name, Name};
 
 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
 pub enum Signedness {
@@ -52,26 +52,26 @@ pub enum BuiltinType {
 impl BuiltinType {
     #[rustfmt::skip]
     pub const ALL: &'static [(Name, BuiltinType)] = &[
-        (name::CHAR, BuiltinType::Char),
-        (name::BOOL, BuiltinType::Bool),
-        (name::STR,  BuiltinType::Str ),
-
-        (name::ISIZE, BuiltinType::Int(BuiltinInt::ISIZE)),
-        (name::I8,    BuiltinType::Int(BuiltinInt::I8)),
-        (name::I16,   BuiltinType::Int(BuiltinInt::I16)),
-        (name::I32,   BuiltinType::Int(BuiltinInt::I32)),
-        (name::I64,   BuiltinType::Int(BuiltinInt::I64)),
-        (name::I128,  BuiltinType::Int(BuiltinInt::I128)),
-
-        (name::USIZE, BuiltinType::Int(BuiltinInt::USIZE)),
-        (name::U8,    BuiltinType::Int(BuiltinInt::U8)),
-        (name::U16,   BuiltinType::Int(BuiltinInt::U16)),
-        (name::U32,   BuiltinType::Int(BuiltinInt::U32)),
-        (name::U64,   BuiltinType::Int(BuiltinInt::U64)),
-        (name::U128,  BuiltinType::Int(BuiltinInt::U128)),
-
-        (name::F32, BuiltinType::Float(BuiltinFloat::F32)),
-        (name::F64, BuiltinType::Float(BuiltinFloat::F64)),
+        (name![char], BuiltinType::Char),
+        (name![bool], BuiltinType::Bool),
+        (name![str],  BuiltinType::Str),
+
+        (name![isize], BuiltinType::Int(BuiltinInt::ISIZE)),
+        (name![i8],    BuiltinType::Int(BuiltinInt::I8)),
+        (name![i16],   BuiltinType::Int(BuiltinInt::I16)),
+        (name![i32],   BuiltinType::Int(BuiltinInt::I32)),
+        (name![i64],   BuiltinType::Int(BuiltinInt::I64)),
+        (name![i128],  BuiltinType::Int(BuiltinInt::I128)),
+
+        (name![usize], BuiltinType::Int(BuiltinInt::USIZE)),
+        (name![u8],    BuiltinType::Int(BuiltinInt::U8)),
+        (name![u16],   BuiltinType::Int(BuiltinInt::U16)),
+        (name![u32],   BuiltinType::Int(BuiltinInt::U32)),
+        (name![u64],   BuiltinType::Int(BuiltinInt::U64)),
+        (name![u128],  BuiltinType::Int(BuiltinInt::U128)),
+
+        (name![f32], BuiltinType::Float(BuiltinFloat::F32)),
+        (name![f64], BuiltinType::Float(BuiltinFloat::F64)),
     ];
 }
 
index b2dac183e3bdbd077b06616ad4bc9d81af7dce7a..4f4ef57cc0a4b0681cf1bfcf51e16273a3cb2933 100644 (file)
@@ -3,7 +3,7 @@
 use std::sync::Arc;
 
 use hir_expand::{
-    name::{self, AsName, Name},
+    name::{name, AsName, Name},
     AstId,
 };
 use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
@@ -37,7 +37,7 @@ pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<Func
                 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
                     TypeRef::from_ast(type_ref)
                 } else {
-                    let self_type = TypeRef::Path(name::SELF_TYPE.into());
+                    let self_type = TypeRef::Path(name![Self].into());
                     match self_param.kind() {
                         ast::SelfParamKind::Owned => self_type,
                         ast::SelfParamKind::Ref => {
index e502dd7983b13e1dac0d156806de16446d9d33a5..e9c28c7309e673104249a2e83dcd822f6a017008 100644 (file)
@@ -6,7 +6,7 @@
 
 use either::Either;
 use hir_expand::{
-    name::{self, AsName, Name},
+    name::{name, AsName, Name},
     InFile,
 };
 use ra_arena::{map::ArenaMap, Arena};
@@ -90,11 +90,11 @@ fn new(db: &impl DefDatabase, def: GenericDefId) -> (GenericParams, InFile<Sourc
 
                 // traits get the Self type as an implicit first type parameter
                 let self_param_id =
-                    generics.types.alloc(TypeParamData { name: name::SELF_TYPE, default: None });
+                    generics.types.alloc(TypeParamData { name: name![Self], default: None });
                 sm.insert(self_param_id, Either::Left(src.value.clone()));
                 // add super traits as bounds on Self
                 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
-                let self_param = TypeRef::Path(name::SELF_TYPE.into());
+                let self_param = TypeRef::Path(name![Self].into());
                 generics.fill_bounds(&src.value, self_param);
 
                 generics.fill(&mut sm, &src.value);
index 04aadead19ba8df88f2463b43658cd56a8de0b49..5d7469a6ecf3337fa04e02f1226b85b9ad473510 100644 (file)
@@ -6,7 +6,7 @@
 use hir_expand::{
     builtin_derive::find_builtin_derive,
     builtin_macro::find_builtin_macro,
-    name::{self, AsName, Name},
+    name::{name, AsName, Name},
     HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
 };
 use ra_cfg::CfgOptions;
@@ -918,7 +918,7 @@ fn is_cfg_enabled(&self, attrs: &Attrs) -> bool {
 }
 
 fn is_macro_rules(path: &Path) -> bool {
-    path.as_ident() == Some(&name::MACRO_RULES)
+    path.as_ident() == Some(&name![macro_rules])
 }
 
 #[cfg(test)]
index ec9d13e827047420481ce253d98625c9542a0d11..1e9eb14ea58838db99f66f95df76684b7678e6f0 100644 (file)
@@ -6,7 +6,7 @@
 use either::Either;
 use hir_expand::{
     hygiene::Hygiene,
-    name::{self, AsName, Name},
+    name::{name, AsName, Name},
 };
 use ra_db::CrateId;
 use ra_syntax::{
@@ -76,10 +76,7 @@ pub(crate) fn expand_use_item(
         }
     }
 
-    pub(crate) fn from_simple_segments(
-        kind: PathKind,
-        segments: impl IntoIterator<Item = Name>,
-    ) -> Path {
+    pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> Path {
         Path {
             kind,
             segments: segments
@@ -276,7 +273,7 @@ pub(crate) fn from_fn_like_path_ast(
         }
         if let Some(ret_type) = ret_type {
             let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
-            bindings.push((name::OUTPUT_TYPE, type_ref))
+            bindings.push((name![Output], type_ref))
         }
         if args.is_empty() && bindings.is_empty() {
             None
@@ -296,61 +293,36 @@ fn from(name: Name) -> Path {
     }
 }
 
-pub mod known {
-    use hir_expand::name;
-
-    use super::{Path, PathKind};
-
-    pub fn std_iter_into_iterator() -> Path {
-        Path::from_simple_segments(
-            PathKind::Abs,
-            vec![name::STD, name::ITER, name::INTO_ITERATOR_TYPE],
-        )
-    }
-
-    pub fn std_ops_try() -> Path {
-        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE])
-    }
-
-    pub fn std_ops_range() -> Path {
-        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TYPE])
-    }
-
-    pub fn std_ops_range_from() -> Path {
-        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FROM_TYPE])
-    }
-
-    pub fn std_ops_range_full() -> Path {
-        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FULL_TYPE])
-    }
-
-    pub fn std_ops_range_inclusive() -> Path {
-        Path::from_simple_segments(
-            PathKind::Abs,
-            vec![name::STD, name::OPS, name::RANGE_INCLUSIVE_TYPE],
-        )
-    }
-
-    pub fn std_ops_range_to() -> Path {
-        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TO_TYPE])
-    }
-
-    pub fn std_ops_range_to_inclusive() -> Path {
-        Path::from_simple_segments(
-            PathKind::Abs,
-            vec![name::STD, name::OPS, name::RANGE_TO_INCLUSIVE_TYPE],
-        )
-    }
-
-    pub fn std_result_result() -> Path {
-        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE])
-    }
-
-    pub fn std_future_future() -> Path {
-        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::FUTURE, name::FUTURE_TYPE])
-    }
+pub use hir_expand::name as __name;
+
+#[macro_export]
+macro_rules! __known_path {
+    (std::iter::IntoIterator) => {};
+    (std::result::Result) => {};
+    (std::ops::Range) => {};
+    (std::ops::RangeFrom) => {};
+    (std::ops::RangeFull) => {};
+    (std::ops::RangeTo) => {};
+    (std::ops::RangeToInclusive) => {};
+    (std::ops::RangeInclusive) => {};
+    (std::boxed::Box) => {};
+    (std::future::Future) => {};
+    (std::ops::Try) => {};
+    (std::ops::Neg) => {};
+    (std::ops::Not) => {};
+    ($path:path) => {
+        compile_error!("Please register your known path in the path module")
+    };
+}
 
-    pub fn std_boxed_box() -> Path {
-        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::BOXED, name::BOX_TYPE])
-    }
+#[macro_export]
+macro_rules! __path {
+    ($start:ident $(:: $seg:ident)*) => ({
+        $crate::__known_path!($start $(:: $seg)*);
+        $crate::path::Path::from_simple_segments($crate::path::PathKind::Abs, vec![
+            $crate::path::__name![$start], $($crate::path::__name![$seg],)*
+        ])
+    });
 }
+
+pub use crate::__path as path;
index 17b2169d2a527e49b016d8223de3f422a5f73677..b6d595a2092d907343ed622f63e208c989993472 100644 (file)
@@ -2,7 +2,7 @@
 use std::sync::Arc;
 
 use hir_expand::{
-    name::{self, Name},
+    name::{name, Name},
     MacroDefId,
 };
 use ra_db::CrateId;
@@ -163,13 +163,13 @@ pub fn resolve_path_in_type_ns(
                     }
                 }
                 Scope::ImplBlockScope(impl_) => {
-                    if first_name == &name::SELF_TYPE {
+                    if first_name == &name![Self] {
                         let idx = if path.segments.len() == 1 { None } else { Some(1) };
                         return Some((TypeNs::SelfType(*impl_), idx));
                     }
                 }
                 Scope::AdtScope(adt) => {
-                    if first_name == &name::SELF_TYPE {
+                    if first_name == &name![Self] {
                         let idx = if path.segments.len() == 1 { None } else { Some(1) };
                         return Some((TypeNs::AdtSelfType(*adt), idx));
                     }
@@ -223,7 +223,7 @@ pub fn resolve_path_in_value_ns<'p>(
             return None;
         }
         let n_segments = path.segments.len();
-        let tmp = name::SELF_PARAM;
+        let tmp = name![self];
         let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name };
         let skip_to_mod = path.kind != PathKind::Plain && !path.is_self();
         for scope in self.scopes.iter().rev() {
@@ -259,13 +259,13 @@ pub fn resolve_path_in_value_ns<'p>(
                 Scope::GenericParams { .. } => continue,
 
                 Scope::ImplBlockScope(impl_) if n_segments > 1 => {
-                    if first_name == &name::SELF_TYPE {
+                    if first_name == &name![Self] {
                         let ty = TypeNs::SelfType(*impl_);
                         return Some(ResolveValueResult::Partial(ty, 1));
                     }
                 }
                 Scope::AdtScope(adt) if n_segments > 1 => {
-                    if first_name == &name::SELF_TYPE {
+                    if first_name == &name![Self] {
                         let ty = TypeNs::AdtSelfType(*adt);
                         return Some(ResolveValueResult::Partial(ty, 1));
                     }
@@ -439,10 +439,10 @@ fn process_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)
                 }
             }
             Scope::ImplBlockScope(i) => {
-                f(name::SELF_TYPE, ScopeDef::ImplSelfType((*i).into()));
+                f(name![Self], ScopeDef::ImplSelfType((*i).into()));
             }
             Scope::AdtScope(i) => {
-                f(name::SELF_TYPE, ScopeDef::AdtSelfType((*i).into()));
+                f(name![Self], ScopeDef::AdtSelfType((*i).into()));
             }
             Scope::ExprScope(scope) => {
                 scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| {
index 5746376022bbcd0cfe1aee9880e9b1a8a7863c82..b2644125383ce4c1a149ea012321c6eaf411a2b2 100644 (file)
 use crate::{name, quote, MacroCallId, MacroDefId, MacroDefKind};
 
 macro_rules! register_builtin {
-    ( $(($name:ident, $kind: ident) => $expand:ident),* ) => {
+    ( $($trait:ident => $expand:ident),* ) => {
         #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
         pub enum BuiltinDeriveExpander {
-            $($kind),*
+            $($trait),*
         }
 
         impl BuiltinDeriveExpander {
@@ -26,7 +26,7 @@ pub fn expand(
                 tt: &tt::Subtree,
             ) -> Result<tt::Subtree, mbe::ExpandError> {
                 let expander = match *self {
-                    $( BuiltinDeriveExpander::$kind => $expand, )*
+                    $( BuiltinDeriveExpander::$trait => $expand, )*
                 };
                 expander(db, id, tt)
             }
@@ -34,7 +34,7 @@ pub fn expand(
 
         pub fn find_builtin_derive(ident: &name::Name) -> Option<MacroDefId> {
             let kind = match ident {
-                 $( id if id == &name::$name => BuiltinDeriveExpander::$kind, )*
+                $( id if id == &name::name![$trait] => BuiltinDeriveExpander::$trait, )*
                  _ => return None,
             };
 
@@ -44,15 +44,15 @@ pub fn find_builtin_derive(ident: &name::Name) -> Option<MacroDefId> {
 }
 
 register_builtin! {
-    (COPY_TRAIT, Copy) => copy_expand,
-    (CLONE_TRAIT, Clone) => clone_expand,
-    (DEFAULT_TRAIT, Default) => default_expand,
-    (DEBUG_TRAIT, Debug) => debug_expand,
-    (HASH_TRAIT, Hash) => hash_expand,
-    (ORD_TRAIT, Ord) => ord_expand,
-    (PARTIAL_ORD_TRAIT, PartialOrd) => partial_ord_expand,
-    (EQ_TRAIT, Eq) => eq_expand,
-    (PARTIAL_EQ_TRAIT, PartialEq) => partial_eq_expand
+    Copy => copy_expand,
+    Clone => clone_expand,
+    Default => default_expand,
+    Debug => debug_expand,
+    Hash => hash_expand,
+    Ord => ord_expand,
+    PartialOrd => partial_ord_expand,
+    Eq => eq_expand,
+    PartialEq => partial_eq_expand
 }
 
 struct BasicAdtInfo {
index be5f3cbe35eee9b4735c7ec17a865950d6431a7a..d2b3d769e8e73064c61ee2ecfac5b24b6bf6c00f 100644 (file)
@@ -34,7 +34,7 @@ pub fn find_builtin_macro(
             ast_id: AstId<ast::MacroCall>,
         ) -> Option<MacroDefId> {
             let kind = match ident {
-                 $( id if id == &name::$name => BuiltinFnLikeExpander::$kind, )*
+                 $( id if id == &name::name![$name] => BuiltinFnLikeExpander::$kind, )*
                  _ => return None,
             };
 
@@ -44,15 +44,15 @@ pub fn find_builtin_macro(
 }
 
 register_builtin! {
-    (COLUMN_MACRO, Column) => column_expand,
-    (COMPILE_ERROR_MACRO, CompileError) => compile_error_expand,
-    (FILE_MACRO, File) => file_expand,
-    (LINE_MACRO, Line) => line_expand,
-    (STRINGIFY_MACRO, Stringify) => stringify_expand,
-    (FORMAT_ARGS_MACRO, FormatArgs) => format_args_expand,
+    (column, Column) => column_expand,
+    (compile_error, CompileError) => compile_error_expand,
+    (file, File) => file_expand,
+    (line, Line) => line_expand,
+    (stringify, Stringify) => stringify_expand,
+    (format_args, FormatArgs) => format_args_expand,
     // format_args_nl only differs in that it adds a newline in the end,
     // so we use the same stub expansion for now
-    (FORMAT_ARGS_NL_MACRO, FormatArgsNl) => format_args_expand
+    (format_args_nl, FormatArgsNl) => format_args_expand
 }
 
 fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize {
index 4f2f702c01f39626b33d4cc1342eafe764023319..59d8214fde89f23b10a9d263ecfac6117a15511a 100644 (file)
@@ -104,71 +104,99 @@ fn as_name(&self) -> Name {
     }
 }
 
-// Primitives
-pub const ISIZE: Name = Name::new_inline_ascii(b"isize");
-pub const I8: Name = Name::new_inline_ascii(b"i8");
-pub const I16: Name = Name::new_inline_ascii(b"i16");
-pub const I32: Name = Name::new_inline_ascii(b"i32");
-pub const I64: Name = Name::new_inline_ascii(b"i64");
-pub const I128: Name = Name::new_inline_ascii(b"i128");
-pub const USIZE: Name = Name::new_inline_ascii(b"usize");
-pub const U8: Name = Name::new_inline_ascii(b"u8");
-pub const U16: Name = Name::new_inline_ascii(b"u16");
-pub const U32: Name = Name::new_inline_ascii(b"u32");
-pub const U64: Name = Name::new_inline_ascii(b"u64");
-pub const U128: Name = Name::new_inline_ascii(b"u128");
-pub const F32: Name = Name::new_inline_ascii(b"f32");
-pub const F64: Name = Name::new_inline_ascii(b"f64");
-pub const BOOL: Name = Name::new_inline_ascii(b"bool");
-pub const CHAR: Name = Name::new_inline_ascii(b"char");
-pub const STR: Name = Name::new_inline_ascii(b"str");
-
-// Special names
-pub const SELF_PARAM: Name = Name::new_inline_ascii(b"self");
-pub const SELF_TYPE: Name = Name::new_inline_ascii(b"Self");
-pub const MACRO_RULES: Name = Name::new_inline_ascii(b"macro_rules");
-
-// Components of known path (value or mod name)
-pub const STD: Name = Name::new_inline_ascii(b"std");
-pub const ITER: Name = Name::new_inline_ascii(b"iter");
-pub const OPS: Name = Name::new_inline_ascii(b"ops");
-pub const FUTURE: Name = Name::new_inline_ascii(b"future");
-pub const RESULT: Name = Name::new_inline_ascii(b"result");
-pub const BOXED: Name = Name::new_inline_ascii(b"boxed");
-
-// Components of known path (type name)
-pub const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(b"IntoIterator");
-pub const ITEM_TYPE: Name = Name::new_inline_ascii(b"Item");
-pub const TRY_TYPE: Name = Name::new_inline_ascii(b"Try");
-pub const OK_TYPE: Name = Name::new_inline_ascii(b"Ok");
-pub const FUTURE_TYPE: Name = Name::new_inline_ascii(b"Future");
-pub const RESULT_TYPE: Name = Name::new_inline_ascii(b"Result");
-pub const OUTPUT_TYPE: Name = Name::new_inline_ascii(b"Output");
-pub const TARGET_TYPE: Name = Name::new_inline_ascii(b"Target");
-pub const BOX_TYPE: Name = Name::new_inline_ascii(b"Box");
-pub const RANGE_FROM_TYPE: Name = Name::new_inline_ascii(b"RangeFrom");
-pub const RANGE_FULL_TYPE: Name = Name::new_inline_ascii(b"RangeFull");
-pub const RANGE_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeInclusive");
-pub const RANGE_TO_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeToInclusive");
-pub const RANGE_TO_TYPE: Name = Name::new_inline_ascii(b"RangeTo");
-pub const RANGE_TYPE: Name = Name::new_inline_ascii(b"Range");
-
-// Builtin Macros
-pub const FILE_MACRO: Name = Name::new_inline_ascii(b"file");
-pub const COLUMN_MACRO: Name = Name::new_inline_ascii(b"column");
-pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(b"compile_error");
-pub const LINE_MACRO: Name = Name::new_inline_ascii(b"line");
-pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(b"stringify");
-pub const FORMAT_ARGS_MACRO: Name = Name::new_inline_ascii(b"format_args");
-pub const FORMAT_ARGS_NL_MACRO: Name = Name::new_inline_ascii(b"format_args_nl");
-
-// Builtin derives
-pub const COPY_TRAIT: Name = Name::new_inline_ascii(b"Copy");
-pub const CLONE_TRAIT: Name = Name::new_inline_ascii(b"Clone");
-pub const DEFAULT_TRAIT: Name = Name::new_inline_ascii(b"Default");
-pub const DEBUG_TRAIT: Name = Name::new_inline_ascii(b"Debug");
-pub const HASH_TRAIT: Name = Name::new_inline_ascii(b"Hash");
-pub const ORD_TRAIT: Name = Name::new_inline_ascii(b"Ord");
-pub const PARTIAL_ORD_TRAIT: Name = Name::new_inline_ascii(b"PartialOrd");
-pub const EQ_TRAIT: Name = Name::new_inline_ascii(b"Eq");
-pub const PARTIAL_EQ_TRAIT: Name = Name::new_inline_ascii(b"PartialEq");
+pub mod known {
+    macro_rules! known_names {
+        ($($ident:ident),* $(,)?) => {
+            $(
+                #[allow(bad_style)]
+                pub const $ident: super::Name =
+                    super::Name::new_inline_ascii(stringify!($ident).as_bytes());
+            )*
+        };
+    }
+
+    known_names!(
+        // Primitives
+        isize,
+        i8,
+        i16,
+        i32,
+        i64,
+        i128,
+        usize,
+        u8,
+        u16,
+        u32,
+        u64,
+        u128,
+        f32,
+        f64,
+        bool,
+        char,
+        str,
+        // Special names
+        macro_rules,
+        // Components of known path (value or mod name)
+        std,
+        iter,
+        ops,
+        future,
+        result,
+        boxed,
+        // Components of known path (type name)
+        IntoIterator,
+        Item,
+        Try,
+        Ok,
+        Future,
+        Result,
+        Output,
+        Target,
+        Box,
+        RangeFrom,
+        RangeFull,
+        RangeInclusive,
+        RangeToInclusive,
+        RangeTo,
+        Range,
+        Neg,
+        Not,
+        // Builtin macros
+        file,
+        column,
+        compile_error,
+        line,
+        stringify,
+        format_args,
+        format_args_nl,
+        // Builtin derives
+        Copy,
+        Clone,
+        Default,
+        Debug,
+        Hash,
+        Ord,
+        PartialOrd,
+        Eq,
+        PartialEq,
+    );
+
+    // self/Self cannot be used as an identifier
+    pub const SELF_PARAM: super::Name = super::Name::new_inline_ascii(b"self");
+    pub const SELF_TYPE: super::Name = super::Name::new_inline_ascii(b"Self");
+
+    #[macro_export]
+    macro_rules! name {
+        (self) => {
+            $crate::name::known::SELF_PARAM
+        };
+        (Self) => {
+            $crate::name::known::SELF_TYPE
+        };
+        ($ident:ident) => {
+            $crate::name::known::$ident
+        };
+    }
+}
+
+pub use crate::name;
index d557962b4fec50fefe45ea52e29b044c9a8d4bf6..ee48fa53700767cfc0d2e632b0b9448b6ef6b810 100644 (file)
@@ -6,7 +6,7 @@
 use std::iter::successors;
 
 use hir_def::lang_item::LangItemTarget;
-use hir_expand::name;
+use hir_expand::name::name;
 use log::{info, warn};
 use ra_db::CrateId;
 
@@ -52,7 +52,7 @@ fn deref_by_trait(
         LangItemTarget::TraitId(it) => it,
         _ => return None,
     };
-    let target = db.trait_data(deref_trait).associated_type_by_name(&name::TARGET_TYPE)?;
+    let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
 
     let generic_params = generics(db, target.into());
     if generic_params.len() != 1 {
index d2bd64e5ccc2702ac87a9a03ac7c21a3c6929416..f752a9f09ae7cc96d5f2c44c0639364042e7c1d1 100644 (file)
@@ -3,7 +3,7 @@
 use std::sync::Arc;
 
 use hir_def::{
-    path::{known, Path},
+    path::{path, Path},
     resolver::HasResolver,
     AdtId, FunctionId,
 };
@@ -124,7 +124,7 @@ fn validate_results_in_tail_expr(
             None => return,
         };
 
-        let std_result_path = known::std_result_result();
+        let std_result_path = path![std::result::Result];
 
         let resolver = self.func.resolver(db);
         let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) {
index d16f1eb46d6265afa6539491790a86d7c323fc45..f1b7e9442d30dba47e78721c8f879295303a82c1 100644 (file)
     body::Body,
     data::{ConstData, FunctionData},
     expr::{BindingAnnotation, ExprId, PatId},
-    path::{known, Path},
+    path::{path, Path},
     resolver::{HasResolver, Resolver, TypeNs},
     type_ref::{Mutability, TypeRef},
     AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId,
 };
-use hir_expand::{diagnostics::DiagnosticSink, name};
+use hir_expand::{diagnostics::DiagnosticSink, name::name};
 use ra_arena::map::ArenaMap;
 use ra_prof::profile;
 
 use super::{
     primitive::{FloatTy, IntTy},
     traits::{Guidance, Obligation, ProjectionPredicate, Solution},
-    ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
-    Uncertain,
+    ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
+    TypeWalk, Uncertain,
 };
 use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
 
@@ -338,6 +338,24 @@ fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
         self.table.resolve_ty_shallow(ty)
     }
 
+    fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option<TypeAliasId>) -> Ty {
+        match assoc_ty {
+            Some(res_assoc_ty) => {
+                let ty = self.table.new_type_var();
+                let projection = ProjectionPredicate {
+                    ty: ty.clone(),
+                    projection_ty: ProjectionTy {
+                        associated_ty: res_assoc_ty,
+                        parameters: Substs::single(inner_ty),
+                    },
+                };
+                self.obligations.push(Obligation::Projection(projection));
+                self.resolve_ty_as_possible(ty)
+            }
+            None => Ty::Unknown,
+        }
+    }
+
     /// Recurses through the given type, normalizing associated types mentioned
     /// in it by replacing them by type variables and registering obligations to
     /// resolve later. This should be done once for every type we get from some
@@ -404,61 +422,73 @@ fn infer_body(&mut self) {
     }
 
     fn resolve_into_iter_item(&self) -> Option<TypeAliasId> {
-        let path = known::std_iter_into_iterator();
+        let path = path![std::iter::IntoIterator];
         let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
-        self.db.trait_data(trait_).associated_type_by_name(&name::ITEM_TYPE)
+        self.db.trait_data(trait_).associated_type_by_name(&name![Item])
     }
 
     fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
-        let path = known::std_ops_try();
+        let path = path![std::ops::Try];
+        let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
+        self.db.trait_data(trait_).associated_type_by_name(&name![Ok])
+    }
+
+    fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
+        let path = path![std::ops::Neg];
+        let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
+        self.db.trait_data(trait_).associated_type_by_name(&name![Output])
+    }
+
+    fn resolve_ops_not_output(&self) -> Option<TypeAliasId> {
+        let path = path![std::ops::Not];
         let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
-        self.db.trait_data(trait_).associated_type_by_name(&name::OK_TYPE)
+        self.db.trait_data(trait_).associated_type_by_name(&name![Output])
     }
 
     fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
-        let path = known::std_future_future();
+        let path = path![std::future::Future];
         let trait_ = self.resolver.resolve_known_trait(self.db, &path)?;
-        self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE)
+        self.db.trait_data(trait_).associated_type_by_name(&name![Output])
     }
 
     fn resolve_boxed_box(&self) -> Option<AdtId> {
-        let path = known::std_boxed_box();
+        let path = path![std::boxed::Box];
         let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
         Some(struct_.into())
     }
 
     fn resolve_range_full(&self) -> Option<AdtId> {
-        let path = known::std_ops_range_full();
+        let path = path![std::ops::RangeFull];
         let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
         Some(struct_.into())
     }
 
     fn resolve_range(&self) -> Option<AdtId> {
-        let path = known::std_ops_range();
+        let path = path![std::ops::Range];
         let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
         Some(struct_.into())
     }
 
     fn resolve_range_inclusive(&self) -> Option<AdtId> {
-        let path = known::std_ops_range_inclusive();
+        let path = path![std::ops::RangeInclusive];
         let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
         Some(struct_.into())
     }
 
     fn resolve_range_from(&self) -> Option<AdtId> {
-        let path = known::std_ops_range_from();
+        let path = path![std::ops::RangeFrom];
         let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
         Some(struct_.into())
     }
 
     fn resolve_range_to(&self) -> Option<AdtId> {
-        let path = known::std_ops_range_to();
+        let path = path![std::ops::RangeTo];
         let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
         Some(struct_.into())
     }
 
     fn resolve_range_to_inclusive(&self) -> Option<AdtId> {
-        let path = known::std_ops_range_to_inclusive();
+        let path = path![std::ops::RangeToInclusive];
         let struct_ = self.resolver.resolve_known_struct(self.db, &path)?;
         Some(struct_.into())
     }
index 2c296987c8a612c82196bd89e305c8e22fb382e8..2e3cdd53a00f9319a41db09e8c43234264c2cc63 100644 (file)
@@ -10,7 +10,7 @@
     resolver::resolver_for_expr,
     AdtId, ContainerId, Lookup, StructFieldId,
 };
-use hir_expand::name::{self, Name};
+use hir_expand::name::{name, Name};
 use ra_syntax::ast::RangeOp;
 
 use crate::{
@@ -19,8 +19,8 @@
     method_resolution, op,
     traits::InEnvironment,
     utils::{generics, variant_data, Generics},
-    CallableDef, InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs,
-    TraitRef, Ty, TypeCtor, TypeWalk, Uncertain,
+    ApplicationTy, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, Ty,
+    TypeCtor, TypeWalk, Uncertain,
 };
 
 use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch};
@@ -95,21 +95,8 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
             Expr::For { iterable, body, pat } => {
                 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
 
-                let pat_ty = match self.resolve_into_iter_item() {
-                    Some(into_iter_item_alias) => {
-                        let pat_ty = self.table.new_type_var();
-                        let projection = ProjectionPredicate {
-                            ty: pat_ty.clone(),
-                            projection_ty: ProjectionTy {
-                                associated_ty: into_iter_item_alias,
-                                parameters: Substs::single(iterable_ty),
-                            },
-                        };
-                        self.obligations.push(Obligation::Projection(projection));
-                        self.resolve_ty_as_possible(pat_ty)
-                    }
-                    None => Ty::Unknown,
-                };
+                let pat_ty =
+                    self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
 
                 self.infer_pat(*pat, &pat_ty, BindingMode::default());
                 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
@@ -284,40 +271,13 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
             }
             Expr::Await { expr } => {
                 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
-                let ty = match self.resolve_future_future_output() {
-                    Some(future_future_output_alias) => {
-                        let ty = self.table.new_type_var();
-                        let projection = ProjectionPredicate {
-                            ty: ty.clone(),
-                            projection_ty: ProjectionTy {
-                                associated_ty: future_future_output_alias,
-                                parameters: Substs::single(inner_ty),
-                            },
-                        };
-                        self.obligations.push(Obligation::Projection(projection));
-                        self.resolve_ty_as_possible(ty)
-                    }
-                    None => Ty::Unknown,
-                };
+                let ty =
+                    self.resolve_associated_type(inner_ty, self.resolve_future_future_output());
                 ty
             }
             Expr::Try { expr } => {
                 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
-                let ty = match self.resolve_ops_try_ok() {
-                    Some(ops_try_ok_alias) => {
-                        let ty = self.table.new_type_var();
-                        let projection = ProjectionPredicate {
-                            ty: ty.clone(),
-                            projection_ty: ProjectionTy {
-                                associated_ty: ops_try_ok_alias,
-                                parameters: Substs::single(inner_ty),
-                            },
-                        };
-                        self.obligations.push(Obligation::Projection(projection));
-                        self.resolve_ty_as_possible(ty)
-                    }
-                    None => Ty::Unknown,
-                };
+                let ty = self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok());
                 ty
             }
             Expr::Cast { expr, type_ref } => {
@@ -372,31 +332,36 @@ fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
                     },
                     UnaryOp::Neg => {
                         match &inner_ty {
-                            Ty::Apply(a_ty) => match a_ty.ctor {
-                                TypeCtor::Int(Uncertain::Unknown)
-                                | TypeCtor::Int(Uncertain::Known(IntTy {
-                                    signedness: Signedness::Signed,
-                                    ..
-                                }))
-                                | TypeCtor::Float(..) => inner_ty,
-                                _ => Ty::Unknown,
-                            },
-                            Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => {
-                                inner_ty
-                            }
-                            // FIXME: resolve ops::Neg trait
-                            _ => Ty::Unknown,
+                            // Fast path for builtins
+                            Ty::Apply(ApplicationTy {
+                                ctor:
+                                    TypeCtor::Int(Uncertain::Known(IntTy {
+                                        signedness: Signedness::Signed,
+                                        ..
+                                    })),
+                                ..
+                            })
+                            | Ty::Apply(ApplicationTy {
+                                ctor: TypeCtor::Int(Uncertain::Unknown),
+                                ..
+                            })
+                            | Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(_), .. })
+                            | Ty::Infer(InferTy::IntVar(..))
+                            | Ty::Infer(InferTy::FloatVar(..)) => inner_ty,
+                            // Otherwise we resolve via the std::ops::Neg trait
+                            _ => self
+                                .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()),
                         }
                     }
                     UnaryOp::Not => {
                         match &inner_ty {
-                            Ty::Apply(a_ty) => match a_ty.ctor {
-                                TypeCtor::Bool | TypeCtor::Int(_) => inner_ty,
-                                _ => Ty::Unknown,
-                            },
-                            Ty::Infer(InferTy::IntVar(..)) => inner_ty,
-                            // FIXME: resolve ops::Not trait for inner_ty
-                            _ => Ty::Unknown,
+                            // Fast path for builtins
+                            Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. })
+                            | Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(_), .. })
+                            | Ty::Infer(InferTy::IntVar(..)) => inner_ty,
+                            // Otherwise we resolve via the std::ops::Not trait
+                            _ => self
+                                .resolve_associated_type(inner_ty, self.resolve_ops_not_output()),
                         }
                     }
                 }
@@ -666,7 +631,7 @@ fn substs_for_method_call(
         // Parent arguments are unknown, except for the receiver type
         if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) {
             for (_id, param) in parent_generics {
-                if param.name == name::SELF_TYPE {
+                if param.name == name![Self] {
                     substs.push(receiver_ty.clone());
                 } else {
                     substs.push(Ty::Unknown);
index 93c5f9a15a377bff9c987f841b55d65f88245e47..6139adb72e501b5b64d49aa159d501c224f32c8e 100644 (file)
@@ -115,6 +115,70 @@ impl<T> crate::iter::IntoIterator for Vec<T> {
     assert_eq!("&str", type_at_pos(&db, pos));
 }
 
+#[test]
+fn infer_ops_neg() {
+    let (db, pos) = TestDB::with_position(
+        r#"
+//- /main.rs crate:main deps:std
+
+struct Bar;
+struct Foo;
+
+impl std::ops::Neg for Bar {
+    type Output = Foo;
+}
+
+fn test() {
+    let a = Bar;
+    let b = -a;
+    b<|>;
+}
+
+//- /std.rs crate:std
+
+#[prelude_import] use ops::*;
+mod ops {
+    pub trait Neg {
+        type Output;
+    }
+}
+"#,
+    );
+    assert_eq!("Foo", type_at_pos(&db, pos));
+}
+
+#[test]
+fn infer_ops_not() {
+    let (db, pos) = TestDB::with_position(
+        r#"
+//- /main.rs crate:main deps:std
+
+struct Bar;
+struct Foo;
+
+impl std::ops::Not for Bar {
+    type Output = Foo;
+}
+
+fn test() {
+    let a = Bar;
+    let b = !a;
+    b<|>;
+}
+
+//- /std.rs crate:std
+
+#[prelude_import] use ops::*;
+mod ops {
+    pub trait Not {
+        type Output;
+    }
+}
+"#,
+    );
+    assert_eq!("Foo", type_at_pos(&db, pos));
+}
+
 #[test]
 fn infer_from_bound_1() {
     assert_snapshot!(
index 598fd81e318793dcccaeee5778a03c1a7b019258..cd587a3382808650742d5dfb35634d9f585a2e85 100644 (file)
@@ -1,7 +1,7 @@
 //! This module provides the built-in trait implementations, e.g. to make
 //! closures implement `Fn`.
 use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId};
-use hir_expand::name;
+use hir_expand::name::name;
 use ra_db::CrateId;
 
 use super::{AssocTyValue, Impl};
@@ -79,7 +79,7 @@ fn closure_fn_trait_impl_datum(
     // and don't want to return a valid value only to find out later that FnOnce
     // is broken
     let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?;
-    let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?;
+    let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
 
     let num_args: u16 = match &db.body(data.def.into())[data.expr] {
         Expr::Lambda { args, .. } => args.len() as u16,
@@ -137,7 +137,7 @@ fn closure_fn_trait_output_assoc_ty_value(
 
     let output_ty_id = db
         .trait_data(fn_once_trait)
-        .associated_type_by_name(&name::OUTPUT_TYPE)
+        .associated_type_by_name(&name![Output])
         .expect("assoc ty value should not exist");
 
     BuiltinImplAssocTyValueData {
index aeb211a91cca86d55537a28d2212358abdeb7fea..0049d3c6fc01023cf6268483a9af70e56e082afd 100644 (file)
     type_ref::TypeRef,
     ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId,
 };
-use hir_expand::name::{self, Name};
+use hir_expand::name::{name, Name};
 
-// FIXME: this is wrong, b/c it can't express `trait T: PartialEq<()>`.
-// We should return a `TraitREf` here.
 fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
     let resolver = trait_.resolver(db);
     // returning the iterator directly doesn't easily work because of
@@ -24,7 +22,7 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec<TraitId> {
         .where_predicates
         .iter()
         .filter_map(|pred| match &pred.type_ref {
-            TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(),
+            TypeRef::Path(p) if p.as_ident() == Some(&name![Self]) => pred.bound.as_path(),
             _ => None,
         })
         .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) {
index 8045f3d60d1cb6f3a3e7247040c35fe8f9973d0b..67942aa4147cd1f6bd273d87fe369dfdf04e142b 100644 (file)
@@ -9,6 +9,7 @@
 
 use rustc_hash::FxHashMap;
 
+use ra_project_model::CargoFeatures;
 use serde::{Deserialize, Deserializer};
 
 /// Client provided initialization options
@@ -37,6 +38,9 @@ pub struct ServerConfig {
 
     /// Fine grained feature flags to disable specific features.
     pub feature_flags: FxHashMap<String, bool>,
+
+    /// Cargo feature configurations.
+    pub cargo_features: CargoFeatures,
 }
 
 impl Default for ServerConfig {
@@ -49,6 +53,7 @@ fn default() -> ServerConfig {
             max_inlay_hint_length: None,
             with_sysroot: true,
             feature_flags: FxHashMap::default(),
+            cargo_features: Default::default(),
         }
     }
 }
index b13093cfe65d9d664ef5dbc3d4653364ec7077c9..5561f6270b6a6a72f433ac91987c54e92655c662 100644 (file)
@@ -130,6 +130,11 @@ fn conv_with(self, ctx: (&LineIndex, LineEndings)) -> ::lsp_types::CompletionIte
             deprecated: Some(self.deprecated()),
             ..Default::default()
         };
+
+        if self.deprecated() {
+            res.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated])
+        }
+
         res.insert_text_format = Some(match self.insert_text_format() {
             InsertTextFormat::Snippet => lsp_types::InsertTextFormat::Snippet,
             InsertTextFormat::PlainText => lsp_types::InsertTextFormat::PlainText,
index 158cac0be17213636397cb216ac134375d5bd346..965e7c53c146e0ca17dd64fe0d5f7780a403fc48 100644 (file)
@@ -67,6 +67,7 @@ pub fn main_loop(
                 let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot(
                     ws_root.as_path(),
                     config.with_sysroot,
+                    &config.cargo_features,
                 );
                 match workspace {
                     Ok(workspace) => loaded_workspaces.push(workspace),
index 351997dcdbeb7b3db9bcc35d8466ad0deca816b0..4a0437da3200c7d220be09e2794ca213a8dc13c6 100644 (file)
@@ -6,6 +6,7 @@
 use ra_arena::{impl_arena_id, Arena, RawId};
 use ra_db::Edition;
 use rustc_hash::FxHashMap;
+use serde::Deserialize;
 
 use crate::Result;
 
@@ -23,6 +24,20 @@ pub struct CargoWorkspace {
     pub(crate) workspace_root: PathBuf,
 }
 
+#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Default)]
+#[serde(rename_all = "camelCase", default)]
+pub struct CargoFeatures {
+    /// Do not activate the `default` feature.
+    pub no_default_features: bool,
+
+    /// Activate all available features
+    pub all_features: bool,
+
+    /// List of features to activate.
+    /// This will be ignored if `cargo_all_features` is true.
+    pub features: Vec<String>,
+}
+
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub struct Package(RawId);
 impl_arena_id!(Package);
@@ -132,9 +147,21 @@ pub fn is_proc_macro(self, ws: &CargoWorkspace) -> bool {
 }
 
 impl CargoWorkspace {
-    pub fn from_cargo_metadata(cargo_toml: &Path) -> Result<CargoWorkspace> {
+    pub fn from_cargo_metadata(
+        cargo_toml: &Path,
+        cargo_features: &CargoFeatures,
+    ) -> Result<CargoWorkspace> {
         let mut meta = MetadataCommand::new();
-        meta.manifest_path(cargo_toml).features(CargoOpt::AllFeatures);
+        meta.manifest_path(cargo_toml);
+        if cargo_features.all_features {
+            meta.features(CargoOpt::AllFeatures);
+        } else if cargo_features.no_default_features {
+            // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures`
+            // https://github.com/oli-obk/cargo_metadata/issues/79
+            meta.features(CargoOpt::NoDefaultFeatures);
+        } else {
+            meta.features(CargoOpt::SomeFeatures(cargo_features.features.clone()));
+        }
         if let Some(parent) = cargo_toml.parent() {
             meta.current_dir(parent);
         }
index 55ff4d6efc78e6a966a20c9b6cf5d228316a927c..d71b7031a8a70825d77e53a6f9f170248d751e55 100644 (file)
@@ -18,7 +18,7 @@
 use serde_json::from_reader;
 
 pub use crate::{
-    cargo_workspace::{CargoWorkspace, Package, Target, TargetKind},
+    cargo_workspace::{CargoFeatures, CargoWorkspace, Package, Target, TargetKind},
     json_project::JsonProject,
     sysroot::Sysroot,
 };
@@ -60,11 +60,15 @@ pub fn is_member(&self) -> bool {
 }
 
 impl ProjectWorkspace {
-    pub fn discover(path: &Path) -> Result<ProjectWorkspace> {
-        ProjectWorkspace::discover_with_sysroot(path, true)
+    pub fn discover(path: &Path, cargo_features: &CargoFeatures) -> Result<ProjectWorkspace> {
+        ProjectWorkspace::discover_with_sysroot(path, true, cargo_features)
     }
 
-    pub fn discover_with_sysroot(path: &Path, with_sysroot: bool) -> Result<ProjectWorkspace> {
+    pub fn discover_with_sysroot(
+        path: &Path,
+        with_sysroot: bool,
+        cargo_features: &CargoFeatures,
+    ) -> Result<ProjectWorkspace> {
         match find_rust_project_json(path) {
             Some(json_path) => {
                 let file = File::open(json_path)?;
@@ -73,7 +77,7 @@ pub fn discover_with_sysroot(path: &Path, with_sysroot: bool) -> Result<ProjectW
             }
             None => {
                 let cargo_toml = find_cargo_toml(path)?;
-                let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml)?;
+                let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features)?;
                 let sysroot =
                     if with_sysroot { Sysroot::discover(&cargo_toml)? } else { Sysroot::default() };
                 Ok(ProjectWorkspace::Cargo { cargo, sysroot })
index 68b3b6e0563727996e07821f6f61524cb00e20ac..43db61a8bc0f82337d406e4e585086c081a8a085 100644 (file)
                     "type": "number",
                     "default": 20,
                     "description": "Maximum length for inlay hints"
+                },
+                "rust-analyzer.cargoFeatures.noDefaultFeatures": {
+                    "type": "boolean",
+                    "default": false,
+                    "description": "Do not activate the `default` feature"
+                },
+                "rust-analyzer.cargoFeatures.allFeatures": {
+                    "type": "boolean",
+                    "default": true,
+                    "description": "Activate all available features"
+                },
+                "rust-analyzer.cargoFeatures.features": {
+                    "type": "array",
+                    "default": [],
+                    "description": "List of features to activate"
                 }
             }
         },
index 2d3b6a54ea5bcde41bd0e4975ab00d8da6dbe3eb..defdfeb9c4bdca69d8d23467136041318ac9369d 100644 (file)
@@ -15,6 +15,12 @@ export interface CargoWatchOptions {
     ignore: string[];
 }
 
+export interface CargoFeatures {
+    noDefaultFeatures: boolean;
+    allFeatures: boolean;
+    features: string[];
+}
+
 export class Config {
     public highlightingOn = true;
     public rainbowHighlightingOn = false;
@@ -35,8 +41,14 @@ export class Config {
         command: '',
         ignore: [],
     };
+    public cargoFeatures: CargoFeatures = {
+        noDefaultFeatures: false,
+        allFeatures: true,
+        features: [],
+    };
 
     private prevEnhancedTyping: null | boolean = null;
+    private prevCargoFeatures: null | CargoFeatures = null;
 
     constructor() {
         vscode.workspace.onDidChangeConfiguration(_ =>
@@ -47,6 +59,8 @@ export class Config {
 
     public userConfigChanged() {
         const config = vscode.workspace.getConfiguration('rust-analyzer');
+        let requireReloadMessage = null;
+
         if (config.has('highlightingOn')) {
             this.highlightingOn = config.get('highlightingOn') as boolean;
         }
@@ -74,19 +88,8 @@ export class Config {
         }
 
         if (this.prevEnhancedTyping !== this.enableEnhancedTyping) {
-            const reloadAction = 'Reload now';
-            vscode.window
-                .showInformationMessage(
-                    'Changing enhanced typing setting requires a reload',
-                    reloadAction,
-                )
-                .then(selectedAction => {
-                    if (selectedAction === reloadAction) {
-                        vscode.commands.executeCommand(
-                            'workbench.action.reloadWindow',
-                        );
-                    }
-                });
+            requireReloadMessage =
+                'Changing enhanced typing setting requires a reload';
             this.prevEnhancedTyping = this.enableEnhancedTyping;
         }
 
@@ -153,5 +156,53 @@ export class Config {
         if (config.has('withSysroot')) {
             this.withSysroot = config.get('withSysroot') || false;
         }
+
+        if (config.has('cargoFeatures.noDefaultFeatures')) {
+            this.cargoFeatures.noDefaultFeatures = config.get(
+                'cargoFeatures.noDefaultFeatures',
+                false,
+            );
+        }
+        if (config.has('cargoFeatures.allFeatures')) {
+            this.cargoFeatures.allFeatures = config.get(
+                'cargoFeatures.allFeatures',
+                true,
+            );
+        }
+        if (config.has('cargoFeatures.features')) {
+            this.cargoFeatures.features = config.get(
+                'cargoFeatures.features',
+                [],
+            );
+        }
+
+        if (
+            this.prevCargoFeatures !== null &&
+            (this.cargoFeatures.allFeatures !==
+                this.prevCargoFeatures.allFeatures ||
+                this.cargoFeatures.noDefaultFeatures !==
+                    this.prevCargoFeatures.noDefaultFeatures ||
+                this.cargoFeatures.features.length !==
+                    this.prevCargoFeatures.features.length ||
+                this.cargoFeatures.features.some(
+                    (v, i) => v !== this.prevCargoFeatures!.features[i],
+                ))
+        ) {
+            requireReloadMessage = 'Changing cargo features requires a reload';
+        }
+        this.prevCargoFeatures = { ...this.cargoFeatures };
+
+        if (requireReloadMessage !== null) {
+            const reloadAction = 'Reload now';
+            vscode.window
+                .showInformationMessage(requireReloadMessage, reloadAction)
+                .then(selectedAction => {
+                    if (selectedAction === reloadAction) {
+                        vscode.commands.executeCommand(
+                            'workbench.action.reloadWindow',
+                        );
+                    }
+                });
+        }
     }
 }
index 2fe45f1ed6841db0805b1de5d2e995b84d1186de..5ace1d0faeb4c2b794e59276cc249748f84c6e43 100644 (file)
@@ -59,6 +59,7 @@ export class Server {
                 useClientWatching: Server.config.useClientWatching,
                 featureFlags: Server.config.featureFlags,
                 withSysroot: Server.config.withSysroot,
+                cargoFeatures: Server.config.cargoFeatures,
             },
             traceOutputChannel,
         };