"tools/rls",
]
+# Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit
+# MSVC when running the compile-fail test suite when a should-fail test panics.
+# But hey if this is removed and it gets past the bots, sounds good to me.
+[profile.release]
+opt-level = 2
+[profile.bench]
+opt-level = 2
+
# These options are controlled from our rustc wrapper script, so turn them off
# here and have them controlled elsewhere.
[profile.dev]
pub backtrace: bool, // support for RUST_BACKTRACE
// misc
+ pub low_priority: bool,
pub channel: String,
pub quiet_tests: bool,
// Fallback musl-root for all targets
target: Vec<String>,
cargo: Option<String>,
rustc: Option<String>,
+ low_priority: Option<bool>,
compiler_docs: Option<bool>,
docs: Option<bool>,
submodules: Option<bool>,
config.nodejs = build.nodejs.map(PathBuf::from);
config.gdb = build.gdb.map(PathBuf::from);
config.python = build.python.map(PathBuf::from);
+ set(&mut config.low_priority, build.low_priority);
set(&mut config.compiler_docs, build.compiler_docs);
set(&mut config.docs, build.docs);
set(&mut config.submodules, build.submodules);
# known-good version of OpenSSL, compile it, and link it to Cargo.
#openssl-static = false
+# Run the build with low priority, by setting the process group's "nice" value
+# to +10 on Unix platforms, and by using a "low priority" job object on Windows.
+#low-priority = false
+
# =============================================================================
# General install configuration options
# =============================================================================
use std::env;
use std::io;
use std::mem;
+use Build;
type HANDLE = *mut u8;
type BOOL = i32;
const PROCESS_DUP_HANDLE: DWORD = 0x40;
const JobObjectExtendedLimitInformation: JOBOBJECTINFOCLASS = 9;
const JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE: DWORD = 0x2000;
+const JOB_OBJECT_LIMIT_PRIORITY_CLASS: DWORD = 0x00000020;
const SEM_FAILCRITICALERRORS: UINT = 0x0001;
const SEM_NOGPFAULTERRORBOX: UINT = 0x0002;
+const BELOW_NORMAL_PRIORITY_CLASS: DWORD = 0x00004000;
extern "system" {
fn CreateJobObjectW(lpJobAttributes: *mut u8, lpName: *const u8) -> HANDLE;
SchedulingClass: DWORD,
}
-pub unsafe fn setup() {
+pub unsafe fn setup(build: &mut Build) {
// Tell Windows to not show any UI on errors (such as not finding a required dll
// during startup or terminating abnormally). This is important for running tests,
// since some of them use abnormal termination by design.
// children will reside in the job by default.
let mut info = mem::zeroed::<JOBOBJECT_EXTENDED_LIMIT_INFORMATION>();
info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+ if build.config.low_priority {
+ info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS;
+ info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
+ }
let r = SetInformationJobObject(job,
JobObjectExtendedLimitInformation,
&mut info as *mut _ as LPVOID,
extern crate rustc_serialize;
extern crate toml;
+#[cfg(unix)]
+extern crate libc;
+
use std::cmp;
use std::collections::HashMap;
use std::env;
#[cfg(windows)]
mod job;
-#[cfg(not(windows))]
+#[cfg(unix)]
+mod job {
+ use libc;
+
+ pub unsafe fn setup(build: &mut ::Build) {
+ if build.config.low_priority {
+ libc::setpriority(libc::PRIO_PGRP as _, 0, 10);
+ }
+ }
+}
+
+#[cfg(not(any(unix, windows)))]
mod job {
- pub unsafe fn setup() {}
+ pub unsafe fn setup(_build: &mut ::Build) {
+ }
}
pub use config::Config;
/// output in the "stageN-rustc" directory.
Librustc,
- /// This cargo is going to some build tool, placing output in the
+ /// This cargo is going to build some tool, placing output in the
/// "stageN-tools" directory.
Tool,
}
/// Executes the entire build, as configured by the flags and configuration.
pub fn build(&mut self) {
unsafe {
- job::setup();
+ job::setup(self);
}
if let Subcommand::Clean = self.flags.cmd {
.env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_libdir(compiler));
}
- // There are two invariants we try must maintain:
+ // There are two invariants we must maintain:
// * stable crates cannot depend on unstable crates (general Rust rule),
// * crates that end up in the sysroot must be unstable (rustbuild rule).
//
// feature and opt-in to `rustc_private`.
//
// We can't always pass `rustbuild` because crates which are outside of
- // the comipiler, libs, and tests are stable and we don't want to make
+ // the compiler, libs, and tests are stable and we don't want to make
// their deps unstable (since this would break the first invariant
// above).
//
}
// Ignore incremental modes except for stage0, since we're
- // not guaranteeing correctness acros builds if the compiler
+ // not guaranteeing correctness across builds if the compiler
// is changing under your feet.`
if self.flags.incremental && compiler.stage == 0 {
let incr_dir = self.incremental_dir(compiler);
cargo.env_remove("MAKEFLAGS");
}
- // Environment variables *required* needed throughout the build
+ // Environment variables *required* throughout the build
//
// FIXME: should update code to not require this env var
cargo.env("CFG_COMPILER_HOST_TRIPLE", target);
}
/// Returns the root output directory for all Cargo output in a given stage,
- /// running a particular comipler, wehther or not we're building the
+ /// running a particular compiler, wehther or not we're building the
/// standard library, and targeting the specified architecture.
fn cargo_out(&self,
compiler: &Compiler,
- [link_llvm_intrinsics](language-features/link-llvm-intrinsics.md)
- [linkage](language-features/linkage.md)
- [log_syntax](language-features/log-syntax.md)
- - [loop_break_value](language-features/loop-break-value.md)
- [macro_reexport](language-features/macro-reexport.md)
- [macro_vis_matcher](language-features/macro-vis-matcher.md)
- [main](language-features/main.md)
- [alloc](library-features/alloc.md)
- [as_c_str](library-features/as-c-str.md)
- [ascii_ctype](library-features/ascii-ctype.md)
- - [binary_heap_peek_mut_pop](library-features/binary-heap-peek-mut-pop.md)
- [box_heap](library-features/box-heap.md)
- [c_void_variant](library-features/c-void-variant.md)
- [char_escape_debug](library-features/char-escape-debug.md)
- [panic_abort](library-features/panic-abort.md)
- [panic_unwind](library-features/panic-unwind.md)
- [pattern](library-features/pattern.md)
- - [peek](library-features/peek.md)
- [placement_in](library-features/placement-in.md)
- [placement_new_protocol](library-features/placement-new-protocol.md)
- [print_internals](library-features/print-internals.md)
- [proc_macro_internals](library-features/proc-macro-internals.md)
- - [process_try_wait](library-features/process-try-wait.md)
- [question_mark_carrier](library-features/question-mark-carrier.md)
- [rand](library-features/rand.md)
- [range_contains](library-features/range-contains.md)
- [raw](library-features/raw.md)
- - [retain_hash_collection](library-features/retain-hash-collection.md)
- [reverse_cmp_key](library-features/reverse-cmp-key.md)
- [rt](library-features/rt.md)
- [rustc_private](library-features/rustc-private.md)
------------------------
+At present, literals are only accepted as the value of a key-value pair in
+attributes. What's more, only _string_ literals are accepted. This means that
+literals can only appear in forms of `#[attr(name = "value")]` or
+`#[attr = "value"]`.
+The `attr_literals` unstable feature allows other types of literals to be used
+in attributes. Here are some examples of attributes that can now be used with
+this feature enabled:
+
++```rust,ignore
++#[attr]
++#[attr(true)]
++#[attr(ident)]
++#[attr(ident, 100, true, "true", ident = 100, ident = "hello", ident(100))]
++#[attr(100)]
++#[attr(enabled = true)]
++#[enabled(true)]
++#[attr("hello")]
++#[repr(C, align = 4)]
++#[repr(C, align(4))]
++```
[#31436]: https://github.com/rust-lang/rust/issues/31436
------------------------
+
+The `catch_expr` feature adds support for a `catch` expression. The `catch`
+expression creates a new scope one can use the `?` operator in.
+
+```rust
+#![feature(catch_expr)]
+
+use std::num::ParseIntError;
+
+let result: Result<i32, ParseIntError> = do catch {
+ Ok("1".parse::<i32>()?
+ + "2".parse::<i32>()?
+ + "3".parse::<i32>()?)
+};
+assert_eq!(result, Ok(6));
+
+let result: Result<i32, ParseIntError> = do catch {
+ Ok("1".parse::<i32>()?
+ + "foo".parse::<i32>()?
+ + "3".parse::<i32>()?)
+};
+assert!(result.is_err());
+```
+++ /dev/null
-# `loop_break_value`
-
-The tracking issue for this feature is: [#37339]
-
-[#37339]: https://github.com/rust-lang/rust/issues/37339
-
-Documentation to be appended to section G of the book.
-
-------------------------
-
-### Loops as expressions
-
-Like most things in Rust, loops are expressions, and have a value; normally `()` unless the loop
-never exits.
-A `loop` can instead evaluate to a useful value via *break with value*:
-
-```rust
-#![feature(loop_break_value)]
-
-// Find the first square number over 1000:
-let mut n = 1;
-let square = loop {
- if n * n > 1000 {
- break n * n;
- }
- n += 1;
-};
-```
-
-The evaluation type may be specified externally:
-
-```rust
-#![feature(loop_break_value)]
-
-// Declare that value returned is unsigned 64-bit:
-let n: u64 = loop {
- break 1;
-};
-```
-
-It is an error if types do not agree, either between a "break" value and an external requirement,
-or between multiple "break" values:
-
-```no_compile
-#![feature(loop_break_value)]
-
-loop {
- if true {
- break 1u32;
- } else {
- break 0u8; // error: types do not agree
- }
-};
-
-let n: i32 = loop {
- break 0u32; // error: type does not agree with external requirement
-};
-```
-
-#### Break: label, value
-
-Four forms of `break` are available, where EXPR is some expression which evaluates to a value:
-
-1. `break;`
-2. `break 'label;`
-3. `break EXPR;`
-4. `break 'label EXPR;`
-
-When no value is given, the value `()` is assumed, thus `break;` is equivalent to `break ();`.
-
-Using a label allows returning a value from an inner loop:
-
-```rust
-#![feature(loop_break_value)]
-
-let result = 'outer: loop {
- for n in 1..10 {
- if n > 4 {
- break 'outer n;
- }
- }
-};
-```
------------------------
+The `on_unimplemented` feature provides the `#[rustc_on_unimplemented]`
+attribute, which allows trait definitions to add specialized notes to error
+messages when an implementation was expected but not found.
+For example:
+
+```rust,compile_fail
+#![feature(on_unimplemented)]
+
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an \
+ iterator over elements of type `{A}`"]
+trait MyIterator<A> {
+ fn next(&mut self) -> A;
+}
+
+fn iterate_chars<I: MyIterator<char>>(i: I) {
+ // ...
+}
+
+fn main() {
+ iterate_chars(&[1, 2, 3][..]);
+}
+```
+
+When the user compiles this, they will see the following;
+
+```txt
+error[E0277]: the trait bound `&[{integer}]: MyIterator<char>` is not satisfied
+ --> <anon>:14:5
+ |
+14 | iterate_chars(&[1, 2, 3][..]);
+ | ^^^^^^^^^^^^^ the trait `MyIterator<char>` is not implemented for `&[{integer}]`
+ |
+ = note: a collection of type `&[{integer}]` cannot be built from an iterator over elements of type `char`
+ = note: required by `iterate_chars`
+
+error: aborting due to previous error
+```
+++ /dev/null
-# `binary_heap_peek_mut_pop`
-
-The tracking issue for this feature is: [#38863]
-
-[#38863]: https://github.com/rust-lang/rust/issues/38863
-
-------------------------
--- /dev/null
+# `needs_drop`
+
+The tracking issue for this feature is: [#41890]
+
+[#41890]: https://github.com/rust-lang/rust/issues/41890
+
+------------------------
+++ /dev/null
-# `peek`
-
-The tracking issue for this feature is: [#38980]
-
-[#38980]: https://github.com/rust-lang/rust/issues/38980
-
-------------------------
+++ /dev/null
-# `process_try_wait`
-
-The tracking issue for this feature is: [#38903]
-
-[#38903]: https://github.com/rust-lang/rust/issues/38903
-
-------------------------
+++ /dev/null
-# `retain_hash_collection`
-
-The tracking issue for this feature is: [#36648]
-
-[#36648]: https://github.com/rust-lang/rust/issues/36648
-
-------------------------
}
}
-#[stable(feature = "boxed_str_conv", since = "1.18.0")]
+#[stable(feature = "boxed_str_conv", since = "1.19.0")]
impl From<Box<str>> for Box<[u8]> {
fn from(s: Box<str>) -> Self {
unsafe {
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![feature(generic_param_attrs)]
+#![feature(needs_drop)]
#![cfg_attr(stage0, feature(staged_api))]
#![cfg_attr(test, feature(test))]
unsafe fn destroy(&mut self, len: usize) {
// The branch on needs_drop() is an -O1 performance optimization.
// Without the branch, dropping TypedArena<u8> takes linear time.
- if intrinsics::needs_drop::<T>() {
+ if mem::needs_drop::<T>() {
let mut start = self.start();
// Destroy all allocated objects.
for _ in 0..len {
#[inline]
pub fn alloc<T>(&self, object: T) -> &mut T {
unsafe {
- assert!(!intrinsics::needs_drop::<T>());
+ assert!(!mem::needs_drop::<T>());
assert!(mem::size_of::<T>() != 0);
self.align_for::<T>();
#[inline]
pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
where T: Copy {
- unsafe {
- assert!(!intrinsics::needs_drop::<T>());
- }
+ assert!(!mem::needs_drop::<T>());
assert!(mem::size_of::<T>() != 0);
assert!(slice.len() != 0);
self.align_for::<T>();
impl<'a, T: Ord> PeekMut<'a, T> {
/// Removes the peeked value from the heap and returns it.
- #[unstable(feature = "binary_heap_peek_mut_pop", issue = "38863")]
+ #[stable(feature = "binary_heap_peek_mut_pop", since = "1.18.0")]
pub fn pop(mut this: PeekMut<'a, T>) -> T {
let value = this.heap.pop().unwrap();
this.sift = false;
/// Converts `self` into a vector without clones or allocation.
///
+ /// The resulting vector can be converted back into a box via
+ /// `Vec<T>`'s `into_boxed_slice` method.
+ ///
/// # Examples
///
/// ```
}
}
-#[stable(feature = "derefmut_for_string", since = "1.2.0")]
+#[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::Range<usize>> for String {
#[inline]
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
&mut self[..][index]
}
}
-#[stable(feature = "derefmut_for_string", since = "1.2.0")]
+#[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::RangeTo<usize>> for String {
#[inline]
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
&mut self[..][index]
}
}
-#[stable(feature = "derefmut_for_string", since = "1.2.0")]
+#[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::RangeFrom<usize>> for String {
#[inline]
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
&mut self[..][index]
}
}
-#[stable(feature = "derefmut_for_string", since = "1.2.0")]
+#[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::RangeFull> for String {
#[inline]
fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
}
}
-#[stable(feature = "derefmut_for_string", since = "1.2.0")]
+#[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::DerefMut for String {
#[inline]
fn deref_mut(&mut self) -> &mut str {
// note: test pulls in libstd, which causes errors here
#[cfg(not(test))]
-#[stable(feature = "string_from_box", since = "1.17.0")]
+#[stable(feature = "string_from_box", since = "1.18.0")]
impl From<Box<str>> for String {
fn from(s: Box<str>) -> String {
s.into_string()
}
}
-#[stable(feature = "box_from_str", since = "1.17.0")]
+#[stable(feature = "box_from_str", since = "1.18.0")]
impl Into<Box<str>> for String {
fn into(self) -> Box<str> {
self.into_boxed_str()
#![deny(warnings)]
-#![feature(binary_heap_peek_mut_pop)]
#![feature(box_syntax)]
#![feature(inclusive_range_syntax)]
#![feature(collection_placement)]
}
}
-#[stable(feature = "vec_from_mut", since = "1.21.0")]
+#[stable(feature = "vec_from_mut", since = "1.19.0")]
impl<'a, T: Clone> From<&'a mut [T]> for Vec<T> {
#[cfg(not(test))]
fn from(s: &'a mut [T]) -> Vec<T> {
// note: test pulls in libstd, which causes errors here
#[cfg(not(test))]
-#[stable(feature = "vec_from_box", since = "1.17.0")]
+#[stable(feature = "vec_from_box", since = "1.18.0")]
impl<T> From<Box<[T]>> for Vec<T> {
fn from(s: Box<[T]>) -> Vec<T> {
s.into_vec()
}
}
-#[stable(feature = "box_from_vec", since = "1.17.0")]
+#[stable(feature = "box_from_vec", since = "1.18.0")]
impl<T> Into<Box<[T]>> for Vec<T> {
fn into(self) -> Box<[T]> {
self.into_boxed_slice()
// Clone-on-write
////////////////////////////////////////////////////////////////////////////////
-#[stable(feature = "cow_from_vec", since = "1.7.0")]
+#[stable(feature = "cow_from_vec", since = "1.8.0")]
impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> {
fn from(s: &'a [T]) -> Cow<'a, [T]> {
Cow::Borrowed(s)
}
}
-#[stable(feature = "cow_from_vec", since = "1.7.0")]
+#[stable(feature = "cow_from_vec", since = "1.8.0")]
impl<'a, T: Clone> From<Vec<T>> for Cow<'a, [T]> {
fn from(v: Vec<T>) -> Cow<'a, [T]> {
Cow::Owned(v)
}
}
-#[stable(feature = "unsafe_cell_default", since = "1.9.0")]
+#[stable(feature = "unsafe_cell_default", since = "1.10.0")]
impl<T: Default> Default for UnsafeCell<T> {
/// Creates an `UnsafeCell`, with the `Default` value for T.
fn default() -> UnsafeCell<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Skip<I> where I: ExactSizeIterator {}
-#[stable(feature = "double_ended_skip_iterator", since = "1.8.0")]
+#[stable(feature = "double_ended_skip_iterator", since = "1.9.0")]
impl<I> DoubleEndedIterator for Skip<I> where I: DoubleEndedIterator + ExactSizeIterator {
fn next_back(&mut self) -> Option<Self::Item> {
if self.len() > 0 {
unsafe { intrinsics::min_align_of_val(val) }
}
+/// Returns whether dropping values of type `T` matters.
+///
+/// This is purely an optimization hint, and may be implemented conservatively.
+/// For instance, always returning `true` would be a valid implementation of
+/// this function.
+///
+/// Low level implementations of things like collections, which need to manually
+/// drop their data, should use this function to avoid unnecessarily
+/// trying to drop all their contents when they are destroyed. This might not
+/// make a difference in release builds (where a loop that has no side-effects
+/// is easily detected and eliminated), but is often a big win for debug builds.
+///
+/// Note that `ptr::drop_in_place` already performs this check, so if your workload
+/// can be reduced to some small number of drop_in_place calls, using this is
+/// unnecessary. In particular note that you can drop_in_place a slice, and that
+/// will do a single needs_drop check for all the values.
+///
+/// Types like Vec therefore just `drop_in_place(&mut self[..])` without using
+/// needs_drop explicitly. Types like HashMap, on the other hand, have to drop
+/// values one at a time and should use this API.
+///
+///
+/// # Examples
+///
+/// Here's an example of how a collection might make use of needs_drop:
+///
+/// ```ignore
+/// #![feature(needs_drop)]
+/// use std::{mem, ptr};
+///
+/// pub struct MyCollection<T> { /* ... */ }
+///
+/// impl<T> Drop for MyCollection<T> {
+/// fn drop(&mut self) {
+/// unsafe {
+/// // drop the data
+/// if mem::needs_drop::<T>() {
+/// for x in self.iter_mut() {
+/// ptr::drop_in_place(x);
+/// }
+/// }
+/// self.free_buffer();
+/// }
+/// }
+/// }
+/// ```
+#[inline]
+#[unstable(feature = "needs_drop", issue = "41890")]
+pub fn needs_drop<T>() -> bool {
+ unsafe { intrinsics::needs_drop::<T>() }
+}
+
/// Creates a value whose bytes are all zero.
///
/// This has the same effect as allocating space with
// Conversions T -> T are covered by a blanket impl and therefore excluded
// Some conversions from and to usize/isize are not implemented due to portability concerns
macro_rules! impl_from {
- ($Small: ty, $Large: ty) => {
- #[stable(feature = "lossless_prim_conv", since = "1.5.0")]
+ ($Small: ty, $Large: ty, #[$attr:meta]) => {
+ #[$attr]
impl From<$Small> for $Large {
#[inline]
fn from(small: $Small) -> $Large {
}
// Unsigned -> Unsigned
-impl_from! { u8, u16 }
-impl_from! { u8, u32 }
-impl_from! { u8, u64 }
-impl_from! { u8, u128 }
-impl_from! { u8, usize }
-impl_from! { u16, u32 }
-impl_from! { u16, u64 }
-impl_from! { u16, u128 }
-impl_from! { u32, u64 }
-impl_from! { u32, u128 }
-impl_from! { u64, u128 }
+impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, u128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, u128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u32, u128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { u64, u128, #[unstable(feature = "i128", issue = "35118")] }
// Signed -> Signed
-impl_from! { i8, i16 }
-impl_from! { i8, i32 }
-impl_from! { i8, i64 }
-impl_from! { i8, i128 }
-impl_from! { i8, isize }
-impl_from! { i16, i32 }
-impl_from! { i16, i64 }
-impl_from! { i16, i128 }
-impl_from! { i32, i64 }
-impl_from! { i32, i128 }
-impl_from! { i64, i128 }
+impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i8, i128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i16, i128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { i32, i128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { i64, i128, #[unstable(feature = "i128", issue = "35118")] }
// Unsigned -> Signed
-impl_from! { u8, i16 }
-impl_from! { u8, i32 }
-impl_from! { u8, i64 }
-impl_from! { u8, i128 }
-impl_from! { u16, i32 }
-impl_from! { u16, i64 }
-impl_from! { u16, i128 }
-impl_from! { u32, i64 }
-impl_from! { u32, i128 }
-impl_from! { u64, i128 }
+impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u8, i128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u16, i128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
+impl_from! { u32, i128, #[unstable(feature = "i128", issue = "35118")] }
+impl_from! { u64, i128, #[unstable(feature = "i128", issue = "35118")] }
// Note: integers can only be represented with full precision in a float if
// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
// Lossy float conversions are not implemented at this time.
// Signed -> Float
-impl_from! { i8, f32 }
-impl_from! { i8, f64 }
-impl_from! { i16, f32 }
-impl_from! { i16, f64 }
-impl_from! { i32, f64 }
+impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
// Unsigned -> Float
-impl_from! { u8, f32 }
-impl_from! { u8, f64 }
-impl_from! { u16, f32 }
-impl_from! { u16, f64 }
-impl_from! { u32, f64 }
+impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
+impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
// Float -> Float
-impl_from! { f32, f64 }
+impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
// Querying the contained values
/////////////////////////////////////////////////////////////////////////
- /// Returns `true` if the option is a `Some` value.
+ /// Returns `true` if the option is a [`Some`] value.
///
/// # Examples
///
/// let x: Option<u32> = None;
/// assert_eq!(x.is_some(), false);
/// ```
+ ///
+ /// [`Some`]: #variant.Some
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_some(&self) -> bool {
}
}
- /// Returns `true` if the option is a `None` value.
+ /// Returns `true` if the option is a [`None`] value.
///
/// # Examples
///
/// let x: Option<u32> = None;
/// assert_eq!(x.is_none(), true);
/// ```
+ ///
+ /// [`None`]: #variant.None
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_none(&self) -> bool {
// Getting to contained values
/////////////////////////////////////////////////////////////////////////
- /// Unwraps an option, yielding the content of a `Some`.
+ /// Unwraps an option, yielding the content of a [`Some`].
///
/// # Panics
///
/// Panics if the value is a [`None`] with a custom panic message provided by
/// `msg`.
///
+ /// [`Some`]: #variant.Some
/// [`None`]: #variant.None
///
/// # Examples
}
}
- /// Moves the value `v` out of the `Option<T>` if it is `Some(v)`.
+ /// Moves the value `v` out of the `Option<T>` if it is [`Some(v)`].
///
/// In general, because this function may panic, its use is discouraged.
- /// Instead, prefer to use pattern matching and handle the `None`
+ /// Instead, prefer to use pattern matching and handle the [`None`]
/// case explicitly.
///
/// # Panics
///
/// Panics if the self value equals [`None`].
///
+ /// [`Some(v)`]: #variant.Some
/// [`None`]: #variant.None
///
/// # Examples
}
/// Applies a function to the contained value (if any),
- /// or returns a `default` (if not).
+ /// or returns a [`default`][] (if not).
+ ///
+ /// [`default`]: ../default/trait.Default.html#tymethod.default
///
/// # Examples
///
}
/// Applies a function to the contained value (if any),
- /// or computes a `default` (if not).
+ /// or computes a [`default`][] (if not).
+ ///
+ /// [`default`]: ../default/trait.Default.html#tymethod.default
///
/// # Examples
///
}
}
- /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping `Some(v)` to
- /// [`Ok(v)`] and `None` to [`Err(err)`][Err].
+ /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
+ /// [`Ok(v)`] and [`None`] to [`Err(err)`].
///
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
/// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
- /// [Err]: ../../std/result/enum.Result.html#variant.Err
+ /// [`Err(err)`]: ../../std/result/enum.Result.html#variant.Err
+ /// [`None`]: #variant.None
+ /// [`Some(v)`]: #variant.Some
///
/// # Examples
///
}
}
- /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping `Some(v)` to
- /// [`Ok(v)`] and `None` to [`Err(err())`][Err].
+ /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
+ /// [`Ok(v)`] and [`None`] to [`Err(err())`].
///
/// [`Result<T, E>`]: ../../std/result/enum.Result.html
/// [`Ok(v)`]: ../../std/result/enum.Result.html#variant.Ok
- /// [Err]: ../../std/result/enum.Result.html#variant.Err
+ /// [`Err(err())`]: ../../std/result/enum.Result.html#variant.Err
+ /// [`None`]: #variant.None
+ /// [`Some(v)`]: #variant.Some
///
/// # Examples
///
// Boolean operations on the values, eager and lazy
/////////////////////////////////////////////////////////////////////////
- /// Returns `None` if the option is `None`, otherwise returns `optb`.
+ /// Returns [`None`] if the option is [`None`], otherwise returns `optb`.
+ ///
+ /// [`None`]: #variant.None
///
/// # Examples
///
}
}
- /// Returns `None` if the option is `None`, otherwise calls `f` with the
+ /// Returns [`None`] if the option is [`None`], otherwise calls `f` with the
/// wrapped value and returns the result.
///
/// Some languages call this operation flatmap.
///
+ /// [`None`]: #variant.None
+ ///
/// # Examples
///
/// ```
// Entry-like operations to insert if None and return a reference
/////////////////////////////////////////////////////////////////////////
- /// Inserts `v` into the option if it is `None`, then
+ /// Inserts `v` into the option if it is [`None`], then
/// returns a mutable reference to the contained value.
///
+ /// [`None`]: #variant.None
+ ///
/// # Examples
///
/// ```
}
}
- /// Inserts a value computed from `f` into the option if it is `None`, then
+ /// Inserts a value computed from `f` into the option if it is [`None`], then
/// returns a mutable reference to the contained value.
///
+ /// [`None`]: #variant.None
+ ///
/// # Examples
///
/// ```
// Misc
/////////////////////////////////////////////////////////////////////////
- /// Takes the value out of the option, leaving a `None` in its place.
+ /// Takes the value out of the option, leaving a [`None`] in its place.
+ ///
+ /// [`None`]: #variant.None
///
/// # Examples
///
impl<T: Default> Option<T> {
/// Returns the contained value or a default
///
- /// Consumes the `self` argument then, if `Some`, returns the contained
- /// value, otherwise if `None`, returns the default value for that
+ /// Consumes the `self` argument then, if [`Some`], returns the contained
+ /// value, otherwise if [`None`], returns the default value for that
/// type.
///
/// # Examples
///
/// Convert a string to an integer, turning poorly-formed strings
- /// into 0 (the default value for integers). `parse` converts
- /// a string to any other type that implements `FromStr`, returning
- /// `None` on error.
+ /// into 0 (the default value for integers). [`parse`] converts
+ /// a string to any other type that implements [`FromStr`], returning
+ /// [`None`] on error.
///
/// ```
/// let good_year_from_input = "1909";
/// assert_eq!(1909, good_year);
/// assert_eq!(0, bad_year);
/// ```
+ ///
+ /// [`Some`]: #variant.Some
+ /// [`None`]: #variant.None
+ /// [`parse`]: ../../std/primitive.str.html#method.parse
+ /// [`FromStr`]: ../../std/str/trait.FromStr.html
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn unwrap_or_default(self) -> T {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Option<T> {
- /// Returns None.
+ /// Returns [`None`].
+ ///
+ /// [`None`]: #variant.None
#[inline]
fn default() -> Option<T> { None }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
- /// Takes each element in the `Iterator`: if it is `None`, no further
- /// elements are taken, and the `None` is returned. Should no `None` occur, a
+ /// Takes each element in the [`Iterator`]: if it is [`None`], no further
+ /// elements are taken, and the [`None`] is returned. Should no [`None`] occur, a
/// container with the values of each `Option` is returned.
///
/// Here is an example which increments every integer in a vector,
/// ).collect();
/// assert!(res == Some(vec![2, 3]));
/// ```
+ ///
+ /// [`Iterator`]: ../iter/trait.Iterator.html
+ /// [`None`]: enum.Option.html#variant.None
#[inline]
fn from_iter<I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {
// FIXME(#11084): This could be replaced with Iterator::scan when this
fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: self._marker } }
}
-#[stable(feature = "slice_iter_as_ref", since = "1.12.0")]
+#[stable(feature = "slice_iter_as_ref", since = "1.13.0")]
impl<'a, T> AsRef<[T]> for Iter<'a, T> {
fn as_ref(&self) -> &[T] {
self.as_slice()
/// byte offset of a character (as defined by `is_char_boundary`).
/// Requires that `begin <= end` and `end <= len` where `len` is the
/// length of the string.
- #[stable(feature = "derefmut_for_string", since = "1.2.0")]
+ #[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::Range<usize>> for str {
#[inline]
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
/// `end`.
///
/// Equivalent to `&mut self[0 .. end]`.
- #[stable(feature = "derefmut_for_string", since = "1.2.0")]
+ #[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::RangeTo<usize>> for str {
#[inline]
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
/// to the end of the string.
///
/// Equivalent to `&mut self[begin .. len]`.
- #[stable(feature = "derefmut_for_string", since = "1.2.0")]
+ #[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::RangeFrom<usize>> for str {
#[inline]
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
/// never panic.
///
/// Equivalent to `&mut self[0 .. len]`.
- #[stable(feature = "derefmut_for_string", since = "1.2.0")]
+ #[stable(feature = "derefmut_for_string", since = "1.3.0")]
impl ops::IndexMut<ops::RangeFull> for str {
#[inline]
fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
}
}
+#[cfg(target_has_atomic = "ptr")]
macro_rules! atomic_int {
($stable:meta,
$stable_cxchg:meta,
SymbolName(D),
SpecializationGraph(D),
ObjectSafety(D),
+ IsCopy(D),
+ IsSized(D),
+ IsFreeze(D),
+ NeedsDrop(D),
// The set of impls for a given trait. Ultimately, it would be
// nice to get more fine-grained here (e.g., to include a
// not a hotspot.
ProjectionCache { def_ids: Vec<D> },
+ ParamEnv(D),
DescribeDef(D),
DefSpan(D),
Stability(D),
// they are always absolute.
WorkProduct(ref id) => Some(WorkProduct(id.clone())),
+ IsCopy(ref d) => op(d).map(IsCopy),
+ IsSized(ref d) => op(d).map(IsSized),
+ IsFreeze(ref d) => op(d).map(IsFreeze),
+ NeedsDrop(ref d) => op(d).map(NeedsDrop),
Hir(ref d) => op(d).map(Hir),
HirBody(ref d) => op(d).map(HirBody),
MetaData(ref d) => op(d).map(MetaData),
let def_ids: Option<Vec<E>> = def_ids.iter().map(op).collect();
def_ids.map(|d| ProjectionCache { def_ids: d })
}
+ ParamEnv(ref d) => op(d).map(ParamEnv),
DescribeDef(ref d) => op(d).map(DescribeDef),
DefSpan(ref d) => op(d).map(DefSpan),
Stability(ref d) => op(d).map(Stability),
heading: &str, span: Span)
-> (String, Option<Span>) {
let lo = tcx.sess.codemap().lookup_char_pos_adj(span.lo);
- (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()),
+ (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1),
Some(span))
}
// For region variables.
region_vars: RegionVarBindings<'a, 'gcx, 'tcx>,
- pub parameter_environment: ty::ParameterEnvironment<'gcx>,
+ pub param_env: ty::ParamEnv<'gcx>,
/// Caches the results of trait selection. This cache is used
/// for things that have to do with the parameters in scope.
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
- Option<ty::ParameterEnvironment<'tcx>>);
+ Option<ty::ParamEnv<'tcx>>);
}
impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
- Option<ty::ParameterEnvironment<'tcx>>) {
+ Option<ty::ParamEnv<'tcx>>) {
(None, None, None)
}
}
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParameterEnvironment<'tcx> {
+impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParamEnv<'tcx> {
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
- Option<ty::ParameterEnvironment<'tcx>>) {
+ Option<ty::ParamEnv<'tcx>>) {
(None, None, Some(self))
}
}
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::TypeckTables<'tcx>, ty::ParameterEnvironment<'tcx>) {
+impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::TypeckTables<'tcx>, ty::ParamEnv<'tcx>) {
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
- Option<ty::ParameterEnvironment<'tcx>>) {
+ Option<ty::ParamEnv<'tcx>>) {
(Some(self.0), None, Some(self.1))
}
}
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::TypeckTables<'tcx>, ty::ParameterEnvironment<'tcx>) {
+impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::TypeckTables<'tcx>, ty::ParamEnv<'tcx>) {
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
- Option<ty::ParameterEnvironment<'tcx>>) {
+ Option<ty::ParamEnv<'tcx>>) {
(None, Some(self.0), Some(self.1))
}
}
fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> (Option<&'a ty::TypeckTables<'tcx>>,
Option<ty::TypeckTables<'tcx>>,
- Option<ty::ParameterEnvironment<'tcx>>) {
+ Option<ty::ParamEnv<'tcx>>) {
let def_id = tcx.hir.body_owner_def_id(self);
(Some(tcx.typeck_tables_of(def_id)),
None,
- Some(tcx.parameter_environment(def_id)))
+ Some(tcx.param_env(def_id)))
}
}
arena: DroplessArena,
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
tables: Option<&'a ty::TypeckTables<'gcx>>,
- param_env: Option<ty::ParameterEnvironment<'gcx>>,
+ param_env: Option<ty::ParamEnv<'gcx>>,
projection_mode: Reveal,
}
int_unification_table: RefCell::new(UnificationTable::new()),
float_unification_table: RefCell::new(UnificationTable::new()),
region_vars: RegionVarBindings::new(self),
- parameter_environment: param_env.unwrap(),
+ param_env: param_env.unwrap(),
selection_cache: traits::SelectionCache::new(),
evaluation_cache: traits::EvaluationCache::new(),
projection_cache: RefCell::new(traits::ProjectionCache::new()),
let tables = tables.map(InferTables::Interned).unwrap_or_else(|| {
fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress)
});
- let param_env = param_env.take().unwrap_or_else(|| {
- global_tcx.empty_parameter_environment()
- });
+ let param_env = param_env.take().unwrap_or_else(|| ty::ParamEnv::empty());
global_tcx.enter_local(arena, |tcx| f(InferCtxt {
tcx: tcx,
tables: tables,
int_unification_table: RefCell::new(UnificationTable::new()),
float_unification_table: RefCell::new(UnificationTable::new()),
region_vars: RegionVarBindings::new(tcx),
- parameter_environment: param_env,
+ param_env: param_env,
selection_cache: traits::SelectionCache::new(),
evaluation_cache: traits::EvaluationCache::new(),
reported_trait_errors: RefCell::new(FxHashSet()),
}
pub fn normalize_associated_type_in_env<T>(
- self, value: &T, env: &'a ty::ParameterEnvironment<'tcx>
+ self, value: &T, env: ty::ParamEnv<'tcx>
) -> T
where T: TransNormalize<'tcx>
{
return value;
}
- self.infer_ctxt(env.clone(), Reveal::All).enter(|infcx| {
+ self.infer_ctxt(env, Reveal::All).enter(|infcx| {
value.trans_normalize(&infcx)
})
}
self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
}
- pub fn param_env(&self) -> &ty::ParameterEnvironment<'gcx> {
- &self.parameter_environment
+ pub fn param_env(&self) -> ty::ParamEnv<'gcx> {
+ self.param_env
}
pub fn closure_kind(&self,
#![feature(core_intrinsics)]
#![feature(i128_type)]
#![feature(libc)]
-#![feature(loop_break_value)]
#![feature(never_type)]
#![feature(nonzero)]
#![feature(quote)]
#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![cfg_attr(stage0, feature(rustc_private))]
#![cfg_attr(stage0, feature(staged_api))]
+#![cfg_attr(stage0, feature(loop_break_value))]
#![recursion_limit="128"]
One subtle interaction is that the results of trait lookup will vary
depending on what where clauses are in scope. Therefore, we actually
have *two* caches, a local and a global cache. The local cache is
-attached to the `ParameterEnvironment` and the global cache attached
-to the `tcx`. We use the local cache whenever the result might depend
-on the where clauses that are in scope. The determination of which
-cache to use is done by the method `pick_candidate_cache` in
-`select.rs`. At the moment, we use a very simple, conservative rule:
-if there are any where-clauses in scope, then we use the local cache.
-We used to try and draw finer-grained distinctions, but that led to a
-serious of annoying and weird bugs like #22019 and #18290. This simple
-rule seems to be pretty clearly safe and also still retains a very
-high hit rate (~95% when compiling rustc).
+attached to the `ParamEnv` and the global cache attached to the
+`tcx`. We use the local cache whenever the result might depend on the
+where clauses that are in scope. The determination of which cache to
+use is done by the method `pick_candidate_cache` in `select.rs`. At
+the moment, we use a very simple, conservative rule: if there are any
+where-clauses in scope, then we use the local cache. We used to try
+and draw finer-grained distinctions, but that led to a serious of
+annoying and weird bugs like #22019 and #18290. This simple rule seems
+to be pretty clearly safe and also still retains a very high hit rate
+(~95% when compiling rustc).
# Specialization
trait_ref.to_predicate(),
post_message);
+ let unimplemented_note = self.on_unimplemented_note(trait_ref, obligation);
+ if let Some(ref s) = unimplemented_note {
+ // If it has a custom "#[rustc_on_unimplemented]"
+ // error message, let's display it as the label!
+ err.span_label(span, s.as_str());
+ err.help(&format!("{}the trait `{}` is not implemented for `{}`",
+ pre_message,
+ trait_ref,
+ trait_ref.self_ty()));
+ } else {
+ err.span_label(span,
+ &*format!("{}the trait `{}` is not implemented for `{}`",
+ pre_message,
+ trait_ref,
+ trait_ref.self_ty()));
+ }
+
// Try to report a help message
if !trait_ref.has_infer_types() &&
self.predicate_can_apply(trait_ref) {
// which is somewhat confusing.
err.help(&format!("consider adding a `where {}` bound",
trait_ref.to_predicate()));
- } else if let Some(s) = self.on_unimplemented_note(trait_ref, obligation) {
- // If it has a custom "#[rustc_on_unimplemented]"
- // error message, let's display it!
- err.note(&s);
- } else {
+ } else if unimplemented_note.is_none() {
// Can't show anything else useful, try to find similar impls.
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
self.report_similar_impl_candidates(impl_candidates, &mut err);
}
- err.span_label(span,
- format!("{}the trait `{}` is not implemented for `{}`",
- pre_message,
- trait_ref,
- trait_ref.self_ty()));
err
}
/// Normalizes the parameter environment, reporting errors if they occur.
pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
region_context: DefId,
- unnormalized_env: ty::ParameterEnvironment<'tcx>,
+ unnormalized_env: ty::ParamEnv<'tcx>,
cause: ObligationCause<'tcx>)
- -> ty::ParameterEnvironment<'tcx>
+ -> ty::ParamEnv<'tcx>
{
// I'm not wild about reporting errors here; I'd prefer to
// have the errors get reported at a defined place (e.g.,
debug!("normalize_param_env_or_error: elaborated-predicates={:?}",
predicates);
- let elaborated_env = unnormalized_env.with_caller_bounds(tcx.intern_predicates(&predicates));
+ let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates));
tcx.infer_ctxt(elaborated_env, Reveal::UserFacing).enter(|infcx| {
let predicates = match fully_normalize(
&infcx, cause,
- // You would really want to pass infcx.parameter_environment.caller_bounds here,
+ // You would really want to pass infcx.param_env.caller_bounds here,
// but that is an interned slice, and fully_normalize takes &T and returns T, so
// without further refactoring, a slice can't be used. Luckily, we still have the
- // predicate vector from which we created the ParameterEnvironment in infcx, so we
+ // predicate vector from which we created the ParamEnv in infcx, so we
// can pass that instead. It's roundabout and a bit brittle, but this code path
// ought to be refactored anyway, and until then it saves us from having to copy.
&predicates,
Err(errors) => {
infcx.report_fulfillment_errors(&errors);
// An unnormalized env is better than nothing.
- return infcx.parameter_environment;
+ return infcx.param_env;
}
};
// all things considered.
tcx.sess.span_err(span, &fixup_err.to_string());
// An unnormalized env is better than nothing.
- return infcx.parameter_environment;
+ return infcx.param_env;
}
};
let predicates = match tcx.lift_to_global(&predicates) {
Some(predicates) => predicates,
- None => return infcx.parameter_environment
+ None => return infcx.param_env
};
debug!("normalize_param_env_or_error: resolved predicates={:?}",
predicates);
- infcx.parameter_environment.with_caller_bounds(tcx.intern_predicates(&predicates))
+ ty::ParamEnv::new(tcx.intern_predicates(&predicates))
})
}
self.infcx.tcx
}
- pub fn param_env(&self) -> &'cx ty::ParameterEnvironment<'gcx> {
+ pub fn param_env(&self) -> ty::ParamEnv<'gcx> {
self.infcx.param_env()
}
}
// create a parameter environment corresponding to a (skolemized) instantiation of impl1
- let penv = tcx.parameter_environment(impl1_def_id);
+ let penv = tcx.param_env(impl1_def_id);
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
// Create a infcx, taking the predicates of impl1 as assumptions:
source_trait_ref,
target_trait_ref,
errors,
- infcx.parameter_environment.caller_bounds);
+ infcx.param_env.caller_bounds);
Err(())
}
let flags = super::flags::FlagComputation::for_sty(&st);
let ty_struct = TyS {
sty: st,
- flags: Cell::new(flags.flags),
+ flags: flags.flags,
region_depth: flags.depth,
};
ty::TyError => /* unimportant */ continue,
$(ty::$variant(..) => &mut $variant,)*
};
- let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER);
- let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER);
+ let region = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
+ let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
variant.total += 1;
total.total += 1;
}
fn add_ty(&mut self, ty: Ty) {
- self.add_flags(ty.flags.get());
+ self.add_flags(ty.flags);
self.add_depth(ty.region_depth);
}
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
fn visit_ty(&mut self, t: Ty) -> bool {
- let flags = t.flags.get();
- debug!("HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", t, flags, self.flags);
- flags.intersects(self.flags)
+ debug!("HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}", t, t.flags, self.flags);
+ t.flags.intersects(self.flags)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
let ptr_layout = |pointee: Ty<'gcx>| {
let non_zero = !ty.is_unsafe_ptr();
let pointee = infcx.normalize_projections(pointee);
- if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
+ if pointee.is_sized(tcx, infcx.param_env, DUMMY_SP) {
Ok(Scalar { value: Pointer, non_zero: non_zero })
} else {
let unsized_part = tcx.struct_tail(pointee);
let kind = if def.is_enum() || def.variants[0].fields.len() == 0{
StructKind::AlwaysSizedUnivariant
} else {
- let param_env = tcx.parameter_environment(def.did);
+ let param_env = tcx.param_env(def.did);
let fields = &def.variants[0].fields;
let last_field = &fields[fields.len()-1];
let always_sized = tcx.type_of(last_field.did)
- .is_sized(tcx, ¶m_env, DUMMY_SP);
+ .is_sized(tcx, param_env, DUMMY_SP);
if !always_sized { StructKind::MaybeUnsizedUnivariant }
else { StructKind::AlwaysSizedUnivariant }
};
// except according to those terms.
use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
-use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use hir::def::Def;
use hir;
use middle::const_val;
}
}
+impl<'tcx, T: Clone + Hash + Eq + Debug> Key for ty::ParamEnvAnd<'tcx, T> {
+ fn map_crate(&self) -> CrateNum {
+ LOCAL_CRATE
+ }
+ fn default_span(&self, _: TyCtxt) -> Span {
+ DUMMY_SP
+ }
+}
+
trait Value<'tcx>: Sized {
fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
}
}
}
+impl<'tcx> QueryDescription for queries::is_copy_raw<'tcx> {
+ fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
+ format!("computing whether `{}` is `Copy`", env.value)
+ }
+}
+
+impl<'tcx> QueryDescription for queries::is_sized_raw<'tcx> {
+ fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
+ format!("computing whether `{}` is `Sized`", env.value)
+ }
+}
+
+impl<'tcx> QueryDescription for queries::is_freeze_raw<'tcx> {
+ fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
+ format!("computing whether `{}` is freeze", env.value)
+ }
+}
+
+impl<'tcx> QueryDescription for queries::needs_drop_raw<'tcx> {
+ fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
+ format!("computing whether `{}` needs drop", env.value)
+ }
+}
+
impl<'tcx> QueryDescription for queries::super_predicates_of<'tcx> {
fn describe(tcx: TyCtxt, def_id: DefId) -> String {
format!("computing the supertraits of `{}`",
-> ty::trait_def::TraitImpls,
[] specialization_graph_of: SpecializationGraph(DefId) -> Rc<specialization_graph::Graph>,
[] is_object_safe: ObjectSafety(DefId) -> bool,
+
+ [] param_env: ParamEnv(DefId) -> ty::ParamEnv<'tcx>,
+
+ // Trait selection queries. These are best used by invoking `ty.moves_by_default()`,
+ // `ty.is_copy()`, etc, since that will prune the environment where possible.
+ [] is_copy_raw: is_copy_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
+ [] is_sized_raw: is_sized_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
+ [] is_freeze_raw: is_freeze_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
+ [] needs_drop_raw: needs_drop_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool,
}
fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
fn relevant_trait_impls_for((def_id, _): (DefId, SimplifiedType)) -> DepNode<DefId> {
DepNode::TraitImpls(def_id)
}
+
+fn is_copy_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+ let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
+ .unwrap_or(DefId::local(CRATE_DEF_INDEX));
+ DepNode::IsCopy(def_id)
+}
+
+fn is_sized_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+ let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
+ .unwrap_or(DefId::local(CRATE_DEF_INDEX));
+ DepNode::IsSized(def_id)
+}
+
+fn is_freeze_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+ let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
+ .unwrap_or(DefId::local(CRATE_DEF_INDEX));
+ DepNode::IsFreeze(def_id)
+}
+
+fn needs_drop_dep_node<'tcx>(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepNode<DefId> {
+ let def_id = ty::item_path::characteristic_def_id_of_type(key.value)
+ .unwrap_or(DefId::local(CRATE_DEF_INDEX));
+ DepNode::NeedsDrop(def_id)
+}
use util::nodemap::{NodeSet, DefIdMap, FxHashMap, FxHashSet};
use serialize::{self, Encodable, Encoder};
-use std::cell::{Cell, RefCell};
use std::collections::BTreeMap;
use std::cmp;
use std::fmt;
TypeFlags::HAS_TY_CLOSURE.bits |
TypeFlags::HAS_LOCAL_NAMES.bits |
TypeFlags::KEEP_IN_LOCAL_TCX.bits,
-
- // Caches for type_is_sized, type_moves_by_default
- const SIZEDNESS_CACHED = 1 << 16,
- const IS_SIZED = 1 << 17,
- const MOVENESS_CACHED = 1 << 18,
- const MOVES_BY_DEFAULT = 1 << 19,
- const FREEZENESS_CACHED = 1 << 20,
- const IS_FREEZE = 1 << 21,
- const NEEDS_DROP_CACHED = 1 << 22,
- const NEEDS_DROP = 1 << 23,
}
}
pub struct TyS<'tcx> {
pub sty: TypeVariants<'tcx>,
- pub flags: Cell<TypeFlags>,
+ pub flags: TypeFlags,
// the maximal depth of any bound regions appearing in this type.
region_depth: u32,
}
}
-/// When type checking, we use the `ParameterEnvironment` to track
-/// details about the type/lifetime parameters that are in scope.
-/// It primarily stores the bounds information.
-///
-/// Note: This information might seem to be redundant with the data in
-/// `tcx.ty_param_defs`, but it is not. That table contains the
-/// parameter definitions from an "outside" perspective, but this
-/// struct will contain the bounds for a parameter as seen from inside
-/// the function body. Currently the only real distinction is that
-/// bound lifetime parameters are replaced with free ones, but in the
-/// future I hope to refine the representation of types so as to make
-/// more distinctions clearer.
-#[derive(Clone)]
-pub struct ParameterEnvironment<'tcx> {
+/// When type checking, we use the `ParamEnv` to track
+/// details about the set of where-clauses that are in scope at this
+/// particular point.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct ParamEnv<'tcx> {
/// Obligations that the caller must satisfy. This is basically
/// the set of bounds on the in-scope type parameters, translated
/// into Obligations, and elaborated and normalized.
- pub caller_bounds: &'tcx [ty::Predicate<'tcx>],
-
- /// A cache for `moves_by_default`.
- pub is_copy_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+ pub caller_bounds: &'tcx Slice<ty::Predicate<'tcx>>,
+}
- /// A cache for `type_is_sized`
- pub is_sized_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+impl<'tcx> ParamEnv<'tcx> {
+ /// Creates a suitable environment in which to perform trait
+ /// queries on the given value. This will either be `self` *or*
+ /// the empty environment, depending on whether `value` references
+ /// type parameters that are in scope. (If it doesn't, then any
+ /// judgements should be completely independent of the context,
+ /// and hence we can safely use the empty environment so as to
+ /// enable more sharing across functions.)
+ ///
+ /// NB: This is a mildly dubious thing to do, in that a function
+ /// (or other environment) might have wacky where-clauses like
+ /// `where Box<u32>: Copy`, which are clearly never
+ /// satisfiable. The code will at present ignore these,
+ /// effectively, when type-checking the body of said
+ /// function. This preserves existing behavior in any
+ /// case. --nmatsakis
+ pub fn and<T: TypeFoldable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
+ assert!(!value.needs_infer());
+ if value.has_param_types() || value.has_self_ty() {
+ ParamEnvAnd {
+ param_env: self,
+ value: value,
+ }
+ } else {
+ ParamEnvAnd {
+ param_env: ParamEnv::empty(),
+ value: value,
+ }
+ }
+ }
+}
- /// A cache for `type_is_freeze`
- pub is_freeze_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub struct ParamEnvAnd<'tcx, T> {
+ pub param_env: ParamEnv<'tcx>,
+ pub value: T,
}
-impl<'a, 'tcx> ParameterEnvironment<'tcx> {
- pub fn with_caller_bounds(&self,
- caller_bounds: &'tcx [ty::Predicate<'tcx>])
- -> ParameterEnvironment<'tcx>
- {
- ParameterEnvironment {
- caller_bounds: caller_bounds,
- is_copy_cache: RefCell::new(FxHashMap()),
- is_sized_cache: RefCell::new(FxHashMap()),
- is_freeze_cache: RefCell::new(FxHashMap()),
- }
+impl<'tcx, T> ParamEnvAnd<'tcx, T> {
+ pub fn into_parts(self) -> (ParamEnv<'tcx>, T) {
+ (self.param_env, self.value)
}
}
}
}
- /// Construct a parameter environment suitable for static contexts or other contexts where there
- /// are no free type/lifetime parameters in scope.
- pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
- ty::ParameterEnvironment {
- caller_bounds: Slice::empty(),
- is_copy_cache: RefCell::new(FxHashMap()),
- is_sized_cache: RefCell::new(FxHashMap()),
- is_freeze_cache: RefCell::new(FxHashMap()),
- }
- }
-
- /// See `ParameterEnvironment` struct def'n for details.
- pub fn parameter_environment(self, def_id: DefId) -> ParameterEnvironment<'gcx> {
- //
- // Compute the bounds on Self and the type parameters.
- //
-
- let tcx = self.global_tcx();
- let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
- let predicates = bounds.predicates;
-
- // Finally, we have to normalize the bounds in the environment, in
- // case they contain any associated type projections. This process
- // can yield errors if the put in illegal associated types, like
- // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
- // report these errors right here; this doesn't actually feel
- // right to me, because constructing the environment feels like a
- // kind of a "idempotent" action, but I'm not sure where would be
- // a better place. In practice, we construct environments for
- // every fn once during type checking, and we'll abort if there
- // are any errors at that point, so after type checking you can be
- // sure that this will succeed without errors anyway.
- //
-
- let unnormalized_env = ty::ParameterEnvironment {
- caller_bounds: tcx.intern_predicates(&predicates),
- is_copy_cache: RefCell::new(FxHashMap()),
- is_sized_cache: RefCell::new(FxHashMap()),
- is_freeze_cache: RefCell::new(FxHashMap()),
- };
-
- let body_id = self.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
- self.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
- });
- let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
- traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
- }
-
pub fn node_scope_region(self, id: NodeId) -> Region<'tcx> {
self.mk_region(ty::ReScope(CodeExtent::Misc(id)))
}
})
}
+/// See `ParamEnv` struct def'n for details.
+fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId)
+ -> ParamEnv<'tcx> {
+ // Compute the bounds on Self and the type parameters.
+
+ let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
+ let predicates = bounds.predicates;
+
+ // Finally, we have to normalize the bounds in the environment, in
+ // case they contain any associated type projections. This process
+ // can yield errors if the put in illegal associated types, like
+ // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
+ // report these errors right here; this doesn't actually feel
+ // right to me, because constructing the environment feels like a
+ // kind of a "idempotent" action, but I'm not sure where would be
+ // a better place. In practice, we construct environments for
+ // every fn once during type checking, and we'll abort if there
+ // are any errors at that point, so after type checking you can be
+ // sure that this will succeed without errors anyway.
+
+ let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates));
+
+ let body_id = tcx.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
+ tcx.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
+ });
+ let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
+ traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
+}
pub fn provide(providers: &mut ty::maps::Providers) {
+ util::provide(providers);
*providers = ty::maps::Providers {
associated_item,
associated_item_def_ids,
adt_sized_constraint,
adt_dtorck_constraint,
def_span,
+ param_env,
trait_of_item,
trait_impls_of: trait_def::trait_impls_of_provider,
relevant_trait_impls_for: trait_def::relevant_trait_impls_provider,
adt_dtorck_constraint,
trait_impls_of: trait_def::trait_impls_of_provider,
relevant_trait_impls_for: trait_def::relevant_trait_impls_provider,
+ param_env,
..*providers
};
}
use infer::InferCtxt;
use ich::{StableHashingContext, NodeIdHashingMode};
use traits::{self, Reveal};
-use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
-use ty::ParameterEnvironment;
+use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::fold::TypeVisitor;
use ty::layout::{Layout, LayoutError};
use ty::subst::{Subst, Kind};
use ty::TypeVariants::*;
use util::common::ErrorReported;
-use util::nodemap::{FxHashMap, FxHashSet};
use middle::lang_items;
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
HashStable};
-use std::cell::RefCell;
use std::cmp;
use std::hash::Hash;
use std::intrinsics;
use syntax::attr::{self, SignedInt, UnsignedInt};
use syntax_pos::{Span, DUMMY_SP};
-use hir;
-
type Disr = ConstInt;
pub trait IntTypeExt {
SelfRecursive(Vec<Span>),
}
-impl<'tcx> ParameterEnvironment<'tcx> {
+impl<'tcx> ty::ParamEnv<'tcx> {
+ /// Construct a trait environment suitable for contexts where
+ /// there are no where clauses in scope.
+ pub fn empty() -> Self {
+ Self::new(ty::Slice::empty())
+ }
+
+ /// Construct a trait environment with the given set of predicates.
+ pub fn new(caller_bounds: &'tcx ty::Slice<ty::Predicate<'tcx>>) -> Self {
+ ty::ParamEnv { caller_bounds }
+ }
+
pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
self_type: Ty<'tcx>, span: Span)
-> Result<(), CopyImplementationError> {
}
impl<'a, 'tcx> ty::TyS<'tcx> {
- fn impls_bound(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>,
- def_id: DefId,
- cache: &RefCell<FxHashMap<Ty<'tcx>, bool>>,
- span: Span) -> bool
- {
- if self.has_param_types() || self.has_self_ty() {
- if let Some(result) = cache.borrow().get(self) {
- return *result;
- }
- }
- let result =
- tcx.infer_ctxt(param_env.clone(), Reveal::UserFacing)
- .enter(|infcx| {
- traits::type_known_to_meet_bound(&infcx, self, def_id, span)
- });
- if self.has_param_types() || self.has_self_ty() {
- cache.borrow_mut().insert(self, result);
- }
- return result;
- }
-
- // FIXME (@jroesch): I made this public to use it, not sure if should be private
- pub fn moves_by_default(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>,
- span: Span) -> bool {
- if self.flags.get().intersects(TypeFlags::MOVENESS_CACHED) {
- return self.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT);
- }
-
- assert!(!self.needs_infer());
-
- // Fast-path for primitive types
- let result = match self.sty {
- TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | TyNever |
- TyRawPtr(..) | TyFnDef(..) | TyFnPtr(_) | TyRef(_, TypeAndMut {
- mutbl: hir::MutImmutable, ..
- }) => Some(false),
-
- TyStr | TyRef(_, TypeAndMut {
- mutbl: hir::MutMutable, ..
- }) => Some(true),
-
- TyArray(..) | TySlice(..) | TyDynamic(..) | TyTuple(..) |
- TyClosure(..) | TyAdt(..) | TyAnon(..) |
- TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
- }.unwrap_or_else(|| {
- !self.impls_bound(tcx, param_env,
- tcx.require_lang_item(lang_items::CopyTraitLangItem),
- ¶m_env.is_copy_cache, span) });
-
- if !self.has_param_types() && !self.has_self_ty() {
- self.flags.set(self.flags.get() | if result {
- TypeFlags::MOVENESS_CACHED | TypeFlags::MOVES_BY_DEFAULT
- } else {
- TypeFlags::MOVENESS_CACHED
- });
- }
-
- result
+ pub fn moves_by_default(&'tcx self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ span: Span)
+ -> bool {
+ !tcx.at(span).is_copy_raw(param_env.and(self))
}
- #[inline]
- pub fn is_sized(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>,
- span: Span) -> bool
+ pub fn is_sized(&'tcx self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ span: Span)-> bool
{
- if self.flags.get().intersects(TypeFlags::SIZEDNESS_CACHED) {
- return self.flags.get().intersects(TypeFlags::IS_SIZED);
- }
-
- self.is_sized_uncached(tcx, param_env, span)
- }
-
- fn is_sized_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>,
- span: Span) -> bool {
- assert!(!self.needs_infer());
-
- // Fast-path for primitive types
- let result = match self.sty {
- TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
- TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
- TyArray(..) | TyTuple(..) | TyClosure(..) | TyNever => Some(true),
-
- TyStr | TyDynamic(..) | TySlice(_) => Some(false),
-
- TyAdt(..) | TyProjection(..) | TyParam(..) |
- TyInfer(..) | TyAnon(..) | TyError => None
- }.unwrap_or_else(|| {
- self.impls_bound(tcx, param_env, tcx.require_lang_item(lang_items::SizedTraitLangItem),
- ¶m_env.is_sized_cache, span) });
-
- if !self.has_param_types() && !self.has_self_ty() {
- self.flags.set(self.flags.get() | if result {
- TypeFlags::SIZEDNESS_CACHED | TypeFlags::IS_SIZED
- } else {
- TypeFlags::SIZEDNESS_CACHED
- });
- }
-
- result
+ tcx.at(span).is_sized_raw(param_env.and(self))
}
- /// Returns `true` if and only if there are no `UnsafeCell`s
- /// nested within the type (ignoring `PhantomData` or pointers).
- #[inline]
- pub fn is_freeze(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>,
- span: Span) -> bool
+ pub fn is_freeze(&'tcx self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ span: Span)-> bool
{
- if self.flags.get().intersects(TypeFlags::FREEZENESS_CACHED) {
- return self.flags.get().intersects(TypeFlags::IS_FREEZE);
- }
-
- self.is_freeze_uncached(tcx, param_env, span)
- }
-
- fn is_freeze_uncached(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>,
- span: Span) -> bool {
- assert!(!self.needs_infer());
-
- // Fast-path for primitive types
- let result = match self.sty {
- TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
- TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
- TyStr | TyNever => Some(true),
-
- TyArray(..) | TySlice(_) |
- TyTuple(..) | TyClosure(..) | TyAdt(..) |
- TyDynamic(..) | TyProjection(..) | TyParam(..) |
- TyInfer(..) | TyAnon(..) | TyError => None
- }.unwrap_or_else(|| {
- self.impls_bound(tcx, param_env, tcx.require_lang_item(lang_items::FreezeTraitLangItem),
- ¶m_env.is_freeze_cache, span) });
-
- if !self.has_param_types() && !self.has_self_ty() {
- self.flags.set(self.flags.get() | if result {
- TypeFlags::FREEZENESS_CACHED | TypeFlags::IS_FREEZE
- } else {
- TypeFlags::FREEZENESS_CACHED
- });
- }
-
- result
+ tcx.at(span).is_freeze_raw(param_env.and(self))
}
/// If `ty.needs_drop(...)` returns `true`, then `ty` is definitely
/// (Note that this implies that if `ty` has a destructor attached,
/// then `needs_drop` will definitely return `true` for `ty`.)
#[inline]
- pub fn needs_drop(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ty::ParameterEnvironment<'tcx>) -> bool {
- if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
- return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
- }
-
- self.needs_drop_uncached(tcx, param_env, &mut FxHashSet())
- }
-
- fn needs_drop_inner(&'tcx self,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ty::ParameterEnvironment<'tcx>,
- stack: &mut FxHashSet<Ty<'tcx>>)
- -> bool {
- if self.flags.get().intersects(TypeFlags::NEEDS_DROP_CACHED) {
- return self.flags.get().intersects(TypeFlags::NEEDS_DROP);
- }
-
- // This should be reported as an error by `check_representable`.
- //
- // Consider the type as not needing drop in the meanwhile to avoid
- // further errors.
- if let Some(_) = stack.replace(self) {
- return false;
- }
-
- let needs_drop = self.needs_drop_uncached(tcx, param_env, stack);
-
- // "Pop" the cycle detection "stack".
- stack.remove(self);
-
- needs_drop
- }
-
- fn needs_drop_uncached(&'tcx self,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ty::ParameterEnvironment<'tcx>,
- stack: &mut FxHashSet<Ty<'tcx>>)
- -> bool {
- assert!(!self.needs_infer());
-
- let result = match self.sty {
- // Fast-path for primitive types
- ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
- ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
- ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
- ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
-
- // Issue #22536: We first query type_moves_by_default. It sees a
- // normalized version of the type, and therefore will definitely
- // know whether the type implements Copy (and thus needs no
- // cleanup/drop/zeroing) ...
- _ if !self.moves_by_default(tcx, param_env, DUMMY_SP) => false,
-
- // ... (issue #22536 continued) but as an optimization, still use
- // prior logic of asking for the structural "may drop".
-
- // FIXME(#22815): Note that this is a conservative heuristic;
- // it may report that the type "may drop" when actual type does
- // not actually have a destructor associated with it. But since
- // the type absolutely did not have the `Copy` bound attached
- // (see above), it is sound to treat it as having a destructor.
-
- // User destructors are the only way to have concrete drop types.
- ty::TyAdt(def, _) if def.has_dtor(tcx) => true,
-
- // Can refer to a type which may drop.
- // FIXME(eddyb) check this against a ParameterEnvironment.
- ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) |
- ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError => true,
-
- // Structural recursion.
- ty::TyArray(ty, _) | ty::TySlice(ty) => {
- ty.needs_drop_inner(tcx, param_env, stack)
- }
-
- ty::TyClosure(def_id, ref substs) => {
- substs.upvar_tys(def_id, tcx)
- .any(|ty| ty.needs_drop_inner(tcx, param_env, stack))
- }
-
- ty::TyTuple(ref tys, _) => {
- tys.iter().any(|ty| ty.needs_drop_inner(tcx, param_env, stack))
- }
-
- // unions don't have destructors regardless of the child types
- ty::TyAdt(def, _) if def.is_union() => false,
-
- ty::TyAdt(def, substs) => {
- def.variants.iter().any(|v| {
- v.fields.iter().any(|f| {
- f.ty(tcx, substs).needs_drop_inner(tcx, param_env, stack)
- })
- })
- }
- };
-
- if !self.has_param_types() && !self.has_self_ty() {
- self.flags.set(self.flags.get() | if result {
- TypeFlags::NEEDS_DROP_CACHED | TypeFlags::NEEDS_DROP
- } else {
- TypeFlags::NEEDS_DROP_CACHED
- });
- }
-
- result
+ pub fn needs_drop(&'tcx self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>)
+ -> bool {
+ tcx.needs_drop_raw(param_env.and(self))
}
#[inline]
r
}
}
+
+fn is_copy_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+ -> bool
+{
+ let (param_env, ty) = query.into_parts();
+ let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem);
+ tcx.infer_ctxt(param_env, Reveal::UserFacing)
+ .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
+}
+
+fn is_sized_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+ -> bool
+{
+ let (param_env, ty) = query.into_parts();
+ let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem);
+ tcx.infer_ctxt(param_env, Reveal::UserFacing)
+ .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
+}
+
+fn is_freeze_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+ -> bool
+{
+ let (param_env, ty) = query.into_parts();
+ let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem);
+ tcx.infer_ctxt(param_env, Reveal::UserFacing)
+ .enter(|infcx| traits::type_known_to_meet_bound(&infcx, ty, trait_def_id, DUMMY_SP))
+}
+
+fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+ -> bool
+{
+ let (param_env, ty) = query.into_parts();
+
+ let needs_drop = |ty: Ty<'tcx>| -> bool {
+ match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) {
+ Ok(v) => v,
+ Err(_) => {
+ // Cycles should be reported as an error by `check_representable`.
+ //
+ // Consider the type as not needing drop in the meanwhile to avoid
+ // further errors.
+ false
+ }
+ }
+ };
+
+ assert!(!ty.needs_infer());
+
+ match ty.sty {
+ // Fast-path for primitive types
+ ty::TyInfer(ty::FreshIntTy(_)) | ty::TyInfer(ty::FreshFloatTy(_)) |
+ ty::TyBool | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyNever |
+ ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar |
+ ty::TyRawPtr(_) | ty::TyRef(..) | ty::TyStr => false,
+
+ // Issue #22536: We first query type_moves_by_default. It sees a
+ // normalized version of the type, and therefore will definitely
+ // know whether the type implements Copy (and thus needs no
+ // cleanup/drop/zeroing) ...
+ _ if !ty.moves_by_default(tcx, param_env, DUMMY_SP) => false,
+
+ // ... (issue #22536 continued) but as an optimization, still use
+ // prior logic of asking for the structural "may drop".
+
+ // FIXME(#22815): Note that this is a conservative heuristic;
+ // it may report that the type "may drop" when actual type does
+ // not actually have a destructor associated with it. But since
+ // the type absolutely did not have the `Copy` bound attached
+ // (see above), it is sound to treat it as having a destructor.
+
+ // User destructors are the only way to have concrete drop types.
+ ty::TyAdt(def, _) if def.has_dtor(tcx) => true,
+
+ // Can refer to a type which may drop.
+ // FIXME(eddyb) check this against a ParamEnv.
+ ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyParam(_) |
+ ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError => true,
+
+ // Structural recursion.
+ ty::TyArray(ty, _) | ty::TySlice(ty) => needs_drop(ty),
+
+ ty::TyClosure(def_id, ref substs) => substs.upvar_tys(def_id, tcx).any(needs_drop),
+
+ ty::TyTuple(ref tys, _) => tys.iter().cloned().any(needs_drop),
+
+ // unions don't have destructors regardless of the child types
+ ty::TyAdt(def, _) if def.is_union() => false,
+
+ ty::TyAdt(def, substs) =>
+ def.variants.iter().any(
+ |variant| variant.fields.iter().any(
+ |field| needs_drop(field.ty(tcx, substs)))),
+ }
+}
+
+
+pub fn provide(providers: &mut ty::maps::Providers) {
+ *providers = ty::maps::Providers {
+ is_copy_raw,
+ is_sized_raw,
+ is_freeze_raw,
+ needs_drop_raw,
+ ..*providers
+ };
+}
}
}
-impl<'tcx> fmt::Debug for ty::ParameterEnvironment<'tcx> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "ParameterEnvironment({:?})", self.caller_bounds)
- }
-}
-
-impl<'tcx> fmt::Display for ty::RegionKind {
+impl fmt::Display for ty::RegionKind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if verbose() {
return write!(f, "{:?}", *self);
dfcx_loans: &'a LoanDataFlow<'a, 'tcx>,
move_data: &'a move_data::FlowedMoveData<'a, 'tcx>,
all_loans: &'a [Loan<'tcx>],
- param_env: &'a ty::ParameterEnvironment<'tcx>,
+ param_env: &'a ty::ParamEnv<'tcx>,
}
impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
dfcx_loans: dfcx_loans,
move_data: move_data,
all_loans: all_loans,
- param_env: &infcx.parameter_environment
+ param_env: &infcx.param_env
};
euv::ExprUseVisitor::new(&mut clcx, &bccx.region_maps, &infcx).consume_body(body);
}
_ => return
}
let id = src.item_id();
- let param_env = tcx.parameter_environment(tcx.hir.local_def_id(id));
- let move_data = MoveData::gather_moves(mir, tcx, ¶m_env);
+ let param_env = tcx.param_env(tcx.hir.local_def_id(id));
+ let move_data = MoveData::gather_moves(mir, tcx, param_env);
let elaborate_patch = {
let mir = &*mir;
let env = MoveDataParamEnv {
self.ctxt.tcx
}
- fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx> {
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.ctxt.param_env()
}
impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
fn move_data(&self) -> &'b MoveData<'tcx> { &self.env.move_data }
- fn param_env(&self) -> &'b ty::ParameterEnvironment<'tcx> {
- &self.env.param_env
+
+ fn param_env(&self) -> ty::ParamEnv<'tcx> {
+ self.env.param_env
}
fn initialization_data_at(&self, loc: Location) -> InitializationData {
// except according to those terms.
-use rustc::ty::{self, TyCtxt, ParameterEnvironment};
+use rustc::ty::{self, TyCtxt};
use rustc::mir::*;
use rustc::util::nodemap::FxHashMap;
use rustc_data_structures::indexed_vec::{IndexVec};
struct MoveDataBuilder<'a, 'tcx: 'a> {
mir: &'a Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &'a ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
data: MoveData<'tcx>,
}
impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
fn new(mir: &'a Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &'a ParameterEnvironment<'tcx>)
+ param_env: ty::ParamEnv<'tcx>)
-> Self {
let mut move_paths = IndexVec::new();
let mut path_map = IndexVec::new();
impl<'a, 'tcx> MoveData<'tcx> {
pub fn gather_moves(mir: &Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>)
+ param_env: ty::ParamEnv<'tcx>)
-> Self {
gather_moves(mir, tcx, param_env)
}
fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ParameterEnvironment<'tcx>)
+ param_env: ty::ParamEnv<'tcx>)
-> MoveData<'tcx> {
let mut builder = MoveDataBuilder::new(mir, tcx, param_env);
pub struct MoveDataParamEnv<'tcx> {
move_data: MoveData<'tcx>,
- param_env: ty::ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
}
pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
// steals it, but it forces the `borrowck` query.
let mir = &tcx.mir_validated(def_id).borrow();
- let param_env = tcx.parameter_environment(def_id);
- let move_data = MoveData::gather_moves(mir, tcx, ¶m_env);
+ let param_env = tcx.param_env(def_id);
+ let move_data = MoveData::gather_moves(mir, tcx, param_env);
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
let flow_inits =
let ty = lvalue.ty(mir, tcx).to_ty(tcx);
debug!("on_all_drop_children_bits({:?}, {:?} : {:?})", path, lvalue, ty);
- if ty.needs_drop(tcx, &ctxt.param_env) {
+ if ty.needs_drop(tcx, ctxt.param_env) {
each_child(child);
} else {
debug!("on_all_drop_children_bits - skipping")
where F: FnMut(MovePathIndex, DropFlagState)
{
let move_data = &ctxt.move_data;
- let param_env = &ctxt.param_env;
+ let param_env = ctxt.param_env;
debug!("drop_flag_effects_for_location({:?})", loc);
// first, move out of the RHS
lp: &LoanPath<'tcx>,
the_move: &move_data::Move,
moved_lp: &LoanPath<'tcx>,
- _param_env: &ty::ParameterEnvironment<'tcx>) {
+ _param_env: &ty::ParamEnv<'tcx>) {
let (verb, verb_participle) = match use_kind {
MovedInUse => ("use", "used"),
MovedInCapture => ("capture", "captured"),
tcx: self.tcx,
tables: self.tcx.body_tables(b),
region_maps: &self.tcx.region_maps(def_id),
- param_env: &self.tcx.parameter_environment(def_id)
+ param_env: self.tcx.param_env(def_id)
}.visit_body(self.tcx.hir.body(b));
}
}
struct MatchVisitor<'a, 'tcx: 'a> {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
- param_env: &'a ty::ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
region_maps: &'a RegionMaps,
}
///
/// FIXME: this should be done by borrowck.
fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
- cx.tcx.infer_ctxt((cx.tables, cx.param_env.clone()), Reveal::UserFacing).enter(|infcx| {
+ cx.tcx.infer_ctxt((cx.tables, cx.param_env), Reveal::UserFacing).enter(|infcx| {
let mut checker = MutationChecker {
cx: cx,
};
#![deny(warnings)]
#![feature(box_syntax)]
-#![feature(loop_break_value)]
#![feature(libc)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![cfg_attr(stage0, feature(rustc_private))]
#![cfg_attr(stage0, feature(staged_api))]
+#![cfg_attr(stage0, feature(loop_break_value))]
extern crate arena;
extern crate getopts;
}
}
-/// Destructor bomb - a DiagnosticBuilder must be either emitted or cancelled or
-/// we emit a bug.
+/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled
+/// or we emit a bug.
impl<'a> Drop for DiagnosticBuilder<'a> {
fn drop(&mut self) {
if !panicking() && !self.cancelled() {
}
fn flush(&mut self) -> io::Result<()> {
let mut stderr = io::stderr();
- let result = (|| {
- stderr.write_all(&self.buffer)?;
- stderr.flush()
- })();
+ let result = stderr.write_all(&self.buffer)
+ .and_then(|_| stderr.flush());
self.buffer.clear();
result
}
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> FatalError {
self.emit(&sp.into(), msg, Fatal);
self.panic_if_treat_err_as_bug();
- return FatalError;
+ FatalError
}
pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self,
sp: S,
-> FatalError {
self.emit_with_code(&sp.into(), msg, code, Fatal);
self.panic_if_treat_err_as_bug();
- return FatalError;
+ FatalError
}
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit(&sp.into(), msg, Error);
if def.has_dtor(cx.tcx) {
return;
}
- let parameter_environment = cx.tcx.empty_parameter_environment();
- // FIXME (@jroesch) should probably inver this so that the parameter env still impls this
- // method
- if !ty.moves_by_default(cx.tcx, ¶meter_environment, item.span) {
+ let param_env = ty::ParamEnv::empty();
+ if !ty.moves_by_default(cx.tcx, param_env, item.span) {
return;
}
- if parameter_environment.can_type_implement_copy(cx.tcx, ty, item.span).is_ok() {
+ if param_env.can_type_implement_copy(cx.tcx, ty, item.span).is_ok() {
cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
item.span,
"type could implement `Copy`; consider adding `impl \
traits::Obligation::new(traits::ObligationCause::misc(span, expr_id),
trait_ref.to_poly_trait_predicate());
- let param_env = tcx.parameter_environment(method.def_id);
+ let param_env = tcx.param_env(method.def_id);
tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
let mut selcx = traits::SelectionContext::new(&infcx);
match selcx.select(&obligation) {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
fn check_item(&mut self, ctx: &LateContext, item: &hir::Item) {
if let hir::ItemUnion(ref vdata, _) = item.node {
- let param_env = &ctx.tcx.parameter_environment(ctx.tcx.hir.local_def_id(item.id));
+ let item_def_id = ctx.tcx.hir.local_def_id(item.id);
+ let param_env = ctx.tcx.param_env(item_def_id);
for field in vdata.fields() {
let field_ty = ctx.tcx.type_of(ctx.tcx.hir.local_def_id(field.id));
if field_ty.needs_drop(ctx.tcx, param_env) {
}
}
- // LLVM requires symbols from this library, but apparently they're not printeds
+ // LLVM requires symbols from this library, but apparently they're not printed
// during llvm-config?
- if target.contains("windows") {
- println!("cargo:rustc-link-lib=ole32");
- }
if target.contains("windows-gnu") {
println!("cargo:rustc-link-lib=static-nobundle=gcc_s");
println!("cargo:rustc-link-lib=static-nobundle=pthread");
-> BlockAnd<Operand<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
{
- let topmost_scope = self.topmost_scope(); // FIXME(#6393)
- self.as_operand(block, Some(topmost_scope), expr)
+ let local_scope = self.local_scope();
+ self.as_operand(block, local_scope, expr)
}
/// Compile `expr` into a value that can be used as an operand.
-> BlockAnd<Rvalue<'tcx>>
where M: Mirror<'tcx, Output = Expr<'tcx>>
{
- let topmost_scope = self.topmost_scope(); // FIXME(#6393)
- self.as_rvalue(block, Some(topmost_scope), expr)
+ let local_scope = self.local_scope();
+ self.as_rvalue(block, local_scope, expr)
}
/// Compile `expr`, yielding an rvalue.
scope: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Rvalue<'tcx>> {
- debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);
+ debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr);
let this = self;
let expr_span = expr.span;
temp_lifetime: Option<CodeExtent>,
expr: Expr<'tcx>)
-> BlockAnd<Lvalue<'tcx>> {
- debug!("expr_as_temp(block={:?}, expr={:?})", block, expr);
+ debug!("expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?})",
+ block, temp_lifetime, expr);
let this = self;
if let ExprKind::Scope { extent, value } = expr.kind {
{
let span = tcx.hir.span(ctor_id);
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
- let pe = tcx.parameter_environment(tcx.hir.local_def_id(ctor_id));
+ let pe = tcx.param_env(tcx.hir.local_def_id(ctor_id));
tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
let (mut mir, src) =
shim::build_adt_ctor(&infcx, ctor_id, fields, span);
mir
}
-pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
- body_id: hir::BodyId)
- -> Mir<'tcx> {
+fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
+ body_id: hir::BodyId)
+ -> Mir<'tcx> {
let tcx = hir.tcx();
let ast_expr = &tcx.hir.body(body_id).value;
let ty = hir.tables().expr_ty_adjusted(ast_expr);
builder.finish(vec![], ty)
}
-pub fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
+fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
body_id: hir::BodyId)
-> Mir<'tcx> {
let span = hir.tcx().hir.span(hir.tcx().hir.body_owner(body_id));
use rustc::ty::subst::{Kind, Subst};
use rustc::ty::{Ty, TyCtxt};
use rustc::mir::*;
+use rustc::mir::transform::MirSource;
use syntax_pos::Span;
use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::fx::FxHashMap;
self.scopes.last().expect("topmost_scope: no scopes present").extent
}
+ /// Returns the scope that we should use as the lifetime of an
+ /// operand. Basically, an operand must live until it is consumed.
+ /// This is similar to, but not quite the same as, the temporary
+ /// scope (which can be larger or smaller).
+ ///
+ /// Consider:
+ ///
+ /// let x = foo(bar(X, Y));
+ ///
+ /// We wish to pop the storage for X and Y after `bar()` is
+ /// called, not after the whole `let` is completed.
+ ///
+ /// As another example, if the second argument diverges:
+ ///
+ /// foo(Box::new(2), panic!())
+ ///
+ /// We would allocate the box but then free it on the unwinding
+ /// path; we would also emit a free on the 'success' path from
+ /// panic, but that will turn out to be removed as dead-code.
+ ///
+ /// When building statics/constants, returns `None` since
+ /// intermediate values do not have to be dropped in that case.
+ pub fn local_scope(&self) -> Option<CodeExtent> {
+ match self.hir.src {
+ MirSource::Const(_) |
+ MirSource::Static(..) =>
+ // No need to free storage in this context.
+ None,
+ MirSource::Fn(_) =>
+ Some(self.topmost_scope()),
+ MirSource::Promoted(..) =>
+ bug!(),
+ }
+ }
+
// Scheduling drops
// ================
/// Indicates that `lvalue` should be dropped on exit from
tcx: TyCtxt<'a, 'gcx, 'tcx>,
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
pub region_maps: Rc<RegionMaps>,
+
+ /// This is `Constness::Const` if we are compiling a `static`,
+ /// `const`, or the body of a `const fn`.
constness: hir::Constness,
+ /// What are we compiling?
+ pub src: MirSource,
+
/// True if this constant/function needs overflow checks.
check_overflow: bool,
}
// Constants and const fn's always need overflow checks.
check_overflow |= constness == hir::Constness::Const;
- Cx { tcx, infcx, region_maps, constness, check_overflow }
+ Cx { tcx, infcx, region_maps, constness, src, check_overflow }
}
}
type with inference types/regions",
ty);
});
- ty.needs_drop(self.tcx.global_tcx(), &self.infcx.parameter_environment)
+ ty.needs_drop(self.tcx.global_tcx(), self.infcx.param_env)
}
pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
-> &'tcx Mir<'tcx>
{
debug!("make_shim({:?})", instance);
- let did = instance.def_id();
- let param_env = tcx.parameter_environment(did);
let mut result = match instance {
ty::InstanceDef::Item(..) =>
)
}
ty::InstanceDef::DropGlue(def_id, ty) => {
- build_drop_shim(tcx, ¶m_env, def_id, ty)
+ build_drop_shim(tcx, def_id, ty)
}
ty::InstanceDef::Intrinsic(_) => {
bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
}
fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ty::ParameterEnvironment<'tcx>,
def_id: DefId,
ty: Option<Ty<'tcx>>)
-> Mir<'tcx>
if let Some(..) = ty {
let patch = {
+ let param_env = tcx.param_env(def_id);
let mut elaborator = DropShimElaborator {
mir: &mir,
patch: MirPatch::new(&mir),
- tcx, param_env
+ tcx,
+ param_env
};
let dropee = Lvalue::Local(Local::new(1+0)).deref();
let resume_block = elaborator.patch.resume_block();
mir: &'a Mir<'tcx>,
patch: MirPatch<'tcx>,
tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &'a ty::ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
}
impl<'a, 'tcx> fmt::Debug for DropShimElaborator<'a, 'tcx> {
fn patch(&mut self) -> &mut MirPatch<'tcx> { &mut self.patch }
fn mir(&self) -> &'a Mir<'tcx> { self.mir }
fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> { self.tcx }
- fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx> { self.param_env }
+ fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env }
fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
if let DropFlagMode::Shallow = mode {
// FIXME: Give a bonus to functions with only a single caller
let def_id = tcx.hir.local_def_id(self.source.item_id());
- let param_env = tcx.parameter_environment(def_id);
+ let param_env = tcx.param_env(def_id);
let mut first_block = true;
let mut cost = 0;
// a regular goto.
let ty = location.ty(&callee_mir, tcx).subst(tcx, callsite.substs);
let ty = ty.to_ty(tcx);
- if ty.needs_drop(tcx, ¶m_env) {
+ if ty.needs_drop(tcx, param_env) {
cost += CALL_PENALTY;
if let Some(unwind) = unwind {
work_list.push(unwind);
}
}
-fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParameterEnvironment<'tcx>,
+fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>) -> Option<u64> {
tcx.infer_ctxt(param_env, traits::Reveal::All).enter(|infcx| {
ty.layout(&infcx).ok().map(|layout| {
/// Remove flags which are impossible for the given type.
fn restrict(&mut self, ty: Ty<'tcx>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: &ty::ParameterEnvironment<'tcx>) {
+ param_env: ty::ParamEnv<'tcx>) {
if ty.is_freeze(tcx, param_env, DUMMY_SP) {
*self = *self - Qualif::MUTABLE_INTERIOR;
}
mir: &'a Mir<'tcx>,
rpo: ReversePostorder<'a, 'tcx>,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
- param_env: ty::ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
temp_qualif: IndexVec<Local, Option<Qualif>>,
return_qualif: Option<Qualif>,
qualif: Qualif,
impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- param_env: ty::ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
def_id: DefId,
mir: &'a Mir<'tcx>,
mode: Mode)
/// Add the given type's qualification to self.qualif.
fn add_type(&mut self, ty: Ty<'tcx>) {
self.add(Qualif::MUTABLE_INTERIOR | Qualif::NEEDS_DROP);
- self.qualif.restrict(ty, self.tcx, &self.param_env);
+ self.qualif.restrict(ty, self.tcx, self.param_env);
}
/// Within the provided closure, self.qualif will start
static, use a constant instead");
}
let ty = lvalue.ty(this.mir, this.tcx).to_ty(this.tcx);
- this.qualif.restrict(ty, this.tcx, &this.param_env);
+ this.qualif.restrict(ty, this.tcx, this.param_env);
}
ProjectionElem::ConstantIndex {..} |
return Qualif::NOT_CONST.bits();
}
- let param_env = tcx.parameter_environment(def_id);
+ let param_env = tcx.param_env(def_id);
let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, Mode::Const);
qualifier.qualify_const().bits()
MirSource::Const(_) |
MirSource::Promoted(..) => return
};
- let param_env = tcx.parameter_environment(def_id);
+ let param_env = tcx.param_env(def_id);
if mode == Mode::Fn || mode == Mode::ConstFn {
// This is ugly because Qualifier holds onto mir,
// broken MIR, so try not to report duplicate errors.
return;
}
- let param_env = tcx.parameter_environment(def_id);
+ let param_env = tcx.param_env(def_id);
tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
let mut checker = TypeChecker::new(&infcx, item_id);
{
fn patch(&mut self) -> &mut MirPatch<'tcx>;
fn mir(&self) -> &'a Mir<'tcx>;
fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx>;
- fn param_env(&self) -> &'a ty::ParameterEnvironment<'tcx>;
+ fn param_env(&self) -> ty::ParamEnv<'tcx>;
fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle;
fn get_drop_flag(&mut self, path: Self::Path) -> Option<Operand<'tcx>>;
in_fn: bool,
promotable: bool,
mut_rvalue_borrows: NodeSet,
- param_env: ty::ParameterEnvironment<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
tables: &'a ty::TypeckTables<'tcx>,
}
// Adds the worst effect out of all the values of one type.
fn add_type(&mut self, ty: Ty<'gcx>) {
- if !ty.is_freeze(self.tcx, &self.param_env, DUMMY_SP) {
+ if !ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) {
self.promotable = false;
}
- if ty.needs_drop(self.tcx, &self.param_env) {
+ if ty.needs_drop(self.tcx, self.param_env) {
self.promotable = false;
}
}
}
let outer_penv = self.tcx.infer_ctxt(body_id, Reveal::UserFacing).enter(|infcx| {
- let param_env = infcx.parameter_environment.clone();
+ let param_env = infcx.param_env.clone();
let outer_penv = mem::replace(&mut self.param_env, param_env);
let region_maps = &self.tcx.region_maps(item_def_id);;
euv::ExprUseVisitor::new(self, region_maps, &infcx).consume_body(body);
in_fn: false,
promotable: false,
mut_rvalue_borrows: NodeSet(),
- param_env: tcx.empty_parameter_environment(),
+ param_env: ty::ParamEnv::empty(),
}.as_deep_visitor());
tcx.sess.abort_if_errors();
}
pub struct SharedCrateContext<'a, 'tcx: 'a> {
exported_symbols: NodeSet,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- empty_param_env: ty::ParameterEnvironment<'tcx>,
check_overflow: bool,
use_dll_storage_attrs: bool,
SharedCrateContext {
exported_symbols: exported_symbols,
- empty_param_env: tcx.empty_parameter_environment(),
tcx: tcx,
check_overflow: check_overflow,
use_dll_storage_attrs: use_dll_storage_attrs,
}
pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
- ty.needs_drop(self.tcx, &self.empty_param_env)
+ ty.needs_drop(self.tcx, ty::ParamEnv::empty())
}
pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
- ty.is_sized(self.tcx, &self.empty_param_env, DUMMY_SP)
+ ty.is_sized(self.tcx, ty::ParamEnv::empty(), DUMMY_SP)
}
pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
- ty.is_freeze(self.tcx, &self.empty_param_env, DUMMY_SP)
+ ty.is_freeze(self.tcx, ty::ParamEnv::empty(), DUMMY_SP)
}
pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet {
// Finally we register each of these predicates as an obligation in
// a fresh FulfillmentCtxt, and invoke select_all_or_error.
- // Create a parameter environment that represents the implementation's
- // method.
- let impl_param_env = tcx.parameter_environment(impl_m.def_id);
-
// Create mapping from impl to skolemized.
let impl_to_skol_substs = Substs::identity_for_item(tcx, impl_m.def_id);
// The key step here is to update the caller_bounds's predicates to be
// the new hybrid bounds we computed.
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id);
- let trait_param_env = impl_param_env.with_caller_bounds(
- tcx.intern_predicates(&hybrid_preds.predicates));
- let trait_param_env = traits::normalize_param_env_or_error(tcx,
- impl_m.def_id,
- trait_param_env,
- normalize_cause.clone());
-
- tcx.infer_ctxt(trait_param_env, Reveal::UserFacing).enter(|infcx| {
+ let param_env = ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates));
+ let param_env = traits::normalize_param_env_or_error(tcx,
+ impl_m.def_id,
+ param_env,
+ normalize_cause.clone());
+
+ tcx.infer_ctxt(param_env, Reveal::UserFacing).enter(|infcx| {
let inh = Inherited::new(infcx, impl_m.def_id);
let infcx = &inh.infcx;
debug!("compare_impl_method: caller_bounds={:?}",
- infcx.parameter_environment.caller_bounds);
+ infcx.param_env.caller_bounds);
let mut selcx = traits::SelectionContext::new(&infcx);
let region_maps = RegionMaps::new();
let mut free_regions = FreeRegionMap::new();
free_regions.relate_free_regions_from_predicates(
- &infcx.parameter_environment.caller_bounds);
+ &infcx.param_env.caller_bounds);
infcx.resolve_regions_and_report_errors(impl_m.def_id, ®ion_maps, &free_regions);
} else {
let fcx = FnCtxt::new(&inh, impl_m_node_id);
// check that the impl type can be made to match the trait type.
- let impl_param_env = tcx.parameter_environment(self_type_did);
+ let impl_param_env = tcx.param_env(self_type_did);
tcx.infer_ctxt(impl_param_env, Reveal::UserFacing).enter(|ref infcx| {
let tcx = infcx.tcx;
let mut fulfillment_cx = traits::FulfillmentContext::new();
param_ty: ty::ParamTy) {
// FIXME -- Do we want to commit to this behavior for param bounds?
- let bounds: Vec<_> = self.parameter_environment
+ let bounds: Vec<_> = self.param_env
.caller_bounds
.iter()
.filter_map(|predicate| {
debug!("assemble_where_clause_candidates(trait_def_id={:?})",
trait_def_id);
- let caller_predicates = self.parameter_environment.caller_bounds.to_vec();
+ let caller_predicates = self.param_env.caller_bounds.to_vec();
for poly_bound in traits::elaborate_predicates(self.tcx, caller_predicates)
.filter_map(|p| p.to_opt_poly_trait_ref())
.filter(|b| b.def_id() == trait_def_id) {
pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId)
-> InheritedBuilder<'a, 'gcx, 'tcx> {
let tables = ty::TypeckTables::empty();
- let param_env = tcx.parameter_environment(def_id);
+ let param_env = tcx.param_env(def_id);
InheritedBuilder {
infcx: tcx.infer_ctxt((tables, param_env), Reveal::UserFacing),
def_id,
let index = generics.type_param_to_index[&def_id.index];
ty::GenericPredicates {
parent: None,
- predicates: self.parameter_environment.caller_bounds.iter().filter(|predicate| {
+ predicates: self.param_env.caller_bounds.iter().filter(|predicate| {
match **predicate {
ty::Predicate::Trait(ref data) => {
data.0.self_ty().is_param(index)
let subject = self.tcx.hir.local_def_id(item_id);
let mut rcx = RegionCtxt::new(self, RepeatingScope(item_id), item_id, Subject(subject));
rcx.free_region_map.relate_free_regions_from_predicates(
- &self.parameter_environment.caller_bounds);
+ &self.param_env.caller_bounds);
rcx.relate_free_regions(wf_tys, item_id, span);
rcx.visit_region_obligations(item_id);
rcx.resolve_regions_and_report_errors();
}
rcx.free_region_map.relate_free_regions_from_predicates(
- &self.parameter_environment.caller_bounds);
+ &self.param_env.caller_bounds);
rcx.resolve_regions_and_report_errors();
fn declared_generic_bounds_from_env(&self, generic: GenericKind<'tcx>)
-> Vec<ty::Region<'tcx>>
{
- let param_env = &self.parameter_environment;
+ let param_env = &self.param_env;
// To start, collect bounds from user:
let mut param_bounds = self.tcx.required_region_bounds(generic.to_ty(self.tcx),
self_type);
let span = tcx.hir.span(impl_node_id);
- let param_env = tcx.parameter_environment(impl_did);
+ let param_env = tcx.param_env(impl_did);
assert!(!self_type.has_escaping_regions());
debug!("visit_implementation_of_copy: self_type={:?} (free)",
target);
let span = tcx.hir.span(impl_node_id);
- let param_env = tcx.parameter_environment(impl_did);
+ let param_env = tcx.param_env(impl_did);
assert!(!source.has_escaping_regions());
let err_info = CoerceUnsizedInfo { custom_kind: None };
// Finally, resolve all regions.
let region_maps = RegionMaps::new();
let mut free_regions = FreeRegionMap::new();
- free_regions.relate_free_regions_from_predicates(&infcx.parameter_environment
+ free_regions.relate_free_regions_from_predicates(&infcx.param_env
.caller_bounds);
infcx.resolve_regions_and_report_errors(impl_did, ®ion_maps, &free_regions);
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(conservative_impl_trait)]
-#![feature(loop_break_value)]
#![feature(never_type)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
#![cfg_attr(stage0, feature(rustc_private))]
#![cfg_attr(stage0, feature(staged_api))]
+#![cfg_attr(stage0, feature(loop_break_value))]
#[macro_use] extern crate log;
#[macro_use] extern crate syntax;
///
/// The returned value is `None` if the definition could not be inlined,
/// and `Some` of a vector of items if it was successfully expanded.
-pub fn try_inline(cx: &DocContext, def: Def, into: Option<ast::Name>)
+pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name)
-> Option<Vec<clean::Item>> {
if def == Def::Err { return None }
let did = def.def_id();
if did.is_local() { return None }
- try_inline_def(cx, def).map(|vec| {
- vec.into_iter().map(|mut item| {
- match into {
- Some(into) if item.name.is_some() => {
- item.name = Some(into.clean(cx));
- }
- _ => {}
- }
- item
- }).collect()
- })
-}
-
-fn try_inline_def(cx: &DocContext, def: Def) -> Option<Vec<clean::Item>> {
- let tcx = cx.tcx;
let mut ret = Vec::new();
let inner = match def {
Def::Trait(did) => {
}
_ => return None,
};
- let did = def.def_id();
cx.renderinfo.borrow_mut().inlined.insert(did);
ret.push(clean::Item {
- source: tcx.def_span(did).clean(cx),
- name: Some(tcx.item_name(did).to_string()),
+ source: cx.tcx.def_span(did).clean(cx),
+ name: Some(name.clean(cx)),
attrs: load_attrs(cx, did),
inner: inner,
visibility: Some(clean::Public),
- stability: tcx.lookup_stability(did).clean(cx),
- deprecation: tcx.lookup_deprecation(did).clean(cx),
+ stability: cx.tcx.lookup_stability(did).clean(cx),
+ deprecation: cx.tcx.lookup_deprecation(did).clean(cx),
def_id: did,
});
Some(ret)
let def_id = item.def.def_id();
if cx.tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public {
if !visited.insert(def_id) { continue }
- if let Some(i) = try_inline_def(cx, item.def) {
+ if let Some(i) = try_inline(cx, item.def, item.name) {
items.extend(i)
}
}
} else {
let name = self.name;
if !denied {
- if let Some(items) = inline::try_inline(cx, path.def, Some(name)) {
+ if let Some(items) = inline::try_inline(cx, path.def, name) {
return items;
}
}
.content .fn .where,
.content .where.fmt-newline {
display: block;
+ color: #4E4C4C;
+ font-size: 0.8em;
}
.content .methods > div { margin-left: 40px; }
/// # Examples
///
/// ```
- /// #![feature(retain_hash_collection)]
/// use std::collections::HashMap;
///
/// let mut map: HashMap<isize, isize> = (0..8).map(|x|(x, x*10)).collect();
/// map.retain(|&k, _| k % 2 == 0);
/// assert_eq!(map.len(), 4);
/// ```
- #[unstable(feature = "retain_hash_collection", issue = "36648")]
+ #[stable(feature = "retain_hash_collection", since = "1.18.0")]
pub fn retain<F>(&mut self, mut f: F)
where F: FnMut(&K, &mut V) -> bool
{
/// [`HashMap`]: struct.HashMap.html
/// [`PartialEq`]: ../../std/cmp/trait.PartialEq.html
/// [`RefCell`]: ../../std/cell/struct.RefCell.html
-
-
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct HashSet<T, S = RandomState> {
/// # Examples
///
/// ```
- /// #![feature(retain_hash_collection)]
/// use std::collections::HashSet;
///
/// let xs = [1,2,3,4,5,6];
/// set.retain(|&k| k % 2 == 0);
/// assert_eq!(set.len(), 3);
/// ```
- #[unstable(feature = "retain_hash_collection", issue = "36648")]
+ #[stable(feature = "retain_hash_collection", since = "1.18.0")]
pub fn retain<F>(&mut self, mut f: F)
where F: FnMut(&T) -> bool
{
#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_list()
- .entries(self.clone())
- .finish()
+ f.debug_list().entries(self.clone()).finish()
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl<K: fmt::Debug> fmt::Debug for IntoIter<K> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let entries_iter = self.iter.inner.iter().map(|(k, _)| k);
- f.debug_list()
- .entries(entries_iter)
- .finish()
+ let entries_iter = self.iter
+ .inner
+ .iter()
+ .map(|(k, _)| k);
+ f.debug_list().entries(entries_iter).finish()
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, K: fmt::Debug> fmt::Debug for Drain<'a, K> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let entries_iter = self.iter.inner.iter().map(|(k, _)| k);
- f.debug_list()
- .entries(entries_iter)
- .finish()
+ let entries_iter = self.iter
+ .inner
+ .iter()
+ .map(|(k, _)| k);
+ f.debug_list().entries(entries_iter).finish()
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, T, S> fmt::Debug for Intersection<'a, T, S>
where T: fmt::Debug + Eq + Hash,
- S: BuildHasher,
+ S: BuildHasher
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_list()
- .entries(self.clone())
- .finish()
+ f.debug_list().entries(self.clone()).finish()
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, T, S> fmt::Debug for Difference<'a, T, S>
where T: fmt::Debug + Eq + Hash,
- S: BuildHasher,
+ S: BuildHasher
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_list()
- .entries(self.clone())
- .finish()
+ f.debug_list().entries(self.clone()).finish()
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S>
where T: fmt::Debug + Eq + Hash,
- S: BuildHasher,
+ S: BuildHasher
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_list()
- .entries(self.clone())
- .finish()
+ f.debug_list().entries(self.clone()).finish()
}
}
#[stable(feature = "std_debug", since = "1.16.0")]
impl<'a, T, S> fmt::Debug for Union<'a, T, S>
where T: fmt::Debug + Eq + Hash,
- S: BuildHasher,
+ S: BuildHasher
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.debug_list()
- .entries(self.clone())
- .finish()
+ f.debug_list().entries(self.clone()).finish()
}
}
#[test]
fn test_retain() {
- let xs = [1,2,3,4,5,6];
+ let xs = [1, 2, 3, 4, 5, 6];
let mut set: HashSet<isize> = xs.iter().cloned().collect();
set.retain(|&k| k % 2 == 0);
assert_eq!(set.len(), 3);
use cmp;
use hash::{BuildHasher, Hash, Hasher};
-use intrinsics::needs_drop;
use marker;
-use mem::{align_of, size_of};
+use mem::{align_of, size_of, needs_drop};
use mem;
use ops::{Deref, DerefMut};
use ptr::{self, Unique, Shared};
//! This module contains functions to inspect various aspects such as
//! environment variables, process arguments, the current directory, and various
//! other important directories.
+//!
+//! There are several functions and structs in this module that have a
+//! counterpart ending in `os`. Those ending in `os` will return an [`OsString`]
+//! and those without will be returning a [`String`].
+//!
+//! [`OsString`]: ../../std/ffi/struct.OsString.html
+//! [`String`]: ../string/struct.String.html
#![stable(feature = "env", since = "1.0.0")]
/// An iterator over a snapshot of the environment variables of this process.
///
-/// This structure is created through the [`std::env::vars`] function.
+/// This structure is created by the [`std::env::vars`] function. See its
+/// documentation for more.
///
/// [`std::env::vars`]: fn.vars.html
#[stable(feature = "env", since = "1.0.0")]
/// An iterator over a snapshot of the environment variables of this process.
///
-/// This structure is created through the [`std::env::vars_os`] function.
+/// This structure is created by the [`std::env::vars_os`] function. See
+/// its documentation for more.
///
/// [`std::env::vars_os`]: fn.vars_os.html
#[stable(feature = "env", since = "1.0.0")]
/// Fetches the environment variable `key` from the current process.
///
-/// The returned result is [`Ok(s)`] if the environment variable is present and is
-/// valid unicode. If the environment variable is not present, or it is not
-/// valid unicode, then [`VarError`] will be returned.
+/// # Errors
///
-/// [`Ok(s)`]: ../result/enum.Result.html#variant.Ok
-/// [`VarError`]: enum.VarError.html
+/// * Environment variable is not present
+/// * Environment variable is not valid unicode
///
/// # Examples
///
})
}
-/// Possible errors from the [`env::var`] function.
+/// The error type for operations interacting with environment variables.
+/// Possibly returned from the [`env::var`] function.
///
/// [`env::var`]: fn.var.html
#[derive(Debug, PartialEq, Eq, Clone)]
})
}
-/// An iterator over `PathBuf` instances for parsing an environment variable
-/// according to platform-specific conventions.
+/// An iterator that splits an environment variable into paths according to
+/// platform-specific conventions.
///
-/// This structure is returned from `std::env::split_paths`.
+/// This structure is created by the [`std::env::split_paths`] function See its
+/// documentation for more.
+///
+/// [`std::env::split_paths`]: fn.split_paths.html
#[stable(feature = "env", since = "1.0.0")]
pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> }
}
}
-/// Error type returned from `std::env::join_paths` when paths fail to be
-/// joined.
+/// The error type for operations on the `PATH` variable. Possibly returned from
+/// the [`env::join_paths`] function.
+///
+/// [`env::join_paths`]: fn.join_paths.html
#[derive(Debug)]
#[stable(feature = "env", since = "1.0.0")]
pub struct JoinPathsError {
/// Joins a collection of [`Path`]s appropriately for the `PATH`
/// environment variable.
///
-/// Returns an [`OsString`] on success.
+/// # Errors
///
/// Returns an [`Err`][err] (containing an error message) if one of the input
/// [`Path`]s contains an invalid character for constructing the `PATH`
/// Returns the path of a temporary directory.
///
-/// On Unix, returns the value of the `TMPDIR` environment variable if it is
+/// # Unix
+///
+/// Returns the value of the `TMPDIR` environment variable if it is
/// set, otherwise for non-Android it returns `/tmp`. If Android, since there
/// is no global temporary folder (it is usually allocated per-app), it returns
/// `/data/local/tmp`.
///
-/// On Windows, returns the value of, in order, the `TMP`, `TEMP`,
+/// # Windows
+///
+/// Returns the value of, in order, the `TMP`, `TEMP`,
/// `USERPROFILE` environment variable if any are set and not the empty
/// string. Otherwise, `temp_dir` returns the path of the Windows directory.
/// This behavior is identical to that of [`GetTempPath`][msdn], which this
fn is_empty(&self) -> bool { self.inner.is_empty() }
}
-#[stable(feature = "env_iterators", since = "1.11.0")]
+#[stable(feature = "env_iterators", since = "1.12.0")]
impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<String> {
self.inner.next_back().map(|s| s.into_string().unwrap())
fn is_empty(&self) -> bool { self.inner.is_empty() }
}
-#[stable(feature = "env_iterators", since = "1.11.0")]
+#[stable(feature = "env_iterators", since = "1.12.0")]
impl DoubleEndedIterator for ArgsOs {
fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() }
}
}
}
-#[stable(feature = "string_box_error", since = "1.7.0")]
+#[stable(feature = "string_box_error", since = "1.6.0")]
impl From<String> for Box<Error> {
fn from(str_err: String) -> Box<Error> {
let err1: Box<Error + Send + Sync> = From::from(str_err);
}
}
-#[stable(feature = "string_box_error", since = "1.7.0")]
+#[stable(feature = "string_box_error", since = "1.6.0")]
impl<'a> From<&'a str> for Box<Error> {
fn from(err: &'a str) -> Box<Error> {
From::from(String::from(err))
}
}
-#[stable(feature = "box_error", since = "1.7.0")]
+#[stable(feature = "box_error", since = "1.8.0")]
impl<T: Error> Error for Box<T> {
fn description(&self) -> &str {
Error::description(&**self)
use slice;
use str::{self, Utf8Error};
-/// A type representing an owned C-compatible string
+/// A type representing an owned C-compatible string.
///
/// This type serves the primary purpose of being able to safely generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
///
-/// A `CString` is created from either a byte slice or a byte vector. A `u8`
-/// slice can be obtained with the `as_bytes` method. Slices produced from a
+/// A `CString` is created from either a byte slice or a byte vector. A [`u8`]
+/// slice can be obtained with the `as_bytes` method. Slices produced from a
/// `CString` do *not* contain the trailing nul terminator unless otherwise
/// specified.
///
+/// [`u8`]: ../primitive.u8.html
+///
/// # Examples
///
/// ```no_run
///
/// Note that this structure is **not** `repr(C)` and is not recommended to be
/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
-/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
+/// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe
/// interface to other consumers.
///
+/// [`from_ptr`]: #method.from_ptr
+///
/// # Examples
///
-/// Inspecting a foreign C string
+/// Inspecting a foreign C string:
///
/// ```no_run
/// use std::ffi::CStr;
/// }
/// ```
///
-/// Passing a Rust-originating C string
+/// Passing a Rust-originating C string:
///
/// ```no_run
/// use std::ffi::{CString, CStr};
/// work(&s);
/// ```
///
-/// Converting a foreign C string into a Rust `String`
+/// Converting a foreign C string into a Rust [`String`]:
+///
+/// [`String`]: ../string/struct.String.html
///
/// ```no_run
/// use std::ffi::CStr;
inner: [c_char]
}
-/// An error returned from `CString::new` to indicate that a nul byte was found
+/// An error returned from [`CString::new`] to indicate that a nul byte was found
/// in the vector provided.
+///
+/// [`CString::new`]: struct.CString.html#method.new
#[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);
-/// An error returned from `CStr::from_bytes_with_nul` to indicate that a nul
+/// An error returned from [`CStr::from_bytes_with_nul`] to indicate that a nul
/// byte was found too early in the slice provided or one wasn't found at all.
+///
+/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
#[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub struct FromBytesWithNulError {
}
}
-/// An error returned from `CString::into_string` to indicate that a UTF-8 error
+/// An error returned from [`CString::into_string`] to indicate that a UTF-8 error
/// was encountered during the conversion.
+///
+/// [`CString::into_string`]: struct.CString.html#method.into_string
#[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "cstring_into", since = "1.7.0")]
pub struct IntoStringError {
/// Creates a C-compatible string from a byte vector without checking for
/// interior 0 bytes.
///
- /// This method is equivalent to `new` except that no runtime assertion
+ /// This method is equivalent to [`new`] except that no runtime assertion
/// is made that `v` contains no 0 bytes, and it requires an actual
/// byte vector, not anything that can be converted to one with Into.
///
+ /// [`new`]: #method.new
+ ///
/// # Examples
///
/// ```
/// # Safety
///
/// This should only ever be called with a pointer that was earlier
- /// obtained by calling `into_raw` on a `CString`. Other usage (e.g. trying to take
+ /// obtained by calling [`into_raw`] on a `CString`. Other usage (e.g. trying to take
/// ownership of a string that was allocated by foreign code) is likely to lead
/// to undefined behavior or allocator corruption.
+ ///
+ /// [`into_raw`]: #method.into_raw
#[stable(feature = "cstr_memory", since = "1.4.0")]
pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
let len = libc::strlen(ptr) + 1; // Including the NUL byte
/// Transfers ownership of the string to a C caller.
///
/// The pointer must be returned to Rust and reconstituted using
- /// `from_raw` to be properly deallocated. Specifically, one
+ /// [`from_raw`] to be properly deallocated. Specifically, one
/// should *not* use the standard C `free` function to deallocate
/// this string.
///
- /// Failure to call `from_raw` will lead to a memory leak.
+ /// Failure to call [`from_raw`] will lead to a memory leak.
+ ///
+ /// [`from_raw`]: #method.from_raw
#[stable(feature = "cstr_memory", since = "1.4.0")]
pub fn into_raw(self) -> *mut c_char {
Box::into_raw(self.into_inner()) as *mut c_char
}
- /// Converts the `CString` into a `String` if it contains valid Unicode data.
+ /// Converts the `CString` into a [`String`] if it contains valid Unicode data.
///
/// On failure, ownership of the original `CString` is returned.
+ ///
+ /// [`String`]: ../string/struct.String.html
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_string(self) -> Result<String, IntoStringError> {
String::from_utf8(self.into_bytes())
vec
}
- /// Equivalent to the `into_bytes` function except that the returned vector
+ /// Equivalent to the [`into_bytes`] function except that the returned vector
/// includes the trailing nul byte.
+ ///
+ /// [`into_bytes`]: #method.into_bytes
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_bytes_with_nul(self) -> Vec<u8> {
self.into_inner().into_vec()
&self.inner[..self.inner.len() - 1]
}
- /// Equivalent to the `as_bytes` function except that the returned slice
+ /// Equivalent to the [`as_bytes`] function except that the returned slice
/// includes the trailing nul byte.
+ ///
+ /// [`as_bytes`]: #method.as_bytes
#[stable(feature = "rust1", since = "1.0.0")]
pub fn as_bytes_with_nul(&self) -> &[u8] {
&self.inner
}
- /// Extracts a `CStr` slice containing the entire string.
+ /// Extracts a [`CStr`] slice containing the entire string.
+ ///
+ /// [`CStr`]: struct.CStr.html
#[unstable(feature = "as_c_str", issue = "40380")]
pub fn as_c_str(&self) -> &CStr {
&*self
}
- /// Converts this `CString` into a boxed `CStr`.
+ /// Converts this `CString` into a boxed [`CStr`].
+ ///
+ /// [`CStr`]: struct.CStr.html
#[unstable(feature = "into_boxed_c_str", issue = "40380")]
pub fn into_boxed_c_str(self) -> Box<CStr> {
unsafe { mem::transmute(self.into_inner()) }
}
- // Bypass "move out of struct which implements `Drop` trait" restriction.
+ // Bypass "move out of struct which implements [`Drop`] trait" restriction.
+ ///
+ /// [`Drop`]: ../ops/trait.Drop.html
fn into_inner(self) -> Box<[u8]> {
unsafe {
let result = ptr::read(&self.inner);
}
}
-#[stable(feature = "c_string_from_box", since = "1.17.0")]
+#[stable(feature = "c_string_from_box", since = "1.18.0")]
impl From<Box<CStr>> for CString {
fn from(s: Box<CStr>) -> CString {
s.into_c_string()
}
}
-#[stable(feature = "box_from_c_string", since = "1.17.0")]
+#[stable(feature = "box_from_c_string", since = "1.18.0")]
impl Into<Box<CStr>> for CString {
fn into(self) -> Box<CStr> {
self.into_boxed_c_str()
impl NulError {
/// Returns the position of the nul byte in the slice that was provided to
- /// `CString::new`.
+ /// [`CString::new`].
+ ///
+ /// [`CString::new`]: struct.CString.html#method.new
///
/// # Examples
///
}
impl IntoStringError {
- /// Consumes this error, returning original `CString` which generated the
+ /// Consumes this error, returning original [`CString`] which generated the
/// error.
+ ///
+ /// [`CString`]: struct.CString.html
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_cstring(self) -> CString {
self.inner
/// allows inspection and interoperation of non-owned C strings. This method
/// is unsafe for a number of reasons:
///
- /// * There is no guarantee to the validity of `ptr`
+ /// * There is no guarantee to the validity of `ptr`.
/// * The returned lifetime is not guaranteed to be the actual lifetime of
- /// `ptr`
+ /// `ptr`.
/// * There is no guarantee that the memory pointed to by `ptr` contains a
/// valid nul terminator byte at the end of the string.
///
/// Converts this C string to a byte slice containing the trailing 0 byte.
///
- /// This function is the equivalent of `to_bytes` except that it will retain
+ /// This function is the equivalent of [`to_bytes`] except that it will retain
/// the trailing nul instead of chopping it off.
///
/// > **Note**: This method is currently implemented as a 0-cost cast, but
/// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called.
+ ///
+ /// [`to_bytes`]: #method.to_bytes
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_bytes_with_nul(&self) -> &[u8] {
unsafe { mem::transmute(&self.inner) }
}
- /// Yields a `&str` slice if the `CStr` contains valid UTF-8.
+ /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8.
///
/// This function will calculate the length of this string and check for
- /// UTF-8 validity, and then return the `&str` if it's valid.
+ /// UTF-8 validity, and then return the [`&str`] if it's valid.
///
/// > **Note**: This method is currently implemented to check for validity
/// > after a 0-cost cast, but it is planned to alter its definition in the
/// > future to perform the length calculation in addition to the UTF-8
/// > check whenever this method is called.
+ ///
+ /// [`&str`]: ../primitive.str.html
#[stable(feature = "cstr_to_str", since = "1.4.0")]
pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
// NB: When CStr is changed to perform the length check in .to_bytes()
str::from_utf8(self.to_bytes())
}
- /// Converts a `CStr` into a `Cow<str>`.
+ /// Converts a `CStr` into a [`Cow`]`<`[`str`]`>`.
///
/// This function will calculate the length of this string (which normally
/// requires a linear amount of work to be done) and then return the
- /// resulting slice as a `Cow<str>`, replacing any invalid UTF-8 sequences
+ /// resulting slice as a [`Cow`]`<`[`str`]`>`, replacing any invalid UTF-8 sequences
/// with `U+FFFD REPLACEMENT CHARACTER`.
///
/// > **Note**: This method is currently implemented to check for validity
/// > after a 0-cost cast, but it is planned to alter its definition in the
/// > future to perform the length calculation in addition to the UTF-8
/// > check whenever this method is called.
+ ///
+ /// [`Cow`]: ../borrow/enum.Cow.html
+ /// [`str`]: ../primitive.str.html
#[stable(feature = "cstr_to_str", since = "1.4.0")]
pub fn to_string_lossy(&self) -> Cow<str> {
String::from_utf8_lossy(self.to_bytes())
}
- /// Converts a `Box<CStr>` into a `CString` without copying or allocating.
+ /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
+ ///
+ /// [`Box`]: ../boxed/struct.Box.html
+ /// [`CString`]: struct.CString.html
#[unstable(feature = "into_boxed_c_str", issue = "40380")]
pub fn into_c_string(self: Box<CStr>) -> CString {
unsafe { mem::transmute(self) }
}
}
-#[stable(feature = "os_string_from_box", since = "1.17.0")]
-impl<'a> From<Box<OsStr>> for OsString {
+#[stable(feature = "os_string_from_box", since = "1.18.0")]
+impl From<Box<OsStr>> for OsString {
fn from(boxed: Box<OsStr>) -> OsString {
boxed.into_os_string()
}
}
-#[stable(feature = "box_from_c_string", since = "1.17.0")]
+#[stable(feature = "box_from_os_string", since = "1.18.0")]
impl Into<Box<OsStr>> for OsString {
fn into(self) -> Box<OsStr> {
self.into_boxed_os_str()
#![feature(linkage)]
#![feature(macro_reexport)]
#![feature(needs_panic_runtime)]
+#![feature(needs_drop)]
#![feature(never_type)]
#![feature(num_bits_bytes)]
#![feature(old_wrapping)]
///
/// Panics if writing to `io::stderr` fails.
#[macro_export]
-#[stable(feature = "eprint", since="1.18.0")]
+#[stable(feature = "eprint", since = "1.19.0")]
#[allow_internal_unstable]
macro_rules! eprint {
($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*)));
///
/// Panics if writing to `io::stderr` fails.
#[macro_export]
-#[stable(feature = "eprint", since="1.18.0")]
+#[stable(feature = "eprint", since = "1.19.0")]
macro_rules! eprintln {
() => (eprint!("\n"));
($fmt:expr) => (eprint!(concat!($fmt, "\n")));
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialEq<Ipv4Addr> for IpAddr {
fn eq(&self, other: &Ipv4Addr) -> bool {
match *self {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialEq<IpAddr> for Ipv4Addr {
fn eq(&self, other: &IpAddr) -> bool {
match *other {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialOrd<Ipv4Addr> for IpAddr {
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
match *self {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialOrd<IpAddr> for Ipv4Addr {
fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
match *other {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialEq<IpAddr> for Ipv6Addr {
fn eq(&self, other: &IpAddr) -> bool {
match *other {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialEq<Ipv6Addr> for IpAddr {
fn eq(&self, other: &Ipv6Addr) -> bool {
match *self {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialOrd<Ipv6Addr> for IpAddr {
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
match *self {
}
}
-#[stable(feature = "ip_cmp", since = "1.15.0")]
+#[stable(feature = "ip_cmp", since = "1.16.0")]
impl PartialOrd<IpAddr> for Ipv6Addr {
fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
match *other {
}
}
-#[stable(feature = "ipv6_from_segments", since = "1.15.0")]
+#[stable(feature = "ipv6_from_segments", since = "1.16.0")]
impl From<[u16; 8]> for Ipv6Addr {
fn from(segments: [u16; 8]) -> Ipv6Addr {
let [a, b, c, d, e, f, g, h] = segments;
/// # Examples
///
/// ```no_run
- /// #![feature(peek)]
/// use std::net::TcpStream;
///
/// let stream = TcpStream::connect("127.0.0.1:8000")
/// let mut buf = [0; 10];
/// let len = stream.peek(&mut buf).expect("peek failed");
/// ```
- #[unstable(feature = "peek", issue = "38980")]
+ #[stable(feature = "peek", since = "1.18.0")]
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
self.0.peek(buf)
}
/// # Examples
///
/// ```no_run
- /// #![feature(peek)]
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf)
/// .expect("Didn't receive data");
/// ```
- #[unstable(feature = "peek", issue = "38980")]
+ #[stable(feature = "peek", since = "1.18.0")]
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
self.0.peek_from(buf)
}
/// # Examples
///
/// ```no_run
- /// #![feature(peek)]
/// use std::net::UdpSocket;
///
/// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
/// Err(e) => println!("peek function failed: {:?}", e),
/// }
/// ```
- #[unstable(feature = "peek", issue = "38980")]
+ #[stable(feature = "peek", since = "1.18.0")]
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
self.0.peek(buf)
}
}
}
-#[stable(feature = "path_buf_from_box", since = "1.17.0")]
-impl<'a> From<Box<Path>> for PathBuf {
+#[stable(feature = "path_buf_from_box", since = "1.18.0")]
+impl From<Box<Path>> for PathBuf {
fn from(boxed: Box<Path>) -> PathBuf {
boxed.into_path_buf()
}
}
-#[stable(feature = "box_from_path_buf", since = "1.17.0")]
+#[stable(feature = "box_from_path_buf", since = "1.18.0")]
impl Into<Box<Path>> for PathBuf {
fn into(self) -> Box<Path> {
self.into_boxed_path()
}
}
-#[stable(feature = "default_for_pathbuf", since = "1.16.0")]
+#[stable(feature = "default_for_pathbuf", since = "1.17.0")]
impl Default for PathBuf {
fn default() -> Self {
PathBuf::new()
/// Basic usage:
///
/// ```no_run
- /// #![feature(process_try_wait)]
- ///
/// use std::process::Command;
///
/// let mut child = Command::new("ls").spawn().unwrap();
/// Err(e) => println!("error attempting to wait: {}", e),
/// }
/// ```
- #[unstable(feature = "process_try_wait", issue = "38903")]
+ #[stable(feature = "process_try_wait", since = "1.18.0")]
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
Ok(self.handle.try_wait()?.map(ExitStatus))
}
}
}
-#[stable(feature = "condvar_default", since = "1.9.0")]
+#[stable(feature = "condvar_default", since = "1.10.0")]
impl Default for Condvar {
/// Creates a `Condvar` which is ready to be waited on and notified.
fn default() -> Condvar {
}
}
-#[stable(feature = "mpsc_debug", since = "1.7.0")]
+#[stable(feature = "mpsc_debug", since = "1.8.0")]
impl<T> fmt::Debug for Sender<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Sender {{ .. }}")
}
}
-#[stable(feature = "mpsc_debug", since = "1.7.0")]
+#[stable(feature = "mpsc_debug", since = "1.8.0")]
impl<T> fmt::Debug for SyncSender<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "SyncSender {{ .. }}")
}
}
-#[stable(feature = "mpsc_debug", since = "1.7.0")]
+#[stable(feature = "mpsc_debug", since = "1.8.0")]
impl<T> fmt::Debug for Receiver<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Receiver {{ .. }}")
}
}
-#[stable(feature = "mpsc_recv_timeout_error", since = "1.14.0")]
+#[stable(feature = "mpsc_recv_timeout_error", since = "1.15.0")]
impl fmt::Display for RecvTimeoutError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
}
}
-#[stable(feature = "mpsc_recv_timeout_error", since = "1.14.0")]
+#[stable(feature = "mpsc_recv_timeout_error", since = "1.15.0")]
impl error::Error for RecvTimeoutError {
fn description(&self) -> &str {
match *self {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> !Send for MutexGuard<'a, T> { }
-#[stable(feature = "mutexguard", since = "1.18.0")]
+#[stable(feature = "mutexguard", since = "1.19.0")]
unsafe impl<'a, T: ?Sized + Sync> Sync for MutexGuard<'a, T> { }
impl<T> Mutex<T> {
}
}
-#[stable(feature = "mutex_default", since = "1.9.0")]
+#[stable(feature = "mutex_default", since = "1.10.0")]
impl<T: ?Sized + Default> Default for Mutex<T> {
/// Creates a `Mutex<T>`, with the `Default` value for T.
fn default() -> Mutex<T> {
}
}
-#[stable(feature = "rw_lock_default", since = "1.9.0")]
+#[stable(feature = "rw_lock_default", since = "1.10.0")]
impl<T: Default> Default for RwLock<T> {
/// Creates a new `RwLock<T>`, with the `Default` value for T.
fn default() -> RwLock<T> {
#![unstable(feature = "thread_local_internals", issue = "0")]
use cell::{Cell, UnsafeCell};
-use intrinsics;
+use mem;
use ptr;
+
pub struct Key<T> {
inner: UnsafeCell<Option<T>>,
pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
unsafe {
- if intrinsics::needs_drop::<T>() && self.dtor_running.get() {
+ if mem::needs_drop::<T>() && self.dtor_running.get() {
return None
}
self.register_dtor();
}
unsafe fn register_dtor(&self) {
- if !intrinsics::needs_drop::<T>() || self.dtor_registered.get() {
+ if !mem::needs_drop::<T>() || self.dtor_registered.get() {
return
}
use cell::{Cell, UnsafeCell};
use fmt;
-use intrinsics;
+use mem;
use ptr;
pub struct Key<T> {
pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
unsafe {
- if intrinsics::needs_drop::<T>() && self.dtor_running.get() {
+ if mem::needs_drop::<T>() && self.dtor_running.get() {
return None
}
self.register_dtor();
}
unsafe fn register_dtor(&self) {
- if !intrinsics::needs_drop::<T>() || self.dtor_registered.get() {
+ if !mem::needs_drop::<T>() || self.dtor_registered.get() {
return
}
/// want to specify the stack size or the name of the thread, use this API
/// instead.
///
+/// As you can see in the signature of `spawn` there are two constraints on
+/// both the closure given to `spawn` and its return value, let's explain them:
+///
+/// - The `'static` constraint means that the closure and its return value
+/// must have a lifetime of the whole program execution. The reason for this
+/// is that threads can `detach` and outlive the lifetime they have been
+/// created in.
+/// Indeed if the thread, and by extension its return value, can outlive their
+/// caller, we need to make sure that they will be valid afterwards, and since
+/// we *can't* know when it will return we need to have them valid as long as
+/// possible, that is until the end of the program, hence the `'static`
+/// lifetime.
+/// - The [`Send`] constraint is because the closure will need to be passed
+/// *by value* from the thread where it is spawned to the new thread. Its
+/// return value will need to be passed from the new thread to the thread
+/// where it is `join`ed.
+/// As a reminder, the [`Send`] marker trait, expresses that it is safe to be
+/// passed from thread to thread. [`Sync`] expresses that it is safe to have a
+/// reference be passed from thread to thread.
+///
/// # Panics
///
/// Panics if the OS fails to create a thread; use [`Builder::spawn`]
/// [`panic`]: ../../std/macro.panic.html
/// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn
/// [`Builder`]: ../../std/thread/struct.Builder.html
+/// [`Send`]: ../../std/marker/trait.Send.html
+/// [`Sync`]: ../../std/marker/trait.Sync.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
pub fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T>
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
{
- let mut parser = Parser::new(sess, self.tokens.clone(), None, false);
+ let mut parser = Parser::new(sess, self.tokens.clone(), None, false, false);
let result = f(&mut parser)?;
if parser.token != token::Eof {
parser.unexpected()?;
Success(())
}
-pub fn parse(sess: &ParseSess, tts: TokenStream, ms: &[TokenTree], directory: Option<Directory>)
+pub fn parse(sess: &ParseSess,
+ tts: TokenStream,
+ ms: &[TokenTree],
+ directory: Option<Directory>,
+ recurse_into_modules: bool)
-> NamedParseResult {
- let mut parser = Parser::new(sess, tts, directory, true);
+ let mut parser = Parser::new(sess, tts, directory, recurse_into_modules, true);
let mut cur_eis = SmallVector::one(initial_matcher_pos(ms.to_owned(), parser.span.lo));
let mut next_eis = Vec::new(); // or proceed normally
path: cx.current_expansion.module.directory.clone(),
ownership: cx.current_expansion.directory_ownership,
};
- let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), false);
+ let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false);
p.root_module_name = cx.current_expansion.module.mod_path.last()
.map(|id| id.name.as_str().to_string());
ast::ItemKind::MacroDef(ref body) => body.clone().into(),
_ => unreachable!(),
};
- let argument_map = match parse(sess, body, &argument_gram, None) {
+ let argument_map = match parse(sess, body, &argument_gram, None, true) {
Success(m) => m,
Failure(sp, tok) => {
let s = parse_failure_msg(tok);
(active, use_extern_macros, "1.15.0", Some(35896)),
- // Allows `break {expr}` with a value inside `loop`s.
- (active, loop_break_value, "1.14.0", Some(37339)),
-
// Allows #[target_feature(...)]
(active, target_feature, "1.15.0", None),
(accepted, question_mark, "1.13.0", Some(31436)),
// Allows `..` in tuple (struct) patterns
(accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
- (accepted, item_like_imports, "1.14.0", Some(35120)),
+ (accepted, item_like_imports, "1.15.0", Some(35120)),
// Allows using `Self` and associated types in struct expressions and patterns.
(accepted, more_struct_aliases, "1.16.0", Some(37544)),
// elide `'static` lifetimes in `static`s and `const`s
(accepted, pub_restricted, "1.18.0", Some(32409)),
// The #![windows_subsystem] attribute
(accepted, windows_subsystem, "1.18.0", Some(37499)),
+ // Allows `break {expr}` with a value inside `loop`s.
+ (accepted, loop_break_value, "1.19.0", Some(37339)),
);
// If you change this, please modify src/doc/unstable-book as well. You must
// move that documentation into the relevant place in the other docs, and
}
}
}
- ast::ExprKind::Break(_, Some(_)) => {
- gate_feature_post!(&self, loop_break_value, e.span,
- "`break` with a value is experimental");
- }
ast::ExprKind::Lit(ref lit) => {
if let ast::LitKind::Int(_, ref ty) = lit.node {
match *ty {
match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) {
Some(&(ascii_char, ascii_name)) => {
let msg =
- format!("unicode character '{}' ({}) looks much like '{}' ({}), but it's not",
+ format!("unicode character '{}' ({}) looks like '{}' ({}), but it's not",
ch, u_name, ascii_char, ascii_name);
err.span_help(span, &msg);
},
// Create a new parser from a source string
pub fn new_parser_from_source_str(sess: &ParseSess, name: String, source: String)
-> Parser {
- filemap_to_parser(sess, sess.codemap().new_filemap(name, source))
+ let mut parser = filemap_to_parser(sess, sess.codemap().new_filemap(name, source));
+ parser.recurse_into_file_modules = false;
+ parser
}
/// Create a new parser, handling errors as appropriate
/// Given stream and the `ParseSess`, produce a parser
pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser {
- Parser::new(sess, stream, None, false)
+ Parser::new(sess, stream, None, true, false)
}
/// Parse a string representing a character literal into its final form.
Err(_) => panic!("could not get snippet"),
}
}
+
+ // This tests that when parsing a string (rather than a file) we don't try
+ // and read in a file for a module declaration and just parse a stub.
+ // See `recurse_into_file_modules` in the parser.
+ #[test]
+ fn out_of_line_mod() {
+ let sess = ParseSess::new(FilePathMapping::empty());
+ let item = parse_item_from_source_str(
+ "foo".to_owned(),
+ "mod foo { struct S; mod this_does_not_exist; }".to_owned(),
+ &sess,
+ ).unwrap().unwrap();
+
+ if let ast::ItemKind::Mod(ref m) = item.node {
+ assert!(m.items.len() == 2);
+ } else {
+ panic!();
+ }
+ }
}
pub obsolete_set: HashSet<ObsoleteSyntax>,
/// Used to determine the path to externally loaded source files
pub directory: Directory,
+ /// Whether to parse sub-modules in other files.
+ pub recurse_into_file_modules: bool,
/// Name of the root module this parser originated from. If `None`, then the
/// name is not known. This does not change while the parser is descending
/// into modules, and sub-parsers have new values for this name.
pub cfg_mods: bool,
}
+
struct TokenCursor {
frame: TokenCursorFrame,
stack: Vec<TokenCursorFrame>,
pub fn new(sess: &'a ParseSess,
tokens: TokenStream,
directory: Option<Directory>,
+ recurse_into_file_modules: bool,
desugar_doc_comments: bool)
-> Self {
let mut parser = Parser {
prev_token_kind: PrevTokenKind::Other,
restrictions: Restrictions::empty(),
obsolete_set: HashSet::new(),
+ recurse_into_file_modules: recurse_into_file_modules,
directory: Directory { path: PathBuf::new(), ownership: DirectoryOwnership::Owned },
root_module_name: None,
expected_tokens: Vec::new(),
let tok = parser.next_tok();
parser.token = tok.tok;
parser.span = tok.sp;
+
if let Some(directory) = directory {
parser.directory = directory;
} else if parser.span != syntax_pos::DUMMY_SP {
parser.directory.path = PathBuf::from(sess.codemap().span_to_filename(parser.span));
parser.directory.path.pop();
}
+
parser.process_potential_macro_variable();
parser
}
mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
let item = self.parse_item_(attrs.clone(), false, true)?;
self.directory.ownership = old_directory_ownership;
+
match item {
Some(i) => Stmt {
id: ast::DUMMY_NODE_ID,
let id = self.parse_ident()?;
if self.check(&token::Semi) {
self.bump();
- if in_cfg {
+ if in_cfg && self.recurse_into_file_modules {
// This mod is in an external file. Let's go get it!
let ModulePathSuccess { path, directory_ownership, warn } =
self.submod_path(id, &outer_attrs, id_span)?;
} else {
let old_directory = self.directory.clone();
self.push_directory(id, &outer_attrs);
+
self.expect(&token::OpenDelim(token::Brace))?;
let mod_inner_lo = self.span;
let attrs = self.parse_inner_attributes()?;
let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?;
+
self.directory = old_directory;
Ok((id, ItemKind::Mod(module), Some(attrs)))
}
fn submod_path(&mut self,
id: ast::Ident,
outer_attrs: &[ast::Attribute],
- id_sp: Span) -> PResult<'a, ModulePathSuccess> {
+ id_sp: Span)
+ -> PResult<'a, ModulePathSuccess> {
if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
return Ok(ModulePathSuccess {
directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
path: cx.current_expansion.module.directory.clone(),
ownership: cx.current_expansion.directory_ownership,
};
- macro_parser::parse(cx.parse_sess(), tts, mtch, Some(directory))
+ macro_parser::parse(cx.parse_sess(), tts, mtch, Some(directory), true)
}
/// Check if this TokenTree is equal to the other, regardless of span information.
fn main() {
is_send::<Foo>();
//~^ ERROR the trait bound `*const u8: std::marker::Send` is not satisfied in `Foo`
- //~| NOTE within `Foo`, the trait `std::marker::Send` is not implemented for `*const u8`
//~| NOTE: `*const u8` cannot be sent between threads safely
//~| NOTE: required because it appears within the type `Baz`
//~| NOTE: required because it appears within the type `Bar`
fn f(p: Path) { }
//~^ ERROR the trait bound `[u8]: std::marker::Sized` is not satisfied in `std::path::Path`
-//~| NOTE within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
//~| NOTE `[u8]` does not have a constant size known at compile-time
//~| NOTE required because it appears within the type `std::path::Path`
//~| NOTE all local variables must have a statically known size
const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
-//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size
const CONST_FOO: str = *"foo";
//~^ ERROR `str: std::marker::Sized` is not satisfied
-//~| NOTE the trait `std::marker::Sized` is not implemented for `str`
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size
static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
-//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size
static STATIC_BAR: str = *"bar";
//~^ ERROR `str: std::marker::Sized` is not satisfied
-//~| NOTE the trait `std::marker::Sized` is not implemented for `str`
//~| NOTE does not have a constant size known at compile-time
//~| NOTE constant expressions must have a statically known size
+++ /dev/null
-// Copyright 2016 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.
-
-fn main() {
- loop {
- break 123; //~ ERROR `break` with a value is experimental
- }
-}
fn main() {
send(before());
//~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
- //~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
//~| NOTE `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
//~| NOTE required because it appears within the type `[closure
//~| NOTE required because it appears within the type `impl std::ops::Fn<(i32,)>`
send(after());
//~^ ERROR the trait bound `std::rc::Rc<std::cell::Cell<i32>>: std::marker::Send` is not satisfied
- //~| NOTE the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::cell::Cell<i32>>`
//~| NOTE `std::rc::Rc<std::cell::Cell<i32>>` cannot be sent between threads safely
//~| NOTE required because it appears within the type `[closure
//~| NOTE required because it appears within the type `impl std::ops::Fn<(i32,)>`
--- /dev/null
+// Copyright 2017 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.
+
+pub struct Nullable<T: NotNull>(T);
+
+pub trait NotNull {}
+
+pub trait IntoNullable {
+ type Nullable;
+}
+
+impl<T: NotNull> IntoNullable for T {
+ type Nullable = Nullable<T>;
+}
+
+impl<T: NotNull> IntoNullable for Nullable<T> {
+ type Nullable = Nullable<T>;
+}
+
+pub trait Expression {
+ type SqlType;
+}
+
+pub trait Column: Expression {}
+
+#[derive(Debug, Copy, Clone)]
+//~^ ERROR the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied
+pub enum ColumnInsertValue<Col, Expr> where
+ Col: Column,
+ Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>,
+{
+ Expression(Col, Expr),
+ Default(Col),
+}
+
+fn main() {}
pub trait Resources<'a> {}
pub trait Buffer<'a, R: Resources<'a>> {
- //~^ NOTE the lifetime 'a as defined on the trait at 13:0...
+ //~^ NOTE the lifetime 'a as defined on the trait at 13:1...
//~| NOTE ...does not necessarily outlive the lifetime 'a as defined on the trait
fn select(&self) -> BufferViewHandle<R>;
//~| ERROR mismatched types
//~| lifetime mismatch
//~| NOTE expected type `Resources<'_>`
- //~| NOTE the anonymous lifetime #1 defined on the method body at 17:4...
+ //~| NOTE the anonymous lifetime #1 defined on the method body at 17:5...
}
pub struct BufferViewHandle<'a, R: 'a+Resources<'a>>(&'a R);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(loop_break_value)]
#![feature(never_type)]
fn main() {
fn main() {
Index::index(&[] as &[i32], 2u32);
//~^ ERROR E0277
- //~| NOTE the trait `Index<u32>` is not implemented for `[i32]`
//~| NOTE trait message
//~| NOTE required by
Index::index(&[] as &[i32], Foo(2u32));
//~^ ERROR E0277
- //~| NOTE the trait `Index<Foo<u32>>` is not implemented for `[i32]`
//~| NOTE on impl for Foo
//~| NOTE required by
Index::index(&[] as &[i32], Bar(2u32));
//~^ ERROR E0277
- //~| NOTE the trait `Index<Bar<u32>>` is not implemented for `[i32]`
//~| NOTE on impl for Bar
//~| NOTE required by
}
fn main() {
Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
//~^ ERROR E0277
- //~| NOTE the trait `Index<u32>` is not implemented for `[i32]`
//~| NOTE a usize is required
//~| NOTE required by
}
//~^ ERROR
//~^^ NOTE a collection of type `std::option::Option<std::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
//~^^^ NOTE required by `collect`
- //~| NOTE the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option<std::vec::Vec<u8>>`
+
let x: String = foobar(); //~ ERROR
//~^ NOTE test error `std::string::String` with `u8` `_` `u32`
//~^^ NOTE required by `foobar`
- //~| NOTE the trait `Foo<u8, _, u32>` is not implemented for `std::string::String`
}
let x = &[1, 2, 3] as &[i32];
x[1i32]; //~ ERROR E0277
//~| NOTE slice indices are of type `usize` or ranges of `usize`
- //~| NOTE trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32`
//~| NOTE required because of the requirements on the impl of `std::ops::Index<i32>`
x[..1i32]; //~ ERROR E0277
//~| NOTE slice indices are of type `usize` or ranges of `usize`
- //~| NOTE trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo<i32>`
//~| NOTE requirements on the impl of `std::ops::Index<std::ops::RangeTo<i32>>`
}
--- /dev/null
+// Copyright 2017 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.
+
+fn foo<T: PartialEq>(a: &T, b: T) {
+ a == b; //~ ERROR E0277
+ //~| NOTE can't compare `&T` with `T`
+ //~| HELP the trait `std::cmp::PartialEq<T>` is not implemented for `&T`
+ //~| HELP consider adding a `where &T: std::cmp::PartialEq<T>` bound
+}
+
+fn main() {
+ foo(&1, 1);
+}
// suggest a where-clause, if needed
mem::size_of::<U>();
//~^ ERROR `U: std::marker::Sized` is not satisfied
- //~| NOTE the trait `std::marker::Sized` is not implemented for `U`
//~| HELP consider adding a `where U: std::marker::Sized` bound
//~| NOTE required by `std::mem::size_of`
+ //~| NOTE `U` does not have a constant size known at compile-time
+ //~| HELP the trait `std::marker::Sized` is not implemented for `U`
mem::size_of::<Misc<U>>();
//~^ ERROR `U: std::marker::Sized` is not satisfied
- //~| NOTE the trait `std::marker::Sized` is not implemented for `U`
//~| HELP consider adding a `where U: std::marker::Sized` bound
//~| NOTE required because it appears within the type `Misc<U>`
//~| NOTE required by `std::mem::size_of`
+ //~| NOTE `U` does not have a constant size known at compile-time
+ //~| HELP within `Misc<U>`, the trait `std::marker::Sized` is not implemented for `U`
// ... even if T occurs as a type parameter
<u64 as From<T>>::from;
//~^ ERROR `u64: std::convert::From<T>` is not satisfied
- //~| NOTE the trait `std::convert::From<T>` is not implemented for `u64`
//~| HELP consider adding a `where u64: std::convert::From<T>` bound
//~| NOTE required by `std::convert::From::from`
+ //~| NOTE the trait `std::convert::From<T>` is not implemented for `u64`
<u64 as From<<T as Iterator>::Item>>::from;
//~^ ERROR `u64: std::convert::From<<T as std::iter::Iterator>::Item>` is not satisfied
- //~| NOTE the trait `std::convert::From<<T as std::iter::Iterator>::Item>` is not implemented
//~| HELP consider adding a `where u64:
//~| NOTE required by `std::convert::From::from`
+ //~| NOTE the trait `std::convert::From<<T as std::iter::Iterator>::Item>` is not implemented
// ... but not if there are inference variables
<Misc<_> as From<T>>::from;
//~^ ERROR `Misc<_>: std::convert::From<T>` is not satisfied
- //~| NOTE the trait `std::convert::From<T>` is not implemented for `Misc<_>`
//~| NOTE required by `std::convert::From::from`
+ //~| NOTE the trait `std::convert::From<T>` is not implemented for `Misc<_>`
// ... and also not if the error is not related to the type
mem::size_of::<[T]>();
//~^ ERROR `[T]: std::marker::Sized` is not satisfied
- //~| NOTE the trait `std::marker::Sized` is not implemented for `[T]`
//~| NOTE `[T]` does not have a constant size
//~| NOTE required by `std::mem::size_of`
+ //~| HELP the trait `std::marker::Sized` is not implemented for `[T]`
mem::size_of::<[&U]>();
//~^ ERROR `[&U]: std::marker::Sized` is not satisfied
- //~| NOTE the trait `std::marker::Sized` is not implemented for `[&U]`
//~| NOTE `[&U]` does not have a constant size
//~| NOTE required by `std::mem::size_of`
+ //~| HELP the trait `std::marker::Sized` is not implemented for `[&U]`
}
fn main() {
--- /dev/null
+// Copyright 2017 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.
+
+// Check that when we compile the static `XXX` into MIR, we do not
+// generate `StorageStart` or `StorageEnd` statements.
+
+// ignore-tidy-linelength
+
+static XXX: &'static Foo = &Foo {
+ tup: "hi",
+ data: &[
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ (0, 1), (0, 2), (0, 3),
+ ]
+};
+
+#[derive(Debug)]
+struct Foo {
+ tup: &'static str,
+ data: &'static [(u32, u32)]
+}
+
+fn main() {
+ println!("{:?}", XXX);
+}
+
+// END RUST SOURCE
+// START rustc.node4.mir_map.0.mir
+// bb0: {
+// _7 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:29:9: 29:15
+// _8 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:29:17: 29:23
+// _9 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:29:25: 29:31
+// _10 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:30:9: 30:15
+// _11 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:30:17: 30:23
+// _12 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:30:25: 30:31
+// _13 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:31:9: 31:15
+// _14 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:31:17: 31:23
+// _15 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:31:25: 31:31
+// _16 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:32:9: 32:15
+// _17 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:32:17: 32:23
+// _18 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:32:25: 32:31
+// _19 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:33:9: 33:15
+// _20 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:33:17: 33:23
+// _21 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:33:25: 33:31
+// _22 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:34:9: 34:15
+// _23 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:34:17: 34:23
+// _24 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:34:25: 34:31
+// _25 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:35:9: 35:15
+// _26 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:35:17: 35:23
+// _27 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:35:25: 35:31
+// _28 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:36:9: 36:15
+// _29 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:36:17: 36:23
+// _30 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:36:25: 36:31
+// _31 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:37:9: 37:15
+// _32 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:37:17: 37:23
+// _33 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:37:25: 37:31
+// _34 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:38:9: 38:15
+// _35 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:38:17: 38:23
+// _36 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:38:25: 38:31
+// _37 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:39:9: 39:15
+// _38 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:39:17: 39:23
+// _39 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:39:25: 39:31
+// _40 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:40:9: 40:15
+// _41 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:40:17: 40:23
+// _42 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:40:25: 40:31
+// _43 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:41:9: 41:15
+// _44 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:41:17: 41:23
+// _45 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:41:25: 41:31
+// _46 = (const 0u32, const 1u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:42:9: 42:15
+// _47 = (const 0u32, const 2u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:42:17: 42:23
+// _48 = (const 0u32, const 3u32); // scope 0 at src/test/mir-opt/basic_assignment.rs:42:25: 42:31
+// _6 = [_7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48]; // scope 0 at src/test/mir-opt/basic_assignment.rs:28:12: 43:6
+// _5 = &_6; // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
+// _4 = &(*_5); // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
+// _3 = _4 as &'static [(u32, u32)] (Unsize); // scope 0 at src/test/mir-opt/basic_assignment.rs:28:11: 43:6
+// _2 = Foo { tup: const "hi", data: _3 }; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:29: 44:2
+// _1 = &_2; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:28: 44:2
+// _0 = &(*_1); // scope 0 at src/test/mir-opt/basic_assignment.rs:26:28: 44:2
+// return; // scope 0 at src/test/mir-opt/basic_assignment.rs:26:1: 44:3
+// }
+// END rustc.node4.mir_map.0.mir
// except according to those terms.
// compile-flags: -Z parse-only
-// ignore-tidy-linelength
fn main() {
let y = 0;
//~^ ERROR unknown start of token: \u{37e}
- //~^^ HELP unicode character ';' (Greek Question Mark) looks much like ';' (Semicolon), but it's not
+ //~^^ HELP unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it's not
}
trait Sized {}
#[lang = "copy"]
trait Copy {}
+#[lang = "freeze"]
+trait Freeze {}
#[cfg(target_has_atomic = "8")]
pub unsafe fn atomic_u8(x: *mut u8) {
const BOTTOM: Self;
}
-// FIXME(#33573): this should work without the 'static lifetime bound.
-impl<T: 'static> Lattice for Option<T> {
+impl<T> Lattice for Option<T> {
const BOTTOM: Option<T> = None;
}
// like to revisit these and potentially change them. --nmatsakis
#![feature(never_type)]
-#![feature(loop_break_value)]
trait BadDefault {
fn default() -> Self;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(loop_break_value)]
#![feature(never_type)]
#[allow(unused)]
--- /dev/null
+// Copyright 2017 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.
+
+#![crate_name = "foo"]
+
+pub mod iter {
+ mod range {
+ pub struct StepBy;
+ }
+ pub use self::range::StepBy as DeprecatedStepBy;
+ pub struct StepBy;
+}
--- /dev/null
+// Copyright 2017 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.
+
+// aux-build:renamed-via-module.rs
+// build-aux-docs
+// ignore-cross-compile
+
+#![crate_name = "bar"]
+
+extern crate foo;
+
+// @has foo/iter/index.html
+// @has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy"
+// @has - '//a/[@href="struct.StepBy.html"]' "StepBy"
+// @has foo/iter/struct.DeprecatedStepBy.html
+// @has - '//h1' "Struct foo::iter::DeprecatedStepBy"
+// @has foo/iter/struct.StepBy.html
+// @has - '//h1' "Struct foo::iter::StepBy"
+
+// @has bar/iter/index.html
+// @has - '//a/[@href="struct.DeprecatedStepBy.html"]' "DeprecatedStepBy"
+// @has - '//a/[@href="struct.StepBy.html"]' "StepBy"
+// @has bar/iter/struct.DeprecatedStepBy.html
+// @has - '//h1' "Struct bar::iter::DeprecatedStepBy"
+// @has bar/iter/struct.StepBy.html
+// @has - '//h1' "Struct bar::iter::StepBy"
+pub use foo::iter;
--> $DIR/equality.rs:34:9
|
34 | n + sum_to(n - 1)
- | ^^^^^^^^^^^^^^^^^ the trait `std::ops::Add<impl Foo>` is not implemented for `u32`
+ | ^^^^^^^^^^^^^^^^^ no implementation for `u32 + impl Foo`
|
- = note: no implementation for `u32 + impl Foo`
+ = help: the trait `std::ops::Add<impl Foo>` is not implemented for `u32`
error[E0308]: mismatched types
--> $DIR/equality.rs:53:18
12 | if x > y { x } else { y }
| ^
|
-note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:0...
+note: ...the reference is valid for the lifetime 'a as defined on the function body at 11:1...
--> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
|
11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
12 | | if x > y { x } else { y }
13 | | }
| |_^
-note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:0
+note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 11:1
--> $DIR/ex1-return-one-existing-name-if-else.rs:11:1
|
11 | / fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {
|
= note: expected type `Ref<'a, _>`
found type `Ref<'_, _>`
-note: the anonymous lifetime #2 defined on the function body at 15:0...
+note: the anonymous lifetime #2 defined on the function body at 15:1...
--> $DIR/ex2a-push-one-existing-name.rs:15:1
|
15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
-note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:0
+note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:1
--> $DIR/ex2a-push-one-existing-name.rs:15:1
|
15 | / fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<i32>) {
|
= note: expected type `Ref<'_, _>`
found type `Ref<'_, _>`
-note: the anonymous lifetime #3 defined on the function body at 15:0...
+note: the anonymous lifetime #3 defined on the function body at 15:1...
--> $DIR/ex2b-push-no-existing-names.rs:15:1
|
15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
16 | | x.push(y);
17 | | }
| |_^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:0
+note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:1
--> $DIR/ex2b-push-no-existing-names.rs:15:1
|
15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
16 | let z = Ref { data: y.data };
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:1...
--> $DIR/ex2c-push-inference-variable.rs:15:1
|
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
16 | let z = Ref { data: y.data };
| ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:1...
--> $DIR/ex2c-push-inference-variable.rs:15:1
|
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
17 | let b = Ref { data: y.data };
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:1...
--> $DIR/ex2d-push-inference-variable-2.rs:15:1
|
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
17 | let b = Ref { data: y.data };
| ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:1...
--> $DIR/ex2d-push-inference-variable-2.rs:15:1
|
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
17 | let b = Ref { data: y.data };
| ^^^
|
-note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:0...
+note: first, the lifetime cannot outlive the lifetime 'c as defined on the function body at 15:1...
--> $DIR/ex2e-push-inference-variable-3.rs:15:1
|
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
|
17 | let b = Ref { data: y.data };
| ^^^^^^
-note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:0...
+note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 15:1...
--> $DIR/ex2e-push-inference-variable-3.rs:15:1
|
15 | / fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(loop_break_value)]
#![allow(unused_variables)]
use std::ptr;
error[E0571]: `break` with value from a `for` loop
- --> $DIR/loop-break-value-no-repeat.rs:23:9
+ --> $DIR/loop-break-value-no-repeat.rs:22:9
|
-23 | break 22
+22 | break 22
| ^^^^^^^^ can only break with a value inside `loop`
error: aborting due to previous error
--> $DIR/binops.rs:12:5
|
12 | 1 + Some(1);
- | ^^^^^^^^^^^ the trait `std::ops::Add<std::option::Option<{integer}>>` is not implemented for `{integer}`
+ | ^^^^^^^^^^^ no implementation for `{integer} + std::option::Option<{integer}>`
|
- = note: no implementation for `{integer} + std::option::Option<{integer}>`
+ = help: the trait `std::ops::Add<std::option::Option<{integer}>>` is not implemented for `{integer}`
error[E0277]: the trait bound `usize: std::ops::Sub<std::option::Option<{integer}>>` is not satisfied
--> $DIR/binops.rs:13:5
|
13 | 2 as usize - Some(1);
- | ^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Sub<std::option::Option<{integer}>>` is not implemented for `usize`
+ | ^^^^^^^^^^^^^^^^^^^^ no implementation for `usize - std::option::Option<{integer}>`
|
- = note: no implementation for `usize - std::option::Option<{integer}>`
+ = help: the trait `std::ops::Sub<std::option::Option<{integer}>>` is not implemented for `usize`
error[E0277]: the trait bound `{integer}: std::ops::Mul<()>` is not satisfied
--> $DIR/binops.rs:14:5
|
14 | 3 * ();
- | ^^^^^^ the trait `std::ops::Mul<()>` is not implemented for `{integer}`
+ | ^^^^^^ no implementation for `{integer} * ()`
|
- = note: no implementation for `{integer} * ()`
+ = help: the trait `std::ops::Mul<()>` is not implemented for `{integer}`
error[E0277]: the trait bound `{integer}: std::ops::Div<&str>` is not satisfied
--> $DIR/binops.rs:15:5
|
15 | 4 / "";
- | ^^^^^^ the trait `std::ops::Div<&str>` is not implemented for `{integer}`
+ | ^^^^^^ no implementation for `{integer} / &str`
|
- = note: no implementation for `{integer} / &str`
+ = help: the trait `std::ops::Div<&str>` is not implemented for `{integer}`
error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::string::String>` is not satisfied
--> $DIR/binops.rs:16:5
|
16 | 5 < String::new();
- | ^^^^^^^^^^^^^^^^^ the trait `std::cmp::PartialEq<std::string::String>` is not implemented for `{integer}`
+ | ^^^^^^^^^^^^^^^^^ can't compare `{integer}` with `std::string::String`
|
- = note: can't compare `{integer}` with `std::string::String`
+ = help: the trait `std::cmp::PartialEq<std::string::String>` is not implemented for `{integer}`
error[E0277]: the trait bound `{integer}: std::cmp::PartialOrd<std::string::String>` is not satisfied
--> $DIR/binops.rs:16:5
|
16 | 5 < String::new();
- | ^^^^^^^^^^^^^^^^^ the trait `std::cmp::PartialOrd<std::string::String>` is not implemented for `{integer}`
+ | ^^^^^^^^^^^^^^^^^ can't compare `{integer}` with `std::string::String`
|
- = note: can't compare `{integer}` with `std::string::String`
+ = help: the trait `std::cmp::PartialOrd<std::string::String>` is not implemented for `{integer}`
error[E0277]: the trait bound `{integer}: std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not satisfied
--> $DIR/binops.rs:17:5
|
17 | 6 == Ok(1);
- | ^^^^^^^^^^ the trait `std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not implemented for `{integer}`
+ | ^^^^^^^^^^ can't compare `{integer}` with `std::result::Result<{integer}, _>`
|
- = note: can't compare `{integer}` with `std::result::Result<{integer}, _>`
+ = help: the trait `std::cmp::PartialEq<std::result::Result<{integer}, _>>` is not implemented for `{integer}`
error: aborting due to 7 previous errors
--> $DIR/cast-rfc0401.rs:63:13
|
63 | let _ = fat_v as *const Foo;
- | ^^^^^ the trait `std::marker::Sized` is not implemented for `[u8]`
+ | ^^^^^ `[u8]` does not have a constant size known at compile-time
|
- = note: `[u8]` does not have a constant size known at compile-time
+ = help: the trait `std::marker::Sized` is not implemented for `[u8]`
= note: required for the cast to the object type `Foo`
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> $DIR/cast-rfc0401.rs:72:13
|
72 | let _ = a as *const Foo;
- | ^ the trait `std::marker::Sized` is not implemented for `str`
+ | ^ `str` does not have a constant size known at compile-time
|
- = note: `str` does not have a constant size known at compile-time
+ = help: the trait `std::marker::Sized` is not implemented for `str`
= note: required for the cast to the object type `Foo`
error: casting `&{float}` as `f32` is invalid
--> $DIR/issue-5035-2.rs:14:8
|
14 | fn foo(_x: K) {} //~ ERROR: `I + 'static: std::marker::Sized` is not satisfied
- | ^^ the trait `std::marker::Sized` is not implemented for `I + 'static`
+ | ^^ `I + 'static` does not have a constant size known at compile-time
|
- = note: `I + 'static` does not have a constant size known at compile-time
+ = help: the trait `std::marker::Sized` is not implemented for `I + 'static`
= note: all local variables must have a statically known size
error: aborting due to previous error
25 | | bar(x,
26 | |
27 | | y),
- | |______________^ the trait `std::ops::Add<()>` is not implemented for `u32`
+ | |______________^ no implementation for `u32 + ()`
|
- = note: no implementation for `u32 + ()`
+ = help: the trait `std::ops::Add<()>` is not implemented for `u32`
error: aborting due to previous error
println!("expected {}:\n{}\n", kind, expected);
println!("diff of {}:\n", kind);
- for diff in diff::lines(actual, expected) {
+ for diff in diff::lines(expected, actual) {
match diff {
- diff::Result::Left(l) => println!("+{}", l),
+ diff::Result::Left(l) => println!("-{}", l),
diff::Result::Both(l, _) => println!(" {}", l),
- diff::Result::Right(r) => println!("-{}", r),
+ diff::Result::Right(r) => println!("+{}", r),
}
}
-Subproject commit daa2a05ebe7b8d07a309e8891ebc548652362954
+Subproject commit 8707ceaf040f6d87b67a002de16a8d2bc4db7a41