diff options
| author | Dawer <[email protected]> | 2021-05-19 14:08:13 +0100 |
|---|---|---|
| committer | Dawer <[email protected]> | 2021-05-31 20:49:44 +0100 |
| commit | 3088ca0a53540e0d7ae14f0d18efcad16cad0735 (patch) | |
| tree | d4adc50c7bddda2470c64dff00a080f522a5ecac /crates/hir_ty/src/diagnostics | |
| parent | e16f413582ea45d6b318337ea2c7838fdc3b82a4 (diff) | |
Take substitutions into account.
Diffstat (limited to 'crates/hir_ty/src/diagnostics')
| -rw-r--r-- | crates/hir_ty/src/diagnostics/match_check.rs | 20 | ||||
| -rw-r--r-- | crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs | 25 | ||||
| -rw-r--r-- | crates/hir_ty/src/diagnostics/match_check/usefulness.rs | 2 |
3 files changed, 33 insertions, 14 deletions
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index 5fb98ff35..992bb8682 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs | |||
| @@ -39,8 +39,8 @@ pub(crate) struct Pat { | |||
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | impl Pat { | 41 | impl Pat { |
| 42 | pub(crate) fn wildcard_from_ty(ty: &Ty) -> Self { | 42 | pub(crate) fn wildcard_from_ty(ty: Ty) -> Self { |
| 43 | Pat { ty: ty.clone(), kind: Box::new(PatKind::Wild) } | 43 | Pat { ty, kind: Box::new(PatKind::Wild) } |
| 44 | } | 44 | } |
| 45 | } | 45 | } |
| 46 | 46 | ||
| @@ -1145,6 +1145,22 @@ fn main() { | |||
| 1145 | ); | 1145 | ); |
| 1146 | } | 1146 | } |
| 1147 | 1147 | ||
| 1148 | #[test] | ||
| 1149 | fn pattern_type_is_of_substitution() { | ||
| 1150 | cov_mark::check!(match_check_wildcard_expanded_to_substitutions); | ||
| 1151 | check_diagnostics( | ||
| 1152 | r#" | ||
| 1153 | struct Foo<T>(T); | ||
| 1154 | struct Bar; | ||
| 1155 | fn main() { | ||
| 1156 | match Foo(Bar) { | ||
| 1157 | _ | Foo(Bar) => {} | ||
| 1158 | } | ||
| 1159 | } | ||
| 1160 | "#, | ||
| 1161 | ); | ||
| 1162 | } | ||
| 1163 | |||
| 1148 | mod false_negatives { | 1164 | mod false_negatives { |
| 1149 | //! The implementation of match checking here is a work in progress. As we roll this out, we | 1165 | //! The implementation of match checking here is a work in progress. As we roll this out, we |
| 1150 | //! prefer false negatives to false positives (ideally there would be no false positives). This | 1166 | //! prefer false negatives to false positives (ideally there would be no false positives). This |
diff --git a/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs b/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs index 15ec5cf45..a47082617 100644 --- a/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs +++ b/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs | |||
| @@ -632,10 +632,7 @@ impl Fields { | |||
| 632 | } | 632 | } |
| 633 | 633 | ||
| 634 | /// Convenience; internal use. | 634 | /// Convenience; internal use. |
| 635 | fn wildcards_from_tys<'a>( | 635 | fn wildcards_from_tys(cx: &MatchCheckCtx<'_>, tys: impl IntoIterator<Item = Ty>) -> Self { |
| 636 | cx: &MatchCheckCtx<'_>, | ||
| 637 | tys: impl IntoIterator<Item = &'a Ty>, | ||
| 638 | ) -> Self { | ||
| 639 | let wilds = tys.into_iter().map(Pat::wildcard_from_ty); | 636 | let wilds = tys.into_iter().map(Pat::wildcard_from_ty); |
| 640 | let pats = wilds.map(|pat| cx.alloc_pat(pat)).collect(); | 637 | let pats = wilds.map(|pat| cx.alloc_pat(pat)).collect(); |
| 641 | Fields::Vec(pats) | 638 | Fields::Vec(pats) |
| @@ -645,13 +642,13 @@ impl Fields { | |||
| 645 | pub(crate) fn wildcards(pcx: PatCtxt<'_>, constructor: &Constructor) -> Self { | 642 | pub(crate) fn wildcards(pcx: PatCtxt<'_>, constructor: &Constructor) -> Self { |
| 646 | let ty = pcx.ty; | 643 | let ty = pcx.ty; |
| 647 | let cx = pcx.cx; | 644 | let cx = pcx.cx; |
| 648 | let wildcard_from_ty = |ty| cx.alloc_pat(Pat::wildcard_from_ty(ty)); | 645 | let wildcard_from_ty = |ty: &Ty| cx.alloc_pat(Pat::wildcard_from_ty(ty.clone())); |
| 649 | 646 | ||
| 650 | let ret = match constructor { | 647 | let ret = match constructor { |
| 651 | Single | Variant(_) => match ty.kind(&Interner) { | 648 | Single | Variant(_) => match ty.kind(&Interner) { |
| 652 | TyKind::Tuple(_, substs) => { | 649 | TyKind::Tuple(_, substs) => { |
| 653 | let tys = substs.iter(&Interner).map(|ty| ty.assert_ty_ref(&Interner)); | 650 | let tys = substs.iter(&Interner).map(|ty| ty.assert_ty_ref(&Interner)); |
| 654 | Fields::wildcards_from_tys(cx, tys) | 651 | Fields::wildcards_from_tys(cx, tys.cloned()) |
| 655 | } | 652 | } |
| 656 | TyKind::Ref(.., rty) => Fields::from_single_pattern(wildcard_from_ty(rty)), | 653 | TyKind::Ref(.., rty) => Fields::from_single_pattern(wildcard_from_ty(rty)), |
| 657 | &TyKind::Adt(AdtId(adt), ref substs) => { | 654 | &TyKind::Adt(AdtId(adt), ref substs) => { |
| @@ -666,14 +663,20 @@ impl Fields { | |||
| 666 | // Whether we must not match the fields of this variant exhaustively. | 663 | // Whether we must not match the fields of this variant exhaustively. |
| 667 | let is_non_exhaustive = | 664 | let is_non_exhaustive = |
| 668 | is_field_list_non_exhaustive(variant_id, cx) && !adt_is_local; | 665 | is_field_list_non_exhaustive(variant_id, cx) && !adt_is_local; |
| 669 | let field_ty_arena = cx.db.field_types(variant_id); | 666 | |
| 670 | let field_tys = | 667 | cov_mark::hit!(match_check_wildcard_expanded_to_substitutions); |
| 671 | || field_ty_arena.iter().map(|(_, binders)| binders.skip_binders()); | 668 | let field_ty_data = cx.db.field_types(variant_id); |
| 669 | let field_tys = || { | ||
| 670 | field_ty_data | ||
| 671 | .iter() | ||
| 672 | .map(|(_, binders)| binders.clone().substitute(&Interner, substs)) | ||
| 673 | }; | ||
| 674 | |||
| 672 | // In the following cases, we don't need to filter out any fields. This is | 675 | // In the following cases, we don't need to filter out any fields. This is |
| 673 | // the vast majority of real cases, since uninhabited fields are uncommon. | 676 | // the vast majority of real cases, since uninhabited fields are uncommon. |
| 674 | let has_no_hidden_fields = (matches!(adt, hir_def::AdtId::EnumId(_)) | 677 | let has_no_hidden_fields = (matches!(adt, hir_def::AdtId::EnumId(_)) |
| 675 | && !is_non_exhaustive) | 678 | && !is_non_exhaustive) |
| 676 | || !field_tys().any(|ty| cx.is_uninhabited(ty)); | 679 | || !field_tys().any(|ty| cx.is_uninhabited(&ty)); |
| 677 | 680 | ||
| 678 | if has_no_hidden_fields { | 681 | if has_no_hidden_fields { |
| 679 | Fields::wildcards_from_tys(cx, field_tys()) | 682 | Fields::wildcards_from_tys(cx, field_tys()) |
| @@ -759,7 +762,7 @@ impl Fields { | |||
| 759 | FloatRange(..) => UNHANDLED, | 762 | FloatRange(..) => UNHANDLED, |
| 760 | Constructor::IntRange(_) => UNHANDLED, | 763 | Constructor::IntRange(_) => UNHANDLED, |
| 761 | NonExhaustive => PatKind::Wild, | 764 | NonExhaustive => PatKind::Wild, |
| 762 | Wildcard => return Pat::wildcard_from_ty(pcx.ty), | 765 | Wildcard => return Pat::wildcard_from_ty(pcx.ty.clone()), |
| 763 | Opaque => pcx.cx.bug("we should not try to apply an opaque constructor"), | 766 | Opaque => pcx.cx.bug("we should not try to apply an opaque constructor"), |
| 764 | Missing => pcx.cx.bug( | 767 | Missing => pcx.cx.bug( |
| 765 | "trying to apply the `Missing` constructor;\ | 768 | "trying to apply the `Missing` constructor;\ |
diff --git a/crates/hir_ty/src/diagnostics/match_check/usefulness.rs b/crates/hir_ty/src/diagnostics/match_check/usefulness.rs index cb322a3de..61fba41bf 100644 --- a/crates/hir_ty/src/diagnostics/match_check/usefulness.rs +++ b/crates/hir_ty/src/diagnostics/match_check/usefulness.rs | |||
| @@ -1152,7 +1152,7 @@ pub(crate) fn compute_match_usefulness( | |||
| 1152 | .collect(); | 1152 | .collect(); |
| 1153 | 1153 | ||
| 1154 | let wild_pattern = | 1154 | let wild_pattern = |
| 1155 | cx.pattern_arena.borrow_mut().alloc(Pat::wildcard_from_ty(&cx.infer[cx.match_expr])); | 1155 | cx.pattern_arena.borrow_mut().alloc(Pat::wildcard_from_ty(cx.infer[cx.match_expr].clone())); |
| 1156 | let v = PatStack::from_pattern(wild_pattern); | 1156 | let v = PatStack::from_pattern(wild_pattern); |
| 1157 | let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, false, true); | 1157 | let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, false, true); |
| 1158 | let non_exhaustiveness_witnesses = match usefulness { | 1158 | let non_exhaustiveness_witnesses = match usefulness { |
