Skip to content

Commit e66f5a3

Browse files
committed
Don't treat references special
1 parent bd69f9e commit e66f5a3

File tree

1 file changed

+68
-62
lines changed
  • src/librustc_mir/build/matches

1 file changed

+68
-62
lines changed

src/librustc_mir/build/matches/test.rs

+68-62
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,10 @@ use build::matches::{Candidate, MatchPair, Test, TestKind};
2020
use hair::*;
2121
use rustc_data_structures::fx::FxHashMap;
2222
use rustc_data_structures::bitvec::BitVector;
23-
use rustc::middle::const_val::ConstVal;
2423
use rustc::ty::{self, Ty};
2524
use rustc::ty::util::IntTypeExt;
2625
use rustc::mir::*;
27-
use rustc::mir::interpret::{Value, PrimVal};
28-
use rustc::hir::RangeEnd;
26+
use rustc::hir::{RangeEnd, Mutability};
2927
use syntax_pos::Span;
3028
use std::cmp::Ordering;
3129

@@ -258,69 +256,77 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
258256

259257
TestKind::Eq { value, mut ty } => {
260258
let mut val = Operand::Copy(place.clone());
261-
262-
let bytes = match value.val {
263-
ConstVal::Value(Value::ByVal(PrimVal::Ptr(p))) => {
264-
let is_array_ptr = ty
265-
.builtin_deref(true, ty::NoPreference)
266-
.and_then(|t| t.ty.builtin_index())
267-
.map_or(false, |t| t == self.hir.tcx().types.u8);
268-
if is_array_ptr {
269-
self.hir
270-
.tcx()
271-
.interpret_interner
272-
.borrow()
273-
.get_alloc(p.alloc_id)
274-
.map(|alloc| &alloc.bytes[..])
275-
} else {
276-
None
277-
}
278-
},
279-
_ => None,
280-
};
281-
// If we're using b"..." as a pattern, we need to insert an
282-
// unsizing coercion, as the byte string has the type &[u8; N].
283-
let expect = if let Some(bytes) = bytes {
284-
let tcx = self.hir.tcx();
285-
286-
// Unsize the place to &[u8], too, if necessary.
287-
if let ty::TyRef(region, mt) = ty.sty {
288-
if let ty::TyArray(_, _) = mt.ty.sty {
289-
ty = tcx.mk_imm_ref(region, tcx.mk_slice(tcx.types.u8));
290-
let val_slice = self.temp(ty, test.span);
291-
self.cfg.push_assign(block, source_info, &val_slice,
292-
Rvalue::Cast(CastKind::Unsize, val, ty));
293-
val = Operand::Move(val_slice);
294-
}
295-
}
296-
297-
assert!(ty.is_slice());
298-
299-
let array_ty = tcx.mk_array(tcx.types.u8, bytes.len() as u64);
300-
let array_ref = tcx.mk_imm_ref(tcx.types.re_static, array_ty);
301-
let array = self.literal_operand(test.span, array_ref, Literal::Value {
302-
value
303-
});
304-
305-
let slice = self.temp(ty, test.span);
306-
self.cfg.push_assign(block, source_info, &slice,
307-
Rvalue::Cast(CastKind::Unsize, array, ty));
308-
Operand::Move(slice)
309-
} else {
310-
self.literal_operand(test.span, ty, Literal::Value {
311-
value
312-
})
313-
};
314-
315-
// Use PartialEq::eq for references, instead of BinOp::Eq.
259+
let mut expect = self.literal_operand(test.span, ty, Literal::Value {
260+
value
261+
});
262+
// Use PartialEq::eq instead of BinOp::Eq
263+
// (the binop can only handle primitives)
316264
let fail = self.cfg.start_new_block();
317-
let str_or_bytestr = ty
318-
.builtin_deref(true, ty::NoPreference)
319-
.map(|tam| tam.ty);
320-
if let Some(ty) = str_or_bytestr {
265+
if !ty.is_scalar() {
266+
// unsize arrays to slices
267+
let unsize = |ty: Ty<'tcx>| match ty.sty {
268+
ty::TyRef(region, tam) => match tam.ty.sty {
269+
ty::TyArray(inner_ty, n) => Some((region, inner_ty, n)),
270+
_ => None,
271+
},
272+
_ => None,
273+
};
274+
let opt_ref_ty = unsize(ty);
275+
let opt_ref_test_ty = unsize(value.ty);
276+
let mut place = place.clone();
277+
match (opt_ref_ty, opt_ref_test_ty) {
278+
// nothing to do, neither is an array
279+
(None, None) => {},
280+
(Some((region, elem_ty, _)), _) |
281+
(None, Some((region, elem_ty, _))) => {
282+
let tcx = self.hir.tcx();
283+
// make both a slice
284+
ty = tcx.mk_imm_ref(region, tcx.mk_slice(elem_ty));
285+
if opt_ref_ty.is_some() {
286+
place = self.temp(ty, test.span);
287+
self.cfg.push_assign(block, source_info, &place,
288+
Rvalue::Cast(CastKind::Unsize, val, ty));
289+
}
290+
if opt_ref_test_ty.is_some() {
291+
let array = self.literal_operand(test.span, value.ty, Literal::Value {
292+
value
293+
});
294+
295+
let slice = self.temp(ty, test.span);
296+
self.cfg.push_assign(block, source_info, &slice,
297+
Rvalue::Cast(CastKind::Unsize, array, ty));
298+
expect = Operand::Move(slice);
299+
}
300+
},
301+
}
321302
let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
322303
let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty]);
323304

305+
// take the argument by reference
306+
let region_scope = self.topmost_scope();
307+
let region = self.hir.tcx().mk_region(ty::ReScope(region_scope));
308+
let tam = ty::TypeAndMut {
309+
ty,
310+
mutbl: Mutability::MutImmutable,
311+
};
312+
let ref_ty = self.hir.tcx().mk_ref(region, tam);
313+
314+
// let lhs_ref_place = &lhs;
315+
let ref_rvalue = Rvalue::Ref(region, BorrowKind::Shared, place.clone());
316+
let lhs_ref_place = self.temp(ref_ty, test.span);
317+
self.cfg.push_assign(block, source_info, &lhs_ref_place, ref_rvalue);
318+
let val = Operand::Move(lhs_ref_place);
319+
320+
// let rhs_place = rhs;
321+
let rhs_place = self.temp(ty, test.span);
322+
self.cfg.push_assign(block, source_info, &rhs_place, Rvalue::Use(expect));
323+
324+
// let rhs_ref_place = &rhs_place;
325+
let ref_rvalue = Rvalue::Ref(region, BorrowKind::Shared, rhs_place);
326+
let rhs_ref_place = self.temp(ref_ty, test.span);
327+
self.cfg.push_assign(block, source_info, &rhs_ref_place, ref_rvalue);
328+
let expect = Operand::Move(rhs_ref_place);
329+
324330
let bool_ty = self.hir.bool_ty();
325331
let eq_result = self.temp(bool_ty, test.span);
326332
let eq_block = self.cfg.start_new_block();

0 commit comments

Comments
 (0)