Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer.rs')
-rw-r--r--crates/hir-ty/src/infer.rs45
1 files changed, 38 insertions, 7 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 062ea27815..8bc3c50725 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -13,7 +13,7 @@
//! to certain types. To record this, we use the union-find implementation from
//! the `ena` crate, which is extracted from rustc.
-mod cast;
+pub(crate) mod cast;
pub(crate) mod closure;
mod coerce;
mod expr;
@@ -76,7 +76,7 @@ pub use coerce::could_coerce;
#[allow(unreachable_pub)]
pub use unify::{could_unify, could_unify_deeply};
-use cast::CastCheck;
+use cast::{CastCheck, CastError};
pub(crate) use closure::{CaptureKind, CapturedItem, CapturedItemWithoutTy};
/// The entry point of type inference.
@@ -254,6 +254,16 @@ pub enum InferenceDiagnostic {
expr: ExprId,
expected: Ty,
},
+ CastToUnsized {
+ expr: ExprId,
+ cast_ty: Ty,
+ },
+ InvalidCast {
+ expr: ExprId,
+ error: CastError,
+ expr_ty: Ty,
+ cast_ty: Ty,
+ },
}
/// A mismatch between an expected and an inferred type.
@@ -456,6 +466,7 @@ pub struct InferenceResult {
pub(crate) closure_info: FxHashMap<ClosureId, (Vec<CapturedItem>, FnTrait)>,
// FIXME: remove this field
pub mutated_bindings_in_closure: FxHashSet<BindingId>,
+ pub coercion_casts: FxHashSet<ExprId>,
}
impl InferenceResult {
@@ -666,7 +677,7 @@ impl<'a> InferenceContext<'a> {
let InferenceContext {
mut table,
mut result,
- deferred_cast_checks,
+ mut deferred_cast_checks,
tuple_field_accesses_rev,
..
} = self;
@@ -695,15 +706,25 @@ impl<'a> InferenceContext<'a> {
closure_info: _,
mutated_bindings_in_closure: _,
tuple_field_access_types: _,
+ coercion_casts,
} = &mut result;
-
table.fallback_if_possible();
// Comment from rustc:
// Even though coercion casts provide type hints, we check casts after fallback for
// backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
- for cast in deferred_cast_checks {
- cast.check(&mut table);
+ let mut apply_adjustments = |expr, adj| {
+ expr_adjustments.insert(expr, adj);
+ };
+ let mut set_coercion_cast = |expr| {
+ coercion_casts.insert(expr);
+ };
+ for cast in deferred_cast_checks.iter_mut() {
+ if let Err(diag) =
+ cast.check(&mut table, &mut apply_adjustments, &mut set_coercion_cast)
+ {
+ diagnostics.push(diag);
+ }
}
// FIXME resolve obligations as well (use Guidance if necessary)
@@ -732,7 +753,7 @@ impl<'a> InferenceContext<'a> {
*has_errors = *has_errors || ty.contains_unknown();
}
- *has_errors = !type_mismatches.is_empty();
+ *has_errors |= !type_mismatches.is_empty();
type_mismatches.retain(|_, mismatch| {
mismatch.expected = table.resolve_completely(mismatch.expected.clone());
@@ -775,20 +796,30 @@ impl<'a> InferenceContext<'a> {
});
for (_, subst) in method_resolutions.values_mut() {
*subst = table.resolve_completely(subst.clone());
+ *has_errors =
+ *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
}
for (_, subst) in assoc_resolutions.values_mut() {
*subst = table.resolve_completely(subst.clone());
+ *has_errors =
+ *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
}
for adjustment in expr_adjustments.values_mut().flatten() {
adjustment.target = table.resolve_completely(adjustment.target.clone());
+ *has_errors = *has_errors || adjustment.target.contains_unknown();
}
for adjustment in pat_adjustments.values_mut().flatten() {
*adjustment = table.resolve_completely(adjustment.clone());
+ *has_errors = *has_errors || adjustment.contains_unknown();
}
result.tuple_field_access_types = tuple_field_accesses_rev
.into_iter()
.enumerate()
.map(|(idx, subst)| (TupleId(idx as u32), table.resolve_completely(subst)))
+ .inspect(|(_, subst)| {
+ *has_errors =
+ *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
+ })
.collect();
result
}