Deal with goals arising from unification

This commit is contained in:
Florian Diebold 2021-05-16 18:27:17 +02:00
parent 4bd446f5b3
commit 9716c0b949
4 changed files with 21 additions and 18 deletions

View File

@ -37,8 +37,8 @@ use syntax::SmolStr;
use super::{DomainGoal, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty}; use super::{DomainGoal, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty};
use crate::{ use crate::{
db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic, db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic,
lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyExt, lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Goal, Interner, TyBuilder,
TyKind, TyExt, TyKind,
}; };
// This lint has a false positive here. See the link below for details. // This lint has a false positive here. See the link below for details.
@ -104,7 +104,7 @@ impl Default for BindingMode {
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct InferOk { pub(crate) struct InferOk {
// obligations goals: Vec<InEnvironment<Goal>>,
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct TypeError; pub(crate) struct TypeError;

View File

@ -26,8 +26,8 @@ impl<'a> InferenceContext<'a> {
return true; return true;
} }
match self.coerce_inner(from_ty, &to_ty) { match self.coerce_inner(from_ty, &to_ty) {
Ok(_result) => { Ok(result) => {
// TODO deal with goals self.table.register_infer_ok(result);
true true
} }
Err(_) => { Err(_) => {
@ -67,8 +67,9 @@ impl<'a> InferenceContext<'a> {
let target_ty = TyKind::Function(sig.to_fn_ptr()).intern(&Interner); let target_ty = TyKind::Function(sig.to_fn_ptr()).intern(&Interner);
let result1 = self.coerce_inner(ty1.clone(), &target_ty); let result1 = self.coerce_inner(ty1.clone(), &target_ty);
let result2 = self.coerce_inner(ty2.clone(), &target_ty); let result2 = self.coerce_inner(ty2.clone(), &target_ty);
if let (Ok(_result1), Ok(_result2)) = (result1, result2) { if let (Ok(result1), Ok(result2)) = (result1, result2) {
// TODO deal with the goals self.table.register_infer_ok(result1);
self.table.register_infer_ok(result2);
return target_ty; return target_ty;
} }
} }
@ -104,7 +105,7 @@ impl<'a> InferenceContext<'a> {
} }
_ => {} _ => {}
} }
return Ok(InferOk {}); return Ok(InferOk { goals: Vec::new() });
} }
// Consider coercing the subtype to a DST // Consider coercing the subtype to a DST
@ -416,10 +417,11 @@ impl<'a> InferenceContext<'a> {
}, },
); );
} }
// FIXME: should we accept ambiguous results here?
_ => return Err(TypeError), _ => 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) { match (from, to) {
(Mutability::Mut, Mutability::Mut) (Mutability::Mut, Mutability::Mut)
| (Mutability::Mut, Mutability::Not) | (Mutability::Mut, Mutability::Not)
| (Mutability::Not, Mutability::Not) => Ok(InferOk {}), | (Mutability::Not, Mutability::Not) => Ok(()),
(Mutability::Not, Mutability::Mut) => Err(TypeError), (Mutability::Not, Mutability::Mut) => Err(TypeError),
} }
} }

View File

@ -307,12 +307,12 @@ impl<'a> InferenceTable<'a> {
/// Unify two types and register new trait goals that arise from that. /// Unify two types and register new trait goals that arise from that.
// TODO give these two functions better names // TODO give these two functions better names
pub(crate) fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 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 r
} else { } else {
return false; return false;
}; };
// TODO deal with new goals self.register_infer_ok(result);
true true
} }
@ -327,10 +327,7 @@ impl<'a> InferenceTable<'a> {
t1, t1,
t2, t2,
) { ) {
Ok(_result) => { Ok(result) => Ok(InferOk { goals: result.goals }),
// TODO deal with new goals
Ok(InferOk {})
}
Err(chalk_ir::NoSolution) => Err(TypeError), Err(chalk_ir::NoSolution) => Err(TypeError),
} }
} }
@ -353,6 +350,10 @@ impl<'a> InferenceTable<'a> {
} }
} }
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) { pub fn resolve_obligations_as_possible(&mut self) {
let _span = profile::span("resolve_obligations_as_possible"); let _span = profile::span("resolve_obligations_as_possible");
let mut changed = true; let mut changed = true;

View File

@ -758,7 +758,7 @@ fn issue_4885() {
"#, "#,
expect![[r#" expect![[r#"
136..139 'key': &K 136..139 'key': &K
198..214 '{ ...key) }': {unknown} 198..214 '{ ...key) }': impl Future<Output = <K as Foo<R>>::Bar>
204..207 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar> 204..207 'bar': fn bar<R, K>(&K) -> impl Future<Output = <K as Foo<R>>::Bar>
204..212 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar> 204..212 'bar(key)': impl Future<Output = <K as Foo<R>>::Bar>
208..211 'key': &K 208..211 'key': &K