Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/pat.rs')
-rw-r--r--crates/hir-ty/src/infer/pat.rs41
1 files changed, 22 insertions, 19 deletions
diff --git a/crates/hir-ty/src/infer/pat.rs b/crates/hir-ty/src/infer/pat.rs
index f21438647c..c36c29d6c7 100644
--- a/crates/hir-ty/src/infer/pat.rs
+++ b/crates/hir-ty/src/infer/pat.rs
@@ -448,7 +448,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
)
}
Pat::Missing => self.types.types.error,
- Pat::Wild | Pat::Rest => expected,
+ Pat::Wild | Pat::Rest | Pat::NotNull => expected,
// We allow any type here; we ensure that the type is uninhabited during match checking.
// Pat::Never => expected,
Pat::Path(_) => {
@@ -662,6 +662,8 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
Pat::Ref { .. }
// No need to do anything on a missing pattern.
| Pat::Missing
+ // No need to do anything on a `NotNull` pattern, they are only allowed in type contexts.
+ | Pat::NotNull
// A `_`/`..` pattern works with any expected type, so there's no need to do anything.
| Pat::Wild | Pat::Rest
// Bindings also work with whatever the expected type is,
@@ -843,7 +845,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) {
// There exists a side that didn't meet our criteria that the end-point
// be of a numeric or char type, as checked in `calc_side` above.
- // FIXME: Emit an error.
+ self.push_diagnostic(InferenceDiagnostic::InvalidRangePatType { pat });
return self.types.types.error;
}
@@ -891,14 +893,14 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
let user_bind_annot = BindingMode::from_annotation(binding_data.mode);
let bm = match user_bind_annot {
BindingMode(ByRef::No, Mutability::Mut) if let ByRef::Yes(_) = def_br => {
- // Only mention the experimental `mut_ref` feature if if we're in edition 2024 and
+ // Only mention the experimental `mut_ref` feature if we're in edition 2024 and
// using other experimental matching features compatible with it.
if self.edition.at_least_2024()
&& (self.features.ref_pat_eat_one_layer_2024
|| self.features.ref_pat_eat_one_layer_2024_structural)
{
if !self.features.mut_ref {
- // FIXME: Emit an error: binding cannot be both mutable and by-reference.
+ self.push_diagnostic(InferenceDiagnostic::MutableRefBinding { pat });
}
BindingMode(def_br, Mutability::Mut)
@@ -957,22 +959,23 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
local_ty
}
- fn check_dereferenceable(&self, expected: Ty<'db>, inner: PatId) -> Result<(), ()> {
+ fn check_dereferenceable(
+ &mut self,
+ expected: Ty<'db>,
+ pat: PatId,
+ inner: PatId,
+ ) -> Result<(), ()> {
if let Pat::Bind { .. } = self.store[inner]
&& let Some(pointee_ty) = self.shallow_resolve(expected).builtin_deref(true)
&& let TyKind::Dynamic(..) = pointee_ty.kind()
{
// This is "x = dyn SomeTrait" being reduced from
// "let &x = &dyn SomeTrait" or "let box x = Box<dyn SomeTrait>", an error.
- // FIXME: Emit an error. rustc emits this message:
- const _CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ: &str = "\
-This error indicates that a pointer to a trait type cannot be implicitly dereferenced by a \
-pattern. Every trait defines a type, but because the size of trait implementors isn't fixed, \
-this type has no compile-time size. Therefore, all accesses to trait types must be through \
-pointers. If you encounter this error you should try to avoid dereferencing the pointer.
-
-You can read more about trait objects in the Trait Objects section of the Reference: \
-https://doc.rust-lang.org/reference/types.html#trait-objects";
+ self.push_diagnostic(InferenceDiagnostic::CannotImplicitlyDerefTraitObject {
+ pat,
+ found: expected.store(),
+ });
+ return Err(());
}
Ok(())
}
@@ -1155,7 +1158,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
fn check_record_pat_fields(
&mut self,
adt_ty: Ty<'db>,
- _pat: PatId,
+ pat: PatId,
variant: VariantId,
fields: &[RecordFieldPat],
has_rest_pat: bool,
@@ -1233,7 +1236,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
// Require `..` if struct has non_exhaustive attribute.
let non_exhaustive = self.has_applicable_non_exhaustive(variant.into());
if non_exhaustive && !has_rest_pat {
- // FIXME: Emit an error.
+ self.push_diagnostic(InferenceDiagnostic::NonExhaustiveRecordPat { pat, variant });
}
// Report an error if an incorrect number of fields was specified.
@@ -1258,7 +1261,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
) -> Ty<'db> {
let interner = self.interner();
let (box_ty, inner_ty) = self
- .check_dereferenceable(expected, inner)
+ .check_dereferenceable(expected, pat, inner)
.map(|()| {
// Here, `demand::subtype` is good enough, but I don't
// think any errors can be introduced by using `demand::eqtype`.
@@ -1471,7 +1474,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
}
}
- let (ref_ty, inner_ty) = match self.check_dereferenceable(expected, inner) {
+ let (ref_ty, inner_ty) = match self.check_dereferenceable(expected, pat, inner) {
Ok(()) => {
// `demand::subtype` would be good enough, but using `eqtype` turns
// out to be equally general. See (note_1) for details.
@@ -1699,7 +1702,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects";
// We have a variable-length pattern and don't know the array length.
// This happens if we have e.g.,
// `let [a, b, ..] = arr` where `arr: [T; N]` where `const N: usize`.
- // FIXME: Emit an error: cannot pattern-match on an array without a fixed length.
+ self.push_diagnostic(InferenceDiagnostic::ArrayPatternWithoutFixedLength { pat });
};
// If we get here, we must have emitted an error.