From d9fb76157dbcedd830b2b3f31aa220f95c431c9a Mon Sep 17 00:00:00 2001 From: austaras Date: Sun, 31 Dec 2023 13:45:37 +0800 Subject: [PATCH] fix: Allow unknown guidance when try to coerce unsized --- crates/hir-ty/src/infer/coerce.rs | 41 ++++++++++++++++---------- crates/hir-ty/src/tests/coercion.rs | 45 +++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 15 deletions(-) diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs index 8e7e62c4961c..9f271dedb00e 100644 --- a/crates/hir-ty/src/infer/coerce.rs +++ b/crates/hir-ty/src/infer/coerce.rs @@ -7,7 +7,7 @@ use std::iter; -use chalk_ir::{cast::Cast, BoundVar, Goal, Mutability, TyKind, TyVariableKind}; +use chalk_ir::{cast::Cast, BoundVar, Mutability, TyKind, TyVariableKind}; use hir_def::{ hir::ExprId, lang_item::{LangItem, LangItemTarget}, @@ -24,8 +24,8 @@ use crate::{ }, static_lifetime, utils::ClosureSubst, - Canonical, DomainGoal, FnPointer, FnSig, Guidance, InEnvironment, Interner, Solution, - Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, + Canonical, FnPointer, FnSig, Goal, Guidance, InEnvironment, Interner, Solution, Substitution, + TraitEnvironment, Ty, TyBuilder, TyExt, }; use super::unify::InferenceTable; @@ -42,11 +42,7 @@ fn simple(kind: Adjust) -> impl FnOnce(Ty) -> Vec { } /// This always returns `Ok(...)`. -fn success( - adj: Vec, - target: Ty, - goals: Vec>>, -) -> CoerceResult { +fn success(adj: Vec, target: Ty, goals: Vec>) -> CoerceResult { Ok(InferOk { goals, value: (adj, target) }) } @@ -229,8 +225,6 @@ impl InferenceContext<'_> { from_ty: &Ty, to_ty: &Ty, ) -> Result { - let from_ty = self.resolve_ty_shallow(from_ty); - let to_ty = self.resolve_ty_shallow(to_ty); let (adjustments, ty) = self.table.coerce(&from_ty, &to_ty)?; if let Some(expr) = expr { self.write_expr_adj(expr, adjustments); @@ -411,10 +405,10 @@ impl InferenceTable<'_> { // mutability [1], since it may be that we are coercing // from `&mut T` to `&U`. let lt = static_lifetime(); // FIXME: handle lifetimes correctly, see rustc - let derefd_from_ty = TyKind::Ref(to_mt, lt, referent_ty).intern(Interner); - match autoderef.table.try_unify(&derefd_from_ty, to_ty) { + let derefed_from_ty = TyKind::Ref(to_mt, lt, referent_ty).intern(Interner); + match autoderef.table.try_unify(&derefed_from_ty, to_ty) { Ok(result) => { - found = Some(result.map(|()| derefd_from_ty)); + found = Some(result.map(|()| derefed_from_ty)); break; } Err(err) => { @@ -626,6 +620,7 @@ impl InferenceTable<'_> { } _ => None, }; + let must_be_unsized = must_be_coerce_unsized(from_ty, to_ty); let coerce_from = reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone()); @@ -644,7 +639,7 @@ impl InferenceTable<'_> { b.push(coerce_from).push(to_ty.clone()).build() }; - let goal: InEnvironment = + let goal: InEnvironment = InEnvironment::new(&self.trait_env.env, coerce_unsized_tref.cast(Interner)); let canonicalized = self.canonicalize(goal); @@ -673,7 +668,10 @@ impl InferenceTable<'_> { // FIXME need to record an obligation here canonicalized.apply_solution(self, subst) } - // FIXME actually we maybe should also accept unknown guidance here + // FIXME workaround for #11847 and #15984, maybe removed after new trait solver + Solution::Ambig(Guidance::Unknown) if must_be_unsized => { + // FIXME need to record an obligation here too + } _ => return Err(TypeError), }; let unsize = @@ -715,6 +713,19 @@ fn coerce_mutabilities(from: Mutability, to: Mutability) -> Result<(), TypeError } } +// a temporary workaroud for coerce_unsized +fn must_be_coerce_unsized(from_ty: &Ty, to_ty: &Ty) -> bool { + // FIXME: many other cases + match (from_ty.kind(Interner), to_ty.kind(Interner)) { + (TyKind::Ref(_, _, from_ty), TyKind::Ref(_, _, to_ty)) => { + must_be_coerce_unsized(from_ty, to_ty) + } + (_, TyKind::Dyn(_)) => true, + (TyKind::Array(_, _), TyKind::Slice(_)) => true, + (_, _) => false, + } +} + pub(super) fn auto_deref_adjust_steps(autoderef: &Autoderef<'_, '_>) -> Vec { let steps = autoderef.steps(); let targets = diff --git a/crates/hir-ty/src/tests/coercion.rs b/crates/hir-ty/src/tests/coercion.rs index 16e5ef85d09d..22fd39bfef8f 100644 --- a/crates/hir-ty/src/tests/coercion.rs +++ b/crates/hir-ty/src/tests/coercion.rs @@ -941,3 +941,48 @@ fn main() { "#, ) } + +#[test] +fn coerce_unsized_impl_trait() { + check_no_mismatches( + r#" +//- minicore: coerce_unsized +struct Sender; + +impl Sender { + fn send(&self, msg: T) {} +} + +trait SelectHandle {} + +impl SelectHandle for Sender {} + +impl SelectHandle for &T {} + +fn foo() { + let sender = Sender; + + let _handle: &dyn SelectHandle = &sender; + + sender.send(0_usize); +} + "#, + ); +} + +#[test] +fn coerce_unsized_impl_trait2() { + check_no_mismatches( + r#" +//- minicore: fmt, coerce_unsized +fn print_me_later(x: &dyn Debug) -> impl FnOnce() + '_ { + move || println!("{x:?}") +} + +fn main() { + let f = print_me_later(&22); + f() +} + "#, + ); +}