Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer.rs')
| -rw-r--r-- | crates/hir-ty/src/infer.rs | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index f229bf2f64..d3e7f6e7dc 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -66,8 +66,10 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer let mut ctx = InferenceContext::new(db, def, &body, resolver); match def { + DefWithBodyId::FunctionId(f) => { + ctx.collect_fn(f); + } DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)), - DefWithBodyId::FunctionId(f) => ctx.collect_fn(f), DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)), DefWithBodyId::VariantId(v) => { ctx.return_ty = TyBuilder::builtin(match db.enum_data(v.parent).variant_body_type() { @@ -392,9 +394,12 @@ pub(crate) struct InferenceContext<'a> { /// currently within one. /// /// We might consider using a nested inference context for checking - /// closures, but currently this is the only field that will change there, - /// so it doesn't make sense. + /// closures so we can swap all shared things out at once. return_ty: Ty, + /// If `Some`, this stores coercion information for returned + /// expressions. If `None`, this is in a context where return is + /// inappropriate, such as a const expression. + return_coercion: Option<CoerceMany>, /// The resume type and the yield type, respectively, of the generator being inferred. resume_yield_tys: Option<(Ty, Ty)>, diverges: Diverges, @@ -462,6 +467,7 @@ impl<'a> InferenceContext<'a> { trait_env, return_ty: TyKind::Error.intern(Interner), // set in collect_* calls resume_yield_tys: None, + return_coercion: None, db, owner, body, @@ -595,10 +601,19 @@ impl<'a> InferenceContext<'a> { }; self.return_ty = self.normalize_associated_types_in(return_ty); + self.return_coercion = Some(CoerceMany::new(self.return_ty.clone())); } fn infer_body(&mut self) { - self.infer_expr_coerce(self.body.body_expr, &Expectation::has_type(self.return_ty.clone())); + match self.return_coercion { + Some(_) => self.infer_return(self.body.body_expr), + None => { + _ = self.infer_expr_coerce( + self.body.body_expr, + &Expectation::has_type(self.return_ty.clone()), + ) + } + } } fn write_expr_ty(&mut self, expr: ExprId, ty: Ty) { |