aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir/src/lib.rs34
-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_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/goto_definition.rs11
-rw-r--r--crates/ide_completion/src/context.rs297
-rw-r--r--crates/ide_completion/src/render.rs15
17 files changed, 485 insertions, 194 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index caa760d21..25e5bfb01 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1597,7 +1597,7 @@ impl Type {
1597 1597
1598 pub fn remove_ref(&self) -> Option<Type> { 1598 pub fn remove_ref(&self) -> Option<Type> {
1599 match &self.ty.value.interned(&Interner) { 1599 match &self.ty.value.interned(&Interner) {
1600 TyKind::Ref(.., substs) => Some(self.derived(substs[0].clone())), 1600 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
1601 _ => None, 1601 _ => None,
1602 } 1602 }
1603 } 1603 }
@@ -1751,10 +1751,30 @@ impl Type {
1751 return go(&self.ty.value); 1751 return go(&self.ty.value);
1752 1752
1753 fn go(ty: &Ty) -> bool { 1753 fn go(ty: &Ty) -> bool {
1754 if ty.is_unknown() { 1754 match ty.interned(&Interner) {
1755 true 1755 TyKind::Unknown => true,
1756 } else { 1756
1757 ty.substs().map_or(false, |substs| substs.iter().any(go)) 1757 TyKind::Adt(_, substs)
1758 | TyKind::AssociatedType(_, substs)
1759 | TyKind::Tuple(_, substs)
1760 | TyKind::OpaqueType(_, substs)
1761 | TyKind::FnDef(_, substs)
1762 | TyKind::Closure(_, substs) => substs.iter().any(go),
1763
1764 TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => {
1765 go(ty)
1766 }
1767
1768 TyKind::Scalar(_)
1769 | TyKind::Str
1770 | TyKind::Never
1771 | TyKind::Placeholder(_)
1772 | TyKind::BoundVar(_)
1773 | TyKind::InferenceVar(_, _)
1774 | TyKind::Dyn(_)
1775 | TyKind::Function(_)
1776 | TyKind::Alias(_)
1777 | TyKind::ForeignType(_) => false,
1758 } 1778 }
1759 } 1779 }
1760 } 1780 }
@@ -1989,6 +2009,10 @@ impl Type {
1989 walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb); 2009 walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
1990 } 2010 }
1991 2011
2012 TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => {
2013 walk_type(db, &type_.derived(ty.clone()), cb);
2014 }
2015
1992 _ => {} 2016 _ => {}
1993 } 2017 }
1994 if let Some(substs) = ty.substs() { 2018 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_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 c7055bee5..741440006 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -435,8 +435,7 @@ fn iterate_method_candidates_with_autoref(
435 } 435 }
436 let refed = Canonical { 436 let refed = Canonical {
437 kinds: deref_chain[0].kinds.clone(), 437 kinds: deref_chain[0].kinds.clone(),
438 value: TyKind::Ref(Mutability::Not, Substs::single(deref_chain[0].value.clone())) 438 value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner),
439 .intern(&Interner),
440 }; 439 };
441 if iterate_method_candidates_by_receiver( 440 if iterate_method_candidates_by_receiver(
442 &refed, 441 &refed,
@@ -452,8 +451,7 @@ fn iterate_method_candidates_with_autoref(
452 } 451 }
453 let ref_muted = Canonical { 452 let ref_muted = Canonical {
454 kinds: deref_chain[0].kinds.clone(), 453 kinds: deref_chain[0].kinds.clone(),
455 value: TyKind::Ref(Mutability::Mut, Substs::single(deref_chain[0].value.clone())) 454 value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner),
456 .intern(&Interner),
457 }; 455 };
458 if iterate_method_candidates_by_receiver( 456 if iterate_method_candidates_by_receiver(
459 &ref_muted, 457 &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/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_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..3e1bff4d6 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -119,17 +119,10 @@ impl<'a> RenderContext<'a> {
119 node.docs(self.db()) 119 node.docs(self.db())
120 } 120 }
121 121
122 // FIXME delete this method in favor of directly using the fields
123 // on CompletionContext
122 fn expected_name_and_type(&self) -> Option<(String, Type)> { 124 fn expected_name_and_type(&self) -> Option<(String, Type)> {
123 if let Some(record_field) = &self.completion.record_field_syntax { 125 Some((self.completion.expected_name.clone()?, self.completion.expected_type.clone()?))
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 } 126 }
134} 127}
135 128
@@ -852,7 +845,6 @@ fn foo(xs: Vec<i128>)
852 845
853 #[test] 846 #[test]
854 fn active_param_relevance() { 847 fn active_param_relevance() {
855 cov_mark::check!(active_param_type_match);
856 check_relevance( 848 check_relevance(
857 r#" 849 r#"
858struct S { foo: i64, bar: u32, baz: u32 } 850struct S { foo: i64, bar: u32, baz: u32 }
@@ -869,7 +861,6 @@ fn foo(s: S) { test(s.$0) }
869 861
870 #[test] 862 #[test]
871 fn record_field_relevances() { 863 fn record_field_relevances() {
872 cov_mark::check!(record_field_type_match);
873 check_relevance( 864 check_relevance(
874 r#" 865 r#"
875struct A { foo: i64, bar: u32, baz: u32 } 866struct A { foo: i64, bar: u32, baz: u32 }