Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #16968 - roife:fix-issue-16801, r=Veykril
fix: silence mismatches involving unresolved projections fix #16801
bors 2024-04-02
parent 3691380 · parent 2636e44 · commit 23dd54b
-rw-r--r--crates/hir-ty/src/infer.rs21
-rw-r--r--crates/hir-ty/src/mir/lower.rs17
-rw-r--r--crates/hir-ty/src/tests/diagnostics.rs17
-rw-r--r--crates/hir/src/lib.rs1
4 files changed, 45 insertions, 11 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index be3b50e141..bb558e533c 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -429,6 +429,8 @@ pub struct InferenceResult {
/// Type of the result of `.into_iter()` on the for. `ExprId` is the one of the whole for loop.
pub type_of_for_iterator: FxHashMap<ExprId, Ty>,
type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
+ /// Whether there are any type-mismatching errors in the result.
+ pub(crate) has_errors: bool,
/// Interned common types to return references to.
standard_types: InternedStandardTypes,
/// Stores the types which were implicitly dereferenced in pattern binding modes.
@@ -654,6 +656,7 @@ impl<'a> InferenceContext<'a> {
type_of_rpit,
type_of_for_iterator,
type_mismatches,
+ has_errors,
standard_types: _,
pat_adjustments,
binding_modes: _,
@@ -695,6 +698,9 @@ impl<'a> InferenceContext<'a> {
for ty in type_of_for_iterator.values_mut() {
*ty = table.resolve_completely(ty.clone());
}
+
+ *has_errors = !type_mismatches.is_empty();
+
type_mismatches.retain(|_, mismatch| {
mismatch.expected = table.resolve_completely(mismatch.expected.clone());
mismatch.actual = table.resolve_completely(mismatch.actual.clone());
@@ -1646,9 +1652,11 @@ 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.
+
+/// A zipper that checks for unequal occurrences of `{unknown}` and unresolved projections
+/// in the two types. Used to filter out mismatch diagnostics that only differ in
+/// `{unknown}` and unresolved projections. 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<'_> {
fn zip_tys(&mut self, variance: Variance, a: &Ty, b: &Ty) -> chalk_ir::Fallible<()> {
@@ -1721,7 +1729,12 @@ 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),
+ (TyKind::Error, _)
+ | (_, TyKind::Error)
+ | (TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(_, _), _)
+ | (_, TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(_, _)) => {
+ return Err(chalk_ir::NoSolution)
+ }
_ => (),
}
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 7e582c03ef..f2505c1937 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -90,7 +90,7 @@ pub enum MirLowerError {
UnresolvedField,
UnsizedTemporary(Ty),
MissingFunctionDefinition(DefWithBodyId, ExprId),
- TypeMismatch(TypeMismatch),
+ TypeMismatch(Option<TypeMismatch>),
/// This should never happen. Type mismatch should catch everything.
TypeError(&'static str),
NotSupported(String),
@@ -170,14 +170,15 @@ impl MirLowerError {
body.pretty_print_expr(db.upcast(), *owner, *it)
)?;
}
- MirLowerError::TypeMismatch(e) => {
- writeln!(
+ MirLowerError::TypeMismatch(e) => match e {
+ Some(e) => writeln!(
f,
"Type mismatch: Expected {}, found {}",
e.expected.display(db),
e.actual.display(db),
- )?;
- }
+ )?,
+ None => writeln!(f, "Type mismatch: types mismatch with {{unknown}}",)?,
+ },
MirLowerError::GenericArgNotProvided(id, subst) => {
let parent = id.parent;
let param = &db.generic_params(parent).type_or_consts[id.local_id];
@@ -2152,8 +2153,10 @@ pub fn lower_to_mir(
// need to take this input explicitly.
root_expr: ExprId,
) -> Result<MirBody> {
- if let Some((_, it)) = infer.type_mismatches().next() {
- return Err(MirLowerError::TypeMismatch(it.clone()));
+ if infer.has_errors {
+ return Err(MirLowerError::TypeMismatch(
+ infer.type_mismatches().next().map(|(_, it)| it.clone()),
+ ));
}
let mut ctx = MirLowerCtx::new(db, owner, body, infer);
// 0 is return local
diff --git a/crates/hir-ty/src/tests/diagnostics.rs b/crates/hir-ty/src/tests/diagnostics.rs
index 80f92eaf43..119de7f050 100644
--- a/crates/hir-ty/src/tests/diagnostics.rs
+++ b/crates/hir-ty/src/tests/diagnostics.rs
@@ -136,3 +136,20 @@ impl Trait for () {
"#,
);
}
+
+#[test]
+fn no_mismatches_with_unresolved_projections() {
+ check_no_mismatches(
+ r#"
+// `Thing` is `{unknown}`
+fn create() -> Option<(i32, Thing)> {
+ Some((69420, Thing))
+}
+
+fn consume() -> Option<()> {
+ let (number, thing) = create()?;
+ Some(())
+}
+"#,
+ );
+}
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 106056c2fc..3165adcd3a 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1678,6 +1678,7 @@ 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 expr_or_pat = match pat_or_expr {
ExprOrPatId::ExprId(expr) => source_map.expr_syntax(expr).map(Either::Left),