Skip to content

Commit 9de34a8

Browse files
committed
Auto merge of #23673 - nikomatsakis:issue-23319-binops-ng-5, r=pnkfelix
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 the unstable SIMD types, which don't fit in with the current traits -- in that case, the LHS type must be known to be SIMD 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 14192d6 + 7595c25 commit 9de34a8

39 files changed

+685
-563
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
@@ -3039,6 +3039,10 @@ pub fn mk_nil<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
30393039
mk_tup(cx, Vec::new())
30403040
}
30413041

3042+
pub fn mk_bool<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
3043+
mk_t(cx, ty_bool)
3044+
}
3045+
30423046
pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>,
30433047
opt_def_id: Option<ast::DefId>,
30443048
fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
@@ -3406,8 +3410,12 @@ pub fn type_is_scalar(ty: Ty) -> bool {
34063410
/// Returns true if this type is a floating point type and false otherwise.
34073411
pub fn type_is_floating_point(ty: Ty) -> bool {
34083412
match ty.sty {
3409-
ty_float(_) => true,
3410-
_ => false,
3413+
ty_float(_) |
3414+
ty_infer(FloatVar(_)) =>
3415+
true,
3416+
3417+
_ =>
3418+
false,
34113419
}
34123420
}
34133421

@@ -5805,78 +5813,6 @@ pub fn closure_upvars<'tcx>(typer: &mc::Typer<'tcx>,
58055813
}
58065814
}
58075815

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

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
@@ -2384,6 +2384,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
23842384
}
23852385
}
23862386

2387+
#[derive(Debug)]
23872388
enum OverflowOp {
23882389
Add,
23892390
Sub,
@@ -2413,6 +2414,7 @@ enum OverflowCodegen {
24132414

24142415
enum OverflowOpViaInputCheck { Shl, Shr, }
24152416

2417+
#[derive(Debug)]
24162418
enum OverflowOpViaIntrinsic { Add, Sub, Mul, }
24172419

24182420
impl OverflowOpViaIntrinsic {
@@ -2437,7 +2439,8 @@ impl OverflowOpViaIntrinsic {
24372439
_ => panic!("unsupported target word size")
24382440
},
24392441
ref t @ ty_uint(_) | ref t @ ty_int(_) => t.clone(),
2440-
_ => panic!("tried to get overflow intrinsic for non-int type")
2442+
_ => panic!("tried to get overflow intrinsic for {:?} applied to non-int type",
2443+
*self)
24412444
};
24422445

24432446
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)