Skip to content

Commit bb4b3fb

Browse files
committed
Auto merge of #32202 - arielb1:slice-patterns, r=nikomatsakis
Implement RFC495 semantics for slice patterns non-MIR translation is still not supported for these and will happily ICE. This is a [breaking-change] for many uses of slice_patterns. [RFC 495 text](https://github.com/rust-lang/rfcs/blob/master/text/0495-array-pattern-changes.md)
2 parents 34505e2 + 2de6ea7 commit bb4b3fb

File tree

77 files changed

+934
-732
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+934
-732
lines changed

mk/crates.mk

+3-3
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ DEPS_rustc := syntax fmt_macros flate arena serialize getopts rbml \
109109
log graphviz rustc_llvm rustc_back rustc_data_structures\
110110
rustc_const_math
111111
DEPS_rustc_back := std syntax flate log libc
112-
DEPS_rustc_borrowck := rustc rustc_mir log graphviz syntax
112+
DEPS_rustc_borrowck := rustc log graphviz syntax rustc_mir
113113
DEPS_rustc_data_structures := std log serialize
114114
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
115115
rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \
@@ -123,9 +123,9 @@ DEPS_rustc_passes := syntax rustc core rustc_const_eval
123123
DEPS_rustc_mir := rustc syntax rustc_const_math rustc_const_eval rustc_bitflags
124124
DEPS_rustc_resolve := arena rustc log syntax
125125
DEPS_rustc_platform_intrinsics := std
126-
DEPS_rustc_plugin := rustc rustc_metadata syntax rustc_mir
126+
DEPS_rustc_plugin := rustc rustc_metadata syntax
127127
DEPS_rustc_privacy := rustc log syntax
128-
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back rustc_mir \
128+
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
129129
log syntax serialize rustc_llvm rustc_platform_intrinsics \
130130
rustc_const_math rustc_const_eval rustc_incremental
131131
DEPS_rustc_incremental := rbml rustc serialize rustc_data_structures

src/doc/book/slice-patterns.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ fn main() {
1010
let v = vec!["match_this", "1"];
1111

1212
match &v[..] {
13-
["match_this", second] => println!("The second element is {}", second),
13+
&["match_this", second] => println!("The second element is {}", second),
1414
_ => {},
1515
}
1616
}
@@ -26,8 +26,8 @@ slice will be bound to that name. For example:
2626

2727
fn is_symmetric(list: &[u32]) -> bool {
2828
match list {
29-
[] | [_] => true,
30-
[x, inside.., y] if x == y => is_symmetric(inside),
29+
&[] | &[_] => true,
30+
&[x, ref inside.., y] if x == y => is_symmetric(inside),
3131
_ => false
3232
}
3333
}

src/librustc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ pub mod mir {
106106
pub mod tcx;
107107
pub mod visit;
108108
pub mod transform;
109+
pub mod traversal;
109110
pub mod mir_map;
110111
}
111112

src/librustc/middle/expr_use_visitor.rs

-34
Original file line numberDiff line numberDiff line change
@@ -993,40 +993,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
993993
}
994994
}
995995
}
996-
PatKind::Vec(_, Some(ref slice_pat), _) => {
997-
// The `slice_pat` here creates a slice into
998-
// the original vector. This is effectively a
999-
// borrow of the elements of the vector being
1000-
// matched.
1001-
1002-
let (slice_cmt, slice_mutbl, slice_r) =
1003-
return_if_err!(mc.cat_slice_pattern(cmt_pat, &slice_pat));
1004-
1005-
// Note: We declare here that the borrow
1006-
// occurs upon entering the `[...]`
1007-
// pattern. This implies that something like
1008-
// `[a; b]` where `a` is a move is illegal,
1009-
// because the borrow is already in effect.
1010-
// In fact such a move would be safe-ish, but
1011-
// it effectively *requires* that we use the
1012-
// nulling out semantics to indicate when a
1013-
// value has been moved, which we are trying
1014-
// to move away from. Otherwise, how can we
1015-
// indicate that the first element in the
1016-
// vector has been moved? Eventually, we
1017-
// could perhaps modify this rule to permit
1018-
// `[..a, b]` where `b` is a move, because in
1019-
// that case we can adjust the length of the
1020-
// original vec accordingly, but we'd have to
1021-
// make trans do the right thing, and it would
1022-
// only work for `Box<[T]>`s. It seems simpler
1023-
// to just require that people call
1024-
// `vec.pop()` or `vec.unshift()`.
1025-
let slice_bk = ty::BorrowKind::from_mutbl(slice_mutbl);
1026-
delegate.borrow(pat.id, pat.span,
1027-
slice_cmt, slice_r,
1028-
slice_bk, RefBinding);
1029-
}
1030996
_ => {}
1031997
}
1032998
}));

src/librustc/middle/mem_categorization.rs

+11-116
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,10 @@ fn deref_kind(t: Ty, context: DerefKindContext) -> McResult<deref_kind> {
228228
Ok(deref_interior(InteriorField(PositionalField(0))))
229229
}
230230

231-
ty::TyArray(_, _) | ty::TySlice(_) | ty::TyStr => {
231+
ty::TyArray(_, _) | ty::TySlice(_) => {
232232
// no deref of indexed content without supplying InteriorOffsetKind
233233
if let Some(context) = context {
234-
Ok(deref_interior(InteriorElement(context, element_kind(t))))
234+
Ok(deref_interior(InteriorElement(context, ElementKind::VecElement)))
235235
} else {
236236
Err(())
237237
}
@@ -981,121 +981,31 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
981981
let method_call = ty::MethodCall::expr(elt.id());
982982
let method_ty = self.infcx.node_method_ty(method_call);
983983

984-
let element_ty = match method_ty {
984+
let (element_ty, element_kind) = match method_ty {
985985
Some(method_ty) => {
986986
let ref_ty = self.overloaded_method_return_ty(method_ty);
987987
base_cmt = self.cat_rvalue_node(elt.id(), elt.span(), ref_ty);
988988

989989
// FIXME(#20649) -- why are we using the `self_ty` as the element type...?
990990
let self_ty = method_ty.fn_sig().input(0);
991-
self.tcx().no_late_bound_regions(&self_ty).unwrap()
991+
(self.tcx().no_late_bound_regions(&self_ty).unwrap(),
992+
ElementKind::OtherElement)
992993
}
993994
None => {
994995
match base_cmt.ty.builtin_index() {
995-
Some(ty) => ty,
996+
Some(ty) => (ty, ElementKind::VecElement),
996997
None => {
997998
return Err(());
998999
}
9991000
}
10001001
}
10011002
};
10021003

1003-
let m = base_cmt.mutbl.inherit();
1004-
let ret = interior(elt, base_cmt.clone(), base_cmt.ty,
1005-
m, context, element_ty);
1004+
let interior_elem = InteriorElement(context, element_kind);
1005+
let ret =
1006+
self.cat_imm_interior(elt, base_cmt.clone(), element_ty, interior_elem);
10061007
debug!("cat_index ret {:?}", ret);
10071008
return Ok(ret);
1008-
1009-
fn interior<'tcx, N: ast_node>(elt: &N,
1010-
of_cmt: cmt<'tcx>,
1011-
vec_ty: Ty<'tcx>,
1012-
mutbl: MutabilityCategory,
1013-
context: InteriorOffsetKind,
1014-
element_ty: Ty<'tcx>) -> cmt<'tcx>
1015-
{
1016-
let interior_elem = InteriorElement(context, element_kind(vec_ty));
1017-
Rc::new(cmt_ {
1018-
id:elt.id(),
1019-
span:elt.span(),
1020-
cat:Categorization::Interior(of_cmt, interior_elem),
1021-
mutbl:mutbl,
1022-
ty:element_ty,
1023-
note: NoteNone
1024-
})
1025-
}
1026-
}
1027-
1028-
// Takes either a vec or a reference to a vec and returns the cmt for the
1029-
// underlying vec.
1030-
fn deref_vec<N:ast_node>(&self,
1031-
elt: &N,
1032-
base_cmt: cmt<'tcx>,
1033-
context: InteriorOffsetKind)
1034-
-> McResult<cmt<'tcx>>
1035-
{
1036-
let ret = match deref_kind(base_cmt.ty, Some(context))? {
1037-
deref_ptr(ptr) => {
1038-
// for unique ptrs, we inherit mutability from the
1039-
// owning reference.
1040-
let m = MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr);
1041-
1042-
// the deref is explicit in the resulting cmt
1043-
Rc::new(cmt_ {
1044-
id:elt.id(),
1045-
span:elt.span(),
1046-
cat:Categorization::Deref(base_cmt.clone(), 0, ptr),
1047-
mutbl:m,
1048-
ty: match base_cmt.ty.builtin_deref(false, ty::NoPreference) {
1049-
Some(mt) => mt.ty,
1050-
None => bug!("Found non-derefable type")
1051-
},
1052-
note: NoteNone
1053-
})
1054-
}
1055-
1056-
deref_interior(_) => {
1057-
base_cmt
1058-
}
1059-
};
1060-
debug!("deref_vec ret {:?}", ret);
1061-
Ok(ret)
1062-
}
1063-
1064-
/// Given a pattern P like: `[_, ..Q, _]`, where `vec_cmt` is the cmt for `P`, `slice_pat` is
1065-
/// the pattern `Q`, returns:
1066-
///
1067-
/// * a cmt for `Q`
1068-
/// * the mutability and region of the slice `Q`
1069-
///
1070-
/// These last two bits of info happen to be things that borrowck needs.
1071-
pub fn cat_slice_pattern(&self,
1072-
vec_cmt: cmt<'tcx>,
1073-
slice_pat: &hir::Pat)
1074-
-> McResult<(cmt<'tcx>, hir::Mutability, ty::Region)> {
1075-
let slice_ty = self.node_ty(slice_pat.id)?;
1076-
let (slice_mutbl, slice_r) = vec_slice_info(slice_pat, slice_ty);
1077-
let context = InteriorOffsetKind::Pattern;
1078-
let cmt_vec = self.deref_vec(slice_pat, vec_cmt, context)?;
1079-
let cmt_slice = self.cat_index(slice_pat, cmt_vec, context)?;
1080-
return Ok((cmt_slice, slice_mutbl, slice_r));
1081-
1082-
/// In a pattern like [a, b, ..c], normally `c` has slice type, but if you have [a, b,
1083-
/// ..ref c], then the type of `ref c` will be `&&[]`, so to extract the slice details we
1084-
/// have to recurse through rptrs.
1085-
fn vec_slice_info(pat: &hir::Pat, slice_ty: Ty)
1086-
-> (hir::Mutability, ty::Region) {
1087-
match slice_ty.sty {
1088-
ty::TyRef(r, ref mt) => match mt.ty.sty {
1089-
ty::TySlice(_) => (mt.mutbl, *r),
1090-
_ => vec_slice_info(pat, mt.ty),
1091-
},
1092-
1093-
_ => {
1094-
span_bug!(pat.span,
1095-
"type of slice pattern is not a slice");
1096-
}
1097-
}
1098-
}
10991009
}
11001010

11011011
pub fn cat_imm_interior<N:ast_node>(&self,
@@ -1319,15 +1229,12 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
13191229

13201230
PatKind::Vec(ref before, ref slice, ref after) => {
13211231
let context = InteriorOffsetKind::Pattern;
1322-
let vec_cmt = self.deref_vec(pat, cmt, context)?;
1323-
let elt_cmt = self.cat_index(pat, vec_cmt, context)?;
1232+
let elt_cmt = self.cat_index(pat, cmt, context)?;
13241233
for before_pat in before {
13251234
self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
13261235
}
13271236
if let Some(ref slice_pat) = *slice {
1328-
let slice_ty = self.pat_ty(&slice_pat)?;
1329-
let slice_cmt = self.cat_rvalue_node(pat.id(), pat.span(), slice_ty);
1330-
self.cat_pattern_(slice_cmt, &slice_pat, op)?;
1237+
self.cat_pattern_(elt_cmt.clone(), &slice_pat, op)?;
13311238
}
13321239
for after_pat in after {
13331240
self.cat_pattern_(elt_cmt.clone(), &after_pat, op)?;
@@ -1620,18 +1527,6 @@ impl fmt::Debug for InteriorKind {
16201527
}
16211528
}
16221529

1623-
fn element_kind(t: Ty) -> ElementKind {
1624-
match t.sty {
1625-
ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
1626-
ty::TyBox(ty) => match ty.sty {
1627-
ty::TySlice(_) => VecElement,
1628-
_ => OtherElement
1629-
},
1630-
ty::TyArray(..) | ty::TySlice(_) => VecElement,
1631-
_ => OtherElement
1632-
}
1633-
}
1634-
16351530
impl fmt::Debug for Upvar {
16361531
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16371532
write!(f, "{:?}/{:?}", self.id, self.kind)

src/librustc/mir/repr.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,14 @@ pub enum ProjectionElem<'tcx, V> {
674674
from_end: bool,
675675
},
676676

677+
/// These indices are generated by slice patterns.
678+
///
679+
/// slice[from:-to] in Python terms.
680+
Subslice {
681+
from: u32,
682+
to: u32,
683+
},
684+
677685
/// "Downcast" to a variant of an ADT. Currently, we only introduce
678686
/// this for ADTs with more than one variant. It may be better to
679687
/// just introduce it always, or always for enums.
@@ -753,6 +761,14 @@ impl<'tcx> Debug for Lvalue<'tcx> {
753761
write!(fmt, "{:?}[{:?} of {:?}]", data.base, offset, min_length),
754762
ProjectionElem::ConstantIndex { offset, min_length, from_end: true } =>
755763
write!(fmt, "{:?}[-{:?} of {:?}]", data.base, offset, min_length),
764+
ProjectionElem::Subslice { from, to } if to == 0 =>
765+
write!(fmt, "{:?}[{:?}:", data.base, from),
766+
ProjectionElem::Subslice { from, to } if from == 0 =>
767+
write!(fmt, "{:?}[:-{:?}]", data.base, to),
768+
ProjectionElem::Subslice { from, to } =>
769+
write!(fmt, "{:?}[{:?}:-{:?}]", data.base,
770+
from, to),
771+
756772
},
757773
}
758774
}
@@ -856,17 +872,6 @@ pub enum Rvalue<'tcx> {
856872
/// away after type-checking and before lowering.
857873
Aggregate(AggregateKind<'tcx>, Vec<Operand<'tcx>>),
858874

859-
/// Generates a slice of the form `&input[from_start..L-from_end]`
860-
/// where `L` is the length of the slice. This is only created by
861-
/// slice pattern matching, so e.g. a pattern of the form `[x, y,
862-
/// .., z]` might create a slice with `from_start=2` and
863-
/// `from_end=1`.
864-
Slice {
865-
input: Lvalue<'tcx>,
866-
from_start: usize,
867-
from_end: usize,
868-
},
869-
870875
InlineAsm {
871876
asm: InlineAsm,
872877
outputs: Vec<Lvalue<'tcx>>,
@@ -972,8 +977,6 @@ impl<'tcx> Debug for Rvalue<'tcx> {
972977
InlineAsm { ref asm, ref outputs, ref inputs } => {
973978
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
974979
}
975-
Slice { ref input, from_start, from_end } =>
976-
write!(fmt, "{:?}[{:?}..-{:?}]", input, from_start, from_end),
977980

978981
Ref(_, borrow_kind, ref lv) => {
979982
let kind_str = match borrow_kind {

src/librustc/mir/tcx.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,20 @@ impl<'a, 'gcx, 'tcx> LvalueTy<'tcx> {
5959
LvalueTy::Ty {
6060
ty: self.to_ty(tcx).builtin_index().unwrap()
6161
},
62+
ProjectionElem::Subslice { from, to } => {
63+
let ty = self.to_ty(tcx);
64+
LvalueTy::Ty {
65+
ty: match ty.sty {
66+
ty::TyArray(inner, size) => {
67+
tcx.mk_array(inner, size-(from as usize)-(to as usize))
68+
}
69+
ty::TySlice(..) => ty,
70+
_ => {
71+
bug!("cannot subslice non-array type: `{:?}`", self)
72+
}
73+
}
74+
}
75+
}
6276
ProjectionElem::Downcast(adt_def1, index) =>
6377
match self.to_ty(tcx).sty {
6478
ty::TyEnum(adt_def, substs) => {
@@ -219,7 +233,6 @@ impl<'a, 'gcx, 'tcx> Mir<'tcx> {
219233
}
220234
}
221235
}
222-
Rvalue::Slice { .. } => None,
223236
Rvalue::InlineAsm { .. } => None
224237
}
225238
}

src/librustc_mir/traversal.rs src/librustc/mir/traversal.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::vec;
1212

1313
use rustc_data_structures::bitvec::BitVector;
1414

15-
use rustc::mir::repr::*;
15+
use super::repr::*;
1616

1717
/// Preorder traversal of a graph.
1818
///

src/librustc/mir/visit.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -533,15 +533,6 @@ macro_rules! make_mir_visitor {
533533
}
534534
}
535535

536-
Rvalue::Slice { ref $($mutability)* input,
537-
from_start,
538-
from_end } => {
539-
self.visit_lvalue(input, LvalueContext::Slice {
540-
from_start: from_start,
541-
from_end: from_end,
542-
});
543-
}
544-
545536
Rvalue::InlineAsm { ref $($mutability)* outputs,
546537
ref $($mutability)* inputs,
547538
asm: _ } => {
@@ -602,6 +593,8 @@ macro_rules! make_mir_visitor {
602593
match *proj {
603594
ProjectionElem::Deref => {
604595
}
596+
ProjectionElem::Subslice { from: _, to: _ } => {
597+
}
605598
ProjectionElem::Field(_field, ref $($mutability)* ty) => {
606599
self.visit_ty(ty);
607600
}

0 commit comments

Comments
 (0)