Skip to content

Commit 8d6b65c

Browse files
committed
fix: silence mismatches involving unresolved projections
1 parent 899db83 commit 8d6b65c

File tree

4 files changed

+58
-22
lines changed

4 files changed

+58
-22
lines changed

crates/hir-ty/src/chalk_ext.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub trait TyExt {
2929
fn contains_unknown(&self) -> bool;
3030
fn is_ty_var(&self) -> bool;
3131
fn is_union(&self) -> bool;
32+
fn is_projection(&self) -> bool;
3233

3334
fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>;
3435
fn as_builtin(&self) -> Option<BuiltinType>;
@@ -101,6 +102,13 @@ impl TyExt for Ty {
101102
matches!(self.adt_id(Interner), Some(AdtId(hir_def::AdtId::UnionId(_))))
102103
}
103104

105+
fn is_projection(&self) -> bool {
106+
matches!(
107+
self.kind(Interner),
108+
TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(_, _)
109+
)
110+
}
111+
104112
fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> {
105113
match self.kind(Interner) {
106114
TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),

crates/hir-ty/src/infer.rs

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,8 @@ pub struct InferenceResult {
429429
/// Type of the result of `.into_iter()` on the for. `ExprId` is the one of the whole for loop.
430430
pub type_of_for_iterator: FxHashMap<ExprId, Ty>,
431431
type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
432+
/// Whether there are any type-mismatching errors in the result.
433+
pub(crate) has_errors: bool,
432434
/// Interned common types to return references to.
433435
standard_types: InternedStandardTypes,
434436
/// Stores the types which were implicitly dereferenced in pattern binding modes.
@@ -654,6 +656,7 @@ impl<'a> InferenceContext<'a> {
654656
type_of_rpit,
655657
type_of_for_iterator,
656658
type_mismatches,
659+
has_errors,
657660
standard_types: _,
658661
pat_adjustments,
659662
binding_modes: _,
@@ -695,16 +698,33 @@ impl<'a> InferenceContext<'a> {
695698
for ty in type_of_for_iterator.values_mut() {
696699
*ty = table.resolve_completely(ty.clone());
697700
}
701+
702+
*has_errors = !type_mismatches.is_empty();
703+
698704
type_mismatches.retain(|_, mismatch| {
699705
mismatch.expected = table.resolve_completely(mismatch.expected.clone());
700706
mismatch.actual = table.resolve_completely(mismatch.actual.clone());
701-
chalk_ir::zip::Zip::zip_with(
702-
&mut UnknownMismatch(self.db),
703-
Variance::Invariant,
704-
&mismatch.expected,
705-
&mismatch.actual,
706-
)
707-
.is_ok()
707+
let unresolved_ty_mismatch = || {
708+
chalk_ir::zip::Zip::zip_with(
709+
&mut UnknownMismatch(self.db, |ty| matches!(ty.kind(Interner), TyKind::Error)),
710+
Variance::Invariant,
711+
&mismatch.expected,
712+
&mismatch.actual,
713+
)
714+
.is_ok()
715+
};
716+
717+
let unresolved_projections_mismatch = || {
718+
chalk_ir::zip::Zip::zip_with(
719+
&mut UnknownMismatch(self.db, |ty| ty.contains_unknown() && ty.is_projection()),
720+
chalk_ir::Variance::Invariant,
721+
&mismatch.expected,
722+
&mismatch.actual,
723+
)
724+
.is_ok()
725+
};
726+
727+
unresolved_ty_mismatch() && unresolved_projections_mismatch()
708728
});
709729
diagnostics.retain_mut(|diagnostic| {
710730
use InferenceDiagnostic::*;
@@ -1646,11 +1666,16 @@ impl std::ops::BitOrAssign for Diverges {
16461666
*self = *self | other;
16471667
}
16481668
}
1649-
/// A zipper that checks for unequal `{unknown}` occurrences in the two types. Used to filter out
1650-
/// mismatch diagnostics that only differ in `{unknown}`. These mismatches are usually not helpful.
1651-
/// As the cause is usually an underlying name resolution problem.
1652-
struct UnknownMismatch<'db>(&'db dyn HirDatabase);
1653-
impl chalk_ir::zip::Zipper<Interner> for UnknownMismatch<'_> {
1669+
/// A zipper that checks for unequal `{unknown}` occurrences in the two types.
1670+
/// Types that have different constructors are filtered out and tested by the
1671+
/// provided closure `F`. Commonly used to filter out mismatch diagnostics that
1672+
/// only differ in `{unknown}`. These mismatches are usually not helpful, as the
1673+
/// cause is usually an underlying name resolution problem.
1674+
///
1675+
/// E.g. when F is `|ty| matches!(ty.kind(Interer), TyKind::Unknown)`, the zipper
1676+
/// will skip over all mismatches that only differ in `{unknown}`.
1677+
struct UnknownMismatch<'db, F: Fn(&Ty) -> bool>(&'db dyn HirDatabase, F);
1678+
impl<F: Fn(&Ty) -> bool> chalk_ir::zip::Zipper<Interner> for UnknownMismatch<'_, F> {
16541679
fn zip_tys(&mut self, variance: Variance, a: &Ty, b: &Ty) -> chalk_ir::Fallible<()> {
16551680
let zip_substs = |this: &mut Self,
16561681
variances,
@@ -1721,7 +1746,7 @@ impl chalk_ir::zip::Zipper<Interner> for UnknownMismatch<'_> {
17211746
zip_substs(self, None, &fn_ptr_a.substitution.0, &fn_ptr_b.substitution.0)?
17221747
}
17231748
(TyKind::Error, TyKind::Error) => (),
1724-
(TyKind::Error, _) | (_, TyKind::Error) => return Err(chalk_ir::NoSolution),
1749+
_ if (self.1)(a) || (self.1)(b) => return Err(chalk_ir::NoSolution),
17251750
_ => (),
17261751
}
17271752

crates/hir-ty/src/mir/lower.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub enum MirLowerError {
9090
UnresolvedField,
9191
UnsizedTemporary(Ty),
9292
MissingFunctionDefinition(DefWithBodyId, ExprId),
93-
TypeMismatch(TypeMismatch),
93+
TypeMismatch(Option<TypeMismatch>),
9494
/// This should never happen. Type mismatch should catch everything.
9595
TypeError(&'static str),
9696
NotSupported(String),
@@ -170,14 +170,15 @@ impl MirLowerError {
170170
body.pretty_print_expr(db.upcast(), *owner, *it)
171171
)?;
172172
}
173-
MirLowerError::TypeMismatch(e) => {
174-
writeln!(
173+
MirLowerError::TypeMismatch(e) => match e {
174+
Some(e) => writeln!(
175175
f,
176176
"Type mismatch: Expected {}, found {}",
177177
e.expected.display(db),
178178
e.actual.display(db),
179-
)?;
180-
}
179+
)?,
180+
None => writeln!(f, "Type mismatch: types mismatch with {{unknown}}",)?,
181+
},
181182
MirLowerError::GenericArgNotProvided(id, subst) => {
182183
let parent = id.parent;
183184
let param = &db.generic_params(parent).type_or_consts[id.local_id];
@@ -2152,8 +2153,10 @@ pub fn lower_to_mir(
21522153
// need to take this input explicitly.
21532154
root_expr: ExprId,
21542155
) -> Result<MirBody> {
2155-
if let Some((_, it)) = infer.type_mismatches().next() {
2156-
return Err(MirLowerError::TypeMismatch(it.clone()));
2156+
if infer.has_errors {
2157+
return Err(MirLowerError::TypeMismatch(
2158+
infer.type_mismatches().next().map(|(_, it)| it.clone()),
2159+
));
21572160
}
21582161
let mut ctx = MirLowerCtx::new(db, owner, body, infer);
21592162
// 0 is return local

crates/hir/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ use hir_ty::{
7373
traits::FnTrait,
7474
AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg,
7575
GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
76-
TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId,
77-
WhereClause,
76+
TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId, WhereClause,
7877
};
7978
use itertools::Itertools;
8079
use nameres::diagnostics::DefDiagnosticKind;
@@ -1678,6 +1677,7 @@ impl DefWithBody {
16781677
for d in &infer.diagnostics {
16791678
acc.extend(AnyDiagnostic::inference_diagnostic(db, self.into(), d, &source_map));
16801679
}
1680+
16811681
for (pat_or_expr, mismatch) in infer.type_mismatches() {
16821682
let expr_or_pat = match pat_or_expr {
16831683
ExprOrPatId::ExprId(expr) => source_map.expr_syntax(expr).map(Either::Left),

0 commit comments

Comments
 (0)