mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 04:19:13 +00:00
Auto merge of #15271 - lowr:patch/re-castable, r=HKalbasi
Properly infer types with type casts
This PR reenables `Expectation::Castable` (previous attempt at #14104, reverted by #14120) and implements type cast checks, which enable us to infer a bit more.
Castable expectations are relatively weak -- they only influence the inference if we cannot infer the types by other means. Therefore, we need to defer possible type unification with the casted type until we type check all expressions of the body. This PR adds a struct and slots in `InferenceContext` for the deferred cast checks (c.f. [`CastCheck`] in `rustc_hir_typeck`).
I only implemented the bits that affect the inference result. It should be possible to return type adjustments for well-formed casts and report diagnostics for invalid casts, but I'm leaving them for future work for now.
Fixes #11571
Fixes #15246
[`CastCheck`]: da1d099f91/compiler/rustc_hir_typeck/src/cast.rs (L55)
This commit is contained in:
commit
037844c8a0
5 changed files with 112 additions and 28 deletions
|
@ -46,8 +46,8 @@ use crate::{
|
|||
};
|
||||
|
||||
use super::{
|
||||
coerce::auto_deref_adjust_steps, find_breakable, BreakableContext, Diverges, Expectation,
|
||||
InferenceContext, InferenceDiagnostic, TypeMismatch,
|
||||
cast::CastCheck, coerce::auto_deref_adjust_steps, find_breakable, BreakableContext, Diverges,
|
||||
Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch,
|
||||
};
|
||||
|
||||
impl InferenceContext<'_> {
|
||||
|
@ -574,16 +574,8 @@ impl InferenceContext<'_> {
|
|||
}
|
||||
Expr::Cast { expr, type_ref } => {
|
||||
let cast_ty = self.make_ty(type_ref);
|
||||
// FIXME: propagate the "castable to" expectation
|
||||
let inner_ty = self.infer_expr_no_expect(*expr);
|
||||
match (inner_ty.kind(Interner), cast_ty.kind(Interner)) {
|
||||
(TyKind::Ref(_, _, inner), TyKind::Raw(_, cast)) => {
|
||||
// FIXME: record invalid cast diagnostic in case of mismatch
|
||||
self.unify(inner, cast);
|
||||
}
|
||||
// FIXME check the other kinds of cast...
|
||||
_ => (),
|
||||
}
|
||||
let expr_ty = self.infer_expr(*expr, &Expectation::Castable(cast_ty.clone()));
|
||||
self.deferred_cast_checks.push(CastCheck::new(expr_ty, cast_ty.clone()));
|
||||
cast_ty
|
||||
}
|
||||
Expr::Ref { expr, rawness, mutability } => {
|
||||
|
@ -1592,7 +1584,7 @@ impl InferenceContext<'_> {
|
|||
output: Ty,
|
||||
inputs: Vec<Ty>,
|
||||
) -> Vec<Ty> {
|
||||
if let Some(expected_ty) = expected_output.to_option(&mut self.table) {
|
||||
if let Some(expected_ty) = expected_output.only_has_type(&mut self.table) {
|
||||
self.table.fudge_inference(|table| {
|
||||
if table.try_unify(&expected_ty, &output).is_ok() {
|
||||
table.resolve_with_fallback(inputs, &|var, kind, _, _| match kind {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue