aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir/src/lib.rs37
-rw-r--r--crates/hir/src/source_analyzer.rs5
-rw-r--r--crates/hir_def/src/body.rs19
-rw-r--r--crates/hir_def/src/body/lower.rs24
-rw-r--r--crates/hir_expand/src/builtin_derive.rs2
-rw-r--r--crates/hir_ty/src/display.rs9
-rw-r--r--crates/hir_ty/src/infer.rs36
-rw-r--r--crates/hir_ty/src/infer/coerce.rs12
-rw-r--r--crates/hir_ty/src/infer/expr.rs26
-rw-r--r--crates/hir_ty/src/infer/pat.rs22
-rw-r--r--crates/hir_ty/src/infer/unify.rs28
-rw-r--r--crates/hir_ty/src/lib.rs91
-rw-r--r--crates/hir_ty/src/lower.rs12
-rw-r--r--crates/hir_ty/src/method_resolution.rs6
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs32
-rw-r--r--crates/ide/src/annotations.rs83
-rw-r--r--crates/ide/src/file_structure.rs228
-rw-r--r--crates/ide/src/goto_definition.rs11
-rw-r--r--crates/ide/src/join_lines.rs4
-rw-r--r--crates/ide/src/lib.rs4
-rw-r--r--crates/ide/src/references.rs26
-rw-r--r--crates/ide/src/references/rename.rs3
-rw-r--r--crates/ide/src/runnables.rs60
-rw-r--r--crates/ide/src/typing.rs3
-rw-r--r--crates/ide_completion/src/completions/postfix/format_like.rs2
-rw-r--r--crates/ide_completion/src/context.rs297
-rw-r--r--crates/ide_completion/src/render.rs25
-rw-r--r--crates/ide_db/src/defs.rs2
-rw-r--r--crates/ide_db/src/helpers.rs28
-rw-r--r--crates/ide_db/src/search.rs16
-rw-r--r--crates/mbe/src/syntax_bridge.rs8
-rw-r--r--crates/proc_macro_api/src/version.rs4
-rw-r--r--crates/project_model/src/rustc_cfg.rs2
-rw-r--r--crates/rust-analyzer/src/handlers.rs22
-rw-r--r--crates/rust-analyzer/src/lsp_utils.rs4
-rw-r--r--crates/rust-analyzer/src/to_proto.rs10
36 files changed, 851 insertions, 352 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index d13b4d5fd..c5161dadd 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -267,8 +267,7 @@ impl ModuleDef {
267 } 267 }
268 268
269 pub fn canonical_path(&self, db: &dyn HirDatabase) -> Option<String> { 269 pub fn canonical_path(&self, db: &dyn HirDatabase) -> Option<String> {
270 let mut segments = Vec::new(); 270 let mut segments = vec![self.name(db)?.to_string()];
271 segments.push(self.name(db)?.to_string());
272 for m in self.module(db)?.path_to_root(db) { 271 for m in self.module(db)?.path_to_root(db) {
273 segments.extend(m.name(db).map(|it| it.to_string())) 272 segments.extend(m.name(db).map(|it| it.to_string()))
274 } 273 }
@@ -1634,7 +1633,7 @@ impl Type {
1634 1633
1635 pub fn remove_ref(&self) -> Option<Type> { 1634 pub fn remove_ref(&self) -> Option<Type> {
1636 match &self.ty.value.interned(&Interner) { 1635 match &self.ty.value.interned(&Interner) {
1637 TyKind::Ref(.., substs) => Some(self.derived(substs[0].clone())), 1636 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
1638 _ => None, 1637 _ => None,
1639 } 1638 }
1640 } 1639 }
@@ -1788,10 +1787,30 @@ impl Type {
1788 return go(&self.ty.value); 1787 return go(&self.ty.value);
1789 1788
1790 fn go(ty: &Ty) -> bool { 1789 fn go(ty: &Ty) -> bool {
1791 if ty.is_unknown() { 1790 match ty.interned(&Interner) {
1792 true 1791 TyKind::Unknown => true,
1793 } else { 1792
1794 ty.substs().map_or(false, |substs| substs.iter().any(go)) 1793 TyKind::Adt(_, substs)
1794 | TyKind::AssociatedType(_, substs)
1795 | TyKind::Tuple(_, substs)
1796 | TyKind::OpaqueType(_, substs)
1797 | TyKind::FnDef(_, substs)
1798 | TyKind::Closure(_, substs) => substs.iter().any(go),
1799
1800 TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => {
1801 go(ty)
1802 }
1803
1804 TyKind::Scalar(_)
1805 | TyKind::Str
1806 | TyKind::Never
1807 | TyKind::Placeholder(_)
1808 | TyKind::BoundVar(_)
1809 | TyKind::InferenceVar(_, _)
1810 | TyKind::Dyn(_)
1811 | TyKind::Function(_)
1812 | TyKind::Alias(_)
1813 | TyKind::ForeignType(_) => false,
1795 } 1814 }
1796 } 1815 }
1797 } 1816 }
@@ -2020,6 +2039,10 @@ impl Type {
2020 walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); 2039 walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
2021 } 2040 }
2022 2041
2042 TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => {
2043 walk_type(db, &type_.derived(ty.clone()), cb);
2044 }
2045
2023 _ => {} 2046 _ => {}
2024 } 2047 }
2025 if let Some(substs) = ty.substs() { 2048 if let Some(substs) = ty.substs() {
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index d546512cb..4d59293e9 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -161,8 +161,9 @@ impl SourceAnalyzer {
161 db: &dyn HirDatabase, 161 db: &dyn HirDatabase,
162 field: &ast::RecordExprField, 162 field: &ast::RecordExprField,
163 ) -> Option<(Field, Option<Local>)> { 163 ) -> Option<(Field, Option<Local>)> {
164 let expr = field.expr()?; 164 let expr_id =
165 let expr_id = self.expr_id(db, &expr)?; 165 self.body_source_map.as_ref()?.node_field(InFile::new(self.file_id, field))?;
166
166 let local = if field.name_ref().is_some() { 167 let local = if field.name_ref().is_some() {
167 None 168 None
168 } else { 169 } else {
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index 19c4eb521..8bcc350ce 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -253,11 +253,18 @@ pub type LabelSource = InFile<LabelPtr>;
253pub struct BodySourceMap { 253pub struct BodySourceMap {
254 expr_map: FxHashMap<ExprSource, ExprId>, 254 expr_map: FxHashMap<ExprSource, ExprId>,
255 expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>, 255 expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>,
256
256 pat_map: FxHashMap<PatSource, PatId>, 257 pat_map: FxHashMap<PatSource, PatId>,
257 pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>, 258 pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>,
259
258 label_map: FxHashMap<LabelSource, LabelId>, 260 label_map: FxHashMap<LabelSource, LabelId>,
259 label_map_back: ArenaMap<LabelId, LabelSource>, 261 label_map_back: ArenaMap<LabelId, LabelSource>,
260 field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordExprField>>>, 262
263 /// We don't create explicit nodes for record fields (`S { record_field: 92 }`).
264 /// Instead, we use id of expression (`92`) to identify the field.
265 field_map: FxHashMap<InFile<AstPtr<ast::RecordExprField>>, ExprId>,
266 field_map_back: FxHashMap<ExprId, InFile<AstPtr<ast::RecordExprField>>>,
267
261 expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>, 268 expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
262 269
263 /// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in 270 /// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in
@@ -337,6 +344,8 @@ impl Index<LabelId> for Body {
337 } 344 }
338} 345}
339 346
347// FIXME: Change `node_` prefix to something more reasonable.
348// Perhaps `expr_syntax` and `expr_id`?
340impl BodySourceMap { 349impl BodySourceMap {
341 pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> { 350 pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> {
342 self.expr_map_back[expr].clone() 351 self.expr_map_back[expr].clone()
@@ -375,8 +384,12 @@ impl BodySourceMap {
375 self.label_map.get(&src).cloned() 384 self.label_map.get(&src).cloned()
376 } 385 }
377 386
378 pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordExprField>> { 387 pub fn field_syntax(&self, expr: ExprId) -> InFile<AstPtr<ast::RecordExprField>> {
379 self.field_map[&(expr, field)].clone() 388 self.field_map_back[&expr].clone()
389 }
390 pub fn node_field(&self, node: InFile<&ast::RecordExprField>) -> Option<ExprId> {
391 let src = node.map(|it| AstPtr::new(it));
392 self.field_map.get(&src).cloned()
380 } 393 }
381 394
382 pub(crate) fn add_diagnostics(&self, _db: &dyn DefDatabase, sink: &mut DiagnosticSink<'_>) { 395 pub(crate) fn add_diagnostics(&self, _db: &dyn DefDatabase, sink: &mut DiagnosticSink<'_>) {
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 8c8eb8007..8934ae6c9 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -379,23 +379,22 @@ impl ExprCollector<'_> {
379 } 379 }
380 ast::Expr::RecordExpr(e) => { 380 ast::Expr::RecordExpr(e) => {
381 let path = e.path().and_then(|path| self.expander.parse_path(path)); 381 let path = e.path().and_then(|path| self.expander.parse_path(path));
382 let mut field_ptrs = Vec::new();
383 let record_lit = if let Some(nfl) = e.record_expr_field_list() { 382 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
384 let fields = nfl 383 let fields = nfl
385 .fields() 384 .fields()
386 .inspect(|field| field_ptrs.push(AstPtr::new(field)))
387 .filter_map(|field| { 385 .filter_map(|field| {
388 self.check_cfg(&field)?; 386 self.check_cfg(&field)?;
389 387
390 let name = field.field_name()?.as_name(); 388 let name = field.field_name()?.as_name();
391 389
392 Some(RecordLitField { 390 let expr = match field.expr() {
393 name, 391 Some(e) => self.collect_expr(e),
394 expr: match field.expr() { 392 None => self.missing_expr(),
395 Some(e) => self.collect_expr(e), 393 };
396 None => self.missing_expr(), 394 let src = self.expander.to_source(AstPtr::new(&field));
397 }, 395 self.source_map.field_map.insert(src.clone(), expr);
398 }) 396 self.source_map.field_map_back.insert(expr, src);
397 Some(RecordLitField { name, expr })
399 }) 398 })
400 .collect(); 399 .collect();
401 let spread = nfl.spread().map(|s| self.collect_expr(s)); 400 let spread = nfl.spread().map(|s| self.collect_expr(s));
@@ -404,12 +403,7 @@ impl ExprCollector<'_> {
404 Expr::RecordLit { path, fields: Vec::new(), spread: None } 403 Expr::RecordLit { path, fields: Vec::new(), spread: None }
405 }; 404 };
406 405
407 let res = self.alloc_expr(record_lit, syntax_ptr); 406 self.alloc_expr(record_lit, syntax_ptr)
408 for (i, ptr) in field_ptrs.into_iter().enumerate() {
409 let src = self.expander.to_source(ptr);
410 self.source_map.field_map.insert((res, i), src);
411 }
412 res
413 } 407 }
414 ast::Expr::FieldExpr(e) => { 408 ast::Expr::FieldExpr(e) => {
415 let expr = self.collect_expr_opt(e.expr()); 409 let expr = self.collect_expr_opt(e.expr());
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs
index dfdb9cf59..5e908b223 100644
--- a/crates/hir_expand/src/builtin_derive.rs
+++ b/crates/hir_expand/src/builtin_derive.rs
@@ -108,7 +108,7 @@ fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, mbe::ExpandError> {
108} 108}
109 109
110fn make_type_args(n: usize, bound: Vec<tt::TokenTree>) -> Vec<tt::TokenTree> { 110fn make_type_args(n: usize, bound: Vec<tt::TokenTree>) -> Vec<tt::TokenTree> {
111 let mut result = Vec::<tt::TokenTree>::new(); 111 let mut result = Vec::<tt::TokenTree>::with_capacity(n * 2);
112 result.push( 112 result.push(
113 tt::Leaf::Punct(tt::Punct { 113 tt::Leaf::Punct(tt::Punct {
114 char: '<', 114 char: '<',
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 378c951c5..c1062387e 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -276,20 +276,17 @@ impl HirDisplay for Ty {
276 &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?, 276 &TyKind::Scalar(Scalar::Float(t)) => write!(f, "{}", primitive::float_ty_to_string(t))?,
277 &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?, 277 &TyKind::Scalar(Scalar::Int(t)) => write!(f, "{}", primitive::int_ty_to_string(t))?,
278 &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?, 278 &TyKind::Scalar(Scalar::Uint(t)) => write!(f, "{}", primitive::uint_ty_to_string(t))?,
279 TyKind::Slice(parameters) => { 279 TyKind::Slice(t) => {
280 let t = parameters.as_single();
281 write!(f, "[")?; 280 write!(f, "[")?;
282 t.hir_fmt(f)?; 281 t.hir_fmt(f)?;
283 write!(f, "]")?; 282 write!(f, "]")?;
284 } 283 }
285 TyKind::Array(parameters) => { 284 TyKind::Array(t) => {
286 let t = parameters.as_single();
287 write!(f, "[")?; 285 write!(f, "[")?;
288 t.hir_fmt(f)?; 286 t.hir_fmt(f)?;
289 write!(f, "; _]")?; 287 write!(f, "; _]")?;
290 } 288 }
291 TyKind::Raw(m, parameters) | TyKind::Ref(m, parameters) => { 289 TyKind::Raw(m, t) | TyKind::Ref(m, t) => {
292 let t = parameters.as_single();
293 let ty_display = 290 let ty_display =
294 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 291 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
295 292
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index fbfedb4e6..9c385b845 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -108,6 +108,17 @@ pub struct TypeMismatch {
108 pub actual: Ty, 108 pub actual: Ty,
109} 109}
110 110
111#[derive(Clone, PartialEq, Eq, Debug)]
112struct InternedStandardTypes {
113 unknown: Ty,
114}
115
116impl Default for InternedStandardTypes {
117 fn default() -> Self {
118 InternedStandardTypes { unknown: TyKind::Unknown.intern(&Interner) }
119 }
120}
121
111/// The result of type inference: A mapping from expressions and patterns to types. 122/// The result of type inference: A mapping from expressions and patterns to types.
112#[derive(Clone, PartialEq, Eq, Debug, Default)] 123#[derive(Clone, PartialEq, Eq, Debug, Default)]
113pub struct InferenceResult { 124pub struct InferenceResult {
@@ -126,6 +137,8 @@ pub struct InferenceResult {
126 pub type_of_expr: ArenaMap<ExprId, Ty>, 137 pub type_of_expr: ArenaMap<ExprId, Ty>,
127 pub type_of_pat: ArenaMap<PatId, Ty>, 138 pub type_of_pat: ArenaMap<PatId, Ty>,
128 pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>, 139 pub(super) type_mismatches: ArenaMap<ExprId, TypeMismatch>,
140 /// Interned Unknown to return references to.
141 standard_types: InternedStandardTypes,
129} 142}
130 143
131impl InferenceResult { 144impl InferenceResult {
@@ -170,7 +183,7 @@ impl Index<ExprId> for InferenceResult {
170 type Output = Ty; 183 type Output = Ty;
171 184
172 fn index(&self, expr: ExprId) -> &Ty { 185 fn index(&self, expr: ExprId) -> &Ty {
173 self.type_of_expr.get(expr).unwrap_or(&Ty(TyKind::Unknown)) 186 self.type_of_expr.get(expr).unwrap_or(&self.standard_types.unknown)
174 } 187 }
175} 188}
176 189
@@ -178,7 +191,7 @@ impl Index<PatId> for InferenceResult {
178 type Output = Ty; 191 type Output = Ty;
179 192
180 fn index(&self, pat: PatId) -> &Ty { 193 fn index(&self, pat: PatId) -> &Ty {
181 self.type_of_pat.get(pat).unwrap_or(&Ty(TyKind::Unknown)) 194 self.type_of_pat.get(pat).unwrap_or(&self.standard_types.unknown)
182 } 195 }
183} 196}
184 197
@@ -723,14 +736,19 @@ impl Expectation {
723 736
724 /// This expresses no expectation on the type. 737 /// This expresses no expectation on the type.
725 fn none() -> Self { 738 fn none() -> Self {
726 Expectation { ty: TyKind::Unknown.intern(&Interner), rvalue_hint: false } 739 Expectation {
740 // FIXME
741 ty: TyKind::Unknown.intern(&Interner),
742 rvalue_hint: false,
743 }
727 } 744 }
728 745
729 fn coercion_target(&self) -> &Ty { 746 fn coercion_target(&self) -> Ty {
730 if self.rvalue_hint { 747 if self.rvalue_hint {
731 &Ty(TyKind::Unknown) 748 // FIXME
749 TyKind::Unknown.intern(&Interner)
732 } else { 750 } else {
733 &self.ty 751 self.ty.clone()
734 } 752 }
735 } 753 }
736} 754}
@@ -784,7 +802,7 @@ mod diagnostics {
784 802
785 #[derive(Debug, PartialEq, Eq, Clone)] 803 #[derive(Debug, PartialEq, Eq, Clone)]
786 pub(super) enum InferenceDiagnostic { 804 pub(super) enum InferenceDiagnostic {
787 NoSuchField { expr: ExprId, field: usize }, 805 NoSuchField { expr: ExprId },
788 BreakOutsideOfLoop { expr: ExprId }, 806 BreakOutsideOfLoop { expr: ExprId },
789 } 807 }
790 808
@@ -796,9 +814,9 @@ mod diagnostics {
796 sink: &mut DiagnosticSink, 814 sink: &mut DiagnosticSink,
797 ) { 815 ) {
798 match self { 816 match self {
799 InferenceDiagnostic::NoSuchField { expr, field } => { 817 InferenceDiagnostic::NoSuchField { expr } => {
800 let (_, source_map) = db.body_with_source_map(owner); 818 let (_, source_map) = db.body_with_source_map(owner);
801 let field = source_map.field_syntax(*expr, *field); 819 let field = source_map.field_syntax(*expr);
802 sink.push(NoSuchField { file: field.file_id, field: field.value }) 820 sink.push(NoSuchField { file: field.file_id, field: field.value })
803 } 821 }
804 InferenceDiagnostic::BreakOutsideOfLoop { expr } => { 822 InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 36670043a..137419264 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -71,7 +71,7 @@ impl<'a> InferenceContext<'a> {
71 } 71 }
72 72
73 // Pointer weakening and function to pointer 73 // Pointer weakening and function to pointer
74 match (&mut from_ty.0, to_ty.interned(&Interner)) { 74 match (from_ty.interned_mut(), to_ty.interned(&Interner)) {
75 // `*mut T` -> `*const T` 75 // `*mut T` -> `*const T`
76 // `&mut T` -> `&T` 76 // `&mut T` -> `&T`
77 (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..)) 77 (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..))
@@ -111,9 +111,7 @@ impl<'a> InferenceContext<'a> {
111 // Auto Deref if cannot coerce 111 // Auto Deref if cannot coerce
112 match (from_ty.interned(&Interner), to_ty.interned(&Interner)) { 112 match (from_ty.interned(&Interner), to_ty.interned(&Interner)) {
113 // FIXME: DerefMut 113 // FIXME: DerefMut
114 (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => { 114 (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => self.unify_autoderef_behind_ref(st1, st2),
115 self.unify_autoderef_behind_ref(&st1[0], &st2[0])
116 }
117 115
118 // Otherwise, normal unify 116 // Otherwise, normal unify
119 _ => self.unify(&from_ty, to_ty), 117 _ => self.unify(&from_ty, to_ty),
@@ -178,11 +176,7 @@ impl<'a> InferenceContext<'a> {
178 // Stop when constructor matches. 176 // Stop when constructor matches.
179 if from_ty.equals_ctor(&to_ty) { 177 if from_ty.equals_ctor(&to_ty) {
180 // It will not recurse to `coerce`. 178 // It will not recurse to `coerce`.
181 return match (from_ty.substs(), to_ty.substs()) { 179 return self.table.unify(&from_ty, &to_ty);
182 (Some(st1), Some(st2)) => self.table.unify_substs(st1, st2, 0),
183 (None, None) => true,
184 _ => false,
185 };
186 } else if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) { 180 } else if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) {
187 return true; 181 return true;
188 } 182 }
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 55163c963..f40dec17f 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -405,14 +405,13 @@ impl<'a> InferenceContext<'a> {
405 let substs = ty.substs().cloned().unwrap_or_else(Substs::empty); 405 let substs = ty.substs().cloned().unwrap_or_else(Substs::empty);
406 let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); 406 let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default();
407 let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); 407 let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it));
408 for (field_idx, field) in fields.iter().enumerate() { 408 for field in fields.iter() {
409 let field_def = 409 let field_def =
410 variant_data.as_ref().and_then(|it| match it.field(&field.name) { 410 variant_data.as_ref().and_then(|it| match it.field(&field.name) {
411 Some(local_id) => Some(FieldId { parent: def_id.unwrap(), local_id }), 411 Some(local_id) => Some(FieldId { parent: def_id.unwrap(), local_id }),
412 None => { 412 None => {
413 self.push_diagnostic(InferenceDiagnostic::NoSuchField { 413 self.push_diagnostic(InferenceDiagnostic::NoSuchField {
414 expr: tgt_expr, 414 expr: field.expr,
415 field: field_idx,
416 }); 415 });
417 None 416 None
418 } 417 }
@@ -504,8 +503,8 @@ impl<'a> InferenceContext<'a> {
504 }; 503 };
505 let inner_ty = self.infer_expr_inner(*expr, &expectation); 504 let inner_ty = self.infer_expr_inner(*expr, &expectation);
506 match rawness { 505 match rawness {
507 Rawness::RawPtr => TyKind::Raw(mutability, Substs::single(inner_ty)), 506 Rawness::RawPtr => TyKind::Raw(mutability, inner_ty),
508 Rawness::Ref => TyKind::Ref(mutability, Substs::single(inner_ty)), 507 Rawness::Ref => TyKind::Ref(mutability, inner_ty),
509 } 508 }
510 .intern(&Interner) 509 .intern(&Interner)
511 } 510 }
@@ -686,7 +685,7 @@ impl<'a> InferenceContext<'a> {
686 } 685 }
687 Expr::Array(array) => { 686 Expr::Array(array) => {
688 let elem_ty = match expected.ty.interned(&Interner) { 687 let elem_ty = match expected.ty.interned(&Interner) {
689 TyKind::Array(st) | TyKind::Slice(st) => st.as_single().clone(), 688 TyKind::Array(st) | TyKind::Slice(st) => st.clone(),
690 _ => self.table.new_type_var(), 689 _ => self.table.new_type_var(),
691 }; 690 };
692 691
@@ -710,18 +709,17 @@ impl<'a> InferenceContext<'a> {
710 } 709 }
711 } 710 }
712 711
713 TyKind::Array(Substs::single(elem_ty)).intern(&Interner) 712 TyKind::Array(elem_ty).intern(&Interner)
714 } 713 }
715 Expr::Literal(lit) => match lit { 714 Expr::Literal(lit) => match lit {
716 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 715 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
717 Literal::String(..) => { 716 Literal::String(..) => {
718 TyKind::Ref(Mutability::Not, Substs::single(TyKind::Str.intern(&Interner))) 717 TyKind::Ref(Mutability::Not, TyKind::Str.intern(&Interner)).intern(&Interner)
719 .intern(&Interner)
720 } 718 }
721 Literal::ByteString(..) => { 719 Literal::ByteString(..) => {
722 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); 720 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
723 let array_type = TyKind::Array(Substs::single(byte_type)).intern(&Interner); 721 let array_type = TyKind::Array(byte_type).intern(&Interner);
724 TyKind::Ref(Mutability::Not, Substs::single(array_type)).intern(&Interner) 722 TyKind::Ref(Mutability::Not, array_type).intern(&Interner)
725 } 723 }
726 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), 724 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
727 Literal::Int(_v, ty) => match ty { 725 Literal::Int(_v, ty) => match ty {
@@ -800,7 +798,7 @@ impl<'a> InferenceContext<'a> {
800 // we don't even make an attempt at coercion 798 // we don't even make an attempt at coercion
801 self.table.new_maybe_never_var() 799 self.table.new_maybe_never_var()
802 } else { 800 } else {
803 self.coerce(&Ty::unit(), expected.coercion_target()); 801 self.coerce(&Ty::unit(), &expected.coercion_target());
804 Ty::unit() 802 Ty::unit()
805 } 803 }
806 }; 804 };
@@ -855,9 +853,7 @@ impl<'a> InferenceContext<'a> {
855 // Apply autoref so the below unification works correctly 853 // Apply autoref so the below unification works correctly
856 // FIXME: return correct autorefs from lookup_method 854 // FIXME: return correct autorefs from lookup_method
857 let actual_receiver_ty = match expected_receiver_ty.as_reference() { 855 let actual_receiver_ty = match expected_receiver_ty.as_reference() {
858 Some((_, mutability)) => { 856 Some((_, mutability)) => TyKind::Ref(mutability, derefed_receiver_ty).intern(&Interner),
859 TyKind::Ref(mutability, Substs::single(derefed_receiver_ty)).intern(&Interner)
860 }
861 _ => derefed_receiver_ty, 857 _ => derefed_receiver_ty,
862 }; 858 };
863 self.unify(&expected_receiver_ty, &actual_receiver_ty); 859 self.unify(&expected_receiver_ty, &actual_receiver_ty);
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index a16755cda..9e8ca18ef 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -158,12 +158,12 @@ impl<'a> InferenceContext<'a> {
158 if mutability != exp_mut { 158 if mutability != exp_mut {
159 // FIXME: emit type error? 159 // FIXME: emit type error?
160 } 160 }
161 inner_ty 161 inner_ty.clone()
162 } 162 }
163 _ => &Ty(TyKind::Unknown), 163 _ => self.result.standard_types.unknown.clone(),
164 }; 164 };
165 let subty = self.infer_pat(*pat, expectation, default_bm); 165 let subty = self.infer_pat(*pat, &expectation, default_bm);
166 TyKind::Ref(mutability, Substs::single(subty)).intern(&Interner) 166 TyKind::Ref(mutability, subty).intern(&Interner)
167 } 167 }
168 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(
169 p.as_ref(), 169 p.as_ref(),
@@ -196,7 +196,7 @@ impl<'a> InferenceContext<'a> {
196 196
197 let bound_ty = match mode { 197 let bound_ty = match mode {
198 BindingMode::Ref(mutability) => { 198 BindingMode::Ref(mutability) => {
199 TyKind::Ref(mutability, Substs::single(inner_ty.clone())).intern(&Interner) 199 TyKind::Ref(mutability, inner_ty.clone()).intern(&Interner)
200 } 200 }
201 BindingMode::Move => inner_ty.clone(), 201 BindingMode::Move => inner_ty.clone(),
202 }; 202 };
@@ -206,8 +206,8 @@ impl<'a> InferenceContext<'a> {
206 } 206 }
207 Pat::Slice { prefix, slice, suffix } => { 207 Pat::Slice { prefix, slice, suffix } => {
208 let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.interned(&Interner) { 208 let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.interned(&Interner) {
209 TyKind::Array(st) => (TyKind::Array, st.as_single().clone()), 209 TyKind::Array(st) => (TyKind::Array, st.clone()),
210 TyKind::Slice(st) => (TyKind::Slice, st.as_single().clone()), 210 TyKind::Slice(st) => (TyKind::Slice, st.clone()),
211 _ => (TyKind::Slice, self.err_ty()), 211 _ => (TyKind::Slice, self.err_ty()),
212 }; 212 };
213 213
@@ -215,7 +215,7 @@ impl<'a> InferenceContext<'a> {
215 self.infer_pat(*pat_id, &elem_ty, default_bm); 215 self.infer_pat(*pat_id, &elem_ty, default_bm);
216 } 216 }
217 217
218 let pat_ty = container_ty(Substs::single(elem_ty)).intern(&Interner); 218 let pat_ty = container_ty(elem_ty).intern(&Interner);
219 if let Some(slice_pat_id) = slice { 219 if let Some(slice_pat_id) = slice {
220 self.infer_pat(*slice_pat_id, &pat_ty, default_bm); 220 self.infer_pat(*slice_pat_id, &pat_ty, default_bm);
221 } 221 }
@@ -232,11 +232,11 @@ impl<'a> InferenceContext<'a> {
232 Pat::Box { inner } => match self.resolve_boxed_box() { 232 Pat::Box { inner } => match self.resolve_boxed_box() {
233 Some(box_adt) => { 233 Some(box_adt) => {
234 let inner_expected = match expected.as_adt() { 234 let inner_expected = match expected.as_adt() {
235 Some((adt, substs)) if adt == box_adt => substs.as_single(), 235 Some((adt, substs)) if adt == box_adt => substs.as_single().clone(),
236 _ => &Ty(TyKind::Unknown), 236 _ => self.result.standard_types.unknown.clone(),
237 }; 237 };
238 238
239 let inner_ty = self.infer_pat(*inner, inner_expected, default_bm); 239 let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm);
240 Ty::adt_ty(box_adt, Substs::single(inner_ty)) 240 Ty::adt_ty(box_adt, Substs::single(inner_ty))
241 } 241 }
242 None => self.err_ty(), 242 None => self.err_ty(),
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index ebc612ca9..66f8fe8a3 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -7,8 +7,8 @@ use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 7
8use super::{InferenceContext, Obligation}; 8use super::{InferenceContext, Obligation};
9use crate::{ 9use crate::{
10 BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferenceVar, Interner, 10 BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate, InEnvironment, InferenceVar,
11 Scalar, Substs, Ty, TyKind, TypeWalk, 11 Interner, Scalar, Substs, Ty, TyKind, TypeWalk,
12}; 12};
13 13
14impl<'a> InferenceContext<'a> { 14impl<'a> InferenceContext<'a> {
@@ -108,7 +108,7 @@ impl<T> Canonicalized<T> {
108 pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { 108 pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty {
109 ty.walk_mut_binders( 109 ty.walk_mut_binders(
110 &mut |ty, binders| { 110 &mut |ty, binders| {
111 if let &mut TyKind::BoundVar(bound) = &mut ty.0 { 111 if let &mut TyKind::BoundVar(bound) = ty.interned_mut() {
112 if bound.debruijn >= binders { 112 if bound.debruijn >= binders {
113 let (v, k) = self.free_vars[bound.index]; 113 let (v, k) = self.free_vars[bound.index];
114 *ty = TyKind::InferenceVar(v, k).intern(&Interner); 114 *ty = TyKind::InferenceVar(v, k).intern(&Interner);
@@ -283,9 +283,23 @@ impl InferenceTable {
283 let ty1 = self.resolve_ty_shallow(ty1); 283 let ty1 = self.resolve_ty_shallow(ty1);
284 let ty2 = self.resolve_ty_shallow(ty2); 284 let ty2 = self.resolve_ty_shallow(ty2);
285 if ty1.equals_ctor(&ty2) { 285 if ty1.equals_ctor(&ty2) {
286 match (ty1.substs(), ty2.substs()) { 286 match (ty1.interned(&Interner), ty2.interned(&Interner)) {
287 (Some(st1), Some(st2)) => self.unify_substs(st1, st2, depth + 1), 287 (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2))
288 (None, None) => true, 288 | (TyKind::FnDef(_, substs1), TyKind::FnDef(_, substs2))
289 | (
290 TyKind::Function(FnPointer { substs: substs1, .. }),
291 TyKind::Function(FnPointer { substs: substs2, .. }),
292 )
293 | (TyKind::Tuple(_, substs1), TyKind::Tuple(_, substs2))
294 | (TyKind::OpaqueType(_, substs1), TyKind::OpaqueType(_, substs2))
295 | (TyKind::AssociatedType(_, substs1), TyKind::AssociatedType(_, substs2))
296 | (TyKind::Closure(.., substs1), TyKind::Closure(.., substs2)) => {
297 self.unify_substs(substs1, substs2, depth + 1)
298 }
299 (TyKind::Ref(_, ty1), TyKind::Ref(_, ty2))
300 | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2))
301 | (TyKind::Array(ty1), TyKind::Array(ty2))
302 | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1),
289 _ => false, 303 _ => false,
290 } 304 }
291 } else { 305 } else {
@@ -404,7 +418,7 @@ impl InferenceTable {
404 if i > 0 { 418 if i > 0 {
405 cov_mark::hit!(type_var_resolves_to_int_var); 419 cov_mark::hit!(type_var_resolves_to_int_var);
406 } 420 }
407 match &ty.0 { 421 match ty.interned(&Interner) {
408 TyKind::InferenceVar(tv, _) => { 422 TyKind::InferenceVar(tv, _) => {
409 let inner = tv.to_inner(); 423 let inner = tv.to_inner();
410 match self.var_unification_table.inlined_probe_value(inner).known() { 424 match self.var_unification_table.inlined_probe_value(inner).known() {
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 484652073..503910dde 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -151,17 +151,17 @@ pub enum TyKind {
151 Tuple(usize, Substs), 151 Tuple(usize, Substs),
152 152
153 /// An array with the given length. Written as `[T; n]`. 153 /// An array with the given length. Written as `[T; n]`.
154 Array(Substs), 154 Array(Ty),
155 155
156 /// The pointee of an array slice. Written as `[T]`. 156 /// The pointee of an array slice. Written as `[T]`.
157 Slice(Substs), 157 Slice(Ty),
158 158
159 /// A raw pointer. Written as `*mut T` or `*const T` 159 /// A raw pointer. Written as `*mut T` or `*const T`
160 Raw(Mutability, Substs), 160 Raw(Mutability, Ty),
161 161
162 /// A reference; a pointer with an associated lifetime. Written as 162 /// A reference; a pointer with an associated lifetime. Written as
163 /// `&'a mut T` or `&'a T`. 163 /// `&'a mut T` or `&'a T`.
164 Ref(Mutability, Substs), 164 Ref(Mutability, Ty),
165 165
166 /// This represents a placeholder for an opaque type in situations where we 166 /// This represents a placeholder for an opaque type in situations where we
167 /// don't know the hidden type (i.e. currently almost always). This is 167 /// don't know the hidden type (i.e. currently almost always). This is
@@ -248,11 +248,11 @@ pub enum TyKind {
248} 248}
249 249
250#[derive(Clone, PartialEq, Eq, Debug, Hash)] 250#[derive(Clone, PartialEq, Eq, Debug, Hash)]
251pub struct Ty(TyKind); 251pub struct Ty(Arc<TyKind>);
252 252
253impl TyKind { 253impl TyKind {
254 pub fn intern(self, _interner: &Interner) -> Ty { 254 pub fn intern(self, _interner: &Interner) -> Ty {
255 Ty(self) 255 Ty(Arc::new(self))
256 } 256 }
257} 257}
258 258
@@ -260,6 +260,14 @@ impl Ty {
260 pub fn interned(&self, _interner: &Interner) -> &TyKind { 260 pub fn interned(&self, _interner: &Interner) -> &TyKind {
261 &self.0 261 &self.0
262 } 262 }
263
264 pub fn interned_mut(&mut self) -> &mut TyKind {
265 Arc::make_mut(&mut self.0)
266 }
267
268 pub fn into_inner(self) -> TyKind {
269 Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone())
270 }
263} 271}
264 272
265/// A list of substitutions for generic parameters. 273/// A list of substitutions for generic parameters.
@@ -665,19 +673,15 @@ impl Ty {
665 673
666 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { 674 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
667 match self.interned(&Interner) { 675 match self.interned(&Interner) {
668 TyKind::Ref(mutability, parameters) => Some((parameters.as_single(), *mutability)), 676 TyKind::Ref(mutability, ty) => Some((ty, *mutability)),
669 _ => None, 677 _ => None,
670 } 678 }
671 } 679 }
672 680
673 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { 681 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
674 match self.interned(&Interner) { 682 match self.interned(&Interner) {
675 TyKind::Ref(mutability, parameters) => { 683 TyKind::Ref(mutability, ty) => Some((ty, Rawness::Ref, *mutability)),
676 Some((parameters.as_single(), Rawness::Ref, *mutability)) 684 TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
677 }
678 TyKind::Raw(mutability, parameters) => {
679 Some((parameters.as_single(), Rawness::RawPtr, *mutability))
680 }
681 _ => None, 685 _ => None,
682 } 686 }
683 } 687 }
@@ -685,8 +689,8 @@ impl Ty {
685 pub fn strip_references(&self) -> &Ty { 689 pub fn strip_references(&self) -> &Ty {
686 let mut t: &Ty = self; 690 let mut t: &Ty = self;
687 691
688 while let TyKind::Ref(_mutability, parameters) = t.interned(&Interner) { 692 while let TyKind::Ref(_mutability, ty) = t.interned(&Interner) {
689 t = parameters.as_single(); 693 t = ty;
690 } 694 }
691 695
692 t 696 t
@@ -772,8 +776,8 @@ impl Ty {
772 776
773 fn builtin_deref(&self) -> Option<Ty> { 777 fn builtin_deref(&self) -> Option<Ty> {
774 match self.interned(&Interner) { 778 match self.interned(&Interner) {
775 TyKind::Ref(.., parameters) => Some(Ty::clone(parameters.as_single())), 779 TyKind::Ref(.., ty) => Some(ty.clone()),
776 TyKind::Raw(.., parameters) => Some(Ty::clone(parameters.as_single())), 780 TyKind::Raw(.., ty) => Some(ty.clone()),
777 _ => None, 781 _ => None,
778 } 782 }
779 } 783 }
@@ -809,40 +813,11 @@ impl Ty {
809 } 813 }
810 } 814 }
811 815
812 /// If this is a type with type parameters (an ADT or function), replaces
813 /// the `Substs` for these type parameters with the given ones. (So e.g. if
814 /// `self` is `Option<_>` and the substs contain `u32`, we'll have
815 /// `Option<u32>` afterwards.)
816 pub fn apply_substs(mut self, new_substs: Substs) -> Ty {
817 match &mut self.0 {
818 TyKind::Adt(_, substs)
819 | TyKind::Slice(substs)
820 | TyKind::Array(substs)
821 | TyKind::Raw(_, substs)
822 | TyKind::Ref(_, substs)
823 | TyKind::FnDef(_, substs)
824 | TyKind::Function(FnPointer { substs, .. })
825 | TyKind::Tuple(_, substs)
826 | TyKind::OpaqueType(_, substs)
827 | TyKind::AssociatedType(_, substs)
828 | TyKind::Closure(.., substs) => {
829 assert_eq!(substs.len(), new_substs.len());
830 *substs = new_substs;
831 }
832 _ => (),
833 }
834 self
835 }
836
837 /// Returns the type parameters of this type if it has some (i.e. is an ADT 816 /// Returns the type parameters of this type if it has some (i.e. is an ADT
838 /// or function); so if `self` is `Option<u32>`, this returns the `u32`. 817 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
839 pub fn substs(&self) -> Option<&Substs> { 818 pub fn substs(&self) -> Option<&Substs> {
840 match self.interned(&Interner) { 819 match self.interned(&Interner) {
841 TyKind::Adt(_, substs) 820 TyKind::Adt(_, substs)
842 | TyKind::Slice(substs)
843 | TyKind::Array(substs)
844 | TyKind::Raw(_, substs)
845 | TyKind::Ref(_, substs)
846 | TyKind::FnDef(_, substs) 821 | TyKind::FnDef(_, substs)
847 | TyKind::Function(FnPointer { substs, .. }) 822 | TyKind::Function(FnPointer { substs, .. })
848 | TyKind::Tuple(_, substs) 823 | TyKind::Tuple(_, substs)
@@ -853,13 +828,9 @@ impl Ty {
853 } 828 }
854 } 829 }
855 830
856 pub fn substs_mut(&mut self) -> Option<&mut Substs> { 831 fn substs_mut(&mut self) -> Option<&mut Substs> {
857 match &mut self.0 { 832 match self.interned_mut() {
858 TyKind::Adt(_, substs) 833 TyKind::Adt(_, substs)
859 | TyKind::Slice(substs)
860 | TyKind::Array(substs)
861 | TyKind::Raw(_, substs)
862 | TyKind::Ref(_, substs)
863 | TyKind::FnDef(_, substs) 834 | TyKind::FnDef(_, substs)
864 | TyKind::Function(FnPointer { substs, .. }) 835 | TyKind::Function(FnPointer { substs, .. })
865 | TyKind::Tuple(_, substs) 836 | TyKind::Tuple(_, substs)
@@ -988,7 +959,7 @@ pub trait TypeWalk {
988 { 959 {
989 self.walk_mut_binders( 960 self.walk_mut_binders(
990 &mut |ty_mut, binders| { 961 &mut |ty_mut, binders| {
991 let ty = mem::replace(ty_mut, Ty(TyKind::Unknown)); 962 let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner));
992 *ty_mut = f(ty, binders); 963 *ty_mut = f(ty, binders);
993 }, 964 },
994 binders, 965 binders,
@@ -1001,7 +972,7 @@ pub trait TypeWalk {
1001 Self: Sized, 972 Self: Sized,
1002 { 973 {
1003 self.walk_mut(&mut |ty_mut| { 974 self.walk_mut(&mut |ty_mut| {
1004 let ty = mem::replace(ty_mut, Ty(TyKind::Unknown)); 975 let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner));
1005 *ty_mut = f(ty); 976 *ty_mut = f(ty);
1006 }); 977 });
1007 self 978 self
@@ -1022,7 +993,7 @@ pub trait TypeWalk {
1022 { 993 {
1023 self.walk_mut_binders( 994 self.walk_mut_binders(
1024 &mut |ty, binders| { 995 &mut |ty, binders| {
1025 if let &mut TyKind::BoundVar(bound) = &mut ty.0 { 996 if let &mut TyKind::BoundVar(bound) = ty.interned_mut() {
1026 if bound.debruijn >= binders { 997 if bound.debruijn >= binders {
1027 *ty = substs.0[bound.index].clone().shift_bound_vars(binders); 998 *ty = substs.0[bound.index].clone().shift_bound_vars(binders);
1028 } 999 }
@@ -1039,7 +1010,7 @@ pub trait TypeWalk {
1039 Self: Sized, 1010 Self: Sized,
1040 { 1011 {
1041 self.fold_binders( 1012 self.fold_binders(
1042 &mut |ty, binders| match &ty.0 { 1013 &mut |ty, binders| match ty.interned(&Interner) {
1043 TyKind::BoundVar(bound) if bound.debruijn >= binders => { 1014 TyKind::BoundVar(bound) if bound.debruijn >= binders => {
1044 TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner) 1015 TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner)
1045 } 1016 }
@@ -1068,6 +1039,9 @@ impl TypeWalk for Ty {
1068 p.walk(f); 1039 p.walk(f);
1069 } 1040 }
1070 } 1041 }
1042 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => {
1043 ty.walk(f);
1044 }
1071 _ => { 1045 _ => {
1072 if let Some(substs) = self.substs() { 1046 if let Some(substs) = self.substs() {
1073 for t in substs.iter() { 1047 for t in substs.iter() {
@@ -1084,7 +1058,7 @@ impl TypeWalk for Ty {
1084 f: &mut impl FnMut(&mut Ty, DebruijnIndex), 1058 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
1085 binders: DebruijnIndex, 1059 binders: DebruijnIndex,
1086 ) { 1060 ) {
1087 match &mut self.0 { 1061 match self.interned_mut() {
1088 TyKind::Alias(AliasTy::Projection(p_ty)) => { 1062 TyKind::Alias(AliasTy::Projection(p_ty)) => {
1089 p_ty.substitution.walk_mut_binders(f, binders); 1063 p_ty.substitution.walk_mut_binders(f, binders);
1090 } 1064 }
@@ -1096,6 +1070,9 @@ impl TypeWalk for Ty {
1096 TyKind::Alias(AliasTy::Opaque(o_ty)) => { 1070 TyKind::Alias(AliasTy::Opaque(o_ty)) => {
1097 o_ty.substitution.walk_mut_binders(f, binders); 1071 o_ty.substitution.walk_mut_binders(f, binders);
1098 } 1072 }
1073 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => {
1074 ty.walk_mut_binders(f, binders);
1075 }
1099 _ => { 1076 _ => {
1100 if let Some(substs) = self.substs_mut() { 1077 if let Some(substs) = self.substs_mut() {
1101 substs.walk_mut_binders(f, binders); 1078 substs.walk_mut_binders(f, binders);
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index d026310f4..b4c650fa1 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -160,21 +160,19 @@ impl<'a> TyLoweringContext<'a> {
160 } 160 }
161 TypeRef::RawPtr(inner, mutability) => { 161 TypeRef::RawPtr(inner, mutability) => {
162 let inner_ty = self.lower_ty(inner); 162 let inner_ty = self.lower_ty(inner);
163 TyKind::Raw(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) 163 TyKind::Raw(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner)
164 .intern(&Interner)
165 } 164 }
166 TypeRef::Array(inner) => { 165 TypeRef::Array(inner) => {
167 let inner_ty = self.lower_ty(inner); 166 let inner_ty = self.lower_ty(inner);
168 TyKind::Array(Substs::single(inner_ty)).intern(&Interner) 167 TyKind::Array(inner_ty).intern(&Interner)
169 } 168 }
170 TypeRef::Slice(inner) => { 169 TypeRef::Slice(inner) => {
171 let inner_ty = self.lower_ty(inner); 170 let inner_ty = self.lower_ty(inner);
172 TyKind::Slice(Substs::single(inner_ty)).intern(&Interner) 171 TyKind::Slice(inner_ty).intern(&Interner)
173 } 172 }
174 TypeRef::Reference(inner, _, mutability) => { 173 TypeRef::Reference(inner, _, mutability) => {
175 let inner_ty = self.lower_ty(inner); 174 let inner_ty = self.lower_ty(inner);
176 TyKind::Ref(lower_to_chalk_mutability(*mutability), Substs::single(inner_ty)) 175 TyKind::Ref(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner)
177 .intern(&Interner)
178 } 176 }
179 TypeRef::Placeholder => TyKind::Unknown.intern(&Interner), 177 TypeRef::Placeholder => TyKind::Unknown.intern(&Interner),
180 TypeRef::Fn(params, is_varargs) => { 178 TypeRef::Fn(params, is_varargs) => {
@@ -993,7 +991,7 @@ pub(crate) fn generic_defaults_query(
993 991
994 // Each default can only refer to previous parameters. 992 // Each default can only refer to previous parameters.
995 ty.walk_mut_binders( 993 ty.walk_mut_binders(
996 &mut |ty, binders| match &mut ty.0 { 994 &mut |ty, binders| match ty.interned_mut() {
997 TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => { 995 TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => {
998 if *index >= idx { 996 if *index >= idx {
999 // type variable default referring to parameter coming 997 // type variable default referring to parameter coming
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 57f37ef4b..be72c4a1c 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -443,8 +443,7 @@ fn iterate_method_candidates_with_autoref(
443 } 443 }
444 let refed = Canonical { 444 let refed = Canonical {
445 kinds: deref_chain[0].kinds.clone(), 445 kinds: deref_chain[0].kinds.clone(),
446 value: TyKind::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone())) 446 value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner),
447 .intern(&Interner),
448 }; 447 };
449 if iterate_method_candidates_by_receiver( 448 if iterate_method_candidates_by_receiver(
450 &refed, 449 &refed,
@@ -460,8 +459,7 @@ fn iterate_method_candidates_with_autoref(
460 } 459 }
461 let ref_muted = Canonical { 460 let ref_muted = Canonical {
462 kinds: deref_chain[0].kinds.clone(), 461 kinds: deref_chain[0].kinds.clone(),
463 value: TyKind::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone())) 462 value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner),
464 .intern(&Interner),
465 }; 463 };
466 if iterate_method_candidates_by_receiver( 464 if iterate_method_candidates_by_receiver(
467 &ref_muted, 465 &ref_muted,
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 05a4bf0df..6a8b6752e 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -24,9 +24,9 @@ use super::*;
24impl ToChalk for Ty { 24impl ToChalk for Ty {
25 type Chalk = chalk_ir::Ty<Interner>; 25 type Chalk = chalk_ir::Ty<Interner>;
26 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { 26 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
27 match self.0 { 27 match self.into_inner() {
28 TyKind::Ref(m, parameters) => ref_to_chalk(db, m, parameters), 28 TyKind::Ref(m, ty) => ref_to_chalk(db, m, ty),
29 TyKind::Array(parameters) => array_to_chalk(db, parameters), 29 TyKind::Array(ty) => array_to_chalk(db, ty),
30 TyKind::Function(FnPointer { sig, substs, .. }) => { 30 TyKind::Function(FnPointer { sig, substs, .. }) => {
31 let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner)); 31 let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner));
32 chalk_ir::TyKind::Function(chalk_ir::FnPointer { 32 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
@@ -54,13 +54,11 @@ impl ToChalk for Ty {
54 let substitution = substs.to_chalk(db); 54 let substitution = substs.to_chalk(db);
55 chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner) 55 chalk_ir::TyKind::Tuple(cardinality.into(), substitution).intern(&Interner)
56 } 56 }
57 TyKind::Raw(mutability, substs) => { 57 TyKind::Raw(mutability, ty) => {
58 let ty = substs[0].clone().to_chalk(db); 58 let ty = ty.to_chalk(db);
59 chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner) 59 chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner)
60 } 60 }
61 TyKind::Slice(substs) => { 61 TyKind::Slice(ty) => chalk_ir::TyKind::Slice(ty.to_chalk(db)).intern(&Interner),
62 chalk_ir::TyKind::Slice(substs[0].clone().to_chalk(db)).intern(&Interner)
63 }
64 TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner), 62 TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner),
65 TyKind::FnDef(id, substs) => { 63 TyKind::FnDef(id, substs) => {
66 let substitution = substs.to_chalk(db); 64 let substitution = substs.to_chalk(db);
@@ -114,7 +112,7 @@ impl ToChalk for Ty {
114 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { 112 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
115 match chalk.data(&Interner).kind.clone() { 113 match chalk.data(&Interner).kind.clone() {
116 chalk_ir::TyKind::Error => TyKind::Unknown, 114 chalk_ir::TyKind::Error => TyKind::Unknown,
117 chalk_ir::TyKind::Array(ty, _size) => TyKind::Array(Substs::single(from_chalk(db, ty))), 115 chalk_ir::TyKind::Array(ty, _size) => TyKind::Array(from_chalk(db, ty)),
118 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx), 116 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx),
119 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => { 117 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
120 let associated_ty = proj.associated_ty_id; 118 let associated_ty = proj.associated_ty_id;
@@ -168,12 +166,10 @@ impl ToChalk for Ty {
168 chalk_ir::TyKind::Tuple(cardinality, subst) => { 166 chalk_ir::TyKind::Tuple(cardinality, subst) => {
169 TyKind::Tuple(cardinality, from_chalk(db, subst)) 167 TyKind::Tuple(cardinality, from_chalk(db, subst))
170 } 168 }
171 chalk_ir::TyKind::Raw(mutability, ty) => { 169 chalk_ir::TyKind::Raw(mutability, ty) => TyKind::Raw(mutability, from_chalk(db, ty)),
172 TyKind::Raw(mutability, Substs::single(from_chalk(db, ty))) 170 chalk_ir::TyKind::Slice(ty) => TyKind::Slice(from_chalk(db, ty)),
173 }
174 chalk_ir::TyKind::Slice(ty) => TyKind::Slice(Substs::single(from_chalk(db, ty))),
175 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => { 171 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => {
176 TyKind::Ref(mutability, Substs::single(from_chalk(db, ty))) 172 TyKind::Ref(mutability, from_chalk(db, ty))
177 } 173 }
178 chalk_ir::TyKind::Str => TyKind::Str, 174 chalk_ir::TyKind::Str => TyKind::Str,
179 chalk_ir::TyKind::Never => TyKind::Never, 175 chalk_ir::TyKind::Never => TyKind::Never,
@@ -197,17 +193,17 @@ impl ToChalk for Ty {
197fn ref_to_chalk( 193fn ref_to_chalk(
198 db: &dyn HirDatabase, 194 db: &dyn HirDatabase,
199 mutability: chalk_ir::Mutability, 195 mutability: chalk_ir::Mutability,
200 subst: Substs, 196 ty: Ty,
201) -> chalk_ir::Ty<Interner> { 197) -> chalk_ir::Ty<Interner> {
202 let arg = subst[0].clone().to_chalk(db); 198 let arg = ty.to_chalk(db);
203 let lifetime = LifetimeData::Static.intern(&Interner); 199 let lifetime = LifetimeData::Static.intern(&Interner);
204 chalk_ir::TyKind::Ref(mutability, lifetime, arg).intern(&Interner) 200 chalk_ir::TyKind::Ref(mutability, lifetime, arg).intern(&Interner)
205} 201}
206 202
207/// We currently don't model constants, but Chalk does. So, we have to insert a 203/// We currently don't model constants, but Chalk does. So, we have to insert a
208/// fake constant here, because Chalks built-in logic may expect it to be there. 204/// fake constant here, because Chalks built-in logic may expect it to be there.
209fn array_to_chalk(db: &dyn HirDatabase, subst: Substs) -> chalk_ir::Ty<Interner> { 205fn array_to_chalk(db: &dyn HirDatabase, ty: Ty) -> chalk_ir::Ty<Interner> {
210 let arg = subst[0].clone().to_chalk(db); 206 let arg = ty.to_chalk(db);
211 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner); 207 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
212 let const_ = chalk_ir::ConstData { 208 let const_ = chalk_ir::ConstData {
213 ty: usize_ty, 209 ty: usize_ty,
diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs
index 2e8e82b70..72492f826 100644
--- a/crates/ide/src/annotations.rs
+++ b/crates/ide/src/annotations.rs
@@ -1,12 +1,13 @@
1use hir::Semantics; 1use either::Either;
2use hir::{HasSource, Semantics};
2use ide_db::{ 3use ide_db::{
3 base_db::{FileId, FilePosition, FileRange, SourceDatabase}, 4 base_db::{FileId, FilePosition, FileRange},
4 RootDatabase, SymbolKind, 5 helpers::visit_file_defs,
6 RootDatabase,
5}; 7};
6use syntax::TextRange; 8use syntax::{ast::NameOwner, AstNode, TextRange, TextSize};
7 9
8use crate::{ 10use crate::{
9 file_structure::file_structure,
10 fn_references::find_all_methods, 11 fn_references::find_all_methods,
11 goto_implementation::goto_implementation, 12 goto_implementation::goto_implementation,
12 references::find_all_refs, 13 references::find_all_refs,
@@ -75,39 +76,56 @@ pub(crate) fn annotations(
75 } 76 }
76 } 77 }
77 78
78 file_structure(&db.parse(file_id).tree()) 79 visit_file_defs(&Semantics::new(db), file_id, &mut |def| match def {
79 .into_iter() 80 Either::Left(def) => {
80 .filter(|node| { 81 let node = match def {
81 matches!( 82 hir::ModuleDef::Const(konst) => {
82 node.kind, 83 konst.source(db).and_then(|node| range_and_position_of(&node.value))
83 SymbolKind::Trait 84 }
84 | SymbolKind::Struct 85 hir::ModuleDef::Trait(trait_) => {
85 | SymbolKind::Enum 86 trait_.source(db).and_then(|node| range_and_position_of(&node.value))
86 | SymbolKind::Union 87 }
87 | SymbolKind::Const 88 hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => {
88 ) 89 strukt.source(db).and_then(|node| range_and_position_of(&node.value))
89 }) 90 }
90 .for_each(|node| { 91 hir::ModuleDef::Adt(hir::Adt::Enum(enum_)) => {
91 if config.annotate_impls && node.kind != SymbolKind::Const { 92 enum_.source(db).and_then(|node| range_and_position_of(&node.value))
93 }
94 hir::ModuleDef::Adt(hir::Adt::Union(union)) => {
95 union.source(db).and_then(|node| range_and_position_of(&node.value))
96 }
97 _ => None,
98 };
99 let (offset, range) = match node {
100 Some(node) => node,
101 None => return,
102 };
103
104 if config.annotate_impls && !matches!(def, hir::ModuleDef::Const(_)) {
92 annotations.push(Annotation { 105 annotations.push(Annotation {
93 range: node.node_range, 106 range,
94 kind: AnnotationKind::HasImpls { 107 kind: AnnotationKind::HasImpls {
95 position: FilePosition { file_id, offset: node.navigation_range.start() }, 108 position: FilePosition { file_id, offset },
96 data: None, 109 data: None,
97 }, 110 },
98 }); 111 });
99 } 112 }
100
101 if config.annotate_references { 113 if config.annotate_references {
102 annotations.push(Annotation { 114 annotations.push(Annotation {
103 range: node.node_range, 115 range,
104 kind: AnnotationKind::HasReferences { 116 kind: AnnotationKind::HasReferences {
105 position: FilePosition { file_id, offset: node.navigation_range.start() }, 117 position: FilePosition { file_id, offset },
106 data: None, 118 data: None,
107 }, 119 },
108 }); 120 });
109 } 121 }
110 }); 122
123 fn range_and_position_of(node: &dyn NameOwner) -> Option<(TextSize, TextRange)> {
124 Some((node.name()?.syntax().text_range().start(), node.syntax().text_range()))
125 }
126 }
127 Either::Right(_) => (),
128 });
111 129
112 if config.annotate_method_references { 130 if config.annotate_method_references {
113 annotations.extend(find_all_methods(db, file_id).into_iter().map(|method| Annotation { 131 annotations.extend(find_all_methods(db, file_id).into_iter().map(|method| Annotation {
@@ -934,4 +952,19 @@ mod tests {
934 "#]], 952 "#]],
935 ); 953 );
936 } 954 }
955
956 #[test]
957 fn test_no_annotations_outside_module_tree() {
958 check(
959 r#"
960//- /foo.rs
961struct Foo;
962//- /lib.rs
963// this file comes last since `check` checks the first file only
964"#,
965 expect![[r#"
966 []
967 "#]],
968 );
969 }
937} 970}
diff --git a/crates/ide/src/file_structure.rs b/crates/ide/src/file_structure.rs
index 26793bdb4..9f879a66e 100644
--- a/crates/ide/src/file_structure.rs
+++ b/crates/ide/src/file_structure.rs
@@ -1,7 +1,8 @@
1use ide_db::SymbolKind; 1use ide_db::SymbolKind;
2use syntax::{ 2use syntax::{
3 ast::{self, AttrsOwner, GenericParamsOwner, NameOwner}, 3 ast::{self, AttrsOwner, GenericParamsOwner, NameOwner},
4 match_ast, AstNode, SourceFile, SyntaxNode, TextRange, WalkEvent, 4 match_ast, AstNode, AstToken, NodeOrToken, SourceFile, SyntaxNode, SyntaxToken, TextRange,
5 WalkEvent,
5}; 6};
6 7
7#[derive(Debug, Clone)] 8#[derive(Debug, Clone)]
@@ -10,11 +11,17 @@ pub struct StructureNode {
10 pub label: String, 11 pub label: String,
11 pub navigation_range: TextRange, 12 pub navigation_range: TextRange,
12 pub node_range: TextRange, 13 pub node_range: TextRange,
13 pub kind: SymbolKind, 14 pub kind: StructureNodeKind,
14 pub detail: Option<String>, 15 pub detail: Option<String>,
15 pub deprecated: bool, 16 pub deprecated: bool,
16} 17}
17 18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
20pub enum StructureNodeKind {
21 SymbolKind(SymbolKind),
22 Region,
23}
24
18// Feature: File Structure 25// Feature: File Structure
19// 26//
20// Provides a tree of the symbols defined in the file. Can be used to 27// Provides a tree of the symbols defined in the file. Can be used to
@@ -32,34 +39,46 @@ pub(crate) fn file_structure(file: &SourceFile) -> Vec<StructureNode> {
32 let mut res = Vec::new(); 39 let mut res = Vec::new();
33 let mut stack = Vec::new(); 40 let mut stack = Vec::new();
34 41
35 for event in file.syntax().preorder() { 42 for event in file.syntax().preorder_with_tokens() {
36 match event { 43 match event {
37 WalkEvent::Enter(node) => { 44 WalkEvent::Enter(NodeOrToken::Node(node)) => {
38 if let Some(mut symbol) = structure_node(&node) { 45 if let Some(mut symbol) = structure_node(&node) {
39 symbol.parent = stack.last().copied(); 46 symbol.parent = stack.last().copied();
40 stack.push(res.len()); 47 stack.push(res.len());
41 res.push(symbol); 48 res.push(symbol);
42 } 49 }
43 } 50 }
44 WalkEvent::Leave(node) => { 51 WalkEvent::Leave(NodeOrToken::Node(node)) => {
45 if structure_node(&node).is_some() { 52 if structure_node(&node).is_some() {
46 stack.pop().unwrap(); 53 stack.pop().unwrap();
47 } 54 }
48 } 55 }
56 WalkEvent::Enter(NodeOrToken::Token(token)) => {
57 if let Some(mut symbol) = structure_token(token) {
58 symbol.parent = stack.last().copied();
59 stack.push(res.len());
60 res.push(symbol);
61 }
62 }
63 WalkEvent::Leave(NodeOrToken::Token(token)) => {
64 if structure_token(token).is_some() {
65 stack.pop().unwrap();
66 }
67 }
49 } 68 }
50 } 69 }
51 res 70 res
52} 71}
53 72
54fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { 73fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
55 fn decl<N: NameOwner + AttrsOwner>(node: N, kind: SymbolKind) -> Option<StructureNode> { 74 fn decl<N: NameOwner + AttrsOwner>(node: N, kind: StructureNodeKind) -> Option<StructureNode> {
56 decl_with_detail(&node, None, kind) 75 decl_with_detail(&node, None, kind)
57 } 76 }
58 77
59 fn decl_with_type_ref<N: NameOwner + AttrsOwner>( 78 fn decl_with_type_ref<N: NameOwner + AttrsOwner>(
60 node: &N, 79 node: &N,
61 type_ref: Option<ast::Type>, 80 type_ref: Option<ast::Type>,
62 kind: SymbolKind, 81 kind: StructureNodeKind,
63 ) -> Option<StructureNode> { 82 ) -> Option<StructureNode> {
64 let detail = type_ref.map(|type_ref| { 83 let detail = type_ref.map(|type_ref| {
65 let mut detail = String::new(); 84 let mut detail = String::new();
@@ -72,7 +91,7 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
72 fn decl_with_detail<N: NameOwner + AttrsOwner>( 91 fn decl_with_detail<N: NameOwner + AttrsOwner>(
73 node: &N, 92 node: &N,
74 detail: Option<String>, 93 detail: Option<String>,
75 kind: SymbolKind, 94 kind: StructureNodeKind,
76 ) -> Option<StructureNode> { 95 ) -> Option<StructureNode> {
77 let name = node.name()?; 96 let name = node.name()?;
78 97
@@ -120,18 +139,18 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
120 collapse_ws(ret_type.syntax(), &mut detail); 139 collapse_ws(ret_type.syntax(), &mut detail);
121 } 140 }
122 141
123 decl_with_detail(&it, Some(detail), SymbolKind::Function) 142 decl_with_detail(&it, Some(detail), StructureNodeKind::SymbolKind(SymbolKind::Function))
124 }, 143 },
125 ast::Struct(it) => decl(it, SymbolKind::Struct), 144 ast::Struct(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Struct)),
126 ast::Union(it) => decl(it, SymbolKind::Union), 145 ast::Union(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Union)),
127 ast::Enum(it) => decl(it, SymbolKind::Enum), 146 ast::Enum(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Enum)),
128 ast::Variant(it) => decl(it, SymbolKind::Variant), 147 ast::Variant(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Variant)),
129 ast::Trait(it) => decl(it, SymbolKind::Trait), 148 ast::Trait(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Trait)),
130 ast::Module(it) => decl(it, SymbolKind::Module), 149 ast::Module(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Module)),
131 ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::TypeAlias), 150 ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty(), StructureNodeKind::SymbolKind(SymbolKind::TypeAlias)),
132 ast::RecordField(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::Field), 151 ast::RecordField(it) => decl_with_type_ref(&it, it.ty(), StructureNodeKind::SymbolKind(SymbolKind::Field)),
133 ast::Const(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::Const), 152 ast::Const(it) => decl_with_type_ref(&it, it.ty(), StructureNodeKind::SymbolKind(SymbolKind::Const)),
134 ast::Static(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::Static), 153 ast::Static(it) => decl_with_type_ref(&it, it.ty(), StructureNodeKind::SymbolKind(SymbolKind::Static)),
135 ast::Impl(it) => { 154 ast::Impl(it) => {
136 let target_type = it.self_ty()?; 155 let target_type = it.self_ty()?;
137 let target_trait = it.trait_(); 156 let target_trait = it.trait_();
@@ -147,18 +166,38 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
147 label, 166 label,
148 navigation_range: target_type.syntax().text_range(), 167 navigation_range: target_type.syntax().text_range(),
149 node_range: it.syntax().text_range(), 168 node_range: it.syntax().text_range(),
150 kind: SymbolKind::Impl, 169 kind: StructureNodeKind::SymbolKind(SymbolKind::Impl),
151 detail: None, 170 detail: None,
152 deprecated: false, 171 deprecated: false,
153 }; 172 };
154 Some(node) 173 Some(node)
155 }, 174 },
156 ast::MacroRules(it) => decl(it, SymbolKind::Macro), 175 ast::MacroRules(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Macro)),
157 _ => None, 176 _ => None,
158 } 177 }
159 } 178 }
160} 179}
161 180
181fn structure_token(token: SyntaxToken) -> Option<StructureNode> {
182 if let Some(comment) = ast::Comment::cast(token) {
183 let text = comment.text().trim();
184
185 if let Some(region_name) = text.strip_prefix("// region:").map(str::trim) {
186 return Some(StructureNode {
187 parent: None,
188 label: region_name.to_string(),
189 navigation_range: comment.syntax().text_range(),
190 node_range: comment.syntax().text_range(),
191 kind: StructureNodeKind::Region,
192 detail: None,
193 deprecated: false,
194 });
195 }
196 }
197
198 None
199}
200
162#[cfg(test)] 201#[cfg(test)]
163mod tests { 202mod tests {
164 use expect_test::{expect, Expect}; 203 use expect_test::{expect, Expect};
@@ -217,6 +256,16 @@ fn obsolete() {}
217 256
218#[deprecated(note = "for awhile")] 257#[deprecated(note = "for awhile")]
219fn very_obsolete() {} 258fn very_obsolete() {}
259
260// region: Some region name
261// endregion
262
263// region: dontpanic
264mod m {
265fn f() {}
266// endregion
267fn g() {}
268}
220"#, 269"#,
221 expect![[r#" 270 expect![[r#"
222 [ 271 [
@@ -225,7 +274,9 @@ fn very_obsolete() {}
225 label: "Foo", 274 label: "Foo",
226 navigation_range: 8..11, 275 navigation_range: 8..11,
227 node_range: 1..26, 276 node_range: 1..26,
228 kind: Struct, 277 kind: SymbolKind(
278 Struct,
279 ),
229 detail: None, 280 detail: None,
230 deprecated: false, 281 deprecated: false,
231 }, 282 },
@@ -236,7 +287,9 @@ fn very_obsolete() {}
236 label: "x", 287 label: "x",
237 navigation_range: 18..19, 288 navigation_range: 18..19,
238 node_range: 18..24, 289 node_range: 18..24,
239 kind: Field, 290 kind: SymbolKind(
291 Field,
292 ),
240 detail: Some( 293 detail: Some(
241 "i32", 294 "i32",
242 ), 295 ),
@@ -247,7 +300,9 @@ fn very_obsolete() {}
247 label: "m", 300 label: "m",
248 navigation_range: 32..33, 301 navigation_range: 32..33,
249 node_range: 28..158, 302 node_range: 28..158,
250 kind: Module, 303 kind: SymbolKind(
304 Module,
305 ),
251 detail: None, 306 detail: None,
252 deprecated: false, 307 deprecated: false,
253 }, 308 },
@@ -258,7 +313,9 @@ fn very_obsolete() {}
258 label: "bar1", 313 label: "bar1",
259 navigation_range: 43..47, 314 navigation_range: 43..47,
260 node_range: 40..52, 315 node_range: 40..52,
261 kind: Function, 316 kind: SymbolKind(
317 Function,
318 ),
262 detail: Some( 319 detail: Some(
263 "fn()", 320 "fn()",
264 ), 321 ),
@@ -271,7 +328,9 @@ fn very_obsolete() {}
271 label: "bar2", 328 label: "bar2",
272 navigation_range: 60..64, 329 navigation_range: 60..64,
273 node_range: 57..81, 330 node_range: 57..81,
274 kind: Function, 331 kind: SymbolKind(
332 Function,
333 ),
275 detail: Some( 334 detail: Some(
276 "fn<T>(t: T) -> T", 335 "fn<T>(t: T) -> T",
277 ), 336 ),
@@ -284,7 +343,9 @@ fn very_obsolete() {}
284 label: "bar3", 343 label: "bar3",
285 navigation_range: 89..93, 344 navigation_range: 89..93,
286 node_range: 86..156, 345 node_range: 86..156,
287 kind: Function, 346 kind: SymbolKind(
347 Function,
348 ),
288 detail: Some( 349 detail: Some(
289 "fn<A, B>(a: A, b: B) -> Vec< u32 >", 350 "fn<A, B>(a: A, b: B) -> Vec< u32 >",
290 ), 351 ),
@@ -295,7 +356,9 @@ fn very_obsolete() {}
295 label: "E", 356 label: "E",
296 navigation_range: 165..166, 357 navigation_range: 165..166,
297 node_range: 160..180, 358 node_range: 160..180,
298 kind: Enum, 359 kind: SymbolKind(
360 Enum,
361 ),
299 detail: None, 362 detail: None,
300 deprecated: false, 363 deprecated: false,
301 }, 364 },
@@ -306,7 +369,9 @@ fn very_obsolete() {}
306 label: "X", 369 label: "X",
307 navigation_range: 169..170, 370 navigation_range: 169..170,
308 node_range: 169..170, 371 node_range: 169..170,
309 kind: Variant, 372 kind: SymbolKind(
373 Variant,
374 ),
310 detail: None, 375 detail: None,
311 deprecated: false, 376 deprecated: false,
312 }, 377 },
@@ -317,7 +382,9 @@ fn very_obsolete() {}
317 label: "Y", 382 label: "Y",
318 navigation_range: 172..173, 383 navigation_range: 172..173,
319 node_range: 172..178, 384 node_range: 172..178,
320 kind: Variant, 385 kind: SymbolKind(
386 Variant,
387 ),
321 detail: None, 388 detail: None,
322 deprecated: false, 389 deprecated: false,
323 }, 390 },
@@ -326,7 +393,9 @@ fn very_obsolete() {}
326 label: "T", 393 label: "T",
327 navigation_range: 186..187, 394 navigation_range: 186..187,
328 node_range: 181..193, 395 node_range: 181..193,
329 kind: TypeAlias, 396 kind: SymbolKind(
397 TypeAlias,
398 ),
330 detail: Some( 399 detail: Some(
331 "()", 400 "()",
332 ), 401 ),
@@ -337,7 +406,9 @@ fn very_obsolete() {}
337 label: "S", 406 label: "S",
338 navigation_range: 201..202, 407 navigation_range: 201..202,
339 node_range: 194..213, 408 node_range: 194..213,
340 kind: Static, 409 kind: SymbolKind(
410 Static,
411 ),
341 detail: Some( 412 detail: Some(
342 "i32", 413 "i32",
343 ), 414 ),
@@ -348,7 +419,9 @@ fn very_obsolete() {}
348 label: "C", 419 label: "C",
349 navigation_range: 220..221, 420 navigation_range: 220..221,
350 node_range: 214..232, 421 node_range: 214..232,
351 kind: Const, 422 kind: SymbolKind(
423 Const,
424 ),
352 detail: Some( 425 detail: Some(
353 "i32", 426 "i32",
354 ), 427 ),
@@ -359,7 +432,9 @@ fn very_obsolete() {}
359 label: "impl E", 432 label: "impl E",
360 navigation_range: 239..240, 433 navigation_range: 239..240,
361 node_range: 234..243, 434 node_range: 234..243,
362 kind: Impl, 435 kind: SymbolKind(
436 Impl,
437 ),
363 detail: None, 438 detail: None,
364 deprecated: false, 439 deprecated: false,
365 }, 440 },
@@ -368,7 +443,9 @@ fn very_obsolete() {}
368 label: "impl fmt::Debug for E", 443 label: "impl fmt::Debug for E",
369 navigation_range: 265..266, 444 navigation_range: 265..266,
370 node_range: 245..269, 445 node_range: 245..269,
371 kind: Impl, 446 kind: SymbolKind(
447 Impl,
448 ),
372 detail: None, 449 detail: None,
373 deprecated: false, 450 deprecated: false,
374 }, 451 },
@@ -377,7 +454,9 @@ fn very_obsolete() {}
377 label: "mc", 454 label: "mc",
378 navigation_range: 284..286, 455 navigation_range: 284..286,
379 node_range: 271..303, 456 node_range: 271..303,
380 kind: Macro, 457 kind: SymbolKind(
458 Macro,
459 ),
381 detail: None, 460 detail: None,
382 deprecated: false, 461 deprecated: false,
383 }, 462 },
@@ -386,7 +465,9 @@ fn very_obsolete() {}
386 label: "mcexp", 465 label: "mcexp",
387 navigation_range: 334..339, 466 navigation_range: 334..339,
388 node_range: 305..356, 467 node_range: 305..356,
389 kind: Macro, 468 kind: SymbolKind(
469 Macro,
470 ),
390 detail: None, 471 detail: None,
391 deprecated: false, 472 deprecated: false,
392 }, 473 },
@@ -395,7 +476,9 @@ fn very_obsolete() {}
395 label: "mcexp", 476 label: "mcexp",
396 navigation_range: 387..392, 477 navigation_range: 387..392,
397 node_range: 358..409, 478 node_range: 358..409,
398 kind: Macro, 479 kind: SymbolKind(
480 Macro,
481 ),
399 detail: None, 482 detail: None,
400 deprecated: false, 483 deprecated: false,
401 }, 484 },
@@ -404,7 +487,9 @@ fn very_obsolete() {}
404 label: "obsolete", 487 label: "obsolete",
405 navigation_range: 428..436, 488 navigation_range: 428..436,
406 node_range: 411..441, 489 node_range: 411..441,
407 kind: Function, 490 kind: SymbolKind(
491 Function,
492 ),
408 detail: Some( 493 detail: Some(
409 "fn()", 494 "fn()",
410 ), 495 ),
@@ -415,12 +500,75 @@ fn very_obsolete() {}
415 label: "very_obsolete", 500 label: "very_obsolete",
416 navigation_range: 481..494, 501 navigation_range: 481..494,
417 node_range: 443..499, 502 node_range: 443..499,
418 kind: Function, 503 kind: SymbolKind(
504 Function,
505 ),
419 detail: Some( 506 detail: Some(
420 "fn()", 507 "fn()",
421 ), 508 ),
422 deprecated: true, 509 deprecated: true,
423 }, 510 },
511 StructureNode {
512 parent: None,
513 label: "Some region name",
514 navigation_range: 501..528,
515 node_range: 501..528,
516 kind: Region,
517 detail: None,
518 deprecated: false,
519 },
520 StructureNode {
521 parent: None,
522 label: "m",
523 navigation_range: 568..569,
524 node_range: 543..606,
525 kind: SymbolKind(
526 Module,
527 ),
528 detail: None,
529 deprecated: false,
530 },
531 StructureNode {
532 parent: Some(
533 20,
534 ),
535 label: "dontpanic",
536 navigation_range: 543..563,
537 node_range: 543..563,
538 kind: Region,
539 detail: None,
540 deprecated: false,
541 },
542 StructureNode {
543 parent: Some(
544 20,
545 ),
546 label: "f",
547 navigation_range: 575..576,
548 node_range: 572..581,
549 kind: SymbolKind(
550 Function,
551 ),
552 detail: Some(
553 "fn()",
554 ),
555 deprecated: false,
556 },
557 StructureNode {
558 parent: Some(
559 20,
560 ),
561 label: "g",
562 navigation_range: 598..599,
563 node_range: 582..604,
564 kind: SymbolKind(
565 Function,
566 ),
567 detail: Some(
568 "fn()",
569 ),
570 deprecated: false,
571 },
424 ] 572 ]
425 "#]], 573 "#]],
426 ); 574 );
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index abed1969e..e8f31e4b1 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1161,4 +1161,15 @@ struct S;
1161"#, 1161"#,
1162 ) 1162 )
1163 } 1163 }
1164
1165 #[test]
1166 fn goto_incomplete_field() {
1167 check(
1168 r#"
1169struct A { a: u32 }
1170 //^
1171fn foo() { A { a$0: }; }
1172"#,
1173 )
1174 }
1164} 1175}
diff --git a/crates/ide/src/join_lines.rs b/crates/ide/src/join_lines.rs
index 20a920ddb..d571ed559 100644
--- a/crates/ide/src/join_lines.rs
+++ b/crates/ide/src/join_lines.rs
@@ -218,7 +218,7 @@ mod tests {
218 let result = join_lines(&file, range); 218 let result = join_lines(&file, range);
219 219
220 let actual = { 220 let actual = {
221 let mut actual = before.to_string(); 221 let mut actual = before;
222 result.apply(&mut actual); 222 result.apply(&mut actual);
223 actual 223 actual
224 }; 224 };
@@ -622,7 +622,7 @@ fn foo() {
622 let parse = SourceFile::parse(&before); 622 let parse = SourceFile::parse(&before);
623 let result = join_lines(&parse.tree(), sel); 623 let result = join_lines(&parse.tree(), sel);
624 let actual = { 624 let actual = {
625 let mut actual = before.to_string(); 625 let mut actual = before;
626 result.apply(&mut actual); 626 result.apply(&mut actual);
627 actual 627 actual
628 }; 628 };
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index a8b169e87..662da5a96 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -71,7 +71,7 @@ pub use crate::{
71 diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity}, 71 diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity},
72 display::navigation_target::NavigationTarget, 72 display::navigation_target::NavigationTarget,
73 expand_macro::ExpandedMacro, 73 expand_macro::ExpandedMacro,
74 file_structure::StructureNode, 74 file_structure::{StructureNode, StructureNodeKind},
75 folding_ranges::{Fold, FoldKind}, 75 folding_ranges::{Fold, FoldKind},
76 hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult}, 76 hover::{HoverAction, HoverConfig, HoverGotoTypeData, HoverResult},
77 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind}, 77 inlay_hints::{InlayHint, InlayHintsConfig, InlayKind},
@@ -101,7 +101,7 @@ pub use ide_db::{
101 search::{ReferenceAccess, SearchScope}, 101 search::{ReferenceAccess, SearchScope},
102 source_change::{FileSystemEdit, SourceChange}, 102 source_change::{FileSystemEdit, SourceChange},
103 symbol_index::Query, 103 symbol_index::Query,
104 RootDatabase, 104 RootDatabase, SymbolKind,
105}; 105};
106pub use ide_ssr::SsrError; 106pub use ide_ssr::SsrError;
107pub use syntax::{TextRange, TextSize}; 107pub use syntax::{TextRange, TextSize};
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index fef70533d..ec7c7686d 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -29,7 +29,7 @@ use crate::{display::TryToNav, FilePosition, NavigationTarget};
29 29
30#[derive(Debug, Clone)] 30#[derive(Debug, Clone)]
31pub struct ReferenceSearchResult { 31pub struct ReferenceSearchResult {
32 pub declaration: Declaration, 32 pub declaration: Option<Declaration>,
33 pub references: FxHashMap<FileId, Vec<(TextRange, Option<ReferenceAccess>)>>, 33 pub references: FxHashMap<FileId, Vec<(TextRange, Option<ReferenceAccess>)>>,
34} 34}
35 35
@@ -91,10 +91,10 @@ pub(crate) fn find_all_refs(
91 _ => {} 91 _ => {}
92 } 92 }
93 } 93 }
94 let nav = def.try_to_nav(sema.db)?; 94 let declaration = def.try_to_nav(sema.db).map(|nav| {
95 let decl_range = nav.focus_or_full_range(); 95 let decl_range = nav.focus_or_full_range();
96 96 Declaration { nav, access: decl_access(&def, &syntax, decl_range) }
97 let declaration = Declaration { nav, access: decl_access(&def, &syntax, decl_range) }; 97 });
98 let references = usages 98 let references = usages
99 .into_iter() 99 .into_iter()
100 .map(|(file_id, refs)| { 100 .map(|(file_id, refs)| {
@@ -1004,8 +1004,7 @@ impl Foo {
1004 let refs = analysis.find_all_refs(pos, search_scope).unwrap().unwrap(); 1004 let refs = analysis.find_all_refs(pos, search_scope).unwrap().unwrap();
1005 1005
1006 let mut actual = String::new(); 1006 let mut actual = String::new();
1007 { 1007 if let Some(decl) = refs.declaration {
1008 let decl = refs.declaration;
1009 format_to!(actual, "{}", decl.nav.debug_render()); 1008 format_to!(actual, "{}", decl.nav.debug_render());
1010 if let Some(access) = decl.access { 1009 if let Some(access) = decl.access {
1011 format_to!(actual, " {:?}", access) 1010 format_to!(actual, " {:?}", access)
@@ -1258,4 +1257,17 @@ fn main() {
1258 "#]], 1257 "#]],
1259 ); 1258 );
1260 } 1259 }
1260
1261 #[test]
1262 fn test_primitives() {
1263 check(
1264 r#"
1265fn foo(_: bool) -> bo$0ol { true }
1266"#,
1267 expect![[r#"
1268 FileId(0) 10..14
1269 FileId(0) 19..23
1270 "#]],
1271 );
1272 }
1261} 1273}
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 1e378279d..5340b638a 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -510,7 +510,8 @@ fn source_edit_from_def(
510 def: Definition, 510 def: Definition,
511 new_name: &str, 511 new_name: &str,
512) -> RenameResult<(FileId, TextEdit)> { 512) -> RenameResult<(FileId, TextEdit)> {
513 let nav = def.try_to_nav(sema.db).unwrap(); 513 let nav =
514 def.try_to_nav(sema.db).ok_or_else(|| format_err!("No references found at position"))?;
514 515
515 let mut replacement_text = String::new(); 516 let mut replacement_text = String::new();
516 let mut repl_range = nav.focus_or_full_range(); 517 let mut repl_range = nav.focus_or_full_range();
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 27d35de5b..0c7a8fbf8 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -2,11 +2,13 @@ use std::fmt;
2 2
3use ast::NameOwner; 3use ast::NameOwner;
4use cfg::CfgExpr; 4use cfg::CfgExpr;
5use either::Either;
5use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, Semantics}; 6use hir::{AsAssocItem, HasAttrs, HasSource, HirDisplay, Semantics};
6use ide_assists::utils::test_related_attribute; 7use ide_assists::utils::test_related_attribute;
7use ide_db::{ 8use ide_db::{
8 base_db::{FilePosition, FileRange}, 9 base_db::{FilePosition, FileRange},
9 defs::Definition, 10 defs::Definition,
11 helpers::visit_file_defs,
10 search::SearchScope, 12 search::SearchScope,
11 RootDatabase, SymbolKind, 13 RootDatabase, SymbolKind,
12}; 14};
@@ -102,13 +104,27 @@ impl Runnable {
102// |=== 104// |===
103pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> { 105pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
104 let sema = Semantics::new(db); 106 let sema = Semantics::new(db);
105 let module = match sema.to_module_def(file_id) {
106 None => return Vec::new(),
107 Some(it) => it,
108 };
109 107
110 let mut res = Vec::new(); 108 let mut res = Vec::new();
111 runnables_mod(&sema, &mut res, module); 109 visit_file_defs(&sema, file_id, &mut |def| match def {
110 Either::Left(def) => {
111 let runnable = match def {
112 hir::ModuleDef::Module(it) => runnable_mod(&sema, it),
113 hir::ModuleDef::Function(it) => runnable_fn(&sema, it),
114 _ => None,
115 };
116 res.extend(runnable.or_else(|| module_def_doctest(&sema, def)))
117 }
118 Either::Right(impl_) => {
119 res.extend(impl_.items(db).into_iter().filter_map(|assoc| match assoc {
120 hir::AssocItem::Function(it) => {
121 runnable_fn(&sema, it).or_else(|| module_def_doctest(&sema, it.into()))
122 }
123 hir::AssocItem::Const(it) => module_def_doctest(&sema, it.into()),
124 hir::AssocItem::TypeAlias(it) => module_def_doctest(&sema, it.into()),
125 }))
126 }
127 });
112 res 128 res
113} 129}
114 130
@@ -211,39 +227,6 @@ fn parent_test_module(sema: &Semantics<RootDatabase>, fn_def: &ast::Fn) -> Optio
211 }) 227 })
212} 228}
213 229
214fn runnables_mod(sema: &Semantics<RootDatabase>, acc: &mut Vec<Runnable>, module: hir::Module) {
215 acc.extend(module.declarations(sema.db).into_iter().filter_map(|def| {
216 let runnable = match def {
217 hir::ModuleDef::Module(it) => runnable_mod(&sema, it),
218 hir::ModuleDef::Function(it) => runnable_fn(&sema, it),
219 _ => None,
220 };
221 runnable.or_else(|| module_def_doctest(&sema, def))
222 }));
223
224 acc.extend(module.impl_defs(sema.db).into_iter().flat_map(|it| it.items(sema.db)).filter_map(
225 |def| match def {
226 hir::AssocItem::Function(it) => {
227 runnable_fn(&sema, it).or_else(|| module_def_doctest(&sema, it.into()))
228 }
229 hir::AssocItem::Const(it) => module_def_doctest(&sema, it.into()),
230 hir::AssocItem::TypeAlias(it) => module_def_doctest(&sema, it.into()),
231 },
232 ));
233
234 for def in module.declarations(sema.db) {
235 if let hir::ModuleDef::Module(submodule) = def {
236 match submodule.definition_source(sema.db).value {
237 hir::ModuleSource::Module(_) => runnables_mod(sema, acc, submodule),
238 hir::ModuleSource::SourceFile(_) => {
239 cov_mark::hit!(dont_recurse_in_outline_submodules)
240 }
241 hir::ModuleSource::BlockExpr(_) => {} // inner items aren't runnable
242 }
243 }
244 }
245}
246
247pub(crate) fn runnable_fn(sema: &Semantics<RootDatabase>, def: hir::Function) -> Option<Runnable> { 230pub(crate) fn runnable_fn(sema: &Semantics<RootDatabase>, def: hir::Function) -> Option<Runnable> {
248 let func = def.source(sema.db)?; 231 let func = def.source(sema.db)?;
249 let name_string = def.name(sema.db).to_string(); 232 let name_string = def.name(sema.db).to_string();
@@ -1178,7 +1161,6 @@ mod tests {
1178 1161
1179 #[test] 1162 #[test]
1180 fn dont_recurse_in_outline_submodules() { 1163 fn dont_recurse_in_outline_submodules() {
1181 cov_mark::check!(dont_recurse_in_outline_submodules);
1182 check( 1164 check(
1183 r#" 1165 r#"
1184//- /lib.rs 1166//- /lib.rs
diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs
index e3c3aebac..a718faf63 100644
--- a/crates/ide/src/typing.rs
+++ b/crates/ide/src/typing.rs
@@ -145,9 +145,8 @@ mod tests {
145 use super::*; 145 use super::*;
146 146
147 fn do_type_char(char_typed: char, before: &str) -> Option<String> { 147 fn do_type_char(char_typed: char, before: &str) -> Option<String> {
148 let (offset, before) = extract_offset(before); 148 let (offset, mut before) = extract_offset(before);
149 let edit = TextEdit::insert(offset, char_typed.to_string()); 149 let edit = TextEdit::insert(offset, char_typed.to_string());
150 let mut before = before.to_string();
151 edit.apply(&mut before); 150 edit.apply(&mut before);
152 let parse = SourceFile::parse(&before); 151 let parse = SourceFile::parse(&before);
153 on_char_typed_inner(&parse.tree(), offset, char_typed).map(|it| { 152 on_char_typed_inner(&parse.tree(), offset, char_typed).map(|it| {
diff --git a/crates/ide_completion/src/completions/postfix/format_like.rs b/crates/ide_completion/src/completions/postfix/format_like.rs
index 3afc63021..cee4eec10 100644
--- a/crates/ide_completion/src/completions/postfix/format_like.rs
+++ b/crates/ide_completion/src/completions/postfix/format_like.rs
@@ -59,7 +59,7 @@ pub(crate) fn add_format_like_completions(
59/// Checks whether provided item is a string literal. 59/// Checks whether provided item is a string literal.
60fn string_literal_contents(item: &ast::String) -> Option<String> { 60fn string_literal_contents(item: &ast::String) -> Option<String> {
61 let item = item.text(); 61 let item = item.text();
62 if item.len() >= 2 && item.starts_with("\"") && item.ends_with("\"") { 62 if item.len() >= 2 && item.starts_with('\"') && item.ends_with('\"') {
63 return Some(item[1..item.len() - 1].to_owned()); 63 return Some(item[1..item.len() - 1].to_owned());
64 } 64 }
65 65
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 17d9a3adf..89e9bda78 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -35,6 +35,7 @@ pub(crate) struct CompletionContext<'a> {
35 /// The token before the cursor, in the macro-expanded file. 35 /// The token before the cursor, in the macro-expanded file.
36 pub(super) token: SyntaxToken, 36 pub(super) token: SyntaxToken,
37 pub(super) krate: Option<hir::Crate>, 37 pub(super) krate: Option<hir::Crate>,
38 pub(super) expected_name: Option<String>,
38 pub(super) expected_type: Option<Type>, 39 pub(super) expected_type: Option<Type>,
39 pub(super) name_ref_syntax: Option<ast::NameRef>, 40 pub(super) name_ref_syntax: Option<ast::NameRef>,
40 pub(super) function_syntax: Option<ast::Fn>, 41 pub(super) function_syntax: Option<ast::Fn>,
@@ -135,6 +136,7 @@ impl<'a> CompletionContext<'a> {
135 original_token, 136 original_token,
136 token, 137 token,
137 krate, 138 krate,
139 expected_name: None,
138 expected_type: None, 140 expected_type: None,
139 name_ref_syntax: None, 141 name_ref_syntax: None,
140 function_syntax: None, 142 function_syntax: None,
@@ -290,23 +292,96 @@ impl<'a> CompletionContext<'a> {
290 file_with_fake_ident: SyntaxNode, 292 file_with_fake_ident: SyntaxNode,
291 offset: TextSize, 293 offset: TextSize,
292 ) { 294 ) {
293 // FIXME: this is wrong in at least two cases: 295 let expected = {
294 // * when there's no token `foo($0)` 296 let mut node = self.token.parent();
295 // * when there is a token, but it happens to have type of it's own 297 loop {
296 self.expected_type = self 298 let ret = match_ast! {
297 .token
298 .ancestors()
299 .find_map(|node| {
300 let ty = match_ast! {
301 match node { 299 match node {
302 ast::Pat(it) => self.sema.type_of_pat(&it), 300 ast::LetStmt(it) => {
303 ast::Expr(it) => self.sema.type_of_expr(&it), 301 cov_mark::hit!(expected_type_let_with_leading_char);
304 _ => return None, 302 cov_mark::hit!(expected_type_let_without_leading_char);
303 let ty = it.pat()
304 .and_then(|pat| self.sema.type_of_pat(&pat));
305 let name = if let Some(ast::Pat::IdentPat(ident)) = it.pat() {
306 Some(ident.syntax().text().to_string())
307 } else {
308 None
309 };
310
311 (ty, name)
312 },
313 ast::ArgList(it) => {
314 cov_mark::hit!(expected_type_fn_param_with_leading_char);
315 cov_mark::hit!(expected_type_fn_param_without_leading_char);
316 ActiveParameter::at_token(
317 &self.sema,
318 self.token.clone(),
319 ).map(|ap| (Some(ap.ty), Some(ap.name)))
320 .unwrap_or((None, None))
321 },
322 ast::RecordExprFieldList(it) => {
323 cov_mark::hit!(expected_type_struct_field_without_leading_char);
324 self.token.prev_sibling_or_token()
325 .and_then(|se| se.into_node())
326 .and_then(|node| ast::RecordExprField::cast(node))
327 .and_then(|rf| self.sema.resolve_record_field(&rf))
328 .map(|f|(
329 Some(f.0.signature_ty(self.db)),
330 Some(f.0.name(self.db).to_string()),
331 ))
332 .unwrap_or((None, None))
333 },
334 ast::RecordExprField(it) => {
335 cov_mark::hit!(expected_type_struct_field_with_leading_char);
336 self.sema
337 .resolve_record_field(&it)
338 .map(|f|(
339 Some(f.0.signature_ty(self.db)),
340 Some(f.0.name(self.db).to_string()),
341 ))
342 .unwrap_or((None, None))
343 },
344 ast::MatchExpr(it) => {
345 cov_mark::hit!(expected_type_match_arm_without_leading_char);
346 let ty = it.expr()
347 .and_then(|e| self.sema.type_of_expr(&e));
348
349 (ty, None)
350 },
351 ast::IdentPat(it) => {
352 cov_mark::hit!(expected_type_if_let_with_leading_char);
353 cov_mark::hit!(expected_type_if_let_without_leading_char);
354 cov_mark::hit!(expected_type_match_arm_with_leading_char);
355 let ty = self.sema.type_of_pat(&ast::Pat::from(it));
356
357 (ty, None)
358 },
359 ast::Fn(it) => {
360 cov_mark::hit!(expected_type_fn_ret_with_leading_char);
361 cov_mark::hit!(expected_type_fn_ret_without_leading_char);
362 let ty = self.token.ancestors()
363 .find_map(|ancestor| ast::Expr::cast(ancestor))
364 .and_then(|expr| self.sema.type_of_expr(&expr));
365
366 (ty, None)
367 },
368 _ => {
369 match node.parent() {
370 Some(n) => {
371 node = n;
372 continue;
373 },
374 None => (None, None),
375 }
376 },
305 } 377 }
306 }; 378 };
307 Some(ty) 379
308 }) 380 break ret;
309 .flatten(); 381 }
382 };
383 self.expected_type = expected.0;
384 self.expected_name = expected.1;
310 self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset); 385 self.attribute_under_caret = find_node_at_offset(&file_with_fake_ident, offset);
311 386
312 // First, let's try to complete a reference to some declaration. 387 // First, let's try to complete a reference to some declaration.
@@ -535,3 +610,197 @@ fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<ast::Path> {
535 let use_tree = use_tree_list.syntax().parent().and_then(ast::UseTree::cast)?; 610 let use_tree = use_tree_list.syntax().parent().and_then(ast::UseTree::cast)?;
536 use_tree.path() 611 use_tree.path()
537} 612}
613
614#[cfg(test)]
615mod tests {
616 use expect_test::{expect, Expect};
617 use hir::HirDisplay;
618
619 use crate::test_utils::{position, TEST_CONFIG};
620
621 use super::CompletionContext;
622
623 fn check_expected_type_and_name(ra_fixture: &str, expect: Expect) {
624 let (db, pos) = position(ra_fixture);
625 let completion_context = CompletionContext::new(&db, pos, &TEST_CONFIG).unwrap();
626
627 let ty = completion_context
628 .expected_type
629 .map(|t| t.display_test(&db).to_string())
630 .unwrap_or("?".to_owned());
631
632 let name = completion_context.expected_name.unwrap_or("?".to_owned());
633
634 expect.assert_eq(&format!("ty: {}, name: {}", ty, name));
635 }
636
637 #[test]
638 fn expected_type_let_without_leading_char() {
639 cov_mark::check!(expected_type_let_without_leading_char);
640 check_expected_type_and_name(
641 r#"
642fn foo() {
643 let x: u32 = $0;
644}
645"#,
646 expect![[r#"ty: u32, name: x"#]],
647 );
648 }
649
650 #[test]
651 fn expected_type_let_with_leading_char() {
652 cov_mark::check!(expected_type_let_with_leading_char);
653 check_expected_type_and_name(
654 r#"
655fn foo() {
656 let x: u32 = c$0;
657}
658"#,
659 expect![[r#"ty: u32, name: x"#]],
660 );
661 }
662
663 #[test]
664 fn expected_type_fn_param_without_leading_char() {
665 cov_mark::check!(expected_type_fn_param_without_leading_char);
666 check_expected_type_and_name(
667 r#"
668fn foo() {
669 bar($0);
670}
671
672fn bar(x: u32) {}
673"#,
674 expect![[r#"ty: u32, name: x"#]],
675 );
676 }
677
678 #[test]
679 fn expected_type_fn_param_with_leading_char() {
680 cov_mark::check!(expected_type_fn_param_with_leading_char);
681 check_expected_type_and_name(
682 r#"
683fn foo() {
684 bar(c$0);
685}
686
687fn bar(x: u32) {}
688"#,
689 expect![[r#"ty: u32, name: x"#]],
690 );
691 }
692
693 #[test]
694 fn expected_type_struct_field_without_leading_char() {
695 cov_mark::check!(expected_type_struct_field_without_leading_char);
696 check_expected_type_and_name(
697 r#"
698struct Foo { a: u32 }
699fn foo() {
700 Foo { a: $0 };
701}
702"#,
703 expect![[r#"ty: u32, name: a"#]],
704 )
705 }
706
707 #[test]
708 fn expected_type_struct_field_with_leading_char() {
709 cov_mark::check!(expected_type_struct_field_with_leading_char);
710 check_expected_type_and_name(
711 r#"
712struct Foo { a: u32 }
713fn foo() {
714 Foo { a: c$0 };
715}
716"#,
717 expect![[r#"ty: u32, name: a"#]],
718 );
719 }
720
721 #[test]
722 fn expected_type_match_arm_without_leading_char() {
723 cov_mark::check!(expected_type_match_arm_without_leading_char);
724 check_expected_type_and_name(
725 r#"
726enum E { X }
727fn foo() {
728 match E::X { $0 }
729}
730"#,
731 expect![[r#"ty: E, name: ?"#]],
732 );
733 }
734
735 #[test]
736 fn expected_type_match_arm_with_leading_char() {
737 cov_mark::check!(expected_type_match_arm_with_leading_char);
738 check_expected_type_and_name(
739 r#"
740enum E { X }
741fn foo() {
742 match E::X { c$0 }
743}
744"#,
745 expect![[r#"ty: E, name: ?"#]],
746 );
747 }
748
749 #[test]
750 fn expected_type_if_let_without_leading_char() {
751 cov_mark::check!(expected_type_if_let_without_leading_char);
752 check_expected_type_and_name(
753 r#"
754enum Foo { Bar, Baz, Quux }
755
756fn foo() {
757 let f = Foo::Quux;
758 if let $0 = f { }
759}
760"#,
761 expect![[r#"ty: (), name: ?"#]],
762 ) // FIXME should be `ty: u32, name: ?`
763 }
764
765 #[test]
766 fn expected_type_if_let_with_leading_char() {
767 cov_mark::check!(expected_type_if_let_with_leading_char);
768 check_expected_type_and_name(
769 r#"
770enum Foo { Bar, Baz, Quux }
771
772fn foo() {
773 let f = Foo::Quux;
774 if let c$0 = f { }
775}
776"#,
777 expect![[r#"ty: Foo, name: ?"#]],
778 )
779 }
780
781 #[test]
782 fn expected_type_fn_ret_without_leading_char() {
783 cov_mark::check!(expected_type_fn_ret_without_leading_char);
784 check_expected_type_and_name(
785 r#"
786fn foo() -> u32 {
787 $0
788}
789"#,
790 expect![[r#"ty: (), name: ?"#]],
791 ) // FIXME this should be `ty: u32, name: ?`
792 }
793
794 #[test]
795 fn expected_type_fn_ret_with_leading_char() {
796 cov_mark::check!(expected_type_fn_ret_with_leading_char);
797 check_expected_type_and_name(
798 r#"
799fn foo() -> u32 {
800 c$0
801}
802"#,
803 expect![[r#"ty: u32, name: ?"#]],
804 )
805 }
806}
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 905f0b197..670563e50 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -118,19 +118,6 @@ impl<'a> RenderContext<'a> {
118 fn docs(&self, node: impl HasAttrs) -> Option<Documentation> { 118 fn docs(&self, node: impl HasAttrs) -> Option<Documentation> {
119 node.docs(self.db()) 119 node.docs(self.db())
120 } 120 }
121
122 fn expected_name_and_type(&self) -> Option<(String, Type)> {
123 if let Some(record_field) = &self.completion.record_field_syntax {
124 cov_mark::hit!(record_field_type_match);
125 let (struct_field, _local) = self.completion.sema.resolve_record_field(record_field)?;
126 Some((struct_field.name(self.db()).to_string(), struct_field.signature_ty(self.db())))
127 } else if let Some(active_parameter) = &self.completion.active_parameter {
128 cov_mark::hit!(active_param_type_match);
129 Some((active_parameter.name.clone(), active_parameter.ty.clone()))
130 } else {
131 None
132 }
133 }
134} 121}
135 122
136/// Generic renderer for completion items. 123/// Generic renderer for completion items.
@@ -256,8 +243,8 @@ impl<'a> Render<'a> {
256 relevance.is_local = true; 243 relevance.is_local = true;
257 item.set_relevance(relevance); 244 item.set_relevance(relevance);
258 245
259 if let Some((_expected_name, expected_type)) = self.ctx.expected_name_and_type() { 246 if let Some(expected_type) = self.ctx.completion.expected_type.as_ref() {
260 if ty != expected_type { 247 if &ty != expected_type {
261 if let Some(ty_without_ref) = expected_type.remove_ref() { 248 if let Some(ty_without_ref) = expected_type.remove_ref() {
262 if relevance_type_match(self.ctx.db().upcast(), &ty, &ty_without_ref) { 249 if relevance_type_match(self.ctx.db().upcast(), &ty, &ty_without_ref) {
263 cov_mark::hit!(suggest_ref); 250 cov_mark::hit!(suggest_ref);
@@ -329,10 +316,8 @@ impl<'a> Render<'a> {
329fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> CompletionRelevance { 316fn compute_relevance(ctx: &RenderContext, ty: &Type, name: &str) -> CompletionRelevance {
330 let mut res = CompletionRelevance::default(); 317 let mut res = CompletionRelevance::default();
331 318
332 if let Some((expected_name, expected_type)) = ctx.expected_name_and_type() { 319 res.exact_type_match = Some(ty) == ctx.completion.expected_type.as_ref();
333 res.exact_type_match = ty == &expected_type; 320 res.exact_name_match = Some(name) == ctx.completion.expected_name.as_deref();
334 res.exact_name_match = name == &expected_name;
335 }
336 321
337 res 322 res
338} 323}
@@ -852,7 +837,6 @@ fn foo(xs: Vec<i128>)
852 837
853 #[test] 838 #[test]
854 fn active_param_relevance() { 839 fn active_param_relevance() {
855 cov_mark::check!(active_param_type_match);
856 check_relevance( 840 check_relevance(
857 r#" 841 r#"
858struct S { foo: i64, bar: u32, baz: u32 } 842struct S { foo: i64, bar: u32, baz: u32 }
@@ -869,7 +853,6 @@ fn foo(s: S) { test(s.$0) }
869 853
870 #[test] 854 #[test]
871 fn record_field_relevances() { 855 fn record_field_relevances() {
872 cov_mark::check!(record_field_type_match);
873 check_relevance( 856 check_relevance(
874 r#" 857 r#"
875struct A { foo: i64, bar: u32, baz: u32 } 858struct A { foo: i64, bar: u32, baz: u32 }
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index ff612b7d0..f86e5ce93 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -70,7 +70,7 @@ impl Definition {
70 hir::ModuleDef::Static(it) => it.name(db)?, 70 hir::ModuleDef::Static(it) => it.name(db)?,
71 hir::ModuleDef::Trait(it) => it.name(db), 71 hir::ModuleDef::Trait(it) => it.name(db),
72 hir::ModuleDef::TypeAlias(it) => it.name(db), 72 hir::ModuleDef::TypeAlias(it) => it.name(db),
73 hir::ModuleDef::BuiltinType(_) => return None, 73 hir::ModuleDef::BuiltinType(it) => it.name(),
74 }, 74 },
75 Definition::SelfType(_) => return None, 75 Definition::SelfType(_) => return None,
76 Definition::Local(it) => it.name(db)?, 76 Definition::Local(it) => it.name(db)?,
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs
index 3c95d3cff..9992a92bd 100644
--- a/crates/ide_db/src/helpers.rs
+++ b/crates/ide_db/src/helpers.rs
@@ -2,6 +2,10 @@
2pub mod insert_use; 2pub mod insert_use;
3pub mod import_assets; 3pub mod import_assets;
4 4
5use std::collections::VecDeque;
6
7use base_db::FileId;
8use either::Either;
5use hir::{Crate, Enum, ItemInNs, MacroDef, Module, ModuleDef, Name, ScopeDef, Semantics, Trait}; 9use hir::{Crate, Enum, ItemInNs, MacroDef, Module, ModuleDef, Name, ScopeDef, Semantics, Trait};
6use syntax::ast::{self, make}; 10use syntax::ast::{self, make};
7 11
@@ -39,6 +43,30 @@ pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
39 make::path_from_segments(segments, is_abs) 43 make::path_from_segments(segments, is_abs)
40} 44}
41 45
46/// Iterates all `ModuleDef`s and `Impl` blocks of the given file.
47pub fn visit_file_defs(
48 sema: &Semantics<RootDatabase>,
49 file_id: FileId,
50 cb: &mut dyn FnMut(Either<hir::ModuleDef, hir::Impl>),
51) {
52 let db = sema.db;
53 let module = match sema.to_module_def(file_id) {
54 Some(it) => it,
55 None => return,
56 };
57 let mut defs: VecDeque<_> = module.declarations(db).into();
58 while let Some(def) = defs.pop_front() {
59 if let ModuleDef::Module(submodule) = def {
60 if let hir::ModuleSource::Module(_) = submodule.definition_source(db).value {
61 defs.extend(submodule.declarations(db));
62 submodule.impl_defs(db).into_iter().for_each(|impl_| cb(Either::Right(impl_)));
63 }
64 }
65 cb(Either::Left(def));
66 }
67 module.impl_defs(db).into_iter().for_each(|impl_| cb(Either::Right(impl_)));
68}
69
42/// Helps with finding well-know things inside the standard library. This is 70/// Helps with finding well-know things inside the standard library. This is
43/// somewhat similar to the known paths infra inside hir, but it different; We 71/// somewhat similar to the known paths infra inside hir, but it different; We
44/// want to make sure that IDE specific paths don't become interesting inside 72/// want to make sure that IDE specific paths don't become interesting inside
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index fa18703e1..d00a8b6e7 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -6,7 +6,7 @@
6 6
7use std::{convert::TryInto, mem}; 7use std::{convert::TryInto, mem};
8 8
9use base_db::{FileId, FileRange, SourceDatabaseExt}; 9use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt};
10use hir::{DefWithBody, HasSource, Module, ModuleSource, Semantics, Visibility}; 10use hir::{DefWithBody, HasSource, Module, ModuleSource, Semantics, Visibility};
11use once_cell::unsync::Lazy; 11use once_cell::unsync::Lazy;
12use rustc_hash::FxHashMap; 12use rustc_hash::FxHashMap;
@@ -138,6 +138,20 @@ impl IntoIterator for SearchScope {
138impl Definition { 138impl Definition {
139 fn search_scope(&self, db: &RootDatabase) -> SearchScope { 139 fn search_scope(&self, db: &RootDatabase) -> SearchScope {
140 let _p = profile::span("search_scope"); 140 let _p = profile::span("search_scope");
141
142 if let Definition::ModuleDef(hir::ModuleDef::BuiltinType(_)) = self {
143 let mut res = FxHashMap::default();
144
145 let graph = db.crate_graph();
146 for krate in graph.iter() {
147 let root_file = graph[krate].root_file_id;
148 let source_root_id = db.file_source_root(root_file);
149 let source_root = db.source_root(source_root_id);
150 res.extend(source_root.iter().map(|id| (id, None)));
151 }
152 return SearchScope::new(res);
153 }
154
141 let module = match self.module(db) { 155 let module = match self.module(db) {
142 Some(it) => it, 156 Some(it) => it,
143 None => return SearchScope::empty(), 157 None => return SearchScope::empty(),
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index aacae1026..b715ebfc4 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -222,14 +222,10 @@ fn convert_doc_comment(token: &syntax::SyntaxToken) -> Option<Vec<tt::TokenTree>
222 let doc = comment.kind().doc?; 222 let doc = comment.kind().doc?;
223 223
224 // Make `doc="\" Comments\"" 224 // Make `doc="\" Comments\""
225 let mut meta_tkns = Vec::new(); 225 let meta_tkns = vec![mk_ident("doc"), mk_punct('='), mk_doc_literal(&comment)];
226 meta_tkns.push(mk_ident("doc"));
227 meta_tkns.push(mk_punct('='));
228 meta_tkns.push(mk_doc_literal(&comment));
229 226
230 // Make `#![]` 227 // Make `#![]`
231 let mut token_trees = Vec::new(); 228 let mut token_trees = vec![mk_punct('#')];
232 token_trees.push(mk_punct('#'));
233 if let ast::CommentPlacement::Inner = doc { 229 if let ast::CommentPlacement::Inner = doc {
234 token_trees.push(mk_punct('!')); 230 token_trees.push(mk_punct('!'));
235 } 231 }
diff --git a/crates/proc_macro_api/src/version.rs b/crates/proc_macro_api/src/version.rs
index 11a7fb59a..b903658fb 100644
--- a/crates/proc_macro_api/src/version.rs
+++ b/crates/proc_macro_api/src/version.rs
@@ -33,7 +33,7 @@ pub(crate) fn read_info(dylib_path: &Path) -> io::Result<RustCInfo> {
33 } 33 }
34 34
35 let version_part = items.next().ok_or(err!("no version string"))?; 35 let version_part = items.next().ok_or(err!("no version string"))?;
36 let mut version_parts = version_part.split("-"); 36 let mut version_parts = version_part.split('-');
37 let version = version_parts.next().ok_or(err!("no version"))?; 37 let version = version_parts.next().ok_or(err!("no version"))?;
38 let channel = version_parts.next().unwrap_or_default().to_string(); 38 let channel = version_parts.next().unwrap_or_default().to_string();
39 39
@@ -51,7 +51,7 @@ pub(crate) fn read_info(dylib_path: &Path) -> io::Result<RustCInfo> {
51 let date = date[0..date.len() - 2].to_string(); 51 let date = date[0..date.len() - 2].to_string();
52 52
53 let version_numbers = version 53 let version_numbers = version
54 .split(".") 54 .split('.')
55 .map(|it| it.parse::<usize>()) 55 .map(|it| it.parse::<usize>())
56 .collect::<Result<Vec<_>, _>>() 56 .collect::<Result<Vec<_>, _>>()
57 .map_err(|_| err!("version number error"))?; 57 .map_err(|_| err!("version number error"))?;
diff --git a/crates/project_model/src/rustc_cfg.rs b/crates/project_model/src/rustc_cfg.rs
index 4a7bd8ae3..312708575 100644
--- a/crates/project_model/src/rustc_cfg.rs
+++ b/crates/project_model/src/rustc_cfg.rs
@@ -6,7 +6,7 @@ use crate::{cfg_flag::CfgFlag, utf8_stdout};
6 6
7pub(crate) fn get(target: Option<&str>) -> Vec<CfgFlag> { 7pub(crate) fn get(target: Option<&str>) -> Vec<CfgFlag> {
8 let _p = profile::span("rustc_cfg::get"); 8 let _p = profile::span("rustc_cfg::get");
9 let mut res = Vec::new(); 9 let mut res = Vec::with_capacity(6 * 2 + 1);
10 10
11 // Some nightly-only cfgs, which are required for stdlib 11 // Some nightly-only cfgs, which are required for stdlib
12 res.push(CfgFlag::Atom("target_thread_local".into())); 12 res.push(CfgFlag::Atom("target_thread_local".into()));
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index 706a39dab..6fb7da79c 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -289,7 +289,7 @@ pub(crate) fn handle_document_symbol(
289 let doc_symbol = lsp_types::DocumentSymbol { 289 let doc_symbol = lsp_types::DocumentSymbol {
290 name: symbol.label, 290 name: symbol.label,
291 detail: symbol.detail, 291 detail: symbol.detail,
292 kind: to_proto::symbol_kind(symbol.kind), 292 kind: to_proto::structure_node_kind(symbol.kind),
293 tags: Some(tags), 293 tags: Some(tags),
294 deprecated: Some(symbol.deprecated), 294 deprecated: Some(symbol.deprecated),
295 range: to_proto::range(&line_index, symbol.node_range), 295 range: to_proto::range(&line_index, symbol.node_range),
@@ -846,9 +846,9 @@ pub(crate) fn handle_references(
846 }; 846 };
847 847
848 let decl = if params.context.include_declaration { 848 let decl = if params.context.include_declaration {
849 Some(FileRange { 849 refs.declaration.map(|decl| FileRange {
850 file_id: refs.declaration.nav.file_id, 850 file_id: decl.nav.file_id,
851 range: refs.declaration.nav.focus_or_full_range(), 851 range: decl.nav.focus_or_full_range(),
852 }) 852 })
853 } else { 853 } else {
854 None 854 None
@@ -1153,14 +1153,12 @@ pub(crate) fn handle_document_highlight(
1153 Some(refs) => refs, 1153 Some(refs) => refs,
1154 }; 1154 };
1155 1155
1156 let decl = if refs.declaration.nav.file_id == position.file_id { 1156 let decl = refs.declaration.filter(|decl| decl.nav.file_id == position.file_id).map(|decl| {
1157 Some(DocumentHighlight { 1157 DocumentHighlight {
1158 range: to_proto::range(&line_index, refs.declaration.nav.focus_or_full_range()), 1158 range: to_proto::range(&line_index, decl.nav.focus_or_full_range()),
1159 kind: refs.declaration.access.map(to_proto::document_highlight_kind), 1159 kind: decl.access.map(to_proto::document_highlight_kind),
1160 }) 1160 }
1161 } else { 1161 });
1162 None
1163 };
1164 1162
1165 let file_refs = refs.references.get(&position.file_id).map_or(&[][..], Vec::as_slice); 1163 let file_refs = refs.references.get(&position.file_id).map_or(&[][..], Vec::as_slice);
1166 let mut res = Vec::with_capacity(file_refs.len() + 1); 1164 let mut res = Vec::with_capacity(file_refs.len() + 1);
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs
index 84f78b5b8..3ca7f8040 100644
--- a/crates/rust-analyzer/src/lsp_utils.rs
+++ b/crates/rust-analyzer/src/lsp_utils.rs
@@ -360,11 +360,11 @@ mod tests {
360 "Completion with disjoint edits is valid" 360 "Completion with disjoint edits is valid"
361 ); 361 );
362 assert!( 362 assert!(
363 !all_edits_are_disjoint(&completion_with_disjoint_edits, &[joint_edit.clone()]), 363 !all_edits_are_disjoint(&completion_with_disjoint_edits, &[joint_edit]),
364 "Completion with disjoint edits and joint extra edit is invalid" 364 "Completion with disjoint edits and joint extra edit is invalid"
365 ); 365 );
366 assert!( 366 assert!(
367 all_edits_are_disjoint(&completion_with_disjoint_edits, &[disjoint_edit_2.clone()]), 367 all_edits_are_disjoint(&completion_with_disjoint_edits, &[disjoint_edit_2]),
368 "Completion with disjoint edits and joint extra edit is valid" 368 "Completion with disjoint edits and joint extra edit is valid"
369 ); 369 );
370 } 370 }
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index d415ed4d3..70eaae5e8 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -9,9 +9,8 @@ use ide::{
9 CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit, Fold, FoldKind, 9 CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit, Fold, FoldKind,
10 Highlight, HlMod, HlPunct, HlRange, HlTag, Indel, InlayHint, InlayKind, InsertTextFormat, 10 Highlight, HlMod, HlPunct, HlRange, HlTag, Indel, InlayHint, InlayKind, InsertTextFormat,
11 Markup, NavigationTarget, ReferenceAccess, RenameError, Runnable, Severity, SourceChange, 11 Markup, NavigationTarget, ReferenceAccess, RenameError, Runnable, Severity, SourceChange,
12 TextEdit, TextRange, TextSize, 12 StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
13}; 13};
14use ide_db::SymbolKind;
15use itertools::Itertools; 14use itertools::Itertools;
16use serde_json::to_value; 15use serde_json::to_value;
17 16
@@ -63,6 +62,13 @@ pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
63 } 62 }
64} 63}
65 64
65pub(crate) fn structure_node_kind(kind: StructureNodeKind) -> lsp_types::SymbolKind {
66 match kind {
67 StructureNodeKind::SymbolKind(symbol) => symbol_kind(symbol),
68 StructureNodeKind::Region => lsp_types::SymbolKind::Namespace,
69 }
70}
71
66pub(crate) fn document_highlight_kind( 72pub(crate) fn document_highlight_kind(
67 reference_access: ReferenceAccess, 73 reference_access: ReferenceAccess,
68) -> lsp_types::DocumentHighlightKind { 74) -> lsp_types::DocumentHighlightKind {