From 9716c0b949b1a1a95b3f36928faed3abc21c0bda Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 16 May 2021 18:27:17 +0200 Subject: [PATCH] Deal with goals arising from unification --- crates/hir_ty/src/infer.rs | 6 +++--- crates/hir_ty/src/infer/coerce.rs | 18 ++++++++++-------- crates/hir_ty/src/infer/unify.rs | 13 +++++++------ crates/hir_ty/src/tests/regression.rs | 2 +- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index ab742e2032e..db223401824 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -37,8 +37,8 @@ use super::{DomainGoal, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty}; use crate::{ db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, - lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyExt, - TyKind, + lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Goal, Interner, TyBuilder, + TyExt, TyKind, }; // This lint has a false positive here. See the link below for details. @@ -104,7 +104,7 @@ fn default() -> Self { #[derive(Debug)] pub(crate) struct InferOk { - // obligations + goals: Vec>, } #[derive(Debug)] pub(crate) struct TypeError; diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 00b2b585f44..60186bc5f94 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs @@ -26,8 +26,8 @@ pub(super) fn coerce(&mut self, from_ty: &Ty, to_ty: &Ty) -> bool { return true; } match self.coerce_inner(from_ty, &to_ty) { - Ok(_result) => { - // TODO deal with goals + Ok(result) => { + self.table.register_infer_ok(result); true } Err(_) => { @@ -67,8 +67,9 @@ pub(super) fn coerce_merge_branch(&mut self, ty1: &Ty, ty2: &Ty) -> Ty { let target_ty = TyKind::Function(sig.to_fn_ptr()).intern(&Interner); let result1 = self.coerce_inner(ty1.clone(), &target_ty); let result2 = self.coerce_inner(ty2.clone(), &target_ty); - if let (Ok(_result1), Ok(_result2)) = (result1, result2) { - // TODO deal with the goals + if let (Ok(result1), Ok(result2)) = (result1, result2) { + self.table.register_infer_ok(result1); + self.table.register_infer_ok(result2); return target_ty; } } @@ -104,7 +105,7 @@ fn coerce_inner(&mut self, from_ty: Ty, to_ty: &Ty) -> InferResult { } _ => {} } - return Ok(InferOk {}); + return Ok(InferOk { goals: Vec::new() }); } // Consider coercing the subtype to a DST @@ -416,10 +417,11 @@ fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty) -> InferResult { }, ); } + // FIXME: should we accept ambiguous results here? _ => return Err(TypeError), }; - Ok(InferOk {}) + Ok(InferOk { goals: Vec::new() }) } } @@ -444,11 +446,11 @@ fn safe_to_unsafe_fn_ty(fn_ty: FnPointer) -> FnPointer { } } -fn coerce_mutabilities(from: Mutability, to: Mutability) -> InferResult { +fn coerce_mutabilities(from: Mutability, to: Mutability) -> Result<(), TypeError> { match (from, to) { (Mutability::Mut, Mutability::Mut) | (Mutability::Mut, Mutability::Not) - | (Mutability::Not, Mutability::Not) => Ok(InferOk {}), + | (Mutability::Not, Mutability::Not) => Ok(()), (Mutability::Not, Mutability::Mut) => Err(TypeError), } } diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 539e124204d..d872cdd58aa 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs @@ -307,12 +307,12 @@ pub(crate) fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { /// Unify two types and register new trait goals that arise from that. // TODO give these two functions better names pub(crate) fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { - let _result = if let Ok(r) = self.unify_inner(ty1, ty2) { + let result = if let Ok(r) = self.unify_inner(ty1, ty2) { r } else { return false; }; - // TODO deal with new goals + self.register_infer_ok(result); true } @@ -327,10 +327,7 @@ pub(crate) fn unify_inner>(&mut self, t1: &T, t2: &T) -> InferR t1, t2, ) { - Ok(_result) => { - // TODO deal with new goals - Ok(InferOk {}) - } + Ok(result) => Ok(InferOk { goals: result.goals }), Err(chalk_ir::NoSolution) => Err(TypeError), } } @@ -353,6 +350,10 @@ fn register_obligation_in_env(&mut self, goal: InEnvironment) { } } + pub fn register_infer_ok(&mut self, infer_ok: InferOk) { + infer_ok.goals.into_iter().for_each(|goal| self.register_obligation_in_env(goal)); + } + pub fn resolve_obligations_as_possible(&mut self) { let _span = profile::span("resolve_obligations_as_possible"); let mut changed = true; diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index baef8159010..ad9edf11cd7 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs @@ -758,7 +758,7 @@ fn bar(key: &K) -> impl Future "#, expect![[r#" 136..139 'key': &K - 198..214 '{ ...key) }': {unknown} + 198..214 '{ ...key) }': impl Future>::Bar> 204..207 'bar': fn bar(&K) -> impl Future>::Bar> 204..212 'bar(key)': impl Future>::Bar> 208..211 'key': &K