diff options
Diffstat (limited to 'crates')
25 files changed, 648 insertions, 111 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 00b0dc082..fc1a74641 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -14,7 +14,7 @@ use hir_def::{ | |||
14 | per_ns::PerNs, | 14 | per_ns::PerNs, |
15 | resolver::{HasResolver, Resolver}, | 15 | resolver::{HasResolver, Resolver}, |
16 | src::HasSource as _, | 16 | src::HasSource as _, |
17 | type_ref::{Mutability, TypeRef}, | 17 | type_ref::TypeRef, |
18 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, | 18 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, |
19 | DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, | 19 | DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, |
20 | LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, | 20 | LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, |
@@ -32,8 +32,8 @@ use hir_ty::{ | |||
32 | method_resolution, | 32 | method_resolution, |
33 | traits::{FnTrait, Solution, SolutionVariables}, | 33 | traits::{FnTrait, Solution, SolutionVariables}, |
34 | AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, | 34 | AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, GenericPredicate, |
35 | InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, | 35 | InEnvironment, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Scalar, Substs, |
36 | Ty, TyDefId, TyVariableKind, | 36 | TraitEnvironment, Ty, TyDefId, TyVariableKind, |
37 | }; | 37 | }; |
38 | use rustc_hash::FxHashSet; | 38 | use rustc_hash::FxHashSet; |
39 | use stdx::{format_to, impl_from}; | 39 | use stdx::{format_to, impl_from}; |
@@ -836,7 +836,7 @@ pub enum Access { | |||
836 | impl From<Mutability> for Access { | 836 | impl From<Mutability> for Access { |
837 | fn from(mutability: Mutability) -> Access { | 837 | fn from(mutability: Mutability) -> Access { |
838 | match mutability { | 838 | match mutability { |
839 | Mutability::Shared => Access::Shared, | 839 | Mutability::Not => Access::Shared, |
840 | Mutability::Mut => Access::Exclusive, | 840 | Mutability::Mut => Access::Exclusive, |
841 | } | 841 | } |
842 | } | 842 | } |
@@ -865,7 +865,10 @@ impl SelfParam { | |||
865 | .params | 865 | .params |
866 | .first() | 866 | .first() |
867 | .map(|param| match *param { | 867 | .map(|param| match *param { |
868 | TypeRef::Reference(.., mutability) => mutability.into(), | 868 | TypeRef::Reference(.., mutability) => match mutability { |
869 | hir_def::type_ref::Mutability::Shared => Access::Shared, | ||
870 | hir_def::type_ref::Mutability::Mut => Access::Exclusive, | ||
871 | }, | ||
869 | _ => Access::Owned, | 872 | _ => Access::Owned, |
870 | }) | 873 | }) |
871 | .unwrap_or(Access::Owned) | 874 | .unwrap_or(Access::Owned) |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 5e2a711b8..3e19a7702 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -1,5 +1,7 @@ | |||
1 | //! An algorithm to find a path to refer to a certain item. | 1 | //! An algorithm to find a path to refer to a certain item. |
2 | 2 | ||
3 | use std::iter; | ||
4 | |||
3 | use hir_expand::name::{known, AsName, Name}; | 5 | use hir_expand::name::{known, AsName, Name}; |
4 | use rustc_hash::FxHashSet; | 6 | use rustc_hash::FxHashSet; |
5 | use test_utils::mark; | 7 | use test_utils::mark; |
@@ -95,7 +97,7 @@ fn find_path_inner( | |||
95 | item: ItemInNs, | 97 | item: ItemInNs, |
96 | from: ModuleId, | 98 | from: ModuleId, |
97 | max_len: usize, | 99 | max_len: usize, |
98 | prefixed: Option<PrefixKind>, | 100 | mut prefixed: Option<PrefixKind>, |
99 | ) -> Option<ModPath> { | 101 | ) -> Option<ModPath> { |
100 | if max_len == 0 { | 102 | if max_len == 0 { |
101 | return None; | 103 | return None; |
@@ -114,8 +116,9 @@ fn find_path_inner( | |||
114 | } | 116 | } |
115 | 117 | ||
116 | // - if the item is the crate root, return `crate` | 118 | // - if the item is the crate root, return `crate` |
117 | let root = def_map.module_id(def_map.root()); | 119 | let root = def_map.crate_root(db); |
118 | if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() { | 120 | if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() { |
121 | // FIXME: the `block_id()` check should be unnecessary, but affects the result | ||
119 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); | 122 | return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); |
120 | } | 123 | } |
121 | 124 | ||
@@ -165,7 +168,7 @@ fn find_path_inner( | |||
165 | 168 | ||
166 | // - otherwise, look for modules containing (reexporting) it and import it from one of those | 169 | // - otherwise, look for modules containing (reexporting) it and import it from one of those |
167 | 170 | ||
168 | let crate_root = def_map.module_id(def_map.root()); | 171 | let crate_root = def_map.crate_root(db); |
169 | let crate_attrs = db.attrs(crate_root.into()); | 172 | let crate_attrs = db.attrs(crate_root.into()); |
170 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); | 173 | let prefer_no_std = crate_attrs.by_key("no_std").exists(); |
171 | let mut best_path = None; | 174 | let mut best_path = None; |
@@ -228,12 +231,16 @@ fn find_path_inner( | |||
228 | } | 231 | } |
229 | } | 232 | } |
230 | 233 | ||
231 | if let Some(mut prefix) = prefixed.map(PrefixKind::prefix) { | 234 | // If the item is declared inside a block expression, don't use a prefix, as we don't handle |
232 | if matches!(prefix, PathKind::Crate | PathKind::Super(0)) && def_map.block_id().is_some() { | 235 | // that correctly (FIXME). |
233 | // Inner items cannot be referred to via `crate::` or `self::` paths. | 236 | if let Some(item_module) = item.as_module_def_id().and_then(|did| did.module(db)) { |
234 | prefix = PathKind::Plain; | 237 | if item_module.def_map(db).block_id().is_some() && prefixed.is_some() { |
238 | mark::hit!(prefixed_in_block_expression); | ||
239 | prefixed = Some(PrefixKind::Plain); | ||
235 | } | 240 | } |
241 | } | ||
236 | 242 | ||
243 | if let Some(prefix) = prefixed.map(PrefixKind::prefix) { | ||
237 | best_path.or_else(|| { | 244 | best_path.or_else(|| { |
238 | scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) | 245 | scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) |
239 | }) | 246 | }) |
@@ -285,12 +292,12 @@ fn find_local_import_locations( | |||
285 | let data = &def_map[from.local_id]; | 292 | let data = &def_map[from.local_id]; |
286 | let mut worklist = | 293 | let mut worklist = |
287 | data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); | 294 | data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); |
288 | let mut parent = data.parent; | 295 | for ancestor in iter::successors(from.containing_module(db), |m| m.containing_module(db)) { |
289 | while let Some(p) = parent { | 296 | worklist.push(ancestor); |
290 | worklist.push(def_map.module_id(p)); | ||
291 | parent = def_map[p].parent; | ||
292 | } | 297 | } |
293 | 298 | ||
299 | let def_map = def_map.crate_root(db).def_map(db); | ||
300 | |||
294 | let mut seen: FxHashSet<_> = FxHashSet::default(); | 301 | let mut seen: FxHashSet<_> = FxHashSet::default(); |
295 | 302 | ||
296 | let mut locations = Vec::new(); | 303 | let mut locations = Vec::new(); |
@@ -301,7 +308,14 @@ fn find_local_import_locations( | |||
301 | 308 | ||
302 | let ext_def_map; | 309 | let ext_def_map; |
303 | let data = if module.krate == from.krate { | 310 | let data = if module.krate == from.krate { |
304 | &def_map[module.local_id] | 311 | if module.block.is_some() { |
312 | // Re-query the block's DefMap | ||
313 | ext_def_map = module.def_map(db); | ||
314 | &ext_def_map[module.local_id] | ||
315 | } else { | ||
316 | // Reuse the root DefMap | ||
317 | &def_map[module.local_id] | ||
318 | } | ||
305 | } else { | 319 | } else { |
306 | // The crate might reexport a module defined in another crate. | 320 | // The crate might reexport a module defined in another crate. |
307 | ext_def_map = module.def_map(db); | 321 | ext_def_map = module.def_map(db); |
@@ -828,6 +842,7 @@ mod tests { | |||
828 | 842 | ||
829 | #[test] | 843 | #[test] |
830 | fn inner_items_from_inner_module() { | 844 | fn inner_items_from_inner_module() { |
845 | mark::check!(prefixed_in_block_expression); | ||
831 | check_found_path( | 846 | check_found_path( |
832 | r#" | 847 | r#" |
833 | fn main() { | 848 | fn main() { |
@@ -869,4 +884,24 @@ mod tests { | |||
869 | "super::Struct", | 884 | "super::Struct", |
870 | ); | 885 | ); |
871 | } | 886 | } |
887 | |||
888 | #[test] | ||
889 | fn outer_items_with_inner_items_present() { | ||
890 | check_found_path( | ||
891 | r#" | ||
892 | mod module { | ||
893 | pub struct CompleteMe; | ||
894 | } | ||
895 | |||
896 | fn main() { | ||
897 | fn inner() {} | ||
898 | $0 | ||
899 | } | ||
900 | "#, | ||
901 | "module::CompleteMe", | ||
902 | "module::CompleteMe", | ||
903 | "crate::module::CompleteMe", | ||
904 | "self::module::CompleteMe", | ||
905 | ) | ||
906 | } | ||
872 | } | 907 | } |
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index ee46c3330..4e5daa2ff 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -12,8 +12,8 @@ use stdx::format_to; | |||
12 | use test_utils::mark; | 12 | use test_utils::mark; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, | 15 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ImplId, |
16 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, ModuleId, TraitId, | 16 | LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId, |
17 | }; | 17 | }; |
18 | 18 | ||
19 | #[derive(Copy, Clone)] | 19 | #[derive(Copy, Clone)] |
@@ -375,19 +375,9 @@ impl ItemInNs { | |||
375 | 375 | ||
376 | /// Returns the crate defining this item (or `None` if `self` is built-in). | 376 | /// Returns the crate defining this item (or `None` if `self` is built-in). |
377 | pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { | 377 | pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> { |
378 | Some(match self { | 378 | match self { |
379 | ItemInNs::Types(did) | ItemInNs::Values(did) => match did { | 379 | ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate), |
380 | ModuleDefId::ModuleId(id) => id.krate, | 380 | ItemInNs::Macros(id) => Some(id.krate), |
381 | ModuleDefId::FunctionId(id) => id.lookup(db).module(db).krate, | 381 | } |
382 | ModuleDefId::AdtId(id) => id.module(db).krate, | ||
383 | ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db).krate, | ||
384 | ModuleDefId::ConstId(id) => id.lookup(db).container.module(db).krate, | ||
385 | ModuleDefId::StaticId(id) => id.lookup(db).container.module(db).krate, | ||
386 | ModuleDefId::TraitId(id) => id.lookup(db).container.module(db).krate, | ||
387 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db).krate, | ||
388 | ModuleDefId::BuiltinType(_) => return None, | ||
389 | }, | ||
390 | ItemInNs::Macros(id) => return Some(id.krate), | ||
391 | }) | ||
392 | } | 382 | } |
393 | } | 383 | } |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 6802bc250..4498d94bb 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -97,6 +97,10 @@ impl ModuleId { | |||
97 | pub fn krate(&self) -> CrateId { | 97 | pub fn krate(&self) -> CrateId { |
98 | self.krate | 98 | self.krate |
99 | } | 99 | } |
100 | |||
101 | pub fn containing_module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> { | ||
102 | self.def_map(db).containing_module(self.local_id) | ||
103 | } | ||
100 | } | 104 | } |
101 | 105 | ||
102 | /// An ID of a module, **local** to a specific crate | 106 | /// An ID of a module, **local** to a specific crate |
@@ -529,6 +533,25 @@ impl HasModule for StaticLoc { | |||
529 | } | 533 | } |
530 | } | 534 | } |
531 | 535 | ||
536 | impl ModuleDefId { | ||
537 | /// Returns the module containing `self` (or `self`, if `self` is itself a module). | ||
538 | /// | ||
539 | /// Returns `None` if `self` refers to a primitive type. | ||
540 | pub fn module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> { | ||
541 | Some(match self { | ||
542 | ModuleDefId::ModuleId(id) => *id, | ||
543 | ModuleDefId::FunctionId(id) => id.lookup(db).module(db), | ||
544 | ModuleDefId::AdtId(id) => id.module(db), | ||
545 | ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db), | ||
546 | ModuleDefId::ConstId(id) => id.lookup(db).container.module(db), | ||
547 | ModuleDefId::StaticId(id) => id.lookup(db).container.module(db), | ||
548 | ModuleDefId::TraitId(id) => id.lookup(db).container.module(db), | ||
549 | ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db), | ||
550 | ModuleDefId::BuiltinType(_) => return None, | ||
551 | }) | ||
552 | } | ||
553 | } | ||
554 | |||
532 | impl AttrDefId { | 555 | impl AttrDefId { |
533 | pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId { | 556 | pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId { |
534 | match self { | 557 | match self { |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 6a3456f2e..003d668ca 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -343,6 +343,18 @@ impl DefMap { | |||
343 | Some(self.block?.parent) | 343 | Some(self.block?.parent) |
344 | } | 344 | } |
345 | 345 | ||
346 | /// Returns the module containing `local_mod`, either the parent `mod`, or the module containing | ||
347 | /// the block, if `self` corresponds to a block expression. | ||
348 | pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> { | ||
349 | match &self[local_mod].parent { | ||
350 | Some(parent) => Some(self.module_id(*parent)), | ||
351 | None => match &self.block { | ||
352 | Some(block) => Some(block.parent), | ||
353 | None => None, | ||
354 | }, | ||
355 | } | ||
356 | } | ||
357 | |||
346 | // FIXME: this can use some more human-readable format (ideally, an IR | 358 | // FIXME: this can use some more human-readable format (ideally, an IR |
347 | // even), as this should be a great debugging aid. | 359 | // even), as this should be a great debugging aid. |
348 | pub fn dump(&self, db: &dyn DefDatabase) -> String { | 360 | pub fn dump(&self, db: &dyn DefDatabase) -> String { |
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index 6ef9d1e7e..d1302d749 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml | |||
@@ -17,9 +17,9 @@ ena = "0.14.0" | |||
17 | log = "0.4.8" | 17 | log = "0.4.8" |
18 | rustc-hash = "1.1.0" | 18 | rustc-hash = "1.1.0" |
19 | scoped-tls = "1" | 19 | scoped-tls = "1" |
20 | chalk-solve = { version = "0.58", default-features = false } | 20 | chalk-solve = { version = "0.59", default-features = false } |
21 | chalk-ir = "0.58" | 21 | chalk-ir = "0.59" |
22 | chalk-recursive = "0.58" | 22 | chalk-recursive = "0.59" |
23 | la-arena = { version = "0.2.0", path = "../../lib/arena" } | 23 | la-arena = { version = "0.2.0", path = "../../lib/arena" } |
24 | 24 | ||
25 | stdx = { path = "../stdx", version = "0.0.0" } | 25 | stdx = { path = "../stdx", version = "0.0.0" } |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index f3a4333cb..d4a8b48e6 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -8,6 +8,7 @@ use crate::{ | |||
8 | TraitRef, Ty, | 8 | TraitRef, Ty, |
9 | }; | 9 | }; |
10 | use arrayvec::ArrayVec; | 10 | use arrayvec::ArrayVec; |
11 | use chalk_ir::Mutability; | ||
11 | use hir_def::{ | 12 | use hir_def::{ |
12 | db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, | 13 | db::DefDatabase, find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, |
13 | AssocContainerId, HasModule, Lookup, ModuleId, TraitId, | 14 | AssocContainerId, HasModule, Lookup, ModuleId, TraitId, |
@@ -291,9 +292,23 @@ impl HirDisplay for Ty { | |||
291 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); | 292 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); |
292 | 293 | ||
293 | if matches!(self, Ty::Raw(..)) { | 294 | if matches!(self, Ty::Raw(..)) { |
294 | write!(f, "*{}", m.as_keyword_for_ptr())?; | 295 | write!( |
296 | f, | ||
297 | "*{}", | ||
298 | match m { | ||
299 | Mutability::Not => "const ", | ||
300 | Mutability::Mut => "mut ", | ||
301 | } | ||
302 | )?; | ||
295 | } else { | 303 | } else { |
296 | write!(f, "&{}", m.as_keyword_for_ref())?; | 304 | write!( |
305 | f, | ||
306 | "&{}", | ||
307 | match m { | ||
308 | Mutability::Not => "", | ||
309 | Mutability::Mut => "mut ", | ||
310 | } | ||
311 | )?; | ||
297 | } | 312 | } |
298 | 313 | ||
299 | let datas; | 314 | let datas; |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 18a4f5e8a..4d771a91e 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -18,6 +18,7 @@ use std::mem; | |||
18 | use std::ops::Index; | 18 | use std::ops::Index; |
19 | use std::sync::Arc; | 19 | use std::sync::Arc; |
20 | 20 | ||
21 | use chalk_ir::Mutability; | ||
21 | use hir_def::{ | 22 | use hir_def::{ |
22 | body::Body, | 23 | body::Body, |
23 | data::{ConstData, FunctionData, StaticData}, | 24 | data::{ConstData, FunctionData, StaticData}, |
@@ -25,7 +26,7 @@ use hir_def::{ | |||
25 | lang_item::LangItemTarget, | 26 | lang_item::LangItemTarget, |
26 | path::{path, Path}, | 27 | path::{path, Path}, |
27 | resolver::{HasResolver, Resolver, TypeNs}, | 28 | resolver::{HasResolver, Resolver, TypeNs}, |
28 | type_ref::{Mutability, TypeRef}, | 29 | type_ref::TypeRef, |
29 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId, | 30 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, Lookup, TraitId, |
30 | TypeAliasId, VariantId, | 31 | TypeAliasId, VariantId, |
31 | }; | 32 | }; |
@@ -87,7 +88,7 @@ impl BindingMode { | |||
87 | fn convert(annotation: BindingAnnotation) -> BindingMode { | 88 | fn convert(annotation: BindingAnnotation) -> BindingMode { |
88 | match annotation { | 89 | match annotation { |
89 | BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move, | 90 | BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move, |
90 | BindingAnnotation::Ref => BindingMode::Ref(Mutability::Shared), | 91 | BindingAnnotation::Ref => BindingMode::Ref(Mutability::Not), |
91 | BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut), | 92 | BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut), |
92 | } | 93 | } |
93 | } | 94 | } |
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index c33d8c61e..cf0a3add4 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -4,8 +4,8 @@ | |||
4 | //! | 4 | //! |
5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html | 5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html |
6 | 6 | ||
7 | use chalk_ir::TyVariableKind; | 7 | use chalk_ir::{Mutability, TyVariableKind}; |
8 | use hir_def::{lang_item::LangItemTarget, type_ref::Mutability}; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | use test_utils::mark; | 9 | use test_utils::mark; |
10 | 10 | ||
11 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty}; | 11 | use crate::{autoderef, traits::Solution, Obligation, Substs, TraitRef, Ty}; |
@@ -73,20 +73,20 @@ impl<'a> InferenceContext<'a> { | |||
73 | match (&mut from_ty, to_ty) { | 73 | match (&mut from_ty, to_ty) { |
74 | // `*mut T` -> `*const T` | 74 | // `*mut T` -> `*const T` |
75 | // `&mut T` -> `&T` | 75 | // `&mut T` -> `&T` |
76 | (Ty::Raw(m1, ..), Ty::Raw(m2 @ Mutability::Shared, ..)) | 76 | (Ty::Raw(m1, ..), Ty::Raw(m2 @ Mutability::Not, ..)) |
77 | | (Ty::Ref(m1, ..), Ty::Ref(m2 @ Mutability::Shared, ..)) => { | 77 | | (Ty::Ref(m1, ..), Ty::Ref(m2 @ Mutability::Not, ..)) => { |
78 | *m1 = *m2; | 78 | *m1 = *m2; |
79 | } | 79 | } |
80 | // `&T` -> `*const T` | 80 | // `&T` -> `*const T` |
81 | // `&mut T` -> `*mut T`/`*const T` | 81 | // `&mut T` -> `*mut T`/`*const T` |
82 | (Ty::Ref(.., substs), &Ty::Raw(m2 @ Mutability::Shared, ..)) | 82 | (Ty::Ref(.., substs), &Ty::Raw(m2 @ Mutability::Not, ..)) |
83 | | (Ty::Ref(Mutability::Mut, substs), &Ty::Raw(m2, ..)) => { | 83 | | (Ty::Ref(Mutability::Mut, substs), &Ty::Raw(m2, ..)) => { |
84 | from_ty = Ty::Raw(m2, substs.clone()); | 84 | from_ty = Ty::Raw(m2, substs.clone()); |
85 | } | 85 | } |
86 | 86 | ||
87 | // Illegal mutability conversion | 87 | // Illegal mutability conversion |
88 | (Ty::Raw(Mutability::Shared, ..), Ty::Raw(Mutability::Mut, ..)) | 88 | (Ty::Raw(Mutability::Not, ..), Ty::Raw(Mutability::Mut, ..)) |
89 | | (Ty::Ref(Mutability::Shared, ..), Ty::Ref(Mutability::Mut, ..)) => return false, | 89 | | (Ty::Ref(Mutability::Not, ..), Ty::Ref(Mutability::Mut, ..)) => return false, |
90 | 90 | ||
91 | // `{function_type}` -> `fn()` | 91 | // `{function_type}` -> `fn()` |
92 | (Ty::FnDef(..), Ty::Function { .. }) => match from_ty.callable_sig(self.db) { | 92 | (Ty::FnDef(..), Ty::Function { .. }) => match from_ty.callable_sig(self.db) { |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 7852b3d23..cf1f1038a 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use std::iter::{repeat, repeat_with}; | 3 | use std::iter::{repeat, repeat_with}; |
4 | use std::{mem, sync::Arc}; | 4 | use std::{mem, sync::Arc}; |
5 | 5 | ||
6 | use chalk_ir::TyVariableKind; | 6 | use chalk_ir::{Mutability, TyVariableKind}; |
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
9 | path::{GenericArg, GenericArgs}, | 9 | path::{GenericArg, GenericArgs}, |
@@ -15,12 +15,14 @@ use syntax::ast::RangeOp; | |||
15 | use test_utils::mark; | 15 | use test_utils::mark; |
16 | 16 | ||
17 | use crate::{ | 17 | use crate::{ |
18 | autoderef, method_resolution, op, | 18 | autoderef, |
19 | lower::lower_to_chalk_mutability, | ||
20 | method_resolution, op, | ||
19 | primitive::{self, UintTy}, | 21 | primitive::{self, UintTy}, |
20 | traits::{FnTrait, InEnvironment}, | 22 | traits::{FnTrait, InEnvironment}, |
21 | utils::{generics, variant_data, Generics}, | 23 | utils::{generics, variant_data, Generics}, |
22 | Binders, CallableDefId, FnPointer, FnSig, Mutability, Obligation, OpaqueTyId, Rawness, Scalar, | 24 | Binders, CallableDefId, FnPointer, FnSig, Obligation, OpaqueTyId, Rawness, Scalar, Substs, |
23 | Substs, TraitRef, Ty, | 25 | TraitRef, Ty, |
24 | }; | 26 | }; |
25 | 27 | ||
26 | use super::{ | 28 | use super::{ |
@@ -462,10 +464,11 @@ impl<'a> InferenceContext<'a> { | |||
462 | cast_ty | 464 | cast_ty |
463 | } | 465 | } |
464 | Expr::Ref { expr, rawness, mutability } => { | 466 | Expr::Ref { expr, rawness, mutability } => { |
467 | let mutability = lower_to_chalk_mutability(*mutability); | ||
465 | let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = | 468 | let expectation = if let Some((exp_inner, exp_rawness, exp_mutability)) = |
466 | &expected.ty.as_reference_or_ptr() | 469 | &expected.ty.as_reference_or_ptr() |
467 | { | 470 | { |
468 | if *exp_mutability == Mutability::Mut && *mutability == Mutability::Shared { | 471 | if *exp_mutability == Mutability::Mut && mutability == Mutability::Not { |
469 | // FIXME: throw type error - expected mut reference but found shared ref, | 472 | // FIXME: throw type error - expected mut reference but found shared ref, |
470 | // which cannot be coerced | 473 | // which cannot be coerced |
471 | } | 474 | } |
@@ -479,8 +482,8 @@ impl<'a> InferenceContext<'a> { | |||
479 | }; | 482 | }; |
480 | let inner_ty = self.infer_expr_inner(*expr, &expectation); | 483 | let inner_ty = self.infer_expr_inner(*expr, &expectation); |
481 | match rawness { | 484 | match rawness { |
482 | Rawness::RawPtr => Ty::Raw(*mutability, Substs::single(inner_ty)), | 485 | Rawness::RawPtr => Ty::Raw(mutability, Substs::single(inner_ty)), |
483 | Rawness::Ref => Ty::Ref(*mutability, Substs::single(inner_ty)), | 486 | Rawness::Ref => Ty::Ref(mutability, Substs::single(inner_ty)), |
484 | } | 487 | } |
485 | } | 488 | } |
486 | Expr::Box { expr } => { | 489 | Expr::Box { expr } => { |
@@ -684,11 +687,11 @@ impl<'a> InferenceContext<'a> { | |||
684 | } | 687 | } |
685 | Expr::Literal(lit) => match lit { | 688 | Expr::Literal(lit) => match lit { |
686 | Literal::Bool(..) => Ty::Scalar(Scalar::Bool), | 689 | Literal::Bool(..) => Ty::Scalar(Scalar::Bool), |
687 | Literal::String(..) => Ty::Ref(Mutability::Shared, Substs::single(Ty::Str)), | 690 | Literal::String(..) => Ty::Ref(Mutability::Not, Substs::single(Ty::Str)), |
688 | Literal::ByteString(..) => { | 691 | Literal::ByteString(..) => { |
689 | let byte_type = Ty::Scalar(Scalar::Uint(UintTy::U8)); | 692 | let byte_type = Ty::Scalar(Scalar::Uint(UintTy::U8)); |
690 | let array_type = Ty::Array(Substs::single(byte_type)); | 693 | let array_type = Ty::Array(Substs::single(byte_type)); |
691 | Ty::Ref(Mutability::Shared, Substs::single(array_type)) | 694 | Ty::Ref(Mutability::Not, Substs::single(array_type)) |
692 | } | 695 | } |
693 | Literal::Char(..) => Ty::Scalar(Scalar::Char), | 696 | Literal::Char(..) => Ty::Scalar(Scalar::Char), |
694 | Literal::Int(_v, ty) => match ty { | 697 | Literal::Int(_v, ty) => match ty { |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index a318e47f3..eb099311c 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -3,17 +3,17 @@ | |||
3 | use std::iter::repeat; | 3 | use std::iter::repeat; |
4 | use std::sync::Arc; | 4 | use std::sync::Arc; |
5 | 5 | ||
6 | use chalk_ir::Mutability; | ||
6 | use hir_def::{ | 7 | use hir_def::{ |
7 | expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, | 8 | expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, |
8 | path::Path, | 9 | path::Path, |
9 | type_ref::Mutability, | ||
10 | FieldId, | 10 | FieldId, |
11 | }; | 11 | }; |
12 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
13 | use test_utils::mark; | 13 | use test_utils::mark; |
14 | 14 | ||
15 | use super::{BindingMode, Expectation, InferenceContext}; | 15 | use super::{BindingMode, Expectation, InferenceContext}; |
16 | use crate::{utils::variant_data, Substs, Ty}; | 16 | use crate::{lower::lower_to_chalk_mutability, utils::variant_data, Substs, Ty}; |
17 | 17 | ||
18 | impl<'a> InferenceContext<'a> { | 18 | impl<'a> InferenceContext<'a> { |
19 | fn infer_tuple_struct_pat( | 19 | fn infer_tuple_struct_pat( |
@@ -103,7 +103,7 @@ impl<'a> InferenceContext<'a> { | |||
103 | expected = inner; | 103 | expected = inner; |
104 | default_bm = match default_bm { | 104 | default_bm = match default_bm { |
105 | BindingMode::Move => BindingMode::Ref(mutability), | 105 | BindingMode::Move => BindingMode::Ref(mutability), |
106 | BindingMode::Ref(Mutability::Shared) => BindingMode::Ref(Mutability::Shared), | 106 | BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not), |
107 | BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability), | 107 | BindingMode::Ref(Mutability::Mut) => BindingMode::Ref(mutability), |
108 | } | 108 | } |
109 | } | 109 | } |
@@ -152,9 +152,10 @@ impl<'a> InferenceContext<'a> { | |||
152 | } | 152 | } |
153 | } | 153 | } |
154 | Pat::Ref { pat, mutability } => { | 154 | Pat::Ref { pat, mutability } => { |
155 | let mutability = lower_to_chalk_mutability(*mutability); | ||
155 | let expectation = match expected.as_reference() { | 156 | let expectation = match expected.as_reference() { |
156 | Some((inner_ty, exp_mut)) => { | 157 | Some((inner_ty, exp_mut)) => { |
157 | if *mutability != exp_mut { | 158 | if mutability != exp_mut { |
158 | // FIXME: emit type error? | 159 | // FIXME: emit type error? |
159 | } | 160 | } |
160 | inner_ty | 161 | inner_ty |
@@ -162,7 +163,7 @@ impl<'a> InferenceContext<'a> { | |||
162 | _ => &Ty::Unknown, | 163 | _ => &Ty::Unknown, |
163 | }; | 164 | }; |
164 | let subty = self.infer_pat(*pat, expectation, default_bm); | 165 | let subty = self.infer_pat(*pat, expectation, default_bm); |
165 | Ty::Ref(*mutability, Substs::single(subty)) | 166 | Ty::Ref(mutability, Substs::single(subty)) |
166 | } | 167 | } |
167 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( | 168 | Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( |
168 | p.as_ref(), | 169 | p.as_ref(), |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 9bcaf6fa7..c2a20c480 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -27,11 +27,9 @@ use std::{iter, mem, ops::Deref, sync::Arc}; | |||
27 | 27 | ||
28 | use base_db::salsa; | 28 | use base_db::salsa; |
29 | use hir_def::{ | 29 | use hir_def::{ |
30 | builtin_type::BuiltinType, | 30 | builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AdtId, AssocContainerId, |
31 | expr::ExprId, | 31 | DefWithBodyId, FunctionId, GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, |
32 | type_ref::{Mutability, Rawness}, | 32 | TypeAliasId, TypeParamId, |
33 | AdtId, AssocContainerId, DefWithBodyId, FunctionId, GenericDefId, HasModule, LifetimeParamId, | ||
34 | Lookup, TraitId, TypeAliasId, TypeParamId, | ||
35 | }; | 33 | }; |
36 | use itertools::Itertools; | 34 | use itertools::Itertools; |
37 | 35 | ||
@@ -49,7 +47,7 @@ pub use lower::{ | |||
49 | }; | 47 | }; |
50 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; | 48 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; |
51 | 49 | ||
52 | pub use chalk_ir::{BoundVar, DebruijnIndex, Scalar, TyVariableKind}; | 50 | pub use chalk_ir::{BoundVar, DebruijnIndex, Mutability, Scalar, TyVariableKind}; |
53 | 51 | ||
54 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 52 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
55 | pub enum Lifetime { | 53 | pub enum Lifetime { |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index ca06c9fe2..1b5843d48 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -8,6 +8,7 @@ | |||
8 | use std::{iter, sync::Arc}; | 8 | use std::{iter, sync::Arc}; |
9 | 9 | ||
10 | use base_db::CrateId; | 10 | use base_db::CrateId; |
11 | use chalk_ir::Mutability; | ||
11 | use hir_def::{ | 12 | use hir_def::{ |
12 | adt::StructKind, | 13 | adt::StructKind, |
13 | builtin_type::BuiltinType, | 14 | builtin_type::BuiltinType, |
@@ -157,7 +158,7 @@ impl Ty { | |||
157 | } | 158 | } |
158 | TypeRef::RawPtr(inner, mutability) => { | 159 | TypeRef::RawPtr(inner, mutability) => { |
159 | let inner_ty = Ty::from_hir(ctx, inner); | 160 | let inner_ty = Ty::from_hir(ctx, inner); |
160 | Ty::Raw(*mutability, Substs::single(inner_ty)) | 161 | Ty::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) |
161 | } | 162 | } |
162 | TypeRef::Array(inner) => { | 163 | TypeRef::Array(inner) => { |
163 | let inner_ty = Ty::from_hir(ctx, inner); | 164 | let inner_ty = Ty::from_hir(ctx, inner); |
@@ -169,7 +170,7 @@ impl Ty { | |||
169 | } | 170 | } |
170 | TypeRef::Reference(inner, _, mutability) => { | 171 | TypeRef::Reference(inner, _, mutability) => { |
171 | let inner_ty = Ty::from_hir(ctx, inner); | 172 | let inner_ty = Ty::from_hir(ctx, inner); |
172 | Ty::Ref(*mutability, Substs::single(inner_ty)) | 173 | Ty::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) |
173 | } | 174 | } |
174 | TypeRef::Placeholder => Ty::Unknown, | 175 | TypeRef::Placeholder => Ty::Unknown, |
175 | TypeRef::Fn(params, is_varargs) => { | 176 | TypeRef::Fn(params, is_varargs) => { |
@@ -1259,3 +1260,10 @@ pub(crate) fn return_type_impl_traits( | |||
1259 | Some(Arc::new(Binders::new(num_binders, return_type_impl_traits))) | 1260 | Some(Arc::new(Binders::new(num_binders, return_type_impl_traits))) |
1260 | } | 1261 | } |
1261 | } | 1262 | } |
1263 | |||
1264 | pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mutability { | ||
1265 | match m { | ||
1266 | hir_def::type_ref::Mutability::Shared => Mutability::Not, | ||
1267 | hir_def::type_ref::Mutability::Mut => Mutability::Mut, | ||
1268 | } | ||
1269 | } | ||
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index dd5109d4e..f301a8477 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -6,9 +6,10 @@ use std::{iter, sync::Arc}; | |||
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use base_db::CrateId; | 8 | use base_db::CrateId; |
9 | use chalk_ir::Mutability; | ||
9 | use hir_def::{ | 10 | use hir_def::{ |
10 | lang_item::LangItemTarget, type_ref::Mutability, AdtId, AssocContainerId, AssocItemId, | 11 | lang_item::LangItemTarget, AdtId, AssocContainerId, AssocItemId, FunctionId, GenericDefId, |
11 | FunctionId, GenericDefId, HasModule, ImplId, Lookup, ModuleId, TraitId, TypeAliasId, | 12 | HasModule, ImplId, Lookup, ModuleId, TraitId, TypeAliasId, |
12 | }; | 13 | }; |
13 | use hir_expand::name::Name; | 14 | use hir_expand::name::Name; |
14 | use rustc_hash::{FxHashMap, FxHashSet}; | 15 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -251,7 +252,7 @@ impl Ty { | |||
251 | } | 252 | } |
252 | Ty::Str => lang_item_crate!("str_alloc", "str"), | 253 | Ty::Str => lang_item_crate!("str_alloc", "str"), |
253 | Ty::Slice(_) => lang_item_crate!("slice_alloc", "slice"), | 254 | Ty::Slice(_) => lang_item_crate!("slice_alloc", "slice"), |
254 | Ty::Raw(Mutability::Shared, _) => lang_item_crate!("const_ptr"), | 255 | Ty::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"), |
255 | Ty::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"), | 256 | Ty::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"), |
256 | Ty::Dyn(_) => { | 257 | Ty::Dyn(_) => { |
257 | return self.dyn_trait().and_then(|trait_| { | 258 | return self.dyn_trait().and_then(|trait_| { |
@@ -429,7 +430,7 @@ fn iterate_method_candidates_with_autoref( | |||
429 | } | 430 | } |
430 | let refed = Canonical { | 431 | let refed = Canonical { |
431 | kinds: deref_chain[0].kinds.clone(), | 432 | kinds: deref_chain[0].kinds.clone(), |
432 | value: Ty::Ref(Mutability::Shared, Substs::single(deref_chain[0].value.clone())), | 433 | value: Ty::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone())), |
433 | }; | 434 | }; |
434 | if iterate_method_candidates_by_receiver( | 435 | if iterate_method_candidates_by_receiver( |
435 | &refed, | 436 | &refed, |
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 6e6055d80..db1760e6c 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs | |||
@@ -10,7 +10,7 @@ use chalk_ir::{ | |||
10 | use chalk_solve::rust_ir; | 10 | use chalk_solve::rust_ir; |
11 | 11 | ||
12 | use base_db::salsa::InternKey; | 12 | use base_db::salsa::InternKey; |
13 | use hir_def::{type_ref::Mutability, AssocContainerId, GenericDefId, Lookup, TypeAliasId}; | 13 | use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId}; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | db::HirDatabase, | 16 | db::HirDatabase, |
@@ -65,7 +65,7 @@ impl ToChalk for Ty { | |||
65 | } | 65 | } |
66 | Ty::Raw(mutability, substs) => { | 66 | Ty::Raw(mutability, substs) => { |
67 | let ty = substs[0].clone().to_chalk(db); | 67 | let ty = substs[0].clone().to_chalk(db); |
68 | chalk_ir::TyKind::Raw(mutability.to_chalk(db), ty).intern(&Interner) | 68 | chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner) |
69 | } | 69 | } |
70 | Ty::Slice(substs) => { | 70 | Ty::Slice(substs) => { |
71 | chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner) | 71 | chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner) |
@@ -198,11 +198,11 @@ impl ToChalk for Ty { | |||
198 | Ty::Tuple(cardinality, from_chalk(db, subst)) | 198 | Ty::Tuple(cardinality, from_chalk(db, subst)) |
199 | } | 199 | } |
200 | chalk_ir::TyKind::Raw(mutability, ty) => { | 200 | chalk_ir::TyKind::Raw(mutability, ty) => { |
201 | Ty::Raw(from_chalk(db, mutability), Substs::single(from_chalk(db, ty))) | 201 | Ty::Raw(mutability, Substs::single(from_chalk(db, ty))) |
202 | } | 202 | } |
203 | chalk_ir::TyKind::Slice(ty) => Ty::Slice(Substs::single(from_chalk(db, ty))), | 203 | chalk_ir::TyKind::Slice(ty) => Ty::Slice(Substs::single(from_chalk(db, ty))), |
204 | chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => { | 204 | chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => { |
205 | Ty::Ref(from_chalk(db, mutability), Substs::single(from_chalk(db, ty))) | 205 | Ty::Ref(mutability, Substs::single(from_chalk(db, ty))) |
206 | } | 206 | } |
207 | chalk_ir::TyKind::Str => Ty::Str, | 207 | chalk_ir::TyKind::Str => Ty::Str, |
208 | chalk_ir::TyKind::Never => Ty::Never, | 208 | chalk_ir::TyKind::Never => Ty::Never, |
@@ -230,12 +230,12 @@ impl ToChalk for Ty { | |||
230 | /// fake lifetime here, because Chalks built-in logic may expect it to be there. | 230 | /// fake lifetime here, because Chalks built-in logic may expect it to be there. |
231 | fn ref_to_chalk( | 231 | fn ref_to_chalk( |
232 | db: &dyn HirDatabase, | 232 | db: &dyn HirDatabase, |
233 | mutability: Mutability, | 233 | mutability: chalk_ir::Mutability, |
234 | subst: Substs, | 234 | subst: Substs, |
235 | ) -> chalk_ir::Ty<Interner> { | 235 | ) -> chalk_ir::Ty<Interner> { |
236 | let arg = subst[0].clone().to_chalk(db); | 236 | let arg = subst[0].clone().to_chalk(db); |
237 | let lifetime = LifetimeData::Static.intern(&Interner); | 237 | let lifetime = LifetimeData::Static.intern(&Interner); |
238 | chalk_ir::TyKind::Ref(mutability.to_chalk(db), lifetime, arg).intern(&Interner) | 238 | chalk_ir::TyKind::Ref(mutability, lifetime, arg).intern(&Interner) |
239 | } | 239 | } |
240 | 240 | ||
241 | /// We currently don't model constants, but Chalk does. So, we have to insert a | 241 | /// We currently don't model constants, but Chalk does. So, we have to insert a |
@@ -313,22 +313,6 @@ impl ToChalk for OpaqueTyId { | |||
313 | } | 313 | } |
314 | } | 314 | } |
315 | 315 | ||
316 | impl ToChalk for Mutability { | ||
317 | type Chalk = chalk_ir::Mutability; | ||
318 | fn to_chalk(self, _db: &dyn HirDatabase) -> Self::Chalk { | ||
319 | match self { | ||
320 | Mutability::Shared => chalk_ir::Mutability::Not, | ||
321 | Mutability::Mut => chalk_ir::Mutability::Mut, | ||
322 | } | ||
323 | } | ||
324 | fn from_chalk(_db: &dyn HirDatabase, chalk: Self::Chalk) -> Self { | ||
325 | match chalk { | ||
326 | chalk_ir::Mutability::Mut => Mutability::Mut, | ||
327 | chalk_ir::Mutability::Not => Mutability::Shared, | ||
328 | } | ||
329 | } | ||
330 | } | ||
331 | |||
332 | impl ToChalk for hir_def::ImplId { | 316 | impl ToChalk for hir_def::ImplId { |
333 | type Chalk = ImplId; | 317 | type Chalk = ImplId; |
334 | 318 | ||
diff --git a/crates/ide_assists/src/handlers/convert_comment_block.rs b/crates/ide_assists/src/handlers/convert_comment_block.rs new file mode 100644 index 000000000..cdc45fc42 --- /dev/null +++ b/crates/ide_assists/src/handlers/convert_comment_block.rs | |||
@@ -0,0 +1,419 @@ | |||
1 | use itertools::Itertools; | ||
2 | use std::convert::identity; | ||
3 | use syntax::{ | ||
4 | ast::{ | ||
5 | self, | ||
6 | edit::IndentLevel, | ||
7 | Comment, CommentKind, | ||
8 | CommentPlacement::{Inner, Outer}, | ||
9 | CommentShape::{self, Block, Line}, | ||
10 | Whitespace, | ||
11 | }, | ||
12 | AstToken, Direction, SyntaxElement, TextRange, | ||
13 | }; | ||
14 | |||
15 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | ||
16 | |||
17 | /// Assist: line_to_block | ||
18 | /// | ||
19 | /// Converts comments between block and single-line form | ||
20 | /// | ||
21 | /// ``` | ||
22 | /// // Multi-line | ||
23 | /// // comment | ||
24 | /// ``` | ||
25 | /// -> | ||
26 | /// ``` | ||
27 | /// /** | ||
28 | /// Multi-line | ||
29 | /// comment | ||
30 | /// */ | ||
31 | /// ``` | ||
32 | pub(crate) fn convert_comment_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
33 | if let Some(comment) = ctx.find_token_at_offset::<ast::Comment>() { | ||
34 | // Only allow comments which are alone on their line | ||
35 | if let Some(prev) = comment.syntax().prev_token() { | ||
36 | if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() { | ||
37 | return None; | ||
38 | } | ||
39 | } | ||
40 | |||
41 | return match comment.kind().shape { | ||
42 | ast::CommentShape::Block => block_to_line(acc, comment), | ||
43 | ast::CommentShape::Line => line_to_block(acc, comment), | ||
44 | }; | ||
45 | } | ||
46 | |||
47 | return None; | ||
48 | } | ||
49 | |||
50 | fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> { | ||
51 | let target = comment.syntax().text_range(); | ||
52 | |||
53 | acc.add( | ||
54 | AssistId("block_to_line", AssistKind::RefactorRewrite), | ||
55 | "Replace block comment with line comments", | ||
56 | target, | ||
57 | |edit| { | ||
58 | let indentation = IndentLevel::from_token(comment.syntax()); | ||
59 | let line_prefix = | ||
60 | comment_kind_prefix(CommentKind { shape: CommentShape::Line, ..comment.kind() }); | ||
61 | |||
62 | let text = comment.text(); | ||
63 | let text = &text[comment.prefix().len()..(text.len() - "*/".len())].trim(); | ||
64 | |||
65 | let lines = text.lines().peekable(); | ||
66 | |||
67 | let indent_spaces = indentation.to_string(); | ||
68 | let output = lines | ||
69 | .map(|l| l.trim_start_matches(&indent_spaces)) | ||
70 | .map(|l| { | ||
71 | // Don't introduce trailing whitespace | ||
72 | if l.is_empty() { | ||
73 | line_prefix.to_string() | ||
74 | } else { | ||
75 | format!("{} {}", line_prefix, l.trim_start_matches(&indent_spaces)) | ||
76 | } | ||
77 | }) | ||
78 | .join(&format!("\n{}", indent_spaces)); | ||
79 | |||
80 | edit.replace(target, output) | ||
81 | }, | ||
82 | ) | ||
83 | } | ||
84 | |||
85 | fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> { | ||
86 | // Find all the comments we'll be collapsing into a block | ||
87 | let comments = relevant_line_comments(&comment); | ||
88 | |||
89 | // Establish the target of our edit based on the comments we found | ||
90 | let target = TextRange::new( | ||
91 | comments[0].syntax().text_range().start(), | ||
92 | comments.last().unwrap().syntax().text_range().end(), | ||
93 | ); | ||
94 | |||
95 | acc.add( | ||
96 | AssistId("line_to_block", AssistKind::RefactorRewrite), | ||
97 | "Replace line comments with a single block comment", | ||
98 | target, | ||
99 | |edit| { | ||
100 | // We pick a single indentation level for the whole block comment based on the | ||
101 | // comment where the assist was invoked. This will be prepended to the | ||
102 | // contents of each line comment when they're put into the block comment. | ||
103 | let indentation = IndentLevel::from_token(&comment.syntax()); | ||
104 | |||
105 | let block_comment_body = | ||
106 | comments.into_iter().map(|c| line_comment_text(indentation, c)).join("\n"); | ||
107 | |||
108 | let block_prefix = | ||
109 | comment_kind_prefix(CommentKind { shape: CommentShape::Block, ..comment.kind() }); | ||
110 | |||
111 | let output = | ||
112 | format!("{}\n{}\n{}*/", block_prefix, block_comment_body, indentation.to_string()); | ||
113 | |||
114 | edit.replace(target, output) | ||
115 | }, | ||
116 | ) | ||
117 | } | ||
118 | |||
119 | /// The line -> block assist can be invoked from anywhere within a sequence of line comments. | ||
120 | /// relevant_line_comments crawls backwards and forwards finding the complete sequence of comments that will | ||
121 | /// be joined. | ||
122 | fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> { | ||
123 | // The prefix identifies the kind of comment we're dealing with | ||
124 | let prefix = comment.prefix(); | ||
125 | let same_prefix = |c: &ast::Comment| c.prefix() == prefix; | ||
126 | |||
127 | // These tokens are allowed to exist between comments | ||
128 | let skippable = |not: &SyntaxElement| { | ||
129 | not.clone() | ||
130 | .into_token() | ||
131 | .and_then(Whitespace::cast) | ||
132 | .map(|w| !w.spans_multiple_lines()) | ||
133 | .unwrap_or(false) | ||
134 | }; | ||
135 | |||
136 | // Find all preceding comments (in reverse order) that have the same prefix | ||
137 | let prev_comments = comment | ||
138 | .syntax() | ||
139 | .siblings_with_tokens(Direction::Prev) | ||
140 | .filter(|s| !skippable(s)) | ||
141 | .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix)) | ||
142 | .take_while(|opt_com| opt_com.is_some()) | ||
143 | .filter_map(identity) | ||
144 | .skip(1); // skip the first element so we don't duplicate it in next_comments | ||
145 | |||
146 | let next_comments = comment | ||
147 | .syntax() | ||
148 | .siblings_with_tokens(Direction::Next) | ||
149 | .filter(|s| !skippable(s)) | ||
150 | .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix)) | ||
151 | .take_while(|opt_com| opt_com.is_some()) | ||
152 | .filter_map(identity); | ||
153 | |||
154 | let mut comments: Vec<_> = prev_comments.collect(); | ||
155 | comments.reverse(); | ||
156 | comments.extend(next_comments); | ||
157 | comments | ||
158 | } | ||
159 | |||
160 | // Line comments usually begin with a single space character following the prefix as seen here: | ||
161 | //^ | ||
162 | // But comments can also include indented text: | ||
163 | // > Hello there | ||
164 | // | ||
165 | // We handle this by stripping *AT MOST* one space character from the start of the line | ||
166 | // This has its own problems because it can cause alignment issues: | ||
167 | // | ||
168 | // /* | ||
169 | // a ----> a | ||
170 | //b ----> b | ||
171 | // */ | ||
172 | // | ||
173 | // But since such comments aren't idiomatic we're okay with this. | ||
174 | fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> String { | ||
175 | let contents_without_prefix = comm.text().strip_prefix(comm.prefix()).unwrap(); | ||
176 | let contents = contents_without_prefix.strip_prefix(' ').unwrap_or(contents_without_prefix); | ||
177 | |||
178 | // Don't add the indentation if the line is empty | ||
179 | if contents.is_empty() { | ||
180 | contents.to_owned() | ||
181 | } else { | ||
182 | indentation.to_string() + &contents | ||
183 | } | ||
184 | } | ||
185 | |||
186 | fn comment_kind_prefix(ck: ast::CommentKind) -> &'static str { | ||
187 | match (ck.shape, ck.doc) { | ||
188 | (Line, Some(Inner)) => "//!", | ||
189 | (Line, Some(Outer)) => "///", | ||
190 | (Line, None) => "//", | ||
191 | (Block, Some(Inner)) => "/*!", | ||
192 | (Block, Some(Outer)) => "/**", | ||
193 | (Block, None) => "/*", | ||
194 | } | ||
195 | } | ||
196 | |||
197 | #[cfg(test)] | ||
198 | mod tests { | ||
199 | use crate::tests::{check_assist, check_assist_not_applicable}; | ||
200 | |||
201 | use super::*; | ||
202 | |||
203 | #[test] | ||
204 | fn single_line_to_block() { | ||
205 | check_assist( | ||
206 | convert_comment_block, | ||
207 | r#" | ||
208 | // line$0 comment | ||
209 | fn main() { | ||
210 | foo(); | ||
211 | } | ||
212 | "#, | ||
213 | r#" | ||
214 | /* | ||
215 | line comment | ||
216 | */ | ||
217 | fn main() { | ||
218 | foo(); | ||
219 | } | ||
220 | "#, | ||
221 | ); | ||
222 | } | ||
223 | |||
224 | #[test] | ||
225 | fn single_line_to_block_indented() { | ||
226 | check_assist( | ||
227 | convert_comment_block, | ||
228 | r#" | ||
229 | fn main() { | ||
230 | // line$0 comment | ||
231 | foo(); | ||
232 | } | ||
233 | "#, | ||
234 | r#" | ||
235 | fn main() { | ||
236 | /* | ||
237 | line comment | ||
238 | */ | ||
239 | foo(); | ||
240 | } | ||
241 | "#, | ||
242 | ); | ||
243 | } | ||
244 | |||
245 | #[test] | ||
246 | fn multiline_to_block() { | ||
247 | check_assist( | ||
248 | convert_comment_block, | ||
249 | r#" | ||
250 | fn main() { | ||
251 | // above | ||
252 | // line$0 comment | ||
253 | // | ||
254 | // below | ||
255 | foo(); | ||
256 | } | ||
257 | "#, | ||
258 | r#" | ||
259 | fn main() { | ||
260 | /* | ||
261 | above | ||
262 | line comment | ||
263 | |||
264 | below | ||
265 | */ | ||
266 | foo(); | ||
267 | } | ||
268 | "#, | ||
269 | ); | ||
270 | } | ||
271 | |||
272 | #[test] | ||
273 | fn end_of_line_to_block() { | ||
274 | check_assist_not_applicable( | ||
275 | convert_comment_block, | ||
276 | r#" | ||
277 | fn main() { | ||
278 | foo(); // end-of-line$0 comment | ||
279 | } | ||
280 | "#, | ||
281 | ); | ||
282 | } | ||
283 | |||
284 | #[test] | ||
285 | fn single_line_different_kinds() { | ||
286 | check_assist( | ||
287 | convert_comment_block, | ||
288 | r#" | ||
289 | fn main() { | ||
290 | /// different prefix | ||
291 | // line$0 comment | ||
292 | // below | ||
293 | foo(); | ||
294 | } | ||
295 | "#, | ||
296 | r#" | ||
297 | fn main() { | ||
298 | /// different prefix | ||
299 | /* | ||
300 | line comment | ||
301 | below | ||
302 | */ | ||
303 | foo(); | ||
304 | } | ||
305 | "#, | ||
306 | ); | ||
307 | } | ||
308 | |||
309 | #[test] | ||
310 | fn single_line_separate_chunks() { | ||
311 | check_assist( | ||
312 | convert_comment_block, | ||
313 | r#" | ||
314 | fn main() { | ||
315 | // different chunk | ||
316 | |||
317 | // line$0 comment | ||
318 | // below | ||
319 | foo(); | ||
320 | } | ||
321 | "#, | ||
322 | r#" | ||
323 | fn main() { | ||
324 | // different chunk | ||
325 | |||
326 | /* | ||
327 | line comment | ||
328 | below | ||
329 | */ | ||
330 | foo(); | ||
331 | } | ||
332 | "#, | ||
333 | ); | ||
334 | } | ||
335 | |||
336 | #[test] | ||
337 | fn doc_block_comment_to_lines() { | ||
338 | check_assist( | ||
339 | convert_comment_block, | ||
340 | r#" | ||
341 | /** | ||
342 | hi$0 there | ||
343 | */ | ||
344 | "#, | ||
345 | r#" | ||
346 | /// hi there | ||
347 | "#, | ||
348 | ); | ||
349 | } | ||
350 | |||
351 | #[test] | ||
352 | fn block_comment_to_lines() { | ||
353 | check_assist( | ||
354 | convert_comment_block, | ||
355 | r#" | ||
356 | /* | ||
357 | hi$0 there | ||
358 | */ | ||
359 | "#, | ||
360 | r#" | ||
361 | // hi there | ||
362 | "#, | ||
363 | ); | ||
364 | } | ||
365 | |||
366 | #[test] | ||
367 | fn inner_doc_block_to_lines() { | ||
368 | check_assist( | ||
369 | convert_comment_block, | ||
370 | r#" | ||
371 | /*! | ||
372 | hi$0 there | ||
373 | */ | ||
374 | "#, | ||
375 | r#" | ||
376 | //! hi there | ||
377 | "#, | ||
378 | ); | ||
379 | } | ||
380 | |||
381 | #[test] | ||
382 | fn block_to_lines_indent() { | ||
383 | check_assist( | ||
384 | convert_comment_block, | ||
385 | r#" | ||
386 | fn main() { | ||
387 | /*! | ||
388 | hi$0 there | ||
389 | |||
390 | ``` | ||
391 | code_sample | ||
392 | ``` | ||
393 | */ | ||
394 | } | ||
395 | "#, | ||
396 | r#" | ||
397 | fn main() { | ||
398 | //! hi there | ||
399 | //! | ||
400 | //! ``` | ||
401 | //! code_sample | ||
402 | //! ``` | ||
403 | } | ||
404 | "#, | ||
405 | ); | ||
406 | } | ||
407 | |||
408 | #[test] | ||
409 | fn end_of_line_block_to_line() { | ||
410 | check_assist_not_applicable( | ||
411 | convert_comment_block, | ||
412 | r#" | ||
413 | fn main() { | ||
414 | foo(); /* end-of-line$0 comment */ | ||
415 | } | ||
416 | "#, | ||
417 | ); | ||
418 | } | ||
419 | } | ||
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs index 53542d433..9c8148462 100644 --- a/crates/ide_assists/src/lib.rs +++ b/crates/ide_assists/src/lib.rs | |||
@@ -115,6 +115,7 @@ mod handlers { | |||
115 | mod auto_import; | 115 | mod auto_import; |
116 | mod change_visibility; | 116 | mod change_visibility; |
117 | mod convert_integer_literal; | 117 | mod convert_integer_literal; |
118 | mod convert_comment_block; | ||
118 | mod early_return; | 119 | mod early_return; |
119 | mod expand_glob_import; | 120 | mod expand_glob_import; |
120 | mod extract_function; | 121 | mod extract_function; |
@@ -178,6 +179,7 @@ mod handlers { | |||
178 | auto_import::auto_import, | 179 | auto_import::auto_import, |
179 | change_visibility::change_visibility, | 180 | change_visibility::change_visibility, |
180 | convert_integer_literal::convert_integer_literal, | 181 | convert_integer_literal::convert_integer_literal, |
182 | convert_comment_block::convert_comment_block, | ||
181 | early_return::convert_to_guarded_return, | 183 | early_return::convert_to_guarded_return, |
182 | expand_glob_import::expand_glob_import, | 184 | expand_glob_import::expand_glob_import, |
183 | extract_struct_from_enum_variant::extract_struct_from_enum_variant, | 185 | extract_struct_from_enum_variant::extract_struct_from_enum_variant, |
diff --git a/crates/proc_macro_srv/src/rustc_server.rs b/crates/proc_macro_srv/src/rustc_server.rs index a8504f762..952b4a97f 100644 --- a/crates/proc_macro_srv/src/rustc_server.rs +++ b/crates/proc_macro_srv/src/rustc_server.rs | |||
@@ -14,7 +14,6 @@ use std::collections::HashMap; | |||
14 | use std::hash::Hash; | 14 | use std::hash::Hash; |
15 | use std::iter::FromIterator; | 15 | use std::iter::FromIterator; |
16 | use std::ops::Bound; | 16 | use std::ops::Bound; |
17 | use std::str::FromStr; | ||
18 | use std::{ascii, vec::IntoIter}; | 17 | use std::{ascii, vec::IntoIter}; |
19 | 18 | ||
20 | type Group = tt::Subtree; | 19 | type Group = tt::Subtree; |
@@ -278,6 +277,42 @@ impl server::FreeFunctions for Rustc { | |||
278 | } | 277 | } |
279 | } | 278 | } |
280 | 279 | ||
280 | fn subtree_replace_token_ids_with_unspecified(subtree: tt::Subtree) -> tt::Subtree { | ||
281 | tt::Subtree { | ||
282 | delimiter: subtree.delimiter.map(|d| tt::Delimiter { id: tt::TokenId::unspecified(), ..d }), | ||
283 | token_trees: subtree | ||
284 | .token_trees | ||
285 | .into_iter() | ||
286 | .map(|t| token_tree_replace_token_ids_with_unspecified(t)) | ||
287 | .collect(), | ||
288 | } | ||
289 | } | ||
290 | |||
291 | fn token_tree_replace_token_ids_with_unspecified(tt: tt::TokenTree) -> tt::TokenTree { | ||
292 | match tt { | ||
293 | tt::TokenTree::Leaf(leaf) => { | ||
294 | tt::TokenTree::Leaf(leaf_replace_token_ids_with_unspecified(leaf)) | ||
295 | } | ||
296 | tt::TokenTree::Subtree(subtree) => { | ||
297 | tt::TokenTree::Subtree(subtree_replace_token_ids_with_unspecified(subtree)) | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | |||
302 | fn leaf_replace_token_ids_with_unspecified(leaf: tt::Leaf) -> tt::Leaf { | ||
303 | match leaf { | ||
304 | tt::Leaf::Literal(lit) => { | ||
305 | tt::Leaf::Literal(tt::Literal { id: tt::TokenId::unspecified(), ..lit }) | ||
306 | } | ||
307 | tt::Leaf::Punct(punct) => { | ||
308 | tt::Leaf::Punct(tt::Punct { id: tt::TokenId::unspecified(), ..punct }) | ||
309 | } | ||
310 | tt::Leaf::Ident(ident) => { | ||
311 | tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), ..ident }) | ||
312 | } | ||
313 | } | ||
314 | } | ||
315 | |||
281 | impl server::TokenStream for Rustc { | 316 | impl server::TokenStream for Rustc { |
282 | fn new(&mut self) -> Self::TokenStream { | 317 | fn new(&mut self) -> Self::TokenStream { |
283 | Self::TokenStream::new() | 318 | Self::TokenStream::new() |
@@ -287,7 +322,8 @@ impl server::TokenStream for Rustc { | |||
287 | stream.is_empty() | 322 | stream.is_empty() |
288 | } | 323 | } |
289 | fn from_str(&mut self, src: &str) -> Self::TokenStream { | 324 | fn from_str(&mut self, src: &str) -> Self::TokenStream { |
290 | Self::TokenStream::from_str(src).expect("cannot parse string") | 325 | let (subtree, _) = mbe::parse_to_token_tree(src).expect("cannot parse string"); |
326 | TokenStream::with_subtree(subtree_replace_token_ids_with_unspecified(subtree)) | ||
291 | } | 327 | } |
292 | fn to_string(&mut self, stream: &Self::TokenStream) -> String { | 328 | fn to_string(&mut self, stream: &Self::TokenStream) -> String { |
293 | stream.to_string() | 329 | stream.to_string() |
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs index 8991f3bdb..ebbbf0596 100644 --- a/crates/rust-analyzer/src/cli/analysis_bench.rs +++ b/crates/rust-analyzer/src/cli/analysis_bench.rs | |||
@@ -68,7 +68,7 @@ impl BenchCmd { | |||
68 | load_out_dirs_from_check: self.load_output_dirs, | 68 | load_out_dirs_from_check: self.load_output_dirs, |
69 | with_proc_macro: self.with_proc_macro, | 69 | with_proc_macro: self.with_proc_macro, |
70 | }; | 70 | }; |
71 | let (mut host, vfs) = | 71 | let (mut host, vfs, _proc_macro) = |
72 | load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; | 72 | load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; |
73 | eprintln!("{:?}\n", start.elapsed()); | 73 | eprintln!("{:?}\n", start.elapsed()); |
74 | 74 | ||
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 9072d8944..ad0759bda 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs | |||
@@ -64,7 +64,7 @@ impl AnalysisStatsCmd { | |||
64 | load_out_dirs_from_check: self.load_output_dirs, | 64 | load_out_dirs_from_check: self.load_output_dirs, |
65 | with_proc_macro: self.with_proc_macro, | 65 | with_proc_macro: self.with_proc_macro, |
66 | }; | 66 | }; |
67 | let (host, vfs) = | 67 | let (host, vfs, _proc_macro) = |
68 | load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; | 68 | load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; |
69 | let db = host.raw_database(); | 69 | let db = host.raw_database(); |
70 | eprintln!("{:<20} {}", "Database loaded:", db_load_sw.elapsed()); | 70 | eprintln!("{:<20} {}", "Database loaded:", db_load_sw.elapsed()); |
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs index 876f6c44f..8b985716b 100644 --- a/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/crates/rust-analyzer/src/cli/diagnostics.rs | |||
@@ -35,7 +35,8 @@ pub fn diagnostics( | |||
35 | ) -> Result<()> { | 35 | ) -> Result<()> { |
36 | let cargo_config = Default::default(); | 36 | let cargo_config = Default::default(); |
37 | let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check, with_proc_macro }; | 37 | let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check, with_proc_macro }; |
38 | let (host, _vfs) = load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; | 38 | let (host, _vfs, _proc_macro) = |
39 | load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; | ||
39 | let db = host.raw_database(); | 40 | let db = host.raw_database(); |
40 | let analysis = host.analysis(); | 41 | let analysis = host.analysis(); |
41 | 42 | ||
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 23442afac..310c36904 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -23,7 +23,7 @@ pub fn load_workspace_at( | |||
23 | cargo_config: &CargoConfig, | 23 | cargo_config: &CargoConfig, |
24 | load_config: &LoadCargoConfig, | 24 | load_config: &LoadCargoConfig, |
25 | progress: &dyn Fn(String), | 25 | progress: &dyn Fn(String), |
26 | ) -> Result<(AnalysisHost, vfs::Vfs)> { | 26 | ) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroClient>)> { |
27 | let root = AbsPathBuf::assert(std::env::current_dir()?.join(root)); | 27 | let root = AbsPathBuf::assert(std::env::current_dir()?.join(root)); |
28 | let root = ProjectManifest::discover_single(&root)?; | 28 | let root = ProjectManifest::discover_single(&root)?; |
29 | let workspace = ProjectWorkspace::load(root, cargo_config, progress)?; | 29 | let workspace = ProjectWorkspace::load(root, cargo_config, progress)?; |
@@ -35,7 +35,7 @@ pub fn load_workspace( | |||
35 | ws: ProjectWorkspace, | 35 | ws: ProjectWorkspace, |
36 | config: &LoadCargoConfig, | 36 | config: &LoadCargoConfig, |
37 | progress: &dyn Fn(String), | 37 | progress: &dyn Fn(String), |
38 | ) -> Result<(AnalysisHost, vfs::Vfs)> { | 38 | ) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroClient>)> { |
39 | let (sender, receiver) = unbounded(); | 39 | let (sender, receiver) = unbounded(); |
40 | let mut vfs = vfs::Vfs::default(); | 40 | let mut vfs = vfs::Vfs::default(); |
41 | let mut loader = { | 41 | let mut loader = { |
@@ -80,7 +80,7 @@ pub fn load_workspace( | |||
80 | log::debug!("crate graph: {:?}", crate_graph); | 80 | log::debug!("crate graph: {:?}", crate_graph); |
81 | let host = | 81 | let host = |
82 | load_crate_graph(crate_graph, project_folders.source_root_config, &mut vfs, &receiver); | 82 | load_crate_graph(crate_graph, project_folders.source_root_config, &mut vfs, &receiver); |
83 | Ok((host, vfs)) | 83 | Ok((host, vfs, proc_macro_client)) |
84 | } | 84 | } |
85 | 85 | ||
86 | fn load_crate_graph( | 86 | fn load_crate_graph( |
@@ -138,7 +138,8 @@ mod tests { | |||
138 | let cargo_config = Default::default(); | 138 | let cargo_config = Default::default(); |
139 | let load_cargo_config = | 139 | let load_cargo_config = |
140 | LoadCargoConfig { load_out_dirs_from_check: false, with_proc_macro: false }; | 140 | LoadCargoConfig { load_out_dirs_from_check: false, with_proc_macro: false }; |
141 | let (host, _vfs) = load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; | 141 | let (host, _vfs, _proc_macro) = |
142 | load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; | ||
142 | 143 | ||
143 | let n_crates = Crate::all(host.raw_database()).len(); | 144 | let n_crates = Crate::all(host.raw_database()).len(); |
144 | // RA has quite a few crates, but the exact count doesn't matter | 145 | // RA has quite a few crates, but the exact count doesn't matter |
diff --git a/crates/rust-analyzer/src/cli/ssr.rs b/crates/rust-analyzer/src/cli/ssr.rs index 71a8f8fb9..79f426fff 100644 --- a/crates/rust-analyzer/src/cli/ssr.rs +++ b/crates/rust-analyzer/src/cli/ssr.rs | |||
@@ -11,7 +11,7 @@ pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> { | |||
11 | let cargo_config = Default::default(); | 11 | let cargo_config = Default::default(); |
12 | let load_cargo_config = | 12 | let load_cargo_config = |
13 | LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro: true }; | 13 | LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro: true }; |
14 | let (host, vfs) = | 14 | let (host, vfs, _proc_macro) = |
15 | load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; | 15 | load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; |
16 | let db = host.raw_database(); | 16 | let db = host.raw_database(); |
17 | let mut match_finder = MatchFinder::at_first_file(db)?; | 17 | let mut match_finder = MatchFinder::at_first_file(db)?; |
@@ -38,7 +38,7 @@ pub fn search_for_patterns(patterns: Vec<SsrPattern>, debug_snippet: Option<Stri | |||
38 | let cargo_config = Default::default(); | 38 | let cargo_config = Default::default(); |
39 | let load_cargo_config = | 39 | let load_cargo_config = |
40 | LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro: true }; | 40 | LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro: true }; |
41 | let (host, _vfs) = | 41 | let (host, _vfs, _proc_macro) = |
42 | load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; | 42 | load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; |
43 | let db = host.raw_database(); | 43 | let db = host.raw_database(); |
44 | let mut match_finder = MatchFinder::at_first_file(db)?; | 44 | let mut match_finder = MatchFinder::at_first_file(db)?; |
diff --git a/crates/syntax/src/ast/edit.rs b/crates/syntax/src/ast/edit.rs index 824ebf41c..0b3b76d4a 100644 --- a/crates/syntax/src/ast/edit.rs +++ b/crates/syntax/src/ast/edit.rs | |||
@@ -595,11 +595,14 @@ impl ops::Add<u8> for IndentLevel { | |||
595 | 595 | ||
596 | impl IndentLevel { | 596 | impl IndentLevel { |
597 | pub fn from_node(node: &SyntaxNode) -> IndentLevel { | 597 | pub fn from_node(node: &SyntaxNode) -> IndentLevel { |
598 | let first_token = match node.first_token() { | 598 | match node.first_token() { |
599 | Some(it) => it, | 599 | Some(it) => Self::from_token(&it), |
600 | None => return IndentLevel(0), | 600 | None => return IndentLevel(0), |
601 | }; | 601 | } |
602 | for ws in prev_tokens(first_token).filter_map(ast::Whitespace::cast) { | 602 | } |
603 | |||
604 | pub fn from_token(token: &SyntaxToken) -> IndentLevel { | ||
605 | for ws in prev_tokens(token.clone()).filter_map(ast::Whitespace::cast) { | ||
603 | let text = ws.syntax().text(); | 606 | let text = ws.syntax().text(); |
604 | if let Some(pos) = text.rfind('\n') { | 607 | if let Some(pos) = text.rfind('\n') { |
605 | let level = text[pos + 1..].chars().count() / 4; | 608 | let level = text[pos + 1..].chars().count() / 4; |
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index 044e3e5e8..977eb8181 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs | |||
@@ -85,8 +85,9 @@ pub enum CommentPlacement { | |||
85 | } | 85 | } |
86 | 86 | ||
87 | impl CommentKind { | 87 | impl CommentKind { |
88 | const BY_PREFIX: [(&'static str, CommentKind); 8] = [ | 88 | const BY_PREFIX: [(&'static str, CommentKind); 9] = [ |
89 | ("/**/", CommentKind { shape: CommentShape::Block, doc: None }), | 89 | ("/**/", CommentKind { shape: CommentShape::Block, doc: None }), |
90 | ("/***", CommentKind { shape: CommentShape::Block, doc: None }), | ||
90 | ("////", CommentKind { shape: CommentShape::Line, doc: None }), | 91 | ("////", CommentKind { shape: CommentShape::Line, doc: None }), |
91 | ("///", CommentKind { shape: CommentShape::Line, doc: Some(CommentPlacement::Outer) }), | 92 | ("///", CommentKind { shape: CommentShape::Line, doc: Some(CommentPlacement::Outer) }), |
92 | ("//!", CommentKind { shape: CommentShape::Line, doc: Some(CommentPlacement::Inner) }), | 93 | ("//!", CommentKind { shape: CommentShape::Line, doc: Some(CommentPlacement::Inner) }), |