use crate::hair::util::UserAnnotatedTyHelpers;
use crate::hair::constant::*;
-use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
+use rustc::mir::{Field, BorrowKind, Mutability};
use rustc::mir::{UserTypeProjection};
-use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
+use rustc::mir::interpret::{GlobalId, ConstValue, sign_extend, AllocId, Pointer};
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
use rustc::ty::subst::{SubstsRef, Kind};
-use rustc::ty::layout::VariantIdx;
+use rustc::ty::layout::{VariantIdx, Size};
use rustc::hir::{self, PatKind, RangeEnd};
use rustc::hir::def::{CtorOf, Res, DefKind, CtorKind};
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
use std::fmt;
use syntax::ast;
use syntax::ptr::P;
+use syntax::symbol::sym;
use syntax_pos::Span;
#[derive(Clone, Debug)]
},
Constant {
- value: ty::Const<'tcx>,
+ value: &'tcx ty::Const<'tcx>,
},
Range(PatternRange<'tcx>),
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct PatternRange<'tcx> {
- pub lo: ty::Const<'tcx>,
- pub hi: ty::Const<'tcx>,
+ pub lo: &'tcx ty::Const<'tcx>,
+ pub hi: &'tcx ty::Const<'tcx>,
pub ty: Ty<'tcx>,
pub end: RangeEnd,
}
write!(f, "{}", subpattern)
}
PatternKind::Constant { value } => {
- fmt_const_val(f, value)
+ write!(f, "{}", value)
}
PatternKind::Range(PatternRange { lo, hi, ty: _, end }) => {
- fmt_const_val(f, lo)?;
+ write!(f, "{}", lo)?;
match end {
RangeEnd::Included => write!(f, "..=")?,
RangeEnd::Excluded => write!(f, "..")?,
}
- fmt_const_val(f, hi)
+ write!(f, "{}", hi)
}
PatternKind::Slice { ref prefix, ref slice, ref suffix } |
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
fn const_to_pat(
&self,
instance: ty::Instance<'tcx>,
- cv: ty::Const<'tcx>,
+ cv: &'tcx ty::Const<'tcx>,
id: hir::HirId,
span: Span,
) -> Pattern<'tcx> {
self.tcx.sess.span_err(span, "cannot use unions in constant patterns");
PatternKind::Wild
}
- ty::Adt(adt_def, _) if !self.tcx.has_attr(adt_def.did, "structural_match") => {
+ ty::Adt(adt_def, _) if !self.tcx.has_attr(adt_def.did, sym::structural_match) => {
let path = self.tcx.def_path_str(adt_def.did);
let msg = format!(
"to use a constant of type `{}` in a pattern, \
PatternKind::Wild
}
ty::Ref(_, ty::TyS { sty: ty::Adt(adt_def, _), .. }, _)
- if !self.tcx.has_attr(adt_def.did, "structural_match") => {
+ if !self.tcx.has_attr(adt_def.did, sym::structural_match) => {
// HACK(estebank): Side-step ICE #53708, but anything other than erroring here
// would be wrong. Returnging `PatternKind::Wild` is not technically correct.
let path = self.tcx.def_path_str(adt_def.did);
PatternKind::Constant {
value
} => PatternKind::Constant {
- value: value.fold_with(folder)
+ value,
},
PatternKind::Range(PatternRange {
lo,
ty,
end,
}) => PatternKind::Range(PatternRange {
- lo: lo.fold_with(folder),
- hi: hi.fold_with(folder),
+ lo,
+ hi,
ty: ty.fold_with(folder),
end,
}),
pub fn compare_const_vals<'a, 'gcx, 'tcx>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- a: ty::Const<'tcx>,
- b: ty::Const<'tcx>,
+ a: &'tcx ty::Const<'tcx>,
+ b: &'tcx ty::Const<'tcx>,
ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
) -> Option<Ordering> {
trace!("compare_const_vals: {:?}, {:?}", a, b);
if let ty::Str = ty.value.sty {
match (a.val, b.val) {
(
- ConstValue::Slice(
- Scalar::Ptr(ptr_a),
- len_a,
- ),
- ConstValue::Slice(
- Scalar::Ptr(ptr_b),
- len_b,
- ),
- ) if ptr_a.offset.bytes() == 0 && ptr_b.offset.bytes() == 0 => {
- if len_a == len_b {
- let map = tcx.alloc_map.lock();
- let alloc_a = map.unwrap_memory(ptr_a.alloc_id);
- let alloc_b = map.unwrap_memory(ptr_b.alloc_id);
- if alloc_a.bytes.len() as u64 == len_a {
- return from_bool(alloc_a == alloc_b);
- }
+ ConstValue::Slice { data: alloc_a, start: offset_a, end: end_a },
+ ConstValue::Slice { data: alloc_b, start: offset_b, end: end_b },
+ ) => {
+ let len_a = end_a - offset_a;
+ let len_b = end_b - offset_b;
+ let a = alloc_a.get_bytes(
+ &tcx,
+ // invent a pointer, only the offset is relevant anyway
+ Pointer::new(AllocId(0), Size::from_bytes(offset_a as u64)),
+ Size::from_bytes(len_a as u64),
+ );
+ let b = alloc_b.get_bytes(
+ &tcx,
+ // invent a pointer, only the offset is relevant anyway
+ Pointer::new(AllocId(0), Size::from_bytes(offset_b as u64)),
+ Size::from_bytes(len_b as u64),
+ );
+ if let (Ok(a), Ok(b)) = (a, b) {
+ return from_bool(a == b);
}
}
_ => (),