mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 21:25:25 +00:00 
			
		
		
		
	hir_ty::match_check: remove special handling for box patterns
				
					
				
			This commit is contained in:
		
							parent
							
								
									3816d0ae53
								
							
						
					
					
						commit
						8dc54f4d33
					
				
					 2 changed files with 18 additions and 58 deletions
				
			
		| 
						 | 
					@ -25,7 +25,6 @@ use crate::{
 | 
				
			||||||
    db::HirDatabase,
 | 
					    db::HirDatabase,
 | 
				
			||||||
    display::{HirDisplay, HirDisplayError, HirFormatter},
 | 
					    display::{HirDisplay, HirDisplayError, HirFormatter},
 | 
				
			||||||
    infer::BindingMode,
 | 
					    infer::BindingMode,
 | 
				
			||||||
    lang_items::is_box,
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use self::pat_util::EnumerateAndAdjustIterator;
 | 
					use self::pat_util::EnumerateAndAdjustIterator;
 | 
				
			||||||
| 
						 | 
					@ -77,7 +76,7 @@ pub(crate) enum PatKind {
 | 
				
			||||||
        subpatterns: Vec<FieldPat>,
 | 
					        subpatterns: Vec<FieldPat>,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// `box P`, `&P`, `&mut P`, etc.
 | 
					    /// `&P`, `&mut P`, etc.
 | 
				
			||||||
    Deref {
 | 
					    Deref {
 | 
				
			||||||
        subpattern: Pat,
 | 
					        subpattern: Pat,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
| 
						 | 
					@ -406,7 +405,6 @@ impl HirDisplay for Pat {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            PatKind::Deref { subpattern } => {
 | 
					            PatKind::Deref { subpattern } => {
 | 
				
			||||||
                match self.ty.kind(Interner) {
 | 
					                match self.ty.kind(Interner) {
 | 
				
			||||||
                    TyKind::Adt(adt, _) if is_box(f.db, adt.0) => write!(f, "box ")?,
 | 
					 | 
				
			||||||
                    &TyKind::Ref(mutbl, ..) => {
 | 
					                    &TyKind::Ref(mutbl, ..) => {
 | 
				
			||||||
                        write!(f, "&{}", if mutbl == Mutability::Mut { "mut " } else { "" })?
 | 
					                        write!(f, "&{}", if mutbl == Mutability::Mut { "mut " } else { "" })?
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ use crate::{
 | 
				
			||||||
    inhabitedness::{is_enum_variant_uninhabited_from, is_ty_uninhabited_from},
 | 
					    inhabitedness::{is_enum_variant_uninhabited_from, is_ty_uninhabited_from},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::{FieldPat, Pat, PatKind, is_box};
 | 
					use super::{FieldPat, Pat, PatKind};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use Constructor::*;
 | 
					use Constructor::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -170,8 +170,6 @@ impl<'db> MatchCheckCtx<'db> {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            PatKind::Deref { subpattern } => {
 | 
					            PatKind::Deref { subpattern } => {
 | 
				
			||||||
                ctor = match pat.ty.kind(Interner) {
 | 
					                ctor = match pat.ty.kind(Interner) {
 | 
				
			||||||
                    // This is a box pattern.
 | 
					 | 
				
			||||||
                    TyKind::Adt(adt, _) if is_box(self.db, adt.0) => Struct,
 | 
					 | 
				
			||||||
                    TyKind::Ref(..) => Ref,
 | 
					                    TyKind::Ref(..) => Ref,
 | 
				
			||||||
                    _ => {
 | 
					                    _ => {
 | 
				
			||||||
                        never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty);
 | 
					                        never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty);
 | 
				
			||||||
| 
						 | 
					@ -194,23 +192,6 @@ impl<'db> MatchCheckCtx<'db> {
 | 
				
			||||||
                        ctor = Struct;
 | 
					                        ctor = Struct;
 | 
				
			||||||
                        arity = substs.len(Interner);
 | 
					                        arity = substs.len(Interner);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    TyKind::Adt(adt, _) if is_box(self.db, adt.0) => {
 | 
					 | 
				
			||||||
                        // The only legal patterns of type `Box` (outside `std`) are `_` and box
 | 
					 | 
				
			||||||
                        // patterns. If we're here we can assume this is a box pattern.
 | 
					 | 
				
			||||||
                        // FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_,
 | 
					 | 
				
			||||||
                        // _)` or a box pattern. As a hack to avoid an ICE with the former, we
 | 
					 | 
				
			||||||
                        // ignore other fields than the first one. This will trigger an error later
 | 
					 | 
				
			||||||
                        // anyway.
 | 
					 | 
				
			||||||
                        // See https://github.com/rust-lang/rust/issues/82772 ,
 | 
					 | 
				
			||||||
                        // explanation: https://github.com/rust-lang/rust/pull/82789#issuecomment-796921977
 | 
					 | 
				
			||||||
                        // The problem is that we can't know from the type whether we'll match
 | 
					 | 
				
			||||||
                        // normally or through box-patterns. We'll have to figure out a proper
 | 
					 | 
				
			||||||
                        // solution when we introduce generalized deref patterns. Also need to
 | 
					 | 
				
			||||||
                        // prevent mixing of those two options.
 | 
					 | 
				
			||||||
                        fields.retain(|ipat| ipat.idx == 0);
 | 
					 | 
				
			||||||
                        ctor = Struct;
 | 
					 | 
				
			||||||
                        arity = 1;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    &TyKind::Adt(AdtId(adt), _) => {
 | 
					                    &TyKind::Adt(AdtId(adt), _) => {
 | 
				
			||||||
                        ctor = match pat.kind.as_ref() {
 | 
					                        ctor = match pat.kind.as_ref() {
 | 
				
			||||||
                            PatKind::Leaf { .. } if matches!(adt, hir_def::AdtId::UnionId(_)) => {
 | 
					                            PatKind::Leaf { .. } if matches!(adt, hir_def::AdtId::UnionId(_)) => {
 | 
				
			||||||
| 
						 | 
					@ -277,12 +258,6 @@ impl<'db> MatchCheckCtx<'db> {
 | 
				
			||||||
                        })
 | 
					                        })
 | 
				
			||||||
                        .collect(),
 | 
					                        .collect(),
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                TyKind::Adt(adt, _) if is_box(self.db, adt.0) => {
 | 
					 | 
				
			||||||
                    // Without `box_patterns`, the only legal pattern of type `Box` is `_` (outside
 | 
					 | 
				
			||||||
                    // of `std`). So this branch is only reachable when the feature is enabled and
 | 
					 | 
				
			||||||
                    // the pattern is a box pattern.
 | 
					 | 
				
			||||||
                    PatKind::Deref { subpattern: subpatterns.next().unwrap() }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                TyKind::Adt(adt, substs) => {
 | 
					                TyKind::Adt(adt, substs) => {
 | 
				
			||||||
                    let variant = Self::variant_id_for_adt(self.db, pat.ctor(), adt.0).unwrap();
 | 
					                    let variant = Self::variant_id_for_adt(self.db, pat.ctor(), adt.0).unwrap();
 | 
				
			||||||
                    let subpatterns = self
 | 
					                    let subpatterns = self
 | 
				
			||||||
| 
						 | 
					@ -343,14 +318,8 @@ impl PatCx for MatchCheckCtx<'_> {
 | 
				
			||||||
            Struct | Variant(_) | UnionField => match *ty.kind(Interner) {
 | 
					            Struct | Variant(_) | UnionField => match *ty.kind(Interner) {
 | 
				
			||||||
                TyKind::Tuple(arity, ..) => arity,
 | 
					                TyKind::Tuple(arity, ..) => arity,
 | 
				
			||||||
                TyKind::Adt(AdtId(adt), ..) => {
 | 
					                TyKind::Adt(AdtId(adt), ..) => {
 | 
				
			||||||
                    if is_box(self.db, adt) {
 | 
					                    let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
 | 
				
			||||||
                        // The only legal patterns of type `Box` (outside `std`) are `_` and box
 | 
					                    variant.fields(self.db).fields().len()
 | 
				
			||||||
                        // patterns. If we're here we can assume this is a box pattern.
 | 
					 | 
				
			||||||
                        1
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
 | 
					 | 
				
			||||||
                        variant.fields(self.db).fields().len()
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                _ => {
 | 
					                _ => {
 | 
				
			||||||
                    never!("Unexpected type for `Single` constructor: {:?}", ty);
 | 
					                    never!("Unexpected type for `Single` constructor: {:?}", ty);
 | 
				
			||||||
| 
						 | 
					@ -383,29 +352,22 @@ impl PatCx for MatchCheckCtx<'_> {
 | 
				
			||||||
                    tys.cloned().map(|ty| (ty, PrivateUninhabitedField(false))).collect()
 | 
					                    tys.cloned().map(|ty| (ty, PrivateUninhabitedField(false))).collect()
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                TyKind::Ref(.., rty) => single(rty.clone()),
 | 
					                TyKind::Ref(.., rty) => single(rty.clone()),
 | 
				
			||||||
                &TyKind::Adt(AdtId(adt), ref substs) => {
 | 
					                &TyKind::Adt(AdtId(adt), ..) => {
 | 
				
			||||||
                    if is_box(self.db, adt) {
 | 
					                    let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
 | 
				
			||||||
                        // The only legal patterns of type `Box` (outside `std`) are `_` and box
 | 
					 | 
				
			||||||
                        // patterns. If we're here we can assume this is a box pattern.
 | 
					 | 
				
			||||||
                        let subst_ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone();
 | 
					 | 
				
			||||||
                        single(subst_ty)
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        let variant = Self::variant_id_for_adt(self.db, ctor, adt).unwrap();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        let visibilities = LazyCell::new(|| self.db.field_visibilities(variant));
 | 
					                    let visibilities = LazyCell::new(|| self.db.field_visibilities(variant));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        self.list_variant_fields(ty, variant)
 | 
					                    self.list_variant_fields(ty, variant)
 | 
				
			||||||
                            .map(move |(fid, ty)| {
 | 
					                        .map(move |(fid, ty)| {
 | 
				
			||||||
                                let is_visible = || {
 | 
					                            let is_visible = || {
 | 
				
			||||||
                                    matches!(adt, hir_def::AdtId::EnumId(..))
 | 
					                                matches!(adt, hir_def::AdtId::EnumId(..))
 | 
				
			||||||
                                        || visibilities[fid].is_visible_from(self.db, self.module)
 | 
					                                    || visibilities[fid].is_visible_from(self.db, self.module)
 | 
				
			||||||
                                };
 | 
					                            };
 | 
				
			||||||
                                let is_uninhabited = self.is_uninhabited(&ty);
 | 
					                            let is_uninhabited = self.is_uninhabited(&ty);
 | 
				
			||||||
                                let private_uninhabited = is_uninhabited && !is_visible();
 | 
					                            let private_uninhabited = is_uninhabited && !is_visible();
 | 
				
			||||||
                                (ty, PrivateUninhabitedField(private_uninhabited))
 | 
					                            (ty, PrivateUninhabitedField(private_uninhabited))
 | 
				
			||||||
                            })
 | 
					                        })
 | 
				
			||||||
                            .collect()
 | 
					                        .collect()
 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                ty_kind => {
 | 
					                ty_kind => {
 | 
				
			||||||
                    never!("Unexpected type for `{:?}` constructor: {:?}", ctor, ty_kind);
 | 
					                    never!("Unexpected type for `{:?}` constructor: {:?}", ctor, ty_kind);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue