diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_assists/src/test_db.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/debug.rs | 94 | ||||
-rw-r--r-- | crates/ra_hir/src/has_source.rs (renamed from crates/ra_hir/src/code_model/src.rs) | 0 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 14 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 206 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/coerce.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/coercion.rs | 37 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_dot.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/db.rs | 14 |
11 files changed, 110 insertions, 277 deletions
diff --git a/crates/ra_assists/src/test_db.rs b/crates/ra_assists/src/test_db.rs index 523259fd4..d5249f308 100644 --- a/crates/ra_assists/src/test_db.rs +++ b/crates/ra_assists/src/test_db.rs | |||
@@ -43,5 +43,3 @@ impl FileLoader for TestDB { | |||
43 | FileLoaderDelegate(self).relevant_crates(file_id) | 43 | FileLoaderDelegate(self).relevant_crates(file_id) |
44 | } | 44 | } |
45 | } | 45 | } |
46 | |||
47 | impl hir::debug::HirDebugHelper for TestDB {} | ||
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 7ac1bf461..c013ff99b 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -1,7 +1,4 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | |||
3 | pub(crate) mod src; | ||
4 | |||
5 | use std::sync::Arc; | 2 | use std::sync::Arc; |
6 | 3 | ||
7 | use either::Either; | 4 | use either::Either; |
@@ -989,11 +986,6 @@ impl Type { | |||
989 | None | 986 | None |
990 | } | 987 | } |
991 | 988 | ||
992 | // FIXME: remove | ||
993 | pub fn into_ty(self) -> Ty { | ||
994 | self.ty.value | ||
995 | } | ||
996 | |||
997 | pub fn as_adt(&self) -> Option<Adt> { | 989 | pub fn as_adt(&self) -> Option<Adt> { |
998 | let (adt, _subst) = self.ty.value.as_adt()?; | 990 | let (adt, _subst) = self.ty.value.as_adt()?; |
999 | Some(adt.into()) | 991 | Some(adt.into()) |
diff --git a/crates/ra_hir/src/debug.rs b/crates/ra_hir/src/debug.rs deleted file mode 100644 index 6cd5c8cb9..000000000 --- a/crates/ra_hir/src/debug.rs +++ /dev/null | |||
@@ -1,94 +0,0 @@ | |||
1 | //! XXX: This does not work at the moment. | ||
2 | //! | ||
3 | //! printf debugging infrastructure for rust-analyzer. | ||
4 | //! | ||
5 | //! When you print a hir type, like a module, using `eprintln!("{:?}", module)`, | ||
6 | //! you usually get back a numeric ID, which doesn't tell you much: | ||
7 | //! `Module(92)`. | ||
8 | //! | ||
9 | //! This module adds convenience `debug` methods to various types, which resolve | ||
10 | //! the id to a human-readable location info: | ||
11 | //! | ||
12 | //! ```not_rust | ||
13 | //! eprintln!("{:?}", module.debug(db)); | ||
14 | //! => | ||
15 | //! Module { name: collections, path: "liballoc/collections/mod.rs" } | ||
16 | //! ``` | ||
17 | //! | ||
18 | //! Note that to get this info, we might need to execute queries! So | ||
19 | //! | ||
20 | //! * don't use the `debug` methods for logging | ||
21 | //! * when debugging, be aware that interference is possible. | ||
22 | |||
23 | use std::fmt; | ||
24 | |||
25 | use hir_expand::HirFileId; | ||
26 | use ra_db::{CrateId, FileId}; | ||
27 | |||
28 | use crate::{db::HirDatabase, Crate, Module, Name}; | ||
29 | |||
30 | impl Crate { | ||
31 | pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ { | ||
32 | debug_fn(move |fmt| db.debug_crate(self, fmt)) | ||
33 | } | ||
34 | } | ||
35 | |||
36 | impl Module { | ||
37 | pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ { | ||
38 | debug_fn(move |fmt| db.debug_module(self, fmt)) | ||
39 | } | ||
40 | } | ||
41 | |||
42 | pub trait HirDebugHelper: HirDatabase { | ||
43 | fn crate_name(&self, _krate: CrateId) -> Option<String> { | ||
44 | None | ||
45 | } | ||
46 | fn file_path(&self, _file_id: FileId) -> Option<String> { | ||
47 | None | ||
48 | } | ||
49 | } | ||
50 | |||
51 | pub trait HirDebugDatabase { | ||
52 | fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result; | ||
53 | fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result; | ||
54 | fn debug_hir_file_id(&self, file_id: HirFileId, fmt: &mut fmt::Formatter<'_>) -> fmt::Result; | ||
55 | } | ||
56 | |||
57 | impl<DB: HirDebugHelper> HirDebugDatabase for DB { | ||
58 | fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
59 | let mut builder = fmt.debug_tuple("Crate"); | ||
60 | match self.crate_name(krate.id) { | ||
61 | Some(name) => builder.field(&name), | ||
62 | None => builder.field(&krate.id), | ||
63 | } | ||
64 | .finish() | ||
65 | } | ||
66 | |||
67 | fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
68 | let file_id = module.definition_source(self).file_id.original_file(self); | ||
69 | let path = self.file_path(file_id).unwrap_or_else(|| "N/A".to_string()); | ||
70 | fmt.debug_struct("Module") | ||
71 | .field("name", &module.name(self).unwrap_or_else(Name::missing)) | ||
72 | .field("path", &path) | ||
73 | .finish() | ||
74 | } | ||
75 | |||
76 | fn debug_hir_file_id(&self, file_id: HirFileId, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
77 | let original = file_id.original_file(self); | ||
78 | let path = self.file_path(original).unwrap_or_else(|| "N/A".to_string()); | ||
79 | let is_macro = file_id != original.into(); | ||
80 | fmt.debug_struct("HirFileId").field("path", &path).field("macro", &is_macro).finish() | ||
81 | } | ||
82 | } | ||
83 | |||
84 | fn debug_fn(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug { | ||
85 | struct DebugFn<F>(F); | ||
86 | |||
87 | impl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for DebugFn<F> { | ||
88 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
89 | (&self.0)(fmt) | ||
90 | } | ||
91 | } | ||
92 | |||
93 | DebugFn(f) | ||
94 | } | ||
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/has_source.rs index b09582f93..b09582f93 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/has_source.rs | |||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index bb22882b1..e7602ee30 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -26,8 +26,6 @@ macro_rules! impl_froms { | |||
26 | } | 26 | } |
27 | } | 27 | } |
28 | 28 | ||
29 | pub mod debug; | ||
30 | |||
31 | pub mod db; | 29 | pub mod db; |
32 | pub mod source_binder; | 30 | pub mod source_binder; |
33 | 31 | ||
@@ -36,16 +34,18 @@ pub mod diagnostics; | |||
36 | mod from_id; | 34 | mod from_id; |
37 | mod code_model; | 35 | mod code_model; |
38 | 36 | ||
39 | pub mod from_source; | 37 | mod has_source; |
38 | mod from_source; | ||
40 | 39 | ||
41 | pub use crate::{ | 40 | pub use crate::{ |
42 | code_model::{ | 41 | code_model::{ |
43 | src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, | 42 | Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, DefWithBody, Docs, Enum, |
44 | DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, HasAttrs, | 43 | EnumVariant, FieldSource, Function, GenericDef, HasAttrs, ImplBlock, Import, Local, |
45 | ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, | 44 | MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, |
46 | StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, | 45 | TypeParam, Union, VariantDef, |
47 | }, | 46 | }, |
48 | from_source::FromSource, | 47 | from_source::FromSource, |
48 | has_source::HasSource, | ||
49 | source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, | 49 | source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, |
50 | }; | 50 | }; |
51 | 51 | ||
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 9efd0477c..44d185003 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -427,7 +427,7 @@ impl SourceAnalyzer { | |||
427 | 427 | ||
428 | /// Checks that particular type `ty` implements `std::future::Future`. | 428 | /// Checks that particular type `ty` implements `std::future::Future`. |
429 | /// This function is used in `.await` syntax completion. | 429 | /// This function is used in `.await` syntax completion. |
430 | pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool { | 430 | pub fn impls_future(&self, db: &impl HirDatabase, ty: Type) -> bool { |
431 | let std_future_path = known::std_future_future(); | 431 | let std_future_path = known::std_future_future(); |
432 | 432 | ||
433 | let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) { | 433 | let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) { |
@@ -440,7 +440,7 @@ impl SourceAnalyzer { | |||
440 | _ => return false, | 440 | _ => return false, |
441 | }; | 441 | }; |
442 | 442 | ||
443 | let canonical_ty = Canonical { value: ty, num_vars: 0 }; | 443 | let canonical_ty = Canonical { value: ty.ty.value, num_vars: 0 }; |
444 | implements_trait(&canonical_ty, db, &self.resolver, krate.into(), std_future_trait) | 444 | implements_trait(&canonical_ty, db, &self.resolver, krate.into(), std_future_trait) |
445 | } | 445 | } |
446 | 446 | ||
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 3ff071f9e..a80067979 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -12,7 +12,7 @@ use hir_expand::{ | |||
12 | use ra_cfg::CfgOptions; | 12 | use ra_cfg::CfgOptions; |
13 | use ra_db::{CrateId, FileId}; | 13 | use ra_db::{CrateId, FileId}; |
14 | use ra_syntax::ast; | 14 | use ra_syntax::ast; |
15 | use rustc_hash::{FxHashMap, FxHashSet}; | 15 | use rustc_hash::FxHashMap; |
16 | use test_utils::tested_by; | 16 | use test_utils::tested_by; |
17 | 17 | ||
18 | use crate::{ | 18 | use crate::{ |
@@ -63,42 +63,12 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C | |||
63 | unexpanded_macros: Vec::new(), | 63 | unexpanded_macros: Vec::new(), |
64 | unexpanded_attribute_macros: Vec::new(), | 64 | unexpanded_attribute_macros: Vec::new(), |
65 | mod_dirs: FxHashMap::default(), | 65 | mod_dirs: FxHashMap::default(), |
66 | macro_stack_monitor: MacroStackMonitor::default(), | ||
67 | poison_macros: FxHashSet::default(), | ||
68 | cfg_options, | 66 | cfg_options, |
69 | }; | 67 | }; |
70 | collector.collect(); | 68 | collector.collect(); |
71 | collector.finish() | 69 | collector.finish() |
72 | } | 70 | } |
73 | 71 | ||
74 | #[derive(Default)] | ||
75 | struct MacroStackMonitor { | ||
76 | counts: FxHashMap<MacroDefId, u32>, | ||
77 | |||
78 | /// Mainly use for test | ||
79 | validator: Option<Box<dyn Fn(u32) -> bool>>, | ||
80 | } | ||
81 | |||
82 | impl MacroStackMonitor { | ||
83 | fn increase(&mut self, macro_def_id: MacroDefId) { | ||
84 | *self.counts.entry(macro_def_id).or_default() += 1; | ||
85 | } | ||
86 | |||
87 | fn decrease(&mut self, macro_def_id: MacroDefId) { | ||
88 | *self.counts.entry(macro_def_id).or_default() -= 1; | ||
89 | } | ||
90 | |||
91 | fn is_poison(&self, macro_def_id: MacroDefId) -> bool { | ||
92 | let cur = *self.counts.get(¯o_def_id).unwrap_or(&0); | ||
93 | |||
94 | if let Some(validator) = &self.validator { | ||
95 | validator(cur) | ||
96 | } else { | ||
97 | cur > 100 | ||
98 | } | ||
99 | } | ||
100 | } | ||
101 | |||
102 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | 72 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] |
103 | enum PartialResolvedImport { | 73 | enum PartialResolvedImport { |
104 | /// None of any namespaces is resolved | 74 | /// None of any namespaces is resolved |
@@ -127,6 +97,14 @@ struct ImportDirective { | |||
127 | status: PartialResolvedImport, | 97 | status: PartialResolvedImport, |
128 | } | 98 | } |
129 | 99 | ||
100 | #[derive(Clone, Debug, Eq, PartialEq)] | ||
101 | struct MacroDirective { | ||
102 | module_id: LocalModuleId, | ||
103 | ast_id: AstId<ast::MacroCall>, | ||
104 | path: Path, | ||
105 | legacy: Option<MacroCallId>, | ||
106 | } | ||
107 | |||
130 | /// Walks the tree of module recursively | 108 | /// Walks the tree of module recursively |
131 | struct DefCollector<'a, DB> { | 109 | struct DefCollector<'a, DB> { |
132 | db: &'a DB, | 110 | db: &'a DB, |
@@ -134,25 +112,9 @@ struct DefCollector<'a, DB> { | |||
134 | glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>, | 112 | glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, LocalImportId)>>, |
135 | unresolved_imports: Vec<ImportDirective>, | 113 | unresolved_imports: Vec<ImportDirective>, |
136 | resolved_imports: Vec<ImportDirective>, | 114 | resolved_imports: Vec<ImportDirective>, |
137 | unexpanded_macros: Vec<(LocalModuleId, AstId<ast::MacroCall>, Path)>, | 115 | unexpanded_macros: Vec<MacroDirective>, |
138 | unexpanded_attribute_macros: Vec<(LocalModuleId, AstId<ast::ModuleItem>, Path)>, | 116 | unexpanded_attribute_macros: Vec<(LocalModuleId, AstId<ast::ModuleItem>, Path)>, |
139 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, | 117 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, |
140 | |||
141 | /// Some macro use `$tt:tt which mean we have to handle the macro perfectly | ||
142 | /// To prevent stack overflow, we add a deep counter here for prevent that. | ||
143 | macro_stack_monitor: MacroStackMonitor, | ||
144 | /// Some macros are not well-behavior, which leads to infinite loop | ||
145 | /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } } | ||
146 | /// We mark it down and skip it in collector | ||
147 | /// | ||
148 | /// FIXME: | ||
149 | /// Right now it only handle a poison macro in a single crate, | ||
150 | /// such that if other crate try to call that macro, | ||
151 | /// the whole process will do again until it became poisoned in that crate. | ||
152 | /// We should handle this macro set globally | ||
153 | /// However, do we want to put it as a global variable? | ||
154 | poison_macros: FxHashSet<MacroDefId>, | ||
155 | |||
156 | cfg_options: &'a CfgOptions, | 118 | cfg_options: &'a CfgOptions, |
157 | } | 119 | } |
158 | 120 | ||
@@ -556,18 +518,24 @@ where | |||
556 | std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new()); | 518 | std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new()); |
557 | let mut resolved = Vec::new(); | 519 | let mut resolved = Vec::new(); |
558 | let mut res = ReachedFixedPoint::Yes; | 520 | let mut res = ReachedFixedPoint::Yes; |
559 | macros.retain(|(module_id, ast_id, path)| { | 521 | macros.retain(|directive| { |
522 | if let Some(call_id) = directive.legacy { | ||
523 | res = ReachedFixedPoint::No; | ||
524 | resolved.push((directive.module_id, call_id)); | ||
525 | return false; | ||
526 | } | ||
527 | |||
560 | let resolved_res = self.def_map.resolve_path_fp_with_macro( | 528 | let resolved_res = self.def_map.resolve_path_fp_with_macro( |
561 | self.db, | 529 | self.db, |
562 | ResolveMode::Other, | 530 | ResolveMode::Other, |
563 | *module_id, | 531 | directive.module_id, |
564 | path, | 532 | &directive.path, |
565 | BuiltinShadowMode::Module, | 533 | BuiltinShadowMode::Module, |
566 | ); | 534 | ); |
567 | 535 | ||
568 | if let Some(def) = resolved_res.resolved_def.take_macros() { | 536 | if let Some(def) = resolved_res.resolved_def.take_macros() { |
569 | let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(*ast_id)); | 537 | let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(directive.ast_id)); |
570 | resolved.push((*module_id, call_id, def)); | 538 | resolved.push((directive.module_id, call_id)); |
571 | res = ReachedFixedPoint::No; | 539 | res = ReachedFixedPoint::No; |
572 | return false; | 540 | return false; |
573 | } | 541 | } |
@@ -579,7 +547,7 @@ where | |||
579 | 547 | ||
580 | if let Some(def) = resolved_res { | 548 | if let Some(def) = resolved_res { |
581 | let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id)); | 549 | let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id)); |
582 | resolved.push((*module_id, call_id, def)); | 550 | resolved.push((*module_id, call_id)); |
583 | res = ReachedFixedPoint::No; | 551 | res = ReachedFixedPoint::No; |
584 | return false; | 552 | return false; |
585 | } | 553 | } |
@@ -590,8 +558,8 @@ where | |||
590 | self.unexpanded_macros = macros; | 558 | self.unexpanded_macros = macros; |
591 | self.unexpanded_attribute_macros = attribute_macros; | 559 | self.unexpanded_attribute_macros = attribute_macros; |
592 | 560 | ||
593 | for (module_id, macro_call_id, macro_def_id) in resolved { | 561 | for (module_id, macro_call_id) in resolved { |
594 | self.collect_macro_expansion(module_id, macro_call_id, macro_def_id); | 562 | self.collect_macro_expansion(module_id, macro_call_id); |
595 | } | 563 | } |
596 | 564 | ||
597 | res | 565 | res |
@@ -611,36 +579,18 @@ where | |||
611 | None | 579 | None |
612 | } | 580 | } |
613 | 581 | ||
614 | fn collect_macro_expansion( | 582 | fn collect_macro_expansion(&mut self, module_id: LocalModuleId, macro_call_id: MacroCallId) { |
615 | &mut self, | 583 | let file_id: HirFileId = macro_call_id.as_file(); |
616 | module_id: LocalModuleId, | 584 | let raw_items = self.db.raw_items(file_id); |
617 | macro_call_id: MacroCallId, | 585 | let mod_dir = self.mod_dirs[&module_id].clone(); |
618 | macro_def_id: MacroDefId, | 586 | ModCollector { |
619 | ) { | 587 | def_collector: &mut *self, |
620 | if self.poison_macros.contains(¯o_def_id) { | 588 | file_id, |
621 | return; | 589 | module_id, |
622 | } | 590 | raw_items: &raw_items, |
623 | 591 | mod_dir, | |
624 | self.macro_stack_monitor.increase(macro_def_id); | ||
625 | |||
626 | if !self.macro_stack_monitor.is_poison(macro_def_id) { | ||
627 | let file_id: HirFileId = macro_call_id.as_file(); | ||
628 | let raw_items = self.db.raw_items(file_id); | ||
629 | let mod_dir = self.mod_dirs[&module_id].clone(); | ||
630 | ModCollector { | ||
631 | def_collector: &mut *self, | ||
632 | file_id, | ||
633 | module_id, | ||
634 | raw_items: &raw_items, | ||
635 | mod_dir, | ||
636 | } | ||
637 | .collect(raw_items.items()); | ||
638 | } else { | ||
639 | log::error!("Too deep macro expansion: {:?}", macro_call_id); | ||
640 | self.poison_macros.insert(macro_def_id); | ||
641 | } | 592 | } |
642 | 593 | .collect(raw_items.items()); | |
643 | self.macro_stack_monitor.decrease(macro_def_id); | ||
644 | } | 594 | } |
645 | 595 | ||
646 | fn finish(self) -> CrateDefMap { | 596 | fn finish(self) -> CrateDefMap { |
@@ -908,15 +858,20 @@ where | |||
908 | return; | 858 | return; |
909 | } | 859 | } |
910 | 860 | ||
911 | // Case 2: try to resolve in legacy scope and expand macro_rules, triggering | 861 | // Case 2: try to resolve in legacy scope and expand macro_rules |
912 | // recursive item collection. | ||
913 | if let Some(macro_def) = mac.path.as_ident().and_then(|name| { | 862 | if let Some(macro_def) = mac.path.as_ident().and_then(|name| { |
914 | self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) | 863 | self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) |
915 | }) { | 864 | }) { |
916 | let macro_call_id = | 865 | let macro_call_id = |
917 | macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id)); | 866 | macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id)); |
918 | 867 | ||
919 | self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, macro_def); | 868 | self.def_collector.unexpanded_macros.push(MacroDirective { |
869 | module_id: self.module_id, | ||
870 | path: mac.path.clone(), | ||
871 | ast_id, | ||
872 | legacy: Some(macro_call_id), | ||
873 | }); | ||
874 | |||
920 | return; | 875 | return; |
921 | } | 876 | } |
922 | 877 | ||
@@ -926,7 +881,13 @@ where | |||
926 | if path.is_ident() { | 881 | if path.is_ident() { |
927 | path.kind = PathKind::Self_; | 882 | path.kind = PathKind::Self_; |
928 | } | 883 | } |
929 | self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path)); | 884 | |
885 | self.def_collector.unexpanded_macros.push(MacroDirective { | ||
886 | module_id: self.module_id, | ||
887 | path, | ||
888 | ast_id, | ||
889 | legacy: None, | ||
890 | }); | ||
930 | } | 891 | } |
931 | 892 | ||
932 | fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) { | 893 | fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) { |
@@ -951,19 +912,13 @@ fn is_macro_rules(path: &Path) -> bool { | |||
951 | 912 | ||
952 | #[cfg(test)] | 913 | #[cfg(test)] |
953 | mod tests { | 914 | mod tests { |
915 | use crate::{db::DefDatabase, test_db::TestDB}; | ||
954 | use ra_arena::Arena; | 916 | use ra_arena::Arena; |
955 | use ra_db::{fixture::WithFixture, SourceDatabase}; | 917 | use ra_db::{fixture::WithFixture, SourceDatabase}; |
956 | use rustc_hash::FxHashSet; | ||
957 | |||
958 | use crate::{db::DefDatabase, test_db::TestDB}; | ||
959 | 918 | ||
960 | use super::*; | 919 | use super::*; |
961 | 920 | ||
962 | fn do_collect_defs( | 921 | fn do_collect_defs(db: &impl DefDatabase, def_map: CrateDefMap) -> CrateDefMap { |
963 | db: &impl DefDatabase, | ||
964 | def_map: CrateDefMap, | ||
965 | monitor: MacroStackMonitor, | ||
966 | ) -> (CrateDefMap, FxHashSet<MacroDefId>) { | ||
967 | let mut collector = DefCollector { | 922 | let mut collector = DefCollector { |
968 | db, | 923 | db, |
969 | def_map, | 924 | def_map, |
@@ -973,19 +928,13 @@ mod tests { | |||
973 | unexpanded_macros: Vec::new(), | 928 | unexpanded_macros: Vec::new(), |
974 | unexpanded_attribute_macros: Vec::new(), | 929 | unexpanded_attribute_macros: Vec::new(), |
975 | mod_dirs: FxHashMap::default(), | 930 | mod_dirs: FxHashMap::default(), |
976 | macro_stack_monitor: monitor, | ||
977 | poison_macros: FxHashSet::default(), | ||
978 | cfg_options: &CfgOptions::default(), | 931 | cfg_options: &CfgOptions::default(), |
979 | }; | 932 | }; |
980 | collector.collect(); | 933 | collector.collect(); |
981 | (collector.def_map, collector.poison_macros) | 934 | collector.def_map |
982 | } | 935 | } |
983 | 936 | ||
984 | fn do_limited_resolve( | 937 | fn do_resolve(code: &str) -> CrateDefMap { |
985 | code: &str, | ||
986 | limit: u32, | ||
987 | poison_limit: u32, | ||
988 | ) -> (CrateDefMap, FxHashSet<MacroDefId>) { | ||
989 | let (db, _file_id) = TestDB::with_single_file(&code); | 938 | let (db, _file_id) = TestDB::with_single_file(&code); |
990 | let krate = db.test_crate(); | 939 | let krate = db.test_crate(); |
991 | 940 | ||
@@ -1003,59 +952,18 @@ mod tests { | |||
1003 | diagnostics: Vec::new(), | 952 | diagnostics: Vec::new(), |
1004 | } | 953 | } |
1005 | }; | 954 | }; |
1006 | 955 | do_collect_defs(&db, def_map) | |
1007 | let mut monitor = MacroStackMonitor::default(); | ||
1008 | monitor.validator = Some(Box::new(move |count| { | ||
1009 | assert!(count < limit); | ||
1010 | count >= poison_limit | ||
1011 | })); | ||
1012 | |||
1013 | do_collect_defs(&db, def_map, monitor) | ||
1014 | } | 956 | } |
1015 | 957 | ||
1016 | #[test] | 958 | #[test] |
1017 | fn test_macro_expand_limit_width() { | 959 | fn test_macro_expand_will_stop() { |
1018 | do_limited_resolve( | 960 | do_resolve( |
1019 | r#" | 961 | r#" |
1020 | macro_rules! foo { | 962 | macro_rules! foo { |
1021 | ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); } | 963 | ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); } |
1022 | } | 964 | } |
1023 | foo!(KABOOM); | 965 | foo!(KABOOM); |
1024 | "#, | 966 | "#, |
1025 | 16, | ||
1026 | 1000, | ||
1027 | ); | 967 | ); |
1028 | } | 968 | } |
1029 | |||
1030 | #[test] | ||
1031 | fn test_macro_expand_poisoned() { | ||
1032 | let (_, poison_macros) = do_limited_resolve( | ||
1033 | r#" | ||
1034 | macro_rules! foo { | ||
1035 | ($ty:ty) => { foo!($ty); } | ||
1036 | } | ||
1037 | foo!(KABOOM); | ||
1038 | "#, | ||
1039 | 100, | ||
1040 | 16, | ||
1041 | ); | ||
1042 | |||
1043 | assert_eq!(poison_macros.len(), 1); | ||
1044 | } | ||
1045 | |||
1046 | #[test] | ||
1047 | fn test_macro_expand_normal() { | ||
1048 | let (_, poison_macros) = do_limited_resolve( | ||
1049 | r#" | ||
1050 | macro_rules! foo { | ||
1051 | ($ident:ident) => { struct $ident {} } | ||
1052 | } | ||
1053 | foo!(Bar); | ||
1054 | "#, | ||
1055 | 16, | ||
1056 | 16, | ||
1057 | ); | ||
1058 | |||
1059 | assert_eq!(poison_macros.len(), 0); | ||
1060 | } | ||
1061 | } | 969 | } |
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 9daa77cfa..0f4dac45e 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs | |||
@@ -332,7 +332,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
332 | // It will not recurse to `coerce`. | 332 | // It will not recurse to `coerce`. |
333 | return self.table.unify_substs(st1, st2, 0); | 333 | return self.table.unify_substs(st1, st2, 0); |
334 | } | 334 | } |
335 | _ => {} | 335 | _ => { |
336 | if self.table.unify_inner_trivial(&derefed_ty, &to_ty) { | ||
337 | return true; | ||
338 | } | ||
339 | } | ||
336 | } | 340 | } |
337 | } | 341 | } |
338 | 342 | ||
diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 58b22396f..ac9e3872a 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs | |||
@@ -403,3 +403,40 @@ fn test() { | |||
403 | "### | 403 | "### |
404 | ); | 404 | ); |
405 | } | 405 | } |
406 | |||
407 | #[test] | ||
408 | fn coerce_autoderef_generic() { | ||
409 | assert_snapshot!( | ||
410 | infer_with_mismatches(r#" | ||
411 | struct Foo; | ||
412 | fn takes_ref<T>(x: &T) -> T { *x } | ||
413 | fn test() { | ||
414 | takes_ref(&Foo); | ||
415 | takes_ref(&&Foo); | ||
416 | takes_ref(&&&Foo); | ||
417 | } | ||
418 | "#, true), | ||
419 | @r###" | ||
420 | [29; 30) 'x': &T | ||
421 | [41; 47) '{ *x }': T | ||
422 | [43; 45) '*x': T | ||
423 | [44; 45) 'x': &T | ||
424 | [58; 127) '{ ...oo); }': () | ||
425 | [64; 73) 'takes_ref': fn takes_ref<Foo>(&T) -> T | ||
426 | [64; 79) 'takes_ref(&Foo)': Foo | ||
427 | [74; 78) '&Foo': &Foo | ||
428 | [75; 78) 'Foo': Foo | ||
429 | [85; 94) 'takes_ref': fn takes_ref<&Foo>(&T) -> T | ||
430 | [85; 101) 'takes_...&&Foo)': &Foo | ||
431 | [95; 100) '&&Foo': &&Foo | ||
432 | [96; 100) '&Foo': &Foo | ||
433 | [97; 100) 'Foo': Foo | ||
434 | [107; 116) 'takes_ref': fn takes_ref<&&Foo>(&T) -> T | ||
435 | [107; 124) 'takes_...&&Foo)': &&Foo | ||
436 | [117; 123) '&&&Foo': &&&Foo | ||
437 | [118; 123) '&&Foo': &&Foo | ||
438 | [119; 123) '&Foo': &Foo | ||
439 | [120; 123) 'Foo': Foo | ||
440 | "### | ||
441 | ); | ||
442 | } | ||
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index a52eb0ee4..294964887 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -27,7 +27,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { | |||
27 | complete_methods(acc, ctx, &receiver_ty); | 27 | complete_methods(acc, ctx, &receiver_ty); |
28 | 28 | ||
29 | // Suggest .await syntax for types that implement Future trait | 29 | // Suggest .await syntax for types that implement Future trait |
30 | if ctx.analyzer.impls_future(ctx.db, receiver_ty.into_ty()) { | 30 | if ctx.analyzer.impls_future(ctx.db, receiver_ty) { |
31 | CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") | 31 | CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") |
32 | .detail("expr.await") | 32 | .detail("expr.await") |
33 | .insert_text("await") | 33 | .insert_text("await") |
diff --git a/crates/ra_ide/src/db.rs b/crates/ra_ide/src/db.rs index f739ebecd..47d0aed6f 100644 --- a/crates/ra_ide/src/db.rs +++ b/crates/ra_ide/src/db.rs | |||
@@ -5,7 +5,7 @@ use std::sync::Arc; | |||
5 | use ra_db::{ | 5 | use ra_db::{ |
6 | salsa::{self, Database, Durability}, | 6 | salsa::{self, Database, Durability}, |
7 | Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, | 7 | Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, |
8 | SourceDatabase, SourceDatabaseExt, SourceRootId, | 8 | SourceDatabase, SourceRootId, |
9 | }; | 9 | }; |
10 | use rustc_hash::FxHashMap; | 10 | use rustc_hash::FxHashMap; |
11 | 11 | ||
@@ -49,18 +49,6 @@ impl FileLoader for RootDatabase { | |||
49 | } | 49 | } |
50 | } | 50 | } |
51 | 51 | ||
52 | impl hir::debug::HirDebugHelper for RootDatabase { | ||
53 | fn crate_name(&self, krate: CrateId) -> Option<String> { | ||
54 | self.debug_data.crate_names.get(&krate).cloned() | ||
55 | } | ||
56 | fn file_path(&self, file_id: FileId) -> Option<String> { | ||
57 | let source_root_id = self.file_source_root(file_id); | ||
58 | let source_root_path = self.debug_data.root_paths.get(&source_root_id)?; | ||
59 | let file_path = self.file_relative_path(file_id); | ||
60 | Some(format!("{}/{}", source_root_path, file_path)) | ||
61 | } | ||
62 | } | ||
63 | |||
64 | impl salsa::Database for RootDatabase { | 52 | impl salsa::Database for RootDatabase { |
65 | fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> { | 53 | fn salsa_runtime(&self) -> &salsa::Runtime<RootDatabase> { |
66 | &self.runtime | 54 | &self.runtime |