diff options
Diffstat (limited to 'crates/hir_ty/src/infer.rs')
-rw-r--r-- | crates/hir_ty/src/infer.rs | 198 |
1 files changed, 98 insertions, 100 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index e4407ff50..bf2da2d4a 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -18,7 +18,7 @@ use std::mem; | |||
18 | use std::ops::Index; | 18 | use std::ops::Index; |
19 | use std::sync::Arc; | 19 | use std::sync::Arc; |
20 | 20 | ||
21 | use chalk_ir::{cast::Cast, Mutability}; | 21 | use chalk_ir::{cast::Cast, DebruijnIndex, Mutability}; |
22 | use hir_def::{ | 22 | use hir_def::{ |
23 | body::Body, | 23 | body::Body, |
24 | data::{ConstData, FunctionData, StaticData}, | 24 | data::{ConstData, FunctionData, StaticData}, |
@@ -37,12 +37,12 @@ use stdx::impl_from; | |||
37 | use syntax::SmolStr; | 37 | use syntax::SmolStr; |
38 | 38 | ||
39 | use super::{ | 39 | use super::{ |
40 | traits::{DomainGoal, Guidance, Solution}, | 40 | DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty, |
41 | InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, | ||
42 | }; | 41 | }; |
43 | use crate::{ | 42 | use crate::{ |
44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, | 43 | db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, |
45 | to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, | 44 | lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, |
45 | TyBuilder, TyExt, TyKind, | ||
46 | }; | 46 | }; |
47 | 47 | ||
48 | // This lint has a false positive here. See the link below for details. | 48 | // This lint has a false positive here. See the link below for details. |
@@ -120,7 +120,7 @@ struct InternedStandardTypes { | |||
120 | 120 | ||
121 | impl Default for InternedStandardTypes { | 121 | impl Default for InternedStandardTypes { |
122 | fn default() -> Self { | 122 | fn default() -> Self { |
123 | InternedStandardTypes { unknown: TyKind::Unknown.intern(&Interner) } | 123 | InternedStandardTypes { unknown: TyKind::Error.intern(&Interner) } |
124 | } | 124 | } |
125 | } | 125 | } |
126 | 126 | ||
@@ -131,10 +131,7 @@ pub struct InferenceResult { | |||
131 | method_resolutions: FxHashMap<ExprId, FunctionId>, | 131 | method_resolutions: FxHashMap<ExprId, FunctionId>, |
132 | /// For each field access expr, records the field it resolves to. | 132 | /// For each field access expr, records the field it resolves to. |
133 | field_resolutions: FxHashMap<ExprId, FieldId>, | 133 | field_resolutions: FxHashMap<ExprId, FieldId>, |
134 | /// For each field in record literal, records the field it resolves to. | 134 | /// For each struct literal or pattern, records the variant it resolves to. |
135 | record_field_resolutions: FxHashMap<ExprId, FieldId>, | ||
136 | record_pat_field_resolutions: FxHashMap<PatId, FieldId>, | ||
137 | /// For each struct literal, records the variant it resolves to. | ||
138 | variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, | 135 | variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, |
139 | /// For each associated item record what it resolves to | 136 | /// For each associated item record what it resolves to |
140 | assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>, | 137 | assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>, |
@@ -153,12 +150,6 @@ impl InferenceResult { | |||
153 | pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { | 150 | pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { |
154 | self.field_resolutions.get(&expr).copied() | 151 | self.field_resolutions.get(&expr).copied() |
155 | } | 152 | } |
156 | pub fn record_field_resolution(&self, expr: ExprId) -> Option<FieldId> { | ||
157 | self.record_field_resolutions.get(&expr).copied() | ||
158 | } | ||
159 | pub fn record_pat_field_resolution(&self, pat: PatId) -> Option<FieldId> { | ||
160 | self.record_pat_field_resolutions.get(&pat).copied() | ||
161 | } | ||
162 | pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> { | 153 | pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> { |
163 | self.variant_resolutions.get(&id.into()).copied() | 154 | self.variant_resolutions.get(&id.into()).copied() |
164 | } | 155 | } |
@@ -210,6 +201,7 @@ struct InferenceContext<'a> { | |||
210 | table: unify::InferenceTable, | 201 | table: unify::InferenceTable, |
211 | trait_env: Arc<TraitEnvironment>, | 202 | trait_env: Arc<TraitEnvironment>, |
212 | obligations: Vec<DomainGoal>, | 203 | obligations: Vec<DomainGoal>, |
204 | last_obligations_check: Option<u32>, | ||
213 | result: InferenceResult, | 205 | result: InferenceResult, |
214 | /// The return type of the function being inferred, or the closure if we're | 206 | /// The return type of the function being inferred, or the closure if we're |
215 | /// currently within one. | 207 | /// currently within one. |
@@ -245,7 +237,8 @@ impl<'a> InferenceContext<'a> { | |||
245 | result: InferenceResult::default(), | 237 | result: InferenceResult::default(), |
246 | table: unify::InferenceTable::new(), | 238 | table: unify::InferenceTable::new(), |
247 | obligations: Vec::default(), | 239 | obligations: Vec::default(), |
248 | return_ty: TyKind::Unknown.intern(&Interner), // set in collect_fn_signature | 240 | last_obligations_check: None, |
241 | return_ty: TyKind::Error.intern(&Interner), // set in collect_fn_signature | ||
249 | trait_env: owner | 242 | trait_env: owner |
250 | .as_generic_def_id() | 243 | .as_generic_def_id() |
251 | .map_or_else(Default::default, |d| db.trait_environment(d)), | 244 | .map_or_else(Default::default, |d| db.trait_environment(d)), |
@@ -259,7 +252,7 @@ impl<'a> InferenceContext<'a> { | |||
259 | } | 252 | } |
260 | 253 | ||
261 | fn err_ty(&self) -> Ty { | 254 | fn err_ty(&self) -> Ty { |
262 | TyKind::Unknown.intern(&Interner) | 255 | TyKind::Error.intern(&Interner) |
263 | } | 256 | } |
264 | 257 | ||
265 | fn resolve_all(mut self) -> InferenceResult { | 258 | fn resolve_all(mut self) -> InferenceResult { |
@@ -323,30 +316,44 @@ impl<'a> InferenceContext<'a> { | |||
323 | 316 | ||
324 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. | 317 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. |
325 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { | 318 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { |
326 | match ty.interned(&Interner) { | 319 | match ty.kind(&Interner) { |
327 | TyKind::Unknown => self.table.new_type_var(), | 320 | TyKind::Error => self.table.new_type_var(), |
328 | _ => ty, | 321 | _ => ty, |
329 | } | 322 | } |
330 | } | 323 | } |
331 | 324 | ||
332 | fn insert_type_vars(&mut self, ty: Ty) -> Ty { | 325 | fn insert_type_vars(&mut self, ty: Ty) -> Ty { |
333 | ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) | 326 | fold_tys(ty, |ty, _| self.insert_type_vars_shallow(ty), DebruijnIndex::INNERMOST) |
334 | } | 327 | } |
335 | 328 | ||
336 | fn resolve_obligations_as_possible(&mut self) { | 329 | fn resolve_obligations_as_possible(&mut self) { |
330 | if self.last_obligations_check == Some(self.table.revision) { | ||
331 | // no change | ||
332 | return; | ||
333 | } | ||
334 | let _span = profile::span("resolve_obligations_as_possible"); | ||
335 | |||
336 | self.last_obligations_check = Some(self.table.revision); | ||
337 | let obligations = mem::replace(&mut self.obligations, Vec::new()); | 337 | let obligations = mem::replace(&mut self.obligations, Vec::new()); |
338 | for obligation in obligations { | 338 | for obligation in obligations { |
339 | let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone()); | 339 | let in_env = InEnvironment::new(&self.trait_env.env, obligation.clone()); |
340 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); | 340 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); |
341 | let solution = | 341 | let solution = |
342 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); | 342 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); |
343 | 343 | ||
344 | match solution { | 344 | match solution { |
345 | Some(Solution::Unique(substs)) => { | 345 | Some(Solution::Unique(canonical_subst)) => { |
346 | canonicalized.apply_solution(self, substs.0); | 346 | canonicalized.apply_solution( |
347 | self, | ||
348 | Canonical { | ||
349 | binders: canonical_subst.binders, | ||
350 | // FIXME: handle constraints | ||
351 | value: canonical_subst.value.subst, | ||
352 | }, | ||
353 | ); | ||
347 | } | 354 | } |
348 | Some(Solution::Ambig(Guidance::Definite(substs))) => { | 355 | Some(Solution::Ambig(Guidance::Definite(substs))) => { |
349 | canonicalized.apply_solution(self, substs.0); | 356 | canonicalized.apply_solution(self, substs); |
350 | self.obligations.push(obligation); | 357 | self.obligations.push(obligation); |
351 | } | 358 | } |
352 | Some(_) => { | 359 | Some(_) => { |
@@ -360,6 +367,11 @@ impl<'a> InferenceContext<'a> { | |||
360 | } | 367 | } |
361 | } | 368 | } |
362 | 369 | ||
370 | fn push_obligation(&mut self, o: DomainGoal) { | ||
371 | self.obligations.push(o); | ||
372 | self.last_obligations_check = None; | ||
373 | } | ||
374 | |||
363 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { | 375 | fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { |
364 | self.table.unify(ty1, ty2) | 376 | self.table.unify(ty1, ty2) |
365 | } | 377 | } |
@@ -395,21 +407,19 @@ impl<'a> InferenceContext<'a> { | |||
395 | _ => panic!("resolve_associated_type called with non-associated type"), | 407 | _ => panic!("resolve_associated_type called with non-associated type"), |
396 | }; | 408 | }; |
397 | let ty = self.table.new_type_var(); | 409 | let ty = self.table.new_type_var(); |
398 | let substs = Substitution::build_for_def(self.db, res_assoc_ty) | 410 | let trait_ref = TyBuilder::trait_ref(self.db, trait_) |
399 | .push(inner_ty) | 411 | .push(inner_ty) |
400 | .fill(params.iter().cloned()) | 412 | .fill(params.iter().cloned()) |
401 | .build(); | 413 | .build(); |
402 | let trait_ref = | ||
403 | TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() }; | ||
404 | let alias_eq = AliasEq { | 414 | let alias_eq = AliasEq { |
405 | alias: AliasTy::Projection(ProjectionTy { | 415 | alias: AliasTy::Projection(ProjectionTy { |
406 | associated_ty_id: to_assoc_type_id(res_assoc_ty), | 416 | associated_ty_id: to_assoc_type_id(res_assoc_ty), |
407 | substitution: substs, | 417 | substitution: trait_ref.substitution.clone(), |
408 | }), | 418 | }), |
409 | ty: ty.clone(), | 419 | ty: ty.clone(), |
410 | }; | 420 | }; |
411 | self.obligations.push(trait_ref.cast(&Interner)); | 421 | self.push_obligation(trait_ref.cast(&Interner)); |
412 | self.obligations.push(alias_eq.cast(&Interner)); | 422 | self.push_obligation(alias_eq.cast(&Interner)); |
413 | self.resolve_ty_as_possible(ty) | 423 | self.resolve_ty_as_possible(ty) |
414 | } | 424 | } |
415 | None => self.err_ty(), | 425 | None => self.err_ty(), |
@@ -424,19 +434,23 @@ impl<'a> InferenceContext<'a> { | |||
424 | /// to do it as well. | 434 | /// to do it as well. |
425 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { | 435 | fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { |
426 | let ty = self.resolve_ty_as_possible(ty); | 436 | let ty = self.resolve_ty_as_possible(ty); |
427 | ty.fold(&mut |ty| match ty.interned(&Interner) { | 437 | fold_tys( |
428 | TyKind::Alias(AliasTy::Projection(proj_ty)) => { | 438 | ty, |
429 | self.normalize_projection_ty(proj_ty.clone()) | 439 | |ty, _| match ty.kind(&Interner) { |
430 | } | 440 | TyKind::Alias(AliasTy::Projection(proj_ty)) => { |
431 | _ => ty, | 441 | self.normalize_projection_ty(proj_ty.clone()) |
432 | }) | 442 | } |
443 | _ => ty, | ||
444 | }, | ||
445 | DebruijnIndex::INNERMOST, | ||
446 | ) | ||
433 | } | 447 | } |
434 | 448 | ||
435 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { | 449 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { |
436 | let var = self.table.new_type_var(); | 450 | let var = self.table.new_type_var(); |
437 | let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; | 451 | let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; |
438 | let obligation = alias_eq.cast(&Interner); | 452 | let obligation = alias_eq.cast(&Interner); |
439 | self.obligations.push(obligation); | 453 | self.push_obligation(obligation); |
440 | var | 454 | var |
441 | } | 455 | } |
442 | 456 | ||
@@ -458,56 +472,32 @@ impl<'a> InferenceContext<'a> { | |||
458 | TypeNs::AdtId(AdtId::StructId(strukt)) => { | 472 | TypeNs::AdtId(AdtId::StructId(strukt)) => { |
459 | let substs = ctx.substs_from_path(path, strukt.into(), true); | 473 | let substs = ctx.substs_from_path(path, strukt.into(), true); |
460 | let ty = self.db.ty(strukt.into()); | 474 | let ty = self.db.ty(strukt.into()); |
461 | let ty = self.insert_type_vars(ty.subst(&substs)); | 475 | let ty = self.insert_type_vars(ty.substitute(&Interner, &substs)); |
462 | forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) | 476 | forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) |
463 | } | 477 | } |
464 | TypeNs::AdtId(AdtId::UnionId(u)) => { | 478 | TypeNs::AdtId(AdtId::UnionId(u)) => { |
465 | let substs = ctx.substs_from_path(path, u.into(), true); | 479 | let substs = ctx.substs_from_path(path, u.into(), true); |
466 | let ty = self.db.ty(u.into()); | 480 | let ty = self.db.ty(u.into()); |
467 | let ty = self.insert_type_vars(ty.subst(&substs)); | 481 | let ty = self.insert_type_vars(ty.substitute(&Interner, &substs)); |
468 | forbid_unresolved_segments((ty, Some(u.into())), unresolved) | 482 | forbid_unresolved_segments((ty, Some(u.into())), unresolved) |
469 | } | 483 | } |
470 | TypeNs::EnumVariantId(var) => { | 484 | TypeNs::EnumVariantId(var) => { |
471 | let substs = ctx.substs_from_path(path, var.into(), true); | 485 | let substs = ctx.substs_from_path(path, var.into(), true); |
472 | let ty = self.db.ty(var.parent.into()); | 486 | let ty = self.db.ty(var.parent.into()); |
473 | let ty = self.insert_type_vars(ty.subst(&substs)); | 487 | let ty = self.insert_type_vars(ty.substitute(&Interner, &substs)); |
474 | forbid_unresolved_segments((ty, Some(var.into())), unresolved) | 488 | forbid_unresolved_segments((ty, Some(var.into())), unresolved) |
475 | } | 489 | } |
476 | TypeNs::SelfType(impl_id) => { | 490 | TypeNs::SelfType(impl_id) => { |
477 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); | 491 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); |
478 | let substs = Substitution::type_params_for_generics(self.db, &generics); | 492 | let substs = generics.type_params_subst(self.db); |
479 | let ty = self.db.impl_self_ty(impl_id).subst(&substs); | 493 | let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs); |
480 | match unresolved { | 494 | self.resolve_variant_on_alias(ty, unresolved, path) |
481 | None => { | ||
482 | let variant = ty_variant(&ty); | ||
483 | (ty, variant) | ||
484 | } | ||
485 | Some(1) => { | ||
486 | let segment = path.mod_path().segments().last().unwrap(); | ||
487 | // this could be an enum variant or associated type | ||
488 | if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { | ||
489 | let enum_data = self.db.enum_data(enum_id); | ||
490 | if let Some(local_id) = enum_data.variant(segment) { | ||
491 | let variant = EnumVariantId { parent: enum_id, local_id }; | ||
492 | return (ty, Some(variant.into())); | ||
493 | } | ||
494 | } | ||
495 | // FIXME potentially resolve assoc type | ||
496 | (self.err_ty(), None) | ||
497 | } | ||
498 | Some(_) => { | ||
499 | // FIXME diagnostic | ||
500 | (self.err_ty(), None) | ||
501 | } | ||
502 | } | ||
503 | } | 495 | } |
504 | TypeNs::TypeAliasId(it) => { | 496 | TypeNs::TypeAliasId(it) => { |
505 | let substs = Substitution::build_for_def(self.db, it) | 497 | let ty = TyBuilder::def_ty(self.db, it.into()) |
506 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) | 498 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) |
507 | .build(); | 499 | .build(); |
508 | let ty = self.db.ty(it.into()).subst(&substs); | 500 | self.resolve_variant_on_alias(ty, unresolved, path) |
509 | let variant = ty_variant(&ty); | ||
510 | forbid_unresolved_segments((ty, variant), unresolved) | ||
511 | } | 501 | } |
512 | TypeNs::AdtSelfType(_) => { | 502 | TypeNs::AdtSelfType(_) => { |
513 | // FIXME this could happen in array size expressions, once we're checking them | 503 | // FIXME this could happen in array size expressions, once we're checking them |
@@ -531,19 +521,46 @@ impl<'a> InferenceContext<'a> { | |||
531 | result | 521 | result |
532 | } else { | 522 | } else { |
533 | // FIXME diagnostic | 523 | // FIXME diagnostic |
534 | (TyKind::Unknown.intern(&Interner), None) | 524 | (TyKind::Error.intern(&Interner), None) |
535 | } | 525 | } |
536 | } | 526 | } |
527 | } | ||
537 | 528 | ||
538 | fn ty_variant(ty: &Ty) -> Option<VariantId> { | 529 | fn resolve_variant_on_alias( |
539 | ty.as_adt().and_then(|(adt_id, _)| match adt_id { | 530 | &mut self, |
540 | AdtId::StructId(s) => Some(VariantId::StructId(s)), | 531 | ty: Ty, |
541 | AdtId::UnionId(u) => Some(VariantId::UnionId(u)), | 532 | unresolved: Option<usize>, |
542 | AdtId::EnumId(_) => { | 533 | path: &Path, |
543 | // FIXME Error E0071, expected struct, variant or union type, found enum `Foo` | 534 | ) -> (Ty, Option<VariantId>) { |
544 | None | 535 | match unresolved { |
536 | None => { | ||
537 | let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id { | ||
538 | AdtId::StructId(s) => Some(VariantId::StructId(s)), | ||
539 | AdtId::UnionId(u) => Some(VariantId::UnionId(u)), | ||
540 | AdtId::EnumId(_) => { | ||
541 | // FIXME Error E0071, expected struct, variant or union type, found enum `Foo` | ||
542 | None | ||
543 | } | ||
544 | }); | ||
545 | (ty, variant) | ||
546 | } | ||
547 | Some(1) => { | ||
548 | let segment = path.mod_path().segments().last().unwrap(); | ||
549 | // this could be an enum variant or associated type | ||
550 | if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() { | ||
551 | let enum_data = self.db.enum_data(enum_id); | ||
552 | if let Some(local_id) = enum_data.variant(segment) { | ||
553 | let variant = EnumVariantId { parent: enum_id, local_id }; | ||
554 | return (ty, Some(variant.into())); | ||
555 | } | ||
545 | } | 556 | } |
546 | }) | 557 | // FIXME potentially resolve assoc type |
558 | (self.err_ty(), None) | ||
559 | } | ||
560 | Some(_) => { | ||
561 | // FIXME diagnostic | ||
562 | (self.err_ty(), None) | ||
563 | } | ||
547 | } | 564 | } |
548 | } | 565 | } |
549 | 566 | ||
@@ -681,25 +698,6 @@ impl<'a> InferenceContext<'a> { | |||
681 | } | 698 | } |
682 | } | 699 | } |
683 | 700 | ||
684 | /// The kinds of placeholders we need during type inference. There's separate | ||
685 | /// values for general types, and for integer and float variables. The latter | ||
686 | /// two are used for inference of literal values (e.g. `100` could be one of | ||
687 | /// several integer types). | ||
688 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | ||
689 | pub struct InferenceVar { | ||
690 | index: u32, | ||
691 | } | ||
692 | |||
693 | impl InferenceVar { | ||
694 | fn to_inner(self) -> unify::TypeVarId { | ||
695 | unify::TypeVarId(self.index) | ||
696 | } | ||
697 | |||
698 | fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self { | ||
699 | InferenceVar { index } | ||
700 | } | ||
701 | } | ||
702 | |||
703 | /// When inferring an expression, we propagate downward whatever type hint we | 701 | /// When inferring an expression, we propagate downward whatever type hint we |
704 | /// are able in the form of an `Expectation`. | 702 | /// are able in the form of an `Expectation`. |
705 | #[derive(Clone, PartialEq, Eq, Debug)] | 703 | #[derive(Clone, PartialEq, Eq, Debug)] |
@@ -744,7 +742,7 @@ impl Expectation { | |||
744 | fn none() -> Self { | 742 | fn none() -> Self { |
745 | Expectation { | 743 | Expectation { |
746 | // FIXME | 744 | // FIXME |
747 | ty: TyKind::Unknown.intern(&Interner), | 745 | ty: TyKind::Error.intern(&Interner), |
748 | rvalue_hint: false, | 746 | rvalue_hint: false, |
749 | } | 747 | } |
750 | } | 748 | } |
@@ -752,7 +750,7 @@ impl Expectation { | |||
752 | fn coercion_target(&self) -> Ty { | 750 | fn coercion_target(&self) -> Ty { |
753 | if self.rvalue_hint { | 751 | if self.rvalue_hint { |
754 | // FIXME | 752 | // FIXME |
755 | TyKind::Unknown.intern(&Interner) | 753 | TyKind::Error.intern(&Interner) |
756 | } else { | 754 | } else { |
757 | self.ty.clone() | 755 | self.ty.clone() |
758 | } | 756 | } |