Skip to content

Commit 05f83b9

Browse files
committed
Auto merge of #23673 - nikomatsakis:issue-23319-binops-ng-5, r=<try>
The current binary operator code assumed that if the LHS was a scalar (`i32` etc), then the RHS had to match. This is not true with multidispatch. This PR generalizes the existing code to (primarily) use the traits -- this also allows us to defer the precise type-checking when the types aren't fully known. The one caveat is unstable SIMD types, which don't fit in with the current traits -- in that case, the types must be known ahead of time. There is one semi-hacky bit in that during writeback, for builtin operators, if the types resolve to scalars (i32 etc) then we clear the method override. This is because we know what the semantics are and it is more efficient to generate the code directly. It also ensures that we can use these overloaded operators in constants and so forth. cc @japaric cc @aturon Fixes #23319 (and others).
2 parents ed81038 + 82fdbdb commit 05f83b9

25 files changed

+614
-520
lines changed

src/libcollectionstest/bench.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ macro_rules! map_insert_rand_bench {
2222
let mut rng = rand::weak_rng();
2323

2424
for _ in 0..n {
25-
let i = rng.gen() % n;
25+
let i = rng.gen::<usize>() % n;
2626
map.insert(i, i);
2727
}
2828

2929
// measure
3030
b.iter(|| {
31-
let k = rng.gen() % n;
31+
let k = rng.gen::<usize>() % n;
3232
map.insert(k, k);
3333
map.remove(&k);
3434
});
@@ -77,7 +77,7 @@ macro_rules! map_find_rand_bench {
7777

7878
// setup
7979
let mut rng = rand::weak_rng();
80-
let mut keys: Vec<_> = (0..n).map(|_| rng.gen() % n).collect();
80+
let mut keys: Vec<_> = (0..n).map(|_| rng.gen::<usize>() % n).collect();
8181

8282
for &k in &keys {
8383
map.insert(k, k);

src/libcore/ops.rs

+2-22
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ pub trait Neg {
485485
macro_rules! neg_impl {
486486
($($t:ty)*) => ($(
487487
#[stable(feature = "rust1", since = "1.0.0")]
488+
#[allow(unsigned_negation)]
488489
impl Neg for $t {
489490
#[stable(feature = "rust1", since = "1.0.0")]
490491
type Output = $t;
@@ -498,28 +499,7 @@ macro_rules! neg_impl {
498499
)*)
499500
}
500501

501-
macro_rules! neg_uint_impl {
502-
($t:ty, $t_signed:ty) => {
503-
#[stable(feature = "rust1", since = "1.0.0")]
504-
impl Neg for $t {
505-
type Output = $t;
506-
507-
#[inline]
508-
fn neg(self) -> $t { -(self as $t_signed) as $t }
509-
}
510-
511-
forward_ref_unop! { impl Neg, neg for $t }
512-
}
513-
}
514-
515-
neg_impl! { isize i8 i16 i32 i64 f32 f64 }
516-
517-
neg_uint_impl! { usize, isize }
518-
neg_uint_impl! { u8, i8 }
519-
neg_uint_impl! { u16, i16 }
520-
neg_uint_impl! { u32, i32 }
521-
neg_uint_impl! { u64, i64 }
522-
502+
neg_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
523503

524504
/// The `Not` trait is used to specify the functionality of unary `!`.
525505
///

src/librand/distributions/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ fn ziggurat<R: Rng, P, Z>(
256256
return zero_case(rng, u);
257257
}
258258
// algebraically equivalent to f1 + DRanU()*(f0 - f1) < 1
259-
if f_tab[i + 1] + (f_tab[i] - f_tab[i + 1]) * rng.gen() < pdf(x) {
259+
if f_tab[i + 1] + (f_tab[i] - f_tab[i + 1]) * rng.gen::<f64>() < pdf(x) {
260260
return x;
261261
}
262262
}

src/librand/distributions/range.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ macro_rules! float_impl {
154154
}
155155
}
156156
fn sample_range<R: Rng>(r: &Range<$ty>, rng: &mut R) -> $ty {
157-
r.low + r.range * rng.gen()
157+
r.low + r.range * rng.gen::<$ty>()
158158
}
159159
}
160160
}

src/librustc/middle/ty.rs

+10-74
Original file line numberDiff line numberDiff line change
@@ -3004,6 +3004,10 @@ pub fn mk_nil<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
30043004
mk_tup(cx, Vec::new())
30053005
}
30063006

3007+
pub fn mk_bool<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
3008+
mk_t(cx, ty_bool)
3009+
}
3010+
30073011
pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>,
30083012
opt_def_id: Option<ast::DefId>,
30093013
fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
@@ -3371,8 +3375,12 @@ pub fn type_is_scalar(ty: Ty) -> bool {
33713375
/// Returns true if this type is a floating point type and false otherwise.
33723376
pub fn type_is_floating_point(ty: Ty) -> bool {
33733377
match ty.sty {
3374-
ty_float(_) => true,
3375-
_ => false,
3378+
ty_float(_) |
3379+
ty_infer(FloatVar(_)) =>
3380+
true,
3381+
3382+
_ =>
3383+
false,
33763384
}
33773385
}
33783386

@@ -5797,78 +5805,6 @@ pub fn closure_upvars<'tcx>(typer: &mc::Typer<'tcx>,
57975805
}
57985806
}
57995807

5800-
pub fn is_binopable<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, op: ast::BinOp) -> bool {
5801-
#![allow(non_upper_case_globals)]
5802-
const tycat_other: int = 0;
5803-
const tycat_bool: int = 1;
5804-
const tycat_char: int = 2;
5805-
const tycat_int: int = 3;
5806-
const tycat_float: int = 4;
5807-
const tycat_raw_ptr: int = 6;
5808-
5809-
const opcat_add: int = 0;
5810-
const opcat_sub: int = 1;
5811-
const opcat_mult: int = 2;
5812-
const opcat_shift: int = 3;
5813-
const opcat_rel: int = 4;
5814-
const opcat_eq: int = 5;
5815-
const opcat_bit: int = 6;
5816-
const opcat_logic: int = 7;
5817-
const opcat_mod: int = 8;
5818-
5819-
fn opcat(op: ast::BinOp) -> int {
5820-
match op.node {
5821-
ast::BiAdd => opcat_add,
5822-
ast::BiSub => opcat_sub,
5823-
ast::BiMul => opcat_mult,
5824-
ast::BiDiv => opcat_mult,
5825-
ast::BiRem => opcat_mod,
5826-
ast::BiAnd => opcat_logic,
5827-
ast::BiOr => opcat_logic,
5828-
ast::BiBitXor => opcat_bit,
5829-
ast::BiBitAnd => opcat_bit,
5830-
ast::BiBitOr => opcat_bit,
5831-
ast::BiShl => opcat_shift,
5832-
ast::BiShr => opcat_shift,
5833-
ast::BiEq => opcat_eq,
5834-
ast::BiNe => opcat_eq,
5835-
ast::BiLt => opcat_rel,
5836-
ast::BiLe => opcat_rel,
5837-
ast::BiGe => opcat_rel,
5838-
ast::BiGt => opcat_rel
5839-
}
5840-
}
5841-
5842-
fn tycat<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> int {
5843-
if type_is_simd(cx, ty) {
5844-
return tycat(cx, simd_type(cx, ty))
5845-
}
5846-
match ty.sty {
5847-
ty_char => tycat_char,
5848-
ty_bool => tycat_bool,
5849-
ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
5850-
ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
5851-
ty_ptr(_) => tycat_raw_ptr,
5852-
_ => tycat_other
5853-
}
5854-
}
5855-
5856-
const t: bool = true;
5857-
const f: bool = false;
5858-
5859-
let tbl = [
5860-
// +, -, *, shift, rel, ==, bit, logic, mod
5861-
/*other*/ [f, f, f, f, f, f, f, f, f],
5862-
/*bool*/ [f, f, f, f, t, t, t, t, f],
5863-
/*char*/ [f, f, f, f, t, t, f, f, f],
5864-
/*int*/ [t, t, t, t, t, t, t, f, t],
5865-
/*float*/ [t, t, t, f, t, t, f, f, f],
5866-
/*bot*/ [t, t, t, t, t, t, t, t, t],
5867-
/*raw ptr*/ [f, f, f, f, t, t, f, f, f]];
5868-
5869-
return tbl[tycat(cx, ty) as uint ][opcat(op) as uint];
5870-
}
5871-
58725808
// Returns the repeat count for a repeating vector expression.
58735809
pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
58745810
match const_eval::eval_const_expr_partial(tcx, count_expr, Some(tcx.types.uint)) {

src/librustc_trans/trans/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
560560
_ => bcx.sess().bug("compare_scalar_types: must be a comparison operator")
561561
}
562562
}
563-
ty::ty_bool | ty::ty_uint(_) | ty::ty_char => {
563+
ty::ty_bare_fn(..) | ty::ty_bool | ty::ty_uint(_) | ty::ty_char => {
564564
ICmp(bcx, bin_op_to_icmp_predicate(bcx.ccx(), op, false), lhs, rhs, debug_loc)
565565
}
566566
ty::ty_ptr(mt) if common::type_is_sized(bcx.tcx(), mt.ty) => {

src/librustc_trans/trans/consts.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,14 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
351351
fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
352352
e: &ast::Expr,
353353
ety: Ty<'tcx>,
354-
param_substs: &'tcx Substs<'tcx>) -> ValueRef {
354+
param_substs: &'tcx Substs<'tcx>)
355+
-> ValueRef
356+
{
357+
debug!("const_expr_unadjusted(e={}, ety={}, param_substs={})",
358+
e.repr(cx.tcx()),
359+
ety.repr(cx.tcx()),
360+
param_substs.repr(cx.tcx()));
361+
355362
let map_list = |exprs: &[P<ast::Expr>]| {
356363
exprs.iter().map(|e| const_expr(cx, &**e, param_substs).0)
357364
.fold(Vec::new(), |mut l, val| { l.push(val); l })
@@ -366,6 +373,9 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
366373
/* Neither type is bottom, and we expect them to be unified
367374
* already, so the following is safe. */
368375
let (te1, ty) = const_expr(cx, &**e1, param_substs);
376+
debug!("const_expr_unadjusted: te1={}, ty={}",
377+
cx.tn().val_to_string(te1),
378+
ty.repr(cx.tcx()));
369379
let is_simd = ty::type_is_simd(cx.tcx(), ty);
370380
let intype = if is_simd {
371381
ty::simd_type(cx.tcx(), ty)

src/librustc_trans/trans/expr.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -2390,6 +2390,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
23902390
}
23912391
}
23922392

2393+
#[derive(Debug)]
23932394
enum OverflowOp {
23942395
Add,
23952396
Sub,
@@ -2419,6 +2420,7 @@ enum OverflowCodegen {
24192420

24202421
enum OverflowOpViaInputCheck { Shl, Shr, }
24212422

2423+
#[derive(Debug)]
24222424
enum OverflowOpViaIntrinsic { Add, Sub, Mul, }
24232425

24242426
impl OverflowOpViaIntrinsic {
@@ -2443,7 +2445,8 @@ impl OverflowOpViaIntrinsic {
24432445
_ => panic!("unsupported target word size")
24442446
},
24452447
ref t @ ty_uint(_) | ref t @ ty_int(_) => t.clone(),
2446-
_ => panic!("tried to get overflow intrinsic for non-int type")
2448+
_ => panic!("tried to get overflow intrinsic for {:?} applied to non-int type",
2449+
*self)
24472450
};
24482451

24492452
match *self {

src/librustc_typeck/check/callee.rs

-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
// except according to those terms.
1010

1111
use super::autoderef;
12-
use super::AutorefArgs;
1312
use super::check_argument_types;
1413
use super::check_expr;
1514
use super::check_method_argument_types;
@@ -258,7 +257,6 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
258257
&fn_sig.inputs,
259258
&expected_arg_tys[..],
260259
arg_exprs,
261-
AutorefArgs::No,
262260
fn_sig.variadic,
263261
TupleArgumentsFlag::DontTupleArguments);
264262

@@ -288,7 +286,6 @@ fn confirm_deferred_closure_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
288286
&*fn_sig.inputs,
289287
&*expected_arg_tys,
290288
arg_exprs,
291-
AutorefArgs::No,
292289
fn_sig.variadic,
293290
TupleArgumentsFlag::TupleArguments);
294291

@@ -308,7 +305,6 @@ fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
308305
method_callee.ty,
309306
callee_expr,
310307
arg_exprs,
311-
AutorefArgs::No,
312308
TupleArgumentsFlag::TupleArguments,
313309
expected);
314310
write_call(fcx, call_expr, output_type);

0 commit comments

Comments
 (0)