Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/infer.rs14
-rw-r--r--crates/hir-ty/src/infer/expr.rs4
-rw-r--r--crates/hir-ty/src/tests/simple.rs31
3 files changed, 41 insertions, 8 deletions
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<Ty> {
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<Ty> {
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<T: ?Sized> {
+ inner: *mut T,
+}
+impl<T> Box<T> {
+ 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<T>
+ 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]
+ "#]],
+ );
+}