Auto merge of #60211 - Centril:rollup-akw4r85, r=Centril
Rollup of 6 pull requests Successful merges: - #59823 ([wg-async-await] Drop `async fn` arguments in async block ) - #59839 (Warn on unused results for operation methods on nums) - #60146 (Update fonts used by rustdoc) - #60169 (Warn when ignore-tidy-linelength is present, but no lines are too long) - #60177 (Promote rust comments to rustdoc) - #60191 (Add f16c target_feature) Failed merges: r? @ghost
This commit is contained in:
commit
e938c2b9aa
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
# ignore-tidy-linelength
|
||||
|
||||
set -ex
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# ignore-tidy-linelength
|
||||
|
||||
set -ex
|
||||
source shared.sh
|
||||
|
||||
|
@ -377,6 +377,8 @@ let m = ", $rot_result, ";
|
||||
assert_eq!(n.rotate_left(", $rot, "), m);
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn rotate_left(self, n: u32) -> Self {
|
||||
(self as $UnsignedT).rotate_left(n) as Self
|
||||
@ -401,6 +403,8 @@ let m = ", $rot_op, ";
|
||||
assert_eq!(n.rotate_right(", $rot, "), m);
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn rotate_right(self, n: u32) -> Self {
|
||||
(self as $UnsignedT).rotate_right(n) as Self
|
||||
@ -598,6 +602,8 @@ assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_add(self, rhs: Self) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_add(rhs);
|
||||
@ -620,6 +626,8 @@ assert_eq!((", stringify!($SelfT), "::min_value() + 2).checked_sub(3), None);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_sub(rhs);
|
||||
@ -642,6 +650,8 @@ assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_mul(self, rhs: Self) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_mul(rhs);
|
||||
@ -665,6 +675,8 @@ assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_div(self, rhs: Self) -> Option<Self> {
|
||||
if rhs == 0 || (self == Self::min_value() && rhs == -1) {
|
||||
@ -691,6 +703,8 @@ assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euclid(-1), None);
|
||||
assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None);
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
|
||||
if rhs == 0 || (self == Self::min_value() && rhs == -1) {
|
||||
@ -718,6 +732,8 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_rem(self, rhs: Self) -> Option<Self> {
|
||||
if rhs == 0 || (self == Self::min_value() && rhs == -1) {
|
||||
@ -745,6 +761,8 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);
|
||||
assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None);
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
|
||||
if rhs == 0 || (self == Self::min_value() && rhs == -1) {
|
||||
@ -791,6 +809,8 @@ assert_eq!(0x1", stringify!($SelfT), ".checked_shl(129), None);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_shl(self, rhs: u32) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_shl(rhs);
|
||||
@ -812,6 +832,8 @@ assert_eq!(0x10", stringify!($SelfT), ".checked_shr(128), None);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_shr(self, rhs: u32) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_shr(rhs);
|
||||
@ -860,6 +882,8 @@ $EndFeature, "
|
||||
```"),
|
||||
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
|
||||
let mut base = self;
|
||||
@ -901,6 +925,8 @@ $EndFeature, "
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_saturating_int_methods")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn saturating_add(self, rhs: Self) -> Self {
|
||||
intrinsics::saturating_add(self, rhs)
|
||||
@ -924,6 +950,8 @@ $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_saturating_int_methods")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn saturating_sub(self, rhs: Self) -> Self {
|
||||
intrinsics::saturating_sub(self, rhs)
|
||||
@ -947,6 +975,8 @@ assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($Self
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn saturating_mul(self, rhs: Self) -> Self {
|
||||
self.checked_mul(rhs).unwrap_or_else(|| {
|
||||
@ -976,6 +1006,8 @@ assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn saturating_pow(self, exp: u32) -> Self {
|
||||
match self.checked_pow(exp) {
|
||||
@ -1001,6 +1033,8 @@ assert_eq!(", stringify!($SelfT), "::max_value().wrapping_add(2), ", stringify!(
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_add(self, rhs: Self) -> Self {
|
||||
intrinsics::overflowing_add(self, rhs)
|
||||
@ -1022,6 +1056,8 @@ stringify!($SelfT), "::max_value());",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_sub(self, rhs: Self) -> Self {
|
||||
intrinsics::overflowing_sub(self, rhs)
|
||||
@ -1042,6 +1078,8 @@ assert_eq!(11i8.wrapping_mul(12), -124);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_mul(self, rhs: Self) -> Self {
|
||||
intrinsics::overflowing_mul(self, rhs)
|
||||
@ -1070,6 +1108,8 @@ assert_eq!((-128i8).wrapping_div(-1), -128);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "num_wrapping", since = "1.2.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn wrapping_div(self, rhs: Self) -> Self {
|
||||
self.overflowing_div(rhs).0
|
||||
@ -1098,6 +1138,8 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);
|
||||
assert_eq!((-128i8).wrapping_div_euclid(-1), -128);
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn wrapping_div_euclid(self, rhs: Self) -> Self {
|
||||
self.overflowing_div_euclid(rhs).0
|
||||
@ -1126,6 +1168,8 @@ assert_eq!((-128i8).wrapping_rem(-1), 0);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "num_wrapping", since = "1.2.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn wrapping_rem(self, rhs: Self) -> Self {
|
||||
self.overflowing_rem(rhs).0
|
||||
@ -1153,6 +1197,8 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);
|
||||
assert_eq!((-128i8).wrapping_rem_euclid(-1), 0);
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn wrapping_rem_euclid(self, rhs: Self) -> Self {
|
||||
self.overflowing_rem_euclid(rhs).0
|
||||
@ -1203,6 +1249,8 @@ assert_eq!((-1", stringify!($SelfT), ").wrapping_shl(128), -1);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "num_wrapping", since = "1.2.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_shl(self, rhs: u32) -> Self {
|
||||
unsafe {
|
||||
@ -1230,6 +1278,8 @@ assert_eq!((-128i16).wrapping_shr(64), -128);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "num_wrapping", since = "1.2.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_shr(self, rhs: u32) -> Self {
|
||||
unsafe {
|
||||
@ -1284,6 +1334,8 @@ assert_eq!(3i8.wrapping_pow(6), -39);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn wrapping_pow(self, mut exp: u32) -> Self {
|
||||
let mut base = self;
|
||||
@ -1326,6 +1378,8 @@ assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($Sel
|
||||
"::MIN, true));", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
|
||||
let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
|
||||
@ -1351,6 +1405,8 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($Sel
|
||||
"::MAX, true));", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
|
||||
let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT);
|
||||
@ -1374,6 +1430,8 @@ assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
|
||||
let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT);
|
||||
@ -1405,6 +1463,8 @@ $EndFeature, "
|
||||
```"),
|
||||
#[inline]
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub fn overflowing_div(self, rhs: Self) -> (Self, bool) {
|
||||
if self == Self::min_value() && rhs == -1 {
|
||||
(self, true)
|
||||
@ -1438,6 +1498,8 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi
|
||||
```"),
|
||||
#[inline]
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
|
||||
if self == Self::min_value() && rhs == -1 {
|
||||
(self, true)
|
||||
@ -1470,6 +1532,8 @@ $EndFeature, "
|
||||
```"),
|
||||
#[inline]
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
|
||||
if self == Self::min_value() && rhs == -1 {
|
||||
(0, true)
|
||||
@ -1502,6 +1566,8 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));
|
||||
assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true));
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
|
||||
if self == Self::min_value() && rhs == -1 {
|
||||
@ -1555,6 +1621,8 @@ assert_eq!(0x1i32.overflowing_shl(36), (0x10, true));",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
|
||||
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
|
||||
@ -1578,6 +1646,8 @@ assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
|
||||
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
|
||||
@ -1630,6 +1700,8 @@ assert_eq!(3i8.overflowing_pow(5), (-13, true));",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
|
||||
let mut base = self;
|
||||
@ -1677,6 +1749,8 @@ assert_eq!(x.pow(5), 32);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
pub fn pow(self, mut exp: u32) -> Self {
|
||||
@ -1732,6 +1806,8 @@ assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2
|
||||
assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
pub fn div_euclid(self, rhs: Self) -> Self {
|
||||
@ -1770,6 +1846,8 @@ assert_eq!(a.rem_euclid(-b), 3);
|
||||
assert_eq!((-a).rem_euclid(-b), 1);
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
pub fn rem_euclid(self, rhs: Self) -> Self {
|
||||
@ -2277,6 +2355,8 @@ let m = ", $rot_result, ";
|
||||
assert_eq!(n.rotate_left(", $rot, "), m);
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn rotate_left(self, n: u32) -> Self {
|
||||
intrinsics::rotate_left(self, n as $SelfT)
|
||||
@ -2301,6 +2381,8 @@ let m = ", $rot_op, ";
|
||||
assert_eq!(n.rotate_right(", $rot, "), m);
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn rotate_right(self, n: u32) -> Self {
|
||||
intrinsics::rotate_right(self, n as $SelfT)
|
||||
@ -2496,6 +2578,8 @@ Basic usage:
|
||||
assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_add(self, rhs: Self) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_add(rhs);
|
||||
@ -2516,6 +2600,8 @@ Basic usage:
|
||||
assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_sub(self, rhs: Self) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_sub(rhs);
|
||||
@ -2536,6 +2622,8 @@ Basic usage:
|
||||
assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_mul(self, rhs: Self) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_mul(rhs);
|
||||
@ -2556,6 +2644,8 @@ Basic usage:
|
||||
assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_div(self, rhs: Self) -> Option<Self> {
|
||||
match rhs {
|
||||
@ -2579,6 +2669,8 @@ assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64));
|
||||
assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None);
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
|
||||
if rhs == 0 {
|
||||
@ -2603,6 +2695,8 @@ Basic usage:
|
||||
assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_rem(self, rhs: Self) -> Option<Self> {
|
||||
if rhs == 0 {
|
||||
@ -2627,6 +2721,8 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1));
|
||||
assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None);
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
|
||||
if rhs == 0 {
|
||||
@ -2672,6 +2768,8 @@ Basic usage:
|
||||
assert_eq!(0x10", stringify!($SelfT), ".checked_shl(129), None);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_shl(self, rhs: u32) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_shl(rhs);
|
||||
@ -2692,6 +2790,8 @@ Basic usage:
|
||||
assert_eq!(0x10", stringify!($SelfT), ".checked_shr(129), None);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_shr(self, rhs: u32) -> Option<Self> {
|
||||
let (a, b) = self.overflowing_shr(rhs);
|
||||
@ -2712,6 +2812,8 @@ Basic usage:
|
||||
assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn checked_pow(self, mut exp: u32) -> Option<Self> {
|
||||
let mut base = self;
|
||||
@ -2750,6 +2852,8 @@ assert_eq!(200u8.saturating_add(127), 255);", $EndFeature, "
|
||||
```"),
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[rustc_const_unstable(feature = "const_saturating_int_methods")]
|
||||
#[inline]
|
||||
pub const fn saturating_add(self, rhs: Self) -> Self {
|
||||
@ -2770,6 +2874,8 @@ Basic usage:
|
||||
assert_eq!(13", stringify!($SelfT), ".saturating_sub(127), 0);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[rustc_const_unstable(feature = "const_saturating_int_methods")]
|
||||
#[inline]
|
||||
pub const fn saturating_sub(self, rhs: Self) -> Self {
|
||||
@ -2793,6 +2899,8 @@ assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($Se
|
||||
"::MAX);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn saturating_mul(self, rhs: Self) -> Self {
|
||||
self.checked_mul(rhs).unwrap_or(Self::max_value())
|
||||
@ -2815,6 +2923,8 @@ assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn saturating_pow(self, exp: u32) -> Self {
|
||||
match self.checked_pow(exp) {
|
||||
@ -2838,6 +2948,8 @@ assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::ma
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_add(self, rhs: Self) -> Self {
|
||||
intrinsics::overflowing_add(self, rhs)
|
||||
@ -2858,6 +2970,8 @@ assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::ma
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_sub(self, rhs: Self) -> Self {
|
||||
intrinsics::overflowing_sub(self, rhs)
|
||||
@ -2879,6 +2993,8 @@ $EndFeature, "
|
||||
/// assert_eq!(25u8.wrapping_mul(12), 44);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_mul(self, rhs: Self) -> Self {
|
||||
intrinsics::overflowing_mul(self, rhs)
|
||||
@ -2899,6 +3015,8 @@ Basic usage:
|
||||
", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_div(10), 10);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "num_wrapping", since = "1.2.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn wrapping_div(self, rhs: Self) -> Self {
|
||||
self / rhs
|
||||
@ -2924,6 +3042,8 @@ Basic usage:
|
||||
assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10);
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn wrapping_div_euclid(self, rhs: Self) -> Self {
|
||||
self / rhs
|
||||
@ -2946,6 +3066,8 @@ Basic usage:
|
||||
", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_rem(10), 0);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "num_wrapping", since = "1.2.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn wrapping_rem(self, rhs: Self) -> Self {
|
||||
self % rhs
|
||||
@ -2972,6 +3094,8 @@ Basic usage:
|
||||
assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0);
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn wrapping_rem_euclid(self, rhs: Self) -> Self {
|
||||
self % rhs
|
||||
@ -3026,6 +3150,8 @@ Basic usage:
|
||||
assert_eq!(1", stringify!($SelfT), ".wrapping_shl(128), 1);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "num_wrapping", since = "1.2.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_shl(self, rhs: u32) -> Self {
|
||||
unsafe {
|
||||
@ -3055,6 +3181,8 @@ Basic usage:
|
||||
assert_eq!(128", stringify!($SelfT), ".wrapping_shr(128), 128);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "num_wrapping", since = "1.2.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn wrapping_shr(self, rhs: u32) -> Self {
|
||||
unsafe {
|
||||
@ -3076,6 +3204,8 @@ Basic usage:
|
||||
assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn wrapping_pow(self, mut exp: u32) -> Self {
|
||||
let mut base = self;
|
||||
@ -3118,6 +3248,8 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));
|
||||
assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_add(self, rhs: Self) -> (Self, bool) {
|
||||
let (a, b) = intrinsics::add_with_overflow(self as $ActualT, rhs as $ActualT);
|
||||
@ -3144,6 +3276,8 @@ assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT),
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_sub(self, rhs: Self) -> (Self, bool) {
|
||||
let (a, b) = intrinsics::sub_with_overflow(self as $ActualT, rhs as $ActualT);
|
||||
@ -3169,6 +3303,8 @@ $EndFeature, "
|
||||
/// assert_eq!(1_000_000_000u32.overflowing_mul(10), (1410065408, true));
|
||||
/// ```
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
|
||||
let (a, b) = intrinsics::mul_with_overflow(self as $ActualT, rhs as $ActualT);
|
||||
@ -3196,6 +3332,8 @@ Basic usage
|
||||
```"),
|
||||
#[inline]
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub fn overflowing_div(self, rhs: Self) -> (Self, bool) {
|
||||
(self / rhs, false)
|
||||
}
|
||||
@ -3226,6 +3364,8 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false));
|
||||
```"),
|
||||
#[inline]
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
|
||||
(self / rhs, false)
|
||||
}
|
||||
@ -3252,6 +3392,8 @@ Basic usage
|
||||
```"),
|
||||
#[inline]
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
|
||||
(self % rhs, false)
|
||||
}
|
||||
@ -3282,6 +3424,8 @@ assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false));
|
||||
```"),
|
||||
#[inline]
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
|
||||
(self % rhs, false)
|
||||
}
|
||||
@ -3329,6 +3473,8 @@ Basic usage
|
||||
assert_eq!(0x1", stringify!($SelfT), ".overflowing_shl(132), (0x10, true));", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
|
||||
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
|
||||
@ -3353,6 +3499,8 @@ Basic usage
|
||||
assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "wrapping", since = "1.7.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
|
||||
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
|
||||
@ -3374,6 +3522,8 @@ Basic usage:
|
||||
assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "no_panic_pow", since = "1.34.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
|
||||
let mut base = self;
|
||||
@ -3418,6 +3568,8 @@ Basic usage:
|
||||
", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
pub fn pow(self, mut exp: u32) -> Self {
|
||||
@ -3459,6 +3611,8 @@ Basic usage:
|
||||
assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
pub fn div_euclid(self, rhs: Self) -> Self {
|
||||
@ -3483,6 +3637,8 @@ Basic usage:
|
||||
assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type
|
||||
```"),
|
||||
#[unstable(feature = "euclidean_division", issue = "49048")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
pub fn rem_euclid(self, rhs: Self) -> Self {
|
||||
|
@ -58,10 +58,10 @@ impl<'a> FnKind<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn header(&self) -> Option<FnHeader> {
|
||||
pub fn header(&self) -> Option<&FnHeader> {
|
||||
match *self {
|
||||
FnKind::ItemFn(_, _, header, _, _) => Some(header),
|
||||
FnKind::Method(_, sig, _, _) => Some(sig.header),
|
||||
FnKind::ItemFn(_, _, ref header, _, _) => Some(header),
|
||||
FnKind::Method(_, ref sig, _, _) => Some(&sig.header),
|
||||
FnKind::Closure(_) => None,
|
||||
}
|
||||
}
|
||||
@ -262,6 +262,9 @@ pub trait Visitor<'v> : Sized {
|
||||
fn visit_pat(&mut self, p: &'v Pat) {
|
||||
walk_pat(self, p)
|
||||
}
|
||||
fn visit_argument_source(&mut self, s: &'v ArgSource) {
|
||||
walk_argument_source(self, s)
|
||||
}
|
||||
fn visit_anon_const(&mut self, c: &'v AnonConst) {
|
||||
walk_anon_const(self, c)
|
||||
}
|
||||
@ -399,10 +402,17 @@ pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
|
||||
for argument in &body.arguments {
|
||||
visitor.visit_id(argument.hir_id);
|
||||
visitor.visit_pat(&argument.pat);
|
||||
visitor.visit_argument_source(&argument.source);
|
||||
}
|
||||
visitor.visit_expr(&body.value);
|
||||
}
|
||||
|
||||
pub fn walk_argument_source<'v, V: Visitor<'v>>(visitor: &mut V, source: &'v ArgSource) {
|
||||
if let ArgSource::AsyncFn(pat) = source {
|
||||
visitor.visit_pat(pat);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
|
||||
// Intentionally visiting the expr first - the initialization expr
|
||||
// dominates the local's definition.
|
||||
|
@ -448,10 +448,9 @@ impl<'a> LoweringContext<'a> {
|
||||
impl<'lcx, 'interner> Visitor<'lcx> for MiscCollector<'lcx, 'interner> {
|
||||
fn visit_pat(&mut self, p: &'lcx Pat) {
|
||||
match p.node {
|
||||
// Doesn't generate a Hir node
|
||||
// Doesn't generate a HIR node
|
||||
PatKind::Paren(..) => {},
|
||||
_ => {
|
||||
|
||||
if let Some(owner) = self.hir_id_owner {
|
||||
self.lctx.lower_node_id_with_owner(p.id, owner);
|
||||
}
|
||||
@ -461,6 +460,32 @@ impl<'a> LoweringContext<'a> {
|
||||
visit::walk_pat(self, p)
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: visit::FnKind<'lcx>, fd: &'lcx FnDecl, s: Span, _: NodeId) {
|
||||
if fk.header().map(|h| h.asyncness.node.is_async()).unwrap_or(false) {
|
||||
// Don't visit the original pattern for async functions as it will be
|
||||
// replaced.
|
||||
for arg in &fd.inputs {
|
||||
if let ArgSource::AsyncFn(pat) = &arg.source { self.visit_pat(pat); }
|
||||
self.visit_ty(&arg.ty)
|
||||
}
|
||||
self.visit_fn_ret_ty(&fd.output);
|
||||
|
||||
match fk {
|
||||
visit::FnKind::ItemFn(_, decl, _, body) => {
|
||||
self.visit_fn_header(decl);
|
||||
self.visit_block(body)
|
||||
},
|
||||
visit::FnKind::Method(_, sig, _, body) => {
|
||||
self.visit_fn_header(&sig.header);
|
||||
self.visit_block(body)
|
||||
},
|
||||
visit::FnKind::Closure(body) => self.visit_expr(body),
|
||||
}
|
||||
} else {
|
||||
visit::walk_fn(self, fk, fd, s)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, item: &'lcx Item) {
|
||||
let hir_id = self.lctx.allocate_hir_id_counter(item.id).hir_id;
|
||||
|
||||
@ -784,12 +809,10 @@ impl<'a> LoweringContext<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
fn record_body(&mut self, value: hir::Expr, decl: Option<&FnDecl>) -> hir::BodyId {
|
||||
fn record_body(&mut self, value: hir::Expr, arguments: HirVec<hir::Arg>) -> hir::BodyId {
|
||||
let body = hir::Body {
|
||||
arguments: decl.map_or(hir_vec![], |decl| {
|
||||
decl.inputs.iter().map(|x| self.lower_arg(x)).collect()
|
||||
}),
|
||||
is_generator: self.is_generator,
|
||||
arguments,
|
||||
value,
|
||||
};
|
||||
let id = body.id();
|
||||
@ -1112,11 +1135,10 @@ impl<'a> LoweringContext<'a> {
|
||||
capture_clause: CaptureBy,
|
||||
closure_node_id: NodeId,
|
||||
ret_ty: Option<&Ty>,
|
||||
span: Span,
|
||||
body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
|
||||
) -> hir::ExprKind {
|
||||
let prev_is_generator = mem::replace(&mut self.is_generator, true);
|
||||
let body_expr = body(self);
|
||||
let span = body_expr.span;
|
||||
let output = match ret_ty {
|
||||
Some(ty) => FunctionRetTy::Ty(P(ty.clone())),
|
||||
None => FunctionRetTy::Default(span),
|
||||
@ -1126,7 +1148,11 @@ impl<'a> LoweringContext<'a> {
|
||||
output,
|
||||
c_variadic: false
|
||||
};
|
||||
let body_id = self.record_body(body_expr, Some(&decl));
|
||||
// Lower the arguments before the body otherwise the body will call `lower_def` expecting
|
||||
// the argument to have been assigned an id already.
|
||||
let arguments = self.lower_args(Some(&decl));
|
||||
let body_expr = body(self);
|
||||
let body_id = self.record_body(body_expr, arguments);
|
||||
self.is_generator = prev_is_generator;
|
||||
|
||||
let capture_clause = self.lower_capture_clause(capture_clause);
|
||||
@ -1157,8 +1183,9 @@ impl<'a> LoweringContext<'a> {
|
||||
F: FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
|
||||
{
|
||||
let prev = mem::replace(&mut self.is_generator, false);
|
||||
let arguments = self.lower_args(decl);
|
||||
let result = f(self);
|
||||
let r = self.record_body(result, decl);
|
||||
let r = self.record_body(result, arguments);
|
||||
self.is_generator = prev;
|
||||
return r;
|
||||
}
|
||||
@ -2224,10 +2251,17 @@ impl<'a> LoweringContext<'a> {
|
||||
init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
|
||||
span: l.span,
|
||||
attrs: l.attrs.clone(),
|
||||
source: hir::LocalSource::Normal,
|
||||
source: self.lower_local_source(l.source),
|
||||
}, ids)
|
||||
}
|
||||
|
||||
fn lower_local_source(&mut self, ls: LocalSource) -> hir::LocalSource {
|
||||
match ls {
|
||||
LocalSource::Normal => hir::LocalSource::Normal,
|
||||
LocalSource::AsyncFn => hir::LocalSource::AsyncFn,
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
|
||||
match m {
|
||||
Mutability::Mutable => hir::MutMutable,
|
||||
@ -2235,11 +2269,23 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_args(&mut self, decl: Option<&FnDecl>) -> HirVec<hir::Arg> {
|
||||
decl.map_or(hir_vec![], |decl| decl.inputs.iter().map(|x| self.lower_arg(x)).collect())
|
||||
}
|
||||
|
||||
fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
|
||||
let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(arg.id);
|
||||
hir::Arg {
|
||||
hir_id,
|
||||
pat: self.lower_pat(&arg.pat),
|
||||
source: self.lower_arg_source(&arg.source),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_arg_source(&mut self, source: &ArgSource) -> hir::ArgSource {
|
||||
match source {
|
||||
ArgSource::Normal => hir::ArgSource::Normal,
|
||||
ArgSource::AsyncFn(pat) => hir::ArgSource::AsyncFn(self.lower_pat(pat)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -2993,15 +3039,21 @@ impl<'a> LoweringContext<'a> {
|
||||
fn lower_async_body(
|
||||
&mut self,
|
||||
decl: &FnDecl,
|
||||
asyncness: IsAsync,
|
||||
asyncness: &IsAsync,
|
||||
body: &Block,
|
||||
) -> hir::BodyId {
|
||||
self.lower_body(Some(decl), |this| {
|
||||
if let IsAsync::Async { closure_id, .. } = asyncness {
|
||||
self.lower_body(Some(&decl), |this| {
|
||||
if let IsAsync::Async { closure_id, ref arguments, .. } = asyncness {
|
||||
let mut body = body.clone();
|
||||
|
||||
for a in arguments.iter().rev() {
|
||||
body.stmts.insert(0, a.stmt.clone());
|
||||
}
|
||||
|
||||
let async_expr = this.make_async_expr(
|
||||
CaptureBy::Value, closure_id, None,
|
||||
CaptureBy::Value, *closure_id, None, body.span,
|
||||
|this| {
|
||||
let body = this.lower_block(body, false);
|
||||
let body = this.lower_block(&body, false);
|
||||
this.expr_block(body, ThinVec::new())
|
||||
});
|
||||
this.expr(body.span, async_expr, ThinVec::new())
|
||||
@ -3060,26 +3112,42 @@ impl<'a> LoweringContext<'a> {
|
||||
value
|
||||
)
|
||||
}
|
||||
ItemKind::Fn(ref decl, header, ref generics, ref body) => {
|
||||
ItemKind::Fn(ref decl, ref header, ref generics, ref body) => {
|
||||
let fn_def_id = self.resolver.definitions().local_def_id(id);
|
||||
self.with_new_scopes(|this| {
|
||||
// Note: we don't need to change the return type from `T` to
|
||||
// `impl Future<Output = T>` here because lower_body
|
||||
// only cares about the input argument patterns in the function
|
||||
// declaration (decl), not the return types.
|
||||
let body_id = this.lower_async_body(decl, header.asyncness.node, body);
|
||||
let mut lower_fn = |decl: &FnDecl| {
|
||||
// Note: we don't need to change the return type from `T` to
|
||||
// `impl Future<Output = T>` here because lower_body
|
||||
// only cares about the input argument patterns in the function
|
||||
// declaration (decl), not the return types.
|
||||
let body_id = this.lower_async_body(&decl, &header.asyncness.node, body);
|
||||
|
||||
let (generics, fn_decl) = this.add_in_band_defs(
|
||||
generics,
|
||||
fn_def_id,
|
||||
AnonymousLifetimeMode::PassThrough,
|
||||
|this, idty| this.lower_fn_decl(
|
||||
decl,
|
||||
Some((fn_def_id, idty)),
|
||||
true,
|
||||
header.asyncness.node.opt_return_id()
|
||||
),
|
||||
);
|
||||
let (generics, fn_decl) = this.add_in_band_defs(
|
||||
generics,
|
||||
fn_def_id,
|
||||
AnonymousLifetimeMode::PassThrough,
|
||||
|this, idty| this.lower_fn_decl(
|
||||
&decl,
|
||||
Some((fn_def_id, idty)),
|
||||
true,
|
||||
header.asyncness.node.opt_return_id()
|
||||
),
|
||||
);
|
||||
|
||||
(body_id, generics, fn_decl)
|
||||
};
|
||||
|
||||
let (body_id, generics, fn_decl) = if let IsAsync::Async {
|
||||
arguments, ..
|
||||
} = &header.asyncness.node {
|
||||
let mut decl = decl.clone();
|
||||
// Replace the arguments of this async function with the generated
|
||||
// arguments that will be moved into the closure.
|
||||
decl.inputs = arguments.clone().drain(..).map(|a| a.arg).collect();
|
||||
lower_fn(&decl)
|
||||
} else {
|
||||
lower_fn(decl)
|
||||
};
|
||||
|
||||
hir::ItemKind::Fn(
|
||||
fn_decl,
|
||||
@ -3558,15 +3626,33 @@ impl<'a> LoweringContext<'a> {
|
||||
)
|
||||
}
|
||||
ImplItemKind::Method(ref sig, ref body) => {
|
||||
let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness.node, body);
|
||||
let impl_trait_return_allow = !self.is_in_trait_impl;
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
&i.generics,
|
||||
sig,
|
||||
impl_item_def_id,
|
||||
impl_trait_return_allow,
|
||||
sig.header.asyncness.node.opt_return_id(),
|
||||
);
|
||||
let mut lower_method = |sig: &MethodSig| {
|
||||
let body_id = self.lower_async_body(
|
||||
&sig.decl, &sig.header.asyncness.node, body
|
||||
);
|
||||
let impl_trait_return_allow = !self.is_in_trait_impl;
|
||||
let (generics, sig) = self.lower_method_sig(
|
||||
&i.generics,
|
||||
sig,
|
||||
impl_item_def_id,
|
||||
impl_trait_return_allow,
|
||||
sig.header.asyncness.node.opt_return_id(),
|
||||
);
|
||||
(body_id, generics, sig)
|
||||
};
|
||||
|
||||
let (body_id, generics, sig) = if let IsAsync::Async {
|
||||
ref arguments, ..
|
||||
} = sig.header.asyncness.node {
|
||||
let mut sig = sig.clone();
|
||||
// Replace the arguments of this async function with the generated
|
||||
// arguments that will be moved into the closure.
|
||||
sig.decl.inputs = arguments.clone().drain(..).map(|a| a.arg).collect();
|
||||
lower_method(&sig)
|
||||
} else {
|
||||
lower_method(sig)
|
||||
};
|
||||
|
||||
(generics, hir::ImplItemKind::Method(sig, body_id))
|
||||
}
|
||||
ImplItemKind::Type(ref ty) => (
|
||||
@ -3760,7 +3846,7 @@ impl<'a> LoweringContext<'a> {
|
||||
impl_trait_return_allow: bool,
|
||||
is_async: Option<NodeId>,
|
||||
) -> (hir::Generics, hir::MethodSig) {
|
||||
let header = self.lower_fn_header(sig.header);
|
||||
let header = self.lower_fn_header(&sig.header);
|
||||
let (generics, decl) = self.add_in_band_defs(
|
||||
generics,
|
||||
fn_def_id,
|
||||
@ -3782,10 +3868,10 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
|
||||
fn lower_fn_header(&mut self, h: &FnHeader) -> hir::FnHeader {
|
||||
hir::FnHeader {
|
||||
unsafety: self.lower_unsafety(h.unsafety),
|
||||
asyncness: self.lower_asyncness(h.asyncness.node),
|
||||
asyncness: self.lower_asyncness(&h.asyncness.node),
|
||||
constness: self.lower_constness(h.constness),
|
||||
abi: h.abi,
|
||||
}
|
||||
@ -3805,7 +3891,7 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {
|
||||
fn lower_asyncness(&mut self, a: &IsAsync) -> hir::IsAsync {
|
||||
match a {
|
||||
IsAsync::Async { .. } => hir::IsAsync::Async,
|
||||
IsAsync::NotAsync => hir::IsAsync::NotAsync,
|
||||
@ -4110,7 +4196,7 @@ impl<'a> LoweringContext<'a> {
|
||||
hir::MatchSource::Normal,
|
||||
),
|
||||
ExprKind::Async(capture_clause, closure_node_id, ref block) => {
|
||||
self.make_async_expr(capture_clause, closure_node_id, None, |this| {
|
||||
self.make_async_expr(capture_clause, closure_node_id, None, block.span, |this| {
|
||||
this.with_new_scopes(|this| {
|
||||
let block = this.lower_block(block, false);
|
||||
this.expr_block(block, ThinVec::new())
|
||||
@ -4118,7 +4204,7 @@ impl<'a> LoweringContext<'a> {
|
||||
})
|
||||
}
|
||||
ExprKind::Closure(
|
||||
capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
|
||||
capture_clause, ref asyncness, movability, ref decl, ref body, fn_decl_span
|
||||
) => {
|
||||
if let IsAsync::Async { closure_id, .. } = asyncness {
|
||||
let outer_decl = FnDecl {
|
||||
@ -4156,7 +4242,7 @@ impl<'a> LoweringContext<'a> {
|
||||
Some(&**ty)
|
||||
} else { None };
|
||||
let async_body = this.make_async_expr(
|
||||
capture_clause, closure_id, async_ret_ty,
|
||||
capture_clause, *closure_id, async_ret_ty, body.span,
|
||||
|this| {
|
||||
this.with_new_scopes(|this| this.lower_expr(body))
|
||||
});
|
||||
|
@ -68,16 +68,17 @@ impl<'a> DefCollector<'a> {
|
||||
id: NodeId,
|
||||
name: Name,
|
||||
span: Span,
|
||||
header: &FnHeader,
|
||||
header: &'a FnHeader,
|
||||
generics: &'a Generics,
|
||||
decl: &'a FnDecl,
|
||||
body: &'a Block,
|
||||
) {
|
||||
let (closure_id, return_impl_trait_id) = match header.asyncness.node {
|
||||
let (closure_id, return_impl_trait_id, arguments) = match &header.asyncness.node {
|
||||
IsAsync::Async {
|
||||
closure_id,
|
||||
return_impl_trait_id,
|
||||
} => (closure_id, return_impl_trait_id),
|
||||
arguments,
|
||||
} => (closure_id, return_impl_trait_id, arguments),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@ -86,17 +87,31 @@ impl<'a> DefCollector<'a> {
|
||||
let fn_def_data = DefPathData::ValueNs(name.as_interned_str());
|
||||
let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span);
|
||||
return self.with_parent(fn_def, |this| {
|
||||
this.create_def(return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span);
|
||||
this.create_def(*return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span);
|
||||
|
||||
visit::walk_generics(this, generics);
|
||||
visit::walk_fn_decl(this, decl);
|
||||
|
||||
let closure_def = this.create_def(closure_id,
|
||||
DefPathData::ClosureExpr,
|
||||
REGULAR_SPACE,
|
||||
span);
|
||||
// Walk the generated arguments for the `async fn`.
|
||||
for a in arguments {
|
||||
use visit::Visitor;
|
||||
this.visit_ty(&a.arg.ty);
|
||||
}
|
||||
|
||||
// We do not invoke `walk_fn_decl` as this will walk the arguments that are being
|
||||
// replaced.
|
||||
visit::walk_fn_ret_ty(this, &decl.output);
|
||||
|
||||
let closure_def = this.create_def(
|
||||
*closure_id, DefPathData::ClosureExpr, REGULAR_SPACE, span,
|
||||
);
|
||||
this.with_parent(closure_def, |this| {
|
||||
visit::walk_block(this, body);
|
||||
for a in arguments {
|
||||
use visit::Visitor;
|
||||
// Walk each of the generated statements before the regular block body.
|
||||
this.visit_stmt(&a.stmt);
|
||||
}
|
||||
|
||||
visit::walk_block(this, &body);
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -290,7 +305,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
|
||||
match expr.node {
|
||||
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
|
||||
ExprKind::Closure(_, asyncness, ..) => {
|
||||
ExprKind::Closure(_, ref asyncness, ..) => {
|
||||
let closure_def = self.create_def(expr.id,
|
||||
DefPathData::ClosureExpr,
|
||||
REGULAR_SPACE,
|
||||
@ -300,7 +315,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
// Async closures desugar to closures inside of closures, so
|
||||
// we must create two defs.
|
||||
if let IsAsync::Async { closure_id, .. } = asyncness {
|
||||
let async_def = self.create_def(closure_id,
|
||||
let async_def = self.create_def(*closure_id,
|
||||
DefPathData::ClosureExpr,
|
||||
REGULAR_SPACE,
|
||||
expr.span);
|
||||
|
@ -1583,6 +1583,17 @@ pub enum LocalSource {
|
||||
Normal,
|
||||
/// A desugared `for _ in _ { .. }` loop.
|
||||
ForLoopDesugar,
|
||||
/// When lowering async functions, we create locals within the `async move` so that
|
||||
/// all arguments are dropped after the future is polled.
|
||||
///
|
||||
/// ```ignore (pseudo-Rust)
|
||||
/// async fn foo(<pattern> @ x: Type) {
|
||||
/// async move {
|
||||
/// let <pattern> = x;
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
AsyncFn,
|
||||
}
|
||||
|
||||
/// Hints at the original code for a `match _ { .. }`.
|
||||
@ -1883,6 +1894,26 @@ pub struct InlineAsm {
|
||||
pub struct Arg {
|
||||
pub pat: P<Pat>,
|
||||
pub hir_id: HirId,
|
||||
pub source: ArgSource,
|
||||
}
|
||||
|
||||
impl Arg {
|
||||
/// Returns the pattern representing the original binding for this argument.
|
||||
pub fn original_pat(&self) -> &P<Pat> {
|
||||
match &self.source {
|
||||
ArgSource::Normal => &self.pat,
|
||||
ArgSource::AsyncFn(pat) => &pat,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the source of an argument in a function header.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
|
||||
pub enum ArgSource {
|
||||
/// Argument as specified by the user.
|
||||
Normal,
|
||||
/// Generated argument from `async fn` lowering, contains the original binding pattern.
|
||||
AsyncFn(P<Pat>),
|
||||
}
|
||||
|
||||
/// Represents the header (not the body) of a function declaration.
|
||||
|
@ -86,19 +86,16 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
let sub_is_ret_type =
|
||||
self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
|
||||
|
||||
let span_label_var1 = if let Some(simple_ident) = anon_arg_sup.pat.simple_ident() {
|
||||
format!(" from `{}`", simple_ident)
|
||||
} else {
|
||||
String::new()
|
||||
let span_label_var1 = match anon_arg_sup.original_pat().simple_ident() {
|
||||
Some(simple_ident) => format!(" from `{}`", simple_ident),
|
||||
None => String::new(),
|
||||
};
|
||||
|
||||
let span_label_var2 = if let Some(simple_ident) = anon_arg_sub.pat.simple_ident() {
|
||||
format!(" into `{}`", simple_ident)
|
||||
} else {
|
||||
String::new()
|
||||
let span_label_var2 = match anon_arg_sub.original_pat().simple_ident() {
|
||||
Some(simple_ident) => format!(" into `{}`", simple_ident),
|
||||
None => String::new(),
|
||||
};
|
||||
|
||||
|
||||
let (span_1, span_2, main_label, span_label) = match (sup_is_ret_type, sub_is_ret_type) {
|
||||
(None, None) => {
|
||||
let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id {
|
||||
|
@ -95,13 +95,12 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let (error_var, span_label_var) = if let Some(simple_ident) = arg.pat.simple_ident() {
|
||||
(
|
||||
let (error_var, span_label_var) = match arg.original_pat().simple_ident() {
|
||||
Some(simple_ident) => (
|
||||
format!("the type of `{}`", simple_ident),
|
||||
format!("the type of `{}`", simple_ident),
|
||||
)
|
||||
} else {
|
||||
("parameter type".to_owned(), "type".to_owned())
|
||||
),
|
||||
None => ("parameter type".to_owned(), "type".to_owned()),
|
||||
};
|
||||
|
||||
let mut diag = struct_span_err!(
|
||||
|
@ -111,31 +111,31 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
/// and for error reporting logic to read arbitrary node types.
|
||||
pub in_progress_tables: Option<&'a RefCell<ty::TypeckTables<'tcx>>>,
|
||||
|
||||
// Cache for projections. This cache is snapshotted along with the
|
||||
// infcx.
|
||||
//
|
||||
// Public so that `traits::project` can use it.
|
||||
/// Cache for projections. This cache is snapshotted along with the
|
||||
/// infcx.
|
||||
///
|
||||
/// Public so that `traits::project` can use it.
|
||||
pub projection_cache: RefCell<traits::ProjectionCache<'tcx>>,
|
||||
|
||||
// We instantiate UnificationTable with bounds<Ty> because the
|
||||
// types that might instantiate a general type variable have an
|
||||
// order, represented by its upper and lower bounds.
|
||||
/// We instantiate `UnificationTable` with `bounds<Ty>` because the
|
||||
/// types that might instantiate a general type variable have an
|
||||
/// order, represented by its upper and lower bounds.
|
||||
pub type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
|
||||
|
||||
// Map from integral variable to the kind of integer it represents
|
||||
/// Map from integral variable to the kind of integer it represents
|
||||
int_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::IntVid>>>,
|
||||
|
||||
// Map from floating variable to the kind of float it represents
|
||||
/// Map from floating variable to the kind of float it represents
|
||||
float_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::FloatVid>>>,
|
||||
|
||||
// Tracks the set of region variables and the constraints between
|
||||
// them. This is initially `Some(_)` but when
|
||||
// `resolve_regions_and_report_errors` is invoked, this gets set
|
||||
// to `None` -- further attempts to perform unification etc may
|
||||
// fail if new region constraints would've been added.
|
||||
/// Tracks the set of region variables and the constraints between
|
||||
/// them. This is initially `Some(_)` but when
|
||||
/// `resolve_regions_and_report_errors` is invoked, this gets set
|
||||
/// to `None` -- further attempts to perform unification etc may
|
||||
/// fail if new region constraints would've been added.
|
||||
region_constraints: RefCell<Option<RegionConstraintCollector<'tcx>>>,
|
||||
|
||||
// Once region inference is done, the values for each variable.
|
||||
/// Once region inference is done, the values for each variable.
|
||||
lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,
|
||||
|
||||
/// Caches the results of trait selection. This cache is used
|
||||
@ -145,65 +145,65 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
/// Caches the results of trait evaluation.
|
||||
pub evaluation_cache: traits::EvaluationCache<'tcx>,
|
||||
|
||||
// the set of predicates on which errors have been reported, to
|
||||
// avoid reporting the same error twice.
|
||||
/// the set of predicates on which errors have been reported, to
|
||||
/// avoid reporting the same error twice.
|
||||
pub reported_trait_errors: RefCell<FxHashMap<Span, Vec<ty::Predicate<'tcx>>>>,
|
||||
|
||||
// When an error occurs, we want to avoid reporting "derived"
|
||||
// errors that are due to this original failure. Normally, we
|
||||
// handle this with the `err_count_on_creation` count, which
|
||||
// basically just tracks how many errors were reported when we
|
||||
// started type-checking a fn and checks to see if any new errors
|
||||
// have been reported since then. Not great, but it works.
|
||||
//
|
||||
// However, when errors originated in other passes -- notably
|
||||
// resolve -- this heuristic breaks down. Therefore, we have this
|
||||
// auxiliary flag that one can set whenever one creates a
|
||||
// type-error that is due to an error in a prior pass.
|
||||
//
|
||||
// Don't read this flag directly, call `is_tainted_by_errors()`
|
||||
// and `set_tainted_by_errors()`.
|
||||
/// When an error occurs, we want to avoid reporting "derived"
|
||||
/// errors that are due to this original failure. Normally, we
|
||||
/// handle this with the `err_count_on_creation` count, which
|
||||
/// basically just tracks how many errors were reported when we
|
||||
/// started type-checking a fn and checks to see if any new errors
|
||||
/// have been reported since then. Not great, but it works.
|
||||
///
|
||||
/// However, when errors originated in other passes -- notably
|
||||
/// resolve -- this heuristic breaks down. Therefore, we have this
|
||||
/// auxiliary flag that one can set whenever one creates a
|
||||
/// type-error that is due to an error in a prior pass.
|
||||
///
|
||||
/// Don't read this flag directly, call `is_tainted_by_errors()`
|
||||
/// and `set_tainted_by_errors()`.
|
||||
tainted_by_errors_flag: Cell<bool>,
|
||||
|
||||
// Track how many errors were reported when this infcx is created.
|
||||
// If the number of errors increases, that's also a sign (line
|
||||
// `tained_by_errors`) to avoid reporting certain kinds of errors.
|
||||
/// Track how many errors were reported when this infcx is created.
|
||||
/// If the number of errors increases, that's also a sign (line
|
||||
/// `tained_by_errors`) to avoid reporting certain kinds of errors.
|
||||
err_count_on_creation: usize,
|
||||
|
||||
// This flag is true while there is an active snapshot.
|
||||
/// This flag is true while there is an active snapshot.
|
||||
in_snapshot: Cell<bool>,
|
||||
|
||||
// A set of constraints that regionck must validate. Each
|
||||
// constraint has the form `T:'a`, meaning "some type `T` must
|
||||
// outlive the lifetime 'a". These constraints derive from
|
||||
// instantiated type parameters. So if you had a struct defined
|
||||
// like
|
||||
//
|
||||
// struct Foo<T:'static> { ... }
|
||||
//
|
||||
// then in some expression `let x = Foo { ... }` it will
|
||||
// instantiate the type parameter `T` with a fresh type `$0`. At
|
||||
// the same time, it will record a region obligation of
|
||||
// `$0:'static`. This will get checked later by regionck. (We
|
||||
// can't generally check these things right away because we have
|
||||
// to wait until types are resolved.)
|
||||
//
|
||||
// These are stored in a map keyed to the id of the innermost
|
||||
// enclosing fn body / static initializer expression. This is
|
||||
// because the location where the obligation was incurred can be
|
||||
// relevant with respect to which sublifetime assumptions are in
|
||||
// place. The reason that we store under the fn-id, and not
|
||||
// something more fine-grained, is so that it is easier for
|
||||
// regionck to be sure that it has found *all* the region
|
||||
// obligations (otherwise, it's easy to fail to walk to a
|
||||
// particular node-id).
|
||||
//
|
||||
// Before running `resolve_regions_and_report_errors`, the creator
|
||||
// of the inference context is expected to invoke
|
||||
// `process_region_obligations` (defined in `self::region_obligations`)
|
||||
// for each body-id in this map, which will process the
|
||||
// obligations within. This is expected to be done 'late enough'
|
||||
// that all type inference variables have been bound and so forth.
|
||||
/// A set of constraints that regionck must validate. Each
|
||||
/// constraint has the form `T:'a`, meaning "some type `T` must
|
||||
/// outlive the lifetime 'a". These constraints derive from
|
||||
/// instantiated type parameters. So if you had a struct defined
|
||||
/// like
|
||||
///
|
||||
/// struct Foo<T:'static> { ... }
|
||||
///
|
||||
/// then in some expression `let x = Foo { ... }` it will
|
||||
/// instantiate the type parameter `T` with a fresh type `$0`. At
|
||||
/// the same time, it will record a region obligation of
|
||||
/// `$0:'static`. This will get checked later by regionck. (We
|
||||
/// can't generally check these things right away because we have
|
||||
/// to wait until types are resolved.)
|
||||
///
|
||||
/// These are stored in a map keyed to the id of the innermost
|
||||
/// enclosing fn body / static initializer expression. This is
|
||||
/// because the location where the obligation was incurred can be
|
||||
/// relevant with respect to which sublifetime assumptions are in
|
||||
/// place. The reason that we store under the fn-id, and not
|
||||
/// something more fine-grained, is so that it is easier for
|
||||
/// regionck to be sure that it has found *all* the region
|
||||
/// obligations (otherwise, it's easy to fail to walk to a
|
||||
/// particular node-id).
|
||||
///
|
||||
/// Before running `resolve_regions_and_report_errors`, the creator
|
||||
/// of the inference context is expected to invoke
|
||||
/// `process_region_obligations` (defined in `self::region_obligations`)
|
||||
/// for each body-id in this map, which will process the
|
||||
/// obligations within. This is expected to be done 'late enough'
|
||||
/// that all type inference variables have been bound and so forth.
|
||||
pub region_obligations: RefCell<Vec<(hir::HirId, RegionObligation<'tcx>)>>,
|
||||
|
||||
/// What is the innermost universe we have created? Starts out as
|
||||
@ -247,85 +247,85 @@ pub struct TypeTrace<'tcx> {
|
||||
/// See `error_reporting` module for more details
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum SubregionOrigin<'tcx> {
|
||||
// Arose from a subtyping relation
|
||||
/// Arose from a subtyping relation
|
||||
Subtype(TypeTrace<'tcx>),
|
||||
|
||||
// Stack-allocated closures cannot outlive innermost loop
|
||||
// or function so as to ensure we only require finite stack
|
||||
/// Stack-allocated closures cannot outlive innermost loop
|
||||
/// or function so as to ensure we only require finite stack
|
||||
InfStackClosure(Span),
|
||||
|
||||
// Invocation of closure must be within its lifetime
|
||||
/// Invocation of closure must be within its lifetime
|
||||
InvokeClosure(Span),
|
||||
|
||||
// Dereference of reference must be within its lifetime
|
||||
/// Dereference of reference must be within its lifetime
|
||||
DerefPointer(Span),
|
||||
|
||||
// Closure bound must not outlive captured free variables
|
||||
/// Closure bound must not outlive captured free variables
|
||||
FreeVariable(Span, ast::NodeId),
|
||||
|
||||
// Index into slice must be within its lifetime
|
||||
/// Index into slice must be within its lifetime
|
||||
IndexSlice(Span),
|
||||
|
||||
// When casting `&'a T` to an `&'b Trait` object,
|
||||
// relating `'a` to `'b`
|
||||
/// When casting `&'a T` to an `&'b Trait` object,
|
||||
/// relating `'a` to `'b`
|
||||
RelateObjectBound(Span),
|
||||
|
||||
// Some type parameter was instantiated with the given type,
|
||||
// and that type must outlive some region.
|
||||
/// Some type parameter was instantiated with the given type,
|
||||
/// and that type must outlive some region.
|
||||
RelateParamBound(Span, Ty<'tcx>),
|
||||
|
||||
// The given region parameter was instantiated with a region
|
||||
// that must outlive some other region.
|
||||
/// The given region parameter was instantiated with a region
|
||||
/// that must outlive some other region.
|
||||
RelateRegionParamBound(Span),
|
||||
|
||||
// A bound placed on type parameters that states that must outlive
|
||||
// the moment of their instantiation.
|
||||
/// A bound placed on type parameters that states that must outlive
|
||||
/// the moment of their instantiation.
|
||||
RelateDefaultParamBound(Span, Ty<'tcx>),
|
||||
|
||||
// Creating a pointer `b` to contents of another reference
|
||||
/// Creating a pointer `b` to contents of another reference
|
||||
Reborrow(Span),
|
||||
|
||||
// Creating a pointer `b` to contents of an upvar
|
||||
/// Creating a pointer `b` to contents of an upvar
|
||||
ReborrowUpvar(Span, ty::UpvarId),
|
||||
|
||||
// Data with type `Ty<'tcx>` was borrowed
|
||||
/// Data with type `Ty<'tcx>` was borrowed
|
||||
DataBorrowed(Ty<'tcx>, Span),
|
||||
|
||||
// (&'a &'b T) where a >= b
|
||||
/// (&'a &'b T) where a >= b
|
||||
ReferenceOutlivesReferent(Ty<'tcx>, Span),
|
||||
|
||||
// Type or region parameters must be in scope.
|
||||
/// Type or region parameters must be in scope.
|
||||
ParameterInScope(ParameterOrigin, Span),
|
||||
|
||||
// The type T of an expression E must outlive the lifetime for E.
|
||||
/// The type T of an expression E must outlive the lifetime for E.
|
||||
ExprTypeIsNotInScope(Ty<'tcx>, Span),
|
||||
|
||||
// A `ref b` whose region does not enclose the decl site
|
||||
/// A `ref b` whose region does not enclose the decl site
|
||||
BindingTypeIsNotValidAtDecl(Span),
|
||||
|
||||
// Regions appearing in a method receiver must outlive method call
|
||||
/// Regions appearing in a method receiver must outlive method call
|
||||
CallRcvr(Span),
|
||||
|
||||
// Regions appearing in a function argument must outlive func call
|
||||
/// Regions appearing in a function argument must outlive func call
|
||||
CallArg(Span),
|
||||
|
||||
// Region in return type of invoked fn must enclose call
|
||||
/// Region in return type of invoked fn must enclose call
|
||||
CallReturn(Span),
|
||||
|
||||
// Operands must be in scope
|
||||
/// Operands must be in scope
|
||||
Operand(Span),
|
||||
|
||||
// Region resulting from a `&` expr must enclose the `&` expr
|
||||
/// Region resulting from a `&` expr must enclose the `&` expr
|
||||
AddrOf(Span),
|
||||
|
||||
// An auto-borrow that does not enclose the expr where it occurs
|
||||
/// An auto-borrow that does not enclose the expr where it occurs
|
||||
AutoBorrow(Span),
|
||||
|
||||
// Region constraint arriving from destructor safety
|
||||
/// Region constraint arriving from destructor safety
|
||||
SafeDestructor(Span),
|
||||
|
||||
// Comparing the signature and requirements of an impl method against
|
||||
// the containing trait.
|
||||
/// Comparing the signature and requirements of an impl method against
|
||||
/// the containing trait.
|
||||
CompareImplMethodObligation {
|
||||
span: Span,
|
||||
item_name: ast::Name,
|
||||
@ -361,35 +361,35 @@ pub enum LateBoundRegionConversionTime {
|
||||
/// See `error_reporting` module for more details
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum RegionVariableOrigin {
|
||||
// Region variables created for ill-categorized reasons,
|
||||
// mostly indicates places in need of refactoring
|
||||
/// Region variables created for ill-categorized reasons,
|
||||
/// mostly indicates places in need of refactoring
|
||||
MiscVariable(Span),
|
||||
|
||||
// Regions created by a `&P` or `[...]` pattern
|
||||
/// Regions created by a `&P` or `[...]` pattern
|
||||
PatternRegion(Span),
|
||||
|
||||
// Regions created by `&` operator
|
||||
/// Regions created by `&` operator
|
||||
AddrOfRegion(Span),
|
||||
|
||||
// Regions created as part of an autoref of a method receiver
|
||||
/// Regions created as part of an autoref of a method receiver
|
||||
Autoref(Span),
|
||||
|
||||
// Regions created as part of an automatic coercion
|
||||
/// Regions created as part of an automatic coercion
|
||||
Coercion(Span),
|
||||
|
||||
// Region variables created as the values for early-bound regions
|
||||
/// Region variables created as the values for early-bound regions
|
||||
EarlyBoundRegion(Span, InternedString),
|
||||
|
||||
// Region variables created for bound regions
|
||||
// in a function or method that is called
|
||||
/// Region variables created for bound regions
|
||||
/// in a function or method that is called
|
||||
LateBoundRegion(Span, ty::BoundRegion, LateBoundRegionConversionTime),
|
||||
|
||||
UpvarRegion(ty::UpvarId, Span),
|
||||
|
||||
BoundRegionInCoherence(ast::Name),
|
||||
|
||||
// This origin is used for the inference variables that we create
|
||||
// during NLL region processing.
|
||||
/// This origin is used for the inference variables that we create
|
||||
/// during NLL region processing.
|
||||
NLL(NLLRegionVariableOrigin),
|
||||
}
|
||||
|
||||
@ -686,22 +686,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the "currently in a snapshot" flag, invoke the closure,
|
||||
// then restore the flag to its original value. This flag is a
|
||||
// debugging measure designed to detect cases where we start a
|
||||
// snapshot, create type variables, and register obligations
|
||||
// which may involve those type variables in the fulfillment cx,
|
||||
// potentially leaving "dangling type variables" behind.
|
||||
// In such cases, an assertion will fail when attempting to
|
||||
// register obligations, within a snapshot. Very useful, much
|
||||
// better than grovelling through megabytes of RUST_LOG output.
|
||||
//
|
||||
// HOWEVER, in some cases the flag is unhelpful. In particular, we
|
||||
// sometimes create a "mini-fulfilment-cx" in which we enroll
|
||||
// obligations. As long as this fulfillment cx is fully drained
|
||||
// before we return, this is not a problem, as there won't be any
|
||||
// escaping obligations in the main cx. In those cases, you can
|
||||
// use this function.
|
||||
/// Clear the "currently in a snapshot" flag, invoke the closure,
|
||||
/// then restore the flag to its original value. This flag is a
|
||||
/// debugging measure designed to detect cases where we start a
|
||||
/// snapshot, create type variables, and register obligations
|
||||
/// which may involve those type variables in the fulfillment cx,
|
||||
/// potentially leaving "dangling type variables" behind.
|
||||
/// In such cases, an assertion will fail when attempting to
|
||||
/// register obligations, within a snapshot. Very useful, much
|
||||
/// better than grovelling through megabytes of `RUST_LOG` output.
|
||||
///
|
||||
/// HOWEVER, in some cases the flag is unhelpful. In particular, we
|
||||
/// sometimes create a "mini-fulfilment-cx" in which we enroll
|
||||
/// obligations. As long as this fulfillment cx is fully drained
|
||||
/// before we return, this is not a problem, as there won't be any
|
||||
/// escaping obligations in the main cx. In those cases, you can
|
||||
/// use this function.
|
||||
pub fn save_and_restore_in_snapshot_flag<F, R>(&self, func: F) -> R
|
||||
where
|
||||
F: FnOnce(&Self) -> R,
|
||||
@ -828,7 +828,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
r
|
||||
}
|
||||
|
||||
// Execute `f` in a snapshot, and commit the bindings it creates
|
||||
/// Execute `f` in a snapshot, and commit the bindings it creates.
|
||||
pub fn in_snapshot<T, F>(&self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> T,
|
||||
@ -854,9 +854,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
/// Scan the constraints produced since `snapshot` began and returns:
|
||||
///
|
||||
/// - None -- if none of them involve "region outlives" constraints
|
||||
/// - Some(true) -- if there are `'a: 'b` constraints where `'a` or `'b` is a placehodler
|
||||
/// - Some(false) -- if there are `'a: 'b` constraints but none involve placeholders
|
||||
/// - `None` -- if none of them involve "region outlives" constraints
|
||||
/// - `Some(true)` -- if there are `'a: 'b` constraints where `'a` or `'b` is a placeholder
|
||||
/// - `Some(false)` -- if there are `'a: 'b` constraints but none involve placeholders
|
||||
pub fn region_constraints_added_in_snapshot(
|
||||
&self,
|
||||
snapshot: &CombinedSnapshot<'a, 'tcx>,
|
||||
@ -1292,19 +1292,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
self.type_variables.borrow_mut().root_var(var)
|
||||
}
|
||||
|
||||
/// Where possible, replaces type/int/float variables in
|
||||
/// `value` with their final value. Note that region variables
|
||||
/// are unaffected. If a type variable has not been unified, it
|
||||
/// is left as is. This is an idempotent operation that does
|
||||
/// not affect inference state in any way and so you can do it
|
||||
/// at will.
|
||||
pub fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
/*!
|
||||
* Where possible, replaces type/int/float variables in
|
||||
* `value` with their final value. Note that region variables
|
||||
* are unaffected. If a type variable has not been unified, it
|
||||
* is left as is. This is an idempotent operation that does
|
||||
* not affect inference state in any way and so you can do it
|
||||
* at will.
|
||||
*/
|
||||
|
||||
if !value.needs_infer() {
|
||||
return value.clone(); // avoid duplicated subst-folding
|
||||
}
|
||||
|
@ -1326,6 +1326,25 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
||||
|
||||
run_early_pass!(self, check_mac, mac);
|
||||
}
|
||||
|
||||
fn visit_fn_header(&mut self, header: &'a ast::FnHeader) {
|
||||
// Unlike in HIR lowering and name resolution, the `AsyncArgument` statements are not added
|
||||
// to the function body and the arguments do not replace those in the declaration. They are
|
||||
// still visited manually here so that buffered lints can be emitted.
|
||||
if let ast::IsAsync::Async { ref arguments, .. } = header.asyncness.node {
|
||||
for a in arguments {
|
||||
// Visit the argument..
|
||||
self.visit_pat(&a.arg.pat);
|
||||
if let ast::ArgSource::AsyncFn(pat) = &a.arg.source {
|
||||
self.visit_pat(pat);
|
||||
}
|
||||
self.visit_ty(&a.arg.ty);
|
||||
|
||||
// ..and the statement.
|
||||
self.visit_stmt(&a.stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LateLintPassObjects<'a> {
|
||||
|
@ -2421,7 +2421,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
|
||||
let help_name = if let Some(body) = parent {
|
||||
let arg = &self.tcx.hir().body(body).arguments[index];
|
||||
format!("`{}`", self.tcx.hir().hir_to_pretty_string(arg.pat.hir_id))
|
||||
format!("`{}`", self.tcx.hir().hir_to_pretty_string(arg.original_pat().hir_id))
|
||||
} else {
|
||||
format!("argument {}", index + 1)
|
||||
};
|
||||
|
@ -438,12 +438,12 @@ bitflags! {
|
||||
// FIXME: Rename this to the actual property since it's used for generators too
|
||||
const HAS_TY_CLOSURE = 1 << 9;
|
||||
|
||||
// `true` if there are "names" of types and regions and so forth
|
||||
// that are local to a particular fn
|
||||
/// `true` if there are "names" of types and regions and so forth
|
||||
/// that are local to a particular fn
|
||||
const HAS_FREE_LOCAL_NAMES = 1 << 10;
|
||||
|
||||
// Present if the type belongs in a local type context.
|
||||
// Only set for Infer other than Fresh.
|
||||
/// Present if the type belongs in a local type context.
|
||||
/// Only set for Infer other than Fresh.
|
||||
const KEEP_IN_LOCAL_TCX = 1 << 11;
|
||||
|
||||
// Is there a projection that does not involve a bound region?
|
||||
@ -462,9 +462,9 @@ bitflags! {
|
||||
TypeFlags::HAS_SELF.bits |
|
||||
TypeFlags::HAS_RE_EARLY_BOUND.bits;
|
||||
|
||||
// Flags representing the nominal content of a type,
|
||||
// computed by FlagsComputation. If you add a new nominal
|
||||
// flag, it should be added here too.
|
||||
/// Flags representing the nominal content of a type,
|
||||
/// computed by FlagsComputation. If you add a new nominal
|
||||
/// flag, it should be added here too.
|
||||
const NOMINAL_FLAGS = TypeFlags::HAS_PARAMS.bits |
|
||||
TypeFlags::HAS_SELF.bits |
|
||||
TypeFlags::HAS_TY_INFER.bits |
|
||||
|
@ -439,16 +439,16 @@ struct SubstFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
substs: &'a [Kind<'tcx>],
|
||||
|
||||
// The location for which the substitution is performed, if available.
|
||||
/// The location for which the substitution is performed, if available.
|
||||
span: Option<Span>,
|
||||
|
||||
// The root type that is being substituted, if available.
|
||||
/// The root type that is being substituted, if available.
|
||||
root_ty: Option<Ty<'tcx>>,
|
||||
|
||||
// Depth of type stack
|
||||
/// Depth of type stack
|
||||
ty_stack_depth: usize,
|
||||
|
||||
// Number of region binders we have passed through while doing the substitution
|
||||
/// Number of region binders we have passed through while doing the substitution
|
||||
binders_passed: u32,
|
||||
}
|
||||
|
||||
|
@ -145,6 +145,7 @@ const X86_WHITELIST: &[(&str, Option<&str>)] = &[
|
||||
("bmi1", None),
|
||||
("bmi2", None),
|
||||
("cmpxchg16b", Some("cmpxchg16b_target_feature")),
|
||||
("f16c", Some("f16c_target_feature")),
|
||||
("fma", None),
|
||||
("fxsr", None),
|
||||
("lzcnt", None),
|
||||
|
@ -76,6 +76,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
|
||||
self.check_irrefutable(&loc.pat, match loc.source {
|
||||
hir::LocalSource::Normal => "local binding",
|
||||
hir::LocalSource::ForLoopDesugar => "`for` loop binding",
|
||||
hir::LocalSource::AsyncFn => "async fn binding",
|
||||
});
|
||||
|
||||
// Check legality of move bindings and `@` patterns.
|
||||
|
@ -222,7 +222,7 @@ impl<'a> AstValidator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait_fn_not_async(&self, span: Span, asyncness: IsAsync) {
|
||||
fn check_trait_fn_not_async(&self, span: Span, asyncness: &IsAsync) {
|
||||
if asyncness.is_async() {
|
||||
struct_span_err!(self.session, span, E0706,
|
||||
"trait fns cannot be declared `async`").emit()
|
||||
@ -570,7 +570,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
self.invalid_visibility(&impl_item.vis, None);
|
||||
if let ImplItemKind::Method(ref sig, _) = impl_item.node {
|
||||
self.check_trait_fn_not_const(sig.header.constness);
|
||||
self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
|
||||
self.check_trait_fn_not_async(impl_item.span, &sig.header.asyncness.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -642,7 +642,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
self.no_questions_in_bounds(bounds, "supertraits", true);
|
||||
for trait_item in trait_items {
|
||||
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
|
||||
self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node);
|
||||
self.check_trait_fn_not_async(trait_item.span, &sig.header.asyncness.node);
|
||||
self.check_trait_fn_not_const(sig.header.constness);
|
||||
if block.is_none() {
|
||||
self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
|
||||
|
@ -948,6 +948,16 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
|
||||
|
||||
intravisit::walk_pat(self, pat);
|
||||
}
|
||||
|
||||
fn visit_argument_source(&mut self, s: &'tcx hir::ArgSource) {
|
||||
match s {
|
||||
// Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
|
||||
// a `NodeId` w/out a type, as it is only used for getting the name of the original
|
||||
// pattern for diagnostics where only an `hir::Arg` is present.
|
||||
hir::ArgSource::AsyncFn(..) => {},
|
||||
_ => intravisit::walk_argument_source(self, s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -1133,6 +1143,16 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
|
||||
intravisit::walk_pat(self, pattern);
|
||||
}
|
||||
|
||||
fn visit_argument_source(&mut self, s: &'tcx hir::ArgSource) {
|
||||
match s {
|
||||
// Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
|
||||
// a `NodeId` w/out a type, as it is only used for getting the name of the original
|
||||
// pattern for diagnostics where only an `hir::Arg` is present.
|
||||
hir::ArgSource::AsyncFn(..) => {},
|
||||
_ => intravisit::walk_argument_source(self, s),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_local(&mut self, local: &'tcx hir::Local) {
|
||||
if let Some(ref init) = local.init {
|
||||
if self.check_expr_pat_type(init.hir_id, init.span) {
|
||||
|
@ -817,13 +817,13 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
|
||||
debug!("(resolving function) entering function");
|
||||
let (rib_kind, asyncness) = match function_kind {
|
||||
FnKind::ItemFn(_, ref header, ..) =>
|
||||
(FnItemRibKind, header.asyncness.node),
|
||||
(FnItemRibKind, &header.asyncness.node),
|
||||
FnKind::Method(_, ref sig, _, _) =>
|
||||
(TraitOrImplItemRibKind, sig.header.asyncness.node),
|
||||
(TraitOrImplItemRibKind, &sig.header.asyncness.node),
|
||||
FnKind::Closure(_) =>
|
||||
// Async closures aren't resolved through `visit_fn`-- they're
|
||||
// processed separately
|
||||
(ClosureRibKind(node_id), IsAsync::NotAsync),
|
||||
(ClosureRibKind(node_id), &IsAsync::NotAsync),
|
||||
};
|
||||
|
||||
// Create a value rib for the function.
|
||||
@ -834,26 +834,42 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
|
||||
|
||||
// Add each argument to the rib.
|
||||
let mut bindings_list = FxHashMap::default();
|
||||
for argument in &declaration.inputs {
|
||||
let mut add_argument = |argument: &ast::Arg| {
|
||||
self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
|
||||
|
||||
self.visit_ty(&argument.ty);
|
||||
|
||||
debug!("(resolving function) recorded argument");
|
||||
};
|
||||
|
||||
// Walk the generated async arguments if this is an `async fn`, otherwise walk the
|
||||
// normal arguments.
|
||||
if let IsAsync::Async { ref arguments, .. } = asyncness {
|
||||
for a in arguments { add_argument(&a.arg); }
|
||||
} else {
|
||||
for a in &declaration.inputs { add_argument(a); }
|
||||
}
|
||||
|
||||
visit::walk_fn_ret_ty(self, &declaration.output);
|
||||
|
||||
// Resolve the function body, potentially inside the body of an async closure
|
||||
if let IsAsync::Async { closure_id, .. } = asyncness {
|
||||
let rib_kind = ClosureRibKind(closure_id);
|
||||
let rib_kind = ClosureRibKind(*closure_id);
|
||||
self.ribs[ValueNS].push(Rib::new(rib_kind));
|
||||
self.label_ribs.push(Rib::new(rib_kind));
|
||||
}
|
||||
|
||||
match function_kind {
|
||||
FnKind::ItemFn(.., body) |
|
||||
FnKind::Method(.., body) => {
|
||||
self.visit_block(body);
|
||||
FnKind::ItemFn(.., body) | FnKind::Method(.., body) => {
|
||||
if let IsAsync::Async { ref arguments, .. } = asyncness {
|
||||
let mut body = body.clone();
|
||||
// Insert the generated statements into the body before attempting to
|
||||
// resolve names.
|
||||
for a in arguments {
|
||||
body.stmts.insert(0, a.stmt.clone());
|
||||
}
|
||||
self.visit_block(&body);
|
||||
} else {
|
||||
self.visit_block(body);
|
||||
}
|
||||
}
|
||||
FnKind::Closure(body) => {
|
||||
self.visit_expr(body);
|
||||
|
@ -374,7 +374,7 @@ impl Sig for ast::Item {
|
||||
|
||||
Ok(extend_sig(ty, text, defs, vec![]))
|
||||
}
|
||||
ast::ItemKind::Fn(ref decl, header, ref generics, _) => {
|
||||
ast::ItemKind::Fn(ref decl, ref header, ref generics, _) => {
|
||||
let mut text = String::new();
|
||||
if header.constness.node == ast::Constness::Const {
|
||||
text.push_str("const ");
|
||||
|
@ -1005,6 +1005,16 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
|
||||
// Don't descend into the bodies of nested closures
|
||||
fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
|
||||
_: hir::BodyId, _: Span, _: hir::HirId) { }
|
||||
|
||||
fn visit_argument_source(&mut self, s: &'gcx hir::ArgSource) {
|
||||
match s {
|
||||
// Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
|
||||
// a `NodeId` w/out a type, as it is only used for getting the name of the original
|
||||
// pattern for diagnostics where only an `hir::Arg` is present.
|
||||
hir::ArgSource::AsyncFn(..) => {},
|
||||
_ => intravisit::walk_argument_source(self, s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// When `check_fn` is invoked on a generator (i.e., a body that
|
||||
|
@ -297,6 +297,16 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
let ty = self.resolve(&ty, &hir_ty.span);
|
||||
self.write_ty_to_tables(hir_ty.hir_id, ty);
|
||||
}
|
||||
|
||||
fn visit_argument_source(&mut self, s: &'gcx hir::ArgSource) {
|
||||
match s {
|
||||
// Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
|
||||
// a `NodeId` w/out a type, as it is only used for getting the name of the original
|
||||
// pattern for diagnostics where only an `hir::Arg` is present.
|
||||
hir::ArgSource::AsyncFn(..) => {},
|
||||
_ => intravisit::walk_argument_source(self, s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
|
||||
|
@ -2017,7 +2017,7 @@ impl<'a> Clean<Arguments> for (&'a [hir::Ty], hir::BodyId) {
|
||||
Arguments {
|
||||
values: self.0.iter().enumerate().map(|(i, ty)| {
|
||||
Argument {
|
||||
name: name_from_pat(&body.arguments[i].pat),
|
||||
name: name_from_pat(&body.arguments[i].original_pat()),
|
||||
type_: ty.clean(cx),
|
||||
}
|
||||
}).collect()
|
||||
|
@ -930,13 +930,13 @@ themePicker.onblur = handleThemeButtonsBlur;
|
||||
static_files::source_serif_pro::BOLD)?;
|
||||
write(cx.dst.join("SourceSerifPro-It.ttf.woff"),
|
||||
static_files::source_serif_pro::ITALIC)?;
|
||||
write(cx.dst.join("SourceSerifPro-LICENSE.txt"),
|
||||
write(cx.dst.join("SourceSerifPro-LICENSE.md"),
|
||||
static_files::source_serif_pro::LICENSE)?;
|
||||
write(cx.dst.join("SourceCodePro-Regular.woff"),
|
||||
static_files::source_code_pro::REGULAR)?;
|
||||
write(cx.dst.join("SourceCodePro-Semibold.woff"),
|
||||
static_files::source_code_pro::SEMIBOLD)?;
|
||||
write(cx.dst.join("SourceCodePro-LICENSE.txt"),
|
||||
write(cx.dst.join("SourceCodePro-LICENSE.md"),
|
||||
static_files::source_code_pro::LICENSE)?;
|
||||
write(cx.dst.join("LICENSE-MIT.txt"),
|
||||
static_files::LICENSE_MIT)?;
|
||||
|
@ -1,10 +1,5 @@
|
||||
Copyright (c) 2014, Mozilla Foundation https://mozilla.org/
|
||||
with Reserved Font Name Fira Sans.
|
||||
|
||||
Copyright (c) 2014, Mozilla Foundation https://mozilla.org/
|
||||
with Reserved Font Name Fira Mono.
|
||||
|
||||
Copyright (c) 2014, Telefonica S.A.
|
||||
Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A.
|
||||
with Reserved Font Name < Fira >,
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
@ -24,7 +19,7 @@ with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
|
Binary file not shown.
Binary file not shown.
@ -18,7 +18,7 @@ with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
Copyright 2014 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
|
||||
Copyright 2014-2018 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
|
Binary file not shown.
@ -91,7 +91,7 @@ pub mod source_serif_pro {
|
||||
pub static ITALIC: &'static [u8] = include_bytes!("static/SourceSerifPro-It.ttf.woff");
|
||||
|
||||
/// The file `SourceSerifPro-LICENSE.txt`, the license text for the Source Serif Pro font.
|
||||
pub static LICENSE: &'static [u8] = include_bytes!("static/SourceSerifPro-LICENSE.txt");
|
||||
pub static LICENSE: &'static [u8] = include_bytes!("static/SourceSerifPro-LICENSE.md");
|
||||
}
|
||||
|
||||
/// Files related to the Source Code Pro font.
|
||||
@ -103,7 +103,7 @@ pub mod source_code_pro {
|
||||
pub static SEMIBOLD: &'static [u8] = include_bytes!("static/SourceCodePro-Semibold.woff");
|
||||
|
||||
/// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font.
|
||||
pub static LICENSE: &'static [u8] = include_bytes!("static/SourceCodePro-LICENSE.txt");
|
||||
pub static LICENSE: &'static [u8] = include_bytes!("static/SourceCodePro-LICENSE.md");
|
||||
}
|
||||
|
||||
/// Files related to the sidebar in rustdoc sources.
|
||||
|
@ -888,6 +888,17 @@ pub struct Local {
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub attrs: ThinVec<Attribute>,
|
||||
/// Origin of this local variable.
|
||||
pub source: LocalSource,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum LocalSource {
|
||||
/// Local was parsed from source.
|
||||
Normal,
|
||||
/// Within `ast::IsAsync::Async`, a local is generated that will contain the moved arguments
|
||||
/// of an `async fn`.
|
||||
AsyncFn,
|
||||
}
|
||||
|
||||
/// An arm of a 'match'.
|
||||
@ -1725,6 +1736,16 @@ pub struct Arg {
|
||||
pub ty: P<Ty>,
|
||||
pub pat: P<Pat>,
|
||||
pub id: NodeId,
|
||||
pub source: ArgSource,
|
||||
}
|
||||
|
||||
/// The source of an argument in a function header.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum ArgSource {
|
||||
/// Argument as written by the user.
|
||||
Normal,
|
||||
/// Argument from `async fn` lowering, contains the original binding pattern.
|
||||
AsyncFn(P<Pat>),
|
||||
}
|
||||
|
||||
/// Alternative representation for `Arg`s describing `self` parameter of methods.
|
||||
@ -1784,6 +1805,7 @@ impl Arg {
|
||||
}),
|
||||
ty,
|
||||
id: DUMMY_NODE_ID,
|
||||
source: ArgSource::Normal,
|
||||
};
|
||||
match eself.node {
|
||||
SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty),
|
||||
@ -1838,18 +1860,35 @@ pub enum Unsafety {
|
||||
Normal,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct AsyncArgument {
|
||||
/// `__arg0`
|
||||
pub ident: Ident,
|
||||
/// `__arg0: <ty>` argument to replace existing function argument `<pat>: <ty>`.
|
||||
pub arg: Arg,
|
||||
/// `let <pat>: <ty> = __arg0;` statement to be inserted at the start of the block.
|
||||
pub stmt: Stmt,
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub enum IsAsync {
|
||||
Async {
|
||||
closure_id: NodeId,
|
||||
return_impl_trait_id: NodeId,
|
||||
/// This field stores the arguments and statements that are used in HIR lowering to
|
||||
/// ensure that `async fn` arguments are dropped at the correct time.
|
||||
///
|
||||
/// The argument and statements here are generated at parse time as they are required in
|
||||
/// both the hir lowering, def collection and name resolution and this stops them needing
|
||||
/// to be created in each place.
|
||||
arguments: Vec<AsyncArgument>,
|
||||
},
|
||||
NotAsync,
|
||||
}
|
||||
|
||||
impl IsAsync {
|
||||
pub fn is_async(self) -> bool {
|
||||
if let IsAsync::Async { .. } = self {
|
||||
pub fn is_async(&self) -> bool {
|
||||
if let IsAsync::Async { .. } = *self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@ -1857,12 +1896,12 @@ impl IsAsync {
|
||||
}
|
||||
|
||||
/// In ths case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
|
||||
pub fn opt_return_id(self) -> Option<NodeId> {
|
||||
pub fn opt_return_id(&self) -> Option<NodeId> {
|
||||
match self {
|
||||
IsAsync::Async {
|
||||
return_impl_trait_id,
|
||||
..
|
||||
} => Some(return_impl_trait_id),
|
||||
} => Some(*return_impl_trait_id),
|
||||
IsAsync::NotAsync => None,
|
||||
}
|
||||
}
|
||||
@ -2202,7 +2241,7 @@ impl Item {
|
||||
///
|
||||
/// All the information between the visibility and the name of the function is
|
||||
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
|
||||
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct FnHeader {
|
||||
pub unsafety: Unsafety,
|
||||
pub asyncness: Spanned<IsAsync>,
|
||||
|
@ -526,6 +526,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: sp,
|
||||
attrs: ThinVec::new(),
|
||||
source: ast::LocalSource::Normal,
|
||||
});
|
||||
ast::Stmt {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
@ -554,6 +555,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: sp,
|
||||
attrs: ThinVec::new(),
|
||||
source: ast::LocalSource::Normal,
|
||||
});
|
||||
ast::Stmt {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
@ -571,6 +573,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span,
|
||||
attrs: ThinVec::new(),
|
||||
source: ast::LocalSource::Normal,
|
||||
});
|
||||
ast::Stmt {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
@ -976,7 +979,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||
ast::Arg {
|
||||
ty,
|
||||
pat: arg_pat,
|
||||
id: ast::DUMMY_NODE_ID
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
source: ast::ArgSource::Normal,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,13 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> {
|
||||
fn remove(&mut self, id: ast::NodeId) -> AstFragment {
|
||||
self.expanded_fragments.remove(&id).unwrap()
|
||||
}
|
||||
|
||||
fn next_id(&mut self, id: &mut ast::NodeId) {
|
||||
if self.monotonic {
|
||||
assert_eq!(*id, ast::DUMMY_NODE_ID);
|
||||
*id = self.cx.resolver.next_node_id()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
|
||||
@ -183,9 +190,16 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
|
||||
noop_visit_block(block, self);
|
||||
|
||||
for stmt in block.stmts.iter_mut() {
|
||||
if self.monotonic {
|
||||
assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
|
||||
stmt.id = self.cx.resolver.next_node_id();
|
||||
self.next_id(&mut stmt.id);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_asyncness(&mut self, a: &mut ast::IsAsync) {
|
||||
noop_visit_asyncness(a, self);
|
||||
|
||||
if let ast::IsAsync::Async { ref mut arguments, .. } = a {
|
||||
for argument in arguments.iter_mut() {
|
||||
self.next_id(&mut argument.stmt.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -208,6 +208,10 @@ pub trait MutVisitor: Sized {
|
||||
noop_visit_local(l, self);
|
||||
}
|
||||
|
||||
fn visit_local_source(&mut self, l: &mut LocalSource) {
|
||||
noop_visit_local_source(l, self);
|
||||
}
|
||||
|
||||
fn visit_mac(&mut self, _mac: &mut Mac) {
|
||||
panic!("visit_mac disabled by default");
|
||||
// N.B., see note about macros above. If you really want a visitor that
|
||||
@ -231,6 +235,10 @@ pub trait MutVisitor: Sized {
|
||||
noop_visit_arg(a, self);
|
||||
}
|
||||
|
||||
fn visit_arg_source(&mut self, a: &mut ArgSource) {
|
||||
noop_visit_arg_source(a, self);
|
||||
}
|
||||
|
||||
fn visit_generics(&mut self, generics: &mut Generics) {
|
||||
noop_visit_generics(generics, self);
|
||||
}
|
||||
@ -511,13 +519,17 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(args: &mut Parenth
|
||||
}
|
||||
|
||||
pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
|
||||
let Local { id, pat, ty, init, span, attrs } = local.deref_mut();
|
||||
let Local { id, pat, ty, init, span, attrs, source } = local.deref_mut();
|
||||
vis.visit_id(id);
|
||||
vis.visit_pat(pat);
|
||||
visit_opt(ty, |ty| vis.visit_ty(ty));
|
||||
visit_opt(init, |init| vis.visit_expr(init));
|
||||
vis.visit_span(span);
|
||||
visit_thin_attrs(attrs, vis);
|
||||
vis.visit_local_source(source);
|
||||
}
|
||||
|
||||
pub fn noop_visit_local_source<T: MutVisitor>(_local_source: &mut LocalSource, _vis: &mut T) {
|
||||
}
|
||||
|
||||
pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
|
||||
@ -556,10 +568,18 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn noop_visit_arg<T: MutVisitor>(Arg { id, pat, ty }: &mut Arg, vis: &mut T) {
|
||||
pub fn noop_visit_arg<T: MutVisitor>(Arg { id, pat, ty, source }: &mut Arg, vis: &mut T) {
|
||||
vis.visit_id(id);
|
||||
vis.visit_pat(pat);
|
||||
vis.visit_ty(ty);
|
||||
vis.visit_arg_source(source);
|
||||
}
|
||||
|
||||
pub fn noop_visit_arg_source<T: MutVisitor>(source: &mut ArgSource, vis: &mut T) {
|
||||
match source {
|
||||
ArgSource::Normal => {},
|
||||
ArgSource::AsyncFn(pat) => vis.visit_pat(pat),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {
|
||||
@ -671,9 +691,17 @@ pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis:
|
||||
|
||||
pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut IsAsync, vis: &mut T) {
|
||||
match asyncness {
|
||||
IsAsync::Async { closure_id, return_impl_trait_id } => {
|
||||
IsAsync::Async { closure_id, return_impl_trait_id, ref mut arguments } => {
|
||||
vis.visit_id(closure_id);
|
||||
vis.visit_id(return_impl_trait_id);
|
||||
for AsyncArgument { ident, arg, stmt } in arguments.iter_mut() {
|
||||
vis.visit_ident(ident);
|
||||
vis.visit_arg(arg);
|
||||
visit_clobber(stmt, |stmt| {
|
||||
vis.flat_map_stmt(stmt)
|
||||
.expect_one("expected visitor to produce exactly one item")
|
||||
});
|
||||
}
|
||||
}
|
||||
IsAsync::NotAsync => {}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::ast::{AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy};
|
||||
use crate::ast::{AngleBracketedArgs, AsyncArgument, ParenthesizedArgs, AttrStyle, BareFnTy};
|
||||
use crate::ast::{GenericBound, TraitBoundModifier};
|
||||
use crate::ast::Unsafety;
|
||||
use crate::ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind};
|
||||
use crate::ast::{Mod, AnonConst, Arg, ArgSource, Arm, Guard, Attribute, BindingMode, TraitItemKind};
|
||||
use crate::ast::Block;
|
||||
use crate::ast::{BlockCheckMode, CaptureBy, Movability};
|
||||
use crate::ast::{Constness, Crate};
|
||||
@ -14,7 +14,7 @@ use crate::ast::{GenericParam, GenericParamKind};
|
||||
use crate::ast::GenericArg;
|
||||
use crate::ast::{Ident, ImplItem, IsAsync, IsAuto, Item, ItemKind};
|
||||
use crate::ast::{Label, Lifetime, Lit, LitKind};
|
||||
use crate::ast::Local;
|
||||
use crate::ast::{Local, LocalSource};
|
||||
use crate::ast::MacStmtStyle;
|
||||
use crate::ast::{Mac, Mac_, MacDelimiter};
|
||||
use crate::ast::{MutTy, Mutability};
|
||||
@ -550,7 +550,7 @@ fn dummy_arg(span: Span) -> Arg {
|
||||
span,
|
||||
id: ast::DUMMY_NODE_ID
|
||||
};
|
||||
Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID }
|
||||
Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -1517,6 +1517,7 @@ impl<'a> Parser<'a> {
|
||||
IsAsync::Async {
|
||||
closure_id: ast::DUMMY_NODE_ID,
|
||||
return_impl_trait_id: ast::DUMMY_NODE_ID,
|
||||
arguments: Vec::new(),
|
||||
}
|
||||
} else {
|
||||
IsAsync::NotAsync
|
||||
@ -1575,7 +1576,7 @@ impl<'a> Parser<'a> {
|
||||
// trait item macro.
|
||||
(keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac), ast::Generics::default())
|
||||
} else {
|
||||
let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
|
||||
let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?;
|
||||
|
||||
let ident = self.parse_ident()?;
|
||||
let mut generics = self.parse_generics()?;
|
||||
@ -1589,6 +1590,7 @@ impl<'a> Parser<'a> {
|
||||
p.parse_arg_general(p.span.rust_2018(), true, false)
|
||||
})?;
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
self.construct_async_arguments(&mut asyncness, &d);
|
||||
|
||||
let sig = ast::MethodSig {
|
||||
header: FnHeader {
|
||||
@ -2124,7 +2126,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID })
|
||||
Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal })
|
||||
}
|
||||
|
||||
/// Parses a single function argument.
|
||||
@ -2147,7 +2149,8 @@ impl<'a> Parser<'a> {
|
||||
Ok(Arg {
|
||||
ty: t,
|
||||
pat,
|
||||
id: ast::DUMMY_NODE_ID
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
source: ast::ArgSource::Normal,
|
||||
})
|
||||
}
|
||||
|
||||
@ -5029,6 +5032,7 @@ impl<'a> Parser<'a> {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: lo.to(hi),
|
||||
attrs,
|
||||
source: LocalSource::Normal,
|
||||
}))
|
||||
}
|
||||
|
||||
@ -6566,7 +6570,7 @@ impl<'a> Parser<'a> {
|
||||
/// Parses an item-position function declaration.
|
||||
fn parse_item_fn(&mut self,
|
||||
unsafety: Unsafety,
|
||||
asyncness: Spanned<IsAsync>,
|
||||
mut asyncness: Spanned<IsAsync>,
|
||||
constness: Spanned<Constness>,
|
||||
abi: Abi)
|
||||
-> PResult<'a, ItemInfo> {
|
||||
@ -6575,6 +6579,7 @@ impl<'a> Parser<'a> {
|
||||
let decl = self.parse_fn_decl(allow_c_variadic)?;
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
self.construct_async_arguments(&mut asyncness, &decl);
|
||||
let header = FnHeader { unsafety, asyncness, constness, abi };
|
||||
Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs)))
|
||||
}
|
||||
@ -6755,11 +6760,12 @@ impl<'a> Parser<'a> {
|
||||
Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(),
|
||||
ast::ImplItemKind::Macro(mac)))
|
||||
} else {
|
||||
let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
|
||||
let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?;
|
||||
let ident = self.parse_ident()?;
|
||||
let mut generics = self.parse_generics()?;
|
||||
let decl = self.parse_fn_decl_with_self(|p| p.parse_arg())?;
|
||||
generics.where_clause = self.parse_where_clause()?;
|
||||
self.construct_async_arguments(&mut asyncness, &decl);
|
||||
*at_end = true;
|
||||
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
|
||||
let header = ast::FnHeader { abi, unsafety, constness, asyncness };
|
||||
@ -8181,6 +8187,7 @@ impl<'a> Parser<'a> {
|
||||
respan(async_span, IsAsync::Async {
|
||||
closure_id: ast::DUMMY_NODE_ID,
|
||||
return_impl_trait_id: ast::DUMMY_NODE_ID,
|
||||
arguments: Vec::new(),
|
||||
}),
|
||||
respan(fn_span, Constness::NotConst),
|
||||
Abi::Rust)?;
|
||||
@ -8826,6 +8833,68 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// When lowering a `async fn` to the HIR, we need to move all of the arguments of the function
|
||||
/// into the generated closure so that they are dropped when the future is polled and not when
|
||||
/// it is created.
|
||||
///
|
||||
/// The arguments of the function are replaced in HIR lowering with the arguments created by
|
||||
/// this function and the statements created here are inserted at the top of the closure body.
|
||||
fn construct_async_arguments(&mut self, asyncness: &mut Spanned<IsAsync>, decl: &FnDecl) {
|
||||
if let IsAsync::Async { ref mut arguments, .. } = asyncness.node {
|
||||
for (index, input) in decl.inputs.iter().enumerate() {
|
||||
let id = ast::DUMMY_NODE_ID;
|
||||
let span = input.pat.span;
|
||||
|
||||
// Construct a name for our temporary argument.
|
||||
let name = format!("__arg{}", index);
|
||||
let ident = Ident::from_str(&name);
|
||||
|
||||
// Construct an argument representing `__argN: <ty>` to replace the argument of the
|
||||
// async function.
|
||||
let arg = Arg {
|
||||
ty: input.ty.clone(),
|
||||
id,
|
||||
pat: P(Pat {
|
||||
id,
|
||||
node: PatKind::Ident(
|
||||
BindingMode::ByValue(Mutability::Immutable), ident, None,
|
||||
),
|
||||
span,
|
||||
}),
|
||||
source: ArgSource::AsyncFn(input.pat.clone()),
|
||||
};
|
||||
|
||||
// Construct a `let <pat> = __argN;` statement to insert at the top of the
|
||||
// async closure.
|
||||
let local = P(Local {
|
||||
pat: input.pat.clone(),
|
||||
// We explicitly do not specify the type for this statement. When the user's
|
||||
// argument type is `impl Trait` then this would require the
|
||||
// `impl_trait_in_bindings` feature to also be present for that same type to
|
||||
// be valid in this binding. At the time of writing (13 Mar 19),
|
||||
// `impl_trait_in_bindings` is not stable.
|
||||
ty: None,
|
||||
init: Some(P(Expr {
|
||||
id,
|
||||
node: ExprKind::Path(None, ast::Path {
|
||||
span,
|
||||
segments: vec![PathSegment { ident, id, args: None }],
|
||||
}),
|
||||
span,
|
||||
attrs: ThinVec::new(),
|
||||
})),
|
||||
id,
|
||||
span,
|
||||
attrs: ThinVec::new(),
|
||||
source: LocalSource::AsyncFn,
|
||||
});
|
||||
let stmt = Stmt { id, node: StmtKind::Local(local), span, };
|
||||
|
||||
arguments.push(AsyncArgument { ident, arg, stmt });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler: &errors::Handler) {
|
||||
|
@ -372,7 +372,7 @@ pub fn vis_to_string(v: &ast::Visibility) -> String {
|
||||
}
|
||||
|
||||
pub fn fun_to_string(decl: &ast::FnDecl,
|
||||
header: ast::FnHeader,
|
||||
header: &ast::FnHeader,
|
||||
name: ast::Ident,
|
||||
generics: &ast::Generics)
|
||||
-> String {
|
||||
@ -1133,7 +1133,7 @@ impl<'a> State<'a> {
|
||||
match item.node {
|
||||
ast::ForeignItemKind::Fn(ref decl, ref generics) => {
|
||||
self.head("")?;
|
||||
self.print_fn(decl, ast::FnHeader::default(),
|
||||
self.print_fn(decl, &ast::FnHeader::default(),
|
||||
Some(item.ident),
|
||||
generics, &item.vis)?;
|
||||
self.end()?; // end head-ibox
|
||||
@ -1263,7 +1263,7 @@ impl<'a> State<'a> {
|
||||
self.s.word(";")?;
|
||||
self.end()?; // end the outer cbox
|
||||
}
|
||||
ast::ItemKind::Fn(ref decl, header, ref param_names, ref body) => {
|
||||
ast::ItemKind::Fn(ref decl, ref header, ref param_names, ref body) => {
|
||||
self.head("")?;
|
||||
self.print_fn(
|
||||
decl,
|
||||
@ -1615,7 +1615,7 @@ impl<'a> State<'a> {
|
||||
vis: &ast::Visibility)
|
||||
-> io::Result<()> {
|
||||
self.print_fn(&m.decl,
|
||||
m.header,
|
||||
&m.header,
|
||||
Some(ident),
|
||||
&generics,
|
||||
vis)
|
||||
@ -2213,7 +2213,7 @@ impl<'a> State<'a> {
|
||||
self.bclose_(expr.span, INDENT_UNIT)?;
|
||||
}
|
||||
ast::ExprKind::Closure(
|
||||
capture_clause, asyncness, movability, ref decl, ref body, _) => {
|
||||
capture_clause, ref asyncness, movability, ref decl, ref body, _) => {
|
||||
self.print_movability(movability)?;
|
||||
self.print_asyncness(asyncness)?;
|
||||
self.print_capture_clause(capture_clause)?;
|
||||
@ -2798,7 +2798,7 @@ impl<'a> State<'a> {
|
||||
|
||||
pub fn print_fn(&mut self,
|
||||
decl: &ast::FnDecl,
|
||||
header: ast::FnHeader,
|
||||
header: &ast::FnHeader,
|
||||
name: Option<ast::Ident>,
|
||||
generics: &ast::Generics,
|
||||
vis: &ast::Visibility) -> io::Result<()> {
|
||||
@ -2853,8 +2853,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_asyncness(&mut self, asyncness: ast::IsAsync)
|
||||
-> io::Result<()> {
|
||||
pub fn print_asyncness(&mut self, asyncness: &ast::IsAsync) -> io::Result<()> {
|
||||
if asyncness.is_async() {
|
||||
self.word_nbsp("async")?;
|
||||
}
|
||||
@ -3126,7 +3125,7 @@ impl<'a> State<'a> {
|
||||
span: syntax_pos::DUMMY_SP,
|
||||
};
|
||||
self.print_fn(decl,
|
||||
ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() },
|
||||
&ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() },
|
||||
name,
|
||||
&generics,
|
||||
&source_map::dummy_spanned(ast::VisibilityKind::Inherited))?;
|
||||
@ -3189,7 +3188,7 @@ impl<'a> State<'a> {
|
||||
}
|
||||
|
||||
pub fn print_fn_header_info(&mut self,
|
||||
header: ast::FnHeader,
|
||||
header: &ast::FnHeader,
|
||||
vis: &ast::Visibility) -> io::Result<()> {
|
||||
self.s.word(visibility_qualified(vis, ""))?;
|
||||
|
||||
@ -3198,7 +3197,7 @@ impl<'a> State<'a> {
|
||||
ast::Constness::Const => self.word_nbsp("const")?
|
||||
}
|
||||
|
||||
self.print_asyncness(header.asyncness.node)?;
|
||||
self.print_asyncness(&header.asyncness.node)?;
|
||||
self.print_unsafety(header.unsafety)?;
|
||||
|
||||
if header.abi != Abi::Rust {
|
||||
@ -3247,7 +3246,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
fun_to_string(
|
||||
&decl,
|
||||
ast::FnHeader {
|
||||
&ast::FnHeader {
|
||||
unsafety: ast::Unsafety::Normal,
|
||||
constness: source_map::dummy_spanned(ast::Constness::NotConst),
|
||||
asyncness: source_map::dummy_spanned(ast::IsAsync::NotAsync),
|
||||
|
@ -544,6 +544,9 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionR
|
||||
pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) {
|
||||
for argument in &function_declaration.inputs {
|
||||
visitor.visit_pat(&argument.pat);
|
||||
if let ArgSource::AsyncFn(pat) = &argument.source {
|
||||
visitor.visit_pat(pat);
|
||||
}
|
||||
visitor.visit_ty(&argument.ty)
|
||||
}
|
||||
visitor.visit_fn_ret_ty(&function_declaration.output)
|
||||
|
@ -128,6 +128,7 @@ fn stmt_let_undescore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P<ast::Expr>) -> ast
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: sp,
|
||||
attrs: ThinVec::new(),
|
||||
source: ast::LocalSource::Normal,
|
||||
});
|
||||
ast::Stmt {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
|
@ -24,11 +24,11 @@ struct SyntaxContextData {
|
||||
outer_mark: Mark,
|
||||
transparency: Transparency,
|
||||
prev_ctxt: SyntaxContext,
|
||||
// This context, but with all transparent and semi-transparent marks filtered away.
|
||||
/// This context, but with all transparent and semi-transparent marks filtered away.
|
||||
opaque: SyntaxContext,
|
||||
// This context, but with all transparent marks filtered away.
|
||||
/// This context, but with all transparent marks filtered away.
|
||||
opaque_and_semitransparent: SyntaxContext,
|
||||
// Name of the crate to which `$crate` with this context would resolve.
|
||||
/// Name of the crate to which `$crate` with this context would resolve.
|
||||
dollar_crate_name: Symbol,
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
// ignoring this test until MIR codegen has taken over completely
|
||||
// ignore-test
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,5 +1,4 @@
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![feature(start)]
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=lazy
|
||||
|
||||
#![deny(dead_code)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=lazy
|
||||
|
||||
// N.B., we do not expect *any* monomorphization to be generated here.
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
// compile-flags:-Zinline-in-all-cgus
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags:-Zprint-mono-items=eager
|
||||
|
||||
#![crate_type="lib"]
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// We specify -Z incremental here because we want to test the partitioning for
|
||||
// incremental compilation
|
||||
// compile-flags:-Zprint-mono-items=lazy -Zincremental=tmp/partitioning-tests/statics
|
||||
|
@ -1,5 +1,4 @@
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
// before 7.0, then backported to the Rust LLVM fork. It tests that
|
||||
// optimized enum debug info accurately reflects the enum layout.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// ignore-windows
|
||||
// min-system-llvm-version 8.0
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
// before 7.0, then backported to the Rust LLVM fork. It tests that
|
||||
// debug info for tagged (ordinary) enums is properly emitted.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// ignore-windows
|
||||
// min-system-llvm-version 8.0
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// ignore-windows
|
||||
|
||||
// compile-flags: -g -C no-prepopulate-passes
|
||||
|
@ -1,7 +1,6 @@
|
||||
// This test depends on a patch that was committed to upstream LLVM
|
||||
// before 4.0, formerly backported to the Rust LLVM fork.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// ignore-windows
|
||||
// ignore-macos
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// ignore-windows
|
||||
// ignore-macos
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
// compile-flags: -g -C no-prepopulate-passes
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
// compile-flags: -g -C no-prepopulate-passes
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// This test is for *-windows-msvc only.
|
||||
// ignore-android
|
||||
// ignore-bitrig
|
||||
|
@ -1,5 +1,4 @@
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
// ignore-windows
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags: -g -C metadata=foo -C no-prepopulate-passes
|
||||
// aux-build:xcrate-generic.rs
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
// This test depends on a patch that was committed to upstream LLVM
|
||||
// after 5.0, then backported to the Rust LLVM fork.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// ignore-windows
|
||||
// ignore-macos
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
|
||||
// min-system-llvm-version: 8.0
|
||||
// min-gdb-version: 8.2
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// ignore-lldb: FIXME(#27089)
|
||||
// min-lldb-version: 310
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// ignore-lldb
|
||||
|
||||
// Require LLVM with DW_TAG_variant_part and a gdb that can read it.
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// Require LLVM with DW_TAG_variant_part and a gdb and lldb that can
|
||||
// read it.
|
||||
// min-system-llvm-version: 8.0
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
//[rpass1] compile-flags: -g
|
||||
//[rpass2] compile-flags: -g
|
||||
//[rpass3] compile-flags: -g --remap-path-prefix={{src-base}}=/the/src
|
||||
|
@ -5,8 +5,6 @@
|
||||
// so subtle breakage in them can leave a quite hard-to-find trail of
|
||||
// destruction.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
fn main() {
|
||||
let nodrop_x = false;
|
||||
let nodrop_y;
|
||||
|
@ -20,7 +20,7 @@ fn foo<T: Copy>(_t: T, q: &i32) -> i32 {
|
||||
// ...
|
||||
// bb0: {
|
||||
// ...
|
||||
// _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 29 }];
|
||||
// _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 31 }];
|
||||
// ...
|
||||
// _4 = &_3;
|
||||
// ...
|
||||
|
@ -16,7 +16,7 @@ fn foo<T: Copy>(_t: T, q: i32) -> i32 {
|
||||
// ...
|
||||
// bb0: {
|
||||
// ...
|
||||
// _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 13 }];
|
||||
// _3 = [closure@HirId { owner: DefIndex(0:4), local_id: 15 }];
|
||||
// ...
|
||||
// _4 = &_3;
|
||||
// ...
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
// compile-flags:-Zborrowck=mir -Zverbose
|
||||
// ^^^^^^^^^ force compiler to dump more region information
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![allow(warnings)]
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
fn main() {
|
||||
let a = 0;
|
||||
{
|
||||
|
@ -12,7 +12,7 @@ fn expect_free_supply_free<'x>(x: &'x u32) {
|
||||
x.push(22_u32);
|
||||
|
||||
// ...since we now know the type of `y` and can resolve the method call.
|
||||
y.wrapping_add(1);
|
||||
let _ = y.wrapping_add(1);
|
||||
});
|
||||
}
|
||||
|
||||
|
184
src/test/run-pass/issue-54716.rs
Normal file
184
src/test/run-pass/issue-54716.rs
Normal file
@ -0,0 +1,184 @@
|
||||
// aux-build:arc_wake.rs
|
||||
// edition:2018
|
||||
// run-pass
|
||||
|
||||
#![allow(unused_variables)]
|
||||
#![feature(async_await, await_macro, futures_api)]
|
||||
|
||||
extern crate arc_wake;
|
||||
|
||||
use arc_wake::ArcWake;
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
use std::rc::Rc;
|
||||
use std::task::Context;
|
||||
|
||||
struct EmptyWaker;
|
||||
|
||||
impl ArcWake for EmptyWaker {
|
||||
fn wake(self: Arc<Self>) {}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
enum DropOrder {
|
||||
Function,
|
||||
Val(&'static str),
|
||||
}
|
||||
|
||||
type DropOrderListPtr = Rc<RefCell<Vec<DropOrder>>>;
|
||||
|
||||
struct D(&'static str, DropOrderListPtr);
|
||||
|
||||
impl Drop for D {
|
||||
fn drop(&mut self) {
|
||||
self.1.borrow_mut().push(DropOrder::Val(self.0));
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that unused bindings are dropped after the function is polled.
|
||||
async fn foo(x: D, _y: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
/// Check that underscore patterns are dropped after the function is polled.
|
||||
async fn bar(x: D, _: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
/// Check that underscore patterns within more complex patterns are dropped after the function
|
||||
/// is polled.
|
||||
async fn baz((x, _): (D, D)) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
/// Check that underscore and unused bindings within and outwith more complex patterns are dropped
|
||||
/// after the function is polled.
|
||||
async fn foobar(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
/// Check that unused bindings are dropped after the method is polled.
|
||||
async fn foo(x: D, _y: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
/// Check that underscore patterns are dropped after the method is polled.
|
||||
async fn bar(x: D, _: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
/// Check that underscore patterns within more complex patterns are dropped after the method
|
||||
/// is polled.
|
||||
async fn baz((x, _): (D, D)) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
/// Check that underscore and unused bindings within and outwith more complex patterns are
|
||||
/// dropped after the method is polled.
|
||||
async fn foobar(x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
}
|
||||
|
||||
struct Bar<'a>(PhantomData<&'a ()>);
|
||||
|
||||
impl<'a> Bar<'a> {
|
||||
/// Check that unused bindings are dropped after the method with self is polled.
|
||||
async fn foo(&'a self, x: D, _y: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
/// Check that underscore patterns are dropped after the method with self is polled.
|
||||
async fn bar(&'a self, x: D, _: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
/// Check that underscore patterns within more complex patterns are dropped after the method
|
||||
/// with self is polled.
|
||||
async fn baz(&'a self, (x, _): (D, D)) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
|
||||
/// Check that underscore and unused bindings within and outwith more complex patterns are
|
||||
/// dropped after the method with self is polled.
|
||||
async fn foobar(&'a self, x: D, (a, _, _c): (D, D, D), _: D, _y: D) {
|
||||
x.1.borrow_mut().push(DropOrder::Function);
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_drop_order_after_poll<Fut: Future<Output = ()>>(
|
||||
f: impl FnOnce(DropOrderListPtr) -> Fut,
|
||||
expected_order: &[DropOrder],
|
||||
) {
|
||||
let empty = Arc::new(EmptyWaker);
|
||||
let waker = ArcWake::into_waker(empty);
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
|
||||
let actual_order = Rc::new(RefCell::new(Vec::new()));
|
||||
let mut fut = Box::pin(f(actual_order.clone()));
|
||||
let _ = fut.as_mut().poll(&mut cx);
|
||||
|
||||
assert_eq!(*actual_order.borrow(), expected_order);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use DropOrder::*;
|
||||
|
||||
// At time of writing (23/04/19), the `bar` and `foobar` tests do not output the same order as
|
||||
// the equivalent non-async functions. This is because the drop order of captured variables
|
||||
// doesn't match the drop order of arguments in a function.
|
||||
|
||||
// Free functions (see doc comment on function for what it tests).
|
||||
assert_drop_order_after_poll(|l| foo(D("x", l.clone()), D("_y", l.clone())),
|
||||
&[Function, Val("_y"), Val("x")]);
|
||||
assert_drop_order_after_poll(|l| bar(D("x", l.clone()), D("_", l.clone())),
|
||||
&[Function, Val("x"), Val("_")]);
|
||||
assert_drop_order_after_poll(|l| baz((D("x", l.clone()), D("_", l.clone()))),
|
||||
&[Function, Val("x"), Val("_")]);
|
||||
assert_drop_order_after_poll(|l| {
|
||||
foobar(
|
||||
D("x", l.clone()),
|
||||
(D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
|
||||
D("_", l.clone()),
|
||||
D("_y", l.clone()),
|
||||
)
|
||||
}, &[Function, Val("_y"), Val("_c"), Val("a"), Val("x"), Val("_"), Val("_")]);
|
||||
|
||||
// Methods w/out self (see doc comment on function for what it tests).
|
||||
assert_drop_order_after_poll(|l| Foo::foo(D("x", l.clone()), D("_y", l.clone())),
|
||||
&[Function, Val("_y"), Val("x")]);
|
||||
assert_drop_order_after_poll(|l| Foo::bar(D("x", l.clone()), D("_", l.clone())),
|
||||
&[Function, Val("x"), Val("_")]);
|
||||
assert_drop_order_after_poll(|l| Foo::baz((D("x", l.clone()), D("_", l.clone()))),
|
||||
&[Function, Val("x"), Val("_")]);
|
||||
assert_drop_order_after_poll(|l| {
|
||||
Foo::foobar(
|
||||
D("x", l.clone()),
|
||||
(D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
|
||||
D("_", l.clone()),
|
||||
D("_y", l.clone()),
|
||||
)
|
||||
}, &[Function, Val("_y"), Val("_c"), Val("a"), Val("x"), Val("_"), Val("_")]);
|
||||
|
||||
// Methods (see doc comment on function for what it tests).
|
||||
let b = Bar(Default::default());
|
||||
assert_drop_order_after_poll(|l| b.foo(D("x", l.clone()), D("_y", l.clone())),
|
||||
&[Function, Val("_y"), Val("x")]);
|
||||
assert_drop_order_after_poll(|l| b.bar(D("x", l.clone()), D("_", l.clone())),
|
||||
&[Function, Val("x"), Val("_")]);
|
||||
assert_drop_order_after_poll(|l| b.baz((D("x", l.clone()), D("_", l.clone()))),
|
||||
&[Function, Val("x"), Val("_")]);
|
||||
assert_drop_order_after_poll(|l| {
|
||||
b.foobar(
|
||||
D("x", l.clone()),
|
||||
(D("a", l.clone()), D("_", l.clone()), D("_c", l.clone())),
|
||||
D("_", l.clone()),
|
||||
D("_y", l.clone()),
|
||||
)
|
||||
}, &[Function, Val("_y"), Val("_c"), Val("a"), Val("x"), Val("_"), Val("_")]);
|
||||
}
|
@ -3,8 +3,8 @@
|
||||
|
||||
// this file has some special \r\n endings (use xxd to see them)
|
||||
|
||||
fn main() {assert_eq!(b"", b"\
|
||||
fn main() {assert_eq!(b"", b"\
|
||||
");
|
||||
assert_eq!(b"\n", b"
|
||||
assert_eq!(b"\n", b"
|
||||
");
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-end-whitespace
|
||||
|
||||
#![deny(intra_doc_link_resolution_failure)]
|
||||
|
||||
// An error in calculating spans while reporting intra-doc link resolution errors caused rustdoc to
|
||||
|
@ -1,11 +1,11 @@
|
||||
error: `[i]` cannot be resolved, ignoring it...
|
||||
--> $DIR/intra-link-span-ice-55723.rs:11:10
|
||||
--> $DIR/intra-link-span-ice-55723.rs:9:10
|
||||
|
|
||||
LL | /// (arr[i])
|
||||
| ^ cannot be resolved, ignoring
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/intra-link-span-ice-55723.rs:3:9
|
||||
--> $DIR/intra-link-span-ice-55723.rs:1:9
|
||||
|
|
||||
LL | #![deny(intra_doc_link_resolution_failure)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags: --document-private-items
|
||||
|
||||
// @has 'empty_mod_private/index.html' '//a[@href="foo/index.html"]' 'foo'
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// compile-flags:-Z unstable-options --extern-html-root-url core=https://example.com/core/0.1.0
|
||||
|
||||
// @has extern_html_root_url/index.html
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has foo/struct.Foo.html
|
||||
|
@ -1,4 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
// compile-flags: --document-private-items
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/two-phase-activation-sharing-interference.rs:32:15
|
||||
--> $DIR/two-phase-activation-sharing-interference.rs:30:15
|
||||
|
|
||||
LL | let y = &mut x;
|
||||
| ------ mutable borrow occurs here
|
||||
@ -10,7 +10,7 @@ LL | *y += 1;
|
||||
| ------- mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/two-phase-activation-sharing-interference.rs:40:13
|
||||
--> $DIR/two-phase-activation-sharing-interference.rs:38:13
|
||||
|
|
||||
LL | let y = &mut x;
|
||||
| ------ mutable borrow occurs here
|
||||
@ -21,7 +21,7 @@ LL | *y += 1;
|
||||
| ------- mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/two-phase-activation-sharing-interference.rs:51:13
|
||||
--> $DIR/two-phase-activation-sharing-interference.rs:49:13
|
||||
|
|
||||
LL | let y = &mut x;
|
||||
| ------ mutable borrow occurs here
|
||||
@ -32,7 +32,7 @@ LL | *y += 1;
|
||||
| ------- mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/two-phase-activation-sharing-interference.rs:62:14
|
||||
--> $DIR/two-phase-activation-sharing-interference.rs:60:14
|
||||
|
|
||||
LL | let y = &mut x;
|
||||
| ------ mutable borrow occurs here
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// revisions: nll_target
|
||||
|
||||
// The following revisions are disabled due to missing support from two-phase beyond autorefs
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
#![feature(const_indexing)]
|
||||
|
||||
const FOO: [usize; 3] = [1, 2, 3];
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/const-array-oob.rs:8:19
|
||||
--> $DIR/const-array-oob.rs:6:19
|
||||
|
|
||||
LL | const BLUB: [u32; FOO[4]] = [5, 6];
|
||||
| ^^^^^^ index out of bounds: the len is 3 but the index is 4
|
||||
|
@ -1,5 +1,3 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// run-pass
|
||||
|
||||
#![deny(deprecated_in_future)]
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user