Skip to content

Commit

Permalink
fix: silence mismatches involving unresolved projections
Browse files Browse the repository at this point in the history
  • Loading branch information
roife committed Mar 29, 2024
1 parent 899db83 commit cef455f
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 10 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions crates/hir-ty/src/chalk_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub trait TyExt {
fn contains_unknown(&self) -> bool;
fn is_ty_var(&self) -> bool;
fn is_union(&self) -> bool;
fn is_projection(&self) -> bool;

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

fn is_projection(&self) -> bool {
matches!(
self.kind(Interner),
TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(_, _)
)
}

fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> {
match self.kind(Interner) {
TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
Expand Down
19 changes: 12 additions & 7 deletions crates/hir-ty/src/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ impl<'a> InferenceContext<'a> {
mismatch.expected = table.resolve_completely(mismatch.expected.clone());
mismatch.actual = table.resolve_completely(mismatch.actual.clone());
chalk_ir::zip::Zip::zip_with(
&mut UnknownMismatch(self.db),
&mut UnknownMismatch(self.db, |ty| matches!(ty.kind(Interner), TyKind::Error)),
Variance::Invariant,
&mismatch.expected,
&mismatch.actual,
Expand Down Expand Up @@ -1646,11 +1646,16 @@ impl std::ops::BitOrAssign for Diverges {
*self = *self | other;
}
}
/// A zipper that checks for unequal `{unknown}` occurrences in the two types. Used to filter out
/// mismatch diagnostics that only differ in `{unknown}`. These mismatches are usually not helpful.
/// As the cause is usually an underlying name resolution problem.
struct UnknownMismatch<'db>(&'db dyn HirDatabase);
impl chalk_ir::zip::Zipper<Interner> for UnknownMismatch<'_> {
/// A zipper that checks for unequal `{unknown}` occurrences in the two types.
/// Types that have different constructors are filtered out and tested by the
/// provided closure `F`. Commonly used to filter out mismatch diagnostics that
/// only differ in `{unknown}`. These mismatches are usually not helpful, as the
/// cause is usually an underlying name resolution problem.
///
/// E.g. when F is `|ty| matches!(ty.kind(Interer), TyKind::Unknown)`, the zipper
/// will skip over all mismatches that only differ in `{unknown}`.
pub struct UnknownMismatch<'db, F: Fn(&Ty) -> bool>(pub &'db dyn HirDatabase, pub F);
impl<F: Fn(&Ty) -> bool> chalk_ir::zip::Zipper<Interner> for UnknownMismatch<'_, F> {
fn zip_tys(&mut self, variance: Variance, a: &Ty, b: &Ty) -> chalk_ir::Fallible<()> {
let zip_substs = |this: &mut Self,
variances,
Expand Down Expand Up @@ -1721,7 +1726,7 @@ impl chalk_ir::zip::Zipper<Interner> for UnknownMismatch<'_> {
zip_substs(self, None, &fn_ptr_a.substitution.0, &fn_ptr_b.substitution.0)?
}
(TyKind::Error, TyKind::Error) => (),
(TyKind::Error, _) | (_, TyKind::Error) => return Err(chalk_ir::NoSolution),
_ if (self.1)(a) || (self.1)(b) => return Err(chalk_ir::NoSolution),
_ => (),
}

Expand Down
2 changes: 1 addition & 1 deletion crates/hir-ty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub use chalk_ext::*;
pub use infer::{
closure::{CaptureKind, CapturedItem},
could_coerce, could_unify, could_unify_deeply, Adjust, Adjustment, AutoBorrow, BindingMode,
InferenceDiagnostic, InferenceResult, OverloadedDeref, PointerCast,
InferenceDiagnostic, InferenceResult, OverloadedDeref, PointerCast, UnknownMismatch,
};
pub use interner::Interner;
pub use lower::{
Expand Down
1 change: 1 addition & 0 deletions crates/hir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ smallvec.workspace = true
tracing.workspace = true
triomphe.workspace = true
once_cell = "1.17.1"
chalk-ir.workspace = true

# local deps
base-db.workspace = true
Expand Down
15 changes: 13 additions & 2 deletions crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use std::{iter, mem::discriminant, ops::ControlFlow};

use arrayvec::ArrayVec;
use base_db::{CrateDisplayName, CrateId, CrateOrigin, FileId};
use chalk_ir::TyKind;
use either::Either;
use hir_def::{
body::{BodyDiagnostic, SyntheticSyntax},
Expand Down Expand Up @@ -73,8 +74,7 @@ use hir_ty::{
traits::FnTrait,
AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg,
GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId,
WhereClause,
TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, ValueTyDefId, WhereClause,
};
use itertools::Itertools;
use nameres::diagnostics::DefDiagnosticKind;
Expand Down Expand Up @@ -1678,7 +1678,18 @@ impl DefWithBody {
for d in &infer.diagnostics {
acc.extend(AnyDiagnostic::inference_diagnostic(db, self.into(), d, &source_map));
}

for (pat_or_expr, mismatch) in infer.type_mismatches() {
let contains_unknown_projection = chalk_ir::zip::Zip::zip_with(
&mut hir_ty::UnknownMismatch(db, |ty| ty.contains_unknown() && ty.is_projection()),
chalk_ir::Variance::Invariant,
&mismatch.expected,
&mismatch.actual,
);
if contains_unknown_projection.is_err() {
continue;
}

let expr_or_pat = match pat_or_expr {
ExprOrPatId::ExprId(expr) => source_map.expr_syntax(expr).map(Either::Left),
ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right),
Expand Down

0 comments on commit cef455f

Please sign in to comment.