diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index a76d33c0cd..43a24c7136 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -1024,7 +1024,7 @@ impl<'a> InferenceContext<'a> { pub(crate) enum Expectation { None, HasType(Ty), - // Castable(Ty), // rustc has this, we currently just don't propagate an expectation for casts + Castable(Ty), RValueLikeUnsized(Ty), } @@ -1077,6 +1077,7 @@ impl Expectation { match self { Expectation::None => Expectation::None, Expectation::HasType(t) => Expectation::HasType(table.resolve_ty_shallow(t)), + Expectation::Castable(t) => Expectation::Castable(table.resolve_ty_shallow(t)), Expectation::RValueLikeUnsized(t) => { Expectation::RValueLikeUnsized(table.resolve_ty_shallow(t)) } @@ -1086,17 +1087,18 @@ impl Expectation { fn to_option(&self, table: &mut unify::InferenceTable<'_>) -> Option { match self.resolve(table) { Expectation::None => None, - Expectation::HasType(t) | - // Expectation::Castable(t) | - Expectation::RValueLikeUnsized(t) => Some(t), + Expectation::HasType(t) + | Expectation::Castable(t) + | Expectation::RValueLikeUnsized(t) => Some(t), } } fn only_has_type(&self, table: &mut unify::InferenceTable<'_>) -> Option { match self { Expectation::HasType(t) => Some(table.resolve_ty_shallow(t)), - // Expectation::Castable(_) | - Expectation::RValueLikeUnsized(_) | Expectation::None => None, + Expectation::Castable(_) | Expectation::RValueLikeUnsized(_) | Expectation::None => { + None + } } } diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs index 7b9bf0c5cf..f0655291b8 100644 --- a/crates/hir-ty/src/infer/expr.rs +++ b/crates/hir-ty/src/infer/expr.rs @@ -610,9 +610,9 @@ impl<'a> InferenceContext<'a> { } } Expr::Cast { expr, type_ref } => { - // FIXME: propagate the "castable to" expectation (and find a test case that shows this is necessary) - let _inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); let cast_ty = self.make_ty(type_ref); + let _inner_ty = + self.infer_expr_inner(*expr, &Expectation::Castable(cast_ty.clone())); // FIXME check the cast... cast_ty } diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs index 146145523b..6f6b334c94 100644 --- a/crates/hir-ty/src/tests/simple.rs +++ b/crates/hir-ty/src/tests/simple.rs @@ -3200,3 +3200,34 @@ fn func() { "#, ); } +#[test] +fn castable_to() { + check_infer( + r#" +//- minicore: sized +#[lang = "owned_box"] +pub struct Box { + inner: *mut T, +} +impl Box { + fn new(t: T) -> Self { loop {} } +} + +fn func() { + let x = Box::new([]) as Box<[i32; 0]>; +} +"#, + expect![[r#" + 99..100 't': T + 113..124 '{ loop {} }': Box + 115..122 'loop {}': ! + 120..122 '{}': () + 138..184 '{ ...0]>; }': () + 148..149 'x': Box<[i32; 0]> + 152..160 'Box::new': fn new<[i32; 0]>([i32; 0]) -> Box<[i32; 0]> + 152..164 'Box::new([])': Box<[i32; 0]> + 152..181 'Box::n...2; 0]>': Box<[i32; 0]> + 161..163 '[]': [i32; 0] + "#]], + ); +}