Skip to content

Commit 516174e

Browse files
committed
fix: Allow unknown guidance when try to coerce unsized
1 parent 3ab1666 commit 516174e

File tree

2 files changed

+70
-15
lines changed

2 files changed

+70
-15
lines changed

crates/hir-ty/src/infer/coerce.rs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
88
use std::iter;
99

10-
use chalk_ir::{cast::Cast, BoundVar, Goal, Mutability, TyKind, TyVariableKind};
10+
use chalk_ir::{cast::Cast, BoundVar, Mutability, TyKind, TyVariableKind};
1111
use hir_def::{
1212
hir::ExprId,
1313
lang_item::{LangItem, LangItemTarget},
@@ -24,8 +24,8 @@ use crate::{
2424
},
2525
static_lifetime,
2626
utils::ClosureSubst,
27-
Canonical, DomainGoal, FnPointer, FnSig, Guidance, InEnvironment, Interner, Solution,
28-
Substitution, TraitEnvironment, Ty, TyBuilder, TyExt,
27+
Canonical, FnPointer, FnSig, Goal, Guidance, InEnvironment, Interner, Solution, Substitution,
28+
TraitEnvironment, Ty, TyBuilder, TyExt,
2929
};
3030

3131
use super::unify::InferenceTable;
@@ -42,11 +42,7 @@ fn simple(kind: Adjust) -> impl FnOnce(Ty) -> Vec<Adjustment> {
4242
}
4343

4444
/// This always returns `Ok(...)`.
45-
fn success(
46-
adj: Vec<Adjustment>,
47-
target: Ty,
48-
goals: Vec<InEnvironment<Goal<Interner>>>,
49-
) -> CoerceResult {
45+
fn success(adj: Vec<Adjustment>, target: Ty, goals: Vec<InEnvironment<Goal>>) -> CoerceResult {
5046
Ok(InferOk { goals, value: (adj, target) })
5147
}
5248

@@ -229,8 +225,6 @@ impl InferenceContext<'_> {
229225
from_ty: &Ty,
230226
to_ty: &Ty,
231227
) -> Result<Ty, TypeError> {
232-
let from_ty = self.resolve_ty_shallow(from_ty);
233-
let to_ty = self.resolve_ty_shallow(to_ty);
234228
let (adjustments, ty) = self.table.coerce(&from_ty, &to_ty)?;
235229
if let Some(expr) = expr {
236230
self.write_expr_adj(expr, adjustments);
@@ -411,10 +405,10 @@ impl InferenceTable<'_> {
411405
// mutability [1], since it may be that we are coercing
412406
// from `&mut T` to `&U`.
413407
let lt = static_lifetime(); // FIXME: handle lifetimes correctly, see rustc
414-
let derefd_from_ty = TyKind::Ref(to_mt, lt, referent_ty).intern(Interner);
415-
match autoderef.table.try_unify(&derefd_from_ty, to_ty) {
408+
let derefed_from_ty = TyKind::Ref(to_mt, lt, referent_ty).intern(Interner);
409+
match autoderef.table.try_unify(&derefed_from_ty, to_ty) {
416410
Ok(result) => {
417-
found = Some(result.map(|()| derefd_from_ty));
411+
found = Some(result.map(|()| derefed_from_ty));
418412
break;
419413
}
420414
Err(err) => {
@@ -626,6 +620,7 @@ impl InferenceTable<'_> {
626620
}
627621
_ => None,
628622
};
623+
let must_be_unsized = must_be_coerce_unsized(from_ty, to_ty);
629624
let coerce_from =
630625
reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone());
631626

@@ -644,7 +639,7 @@ impl InferenceTable<'_> {
644639
b.push(coerce_from).push(to_ty.clone()).build()
645640
};
646641

647-
let goal: InEnvironment<DomainGoal> =
642+
let goal: InEnvironment<Goal> =
648643
InEnvironment::new(&self.trait_env.env, coerce_unsized_tref.cast(Interner));
649644

650645
let canonicalized = self.canonicalize(goal);
@@ -673,7 +668,9 @@ impl InferenceTable<'_> {
673668
// FIXME need to record an obligation here
674669
canonicalized.apply_solution(self, subst)
675670
}
676-
// FIXME actually we maybe should also accept unknown guidance here
671+
Solution::Ambig(Guidance::Unknown) if must_be_unsized => {
672+
// FIXME need to record an obligation here too
673+
}
677674
_ => return Err(TypeError),
678675
};
679676
let unsize =
@@ -715,6 +712,19 @@ fn coerce_mutabilities(from: Mutability, to: Mutability) -> Result<(), TypeError
715712
}
716713
}
717714

715+
// a temporary workaroud for coerce_unsized
716+
fn must_be_coerce_unsized(from_ty: &Ty, to_ty: &Ty) -> bool {
717+
// TODO: many other cases
718+
match (from_ty.kind(Interner), to_ty.kind(Interner)) {
719+
(TyKind::Ref(_, _, from_ty), TyKind::Ref(_, _, to_ty)) => {
720+
must_be_coerce_unsized(from_ty, to_ty)
721+
}
722+
(_, TyKind::Dyn(_)) => true,
723+
(TyKind::Array(_, _), TyKind::Slice(_)) => true,
724+
(_, _) => false,
725+
}
726+
}
727+
718728
pub(super) fn auto_deref_adjust_steps(autoderef: &Autoderef<'_, '_>) -> Vec<Adjustment> {
719729
let steps = autoderef.steps();
720730
let targets =

crates/hir-ty/src/tests/coercion.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,3 +941,48 @@ fn main() {
941941
"#,
942942
)
943943
}
944+
945+
#[test]
946+
fn coerce_unsized_impl_trait() {
947+
check_no_mismatches(
948+
r#"
949+
//- minicore: coerce_unsized
950+
struct Sender<T>;
951+
952+
impl<T> Sender<T> {
953+
fn send(&self, msg: T) {}
954+
}
955+
956+
trait SelectHandle {}
957+
958+
impl<T> SelectHandle for Sender<T> {}
959+
960+
impl<T: SelectHandle> SelectHandle for &T {}
961+
962+
fn foo() {
963+
let sender = Sender;
964+
965+
let _handle: &dyn SelectHandle = &sender;
966+
967+
sender.send(0_usize);
968+
}
969+
"#,
970+
);
971+
}
972+
973+
#[test]
974+
fn coerce_unsized_impl_trait2() {
975+
check_no_mismatches(
976+
r#"
977+
//- minicore: fmt, coerce_unsized
978+
fn print_me_later(x: &dyn Debug) -> impl FnOnce() + '_ {
979+
move || println!("{x:?}")
980+
}
981+
982+
fn main() {
983+
let f = print_me_later(&22);
984+
f()
985+
}
986+
"#,
987+
);
988+
}

0 commit comments

Comments
 (0)