Skip to content

Commit

Permalink
Fix inference of literals when the expectation is Castable
Browse files Browse the repository at this point in the history
  • Loading branch information
ChayimFriedman2 committed Sep 11, 2024
1 parent 51cc5a7 commit 5ea245e
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 9 deletions.
37 changes: 34 additions & 3 deletions src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -895,21 +895,52 @@ impl InferenceContext<'_> {
TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty)))
.intern(Interner)
}
None => self.table.new_integer_var(),
None => {
let expected_ty = expected.to_option(&mut self.table);
let opt_ty = match expected_ty.as_ref().map(|it| it.kind(Interner)) {
Some(TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))) => expected_ty,
Some(TyKind::Scalar(Scalar::Char)) => {
Some(TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner))
}
Some(TyKind::Raw(..) | TyKind::FnDef(..) | TyKind::Function(..)) => {
Some(TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner))
}
_ => None,
};
opt_ty.unwrap_or_else(|| self.table.new_integer_var())
}
},
Literal::Uint(_v, ty) => match ty {
Some(int_ty) => {
TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty)))
.intern(Interner)
}
None => self.table.new_integer_var(),
None => {
let expected_ty = expected.to_option(&mut self.table);
let opt_ty = match expected_ty.as_ref().map(|it| it.kind(Interner)) {
Some(TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))) => expected_ty,
Some(TyKind::Scalar(Scalar::Char)) => {
Some(TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner))
}
Some(TyKind::Raw(..) | TyKind::FnDef(..) | TyKind::Function(..)) => {
Some(TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner))
}
_ => None,
};
opt_ty.unwrap_or_else(|| self.table.new_integer_var())
}
},
Literal::Float(_v, ty) => match ty {
Some(float_ty) => {
TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty)))
.intern(Interner)
}
None => self.table.new_float_var(),
None => {
let opt_ty = expected.to_option(&mut self.table).filter(|ty| {
matches!(ty.kind(Interner), TyKind::Scalar(Scalar::Float(_)))
});
opt_ty.unwrap_or_else(|| self.table.new_float_var())
}
},
},
Expr::Underscore => {
Expand Down
4 changes: 2 additions & 2 deletions src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn let_stmt_coerce() {
//- minicore: coerce_unsized
fn test() {
let x: &[isize] = &[1];
// ^^^^ adjustments: Deref(None), Borrow(Ref('?3, Not)), Pointer(Unsize)
// ^^^^ adjustments: Deref(None), Borrow(Ref('?2, Not)), Pointer(Unsize)
let x: *const [isize] = &[1];
// ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize)
}
Expand Down Expand Up @@ -148,7 +148,7 @@ fn foo<T>(x: &[T]) -> &[T] { x }
fn test(i: i32) {
let x = match i {
2 => foo(&[2]),
// ^^^^ adjustments: Deref(None), Borrow(Ref('?10, Not)), Pointer(Unsize)
// ^^^^ adjustments: Deref(None), Borrow(Ref('?8, Not)), Pointer(Unsize)
1 => &[1],
_ => &[3],
};
Expand Down
2 changes: 1 addition & 1 deletion src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ fn test(a: A<i32>) {
278..279 'A': extern "rust-call" A<i32>(*mut i32) -> A<i32>
278..292 'A(0 as *mut _)': A<i32>
278..307 'A(0 as...B(a)))': &'? i32
280..281 '0': i32
280..281 '0': usize
280..291 '0 as *mut _': *mut i32
297..306 '&&B(B(a))': &'? &'? B<B<A<i32>>>
298..306 '&B(B(a))': &'? B<B<A<i32>>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -441,16 +441,16 @@ fn main() {
//^^^^^^^^^^^^^^^^^ error: cannot cast thin pointer `*const i32` to fat pointer `*const [i32]`
let t: *mut (dyn Trait + 'static) = 0 as *mut _;
//^^^^^^^^^^^ error: cannot cast `i32` to a fat pointer `*mut _`
//^^^^^^^^^^^ error: cannot cast `usize` to a fat pointer `*mut _`
let mut fail: *const str = 0 as *const str;
//^^^^^^^^^^^^^^^ error: cannot cast `i32` to a fat pointer `*const str`
//^^^^^^^^^^^^^^^ error: cannot cast `usize` to a fat pointer `*const str`
let mut fail2: *const str = 0isize as *const str;
//^^^^^^^^^^^^^^^^^^^^ error: cannot cast `isize` to a fat pointer `*const str`
}
fn foo<T: ?Sized>() {
let s = 0 as *const T;
//^^^^^^^^^^^^^ error: cannot cast `i32` to a fat pointer `*const T`
//^^^^^^^^^^^^^ error: cannot cast `usize` to a fat pointer `*const T`
}
"#,
&["E0308", "unused_variables"],
Expand Down Expand Up @@ -1100,4 +1100,15 @@ where
"#,
);
}

#[test]
fn cast_literal_to_char() {
check_diagnostics(
r#"
fn foo() {
0 as char;
}
"#,
);
}
}

0 comments on commit 5ea245e

Please sign in to comment.