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.rs | 45 |
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 } |