version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.0.0",
"core 0.0.0",
"libc 0.0.0",
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "cc"
-version = "1.0.22"
+version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
version = "0.1.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "compiler_builtins"
version = "0.0.0"
dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"core 0.0.0",
]
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "curl-sys 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "curl-sys"
-version = "0.4.8"
+version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "libgit2-sys"
-version = "0.7.7"
+version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl-sys 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libssh2-sys 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libssh2-sys"
-version = "0.2.10"
+version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
[[package]]
name = "libz-sys"
-version = "1.0.20"
+version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
version = "110.0.7+1.1.0i"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
version = "0.9.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"openssl-src 110.0.7+1.1.0i (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
name = "profiler_builtins"
version = "0.0.0"
dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.0.0",
"core 0.0.0",
]
name = "rustc_codegen_llvm"
version = "0.0.0"
dependencies = [
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
version = "0.0.0"
dependencies = [
"build_helper 0.1.0",
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
"alloc_jemalloc 0.0.0",
"alloc_system 0.0.0",
"build_helper 0.1.0",
- "cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.0.0",
"core 0.0.0",
"libc 0.0.0",
"checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
"checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9"
"checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1"
-"checksum cc 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4a6007c146fdd28d4512a794b07ffe9d8e89e6bf86e2e0c4ddff2e1fb54a0007"
+"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3"
"checksum chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25ce2f28f55ed544a2a3756b7acf41dd7d6f27acffb2086439950925506af7d0"
"checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e"
"checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
"checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
"checksum curl 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "444c2f9e71458b34e75471ed8d756947a0bb920b8b8b9bfc56dfcc4fc6819a13"
-"checksum curl-sys 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "981bd902fcd8b8b999cf71b81447e27d66c3493a7f62f1372866fd32986c0c82"
+"checksum curl-sys 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2edeedbbd9c7cdccb14bfb5dfbcc108901f99d3411eb5bab3758789377c5bec4"
"checksum datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d724bf4ffe77cdceeecd461009b5f8d9e23c5d645d68bedb4586bf43e7e142"
"checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a"
"checksum derive_more 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46c7f14685a20f5dd08e7f754f2ea8cc064d8f4214ae21116c106a2768ba7b9b"
"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7"
"checksum lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d33a48d0365c96081958cc663eef834975cb1e8d8bea3378513fc72bdbf11e50"
"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
-"checksum libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6ab62b46003ba97701554631fa570d9f7e7947e2480ae3d941e555a54a2c0f05"
-"checksum libssh2-sys 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "10dbc0957a27626444f5a3f523e6b97a70c3d702999bf1c7161cfbe7a25a9368"
-"checksum libz-sys 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "f5f9aba969b3c45fe9c94bec65895868a9ceca9a600699f4054b75747a19c7c6"
+"checksum libgit2-sys 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "44b1900be992dd5698bd3bb422921e336306d413e2860e6ba3b50e62e6219c4c"
+"checksum libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "126a1f4078368b163bfdee65fbab072af08a1b374a5551b21e87ade27b1fbf9d"
+"checksum libz-sys 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "65ff614643d7635dfa2151913d95c4ee90ee1fe15d9e0980f4dcb1a7e5837c18"
"checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
"checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2"
-Subproject commit cff0930664b688f1dd22aefb3d16944eb4cdbfd5
+Subproject commit fa91738b66367b6f70b078251868a071f1991ace
//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5));
//! ```
-use fmt;
+use {fmt, u64};
use iter::Sum;
use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};
const NANOS_PER_MICRO: u32 = 1_000;
const MILLIS_PER_SEC: u64 = 1_000;
const MICROS_PER_SEC: u64 = 1_000_000;
+const MAX_NANOS_F64: f64 = ((u64::MAX as u128 + 1)*(NANOS_PER_SEC as u128)) as f64;
/// A `Duration` type to represent a span of time, typically used for system
/// timeouts.
None
}
}
+
+ /// Returns the number of seconds contained by this `Duration` as `f64`.
+ ///
+ /// The returned value does include the fractional (nanosecond) part of the duration.
+ ///
+ /// # Examples
+ /// ```
+ /// #![feature(duration_float)]
+ /// use std::time::Duration;
+ ///
+ /// let dur = Duration::new(2, 700_000_000);
+ /// assert_eq!(dur.as_float_secs(), 2.7);
+ /// ```
+ #[unstable(feature = "duration_float", issue = "54361")]
+ #[inline]
+ pub fn as_float_secs(&self) -> f64 {
+ (self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64)
+ }
+
+ /// Creates a new `Duration` from the specified number of seconds.
+ ///
+ /// # Panics
+ /// This constructor will panic if `secs` is not finite, negative or overflows `Duration`.
+ ///
+ /// # Examples
+ /// ```
+ /// #![feature(duration_float)]
+ /// use std::time::Duration;
+ ///
+ /// let dur = Duration::from_float_secs(2.7);
+ /// assert_eq!(dur, Duration::new(2, 700_000_000));
+ /// ```
+ #[unstable(feature = "duration_float", issue = "54361")]
+ #[inline]
+ pub fn from_float_secs(secs: f64) -> Duration {
+ let nanos = secs * (NANOS_PER_SEC as f64);
+ if !nanos.is_finite() {
+ panic!("got non-finite value when converting float to duration");
+ }
+ if nanos >= MAX_NANOS_F64 {
+ panic!("overflow when converting float to duration");
+ }
+ if nanos < 0.0 {
+ panic!("underflow when converting float to duration");
+ }
+ let nanos = nanos as u128;
+ Duration {
+ secs: (nanos / (NANOS_PER_SEC as u128)) as u64,
+ nanos: (nanos % (NANOS_PER_SEC as u128)) as u32,
+ }
+ }
+
+ /// Multiply `Duration` by `f64`.
+ ///
+ /// # Panics
+ /// This method will panic if result is not finite, negative or overflows `Duration`.
+ ///
+ /// # Examples
+ /// ```
+ /// #![feature(duration_float)]
+ /// use std::time::Duration;
+ ///
+ /// let dur = Duration::new(2, 700_000_000);
+ /// assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000));
+ /// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0));
+ /// ```
+ #[unstable(feature = "duration_float", issue = "54361")]
+ #[inline]
+ pub fn mul_f64(self, rhs: f64) -> Duration {
+ Duration::from_float_secs(rhs * self.as_float_secs())
+ }
+
+ /// Divide `Duration` by `f64`.
+ ///
+ /// # Panics
+ /// This method will panic if result is not finite, negative or overflows `Duration`.
+ ///
+ /// # Examples
+ /// ```
+ /// #![feature(duration_float)]
+ /// use std::time::Duration;
+ ///
+ /// let dur = Duration::new(2, 700_000_000);
+ /// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611));
+ /// // note that truncation is used, not rounding
+ /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_598));
+ /// ```
+ #[unstable(feature = "duration_float", issue = "54361")]
+ #[inline]
+ pub fn div_f64(self, rhs: f64) -> Duration {
+ Duration::from_float_secs(self.as_float_secs() / rhs)
+ }
+
+ /// Divide `Duration` by `Duration` and return `f64`.
+ ///
+ /// # Examples
+ /// ```
+ /// #![feature(duration_float)]
+ /// use std::time::Duration;
+ ///
+ /// let dur1 = Duration::new(2, 700_000_000);
+ /// let dur2 = Duration::new(5, 400_000_000);
+ /// assert_eq!(dur1.div_duration(dur2), 0.5);
+ /// ```
+ #[unstable(feature = "duration_float", issue = "54361")]
+ #[inline]
+ pub fn div_duration(self, rhs: Duration) -> f64 {
+ self.as_float_secs() / rhs.as_float_secs()
+ }
}
#[stable(feature = "duration", since = "1.3.0")]
}
}
+#[stable(feature = "symmetric_u32_duration_mul", since = "1.31.0")]
+impl Mul<Duration> for u32 {
+ type Output = Duration;
+
+ fn mul(self, rhs: Duration) -> Duration {
+ rhs * self
+ }
+}
+
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
impl MulAssign<u32> for Duration {
fn mul_assign(&mut self, rhs: u32) {
use infer::error_reporting::nice_region_error::NiceRegionError;
use ty;
use util::common::ErrorReported;
+use errors::Applicability;
impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
E0621,
"explicit lifetime required in {}",
error_var
- ).span_suggestion(
+ ).span_suggestion_with_applicability(
new_ty_span,
&format!("add explicit lifetime `{}` to {}", named, span_label_var),
- new_ty.to_string()
+ new_ty.to_string(),
+ Applicability::Unspecified,
)
- .span_label(span, format!("lifetime `{}` required", named))
- .emit();
+ .span_label(span, format!("lifetime `{}` required", named))
+ .emit();
return Some(ErrorReported);
}
use infer::lexical_region_resolve::RegionResolutionError;
use ty::{BoundRegion, FreeRegion, RegionKind};
use util::common::ErrorReported;
+use errors::Applicability;
impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
/// Print the error message for lifetime errors when the return type is a static impl Trait.
_ => "'_".to_owned(),
};
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(return_sp) {
- err.span_suggestion(
+ err.span_suggestion_with_applicability(
return_sp,
&format!(
"you can add a constraint to the return type to make it last \
lifetime,
),
format!("{} + {}", snippet, lifetime_name),
+ Applicability::Unspecified,
);
}
err.emit();
//! methods. It effectively does a reverse walk of the AST; whenever we
//! reach a loop node, we iterate until a fixed point is reached.
//!
-//! ## The `Users` struct
+//! ## The `users_*` fields
//!
//! At each live node `N`, we track three pieces of information for each
-//! variable `V` (these are encapsulated in the `Users` struct):
+//! variable `V` (these are in the `users_*` fields):
//!
//! - `reader`: the `LiveNode` ID of some node which will read the value
//! that `V` holds on entry to `N`. Formally: a node `M` such
// Actually we compute just a bit more than just liveness, but we use
// the same basic propagation framework in all cases.
-#[derive(Clone, Copy)]
-struct Users {
- reader: LiveNode,
- writer: LiveNode,
- used: bool
-}
-
-fn invalid_users() -> Users {
- Users {
- reader: invalid_node(),
- writer: invalid_node(),
- used: false
- }
-}
-
#[derive(Copy, Clone)]
struct Specials {
exit_ln: LiveNode,
tables: &'a ty::TypeckTables<'tcx>,
s: Specials,
successors: Vec<LiveNode>,
- users: Vec<Users>,
+
+ // We used to have a single `users: Vec<Users>` field here, where `Users`
+ // had `reader`, `writer` and `used` fields. But the number of users can
+ // get very large, and it's more compact to store the data in three
+ // separate `Vec`s so that no space is wasted for padding.
+ users_reader: Vec<LiveNode>,
+ users_writer: Vec<LiveNode>,
+ users_used: Vec<bool>,
// mappings from loop node ID to LiveNode
// ("break" label should map to loop node ID,
let num_live_nodes = ir.num_live_nodes;
let num_vars = ir.num_vars;
+ let num_users = num_live_nodes * num_vars;
Liveness {
ir,
tables,
s: specials,
successors: vec![invalid_node(); num_live_nodes],
- users: vec![invalid_users(); num_live_nodes * num_vars],
+ users_reader: vec![invalid_node(); num_users],
+ users_writer: vec![invalid_node(); num_users],
+ users_used: vec![false; num_users],
break_ln: NodeMap(),
cont_ln: NodeMap(),
}
fn live_on_entry(&self, ln: LiveNode, var: Variable)
-> Option<LiveNodeKind> {
assert!(ln.is_valid());
- let reader = self.users[self.idx(ln, var)].reader;
+ let reader = self.users_reader[self.idx(ln, var)];
if reader.is_valid() {Some(self.ir.lnk(reader))} else {None}
}
fn used_on_entry(&self, ln: LiveNode, var: Variable) -> bool {
assert!(ln.is_valid());
- self.users[self.idx(ln, var)].used
+ self.users_used[self.idx(ln, var)]
}
fn assigned_on_entry(&self, ln: LiveNode, var: Variable)
-> Option<LiveNodeKind> {
assert!(ln.is_valid());
- let writer = self.users[self.idx(ln, var)].writer;
+ let writer = self.users_writer[self.idx(ln, var)];
if writer.is_valid() {Some(self.ir.lnk(writer))} else {None}
}
{
let wr = &mut wr as &mut dyn Write;
write!(wr, "[ln({:?}) of kind {:?} reads", ln.get(), self.ir.lnk(ln));
- self.write_vars(wr, ln, |idx| self.users[idx].reader);
+ self.write_vars(wr, ln, |idx| self.users_reader[idx]);
write!(wr, " writes");
- self.write_vars(wr, ln, |idx| self.users[idx].writer);
+ self.write_vars(wr, ln, |idx| self.users_writer[idx]);
write!(wr, " precedes {:?}]", self.successors[ln.get()]);
}
String::from_utf8(wr).unwrap()
// only grow during iterations.
//
// self.indices(ln) { |idx|
- // self.users[idx] = invalid_users();
+ // self.users_reader[idx] = invalid_node();
+ // self.users_writer[idx] = invalid_node();
+ // self.users_used[idx] = false;
// }
}
self.successors[ln.get()] = succ_ln;
self.indices2(ln, succ_ln, |this, idx, succ_idx| {
- this.users[idx] = this.users[succ_idx]
+ this.users_reader[idx] = this.users_reader[succ_idx];
+ this.users_writer[idx] = this.users_writer[succ_idx];
+ this.users_used[idx] = this.users_used[succ_idx];
});
debug!("init_from_succ(ln={}, succ={})",
self.ln_str(ln), self.ln_str(succ_ln));
let mut changed = false;
self.indices2(ln, succ_ln, |this, idx, succ_idx| {
- changed |= copy_if_invalid(this.users[succ_idx].reader,
- &mut this.users[idx].reader);
- changed |= copy_if_invalid(this.users[succ_idx].writer,
- &mut this.users[idx].writer);
- if this.users[succ_idx].used && !this.users[idx].used {
- this.users[idx].used = true;
+ changed |= copy_if_invalid(this.users_reader[succ_idx], &mut this.users_reader[idx]);
+ changed |= copy_if_invalid(this.users_writer[succ_idx], &mut this.users_writer[idx]);
+ if this.users_used[succ_idx] && !this.users_used[idx] {
+ this.users_used[idx] = true;
changed = true;
}
});
// this) so we just clear out all the data.
fn define(&mut self, writer: LiveNode, var: Variable) {
let idx = self.idx(writer, var);
- self.users[idx].reader = invalid_node();
- self.users[idx].writer = invalid_node();
+ self.users_reader[idx] = invalid_node();
+ self.users_writer[idx] = invalid_node();
debug!("{:?} defines {:?} (idx={}): {}", writer, var,
idx, self.ln_str(writer));
ln, acc, var, self.ln_str(ln));
let idx = self.idx(ln, var);
- let user = &mut self.users[idx];
if (acc & ACC_WRITE) != 0 {
- user.reader = invalid_node();
- user.writer = ln;
+ self.users_reader[idx] = invalid_node();
+ self.users_writer[idx] = ln;
}
// Important: if we both read/write, must do read second
// or else the write will override.
if (acc & ACC_READ) != 0 {
- user.reader = ln;
+ self.users_reader[idx] = ln;
}
if (acc & ACC_USE) != 0 {
- user.used = true;
+ self.users_used[idx] = true;
}
}
use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock};
use syntax::ast::NodeId;
-use errors::{self, DiagnosticBuilder, DiagnosticId};
+use errors::{self, DiagnosticBuilder, DiagnosticId, Applicability};
use errors::emitter::{Emitter, EmitterWriter};
use syntax::edition::Edition;
use syntax::json::JsonEmitter;
diag_builder.span_note(span, message);
}
DiagnosticBuilderMethod::SpanSuggestion(suggestion) => {
- let span = span_maybe.expect("span_suggestion needs a span");
- diag_builder.span_suggestion(span, message, suggestion);
+ let span = span_maybe.expect("span_suggestion_* needs a span");
+ diag_builder.span_suggestion_with_applicability(
+ span,
+ message,
+ suggestion,
+ Applicability::Unspecified,
+ );
}
}
}
orig_params,
trait_pred.to_poly_trait_predicate(),
));
+
match result {
Ok(Some(Vtable::VtableImpl(_))) => {
debug!(
manual impl found, bailing out",
did, trait_did, generics
);
- return true;
+ true
}
- _ => return false,
- };
+ _ => false
+ }
});
// If an explicit impl exists, it always takes priority over an auto impl
if new_trait.def_id() == old_trait.def_id() {
let new_substs = new_trait.skip_binder().trait_ref.substs;
let old_substs = old_trait.skip_binder().trait_ref.substs;
+
if !new_substs.types().eq(old_substs.types()) {
// We can't compare lifetimes if the types are different,
// so skip checking old_pred
pub fn get_lifetime(&self, region: Region, names_map: &FxHashMap<String, String>) -> String {
self.region_name(region)
- .map(|name| {
- names_map.get(&name).unwrap_or_else(|| {
+ .map(|name|
+ names_map.get(&name).unwrap_or_else(||
panic!("Missing lifetime with name {:?} for {:?}", name, region)
- })
- })
- .unwrap_or(&"'static".to_string())
+ )
+ )
+ .unwrap_or(&"'static".to_owned())
.clone()
}
let trait_ref = ty.erase_regions(&trait_ref);
debug!("codegen_fulfill_obligation(trait_ref={:?}, def_id={:?})",
- (param_env, trait_ref), trait_ref.def_id());
+ (param_env, trait_ref), trait_ref.def_id());
// Do the initial selection for the obligation. This yields the
// shallow result we are looking for -- that is, what specific impl.
let obligation_cause = ObligationCause::dummy();
let obligation = Obligation::new(obligation_cause,
- param_env,
- trait_ref.to_poly_trait_predicate());
+ param_env,
+ trait_ref.to_poly_trait_predicate());
let selection = match selcx.select(&obligation) {
Ok(Some(selection)) => selection,
// overflow bug, since I believe this is the only case
// where ambiguity can result.
bug!("Encountered ambiguity selecting `{:?}` during codegen, \
- presuming due to overflow",
- trait_ref)
+ presuming due to overflow",
+ trait_ref)
}
Err(e) => {
- bug!("Encountered error `{:?}` selecting `{:?}` during codegen",
- e, trait_ref)
+ bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
}
};
// In principle, we only need to do this so long as `result`
// contains unbound type parameters. It could be a slight
// optimization to stop iterating early.
- match fulfill_cx.select_all_or_error(self) {
- Ok(()) => { }
- Err(errors) => {
- span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking",
- errors);
- }
+ if let Err(errors) = fulfill_cx.select_all_or_error(self) {
+ span_bug!(span, "Encountered errors `{:?}` resolving bounds after type-checking",
+ errors);
}
let result = self.resolve_type_vars_if_possible(result);
let result = self.tcx.erase_regions(&result);
- match self.tcx.lift_to_global(&result) {
- Some(result) => result,
- None => {
- span_bug!(span, "Uninferred types/regions in `{:?}`", result);
- }
- }
+ self.tcx.lift_to_global(&result).unwrap_or_else(||
+ span_bug!(span, "Uninferred types/regions in `{:?}`", result)
+ )
}
}
b_def_id: DefId)
-> Option<OverlapResult<'tcx>>
{
- debug!("overlap(a_def_id={:?}, b_def_id={:?})",
- a_def_id,
- b_def_id);
+ debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id);
// For the purposes of this check, we don't bring any skolemized
// types into scope; instead, we replace the generic types with
// Do `a` and `b` unify? If not, no overlap.
let obligations = match selcx.infcx().at(&ObligationCause::dummy(), param_env)
- .eq_impl_headers(&a_impl_header, &b_impl_header) {
- Ok(InferOk { obligations, value: () }) => {
- obligations
- }
+ .eq_impl_headers(&a_impl_header, &b_impl_header)
+ {
+ Ok(InferOk { obligations, value: () }) => obligations,
Err(_) => return None
};
return None
}
- let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header);
+ let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header);
let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes();
debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
Some(OverlapResult { impl_header, intercrate_ambiguity_causes })
ty::Foreign(did) => def_id_is_local(did, in_crate),
ty::Dynamic(ref tt, ..) => {
- tt.principal().map_or(false, |p| {
+ tt.principal().map_or(false, |p|
def_id_is_local(p.def_id(), in_crate)
- })
+ )
}
- ty::Error => {
- true
- }
+ ty::Error => true,
ty::Closure(..) |
ty::Generator(..) |
use infer::{self, InferCtxt};
use infer::type_variable::TypeVariableOrigin;
use std::fmt;
+use std::iter;
use syntax::ast;
use session::DiagnosticMessageId;
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
index: Option<usize>, // None if this is an old error
}
- let mut error_map : FxHashMap<_, Vec<_>> =
+ let mut error_map: FxHashMap<_, Vec<_>> =
self.reported_trait_errors.borrow().iter().map(|(&span, predicates)| {
(span, predicates.iter().map(|predicate| ErrorDescriptor {
predicate: predicate.clone(),
// We do this in 2 passes because we want to display errors in order, tho
// maybe it *is* better to sort errors by span or something.
- let mut is_suppressed: Vec<bool> = errors.iter().map(|_| false).collect();
+ let mut is_suppressed = vec![false; errors.len()];
for (_, error_set) in error_map.iter() {
// We want to suppress "duplicate" errors with the same span.
for error in error_set {
_ => {
// this is a "direct", user-specified, rather than derived,
// obligation.
- flags.push(("direct".to_string(), None));
+ flags.push(("direct".to_owned(), None));
}
}
// Currently I'm leaving it for what I need for `try`.
if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
let method = self.tcx.item_name(item);
- flags.push(("from_method".to_string(), None));
- flags.push(("from_method".to_string(), Some(method.to_string())));
+ flags.push(("from_method".to_owned(), None));
+ flags.push(("from_method".to_owned(), Some(method.to_string())));
}
}
if let Some(k) = obligation.cause.span.compiler_desugaring_kind() {
- flags.push(("from_desugaring".to_string(), None));
- flags.push(("from_desugaring".to_string(), Some(k.name().to_string())));
+ flags.push(("from_desugaring".to_owned(), None));
+ flags.push(("from_desugaring".to_owned(), Some(k.name().to_string())));
}
let generics = self.tcx.generics_of(def_id);
let self_ty = trait_ref.self_ty();
// This is also included through the generics list as `Self`,
// but the parser won't allow you to use it
- flags.push(("_Self".to_string(), Some(self_ty.to_string())));
+ flags.push(("_Self".to_owned(), Some(self_ty.to_string())));
if let Some(def) = self_ty.ty_adt_def() {
// We also want to be able to select self's original
// signature with no type arguments resolved
- flags.push(("_Self".to_string(), Some(self.tcx.type_of(def.did).to_string())));
+ flags.push(("_Self".to_owned(), Some(self.tcx.type_of(def.did).to_string())));
}
for param in generics.params.iter() {
}
if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
- flags.push(("crate_local".to_string(), None));
+ flags.push(("crate_local".to_owned(), None));
}
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(
let simp = fast_reject::simplify_type(self.tcx,
trait_ref.skip_binder().self_ty(),
true);
- let mut impl_candidates = Vec::new();
+ let all_impls = self.tcx.all_impls(trait_ref.def_id());
match simp {
- Some(simp) => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| {
+ Some(simp) => all_impls.iter().filter_map(|&def_id| {
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
let imp_simp = fast_reject::simplify_type(self.tcx,
imp.self_ty(),
true);
if let Some(imp_simp) = imp_simp {
if simp != imp_simp {
- return;
+ return None
}
}
- impl_candidates.push(imp);
- }),
- None => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| {
- impl_candidates.push(
- self.tcx.impl_trait_ref(def_id).unwrap());
- })
- };
- impl_candidates
+
+ Some(imp)
+ }).collect(),
+ None => all_impls.iter().map(|&def_id|
+ self.tcx.impl_trait_ref(def_id).unwrap()
+ ).collect()
+ }
}
fn report_similar_impl_candidates(&self,
span,
E0277,
"{}",
- message.unwrap_or_else(|| {
+ message.unwrap_or_else(||
format!("the trait bound `{}` is not satisfied{}",
trait_ref.to_predicate(), post_message)
- }));
+ ));
let explanation =
if obligation.cause.code == ObligationCauseCode::MainFunctionType {
// "the type `T` can't be frobnicated"
// which is somewhat confusing.
err.help(&format!("consider adding a `where {}` bound",
- trait_ref.to_predicate()));
+ trait_ref.to_predicate()));
} else if !have_alt_message {
// Can't show anything else useful, try to find similar impls.
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
ty::Predicate::RegionOutlives(ref predicate) => {
let predicate = self.resolve_type_vars_if_possible(predicate);
let err = self.region_outlives_predicate(&obligation.cause,
- &predicate).err().unwrap();
+ &predicate).err().unwrap();
struct_span_err!(self.tcx.sess, span, E0279,
"the requirement `{}` is not satisfied (`{}`)",
predicate, err)
let mut err = struct_span_err!(
self.tcx.sess, closure_span, E0525,
"expected a closure that implements the `{}` trait, \
- but this closure only implements `{}`",
+ but this closure only implements `{}`",
kind,
found_kind);
OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
let found_trait_ref = self.resolve_type_vars_if_possible(&*found_trait_ref);
let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref);
+
if expected_trait_ref.self_ty().references_error() {
return;
}
+
let found_trait_ty = found_trait_ref.self_ty();
let found_did = match found_trait_ty.sty {
- ty::Closure(did, _) |
- ty::Foreign(did) |
- ty::FnDef(did, _) => Some(did),
+ ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
ty::Adt(def, _) => Some(def.did),
_ => None,
};
- let found_span = found_did.and_then(|did| {
+
+ let found_span = found_did.and_then(|did|
self.tcx.hir.span_if_local(did)
- }).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
+ ).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
let found = match found_trait_ref.skip_binder().substs.type_at(1).sty {
- ty::Tuple(ref tys) => tys.iter()
- .map(|_| ArgKind::empty()).collect::<Vec<_>>(),
+ ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
_ => vec![ArgKind::empty()],
};
+
let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty {
ty::Tuple(ref tys) => tys.iter()
- .map(|t| match t.sty {
- ty::Tuple(ref tys) => ArgKind::Tuple(
- Some(span),
- tys.iter()
- .map(|ty| ("_".to_owned(), ty.sty.to_string()))
- .collect::<Vec<_>>()
- ),
- _ => ArgKind::Arg("_".to_owned(), t.sty.to_string()),
- }).collect(),
+ .map(|t| ArgKind::from_expected_ty(t, Some(span))).collect(),
ref sty => vec![ArgKind::Arg("_".to_owned(), sty.to_string())],
};
+
if found.len() == expected.len() {
self.report_closure_arg_mismatch(span,
found_span,
TraitNotObjectSafe(did) => {
let violations = self.tcx.object_safety_violations(did);
- self.tcx.report_object_safety_error(span, did,
- violations)
+ self.tcx.report_object_safety_error(span, did, violations)
}
ConstEvalFailure(ref err) => {
"could not evaluate constant expression",
) {
Some(err) => err,
- None => return,
+ None => {
+ self.tcx.sess.delay_span_bug(span,
+ &format!("constant in type had an ignored error: {:?}", err));
+ return;
+ }
}
}
.map(|arg| match arg.clone().node {
hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
Some(arg.span),
- tys.iter()
- .map(|_| ("_".to_owned(), "_".to_owned()))
- .collect::<Vec<_>>(),
+ vec![("_".to_owned(), "_".to_owned()); tys.len()]
),
- _ => ArgKind::Arg("_".to_owned(), "_".to_owned())
+ _ => ArgKind::empty()
}).collect::<Vec<ArgKind>>())
}
Node::Variant(&hir::Variant {
..
}) => {
(self.tcx.sess.source_map().def_span(span),
- fields.iter().map(|field| {
+ fields.iter().map(|field|
ArgKind::Arg(field.ident.to_string(), "_".to_string())
- }).collect::<Vec<_>>())
+ ).collect::<Vec<_>>())
}
Node::StructCtor(ref variant_data) => {
(self.tcx.sess.source_map().def_span(self.tcx.hir.span(variant_data.id())),
- variant_data.fields()
- .iter().map(|_| ArgKind::Arg("_".to_owned(), "_".to_owned()))
- .collect())
+ vec![ArgKind::empty(); variant_data.fields().len()])
}
_ => panic!("non-FnLike node found: {:?}", node),
}
found_str,
);
- err.span_label(span, format!( "expected {} that takes {}", kind, expected_str));
+ err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
if let Some(found_span) = found_span {
err.span_label(found_span, format!("takes {}", found_str));
// found arguments is empty (assume the user just wants to ignore args in this case).
// For example, if `expected_args_length` is 2, suggest `|_, _|`.
if found_args.is_empty() && is_closure {
- let underscores = "_".repeat(expected_args.len())
- .split("")
- .filter(|s| !s.is_empty())
+ let underscores = iter::repeat("_")
+ .take(expected_args.len())
.collect::<Vec<_>>()
.join(", ");
err.span_suggestion_with_applicability(
if fields.len() == expected_args.len() {
let sugg = fields.iter()
.map(|(name, _)| name.to_owned())
- .collect::<Vec<String>>().join(", ");
+ .collect::<Vec<String>>()
+ .join(", ");
err.span_suggestion_with_applicability(found_span,
"change the closure to take multiple \
arguments instead of a single tuple",
let inputs = trait_ref.substs.type_at(1);
let sig = if let ty::Tuple(inputs) = inputs.sty {
tcx.mk_fn_sig(
- inputs.iter().map(|&x| x),
+ inputs.iter().cloned(),
tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
false,
hir::Unsafety::Normal,
let mut reported_violations = FxHashSet();
for violation in violations {
- if !reported_violations.insert(violation.clone()) {
- continue;
+ if reported_violations.insert(violation.clone()) {
+ err.note(&violation.error_msg());
}
- err.note(&violation.error_msg());
}
err
}
self.need_type_info_err(body_id, span, self_ty).emit();
} else {
let mut err = struct_span_err!(self.tcx.sess,
- span, E0283,
- "type annotations required: \
+ span, E0283,
+ "type annotations required: \
cannot resolve `{}`",
- predicate);
+ predicate);
self.note_obligation_cause(&mut err, obligation);
err.emit();
}
ObligationCauseCode::ItemObligation(item_def_id) => {
let item_name = tcx.item_path_str(item_def_id);
let msg = format!("required by `{}`", item_name);
+
if let Some(sp) = tcx.hir.span_if_local(item_def_id) {
let sp = tcx.sess.source_map().def_span(sp);
err.span_note(sp, &msg);
parent_trait_ref.skip_binder().self_ty()));
let parent_predicate = parent_trait_ref.to_predicate();
self.note_obligation_cause_code(err,
- &parent_predicate,
- &data.parent_code,
- obligated_types);
+ &parent_predicate,
+ &data.parent_code,
+ obligated_types);
}
ObligationCauseCode::CompareImplMethodObligation { .. } => {
err.note(
}
fn is_recursive_obligation(&self,
- obligated_types: &mut Vec<&ty::TyS<'tcx>>,
- cause_code: &ObligationCauseCode<'tcx>) -> bool {
+ obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+ cause_code: &ObligationCauseCode<'tcx>) -> bool {
if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
- for obligated_type in obligated_types {
- if obligated_type == &parent_trait_ref.skip_binder().self_ty() {
- return true;
- }
+
+ if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
+ return true;
}
}
- return false;
+ false
}
}
/// Summarizes information
+#[derive(Clone)]
pub enum ArgKind {
/// An argument of non-tuple type. Parameters are (name, ty)
Arg(String, String),
}
/// Creates an `ArgKind` from the expected type of an
- /// argument. This has no name (`_`) and no source spans..
- pub fn from_expected_ty(t: Ty<'_>) -> ArgKind {
+ /// argument. It has no name (`_`) and an optional source span.
+ pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
match t.sty {
ty::Tuple(ref tys) => ArgKind::Tuple(
- None,
+ span,
tys.iter()
.map(|ty| ("_".to_owned(), ty.sty.to_string()))
.collect::<Vec<_>>()
if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) {
debug!("process_child_obligations: coinductive match");
} else {
- let cycle : Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
+ let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
self.selcx.infcx().report_overflow_error_cycle(&cycle);
}
}
let predicates: Vec<_> =
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec())
- .collect();
+ .collect();
debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
predicates);
};
debug!("normalize_param_env_or_error: normalized predicates={:?}",
- predicates);
+ predicates);
let region_scope_tree = region::ScopeTree::default();
// the method may have some early-bound lifetimes, add
// regions for those
- let substs = trait_ref.map_bound(|trait_ref| {
- Substs::for_item(tcx, def_id, |param, _| {
+ let substs = trait_ref.map_bound(|trait_ref|
+ Substs::for_item(tcx, def_id, |param, _|
match param.kind {
GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
GenericParamDefKind::Type {..} => {
trait_ref.substs[param.index as usize]
}
}
- })
- });
+ )
+ );
// the trait type may have higher-ranked lifetimes in it;
// so erase them if they appear, so that we get the type
// Check methods for violations.
let mut violations: Vec<_> = self.associated_items(trait_def_id)
.filter(|item| item.kind == ty::AssociatedKind::Method)
- .filter_map(|item| {
+ .filter_map(|item|
self.object_safety_violation_for_method(trait_def_id, &item)
.map(|code| ObjectSafetyViolation::Method(item.ident.name, code))
- }).filter(|violation| {
+ ).filter(|violation| {
if let ObjectSafetyViolation::Method(_,
- MethodViolationCode::WhereClauseReferencesSelf(span)) = violation {
- // Using`CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
+ MethodViolationCode::WhereClauseReferencesSelf(span)) = violation
+ {
+ // Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
// It's also hard to get a use site span, so we use the method definition span.
self.lint_node_note(
lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY,
ast::CRATE_NODE_ID,
*span,
&format!("the trait `{}` cannot be made into an object",
- self.item_path_str(trait_def_id)),
+ self.item_path_str(trait_def_id)),
&violation.error_msg());
false
} else {
let predicates = self.predicates_of(def_id);
let predicates = predicates.instantiate_identity(self).predicates;
elaborate_predicates(self, predicates)
- .any(|predicate| {
- match predicate {
- ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
- trait_pred.skip_binder().self_ty().is_self()
- }
- ty::Predicate::Projection(..) |
- ty::Predicate::Trait(..) |
- ty::Predicate::Subtype(..) |
- ty::Predicate::RegionOutlives(..) |
- ty::Predicate::WellFormed(..) |
- ty::Predicate::ObjectSafe(..) |
- ty::Predicate::ClosureKind(..) |
- ty::Predicate::TypeOutlives(..) |
- ty::Predicate::ConstEvaluatable(..) => {
- false
- }
+ .any(|predicate| match predicate {
+ ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
+ trait_pred.skip_binder().self_ty().is_self()
}
- })
+ ty::Predicate::Projection(..) |
+ ty::Predicate::Trait(..) |
+ ty::Predicate::Subtype(..) |
+ ty::Predicate::RegionOutlives(..) |
+ ty::Predicate::WellFormed(..) |
+ ty::Predicate::ObjectSafe(..) |
+ ty::Predicate::ClosureKind(..) |
+ ty::Predicate::TypeOutlives(..) |
+ ty::Predicate::ConstEvaluatable(..) => {
+ false
+ }
+ }
+ )
}
/// Returns `Some(_)` if this method makes the containing trait not object safe.
let condition = if is_root {
None
} else {
- let cond = item_iter.next().ok_or_else(|| {
+ let cond = item_iter.next().ok_or_else(||
parse_error(tcx, span,
"empty `on`-clause in `#[rustc_on_unimplemented]`",
"empty on-clause here",
None)
- })?.meta_item().ok_or_else(|| {
+ )?.meta_item().ok_or_else(||
parse_error(tcx, span,
"invalid `on`-clause in `#[rustc_on_unimplemented]`",
"invalid on-clause here",
None)
- })?;
+ )?;
attr::eval_condition(cond, &tcx.sess.parse_sess, &mut |_| true);
Some(cond.clone())
};
// `{from_desugaring}` is allowed
Position::ArgumentNamed(s) if s == "from_desugaring" => (),
// So is `{A}` if A is a type parameter
- Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
+ Position::ArgumentNamed(s) => match generics.params.iter().find(|param|
param.name == s
- }) {
+ ) {
Some(_) => (),
None => {
span_err!(tcx.sess, span, E0230,
let empty_string = String::new();
let parser = Parser::new(&self.0, None);
- parser.map(|p| {
+ parser.map(|p|
match p {
Piece::String(s) => s,
Piece::NextArgument(a) => match a.position {
}
}
},
- _ => {
- bug!("broken on_unimplemented {:?} - bad format arg", self.0)
- }
+ _ => bug!("broken on_unimplemented {:?} - bad format arg", self.0)
}
}
- }).collect()
+ ).collect()
}
}
match (current, candidate) {
(ParamEnv(..), ParamEnv(..)) => convert_to_ambiguous = (),
(ParamEnv(..), _) => return false,
- (_, ParamEnv(..)) => { unreachable!(); }
+ (_, ParamEnv(..)) => unreachable!(),
(_, _) => convert_to_ambiguous = (),
}
}
normalized_ty
}
- _ => {
- ty
- }
+ _ => ty
}
}
instance,
promoted: None
};
- match tcx.const_eval(param_env.and(cid)) {
- Ok(evaluated) => {
- let evaluated = evaluated.subst(self.tcx(), substs);
- return self.fold_const(evaluated);
- }
- Err(_) => {}
+ if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
+ let evaluated = evaluated.subst(self.tcx(), substs);
+ return self.fold_const(evaluated);
}
}
} else {
instance,
promoted: None
};
- match tcx.const_eval(param_env.and(cid)) {
- Ok(evaluated) => return self.fold_const(evaluated),
- Err(_) => {}
+ if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
+ return self.fold_const(evaluated)
}
}
}
candidate_set.mark_ambiguous();
return;
}
- _ => { return; }
+ _ => return
};
// If so, extract what we know from the trait and try to come up with a good answer.
for predicate in env_predicates {
debug!("assemble_candidates_from_predicates: predicate={:?}",
predicate);
- match predicate {
- ty::Predicate::Projection(data) => {
- let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
-
- let is_match = same_def_id && infcx.probe(|_| {
- let data_poly_trait_ref =
- data.to_poly_trait_ref(infcx.tcx);
- let obligation_poly_trait_ref =
- obligation_trait_ref.to_poly_trait_ref();
- infcx.at(&obligation.cause, obligation.param_env)
- .sup(obligation_poly_trait_ref, data_poly_trait_ref)
- .map(|InferOk { obligations: _, value: () }| {
- // FIXME(#32730) -- do we need to take obligations
- // into account in any way? At the moment, no.
- })
- .is_ok()
- });
-
- debug!("assemble_candidates_from_predicates: candidate={:?} \
- is_match={} same_def_id={}",
- data, is_match, same_def_id);
-
- if is_match {
- candidate_set.push_candidate(ctor(data));
- }
+ if let ty::Predicate::Projection(data) = predicate {
+ let same_def_id = data.projection_def_id() == obligation.predicate.item_def_id;
+
+ let is_match = same_def_id && infcx.probe(|_| {
+ let data_poly_trait_ref =
+ data.to_poly_trait_ref(infcx.tcx);
+ let obligation_poly_trait_ref =
+ obligation_trait_ref.to_poly_trait_ref();
+ infcx.at(&obligation.cause, obligation.param_env)
+ .sup(obligation_poly_trait_ref, data_poly_trait_ref)
+ .map(|InferOk { obligations: _, value: () }| {
+ // FIXME(#32730) -- do we need to take obligations
+ // into account in any way? At the moment, no.
+ })
+ .is_ok()
+ });
+
+ debug!("assemble_candidates_from_predicates: candidate={:?} \
+ is_match={} same_def_id={}",
+ data, is_match, same_def_id);
+
+ if is_match {
+ candidate_set.push_candidate(ctor(data));
}
- _ => {}
}
}
}
return Err(());
}
Err(e) => {
- debug!("assemble_candidates_from_impls: selection error {:?}",
- e);
+ debug!("assemble_candidates_from_impls: selection error {:?}", e);
candidate_set.mark_error(e);
return Err(());
}
let mut env_predicates = env_predicates.filter(|data| {
let data_poly_trait_ref = data.to_poly_trait_ref(selcx.tcx());
let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref();
- selcx.infcx().probe(|_| {
+ selcx.infcx().probe(|_|
selcx.infcx().at(&obligation.cause, obligation.param_env)
.sup(obligation_poly_trait_ref, data_poly_trait_ref)
.is_ok()
- })
+ )
});
// select the first matching one; there really ought to be one or
obligation.predicate.self_ty(),
fn_sig,
flag)
- .map_bound(|(trait_ref, ret_type)| {
+ .map_bound(|(trait_ref, ret_type)|
ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy::from_ref_and_name(
tcx,
),
ty: ret_type
}
- });
+ );
confirm_param_env_candidate(selcx, obligation, predicate)
}
debug!("c_ty = {:?}", c_ty);
match &gcx.dropck_outlives(c_ty) {
Ok(result) if result.is_proven() => {
- match self.infcx.instantiate_query_result_and_region_obligations(
+ if let Ok(InferOk { value, obligations }) =
+ self.infcx.instantiate_query_result_and_region_obligations(
self.cause,
self.param_env,
&orig_values,
- result,
- ) {
- Ok(InferOk { value, obligations }) => {
- let ty = self.infcx.resolve_type_vars_if_possible(&ty);
- let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
- return InferOk {
- value: kinds,
- obligations,
- };
- }
-
- Err(_) => { /* fallthrough to error-handling code below */ }
+ result)
+ {
+ let ty = self.infcx.resolve_type_vars_if_possible(&ty);
+ let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
+ return InferOk {
+ value: kinds,
+ obligations,
+ };
}
}
fn from_iter<I: IntoIterator<Item = DtorckConstraint<'tcx>>>(iter: I) -> Self {
let mut result = Self::empty();
- for DtorckConstraint {
- outlives,
- dtorck_types,
- overflows,
- } in iter
- {
+ for DtorckConstraint { outlives, dtorck_types, overflows } in iter {
result.outlives.extend(outlives);
result.dtorck_types.extend(dtorck_types);
result.overflows.extend(overflows);
}
}
- // The following *might* require a destructor: it would deeper inspection to tell.
+ // The following *might* require a destructor: needs deeper inspection.
ty::Dynamic(..)
| ty::Projection(..)
| ty::Param(_)
value,
self.param_env,
);
+ if !value.has_projections() {
+ return Ok(Normalized {
+ value: value.clone(),
+ obligations: vec![],
+ });
+ }
+
let mut normalizer = QueryNormalizer {
infcx: self.infcx,
cause: self.cause,
error: false,
anon_depth: 0,
};
- if !value.has_projections() {
- return Ok(Normalized {
- value: value.clone(),
- obligations: vec![],
- });
- }
let value1 = value.fold_with(&mut normalizer);
if normalizer.error {
let gcx = self.infcx.tcx.global_tcx();
let mut orig_values = SmallVec::new();
- let c_data = self.infcx
- .canonicalize_query(&self.param_env.and(*data), &mut orig_values);
+ let c_data = self.infcx.canonicalize_query(
+ &self.param_env.and(*data), &mut orig_values);
debug!("QueryNormalizer: c_data = {:#?}", c_data);
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
match gcx.normalize_projection_ty(c_data) {
self.cause,
self.param_env,
&orig_values,
- &result,
- ) {
- Ok(InferOk {
- value: result,
- obligations,
- }) => {
+ &result)
+ {
+ Ok(InferOk { value: result, obligations }) => {
debug!("QueryNormalizer: result = {:#?}", result);
debug!("QueryNormalizer: obligations = {:#?}", obligations);
self.obligations.extend(obligations);
instance,
promoted: None,
};
- match tcx.const_eval(param_env.and(cid)) {
- Ok(evaluated) => {
- let evaluated = evaluated.subst(self.tcx(), substs);
- return self.fold_const(evaluated);
- }
- Err(_) => {}
+ if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
+ let evaluated = evaluated.subst(self.tcx(), substs);
+ return self.fold_const(evaluated);
}
}
} else {
instance,
promoted: None,
};
- match tcx.const_eval(param_env.and(cid)) {
- Ok(evaluated) => return self.fold_const(evaluated),
- Err(_) => {}
+ if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
+ return self.fold_const(evaluated)
}
}
}
use hir;
use util::nodemap::{FxHashMap, FxHashSet};
-
pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
#[derive(Clone)]
pub struct SelectionCache<'tcx> {
hashmap: Lock<FxHashMap<ty::TraitRef<'tcx>,
- WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>>>,
+ WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>>>,
}
/// The selection process begins by considering all impls, where
obligation: &PredicateObligation<'tcx>)
-> Result<EvaluationResult, OverflowError>
{
- self.probe(|this, _| {
+ self.probe(|this, _|
this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
- })
+ )
}
/// Evaluates the predicates in `predicates` recursively. Note that
self.infcx.projection_cache.borrow_mut().complete(key);
}
result
- }
- Ok(None) => {
- Ok(EvaluatedToAmbig)
- }
- Err(_) => {
- Ok(EvaluatedToErr)
- }
+ },
+ Ok(None) => Ok(EvaluatedToAmbig),
+ Err(_) => Ok(EvaluatedToErr)
}
}
} else {
Ok(EvaluatedToErr)
}
- }
- None => {
- Ok(EvaluatedToAmbig)
- }
+ },
+ None => Ok(EvaluatedToAmbig)
}
}
// same unbound type variable.
if let Some(rec_index) =
stack.iter()
- .skip(1) // skip top-most frame
- .position(|prev| stack.obligation.param_env == prev.obligation.param_env &&
- stack.fresh_trait_ref == prev.fresh_trait_ref)
+ .skip(1) // skip top-most frame
+ .position(|prev| stack.obligation.param_env == prev.obligation.param_env &&
+ stack.fresh_trait_ref == prev.fresh_trait_ref)
{
debug!("evaluate_stack({:?}) --> recursive",
stack.fresh_trait_ref);
- let cycle = stack.iter().skip(1).take(rec_index+1);
+ let cycle = stack.iter().skip(1).take(rec_index + 1);
let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate));
if self.coinductive_match(cycle) {
debug!("evaluate_stack({:?}) --> recursive, coinductive",
let result = match predicate {
ty::Predicate::Trait(ref data) => {
self.tcx().trait_is_auto(data.def_id())
- }
- _ => {
- false
- }
+ },
+ _ => false
};
debug!("coinductive_predicate({:?}) = {:?}", predicate, result);
result
}
// If no match, compute result and insert into cache.
- let (candidate, dep_node) = self.in_task(|this| {
+ let (candidate, dep_node) = self.in_task(|this|
this.candidate_from_obligation_no_cache(stack)
- });
+ );
debug!("CACHE MISS: SELECT({:?})={:?}",
cache_fresh_trait_pred, candidate);
fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
where OP: FnOnce(&mut Self) -> R
{
- let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, || {
+ let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, ||
op(self)
- });
+ );
self.tcx().dep_graph.read_index(dep_node);
(result, dep_node)
}
return Ok(None);
}
- match self.is_knowable(stack) {
- None => {}
- Some(conflict) => {
- debug!("coherence stage: not knowable");
- if self.intercrate_ambiguity_causes.is_some() {
- debug!("evaluate_stack: intercrate_ambiguity_causes is some");
- // Heuristics: show the diagnostics when there are no candidates in crate.
- if let Ok(candidate_set) = self.assemble_candidates(stack) {
- let no_candidates_apply =
- candidate_set
- .vec
- .iter()
- .map(|c| self.evaluate_candidate(stack, &c))
- .collect::<Result<Vec<_>, OverflowError>>()?
- .iter()
- .all(|r| !r.may_apply());
- if !candidate_set.ambiguous && no_candidates_apply {
- let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
- let self_ty = trait_ref.self_ty();
- let trait_desc = trait_ref.to_string();
- let self_desc = if self_ty.has_concrete_skeleton() {
- Some(self_ty.to_string())
- } else {
- None
- };
- let cause = if let Conflict::Upstream = conflict {
- IntercrateAmbiguityCause::UpstreamCrateUpdate {
- trait_desc,
- self_desc,
- }
- } else {
- IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
- };
- debug!("evaluate_stack: pushing cause = {:?}", cause);
- self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+ if let Some(conflict) = self.is_knowable(stack) {
+ debug!("coherence stage: not knowable");
+ if self.intercrate_ambiguity_causes.is_some() {
+ debug!("evaluate_stack: intercrate_ambiguity_causes is some");
+ // Heuristics: show the diagnostics when there are no candidates in crate.
+ if let Ok(candidate_set) = self.assemble_candidates(stack) {
+ let mut no_candidates_apply = true;
+ {
+ let evaluated_candidates = candidate_set.vec.iter().map(|c|
+ self.evaluate_candidate(stack, &c));
+
+ for ec in evaluated_candidates {
+ match ec {
+ Ok(c) => {
+ if c.may_apply() {
+ no_candidates_apply = false;
+ break
+ }
+ },
+ Err(e) => return Err(e.into())
+ }
}
}
+
+ if !candidate_set.ambiguous && no_candidates_apply {
+ let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
+ let self_ty = trait_ref.self_ty();
+ let trait_desc = trait_ref.to_string();
+ let self_desc = if self_ty.has_concrete_skeleton() {
+ Some(self_ty.to_string())
+ } else {
+ None
+ };
+ let cause = if let Conflict::Upstream = conflict {
+ IntercrateAmbiguityCause::UpstreamCrateUpdate {
+ trait_desc,
+ self_desc,
+ }
+ } else {
+ IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
+ };
+ debug!("evaluate_stack: pushing cause = {:?}", cause);
+ self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+ }
}
- return Ok(None);
}
+ return Ok(None);
}
let candidate_set = self.assemble_candidates(stack)?;
// Other bounds. Consider both in-scope bounds from fn decl
// and applicable impls. There is a certain set of precedence rules here.
-
let def_id = obligation.predicate.def_id();
let lang_items = self.tcx().lang_items();
+
if lang_items.copy_trait() == Some(def_id) {
debug!("obligation self ty is {:?}",
obligation.predicate.skip_binder().self_ty());
ty::Projection(_) | ty::Opaque(..) => {}
ty::Infer(ty::TyVar(_)) => {
span_bug!(obligation.cause.span,
- "Self=_ should have been handled by assemble_candidates");
+ "Self=_ should have been handled by assemble_candidates");
}
_ => return
}
- let result = self.probe(|this, snapshot| {
+ let result = self.probe(|this, snapshot|
this.match_projection_obligation_against_definition_bounds(obligation,
snapshot)
- });
+ );
if result {
candidates.vec.push(ProjectionCandidate);
span_bug!(
obligation.cause.span,
"match_projection_obligation_against_definition_bounds() called \
- but self-ty not a projection: {:?}",
+ but self-ty is not a projection: {:?}",
skol_trait_predicate.trait_ref.self_ty());
}
};
where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
-> Result<EvaluationResult, OverflowError>
{
- self.probe(move |this, _| {
+ self.probe(move |this, _|
match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
Ok(obligations) => {
this.evaluate_predicates_recursively(stack.list(), obligations.iter())
}
Err(()) => Ok(EvaluatedToErr)
}
- })
+ )
}
fn assemble_generator_candidates(&mut self,
obligation);
candidates.vec.push(GeneratorCandidate);
- Ok(())
}
ty::Infer(ty::TyVar(_)) => {
debug!("assemble_generator_candidates: ambiguous self-type");
candidates.ambiguous = true;
- return Ok(());
}
- _ => { return Ok(()); }
+ _ => {}
}
+
+ Ok(())
}
/// Check for the artificial impl that the compiler will create for an obligation like `X :
debug!("assemble_unboxed_candidates: closure_kind not yet known");
candidates.vec.push(ClosureCandidate);
}
- };
- Ok(())
+ }
}
ty::Infer(ty::TyVar(_)) => {
debug!("assemble_unboxed_closure_candidates: ambiguous self-type");
candidates.ambiguous = true;
- return Ok(());
}
- _ => { return Ok(()); }
+ _ => {}
}
+
+ Ok(())
}
/// Implement one of the `Fn()` family for a fn pointer.
debug!("assemble_fn_pointer_candidates: ambiguous self-type");
candidates.ambiguous = true; // could wind up being a fn() type
}
-
// provide an impl, but only for suitable `fn` pointers
ty::FnDef(..) | ty::FnPtr(_) => {
if let ty::FnSig {
candidates.vec.push(FnPointerCandidate);
}
}
-
- _ => { }
+ _ => {}
}
Ok(())
obligation.predicate.def_id(),
obligation.predicate.skip_binder().trait_ref.self_ty(),
|impl_def_id| {
- self.probe(|this, snapshot| { /* [1] */
- match this.match_impl(impl_def_id, obligation, snapshot) {
- Ok(skol_map) => {
- candidates.vec.push(ImplCandidate(impl_def_id));
-
- // NB: we can safely drop the skol map
- // since we are in a probe [1]
- mem::drop(skol_map);
- }
- Err(_) => { }
+ self.probe(|this, snapshot| /* [1] */
+ if let Ok(skol_map) = this.match_impl(impl_def_id, obligation, snapshot) {
+ candidates.vec.push(ImplCandidate(impl_def_id));
+
+ // NB: we can safely drop the skol map
+ // since we are in a probe [1]
+ mem::drop(skol_map);
}
- });
+ );
}
);
ty::Dynamic(ref data, ..) => {
if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
debug!("assemble_candidates_from_object_ty: matched builtin bound, \
- pushing candidate");
+ pushing candidate");
candidates.vec.push(BuiltinObjectCandidate);
return;
}
candidates.ambiguous = true; // could wind up being an object type
return;
}
- _ => {
- return;
- }
+ _ => return
};
debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}",
// but `Foo` is declared as `trait Foo : Bar<u32>`.
let upcast_trait_refs =
util::supertraits(this.tcx(), poly_trait_ref)
- .filter(|upcast_trait_ref| {
+ .filter(|upcast_trait_ref|
this.probe(|this, _| {
let upcast_trait_ref = upcast_trait_ref.clone();
this.match_poly_trait_ref(obligation, upcast_trait_ref).is_ok()
})
- })
+ )
.count();
if upcast_trait_refs > 1 {
other: &EvaluatedCandidate<'tcx>)
-> bool
{
+ if victim.candidate == other.candidate {
+ return true;
+ }
+
// Check if a bound would previously have been removed when normalizing
// the param_env so that it can be given the lowest priority. See
// #50825 for the motivation for this.
cand.is_global() && !cand.has_late_bound_regions()
};
- if victim.candidate == other.candidate {
- return true;
- }
-
match other.candidate {
// Prefer BuiltinCandidate { has_nested: false } to anything else.
// This is a fix for #53123 and prevents winnowing from accidentally extending the
BuiltinCandidate { has_nested: false } => true,
ParamCandidate(ref cand) => match victim.candidate {
AutoImplCandidate(..) => {
- bug!(
- "default implementations shouldn't be recorded \
- when there are other valid candidates");
+ bug!("default implementations shouldn't be recorded \
+ when there are other valid candidates");
}
// Prefer BuiltinCandidate { has_nested: false } to anything else.
// This is a fix for #53123 and prevents winnowing from accidentally extending the
ObjectCandidate |
ProjectionCandidate => match victim.candidate {
AutoImplCandidate(..) => {
- bug!(
- "default implementations shouldn't be recorded \
- when there are other valid candidates");
+ bug!("default implementations shouldn't be recorded \
+ when there are other valid candidates");
}
// Prefer BuiltinCandidate { has_nested: false } to anything else.
// This is a fix for #53123 and prevents winnowing from accidentally extending the
fn assemble_builtin_bound_candidates<'o>(&mut self,
conditions: BuiltinImplConditions<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>)
- -> Result<(),SelectionError<'tcx>>
+ -> Result<(), SelectionError<'tcx>>
{
match conditions {
BuiltinImplConditions::Where(nested) => {
candidates.vec.push(BuiltinCandidate {
has_nested: nested.skip_binder().len() > 0
});
- Ok(())
}
- BuiltinImplConditions::None => { Ok(()) }
+ BuiltinImplConditions::None => {}
BuiltinImplConditions::Ambiguous => {
debug!("assemble_builtin_bound_candidates: ambiguous builtin");
- Ok(candidates.ambiguous = true)
+ candidates.ambiguous = true;
}
}
+
+ Ok(())
}
- fn sized_conditions(&mut self, obligation: &TraitObligation<'tcx>)
- -> BuiltinImplConditions<'tcx>
+ fn sized_conditions(&mut self,
+ obligation: &TraitObligation<'tcx>)
+ -> BuiltinImplConditions<'tcx>
{
use self::BuiltinImplConditions::{Ambiguous, None, Where};
}
}
- fn copy_clone_conditions(&mut self, obligation: &TraitObligation<'tcx>)
- -> BuiltinImplConditions<'tcx>
+ fn copy_clone_conditions(&mut self,
+ obligation: &TraitObligation<'tcx>)
+ -> BuiltinImplConditions<'tcx>
{
// NOTE: binder moved to (*)
let self_ty = self.infcx.shallow_resolve(
let lang_items = self.tcx().lang_items();
let obligations = if has_nested {
let trait_def = obligation.predicate.def_id();
- let conditions = match trait_def {
- _ if Some(trait_def) == lang_items.sized_trait() => {
+ let conditions =
+ if Some(trait_def) == lang_items.sized_trait() {
self.sized_conditions(obligation)
- }
- _ if Some(trait_def) == lang_items.copy_trait() => {
+ } else if Some(trait_def) == lang_items.copy_trait() {
self.copy_clone_conditions(obligation)
- }
- _ if Some(trait_def) == lang_items.clone_trait() => {
+ } else if Some(trait_def) == lang_items.clone_trait() {
self.copy_clone_conditions(obligation)
- }
- _ => bug!("unexpected builtin trait {:?}", trait_def)
+ } else {
+ bug!("unexpected builtin trait {:?}", trait_def)
};
let nested = match conditions {
BuiltinImplConditions::Where(nested) => nested,
/// See `confirm_auto_impl_candidate`
fn vtable_auto_impl(&mut self,
- obligation: &TraitObligation<'tcx>,
- trait_def_id: DefId,
- nested: ty::Binder<Vec<Ty<'tcx>>>)
- -> VtableAutoImplData<PredicateObligation<'tcx>>
+ obligation: &TraitObligation<'tcx>,
+ trait_def_id: DefId,
+ nested: ty::Binder<Vec<Ty<'tcx>>>)
+ -> VtableAutoImplData<PredicateObligation<'tcx>>
{
debug!("vtable_auto_impl: nested={:?}", nested);
ty::Dynamic(ref data, ..) => {
data.principal().unwrap().with_self_ty(self.tcx(), self_ty)
}
- _ => {
- span_bug!(obligation.cause.span,
- "object candidate with non-object");
- }
+ _ => span_bug!(obligation.cause.span,
+ "object candidate with non-object")
};
let mut upcast_trait_ref = None;
// record it for later.)
let nonmatching =
util::supertraits(tcx, poly_trait_ref)
- .take_while(|&t| {
- match
- self.commit_if_ok(
- |this, _| this.match_poly_trait_ref(obligation, t))
+ .take_while(|&t|
+ match self.commit_if_ok(|this, _|
+ this.match_poly_trait_ref(obligation, t))
{
Ok(obligations) => {
upcast_trait_ref = Some(t);
}
Err(_) => { true }
}
- });
+ );
// Additionally, for each of the nonmatching predicates that
// we pass over, we sum up the set of number of vtable
// entries, so that we can compute the offset for the selected
// trait.
- vtable_base =
- nonmatching.map(|t| tcx.count_own_vtable_entries(t))
- .sum();
-
+ vtable_base = nonmatching.map(|t| tcx.count_own_vtable_entries(t)).sum();
}
VtableObjectData {
fn confirm_generator_candidate(&mut self,
obligation: &TraitObligation<'tcx>)
-> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
- SelectionError<'tcx>>
+ SelectionError<'tcx>>
{
// ok to skip binder because the substs on generator types never
// touch bound regions, they just capture the in-scope
{
debug!("confirm_closure_candidate({:?})", obligation);
- let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()) {
- Some(k) => k,
- None => bug!("closure candidate for non-fn trait {:?}", obligation)
- };
+ let kind = self.tcx()
+ .lang_items()
+ .fn_trait_kind(obligation.predicate.def_id())
+ .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}",
+ obligation));
// ok to skip binder because the substs on closure types never
// touch bound regions, they just capture the in-scope
obligations.extend(
self.confirm_poly_trait_refs(obligation.cause.clone(),
- obligation.param_env,
- obligation.predicate.to_poly_trait_ref(),
- trait_ref)?);
+ obligation.param_env,
+ obligation.predicate.to_poly_trait_ref(),
+ trait_ref)?);
obligations.push(Obligation::new(
obligation.cause.clone(),
(_, &ty::Dynamic(ref data, r)) => {
let mut object_dids =
data.auto_traits().chain(data.principal().map(|p| p.def_id()));
- if let Some(did) = object_dids.find(|did| {
- !tcx.is_object_safe(*did)
- }) {
+ if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
return Err(TraitNotObjectSafe(did))
}
let cause = ObligationCause::new(obligation.cause.span,
obligation.cause.body_id,
ObjectCastObligation(target));
- let mut push = |predicate| {
- nested.push(Obligation::with_depth(cause.clone(),
- obligation.recursion_depth + 1,
- obligation.param_env,
- predicate));
+
+ let predicate_to_obligation = |predicate| {
+ Obligation::with_depth(cause.clone(),
+ obligation.recursion_depth + 1,
+ obligation.param_env,
+ predicate)
};
// Create obligations:
// words, if the object type is Foo+Send, this would create an obligation for the
// Send check.)
// - Projection predicates
- for predicate in data.iter() {
- push(predicate.with_self_ty(tcx, source));
- }
+ nested.extend(data.iter().map(|d|
+ predicate_to_obligation(d.with_self_ty(tcx, source))
+ ));
// We can only make objects from sized types.
let tr = ty::TraitRef {
def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem),
substs: tcx.mk_substs_trait(source, &[]),
};
- push(tr.to_predicate());
+ nested.push(predicate_to_obligation(tr.to_predicate()));
// If the type is `Foo+'a`, ensures that the type
// being cast to `Foo+'a` outlives `'a`:
let outlives = ty::OutlivesPredicate(source, r);
- push(ty::Binder::dummy(outlives).to_predicate());
+ nested.push(predicate_to_obligation(
+ ty::Binder::dummy(outlives).to_predicate()));
}
// [T; n] -> [T].
// Check that the source struct with the target's
// unsized parameters is equal to the target.
- let params = substs_a.iter().enumerate().map(|(i, &k)| {
+ let params = substs_a.iter().enumerate().map(|(i, &k)|
if ty_params.contains(i) {
substs_b.type_at(i).into()
} else {
k
}
- });
+ );
let new_struct = tcx.mk_adt(def, tcx.mk_substs(params));
let InferOk { obligations, .. } =
self.infcx.at(&obligation.cause, obligation.param_env)
let InferOk { obligations, .. } =
self.infcx.at(&obligation.cause, obligation.param_env)
.eq(skol_obligation_trait_ref, impl_trait_ref)
- .map_err(|e| {
- debug!("match_impl: failed eq_trait_refs due to `{}`", e);
- ()
- })?;
+ .map_err(|e|
+ debug!("match_impl: failed eq_trait_refs due to `{}`", e)
+ )?;
nested_obligations.extend(obligations);
if let Err(e) = self.infcx.leak_check(false,
fn match_where_clause_trait_ref(&mut self,
obligation: &TraitObligation<'tcx>,
where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
- -> Result<Vec<PredicateObligation<'tcx>>,()>
+ -> Result<Vec<PredicateObligation<'tcx>>, ()>
{
self.match_poly_trait_ref(obligation, where_clause_trait_ref)
}
fn match_poly_trait_ref(&mut self,
obligation: &TraitObligation<'tcx>,
poly_trait_ref: ty::PolyTraitRef<'tcx>)
- -> Result<Vec<PredicateObligation<'tcx>>,()>
+ -> Result<Vec<PredicateObligation<'tcx>>, ()>
{
debug!("match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}",
obligation,
// in fact unparameterized (or at least does not reference any
// regions bound in the obligation). Still probably some
// refactoring could make this nicer.
-
self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
obligation.predicate
- .skip_binder().self_ty(), // (1)
+ .skip_binder()
+ .self_ty(), // (1)
closure_type,
util::TupleArgumentsFlag::No)
.map_bound(|(trait_ref, _)| trait_ref)
}
fn generator_trait_ref_unnormalized(&mut self,
- obligation: &TraitObligation<'tcx>,
- closure_def_id: DefId,
- substs: ty::GeneratorSubsts<'tcx>)
- -> ty::PolyTraitRef<'tcx>
+ obligation: &TraitObligation<'tcx>,
+ closure_def_id: DefId,
+ substs: ty::GeneratorSubsts<'tcx>)
+ -> ty::PolyTraitRef<'tcx>
{
let gen_sig = substs.poly_sig(closure_def_id, self.tcx());
self.tcx().generator_trait_ref_and_outputs(obligation.predicate.def_id(),
obligation.predicate
- .skip_binder().self_ty(), // (1)
+ .skip_binder()
+ .self_ty(), // (1)
gen_sig)
.map_bound(|(trait_ref, ..)| trait_ref)
}
impl<'tcx> TraitObligation<'tcx> {
#[allow(unused_comparisons)]
pub fn derived_cause(&self,
- variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>)
- -> ObligationCause<'tcx>
+ variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>)
+ -> ObligationCause<'tcx>
{
/*!
* Creates a cause for obligations that are derived from
}
fulfill_implication(infcx, param_env, source_trait_ref, target_impl)
- .unwrap_or_else(|_| {
+ .unwrap_or_else(|_|
bug!("When translating substitutions for specialization, the expected \
specialization failed to hold")
- })
+ )
}
specialization_graph::Node::Trait(..) => source_trait_ref.substs,
};
let substs = translate_substs(&infcx, param_env, impl_data.impl_def_id,
substs, node_item.node);
let substs = infcx.tcx.erase_regions(&substs);
- tcx.lift(&substs).unwrap_or_else(|| {
+ tcx.lift(&substs).unwrap_or_else(||
bug!("find_method: translate_substs \
returned {:?} which contains inference types/regions",
- substs);
- })
+ substs)
+ )
});
(node_item.item.def_id, substs)
}
- None => {
- bug!("{:?} not found in {:?}", item, impl_data.impl_def_id)
- }
+ None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id)
}
}
-> Lrc<specialization_graph::Graph> {
let mut sg = specialization_graph::Graph::new();
- let mut trait_impls = Vec::new();
- tcx.for_each_impl(trait_id, |impl_did| trait_impls.push(impl_did));
+ let mut trait_impls = tcx.all_impls(trait_id);
// The coherence checking implementation seems to rely on impls being
// iterated over (roughly) in definition order, so we are sorting by
"first implementation here".to_string());
err.span_label(impl_span,
format!("conflicting implementation{}",
- overlap.self_desc
- .map_or(String::new(),
- |ty| format!(" for `{}`", ty))));
+ overlap.self_desc
+ .map_or(String::new(),
+ |ty| format!(" for `{}`", ty))));
}
Err(cname) => {
let msg = match to_pretty_impl_header(tcx, overlap.with_impl) {
// The predicates will contain default bounds like `T: Sized`. We need to
// remove these bounds, and add `T: ?Sized` to any untouched type parameters.
let predicates = tcx.predicates_of(impl_def_id).predicates;
- let mut pretty_predicates = Vec::with_capacity(predicates.len());
+ let mut pretty_predicates = Vec::with_capacity(
+ predicates.len() + types_without_default_bounds.len());
+
for p in predicates {
if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() {
if Some(poly_trait_ref.def_id()) == sized_trait {
}
pretty_predicates.push(p.to_string());
}
+
pretty_predicates.extend(
types_without_default_bounds.iter().map(|ty| format!("{}: ?Sized", ty))
);
+
if !pretty_predicates.is_empty() {
write!(w, "\n where {}", pretty_predicates.join(", ")).unwrap();
}
let cur = self.current_source.take();
if let Some(Node::Impl(cur_impl)) = cur {
let parent = self.specialization_graph.parent(cur_impl);
- if parent == self.trait_def_id {
- self.current_source = Some(Node::Trait(parent));
+
+ self.current_source = if parent == self.trait_def_id {
+ Some(Node::Trait(parent))
} else {
- self.current_source = Some(Node::Impl(parent));
- }
+ Some(Node::Impl(parent))
+ };
}
cur
}
match *self {
super::Unimplemented => Some(super::Unimplemented),
super::OutputTypeParameterMismatch(a, b, ref err) => {
- tcx.lift(&(a, b)).and_then(|(a, b)| {
+ tcx.lift(&(a, b)).and_then(|(a, b)|
tcx.lift(err)
.map(|err| super::OutputTypeParameterMismatch(a, b, err))
- })
+ )
}
super::TraitNotObjectSafe(def_id) => Some(super::TraitNotObjectSafe(def_id)),
super::ConstEvalFailure(ref err) => tcx.lift(&**err).map(|err| super::ConstEvalFailure(
super::ReferenceOutlivesReferent(ty) => {
tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
}
- super::ObjectTypeBound(ty, r) => tcx.lift(&ty).and_then(|ty| {
+ super::ObjectTypeBound(ty, r) => tcx.lift(&ty).and_then(|ty|
tcx.lift(&r)
- .and_then(|r| Some(super::ObjectTypeBound(ty, r)))
- }),
+ .and_then(|r| Some(super::ObjectTypeBound(ty, r)))
+ ),
super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation),
super::AssignmentLhsSized => Some(super::AssignmentLhsSized),
super::TupleInitializerSized => Some(super::TupleInitializerSized),
impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
type Lifted = traits::DerivedObligationCause<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
- tcx.lift(&self.parent_trait_ref).and_then(|trait_ref| {
+ tcx.lift(&self.parent_trait_ref).and_then(|trait_ref|
tcx.lift(&*self.parent_code)
- .map(|code| traits::DerivedObligationCause {
- parent_trait_ref: trait_ref,
- parent_code: Rc::new(code),
- })
- })
+ .map(|code| traits::DerivedObligationCause {
+ parent_trait_ref: trait_ref,
+ parent_code: Rc::new(code),
+ })
+ )
}
}
impl_def_id,
substs,
nested,
- }) => tcx.lift(&substs).map(|substs| {
+ }) => tcx.lift(&substs).map(|substs|
traits::VtableImpl(traits::VtableImplData {
impl_def_id,
substs,
nested,
})
- }),
+ ),
traits::VtableAutoImpl(t) => Some(traits::VtableAutoImpl(t)),
traits::VtableGenerator(traits::VtableGeneratorData {
generator_def_id,
substs,
nested,
- }) => tcx.lift(&substs).map(|substs| {
+ }) => tcx.lift(&substs).map(|substs|
traits::VtableGenerator(traits::VtableGeneratorData {
generator_def_id: generator_def_id,
substs: substs,
nested: nested,
})
- }),
+ ),
traits::VtableClosure(traits::VtableClosureData {
closure_def_id,
substs,
nested,
- }) => tcx.lift(&substs).map(|substs| {
+ }) => tcx.lift(&substs).map(|substs|
traits::VtableClosure(traits::VtableClosureData {
closure_def_id,
substs,
nested,
})
- }),
+ ),
traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested }) => {
- tcx.lift(&fn_ty).map(|fn_ty| {
+ tcx.lift(&fn_ty).map(|fn_ty|
traits::VtableFnPointer(traits::VtableFnPointerData { fn_ty, nested })
- })
+ )
}
traits::VtableParam(n) => Some(traits::VtableParam(n)),
traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)),
upcast_trait_ref,
vtable_base,
nested,
- }) => tcx.lift(&upcast_trait_ref).map(|trait_ref| {
+ }) => tcx.lift(&upcast_trait_ref).map(|trait_ref|
traits::VtableObject(traits::VtableObjectData {
upcast_trait_ref: trait_ref,
vtable_base,
nested,
})
- }),
+ ),
}
}
}
Some(ty::Predicate::Trait(data)) => {
return Some(data.to_poly_trait_ref());
}
- Some(_) => {
- }
+ Some(_) => {}
}
}
}
}
}
}
+
+ /// Return a vector containing all impls
+ pub fn all_impls(self, def_id: DefId) -> Vec<DefId> {
+ let impls = self.trait_impls_of(def_id);
+
+ impls.blanket_impls.iter().chain(
+ impls.non_blanket_impls.values().flatten()
+ ).cloned().collect()
+ }
}
// Query provider for `trait_impls_of`.
}) = cmt.cat {
db.note(fn_closure_msg);
} else {
- db.span_suggestion(sp, msg, suggestion);
+ db.span_suggestion_with_applicability(
+ sp,
+ msg,
+ suggestion,
+ Applicability::Unspecified,
+ );
}
} else {
- db.span_suggestion(sp, msg, suggestion);
+ db.span_suggestion_with_applicability(
+ sp,
+ msg,
+ suggestion,
+ Applicability::Unspecified,
+ );
}
}
_ => {
let let_span = self.tcx.hir.span(node_id);
let suggestion = suggest_ref_mut(self.tcx, let_span);
if let Some(replace_str) = suggestion {
- db.span_suggestion(
+ db.span_suggestion_with_applicability(
let_span,
"use a mutable reference instead",
replace_str,
+ // I believe this can be machine applicable,
+ // but if there are multiple attempted uses of an immutable
+ // reference, I don't know how rustfix handles it, it might
+ // attempt fixing them multiple times.
+ // @estebank
+ Applicability::Unspecified,
);
}
}
)) = ty.map(|t| &t.node)
{
let borrow_expr_id = self.tcx.hir.get_parent_node(borrowed_node_id);
- db.span_suggestion(
+ db.span_suggestion_with_applicability(
self.tcx.hir.span(borrow_expr_id),
"consider removing the `&mut`, as it is an \
immutable binding to a mutable reference",
- snippet
+ snippet,
+ Applicability::MachineApplicable,
);
} else {
db.span_suggestion_with_applicability(
&cmt_path_or_string,
capture_span,
Origin::Ast)
- .span_suggestion(err.span,
- &format!("to force the closure to take ownership of {} \
- (and any other referenced variables), \
- use the `move` keyword",
- cmt_path_or_string),
- suggestion)
+ .span_suggestion_with_applicability(
+ err.span,
+ &format!("to force the closure to take ownership of {} \
+ (and any other referenced variables), \
+ use the `move` keyword",
+ cmt_path_or_string),
+ suggestion,
+ Applicability::MachineApplicable,
+ )
.emit();
self.signal_error();
}
// Make the default table accessible
self.cmd.arg("--export-table");
+ // Rust code should never have warnings, and warnings are often
+ // indicative of bugs, let's prevent them.
+ self.cmd.arg("--fatal-warnings");
+
let mut cmd = Command::new("");
::std::mem::swap(&mut cmd, &mut self.cmd);
cmd
llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
NO_SCOPE_METADATA,
name.as_ptr(),
- // LLVM 3.9
- // doesn't accept
- // null here, so
- // pass the name
- // as the linkage
- // name.
- name.as_ptr(),
+ ptr::null(),
unknown_file_metadata(cx),
UNKNOWN_LINE_NUMBER,
vtable_type,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression'
-// once support for LLVM 3.9 is dropped.
-//
-// This method was changed in this LLVM patch:
-// https://reviews.llvm.org/D26769
-
use super::debuginfo::{
DIBuilder, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType,
DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable,
- DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator,
+ DIGlobalVariableExpression, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator,
DINameSpace, DIFlags,
};
pub type DIDerivedType = DIType;
pub type DICompositeType = DIDerivedType;
pub type DIVariable = DIDescriptor;
- pub type DIGlobalVariable = DIDescriptor;
+ pub type DIGlobalVariableExpression = DIDescriptor;
pub type DIArray = DIDescriptor;
pub type DISubrange = DIDescriptor;
pub type DIEnumerator = DIDescriptor;
Val: &'a Value,
Decl: Option<&'a DIDescriptor>,
AlignInBits: u32)
- -> &'a DIGlobalVariable;
+ -> &'a DIGlobalVariableExpression;
pub fn LLVMRustDIBuilderCreateVariable(Builder: &DIBuilder<'a>,
Tag: c_uint,
/// inline it will only show the text message and not the text.
///
/// See `CodeSuggestion` for more information.
+ #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
self.suggestions.push(CodeSuggestion {
substitutions: vec![Substitution {
/// * may contain a name of a function, variable or type, but not whole expressions
///
/// See `CodeSuggestion` for more information.
+ #[deprecated(note = "Use `span_suggestion_with_applicability`")]
pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &mut Self {
self.suggestions.push(CodeSuggestion {
substitutions: vec![Substitution {
self
}
- pub fn multipart_suggestion(
+ pub fn multipart_suggestion_with_applicability(
&mut self,
msg: &str,
suggestion: Vec<(Span, String)>,
+ applicability: Applicability,
) -> &mut Self {
self.suggestions.push(CodeSuggestion {
substitutions: vec![Substitution {
}],
msg: msg.to_owned(),
show_code_when_inline: true,
- applicability: Applicability::Unspecified,
+ applicability,
});
self
}
+ #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
+ pub fn multipart_suggestion(
+ &mut self,
+ msg: &str,
+ suggestion: Vec<(Span, String)>,
+ ) -> &mut Self {
+ self.multipart_suggestion_with_applicability(
+ msg,
+ suggestion,
+ Applicability::Unspecified,
+ )
+ }
+
/// Prints out a message with multiple suggested edits of the code.
+ #[deprecated(note = "Use `span_suggestions_with_applicability`")]
pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec<String>) -> &mut Self {
self.suggestions.push(CodeSuggestion {
substitutions: suggestions.into_iter().map(|snippet| Substitution {
/// it easy to declare such methods on the builder.
macro_rules! forward {
// Forward pattern for &self -> &Self
- (pub fn $n:ident(&self, $($name:ident: $ty:ty),*) -> &Self) => {
+ (pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)*) -> &Self) => {
pub fn $n(&self, $($name: $ty),*) -> &Self {
+ #[allow(deprecated)]
self.diagnostic.$n($($name),*);
self
}
};
// Forward pattern for &mut self -> &mut Self
- (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => {
+ (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)*) -> &mut Self) => {
pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
+ #[allow(deprecated)]
self.diagnostic.$n($($name),*);
self
}
// Forward pattern for &mut self -> &mut Self, with S: Into<MultiSpan>
// type parameter. No obvious way to make this more generic.
- (pub fn $n:ident<S: Into<MultiSpan>>(&mut self, $($name:ident: $ty:ty),*) -> &mut Self) => {
+ (pub fn $n:ident<S: Into<MultiSpan>>(
+ &mut self,
+ $($name:ident: $ty:ty),*
+ $(,)*) -> &mut Self) => {
pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty),*) -> &mut Self {
+ #[allow(deprecated)]
self.diagnostic.$n($($name),*);
self
}
forward!(pub fn note_expected_found(&mut self,
label: &dyn fmt::Display,
expected: DiagnosticStyledString,
- found: DiagnosticStyledString)
- -> &mut Self);
+ found: DiagnosticStyledString,
+ ) -> &mut Self);
forward!(pub fn note_expected_found_extra(&mut self,
label: &dyn fmt::Display,
expected: DiagnosticStyledString,
found: DiagnosticStyledString,
expected_extra: &dyn fmt::Display,
- found_extra: &dyn fmt::Display)
- -> &mut Self);
+ found_extra: &dyn fmt::Display,
+ ) -> &mut Self);
forward!(pub fn note(&mut self, msg: &str) -> &mut Self);
forward!(pub fn span_note<S: Into<MultiSpan>>(&mut self,
sp: S,
- msg: &str)
- -> &mut Self);
+ msg: &str,
+ ) -> &mut Self);
forward!(pub fn warn(&mut self, msg: &str) -> &mut Self);
forward!(pub fn span_warn<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> &mut Self);
forward!(pub fn help(&mut self , msg: &str) -> &mut Self);
forward!(pub fn span_help<S: Into<MultiSpan>>(&mut self,
sp: S,
- msg: &str)
- -> &mut Self);
- forward!(pub fn span_suggestion_short(&mut self,
- sp: Span,
- msg: &str,
- suggestion: String)
- -> &mut Self);
+ msg: &str,
+ ) -> &mut Self);
+
+ #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
+ forward!(pub fn span_suggestion_short(
+ &mut self,
+ sp: Span,
+ msg: &str,
+ suggestion: String,
+ ) -> &mut Self);
+
+ #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
forward!(pub fn multipart_suggestion(
&mut self,
msg: &str,
- suggestion: Vec<(Span, String)>
+ suggestion: Vec<(Span, String)>,
) -> &mut Self);
+
+ #[deprecated(note = "Use `span_suggestion_with_applicability`")]
forward!(pub fn span_suggestion(&mut self,
sp: Span,
msg: &str,
- suggestion: String)
- -> &mut Self);
+ suggestion: String,
+ ) -> &mut Self);
+
+ #[deprecated(note = "Use `span_suggestions_with_applicability`")]
forward!(pub fn span_suggestions(&mut self,
sp: Span,
msg: &str,
- suggestions: Vec<String>)
- -> &mut Self);
+ suggestions: Vec<String>,
+ ) -> &mut Self);
+
+ pub fn multipart_suggestion_with_applicability(&mut self,
+ msg: &str,
+ suggestion: Vec<(Span, String)>,
+ applicability: Applicability,
+ ) -> &mut Self {
+ if !self.allow_suggestions {
+ return self
+ }
+ self.diagnostic.multipart_suggestion_with_applicability(
+ msg,
+ suggestion,
+ applicability,
+ );
+ self
+ }
+
pub fn span_suggestion_with_applicability(&mut self,
sp: Span,
msg: &str,
}
}
Err(err) => {
- info!("no metadata found: {}", err);
+ warn!("no metadata found: {}", err);
continue;
}
};
// created by `StorageDead` and at the beginning
// of a function.
} else {
+ // If we are found a use of a.b.c which was in error, then we want to look for
+ // moves not only of a.b.c but also a.b and a.
+ //
+ // Note that the moves data already includes "parent" paths, so we don't have to
+ // worry about the other case: that is, if there is a move of a.b.c, it is already
+ // marked as a move of a.b and a as well, so we will generate the correct errors
+ // there.
+ let mut mpis = vec![mpi];
+ let move_paths = &self.move_data.move_paths;
+ mpis.extend(move_paths[mpi].parents(move_paths));
+
for moi in &self.move_data.loc_map[l] {
debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi);
- if self.move_data.moves[*moi].path == mpi {
+ if mpis.contains(&self.move_data.moves[*moi].path) {
debug!("report_use_of_moved_or_uninitialized: found");
result.push(*moi);
use core::unicode::property::Pattern_White_Space;
use rustc::mir::*;
use rustc::ty;
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{DiagnosticBuilder,Applicability};
use syntax_pos::Span;
use borrow_check::MirBorrowckCtxt;
// expressions `a[b]`, which roughly desugar to
// `*Index::index(&a, b)` or
// `*IndexMut::index_mut(&mut a, b)`.
- err.span_suggestion(
+ err.span_suggestion_with_applicability(
span,
"consider removing the `*`",
snippet[1..].to_owned(),
+ Applicability::Unspecified,
);
} else {
- err.span_suggestion(
+ err.span_suggestion_with_applicability(
span,
"consider borrowing here",
format!("&{}", snippet),
+ Applicability::Unspecified,
);
}
suggestions.sort_unstable_by_key(|&(span, _, _)| span);
suggestions.dedup_by_key(|&mut (span, _, _)| span);
for (span, to_remove, suggestion) in suggestions {
- err.span_suggestion(
+ err.span_suggestion_with_applicability(
span,
&format!("consider removing the `{}`", to_remove),
- suggestion
+ suggestion,
+ Applicability::MachineApplicable,
);
}
}
use util::borrowck_errors::{BorrowckErrors, Origin};
use util::collect_writes::FindAssignments;
use util::suggest_ref_mut;
+use rustc_errors::Applicability;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(super) enum AccessKind {
assert_eq!(local_decl.mutability, Mutability::Not);
err.span_label(span, format!("cannot {ACT}", ACT = act));
- err.span_suggestion(
+ err.span_suggestion_with_applicability(
local_decl.source_info.span,
"consider changing this to be mutable",
format!("mut {}", local_decl.name.unwrap()),
+ Applicability::MachineApplicable,
);
}
_,
) = pat.node
{
- err.span_suggestion(
+ err.span_suggestion_with_applicability(
upvar_ident.span,
"consider changing this to be mutable",
format!("mut {}", upvar_ident.name),
+ Applicability::MachineApplicable,
);
}
}
};
if let Some((err_help_span, suggested_code)) = suggestion {
- err.span_suggestion(
+ err.span_suggestion_with_applicability(
err_help_span,
&format!("consider changing this to be a mutable {}", pointer_desc),
suggested_code,
+ Applicability::MachineApplicable,
);
}
pub place: Place<'tcx>,
}
+impl<'tcx> MovePath<'tcx> {
+ pub fn parents(&self, move_paths: &IndexVec<MovePathIndex, MovePath>) -> Vec<MovePathIndex> {
+ let mut parents = Vec::new();
+
+ let mut curr_parent = self.parent;
+ while let Some(parent_mpi) = curr_parent {
+ parents.push(parent_mpi);
+ curr_parent = move_paths[parent_mpi].parent;
+ }
+
+ parents
+ }
+}
+
impl<'tcx> fmt::Debug for MovePath<'tcx> {
fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
write!(w, "MovePath {{")?;
};
let ptr = base.ptr.ptr_offset(offset, self)?;
- let align = base.align.min(field_layout.align); // only use static information
+ let align = base.align
+ // We do not look at `base.layout.align` nor `field_layout.align`, unlike
+ // codegen -- mostly to see if we can get away with that
+ .restrict_for_offset(offset); // must be last thing that happens
Ok(MPlaceTy { mplace: MemPlace { ptr, align, extra }, layout: field_layout })
}
);
if let Ok(snippet) = self.session.source_map().span_to_snippet(span) {
- err.span_suggestion(
+ err.span_suggestion_with_applicability(
span, "consider adding parentheses", format!("({})", snippet),
+ Applicability::MachineApplicable,
);
}
use rustc::hir::{self, Node, Destination};
use syntax::ast;
use syntax_pos::Span;
+use errors::Applicability;
#[derive(Clone, Copy, Debug, PartialEq)]
enum LoopKind {
.span_label(e.span,
"can only break with a value inside \
`loop` or breakable block")
- .span_suggestion(e.span,
- &format!("instead, use `break` on its own \
- without a value inside this `{}` loop",
- kind.name()),
- "break".to_string())
+ .span_suggestion_with_applicability(
+ e.span,
+ &format!(
+ "instead, use `break` on its own \
+ without a value inside this `{}` loop",
+ kind.name()
+ ),
+ "break".to_string(),
+ Applicability::MaybeIncorrect,
+ )
.emit();
}
}
err.span_label(base_span,
"expecting a type here because of type ascription");
if line_sp != line_base_sp {
- err.span_suggestion_short(sp,
- "did you mean to use `;` here instead?",
- ";".to_string());
+ err.span_suggestion_short_with_applicability(
+ sp,
+ "did you mean to use `;` here instead?",
+ ";".to_string(),
+ Applicability::MaybeIncorrect,
+ );
}
break;
} else if snippet.trim().len() != 0 {
*candidate = format!("use {};\n{}", candidate, additional_newline);
}
- err.span_suggestions(span, &msg, path_strings);
+ err.span_suggestions_with_applicability(
+ span,
+ &msg,
+ path_strings,
+ Applicability::Unspecified,
+ );
} else {
let mut msg = msg;
msg.push(':');
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy, LldFlavor};
+use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy};
pub fn target() -> TargetResult {
let mut base = super::windows_msvc_base::opts();
// FIXME: this shouldn't be panic=abort, it should be panic=unwind
base.panic_strategy = PanicStrategy::Abort;
- base.linker = Some("rust-lld".to_owned());
Ok(Target {
llvm_target: "aarch64-pc-windows-msvc".to_string(),
target_os: "windows".to_string(),
target_env: "msvc".to_string(),
target_vendor: "pc".to_string(),
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Link),
+ linker_flavor: LinkerFlavor::Msvc,
options: base,
})
}
use super::FnCtxt;
-use errors::DiagnosticBuilder;
+use errors::{DiagnosticBuilder,Applicability};
use hir::def_id::DefId;
use lint;
use rustc::hir;
err.note("The type information given here is insufficient to check whether \
the pointer cast is valid");
if unknown_cast_to {
- err.span_suggestion_short(self.cast_span,
- "consider giving more type information",
- String::new());
+ err.span_suggestion_short_with_applicability(
+ self.cast_span,
+ "consider giving more type information",
+ String::new(),
+ Applicability::Unspecified,
+ );
}
err.emit();
}
if self.cast_ty.is_trait() {
match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) {
Ok(s) => {
- err.span_suggestion(self.cast_span,
- "try casting to a reference instead",
- format!("&{}{}", mtstr, s));
+ err.span_suggestion_with_applicability(
+ self.cast_span,
+ "try casting to a reference instead",
+ format!("&{}{}", mtstr, s),
+ Applicability::MachineApplicable,
+ );
}
Err(_) => {
span_help!(err, self.cast_span, "did you mean `&{}{}`?", mtstr, tstr)
ty::Adt(def, ..) if def.is_box() => {
match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) {
Ok(s) => {
- err.span_suggestion(self.cast_span,
- "try casting to a `Box` instead",
- format!("Box<{}>", s));
+ err.span_suggestion_with_applicability(
+ self.cast_span,
+ "try casting to a `Box` instead",
+ format!("Box<{}>", s),
+ Applicability::MachineApplicable,
+ );
}
Err(_) => span_help!(err, self.cast_span, "did you mean `Box<{}>`?", tstr),
}
.sig
.inputs()
.iter()
- .map(|ty| ArgKind::from_expected_ty(ty))
+ .map(|ty| ArgKind::from_expected_ty(ty, None))
.collect();
let (closure_span, found_args) = self.get_fn_like_arguments(expr_map_node);
let expected_span = expected_sig.cause_span.unwrap_or(closure_span);
use rustc::ty::error::{ExpectedFound, TypeError};
use rustc::ty::subst::{Subst, Substs};
use rustc::util::common::ErrorReported;
+use errors::Applicability;
use syntax_pos::Span;
if let Some(trait_err_span) = trait_err_span {
if let Ok(trait_err_str) = tcx.sess.source_map().
span_to_snippet(trait_err_span) {
- diag.span_suggestion(
+ diag.span_suggestion_with_applicability(
impl_err_span,
"consider change the type to match the mutability in trait",
format!("{}", trait_err_str),
+ Applicability::MachineApplicable,
);
}
}
.span_to_snippet(trait_m.generics.span)
.ok()?;
- err.multipart_suggestion(
+ err.multipart_suggestion_with_applicability(
"try changing the `impl Trait` argument to a generic parameter",
vec![
// replace `impl Trait` with `T`
// of the generics, but it works for the common case
(generics_span, new_generics),
],
+ Applicability::MaybeIncorrect,
);
Some(())
})();
.span_to_snippet(bounds)
.ok()?;
- err.multipart_suggestion(
+ err.multipart_suggestion_with_applicability(
"try removing the generic parameter and using `impl Trait` instead",
vec![
// delete generic parameters
// replace param usage with `impl Trait`
(span, format!("impl {}", bounds)),
],
+ Applicability::MaybeIncorrect,
);
Some(())
})();
let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr));
let suggestions = compatible_variants.iter()
.map(|v| format!("{}({})", v, expr_text)).collect::<Vec<_>>();
- err.span_suggestions(expr.span,
- "try using a variant of the expected type",
- suggestions);
+ err.span_suggestions_with_applicability(
+ expr.span,
+ "try using a variant of the expected type",
+ suggestions,
+ Applicability::MaybeIncorrect,
+ );
}
}
"a method with this name may be added to the standard library in the future",
);
- // FIXME: This should be a `span_suggestion` instead of `help`. However `self.span` only
+ // FIXME: This should be a `span_suggestion_with_applicability` instead of `help`
+ // However `self.span` only
// highlights the method name, so we can't use it. Also consider reusing the code from
// `report_method_error()`.
diag.help(&format!(
let snippet = tcx.sess.source_map().span_to_snippet(lit.span)
.unwrap_or("<numeric literal>".to_string());
- err.span_suggestion(lit.span,
+ err.span_suggestion_with_applicability(
+ lit.span,
&format!("you must specify a concrete type for \
this numeric value, like `{}`",
concrete_type),
format!("{}_{}",
snippet,
- concrete_type));
+ concrete_type),
+ Applicability::MaybeIncorrect,
+ );
}
hir::ExprKind::Path(ref qpath) => { // local binding
if let &hir::QPath::Resolved(_, ref path) = &qpath {
ty,
..
})) => {
- err.span_suggestion(
+ err.span_suggestion_with_applicability(
// account for `let x: _ = 42;`
// ^^^^
span.to(ty.as_ref().map(|ty| ty.span)
.unwrap_or(span)),
&msg,
format!("{}: {}", snippet, concrete_type),
+ Applicability::MaybeIncorrect,
);
}
_ => {
format!("use {};\n{}", self.tcx.item_path_str(*did), additional_newline)
}).collect();
- err.span_suggestions(span, &msg, path_strings);
+ err.span_suggestions_with_applicability(
+ span,
+ &msg,
+ path_strings,
+ Applicability::MaybeIncorrect,
+ );
} else {
let limit = if candidates.len() == 5 { 5 } else { 4 };
for (i, trait_did) in candidates.iter().take(limit).enumerate() {
}
};
}
+ ty::Array(_, len) => {
+ if let (Some(len), Ok(user_index)) = (
+ len.assert_usize(self.tcx),
+ field.as_str().parse::<u64>()
+ ) {
+ let base = self.tcx.hir.node_to_pretty_string(base.id);
+ let help = "instead of using tuple indexing, use array indexing";
+ let suggestion = format!("{}[{}]", base, field);
+ let applicability = if len < user_index {
+ Applicability::MachineApplicable
+ } else {
+ Applicability::MaybeIncorrect
+ };
+ err.span_suggestion_with_applicability(
+ expr.span, help, suggestion, applicability
+ );
+ }
+ }
ty::RawPtr(..) => {
let base = self.tcx.hir.node_to_pretty_string(base.id);
let msg = format!("`{}` is a native pointer; try dereferencing it", base);
let suggestion = format!("(*{}).{}", base, field);
- err.span_suggestion(field.span, &msg, suggestion);
+ err.span_suggestion_with_applicability(
+ field.span,
+ &msg,
+ suggestion,
+ Applicability::MaybeIncorrect,
+ );
}
_ => {}
}
found: Ty<'tcx>,
) {
if let Some((sp, msg, suggestion)) = self.check_ref(expr, found, expected) {
- err.span_suggestion(sp, msg, suggestion);
+ err.span_suggestion_with_applicability(
+ sp,
+ msg,
+ suggestion,
+ Applicability::MachineApplicable,
+ );
} else if !self.check_for_cast(err, expr, found, expected) {
let methods = self.get_conversion_methods(expr.span, expected, found);
if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
}
}) .collect::<Vec<_>>();
if !suggestions.is_empty() {
- err.span_suggestions(expr.span, "try using a conversion method", suggestions);
+ err.span_suggestions_with_applicability(
+ expr.span,
+ "try using a conversion method",
+ suggestions,
+ Applicability::MaybeIncorrect,
+ );
}
}
}
use rustc::ty::TyKind::{Ref, Adt, Str, Uint, Never, Tuple, Char, Array};
use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc::infer::type_variable::TypeVariableOrigin;
-use errors;
+use errors::{self,Applicability};
use syntax_pos::Span;
use syntax::ast::Ident;
use rustc::hir;
err.span_label(expr.span,
"`+` can't be used to concatenate two `&str` strings");
match source_map.span_to_snippet(lhs_expr.span) {
- Ok(lstring) => err.span_suggestion(lhs_expr.span,
- msg,
- format!("{}.to_owned()", lstring)),
+ Ok(lstring) => err.span_suggestion_with_applicability(
+ lhs_expr.span,
+ msg,
+ format!("{}.to_owned()", lstring),
+ Applicability::MachineApplicable,
+ ),
_ => err.help(msg),
};
}
is_assign,
) {
(Ok(l), Ok(r), false) => {
- err.multipart_suggestion(msg, vec![
- (lhs_expr.span, format!("{}.to_owned()", l)),
- (rhs_expr.span, format!("&{}", r)),
- ]);
+ err.multipart_suggestion_with_applicability(
+ msg,
+ vec![
+ (lhs_expr.span, format!("{}.to_owned()", l)),
+ (rhs_expr.span, format!("&{}", r)),
+ ],
+ Applicability::MachineApplicable,
+ );
}
_ => {
err.help(msg);
assert_eq!(2+2, 4);
}".to_string();
let output = make_test(input, None, false, &opts);
- assert_eq!(output, (expected.clone(), 2));
+ assert_eq!(output, (expected, 2));
}
#[test]
assert_eq!(2+2, 4);
}".to_string();
let output = make_test(input, None, false, &opts);
- assert_eq!(output, (expected.clone(), 2));
+ assert_eq!(output, (expected, 2));
}
#[test]
//Ceci n'est pas une `fn main`
assert_eq!(2+2, 4);".to_string();
let output = make_test(input, None, true, &opts);
- assert_eq!(output, (expected.clone(), 1));
+ assert_eq!(output, (expected, 1));
}
#[test]
assert_eq!(2+2, 4);
}".to_string();
let output = make_test(input, None, false, &opts);
- assert_eq!(output, (expected.clone(), 1));
+ assert_eq!(output, (expected, 1));
}
}
f64::tanh(n as f64) as f32
}
-// Right now all these functions, the f64 version of the functions above, all
-// shell out to random names. These names aren't actually defined anywhere, per
-// se, but we need this to compile somehow.
-//
-// The idea with this is that when you're using wasm then, for now, we have no
-// way of providing an implementation of these which delegates to a "correct"
-// implementation. For example most wasm applications probably just want to
-// delegate to the javascript `Math` object and its related functions, but wasm
-// doesn't currently have the ability to seamlessly do that (when you
-// instantiate a module you have to set that up).
-//
-// As a result these are just defined here with "hopefully helpful" names. The
-// symbols won't ever be needed or show up unless these functions are called,
-// and hopefully when they're called the errors are self-explanatory enough to
-// figure out what's going on.
-
+// These symbols are all defined in `compiler-builtins`
extern {
- #[link_name = "Math_acos"]
pub fn acos(n: f64) -> f64;
- #[link_name = "Math_asin"]
pub fn asin(n: f64) -> f64;
- #[link_name = "Math_atan"]
pub fn atan(n: f64) -> f64;
- #[link_name = "Math_atan2"]
pub fn atan2(a: f64, b: f64) -> f64;
- #[link_name = "Math_cbrt"]
pub fn cbrt(n: f64) -> f64;
- #[link_name = "Math_cosh"]
pub fn cosh(n: f64) -> f64;
- #[link_name = "Math_expm1"]
pub fn expm1(n: f64) -> f64;
pub fn fdim(a: f64, b: f64) -> f64;
- #[link_name = "Math_log1p"]
pub fn log1p(n: f64) -> f64;
- #[link_name = "Math_sinh"]
pub fn sinh(n: f64) -> f64;
- #[link_name = "Math_tan"]
pub fn tan(n: f64) -> f64;
- #[link_name = "Math_tanh"]
pub fn tanh(n: f64) -> f64;
- #[link_name = "Math_hypot"]
pub fn hypot(x: f64, y: f64) -> f64;
}
match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
Ok(_) => {}
Err(NOTIFIED) => {
- thread.inner.state.store(EMPTY, SeqCst);
+ // We must read here, even though we know it will be `NOTIFIED`.
+ // This is because `unpark` may have been called again since we read
+ // `NOTIFIED` in the `compare_exchange` above. We must perform an
+ // acquire operation that synchronizes with that `unpark` to observe
+ // any writes it made before the call to unpark. To do that we must
+ // read from the write it made to `state`.
+ let old = thread.inner.state.swap(EMPTY, SeqCst);
+ assert_eq!(old, NOTIFIED, "park state changed unexpectedly");
return;
} // should consume this notification, so prohibit spurious wakeups in next park.
Err(_) => panic!("inconsistent park state"),
match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
Ok(_) => {}
Err(NOTIFIED) => {
- thread.inner.state.store(EMPTY, SeqCst);
+ // We must read again here, see `park`.
+ let old = thread.inner.state.swap(EMPTY, SeqCst);
+ assert_eq!(old, NOTIFIED, "park state changed unexpectedly");
return;
} // should consume this notification, so prohibit spurious wakeups in next park.
Err(_) => panic!("inconsistent park_timeout state"),
/// [park]: fn.park.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn unpark(&self) {
- loop {
- match self.inner.state.compare_exchange(EMPTY, NOTIFIED, SeqCst, SeqCst) {
- Ok(_) => return, // no one was waiting
- Err(NOTIFIED) => return, // already unparked
- Err(PARKED) => {} // gotta go wake someone up
- _ => panic!("inconsistent state in unpark"),
- }
-
- // Coordinate wakeup through the mutex and a condvar notification
- let _lock = self.inner.lock.lock().unwrap();
- match self.inner.state.compare_exchange(PARKED, NOTIFIED, SeqCst, SeqCst) {
- Ok(_) => return self.inner.cvar.notify_one(),
- Err(NOTIFIED) => return, // a different thread unparked
- Err(EMPTY) => {} // parked thread went away, try again
- _ => panic!("inconsistent state in unpark"),
- }
+ // To ensure the unparked thread will observe any writes we made
+ // before this call, we must perform a release operation that `park`
+ // can synchronize with. To do that we must write `NOTIFIED` even if
+ // `state` is already `NOTIFIED`. That is why this must be a swap
+ // rather than a compare-and-swap that returns if it reads `NOTIFIED`
+ // on failure.
+ match self.inner.state.swap(NOTIFIED, SeqCst) {
+ EMPTY => return, // no one was waiting
+ NOTIFIED => return, // already unparked
+ PARKED => {} // gotta go wake someone up
+ _ => panic!("inconsistent state in unpark"),
}
+
+ // Coordinate wakeup through the mutex and a condvar notification
+ let _lock = self.inner.lock.lock().unwrap();
+ self.inner.cvar.notify_one()
}
/// Gets the thread's unique identifier.
use edition::Edition;
use parse::{token, ParseSess};
use OneVector;
+use errors::Applicability;
use ptr::P;
let error = |span, msg, suggestion: &str| {
let mut err = self.sess.span_diagnostic.struct_span_err(span, msg);
if !suggestion.is_empty() {
- err.span_suggestion(span, "expected syntax is", suggestion.into());
+ err.span_suggestion_with_applicability(
+ span,
+ "expected syntax is",
+ suggestion.into(),
+ Applicability::MaybeIncorrect,
+ );
}
err.emit();
true
use std::collections::hash_map::Entry;
use rustc_data_structures::sync::Lrc;
+use errors::Applicability;
pub struct ParserAnyMacro<'a> {
parser: Parser<'a>,
if comma_span == DUMMY_SP {
err.note("you might be missing a comma");
} else {
- err.span_suggestion_short(
+ err.span_suggestion_short_with_applicability(
comma_span,
"missing comma here",
", ".to_string(),
+ Applicability::MachineApplicable,
);
}
}
if self.token == token::CloseDelim(token::Brace) {
// If the struct looks otherwise well formed, recover and continue.
if let Some(sp) = comma_sp {
- err.span_suggestion_short(sp, "remove this comma", String::new());
+ err.span_suggestion_short_with_applicability(
+ sp,
+ "remove this comma",
+ String::new(),
+ Applicability::MachineApplicable,
+ );
}
err.emit();
break;
));
}
if suggestions.len() > 0 {
- diag.multipart_suggestion(
+ diag.multipart_suggestion_with_applicability(
"format specifiers use curly braces",
suggestions,
+ Applicability::MachineApplicable,
);
}
}};
-Subproject commit 5a081f0363340dd895d0958955d0c84661f60f05
+Subproject commit caddcd9b9dc9479a20908d93c3e47c49b021379e
# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime.
-2018-09-11
+2018-09-16
--- /dev/null
+// issue #53712: make the error generated by using tuple indexing on an array more specific
+
+fn main() {
+ let arr = [10, 20, 30, 40, 50];
+ arr.0;
+ //~^ ERROR no field `0` on type `[{integer}; 5]` [E0609]
+ //~| HELP instead of using tuple indexing, use array indexing
+ //~| SUGGESTION arr[0]
+}
--- /dev/null
+error[E0609]: no field `0` on type `[{integer}; 5]`
+ --> $DIR/issue-53712.rs:5:9
+ |
+LL | arr.0;
+ | ----^
+ | |
+ | help: instead of using tuple indexing, use array indexing: `arr[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+struct A {
+ b: B,
+}
+
+#[derive(Clone)]
+struct B;
+
+fn foo(_: A) {}
+
+fn bar(mut a: A) -> B {
+ a.b = B;
+ foo(a);
+ a.b.clone()
+}
+
+fn main() {}
--- /dev/null
+error[E0382]: borrow of moved value: `a.b`
+ --> $DIR/issue-52669.rs:25:5
+ |
+LL | foo(a);
+ | - value moved here
+LL | a.b.clone()
+ | ^^^ value borrowed here after move
+ |
+ = note: move occurs because `a` has type `A`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+fn main() {
+ let x = (vec![1, 2, 3], );
+ drop(x.0);
+ drop(x);
+}
--- /dev/null
+error[E0382]: use of moved value: `x`
+ --> $DIR/move-subpaths-moves-root.rs:16:10
+ |
+LL | drop(x.0);
+ | --- value moved here
+LL | drop(x);
+ | ^ value used here after move
+ |
+ = note: move occurs because `x.0` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.