Skip to content

Commit 972e8ba

Browse files
committed
Auto merge of rust-lang#18101 - ChayimFriedman2:inference-fix, r=Veykril
fix: Fix inference of literals when the expectation is Castable I followed the compiler: https://github.com/rust-lang/rust/blob/5bce6d48ff09dcb2613278ec93013795718478ef/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs#L1560-L1579. Fixes rust-lang#18095.
2 parents 51cc5a7 + 5ea245e commit 972e8ba

File tree

4 files changed

+51
-9
lines changed

4 files changed

+51
-9
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs

+34-3
Original file line numberDiff line numberDiff line change
@@ -895,21 +895,52 @@ impl InferenceContext<'_> {
895895
TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(*int_ty)))
896896
.intern(Interner)
897897
}
898-
None => self.table.new_integer_var(),
898+
None => {
899+
let expected_ty = expected.to_option(&mut self.table);
900+
let opt_ty = match expected_ty.as_ref().map(|it| it.kind(Interner)) {
901+
Some(TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))) => expected_ty,
902+
Some(TyKind::Scalar(Scalar::Char)) => {
903+
Some(TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner))
904+
}
905+
Some(TyKind::Raw(..) | TyKind::FnDef(..) | TyKind::Function(..)) => {
906+
Some(TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner))
907+
}
908+
_ => None,
909+
};
910+
opt_ty.unwrap_or_else(|| self.table.new_integer_var())
911+
}
899912
},
900913
Literal::Uint(_v, ty) => match ty {
901914
Some(int_ty) => {
902915
TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(*int_ty)))
903916
.intern(Interner)
904917
}
905-
None => self.table.new_integer_var(),
918+
None => {
919+
let expected_ty = expected.to_option(&mut self.table);
920+
let opt_ty = match expected_ty.as_ref().map(|it| it.kind(Interner)) {
921+
Some(TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))) => expected_ty,
922+
Some(TyKind::Scalar(Scalar::Char)) => {
923+
Some(TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner))
924+
}
925+
Some(TyKind::Raw(..) | TyKind::FnDef(..) | TyKind::Function(..)) => {
926+
Some(TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner))
927+
}
928+
_ => None,
929+
};
930+
opt_ty.unwrap_or_else(|| self.table.new_integer_var())
931+
}
906932
},
907933
Literal::Float(_v, ty) => match ty {
908934
Some(float_ty) => {
909935
TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(*float_ty)))
910936
.intern(Interner)
911937
}
912-
None => self.table.new_float_var(),
938+
None => {
939+
let opt_ty = expected.to_option(&mut self.table).filter(|ty| {
940+
matches!(ty.kind(Interner), TyKind::Scalar(Scalar::Float(_)))
941+
});
942+
opt_ty.unwrap_or_else(|| self.table.new_float_var())
943+
}
913944
},
914945
},
915946
Expr::Underscore => {

src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ fn let_stmt_coerce() {
4949
//- minicore: coerce_unsized
5050
fn test() {
5151
let x: &[isize] = &[1];
52-
// ^^^^ adjustments: Deref(None), Borrow(Ref('?3, Not)), Pointer(Unsize)
52+
// ^^^^ adjustments: Deref(None), Borrow(Ref('?2, Not)), Pointer(Unsize)
5353
let x: *const [isize] = &[1];
5454
// ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize)
5555
}
@@ -148,7 +148,7 @@ fn foo<T>(x: &[T]) -> &[T] { x }
148148
fn test(i: i32) {
149149
let x = match i {
150150
2 => foo(&[2]),
151-
// ^^^^ adjustments: Deref(None), Borrow(Ref('?10, Not)), Pointer(Unsize)
151+
// ^^^^ adjustments: Deref(None), Borrow(Ref('?8, Not)), Pointer(Unsize)
152152
1 => &[1],
153153
_ => &[3],
154154
};

src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ fn test(a: A<i32>) {
917917
278..279 'A': extern "rust-call" A<i32>(*mut i32) -> A<i32>
918918
278..292 'A(0 as *mut _)': A<i32>
919919
278..307 'A(0 as...B(a)))': &'? i32
920-
280..281 '0': i32
920+
280..281 '0': usize
921921
280..291 '0 as *mut _': *mut i32
922922
297..306 '&&B(B(a))': &'? &'? B<B<A<i32>>>
923923
298..306 '&B(B(a))': &'? B<B<A<i32>>>

src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -441,16 +441,16 @@ fn main() {
441441
//^^^^^^^^^^^^^^^^^ error: cannot cast thin pointer `*const i32` to fat pointer `*const [i32]`
442442
443443
let t: *mut (dyn Trait + 'static) = 0 as *mut _;
444-
//^^^^^^^^^^^ error: cannot cast `i32` to a fat pointer `*mut _`
444+
//^^^^^^^^^^^ error: cannot cast `usize` to a fat pointer `*mut _`
445445
let mut fail: *const str = 0 as *const str;
446-
//^^^^^^^^^^^^^^^ error: cannot cast `i32` to a fat pointer `*const str`
446+
//^^^^^^^^^^^^^^^ error: cannot cast `usize` to a fat pointer `*const str`
447447
let mut fail2: *const str = 0isize as *const str;
448448
//^^^^^^^^^^^^^^^^^^^^ error: cannot cast `isize` to a fat pointer `*const str`
449449
}
450450
451451
fn foo<T: ?Sized>() {
452452
let s = 0 as *const T;
453-
//^^^^^^^^^^^^^ error: cannot cast `i32` to a fat pointer `*const T`
453+
//^^^^^^^^^^^^^ error: cannot cast `usize` to a fat pointer `*const T`
454454
}
455455
"#,
456456
&["E0308", "unused_variables"],
@@ -1100,4 +1100,15 @@ where
11001100
"#,
11011101
);
11021102
}
1103+
1104+
#[test]
1105+
fn cast_literal_to_char() {
1106+
check_diagnostics(
1107+
r#"
1108+
fn foo() {
1109+
0 as char;
1110+
}
1111+
"#,
1112+
);
1113+
}
11031114
}

0 commit comments

Comments
 (0)