pub use self::check_match::check_crate;
pub(crate) use self::check_match::check_match;
-use interpret::{const_field, const_variant_index};
+use const_eval::{const_field, const_variant_index};
+
+use hair::util::UserAnnotatedTyHelpers;
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
+use rustc::mir::{ProjectionElem, UserTypeAnnotation, UserTypeProjection, UserTypeProjections};
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
-use rustc::ty::{self, CanonicalTy, TyCtxt, AdtDef, Ty, Region};
+use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty};
use rustc::ty::subst::{Substs, Kind};
use rustc::hir::{self, PatKind, RangeEnd};
use rustc::hir::def::{Def, CtorKind};
pub kind: Box<PatternKind<'tcx>>,
}
+
+#[derive(Clone, Debug)]
+pub(crate) struct PatternTypeProjections<'tcx> {
+ contents: Vec<(PatternTypeProjection<'tcx>, Span)>,
+}
+
+impl<'tcx> PatternTypeProjections<'tcx> {
+ pub(crate) fn user_ty(self) -> UserTypeProjections<'tcx> {
+ UserTypeProjections::from_projections(
+ self.contents.into_iter().map(|(pat_ty_proj, span)| (pat_ty_proj.user_ty(), span)))
+ }
+
+ pub(crate) fn none() -> Self {
+ PatternTypeProjections { contents: vec![] }
+ }
+
+ pub(crate) fn ref_binding(&self) -> Self {
+ // FIXME(#47184): ignore for now
+ PatternTypeProjections { contents: vec![] }
+ }
+
+ fn map_projs(&self,
+ mut f: impl FnMut(&PatternTypeProjection<'tcx>) -> PatternTypeProjection<'tcx>)
+ -> Self
+ {
+ PatternTypeProjections {
+ contents: self.contents
+ .iter()
+ .map(|(proj, span)| (f(proj), *span))
+ .collect(), }
+ }
+
+ pub(crate) fn index(&self) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.index()) }
+
+ pub(crate) fn subslice(&self, from: u32, to: u32) -> Self {
+ self.map_projs(|pat_ty_proj| pat_ty_proj.subslice(from, to))
+ }
+
+ pub(crate) fn deref(&self) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.deref()) }
+
+ pub(crate) fn leaf(&self, field: Field) -> Self {
+ self.map_projs(|pat_ty_proj| pat_ty_proj.leaf(field))
+ }
+
+ pub(crate) fn variant(&self,
+ adt_def: &'tcx AdtDef,
+ variant_index: usize,
+ field: Field) -> Self {
+ self.map_projs(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
+ }
+
+ pub(crate) fn add_user_type(&self, user_ty: &PatternTypeProjection<'tcx>, sp: Span) -> Self {
+ let mut new = self.clone();
+ new.contents.push((user_ty.clone(), sp));
+ new
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct PatternTypeProjection<'tcx>(UserTypeProjection<'tcx>);
+
+impl<'tcx> PatternTypeProjection<'tcx> {
+ pub(crate) fn index(&self) -> Self {
+ let mut new = self.clone();
+ new.0.projs.push(ProjectionElem::Index(()));
+ new
+ }
+
+ pub(crate) fn subslice(&self, from: u32, to: u32) -> Self {
+ let mut new = self.clone();
+ new.0.projs.push(ProjectionElem::Subslice { from, to });
+ new
+ }
+
+ pub(crate) fn deref(&self) -> Self {
+ let mut new = self.clone();
+ new.0.projs.push(ProjectionElem::Deref);
+ new
+ }
+
+ pub(crate) fn leaf(&self, field: Field) -> Self {
+ let mut new = self.clone();
+ new.0.projs.push(ProjectionElem::Field(field, ()));
+ new
+ }
+
+ pub(crate) fn variant(&self,
+ adt_def: &'tcx AdtDef,
+ variant_index: usize,
+ field: Field) -> Self {
+ let mut new = self.clone();
+ new.0.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
+ new.0.projs.push(ProjectionElem::Field(field, ()));
+ new
+ }
+
+ pub(crate) fn from_canonical_ty(c_ty: ty::CanonicalTy<'tcx>) -> Self {
+ Self::from_user_type(UserTypeAnnotation::Ty(c_ty))
+ }
+
+ pub(crate) fn from_user_type(u_ty: UserTypeAnnotation<'tcx>) -> Self {
+ Self::from_user_type_proj(UserTypeProjection { base: u_ty, projs: vec![], })
+ }
+
+ pub(crate) fn from_user_type_proj(u_ty: UserTypeProjection<'tcx>) -> Self {
+ PatternTypeProjection(u_ty)
+ }
+
+ pub(crate) fn user_ty(self) -> UserTypeProjection<'tcx> { self.0 }
+}
+
#[derive(Clone, Debug)]
pub enum PatternKind<'tcx> {
Wild,
AscribeUserType {
- user_ty: CanonicalTy<'tcx>,
+ user_ty: PatternTypeProjection<'tcx>,
subpattern: Pattern<'tcx>,
+ user_ty_span: Span,
},
/// x, ref x, x @ P, etc
field: Field::new(i),
pattern: self.lower_pattern(field),
})
- .collect();
- self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
+ .collect();
+
+ self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
}
PatKind::Struct(ref qpath, ref fields, _) => {
})
.collect();
- self.lower_variant_or_leaf(def, pat.span, ty, subpatterns)
+ self.lower_variant_or_leaf(def, pat.hir_id, pat.span, ty, subpatterns)
}
};
fn lower_variant_or_leaf(
&mut self,
def: Def,
+ hir_id: hir::HirId,
span: Span,
ty: Ty<'tcx>,
- subpatterns: Vec<FieldPattern<'tcx>>)
- -> PatternKind<'tcx>
- {
- match def {
+ subpatterns: Vec<FieldPattern<'tcx>>,
+ ) -> PatternKind<'tcx> {
+ let mut kind = match def {
Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
let enum_id = self.tcx.parent_def_id(variant_id).unwrap();
let adt_def = self.tcx.adt_def(enum_id);
self.errors.push(PatternError::NonConstPath(span));
PatternKind::Wild
}
+ };
+
+ if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) {
+ let subpattern = Pattern {
+ span,
+ ty,
+ kind: Box::new(kind),
+ };
+
+ debug!("pattern user_ty = {:?} for pattern at {:?}", user_ty, span);
+
+ let pat_ty = PatternTypeProjection::from_user_type(user_ty);
+ kind = PatternKind::AscribeUserType {
+ subpattern,
+ user_ty: pat_ty,
+ user_ty_span: span,
+ };
}
+
+ kind
}
/// Takes a HIR Path. If the path is a constant, evaluates it and feeds
},
}
}
- _ => self.lower_variant_or_leaf(def, span, ty, vec![]),
+ _ => self.lower_variant_or_leaf(def, id, span, ty, vec![]),
};
Pattern {
}
}
+impl UserAnnotatedTyHelpers<'tcx, 'tcx> for PatternContext<'_, 'tcx> {
+ fn tcx(&self) -> TyCtxt<'_, 'tcx, 'tcx> {
+ self.tcx
+ }
+
+ fn tables(&self) -> &ty::TypeckTables<'tcx> {
+ self.tables
+ }
+}
+
+
pub trait PatternFoldable<'tcx> : Sized {
fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
self.super_fold_with(folder)
CloneImpls!{ <'tcx>
Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ty::Const<'tcx>,
Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
- &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, CanonicalTy<'tcx>
+ &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, UserTypeAnnotation<'tcx>,
+ UserTypeProjection<'tcx>, PatternTypeProjection<'tcx>
}
impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {
PatternKind::Wild => PatternKind::Wild,
PatternKind::AscribeUserType {
ref subpattern,
- user_ty,
+ ref user_ty,
+ user_ty_span,
} => PatternKind::AscribeUserType {
subpattern: subpattern.fold_with(folder),
user_ty: user_ty.fold_with(folder),
+ user_ty_span,
},
PatternKind::Binding {
mutability,
len_b,
),
) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
- let len_a = len_a.not_undef().ok();
- let len_b = len_b.not_undef().ok();
- if len_a.is_none() || len_b.is_none() {
- tcx.sess.struct_err("str slice len is undef").delay_as_bug();
- }
- let len_a = len_a?;
- let len_b = len_b?;
if let Ok(len_a) = len_a.to_bits(tcx.data_layout.pointer_size) {
if let Ok(len_b) = len_b.to_bits(tcx.data_layout.pointer_size) {
if len_a == len_b {