diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 0b392897f9d8a..d23f5244d88d4 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -878,40 +878,4 @@ impl f32 { pub fn atanh(self) -> f32 { 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() } - - /// Linear interpolation between `start` and `end`. - /// - /// This enables linear interpolation between `start` and `end`, where start is represented by - /// `self == 0.0` and `end` is represented by `self == 1.0`. This is the basis of all - /// "transition", "easing", or "step" functions; if you change `self` from 0.0 to 1.0 - /// at a given rate, the result will change from `start` to `end` at a similar rate. - /// - /// Values below 0.0 or above 1.0 are allowed, allowing you to extrapolate values outside the - /// range from `start` to `end`. This also is useful for transition functions which might - /// move slightly past the end or start for a desired effect. Mathematically, the values - /// returned are equivalent to `start + self * (end - start)`, although we make a few specific - /// guarantees that are useful specifically to linear interpolation. - /// - /// These guarantees are: - /// - /// * If `start` and `end` are [finite], the value at 0.0 is always `start` and the - /// value at 1.0 is always `end`. (exactness) - /// * If `start` and `end` are [finite], the values will always move in the direction from - /// `start` to `end` (monotonicity) - /// * If `self` is [finite] and `start == end`, the value at any point will always be - /// `start == end`. (consistency) - /// - /// [finite]: #method.is_finite - #[must_use = "method returns a new number and does not mutate the original value"] - #[unstable(feature = "float_interpolation", issue = "86269")] - pub fn lerp(self, start: f32, end: f32) -> f32 { - // consistent - if start == end { - start - - // exact/monotonic - } else { - self.mul_add(end, (-self).mul_add(start, start)) - } - } } diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs index fe66a73afd63a..0d4b865f3392a 100644 --- a/library/std/src/f32/tests.rs +++ b/library/std/src/f32/tests.rs @@ -757,66 +757,3 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::INFINITY)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); } - -#[test] -fn test_lerp_exact() { - // simple values - assert_eq!(f32::lerp(0.0, 2.0, 4.0), 2.0); - assert_eq!(f32::lerp(1.0, 2.0, 4.0), 4.0); - - // boundary values - assert_eq!(f32::lerp(0.0, f32::MIN, f32::MAX), f32::MIN); - assert_eq!(f32::lerp(1.0, f32::MIN, f32::MAX), f32::MAX); -} - -#[test] -fn test_lerp_consistent() { - assert_eq!(f32::lerp(f32::MAX, f32::MIN, f32::MIN), f32::MIN); - assert_eq!(f32::lerp(f32::MIN, f32::MAX, f32::MAX), f32::MAX); - - // as long as t is finite, a/b can be infinite - assert_eq!(f32::lerp(f32::MAX, f32::NEG_INFINITY, f32::NEG_INFINITY), f32::NEG_INFINITY); - assert_eq!(f32::lerp(f32::MIN, f32::INFINITY, f32::INFINITY), f32::INFINITY); -} - -#[test] -fn test_lerp_nan_infinite() { - // non-finite t is not NaN if a/b different - assert!(!f32::lerp(f32::INFINITY, f32::MIN, f32::MAX).is_nan()); - assert!(!f32::lerp(f32::NEG_INFINITY, f32::MIN, f32::MAX).is_nan()); -} - -#[test] -fn test_lerp_values() { - // just a few basic values - assert_eq!(f32::lerp(0.25, 1.0, 2.0), 1.25); - assert_eq!(f32::lerp(0.50, 1.0, 2.0), 1.50); - assert_eq!(f32::lerp(0.75, 1.0, 2.0), 1.75); -} - -#[test] -fn test_lerp_monotonic() { - // near 0 - let below_zero = f32::lerp(-f32::EPSILON, f32::MIN, f32::MAX); - let zero = f32::lerp(0.0, f32::MIN, f32::MAX); - let above_zero = f32::lerp(f32::EPSILON, f32::MIN, f32::MAX); - assert!(below_zero <= zero); - assert!(zero <= above_zero); - assert!(below_zero <= above_zero); - - // near 0.5 - let below_half = f32::lerp(0.5 - f32::EPSILON, f32::MIN, f32::MAX); - let half = f32::lerp(0.5, f32::MIN, f32::MAX); - let above_half = f32::lerp(0.5 + f32::EPSILON, f32::MIN, f32::MAX); - assert!(below_half <= half); - assert!(half <= above_half); - assert!(below_half <= above_half); - - // near 1 - let below_one = f32::lerp(1.0 - f32::EPSILON, f32::MIN, f32::MAX); - let one = f32::lerp(1.0, f32::MIN, f32::MAX); - let above_one = f32::lerp(1.0 + f32::EPSILON, f32::MIN, f32::MAX); - assert!(below_one <= one); - assert!(one <= above_one); - assert!(below_one <= above_one); -} diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index 602cceb5d1a1c..55e17b471905d 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -881,42 +881,6 @@ impl f64 { 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p() } - /// Linear interpolation between `start` and `end`. - /// - /// This enables linear interpolation between `start` and `end`, where start is represented by - /// `self == 0.0` and `end` is represented by `self == 1.0`. This is the basis of all - /// "transition", "easing", or "step" functions; if you change `self` from 0.0 to 1.0 - /// at a given rate, the result will change from `start` to `end` at a similar rate. - /// - /// Values below 0.0 or above 1.0 are allowed, allowing you to extrapolate values outside the - /// range from `start` to `end`. This also is useful for transition functions which might - /// move slightly past the end or start for a desired effect. Mathematically, the values - /// returned are equivalent to `start + self * (end - start)`, although we make a few specific - /// guarantees that are useful specifically to linear interpolation. - /// - /// These guarantees are: - /// - /// * If `start` and `end` are [finite], the value at 0.0 is always `start` and the - /// value at 1.0 is always `end`. (exactness) - /// * If `start` and `end` are [finite], the values will always move in the direction from - /// `start` to `end` (monotonicity) - /// * If `self` is [finite] and `start == end`, the value at any point will always be - /// `start == end`. (consistency) - /// - /// [finite]: #method.is_finite - #[must_use = "method returns a new number and does not mutate the original value"] - #[unstable(feature = "float_interpolation", issue = "86269")] - pub fn lerp(self, start: f64, end: f64) -> f64 { - // consistent - if start == end { - start - - // exact/monotonic - } else { - self.mul_add(end, (-self).mul_add(start, start)) - } - } - // Solaris/Illumos requires a wrapper around log, log2, and log10 functions // because of their non-standard behavior (e.g., log(-n) returns -Inf instead // of expected NaN). diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 04cb0109261a4..5c163cfe90e0b 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -753,58 +753,3 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::INFINITY)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); } - -#[test] -fn test_lerp_exact() { - // simple values - assert_eq!(f64::lerp(0.0, 2.0, 4.0), 2.0); - assert_eq!(f64::lerp(1.0, 2.0, 4.0), 4.0); - - // boundary values - assert_eq!(f64::lerp(0.0, f64::MIN, f64::MAX), f64::MIN); - assert_eq!(f64::lerp(1.0, f64::MIN, f64::MAX), f64::MAX); -} - -#[test] -fn test_lerp_consistent() { - assert_eq!(f64::lerp(f64::MAX, f64::MIN, f64::MIN), f64::MIN); - assert_eq!(f64::lerp(f64::MIN, f64::MAX, f64::MAX), f64::MAX); - - // as long as t is finite, a/b can be infinite - assert_eq!(f64::lerp(f64::MAX, f64::NEG_INFINITY, f64::NEG_INFINITY), f64::NEG_INFINITY); - assert_eq!(f64::lerp(f64::MIN, f64::INFINITY, f64::INFINITY), f64::INFINITY); -} - -#[test] -fn test_lerp_nan_infinite() { - // non-finite t is not NaN if a/b different - assert!(!f64::lerp(f64::INFINITY, f64::MIN, f64::MAX).is_nan()); - assert!(!f64::lerp(f64::NEG_INFINITY, f64::MIN, f64::MAX).is_nan()); -} - -#[test] -fn test_lerp_values() { - // just a few basic values - assert_eq!(f64::lerp(0.25, 1.0, 2.0), 1.25); - assert_eq!(f64::lerp(0.50, 1.0, 2.0), 1.50); - assert_eq!(f64::lerp(0.75, 1.0, 2.0), 1.75); -} - -#[test] -fn test_lerp_monotonic() { - // near 0 - let below_zero = f64::lerp(-f64::EPSILON, f64::MIN, f64::MAX); - let zero = f64::lerp(0.0, f64::MIN, f64::MAX); - let above_zero = f64::lerp(f64::EPSILON, f64::MIN, f64::MAX); - assert!(below_zero <= zero); - assert!(zero <= above_zero); - assert!(below_zero <= above_zero); - - // near 1 - let below_one = f64::lerp(1.0 - f64::EPSILON, f64::MIN, f64::MAX); - let one = f64::lerp(1.0, f64::MIN, f64::MAX); - let above_one = f64::lerp(1.0 + f64::EPSILON, f64::MIN, f64::MAX); - assert!(below_one <= one); - assert!(one <= above_one); - assert!(below_one <= above_one); -} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 335e0e072f3d9..d7c0ffd476a59 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -284,7 +284,6 @@ #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] #![feature(extend_one)] -#![feature(float_interpolation)] #![feature(fn_traits)] #![feature(format_args_nl)] #![feature(gen_future)] diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 6fa0425c4956b..443ac2821342e 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -412,7 +412,7 @@ impl FromWithTcx for Type { .map(|t| { clean::GenericBound::TraitBound(t, rustc_hir::TraitBoundModifier::None) }) - .chain(lt.into_iter().map(clean::GenericBound::Outlives)) + .chain(lt.map(clean::GenericBound::Outlives)) .map(|bound| bound.into_tcx(tcx)) .collect(), } diff --git a/src/test/ui/generic-associated-types/issue-87258_a.rs b/src/test/ui/generic-associated-types/issue-87258_a.rs new file mode 100644 index 0000000000000..d9d17751fa6e2 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87258_a.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] +#![feature(generic_associated_types)] + +// See https://github.com/rust-lang/rust/issues/87258#issuecomment-883293367 + +trait Trait1 {} + +struct Struct<'b>(&'b ()); + +impl<'d> Trait1 for Struct<'d> {} + +pub trait Trait2 { + type FooFuture<'a>: Trait1; + fn foo<'a>() -> Self::FooFuture<'a>; +} + +impl<'c, S: Trait2> Trait2 for &'c mut S { + type FooFuture<'a> = impl Trait1; + fn foo<'a>() -> Self::FooFuture<'a> { //~ ERROR + Struct(unimplemented!()) + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-87258_a.stderr b/src/test/ui/generic-associated-types/issue-87258_a.stderr new file mode 100644 index 0000000000000..93513a4563f07 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87258_a.stderr @@ -0,0 +1,11 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/issue-87258_a.rs:19:21 + | +LL | fn foo<'a>() -> Self::FooFuture<'a> { + | ^^^^^^^^^^^^^^^^^^^ + | + = note: hidden type `Struct<'_>` captures lifetime '_#7r + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/generic-associated-types/issue-87258_b.rs b/src/test/ui/generic-associated-types/issue-87258_b.rs new file mode 100644 index 0000000000000..b29a978f517ff --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87258_b.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] +#![feature(generic_associated_types)] + +// See https://github.com/rust-lang/rust/issues/87258#issuecomment-883293367 + +trait Trait1 {} + +struct Struct<'b>(&'b ()); + +impl<'d> Trait1 for Struct<'d> {} + +pub trait Trait2 { + type FooFuture<'a>: Trait1; + fn foo<'a>() -> Self::FooFuture<'a>; +} + +type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1; + +impl<'c, S: Trait2> Trait2 for &'c mut S { + type FooFuture<'a> = Helper<'c, 'a, S>; + fn foo<'a>() -> Self::FooFuture<'a> { //~ ERROR + Struct(unimplemented!()) + } +} + +fn main() {} diff --git a/src/test/ui/generic-associated-types/issue-87258_b.stderr b/src/test/ui/generic-associated-types/issue-87258_b.stderr new file mode 100644 index 0000000000000..e077a423400df --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87258_b.stderr @@ -0,0 +1,11 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/issue-87258_b.rs:21:21 + | +LL | fn foo<'a>() -> Self::FooFuture<'a> { + | ^^^^^^^^^^^^^^^^^^^ + | + = note: hidden type `Struct<'_>` captures lifetime '_#7r + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/typeck/issue-90164.rs b/src/test/ui/typeck/issue-90164.rs new file mode 100644 index 0000000000000..63350433e46a6 --- /dev/null +++ b/src/test/ui/typeck/issue-90164.rs @@ -0,0 +1,9 @@ +fn copy(_: R, _: W) {} + +fn f(r: T) { + let w = (); + copy(r, w); + //~^ ERROR [E0277] +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-90164.stderr b/src/test/ui/typeck/issue-90164.stderr new file mode 100644 index 0000000000000..1e2f1bae3bd87 --- /dev/null +++ b/src/test/ui/typeck/issue-90164.stderr @@ -0,0 +1,22 @@ +error[E0277]: `T` cannot be unpinned + --> $DIR/issue-90164.rs:5:10 + | +LL | copy(r, w); + | ---- ^ the trait `Unpin` is not implemented for `T` + | | + | required by a bound introduced by this call + | + = note: consider using `Box::pin` +note: required by a bound in `copy` + --> $DIR/issue-90164.rs:1:12 + | +LL | fn copy(_: R, _: W) {} + | ^^^^^ required by this bound in `copy` +help: consider restricting type parameter `T` + | +LL | fn f(r: T) { + | ++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.