Skip to content

Commit 757f8ee

Browse files
authored
Merge pull request #509 from sicking/borrow_fix
Fix ambiguity issues in use of Borrow<T>
2 parents 8f2290f + fd9f3e4 commit 757f8ee

2 files changed

Lines changed: 63 additions & 48 deletions

File tree

src/distributions/uniform.rs

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,15 @@
5454
//! `low < high`). The example below merely wraps another back-end.
5555
//!
5656
//! The `new`, `new_inclusive` and `sample_single` functions use arguments of
57-
//! type Borrow<X> in order to support passing in values by reference or by
58-
//! value. In the implementation of these functions, you can choose to simply
59-
//! use the reference returned by [`Borrow::borrow`], or you can choose to copy
60-
//! or clone the value, whatever is appropriate for your type.
57+
//! type SampleBorrow<X> in order to support passing in values by reference or
58+
//! by value. In the implementation of these functions, you can choose to
59+
//! simply use the reference returned by [`SampleBorrow::borrow`], or you can choose
60+
//! to copy or clone the value, whatever is appropriate for your type.
6161
//!
6262
//! ```
6363
//! use rand::prelude::*;
6464
//! use rand::distributions::uniform::{Uniform, SampleUniform,
65-
//! UniformSampler, UniformFloat};
66-
//! use std::borrow::Borrow;
65+
//! UniformSampler, UniformFloat, SampleBorrow};
6766
//!
6867
//! struct MyF32(f32);
6968
//!
@@ -75,16 +74,16 @@
7574
//! impl UniformSampler for UniformMyF32 {
7675
//! type X = MyF32;
7776
//! fn new<B1, B2>(low: B1, high: B2) -> Self
78-
//! where B1: Borrow<Self::X> + Sized,
79-
//! B2: Borrow<Self::X> + Sized
77+
//! where B1: SampleBorrow<Self::X> + Sized,
78+
//! B2: SampleBorrow<Self::X> + Sized
8079
//! {
8180
//! UniformMyF32 {
8281
//! inner: UniformFloat::<f32>::new(low.borrow().0, high.borrow().0),
8382
//! }
8483
//! }
8584
//! fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
86-
//! where B1: Borrow<Self::X> + Sized,
87-
//! B2: Borrow<Self::X> + Sized
85+
//! where B1: SampleBorrow<Self::X> + Sized,
86+
//! B2: SampleBorrow<Self::X> + Sized
8887
//! {
8988
//! UniformSampler::new(low, high)
9089
//! }
@@ -109,11 +108,10 @@
109108
//! [`UniformInt`]: struct.UniformInt.html
110109
//! [`UniformFloat`]: struct.UniformFloat.html
111110
//! [`UniformDuration`]: struct.UniformDuration.html
112-
//! [`Borrow::borrow`]: https://doc.rust-lang.org/std/borrow/trait.Borrow.html
111+
//! [`Borrow::borrow`]: trait.SampleBorrow.html
113112
114113
#[cfg(feature = "std")]
115114
use std::time::Duration;
116-
use core::borrow::Borrow;
117115

118116
use Rng;
119117
use distributions::Distribution;
@@ -171,17 +169,17 @@ impl<X: SampleUniform> Uniform<X> {
171169
/// Create a new `Uniform` instance which samples uniformly from the half
172170
/// open range `[low, high)` (excluding `high`). Panics if `low >= high`.
173171
pub fn new<B1, B2>(low: B1, high: B2) -> Uniform<X>
174-
where B1: Borrow<X> + Sized,
175-
B2: Borrow<X> + Sized
172+
where B1: SampleBorrow<X> + Sized,
173+
B2: SampleBorrow<X> + Sized
176174
{
177175
Uniform { inner: X::Sampler::new(low, high) }
178176
}
179177

180178
/// Create a new `Uniform` instance which samples uniformly from the closed
181179
/// range `[low, high]` (inclusive). Panics if `low > high`.
182180
pub fn new_inclusive<B1, B2>(low: B1, high: B2) -> Uniform<X>
183-
where B1: Borrow<X> + Sized,
184-
B2: Borrow<X> + Sized
181+
where B1: SampleBorrow<X> + Sized,
182+
B2: SampleBorrow<X> + Sized
185183
{
186184
Uniform { inner: X::Sampler::new_inclusive(low, high) }
187185
}
@@ -228,17 +226,17 @@ pub trait UniformSampler: Sized {
228226
/// Usually users should not call this directly but instead use
229227
/// `Uniform::new`, which asserts that `low < high` before calling this.
230228
fn new<B1, B2>(low: B1, high: B2) -> Self
231-
where B1: Borrow<Self::X> + Sized,
232-
B2: Borrow<Self::X> + Sized;
229+
where B1: SampleBorrow<Self::X> + Sized,
230+
B2: SampleBorrow<Self::X> + Sized;
233231

234232
/// Construct self, with inclusive bounds `[low, high]`.
235233
///
236234
/// Usually users should not call this directly but instead use
237235
/// `Uniform::new_inclusive`, which asserts that `low <= high` before
238236
/// calling this.
239237
fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
240-
where B1: Borrow<Self::X> + Sized,
241-
B2: Borrow<Self::X> + Sized;
238+
where B1: SampleBorrow<Self::X> + Sized,
239+
B2: SampleBorrow<Self::X> + Sized;
242240

243241
/// Sample a value.
244242
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::X;
@@ -256,8 +254,8 @@ pub trait UniformSampler: Sized {
256254
/// result.
257255
fn sample_single<R: Rng + ?Sized, B1, B2>(low: B1, high: B2, rng: &mut R)
258256
-> Self::X
259-
where B1: Borrow<Self::X> + Sized,
260-
B2: Borrow<Self::X> + Sized
257+
where B1: SampleBorrow<Self::X> + Sized,
258+
B2: SampleBorrow<Self::X> + Sized
261259
{
262260
let uniform: Self = UniformSampler::new(low, high);
263261
uniform.sample(rng)
@@ -270,6 +268,22 @@ impl<X: SampleUniform> From<::core::ops::Range<X>> for Uniform<X> {
270268
}
271269
}
272270

271+
/// Helper trait similar to [`Borrow`] but implemented
272+
/// only for SampleUniform and references to SampleUniform in
273+
/// order to resolve ambiguity issues.
274+
/// [`Borrow`] https://doc.rust-lang.org/std/borrow/trait.Borrow.html
275+
pub trait SampleBorrow<Borrowed> {
276+
/// Immutably borrows from an owned value. See [`Borrow::borrow`]
277+
/// [`Borrow::borrow`] https://doc.rust-lang.org/std/borrow/trait.Borrow.html#tymethod.borrow
278+
fn borrow(&self) -> &Borrowed;
279+
}
280+
impl<Borrowed> SampleBorrow<Borrowed> for Borrowed where Borrowed: SampleUniform {
281+
fn borrow(&self) -> &Borrowed { self }
282+
}
283+
impl<'a, Borrowed> SampleBorrow<Borrowed> for &'a Borrowed where Borrowed: SampleUniform {
284+
fn borrow(&self) -> &Borrowed { *self }
285+
}
286+
273287
////////////////////////////////////////////////////////////////////////////////
274288

275289
// What follows are all back-ends.
@@ -339,8 +353,8 @@ macro_rules! uniform_int_impl {
339353
#[inline] // if the range is constant, this helps LLVM to do the
340354
// calculations at compile-time.
341355
fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
342-
where B1: Borrow<Self::X> + Sized,
343-
B2: Borrow<Self::X> + Sized
356+
where B1: SampleBorrow<Self::X> + Sized,
357+
B2: SampleBorrow<Self::X> + Sized
344358
{
345359
let low = *low_b.borrow();
346360
let high = *high_b.borrow();
@@ -351,8 +365,8 @@ macro_rules! uniform_int_impl {
351365
#[inline] // if the range is constant, this helps LLVM to do the
352366
// calculations at compile-time.
353367
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
354-
where B1: Borrow<Self::X> + Sized,
355-
B2: Borrow<Self::X> + Sized
368+
where B1: SampleBorrow<Self::X> + Sized,
369+
B2: SampleBorrow<Self::X> + Sized
356370
{
357371
let low = *low_b.borrow();
358372
let high = *high_b.borrow();
@@ -401,8 +415,8 @@ macro_rules! uniform_int_impl {
401415

402416
fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R)
403417
-> Self::X
404-
where B1: Borrow<Self::X> + Sized,
405-
B2: Borrow<Self::X> + Sized
418+
where B1: SampleBorrow<Self::X> + Sized,
419+
B2: SampleBorrow<Self::X> + Sized
406420
{
407421
let low = *low_b.borrow();
408422
let high = *high_b.borrow();
@@ -573,8 +587,8 @@ macro_rules! uniform_float_impl {
573587
type X = $ty;
574588

575589
fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
576-
where B1: Borrow<Self::X> + Sized,
577-
B2: Borrow<Self::X> + Sized
590+
where B1: SampleBorrow<Self::X> + Sized,
591+
B2: SampleBorrow<Self::X> + Sized
578592
{
579593
let low = *low_b.borrow();
580594
let high = *high_b.borrow();
@@ -588,8 +602,8 @@ macro_rules! uniform_float_impl {
588602
}
589603

590604
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
591-
where B1: Borrow<Self::X> + Sized,
592-
B2: Borrow<Self::X> + Sized
605+
where B1: SampleBorrow<Self::X> + Sized,
606+
B2: SampleBorrow<Self::X> + Sized
593607
{
594608
let low = *low_b.borrow();
595609
let high = *high_b.borrow();
@@ -617,8 +631,8 @@ macro_rules! uniform_float_impl {
617631

618632
fn sample_single<R: Rng + ?Sized, B1, B2>(low_b: B1, high_b: B2, rng: &mut R)
619633
-> Self::X
620-
where B1: Borrow<Self::X> + Sized,
621-
B2: Borrow<Self::X> + Sized
634+
where B1: SampleBorrow<Self::X> + Sized,
635+
B2: SampleBorrow<Self::X> + Sized
622636
{
623637
let low = *low_b.borrow();
624638
let high = *high_b.borrow();
@@ -679,8 +693,8 @@ impl UniformSampler for UniformDuration {
679693

680694
#[inline]
681695
fn new<B1, B2>(low_b: B1, high_b: B2) -> Self
682-
where B1: Borrow<Self::X> + Sized,
683-
B2: Borrow<Self::X> + Sized
696+
where B1: SampleBorrow<Self::X> + Sized,
697+
B2: SampleBorrow<Self::X> + Sized
684698
{
685699
let low = *low_b.borrow();
686700
let high = *high_b.borrow();
@@ -690,8 +704,8 @@ impl UniformSampler for UniformDuration {
690704

691705
#[inline]
692706
fn new_inclusive<B1, B2>(low_b: B1, high_b: B2) -> Self
693-
where B1: Borrow<Self::X> + Sized,
694-
B2: Borrow<Self::X> + Sized
707+
where B1: SampleBorrow<Self::X> + Sized,
708+
B2: SampleBorrow<Self::X> + Sized
695709
{
696710
let low = *low_b.borrow();
697711
let high = *high_b.borrow();
@@ -748,7 +762,7 @@ impl UniformSampler for UniformDuration {
748762
#[cfg(test)]
749763
mod tests {
750764
use Rng;
751-
use distributions::uniform::{Uniform, UniformSampler, UniformFloat, SampleUniform};
765+
use distributions::uniform::Uniform;
752766

753767
#[should_panic]
754768
#[test]
@@ -885,7 +899,7 @@ mod tests {
885899

886900
#[test]
887901
fn test_custom_uniform() {
888-
use core::borrow::Borrow;
902+
use distributions::uniform::{UniformSampler, UniformFloat, SampleUniform, SampleBorrow};
889903
#[derive(Clone, Copy, PartialEq, PartialOrd)]
890904
struct MyF32 {
891905
x: f32,
@@ -897,16 +911,16 @@ mod tests {
897911
impl UniformSampler for UniformMyF32 {
898912
type X = MyF32;
899913
fn new<B1, B2>(low: B1, high: B2) -> Self
900-
where B1: Borrow<Self::X> + Sized,
901-
B2: Borrow<Self::X> + Sized
914+
where B1: SampleBorrow<Self::X> + Sized,
915+
B2: SampleBorrow<Self::X> + Sized
902916
{
903917
UniformMyF32 {
904918
inner: UniformFloat::<f32>::new(low.borrow().x, high.borrow().x),
905919
}
906920
}
907921
fn new_inclusive<B1, B2>(low: B1, high: B2) -> Self
908-
where B1: Borrow<Self::X> + Sized,
909-
B2: Borrow<Self::X> + Sized
922+
where B1: SampleBorrow<Self::X> + Sized,
923+
B2: SampleBorrow<Self::X> + Sized
910924
{
911925
UniformSampler::new(low, high)
912926
}

src/lib.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,8 @@ pub mod read {
323323

324324

325325
use core::{mem, slice};
326-
use core::borrow::Borrow;
327326
use distributions::{Distribution, Standard};
328-
use distributions::uniform::{SampleUniform, UniformSampler};
327+
use distributions::uniform::{SampleUniform, UniformSampler, SampleBorrow};
329328

330329
/// An automatically-implemented extension trait on [`RngCore`] providing high-level
331330
/// generic methods for sampling values and other convenience methods.
@@ -411,8 +410,8 @@ pub trait Rng: RngCore {
411410
///
412411
/// [`Uniform`]: distributions/uniform/struct.Uniform.html
413412
fn gen_range<T: SampleUniform, B1, B2>(&mut self, low: B1, high: B2) -> T
414-
where B1: Borrow<T> + Sized,
415-
B2: Borrow<T> + Sized {
413+
where B1: SampleBorrow<T> + Sized,
414+
B2: SampleBorrow<T> + Sized {
416415
T::Sampler::sample_single(low, high, self)
417416
}
418417

@@ -940,6 +939,8 @@ mod test {
940939
assert!(a >= 10u16 && a < 99u16);
941940
let a = r.gen_range(-100i32, &2000);
942941
assert!(a >= -100i32 && a < 2000i32);
942+
let a = r.gen_range(&12u32, &24u32);
943+
assert!(a >= 12u32 && a < 24u32);
943944

944945
assert_eq!(r.gen_range(0u32, 1), 0u32);
945946
assert_eq!(r.gen_range(-12i64, -11), -12i64);

0 commit comments

Comments
 (0)