Auto merge of #16968 - roife:fix-issue-16801, r=Veykril
fix: silence mismatches involving unresolved projections fix #16801
This commit is contained in:
commit
23dd54b010
@ -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 @@ pub(crate) fn resolve_all(self) -> InferenceResult {
|
||||
type_of_rpit,
|
||||
type_of_for_iterator,
|
||||
type_mismatches,
|
||||
has_errors,
|
||||
standard_types: _,
|
||||
pat_adjustments,
|
||||
binding_modes: _,
|
||||
@ -695,6 +698,9 @@ pub(crate) fn resolve_all(self) -> InferenceResult {
|
||||
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 @@ fn bitor_assign(&mut self, other: Self) {
|
||||
*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 @@ fn zip_tys(&mut self, variance: Variance, a: &Ty, b: &Ty) -> chalk_ir::Fallible<
|
||||
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)
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
|
@ -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 @@ pub fn pretty_print(
|
||||
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
|
||||
|
@ -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(())
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -1678,6 +1678,7 @@ pub fn diagnostics(
|
||||
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),
|
||||
|
Loading…
Reference in New Issue
Block a user