diff options
116 files changed, 427 insertions, 3285 deletions
diff --git a/.mailmap b/.mailmap index e5aad52ef4b..ea8ef0eebf9 100644 --- a/.mailmap +++ b/.mailmap @@ -5,7 +5,6 @@ # email addresses. # -Aaron Power <theaaronepower@gmail.com> Erin Power <xampprocky@gmail.com> Aaron Todd <github@opprobrio.us> Abhishek Chanda <abhishek.becs@gmail.com> Abhishek Chanda <abhishek@cloudscaling.com> Adolfo Ochagavía <aochagavia92@gmail.com> @@ -84,6 +83,8 @@ Eric Holk <eric.holk@gmail.com> <eholk@mozilla.com> Eric Holmes <eric@ejholmes.net> Eric Reed <ecreed@cs.washington.edu> <ereed@mozilla.com> Erick Tryzelaar <erick.tryzelaar@gmail.com> <etryzelaar@iqt.org> +Erin Power <xampprocky@gmail.com> <theaaronepower@gmail.com> +Erin Power <xampprocky@gmail.com> <Aaronepower@users.noreply.github.com> Esteban Küber <esteban@kuber.com.ar> <esteban@commure.com> Esteban Küber <esteban@kuber.com.ar> <estebank@users.noreply.github.com> Esteban Küber <esteban@kuber.com.ar> <github@kuber.com.ar> diff --git a/Cargo.lock b/Cargo.lock index 1676b5b1275..45ad7fee9f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -420,25 +420,6 @@ dependencies = [ ] [[package]] -name = "chalk-engine" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ec698a6f053a23bfbe646d9f2fde4b02abc19125595270a99e6f44ae0bdd1a" -dependencies = [ - "chalk-macros", - "rustc-hash", -] - -[[package]] -name = "chalk-macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e" -dependencies = [ - "lazy_static 0.2.11", -] - -[[package]] name = "chrono" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2494,9 +2475,9 @@ checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" [[package]] name = "polonius-engine" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e478d7c38eb785c6416cbe58df12aa55d7aefa3759b6d3e044b2ed03f423cec" +checksum = "04d8ef65e3f89ecaec9ca7cb0e0911b4617352d4494018bcf934992f03f2024c" dependencies = [ "datafrog", "log", @@ -3110,7 +3091,6 @@ dependencies = [ "backtrace", "bitflags", "byteorder", - "chalk-engine", "jobserver", "log", "measureme", @@ -4144,7 +4124,6 @@ checksum = "b725dadae9fabc488df69a287f5a99c5eaf5d10853842a8a3dfac52476f544ee" name = "rustc_traits" version = "0.0.0" dependencies = [ - "chalk-engine", "log", "rustc", "rustc_ast", diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 5c39f5d5bc3..7cffc472930 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -443,7 +443,7 @@ fn change_toolstate( if new_state != state { eprintln!("The state of `{}` has changed from `{}` to `{}`", tool, state, new_state); if new_state < state { - if !["rustc-guide", "miri", "embedded-book"].contains(&tool.as_str()) { + if !NIGHTLY_TOOLS.iter().any(|(name, _path)| name == tool) { regressed = true; } } diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index f41404bf8ca..73e8121868a 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -165,8 +165,8 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl AllocRef for Global { #[inline] - unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> { - NonNull::new(alloc(layout)).ok_or(AllocErr) + unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> { + NonNull::new(alloc(layout)).ok_or(AllocErr).map(|p| (p, layout.size())) } #[inline] @@ -180,13 +180,13 @@ unsafe impl AllocRef for Global { ptr: NonNull<u8>, layout: Layout, new_size: usize, - ) -> Result<NonNull<u8>, AllocErr> { - NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr) + ) -> Result<(NonNull<u8>, usize), AllocErr> { + NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr).map(|p| (p, new_size)) } #[inline] - unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> { - NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr) + unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> { + NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr).map(|p| (p, layout.size())) } } @@ -201,7 +201,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { } else { let layout = Layout::from_size_align_unchecked(size, align); match Global.alloc(layout) { - Ok(ptr) => ptr.as_ptr(), + Ok((ptr, _)) => ptr.as_ptr(), Err(_) => handle_alloc_error(layout), } } diff --git a/src/liballoc/alloc/tests.rs b/src/liballoc/alloc/tests.rs index c902971638b..55944398e16 100644 --- a/src/liballoc/alloc/tests.rs +++ b/src/liballoc/alloc/tests.rs @@ -8,7 +8,7 @@ use test::Bencher; fn allocate_zeroed() { unsafe { let layout = Layout::from_size_align(1024, 1).unwrap(); - let ptr = + let (ptr, _) = Global.alloc_zeroed(layout.clone()).unwrap_or_else(|_| handle_alloc_error(layout)); let mut i = ptr.cast::<u8>().as_ptr(); diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 81b0e9817d2..9a7d0d9aeba 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -200,7 +200,7 @@ impl<T> Box<T> { let ptr = if layout.size() == 0 { NonNull::dangling() } else { - Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).cast() + Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).0.cast() }; Box::from_raw(ptr.as_ptr()) } @@ -270,7 +270,7 @@ impl<T> Box<[T]> { let ptr = if layout.size() == 0 { NonNull::dangling() } else { - Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).cast() + Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).0.cast() }; Box::from_raw(slice::from_raw_parts_mut(ptr.as_ptr(), len)) } diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index c1bd68a020a..362755f8b7f 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -1191,7 +1191,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker:: let right_len = right_node.len(); // necessary for correctness, but in a private module - assert!(left_len + right_len + 1 <= CAPACITY); + assert!(left_len + right_len < CAPACITY); unsafe { ptr::write( diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 144654946a2..345834d7daa 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -72,7 +72,7 @@ impl<T, A: AllocRef> RawVec<T, A> { RawVec::allocate_in(capacity, true, a) } - fn allocate_in(capacity: usize, zeroed: bool, mut a: A) -> Self { + fn allocate_in(mut capacity: usize, zeroed: bool, mut a: A) -> Self { unsafe { let elem_size = mem::size_of::<T>(); @@ -87,7 +87,10 @@ impl<T, A: AllocRef> RawVec<T, A> { let layout = Layout::from_size_align(alloc_size, align).unwrap(); let result = if zeroed { a.alloc_zeroed(layout) } else { a.alloc(layout) }; match result { - Ok(ptr) => ptr.cast(), + Ok((ptr, size)) => { + capacity = size / elem_size; + ptr.cast() + } Err(_) => handle_alloc_error(layout), } }; @@ -280,7 +283,7 @@ impl<T, A: AllocRef> RawVec<T, A> { // 0, getting to here necessarily means the `RawVec` is overfull. assert!(elem_size != 0, "capacity overflow"); - let (new_cap, ptr) = match self.current_layout() { + let (ptr, new_cap) = match self.current_layout() { Some(cur) => { // Since we guarantee that we never allocate more than // `isize::MAX` bytes, `elem_size * self.cap <= isize::MAX` as @@ -297,7 +300,7 @@ impl<T, A: AllocRef> RawVec<T, A> { alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow()); let ptr_res = self.a.realloc(NonNull::from(self.ptr).cast(), cur, new_size); match ptr_res { - Ok(ptr) => (new_cap, ptr), + Ok((ptr, new_size)) => (ptr, new_size / elem_size), Err(_) => handle_alloc_error(Layout::from_size_align_unchecked( new_size, cur.align(), @@ -310,7 +313,7 @@ impl<T, A: AllocRef> RawVec<T, A> { let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 }; let layout = Layout::array::<T>(new_cap).unwrap(); match self.a.alloc(layout) { - Ok(ptr) => (new_cap, ptr), + Ok((ptr, new_size)) => (ptr, new_size / elem_size), Err(_) => handle_alloc_error(layout), } } @@ -598,7 +601,7 @@ impl<T, A: AllocRef> RawVec<T, A> { let align = mem::align_of::<T>(); let old_layout = Layout::from_size_align_unchecked(old_size, align); match self.a.realloc(NonNull::from(self.ptr).cast(), old_layout, new_size) { - Ok(p) => self.ptr = p.cast().into(), + Ok((ptr, _)) => self.ptr = ptr.cast().into(), Err(_) => { handle_alloc_error(Layout::from_size_align_unchecked(new_size, align)) } @@ -631,6 +634,8 @@ impl<T, A: AllocRef> RawVec<T, A> { fallibility: Fallibility, strategy: ReserveStrategy, ) -> Result<(), TryReserveError> { + let elem_size = mem::size_of::<T>(); + unsafe { // NOTE: we don't early branch on ZSTs here because we want this // to actually catch "asking for more than usize::MAX" in that case. @@ -662,7 +667,7 @@ impl<T, A: AllocRef> RawVec<T, A> { None => self.a.alloc(new_layout), }; - let ptr = match (res, fallibility) { + let (ptr, new_cap) = match (res, fallibility) { (Err(AllocErr), Infallible) => handle_alloc_error(new_layout), (Err(AllocErr), Fallible) => { return Err(TryReserveError::AllocError { @@ -670,7 +675,7 @@ impl<T, A: AllocRef> RawVec<T, A> { non_exhaustive: (), }); } - (Ok(ptr), _) => ptr, + (Ok((ptr, new_size)), _) => (ptr, new_size / elem_size), }; self.ptr = ptr.cast().into(); diff --git a/src/liballoc/raw_vec/tests.rs b/src/liballoc/raw_vec/tests.rs index 63087501f0e..860058debe1 100644 --- a/src/liballoc/raw_vec/tests.rs +++ b/src/liballoc/raw_vec/tests.rs @@ -20,7 +20,7 @@ fn allocator_param() { fuel: usize, } unsafe impl AllocRef for BoundedAlloc { - unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> { + unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> { let size = layout.size(); if size > self.fuel { return Err(AllocErr); diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 6ee128f4fa1..9c286298aa6 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -923,7 +923,7 @@ impl<T: ?Sized> Rc<T> { let layout = Layout::new::<RcBox<()>>().extend(value_layout).unwrap().0.pad_to_align(); // Allocate for the layout. - let mem = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + let (mem, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); // Initialize the RcBox let inner = mem_to_rcbox(mem.as_ptr()); diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 9bd708c0f59..4a0cf2984ed 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -784,7 +784,7 @@ impl<T: ?Sized> Arc<T> { // reference (see #54908). let layout = Layout::new::<ArcInner<()>>().extend(value_layout).unwrap().0.pad_to_align(); - let mem = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + let (mem, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); // Initialize the ArcInner let inner = mem_to_arcinner(mem.as_ptr()); diff --git a/src/liballoc/tests/heap.rs b/src/liballoc/tests/heap.rs index 7fcfcf9b294..d159126f426 100644 --- a/src/liballoc/tests/heap.rs +++ b/src/liballoc/tests/heap.rs @@ -20,7 +20,7 @@ fn check_overalign_requests<T: AllocRef>(mut allocator: T) { unsafe { let pointers: Vec<_> = (0..iterations) .map(|_| { - allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() + allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap().0 }) .collect(); for &ptr in &pointers { diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 71f7f971eab..f3a2b73f2b8 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -11,12 +11,6 @@ use crate::num::NonZeroUsize; use crate::ptr::{self, NonNull}; use crate::usize; -/// Represents the combination of a starting address and -/// a total capacity of the returned block. -#[unstable(feature = "allocator_api", issue = "32838")] -#[derive(Debug)] -pub struct Excess(pub NonNull<u8>, pub usize); - const fn size_align<T>() -> (usize, usize) { (mem::size_of::<T>(), mem::align_of::<T>()) } @@ -593,13 +587,12 @@ pub unsafe trait GlobalAlloc { /// /// * the starting address for that memory block was previously /// returned by a previous call to an allocation method (`alloc`, -/// `alloc_zeroed`, `alloc_excess`) or reallocation method -/// (`realloc`, `realloc_excess`), and +/// `alloc_zeroed`) or reallocation method (`realloc`), and /// /// * the memory block has not been subsequently deallocated, where /// blocks are deallocated either by being passed to a deallocation -/// method (`dealloc`, `dealloc_one`, `dealloc_array`) or by being -/// passed to a reallocation method (see above) that returns `Ok`. +/// method (`dealloc`) or by being passed to a reallocation method +/// (see above) that returns `Ok`. /// /// A note regarding zero-sized types and zero-sized layouts: many /// methods in the `AllocRef` trait state that allocation requests @@ -625,11 +618,9 @@ pub unsafe trait GlobalAlloc { /// /// 2. The block's size must fall in the range `[use_min, use_max]`, where: /// -/// * `use_min` is `self.usable_size(layout).0`, and +/// * `use_min` is `layout.size()`, and /// -/// * `use_max` is the capacity that was (or would have been) -/// returned when (if) the block was allocated via a call to -/// `alloc_excess` or `realloc_excess`. +/// * `use_max` is the capacity that was returned. /// /// Note that: /// @@ -643,6 +634,9 @@ pub unsafe trait GlobalAlloc { /// currently allocated via an allocator `a`, then it is legal to /// use that layout to deallocate it, i.e., `a.dealloc(ptr, k);`. /// +/// * if an allocator does not support overallocating, it is fine to +/// simply return `layout.size()` as the allocated size. +/// /// # Safety /// /// The `AllocRef` trait is an `unsafe` trait for a number of reasons, and @@ -671,8 +665,9 @@ pub unsafe trait AllocRef { // However in jemalloc for example, // `mallocx(0)` is documented as undefined behavior.) - /// Returns a pointer meeting the size and alignment guarantees of - /// `layout`. + /// On success, returns a pointer meeting the size and alignment + /// guarantees of `layout` and the actual size of the allocated block, + /// which must be greater than or equal to `layout.size()`. /// /// If this method returns an `Ok(addr)`, then the `addr` returned /// will be non-null address pointing to a block of storage @@ -709,7 +704,7 @@ pub unsafe trait AllocRef { /// rather than directly invoking `panic!` or similar. /// /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr>; + unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr>; /// Deallocate the memory referenced by `ptr`. /// @@ -728,38 +723,31 @@ pub unsafe trait AllocRef { /// to allocate that block of memory. unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout); - // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS == - // usable_size - - /// Returns bounds on the guaranteed usable size of a successful - /// allocation created with the specified `layout`. - /// - /// In particular, if one has a memory block allocated via a given - /// allocator `a` and layout `k` where `a.usable_size(k)` returns - /// `(l, u)`, then one can pass that block to `a.dealloc()` with a - /// layout in the size range [l, u]. - /// - /// (All implementors of `usable_size` must ensure that - /// `l <= k.size() <= u`) - /// - /// Both the lower- and upper-bounds (`l` and `u` respectively) - /// are provided, because an allocator based on size classes could - /// misbehave if one attempts to deallocate a block without - /// providing a correct value for its size (i.e., one within the - /// range `[l, u]`). - /// - /// Clients who wish to make use of excess capacity are encouraged - /// to use the `alloc_excess` and `realloc_excess` instead, as - /// this method is constrained to report conservative values that - /// serve as valid bounds for *all possible* allocation method - /// calls. - /// - /// However, for clients that do not wish to track the capacity - /// returned by `alloc_excess` locally, this method is likely to - /// produce useful results. - #[inline] - fn usable_size(&self, layout: &Layout) -> (usize, usize) { - (layout.size(), layout.size()) + /// Behaves like `alloc`, but also ensures that the contents + /// are set to zero before being returned. + /// + /// # Safety + /// + /// This function is unsafe for the same reasons that `alloc` is. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `layout` does not meet allocator's size or alignment + /// constraints, just as in `alloc`. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> { + let size = layout.size(); + let result = self.alloc(layout); + if let Ok((p, _)) = result { + ptr::write_bytes(p.as_ptr(), 0, size); + } + result } // == METHODS FOR MEMORY REUSE == @@ -767,9 +755,10 @@ pub unsafe trait AllocRef { /// Returns a pointer suitable for holding data described by /// a new layout with `layout`’s alignment and a size given - /// by `new_size`. To - /// accomplish this, this may extend or shrink the allocation - /// referenced by `ptr` to fit the new layout. + /// by `new_size` and the actual size of the allocated block. + /// The latter is greater than or equal to `layout.size()`. + /// To accomplish this, the allocator may extend or shrink + /// the allocation referenced by `ptr` to fit the new layout. /// /// If this returns `Ok`, then ownership of the memory block /// referenced by `ptr` has been transferred to this @@ -824,23 +813,25 @@ pub unsafe trait AllocRef { ptr: NonNull<u8>, layout: Layout, new_size: usize, - ) -> Result<NonNull<u8>, AllocErr> { + ) -> Result<(NonNull<u8>, usize), AllocErr> { let old_size = layout.size(); - if new_size >= old_size { - if let Ok(()) = self.grow_in_place(ptr, layout, new_size) { - return Ok(ptr); + if new_size > old_size { + if let Ok(size) = self.grow_in_place(ptr, layout, new_size) { + return Ok((ptr, size)); } } else if new_size < old_size { - if let Ok(()) = self.shrink_in_place(ptr, layout, new_size) { - return Ok(ptr); + if let Ok(size) = self.shrink_in_place(ptr, layout, new_size) { + return Ok((ptr, size)); } + } else { + return Ok((ptr, new_size)); } // otherwise, fall back on alloc + copy + dealloc. let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); let result = self.alloc(new_layout); - if let Ok(new_ptr) = result { + if let Ok((new_ptr, _)) = result { ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size)); self.dealloc(ptr, layout); } @@ -877,174 +868,40 @@ pub unsafe trait AllocRef { ptr: NonNull<u8>, layout: Layout, new_size: usize, - ) -> Result<NonNull<u8>, AllocErr> { + ) -> Result<(NonNull<u8>, usize), AllocErr> { let old_size = layout.size(); - if new_size >= old_size { - if let Ok(()) = self.grow_in_place_zeroed(ptr, layout, new_size) { - return Ok(ptr); + if new_size > old_size { + if let Ok(size) = self.grow_in_place_zeroed(ptr, layout, new_size) { + return Ok((ptr, size)); } } else if new_size < old_size { - if let Ok(()) = self.shrink_in_place(ptr, layout, new_size) { - return Ok(ptr); + if let Ok(size) = self.shrink_in_place(ptr, layout, new_size) { + return Ok((ptr, size)); } + } else { + return Ok((ptr, new_size)); } // otherwise, fall back on alloc + copy + dealloc. let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); let result = self.alloc_zeroed(new_layout); - if let Ok(new_ptr) = result { + if let Ok((new_ptr, _)) = result { ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size)); self.dealloc(ptr, layout); } result } - /// Behaves like `alloc`, but also ensures that the contents - /// are set to zero before being returned. - /// - /// # Safety - /// - /// This function is unsafe for the same reasons that `alloc` is. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `layout` does not meet allocator's size or alignment - /// constraints, just as in `alloc`. - /// - /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> { - let size = layout.size(); - let p = self.alloc(layout); - if let Ok(p) = p { - ptr::write_bytes(p.as_ptr(), 0, size); - } - p - } - - /// Behaves like `alloc`, but also returns the whole size of - /// the returned block. For some `layout` inputs, like arrays, this - /// may include extra storage usable for additional data. - /// - /// # Safety - /// - /// This function is unsafe for the same reasons that `alloc` is. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `layout` does not meet allocator's size or alignment - /// constraints, just as in `alloc`. - /// - /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> { - let usable_size = self.usable_size(&layout); - self.alloc(layout).map(|p| Excess(p, usable_size.1)) - } - - /// Behaves like `alloc`, but also returns the whole size of - /// the returned block. For some `layout` inputs, like arrays, this - /// may include extra storage usable for additional data. - /// Also it ensures that the contents are set to zero before being returned. - /// - /// # Safety - /// - /// This function is unsafe for the same reasons that `alloc` is. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `layout` does not meet allocator's size or alignment - /// constraints, just as in `alloc`. - /// - /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn alloc_excess_zeroed(&mut self, layout: Layout) -> Result<Excess, AllocErr> { - let usable_size = self.usable_size(&layout); - self.alloc_zeroed(layout).map(|p| Excess(p, usable_size.1)) - } - - /// Behaves like `realloc`, but also returns the whole size of - /// the returned block. For some `layout` inputs, like arrays, this - /// may include extra storage usable for additional data. - /// - /// # Safety - /// - /// This function is unsafe for the same reasons that `realloc` is. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `layout` does not meet allocator's size or alignment - /// constraints, just as in `realloc`. - /// - /// Clients wishing to abort computation in response to a - /// reallocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn realloc_excess( - &mut self, - ptr: NonNull<u8>, - layout: Layout, - new_size: usize, - ) -> Result<Excess, AllocErr> { - let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); - let usable_size = self.usable_size(&new_layout); - self.realloc(ptr, layout, new_size).map(|p| Excess(p, usable_size.1)) - } - - /// Behaves like `realloc`, but also returns the whole size of - /// the returned block. For some `layout` inputs, like arrays, this - /// may include extra storage usable for additional data. - /// Also it ensures that the contents are set to zero before being returned. - /// - /// # Safety - /// - /// This function is unsafe for the same reasons that `realloc` is. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `layout` does not meet allocator's size or alignment - /// constraints, just as in `realloc`. - /// - /// Clients wishing to abort computation in response to a - /// reallocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn realloc_excess_zeroed( - &mut self, - ptr: NonNull<u8>, - layout: Layout, - new_size: usize, - ) -> Result<Excess, AllocErr> { - let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); - let usable_size = self.usable_size(&new_layout); - self.realloc_zeroed(ptr, layout, new_size).map(|p| Excess(p, usable_size.1)) - } - /// Attempts to extend the allocation referenced by `ptr` to fit `new_size`. /// /// If this returns `Ok`, then the allocator has asserted that the /// memory block referenced by `ptr` now fits `new_size`, and thus can /// be used to carry data of a layout of that size and same alignment as - /// `layout`. (The allocator is allowed to - /// expend effort to accomplish this, such as extending the memory block to - /// include successor blocks, or virtual memory tricks.) + /// `layout`. The returned value is the new size of the allocated block. + /// (The allocator is allowed to expend effort to accomplish this, such + /// as extending the memory block to include successor blocks, or virtual + /// memory tricks.) /// /// Regardless of what this method returns, ownership of the /// memory block referenced by `ptr` has not been transferred, and @@ -1072,18 +929,17 @@ pub unsafe trait AllocRef { /// function; clients are expected either to be able to recover from /// `grow_in_place` failures without aborting, or to fall back on /// another reallocation method before resorting to an abort. + #[inline] unsafe fn grow_in_place( &mut self, ptr: NonNull<u8>, layout: Layout, new_size: usize, - ) -> Result<(), CannotReallocInPlace> { - let _ = ptr; // this default implementation doesn't care about the actual address. - debug_assert!(new_size >= layout.size()); - let (_l, u) = self.usable_size(&layout); - // _l <= layout.size() [guaranteed by usable_size()] - // layout.size() <= new_layout.size() [required by this method] - if new_size <= u { Ok(()) } else { Err(CannotReallocInPlace) } + ) -> Result<usize, CannotReallocInPlace> { + let _ = ptr; + let _ = layout; + let _ = new_size; + Err(CannotReallocInPlace) } /// Behaves like `grow_in_place`, but also ensures that the new @@ -1108,10 +964,10 @@ pub unsafe trait AllocRef { ptr: NonNull<u8>, layout: Layout, new_size: usize, - ) -> Result<(), CannotReallocInPlace> { - self.grow_in_place(ptr, layout, new_size)?; + ) -> Result<usize, CannotReallocInPlace> { + let size = self.grow_in_place(ptr, layout, new_size)?; ptr.as_ptr().add(layout.size()).write_bytes(0, new_size - layout.size()); - Ok(()) + Ok(size) } /// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`. @@ -1119,7 +975,8 @@ pub unsafe trait AllocRef { /// If this returns `Ok`, then the allocator has asserted that the /// memory block referenced by `ptr` now fits `new_size`, and /// thus can only be used to carry data of that smaller - /// layout. (The allocator is allowed to take advantage of this, + /// layout. The returned value is the new size the allocated block. + /// (The allocator is allowed to take advantage of this, /// carving off portions of the block for reuse elsewhere.) The /// truncated contents of the block within the smaller layout are /// unaltered, and ownership of block has not been transferred. @@ -1153,17 +1010,16 @@ pub unsafe trait AllocRef { /// function; clients are expected either to be able to recover from /// `shrink_in_place` failures without aborting, or to fall back /// on another reallocation method before resorting to an abort. + #[inline] unsafe fn shrink_in_place( &mut self, ptr: NonNull<u8>, layout: Layout, new_size: usize, - ) -> Result<(), CannotReallocInPlace> { - let _ = ptr; // this default implementation doesn't care about the actual address. - debug_assert!(new_size <= layout.size()); - let (l, _u) = self.usable_size(&layout); - // layout.size() <= _u [guaranteed by usable_size()] - // new_layout.size() <= layout.size() [required by this method] - if l <= new_size { Ok(()) } else { Err(CannotReallocInPlace) } + ) -> Result<usize, CannotReallocInPlace> { + let _ = ptr; + let _ = layout; + let _ = new_size; + Err(CannotReallocInPlace) } } diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 58606531a1a..02dc9b8f82e 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -1894,9 +1894,7 @@ where let to_skip = self.n; self.n = 0; // nth(n) skips n+1 - if self.iter.nth(to_skip - 1).is_none() { - return None; - } + self.iter.nth(to_skip - 1)?; } self.iter.nth(n) } @@ -1916,9 +1914,7 @@ where fn last(mut self) -> Option<I::Item> { if self.n > 0 { // nth(n) skips n+1 - if self.iter.nth(self.n - 1).is_none() { - return None; - } + self.iter.nth(self.n - 1)?; } self.iter.last() } diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 5fa9962f811..080b70c6368 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -43,7 +43,7 @@ //! are elements, and once they've all been exhausted, will return `None` to //! indicate that iteration is finished. Individual iterators may choose to //! resume iteration, and so calling [`next`] again may or may not eventually -//! start returning `Some(Item)` again at some point. +//! start returning `Some(Item)` again at some point (for example, see [`TryIter`]). //! //! [`Iterator`]'s full definition includes a number of other methods as well, //! but they are default methods, built on top of [`next`], and so you get @@ -56,6 +56,7 @@ //! [`Iterator`]: trait.Iterator.html //! [`next`]: trait.Iterator.html#tymethod.next //! [`Option`]: ../../std/option/enum.Option.html +//! [`TryIter`]: ../../std/sync/mpsc/struct.TryIter.html //! //! # The three forms of iteration //! diff --git a/src/libcore/iter/traits/exact_size.rs b/src/libcore/iter/traits/exact_size.rs index 4a7db348b18..ad87d09588e 100644 --- a/src/libcore/iter/traits/exact_size.rs +++ b/src/libcore/iter/traits/exact_size.rs @@ -69,8 +69,10 @@ /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait ExactSizeIterator: Iterator { - /// Returns the exact number of times the iterator will iterate. + /// Returns the exact length of the iterator. /// + /// The implementation ensures that the iterator will return exactly `len()` + /// more times a `Some(T)` value, before returning `None`. /// This method has a default implementation, so you usually should not /// implement it directly. However, if you can provide a more efficient /// implementation, you can do so. See the [trait-level] docs for an diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index bac2540ab45..481d691b8e9 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -17,7 +17,7 @@ scoped-tls = "1.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } rustc-rayon = "0.3.0" rustc-rayon-core = "0.3.0" -polonius-engine = "0.11.0" +polonius-engine = "0.12.0" rustc_apfloat = { path = "../librustc_apfloat" } rustc_attr = { path = "../librustc_attr" } rustc_feature = { path = "../librustc_feature" } @@ -33,7 +33,6 @@ rustc_span = { path = "../librustc_span" } backtrace = "0.3.40" parking_lot = "0.9" byteorder = { version = "1.3" } -chalk-engine = { version = "0.9.0", default-features=false } smallvec = { version = "1.0", features = ["union", "may_dangle"] } measureme = "0.7.1" rustc_session = { path = "../librustc_session" } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 4f7c4153ea1..bd26e02efb7 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -338,9 +338,8 @@ impl<'hir> Map<'hir> { Node::Variant(_) => DefKind::Variant, Node::Ctor(variant_data) => { // FIXME(eddyb) is this even possible, if we have a `Node::Ctor`? - if variant_data.ctor_hir_id().is_none() { - return None; - } + variant_data.ctor_hir_id()?; + let ctor_of = match self.find(self.get_parent_node(hir_id)) { Some(Node::Item(..)) => def::CtorOf::Struct, Some(Node::Variant(..)) => def::CtorOf::Variant, diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 668240ab42b..36818020569 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -189,7 +189,7 @@ impl<'tcx> Body<'tcx> { ) -> Self { // We need `arg_count` locals, and one for the return place. assert!( - local_decls.len() >= arg_count + 1, + local_decls.len() > arg_count, "expected at least {} locals, got {}", arg_count + 1, local_decls.len() diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index b3315cc3701..9277f5a380b 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -1130,16 +1130,6 @@ rustc_queries! { desc { "evaluating trait selection obligation `{}`", goal.value.value } } - query evaluate_goal( - goal: traits::ChalkCanonicalGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, - NoSolution - > { - no_force - desc { "evaluating trait selection obligation `{}`", goal.value.goal } - } - /// Do not call this query directly: part of the `Eq` type-op query type_op_ascribe_user_type( goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx> diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 1a4ea66a5f1..4e02a1744ff 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -7,9 +7,7 @@ pub mod select; pub mod specialization_graph; mod structural_impls; -use crate::infer::canonical::Canonical; use crate::mir::interpret::ErrorHandled; -use crate::ty::fold::{TypeFolder, TypeVisitor}; use crate::ty::subst::SubstsRef; use crate::ty::{self, AdtKind, List, Ty, TyCtxt}; @@ -25,8 +23,6 @@ use std::rc::Rc; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; -pub type ChalkCanonicalGoal<'tcx> = Canonical<'tcx, InEnvironment<'tcx, ty::Predicate<'tcx>>>; - pub use self::ObligationCauseCode::*; pub use self::SelectionError::*; pub use self::Vtable::*; @@ -715,45 +711,6 @@ pub struct VtableTraitAliasData<'tcx, N> { pub nested: Vec<N>, } -pub trait ExClauseFold<'tcx> -where - Self: chalk_engine::context::Context + Clone, -{ - fn fold_ex_clause_with<F: TypeFolder<'tcx>>( - ex_clause: &chalk_engine::ExClause<Self>, - folder: &mut F, - ) -> chalk_engine::ExClause<Self>; - - fn visit_ex_clause_with<V: TypeVisitor<'tcx>>( - ex_clause: &chalk_engine::ExClause<Self>, - visitor: &mut V, - ) -> bool; -} - -pub trait ChalkContextLift<'tcx> -where - Self: chalk_engine::context::Context + Clone, -{ - type LiftedExClause: Debug + 'tcx; - type LiftedDelayedLiteral: Debug + 'tcx; - type LiftedLiteral: Debug + 'tcx; - - fn lift_ex_clause_to_tcx( - ex_clause: &chalk_engine::ExClause<Self>, - tcx: TyCtxt<'tcx>, - ) -> Option<Self::LiftedExClause>; - - fn lift_delayed_literal_to_tcx( - ex_clause: &chalk_engine::DelayedLiteral<Self>, - tcx: TyCtxt<'tcx>, - ) -> Option<Self::LiftedDelayedLiteral>; - - fn lift_literal_to_tcx( - ex_clause: &chalk_engine::Literal<Self>, - tcx: TyCtxt<'tcx>, - ) -> Option<Self::LiftedLiteral>; -} - #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)] pub enum ObjectSafetyViolation { /// `Self: Sized` declared on the trait. diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 48ed29f2bb3..f9c8b01571e 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -234,7 +234,7 @@ impl BoundNamesCollector { start = false; write!(fmt, "{}", r)?; } - for (_, t) in &self.types { + for t in self.types.values() { if !start { write!(fmt, ", ")?; } @@ -595,42 +595,6 @@ impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> { } } -impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause<C> -where - C: chalk_engine::context::Context + Clone, - C: traits::ChalkContextLift<'tcx>, -{ - type Lifted = C::LiftedExClause; - - fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - <C as traits::ChalkContextLift>::lift_ex_clause_to_tcx(self, tcx) - } -} - -impl<'tcx, C> Lift<'tcx> for chalk_engine::DelayedLiteral<C> -where - C: chalk_engine::context::Context + Clone, - C: traits::ChalkContextLift<'tcx>, -{ - type Lifted = C::LiftedDelayedLiteral; - - fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - <C as traits::ChalkContextLift>::lift_delayed_literal_to_tcx(self, tcx) - } -} - -impl<'tcx, C> Lift<'tcx> for chalk_engine::Literal<C> -where - C: chalk_engine::context::Context + Clone, - C: traits::ChalkContextLift<'tcx>, -{ - type Lifted = C::LiftedLiteral; - - fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - <C as traits::ChalkContextLift>::lift_literal_to_tcx(self, tcx) - } -} - /////////////////////////////////////////////////////////////////////////// // TypeFoldable implementations. @@ -674,39 +638,3 @@ impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'tcx> { self.iter().any(|t| t.visit_with(visitor)) } } - -impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::ExClause<C> -where - C: traits::ExClauseFold<'tcx>, - C::Substitution: Clone, - C::RegionConstraint: Clone, -{ - fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self { - <C as traits::ExClauseFold>::fold_ex_clause_with(self, folder) - } - - fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool { - <C as traits::ExClauseFold>::visit_ex_clause_with(self, visitor) - } -} - -EnumTypeFoldableImpl! { - impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::DelayedLiteral<C> { - (chalk_engine::DelayedLiteral::CannotProve)(a), - (chalk_engine::DelayedLiteral::Negative)(a), - (chalk_engine::DelayedLiteral::Positive)(a, b), - } where - C: chalk_engine::context::Context<CanonicalConstrainedSubst: TypeFoldable<'tcx>> + Clone, -} - -EnumTypeFoldableImpl! { - impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::Literal<C> { - (chalk_engine::Literal::Negative)(a), - (chalk_engine::Literal::Positive)(a), - } where - C: chalk_engine::context::Context<GoalInEnvironment: Clone + TypeFoldable<'tcx>> + Clone, -} - -CloneTypeFoldableAndLiftImpls! { - chalk_engine::TableIndex, -} diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index f65822aba4c..4014d1d8ae2 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -115,9 +115,7 @@ impl<'tcx> Instance<'tcx> { } // If this a non-generic instance, it cannot be a shared monomorphization. - if self.substs.non_erasable_generics().next().is_none() { - return None; - } + self.substs.non_erasable_generics().next()?; match self.def { InstanceDef::Item(def_id) => tcx diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 28553954b22..f1b4b828c71 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1382,10 +1382,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Write down the order of our locals that will be promoted to the prefix. { - let mut idx = 0u32; - for local in ineligible_locals.iter() { - assignments[local] = Ineligible(Some(idx)); - idx += 1; + for (idx, local) in ineligible_locals.iter().enumerate() { + assignments[local] = Ineligible(Some(idx as u32)); } } debug!("generator saved local assignments: {:?}", assignments); diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index 6e2b3ec5fd2..3724a83a949 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -188,7 +188,7 @@ fn parse_args<'a>( let mut err = ecx .struct_span_err(e.span, "positional arguments cannot follow named arguments"); err.span_label(e.span, "positional arguments must be before named arguments"); - for (_, pos) in &names { + for pos in names.values() { err.span_label(args[*pos].span, "named argument"); } err.emit(); diff --git a/src/librustc_codegen_llvm/va_arg.rs b/src/librustc_codegen_llvm/va_arg.rs index 9bc3eec60ae..a552f2cdb78 100644 --- a/src/librustc_codegen_llvm/va_arg.rs +++ b/src/librustc_codegen_llvm/va_arg.rs @@ -117,8 +117,7 @@ pub(super) fn emit_va_arg( // Windows x86_64 ("x86_64", true) => { let target_ty_size = bx.cx.size_of(target_ty).bytes(); - let indirect = - if target_ty_size > 8 || !target_ty_size.is_power_of_two() { true } else { false }; + let indirect: bool = target_ty_size > 8 || !target_ty_size.is_power_of_two(); emit_ptr_va_arg(bx, addr, target_ty, indirect, Align::from_bytes(8).unwrap(), false) } // For all other architecture/OS combinations fall back to using diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 90601521b19..0dd2f029e8d 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -186,7 +186,7 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB if flavor == LinkerFlavor::Msvc && t.target_vendor == "uwp" { if let Some(ref tool) = msvc_tool { let original_path = tool.path(); - if let Some(ref root_lib_path) = original_path.ancestors().skip(4).next() { + if let Some(ref root_lib_path) = original_path.ancestors().nth(4) { let arch = match t.arch.as_str() { "x86_64" => Some("x64".to_string()), "x86" => Some("x86".to_string()), @@ -1519,17 +1519,25 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( // for the current implementation of the standard library. let mut group_end = None; let mut group_start = None; - let mut end_with = FxHashSet::default(); + // Crates available for linking thus far. + let mut available = FxHashSet::default(); + // Crates required to satisfy dependencies discovered so far. + let mut required = FxHashSet::default(); + let info = &codegen_results.crate_info; for &(cnum, _) in deps.iter().rev() { if let Some(missing) = info.missing_lang_items.get(&cnum) { - end_with.extend(missing.iter().cloned()); - if !end_with.is_empty() && group_end.is_none() { - group_end = Some(cnum); - } + let missing_crates = missing.iter().map(|i| info.lang_item_to_crate.get(i).copied()); + required.extend(missing_crates); + } + + required.insert(Some(cnum)); + available.insert(Some(cnum)); + + if required.len() > available.len() && group_end.is_none() { + group_end = Some(cnum); } - end_with.retain(|item| info.lang_item_to_crate.get(item) != Some(&cnum)); - if end_with.is_empty() && group_end.is_some() { + if required.len() == available.len() && group_end.is_some() { group_start = Some(cnum); break; } diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 89359bb1bfd..11d1209923f 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -395,6 +395,7 @@ E0714: include_str!("./error_codes/E0714.md"), E0715: include_str!("./error_codes/E0715.md"), E0716: include_str!("./error_codes/E0716.md"), E0718: include_str!("./error_codes/E0718.md"), +E0719: include_str!("./error_codes/E0719.md"), E0720: include_str!("./error_codes/E0720.md"), E0723: include_str!("./error_codes/E0723.md"), E0725: include_str!("./error_codes/E0725.md"), @@ -605,7 +606,6 @@ E0748: include_str!("./error_codes/E0748.md"), E0710, // an unknown tool name found in scoped lint E0711, // a feature has been declared with conflicting stability attributes E0717, // rustc_promotable without stability attribute - E0719, // duplicate values for associated type binding // E0721, // `await` keyword E0722, // Malformed `#[optimize]` attribute E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions diff --git a/src/librustc_error_codes/error_codes/E0378.md b/src/librustc_error_codes/error_codes/E0378.md index 311483c8900..7f4374738de 100644 --- a/src/librustc_error_codes/error_codes/E0378.md +++ b/src/librustc_error_codes/error_codes/E0378.md @@ -1,10 +1,28 @@ +The `DispatchFromDyn` trait was implemented on something which is not a pointer +or a newtype wrapper around a pointer. + +Erroneous code example: + +```compile-fail,E0378 +#![feature(dispatch_from_dyn)] +use std::ops::DispatchFromDyn; + +struct WrapperExtraField<T> { + ptr: T, + extra_stuff: i32, +} + +impl<T, U> DispatchFromDyn<WrapperExtraField<U>> for WrapperExtraField<T> +where + T: DispatchFromDyn<U>, +{} +``` + The `DispatchFromDyn` trait currently can only be implemented for builtin pointer types and structs that are newtype wrappers around them — that is, the struct must have only one field (except for`PhantomData`), and that field must itself implement `DispatchFromDyn`. -Examples: - ``` #![feature(dispatch_from_dyn, unsize)] use std::{ @@ -20,6 +38,8 @@ where {} ``` +Another example: + ``` #![feature(dispatch_from_dyn)] use std::{ @@ -37,21 +57,3 @@ where T: DispatchFromDyn<U>, {} ``` - -Example of illegal `DispatchFromDyn` implementation -(illegal because of extra field) - -```compile-fail,E0378 -#![feature(dispatch_from_dyn)] -use std::ops::DispatchFromDyn; - -struct WrapperExtraField<T> { - ptr: T, - extra_stuff: i32, -} - -impl<T, U> DispatchFromDyn<WrapperExtraField<U>> for WrapperExtraField<T> -where - T: DispatchFromDyn<U>, -{} -``` diff --git a/src/librustc_error_codes/error_codes/E0719.md b/src/librustc_error_codes/error_codes/E0719.md new file mode 100644 index 00000000000..38bc63550ac --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0719.md @@ -0,0 +1,35 @@ +The value for an associated type has already been specified. + +Erroneous code example: + +```compile_fail,E0719 +#![feature(associated_type_bounds)] + +trait FooTrait {} +trait BarTrait {} + +// error: associated type `Item` in trait `Iterator` is specified twice +struct Foo<T: Iterator<Item: FooTrait, Item: BarTrait>> { f: T } +``` + +`Item` in trait `Iterator` cannot be specified multiple times for struct `Foo`. +To fix this, create a new trait that is a combination of the desired traits and +specify the associated type with the new trait. + +Corrected example: + +``` +#![feature(associated_type_bounds)] + +trait FooTrait {} +trait BarTrait {} +trait FooBarTrait: FooTrait + BarTrait {} + +struct Foo<T: Iterator<Item: FooBarTrait>> { f: T } +``` + +For more information about associated types, see [the book][bk-at]. For more +information on associated type bounds, see [RFC 2289][rfc-2289]. + +[bk-at]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#specifying-placeholder-types-in-trait-definitions-with-associated-types +[rfc-2289]: https://rust-lang.github.io/rfcs/2289-associated-type-bounds.html diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 39f585231ee..008d2e92418 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -136,12 +136,11 @@ impl<'a> DiagnosticBuilder<'a> { let handler = self.0.handler; - // We need to use `ptr::read` because `DiagnosticBuilder` implements `Drop`. - let diagnostic; - unsafe { - diagnostic = std::ptr::read(&self.0.diagnostic); - std::mem::forget(self); - }; + // We must use `Level::Cancelled` for `dummy` to avoid an ICE about an + // unused diagnostic. + let dummy = Diagnostic::new(Level::Cancelled, ""); + let diagnostic = std::mem::replace(&mut self.0.diagnostic, dummy); + // Logging here is useful to help track down where in logs an error was // actually emitted. debug!("buffer: diagnostic={:?}", diagnostic); diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 2d7ff191c77..eb9d4b887ad 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -1574,9 +1574,9 @@ impl EmitterWriter { let line_start = sm.lookup_char_pos(parts[0].span.lo()).line; draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1); - let mut line_pos = 0; let mut lines = complete.lines(); - for line in lines.by_ref().take(MAX_SUGGESTION_HIGHLIGHT_LINES) { + for (line_pos, line) in lines.by_ref().take(MAX_SUGGESTION_HIGHLIGHT_LINES).enumerate() + { // Print the span column to avoid confusion buffer.puts( row_num, @@ -1587,7 +1587,6 @@ impl EmitterWriter { // print the suggestion draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); buffer.append(row_num, line, Style::NoStyle); - line_pos += 1; row_num += 1; } diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs index 80bf02b1366..d12dedf9e0c 100644 --- a/src/librustc_expand/mbe/transcribe.rs +++ b/src/librustc_expand/mbe/transcribe.rs @@ -119,9 +119,9 @@ pub(super) fn transcribe( let tree = if let Some(tree) = stack.last_mut().unwrap().next() { // If it still has a TokenTree we have not looked at yet, use that tree. tree - } - // The else-case never produces a value for `tree` (it `continue`s or `return`s). - else { + } else { + // This else-case never produces a value for `tree` (it `continue`s or `return`s). + // Otherwise, if we have just reached the end of a sequence and we can keep repeating, // go back to the beginning of the sequence. if let Frame::Sequence { idx, sep, .. } = stack.last_mut().unwrap() { diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 1a74b50b57e..f948e22e84b 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -679,15 +679,15 @@ impl Crate<'_> { where V: itemlikevisit::ItemLikeVisitor<'hir>, { - for (_, item) in &self.items { + for item in self.items.values() { visitor.visit_item(item); } - for (_, trait_item) in &self.trait_items { + for trait_item in self.trait_items.values() { visitor.visit_trait_item(trait_item); } - for (_, impl_item) in &self.impl_items { + for impl_item in self.impl_items.values() { visitor.visit_impl_item(impl_item); } } diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index 65a742a202d..b1861acec04 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -13,9 +13,7 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( files: &[(WorkProductFileKind, PathBuf)], ) -> Option<(WorkProductId, WorkProduct)> { debug!("copy_cgu_workproducts_to_incr_comp_cache_dir({:?},{:?})", cgu_name, files); - if sess.opts.incremental.is_none() { - return None; - } + sess.opts.incremental.as_ref()?; let saved_files = files .iter() diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs index 26f855b177e..4d3f25290e1 100644 --- a/src/librustc_infer/infer/canonical/canonicalizer.rs +++ b/src/librustc_infer/infer/canonical/canonicalizer.rs @@ -357,10 +357,8 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { // `TyVar(vid)` is unresolved, track its universe index in the canonicalized // result. Err(mut ui) => { - if !self.infcx.unwrap().tcx.sess.opts.debugging_opts.chalk { - // FIXME: perf problem described in #55921. - ui = ty::UniverseIndex::ROOT; - } + // FIXME: perf problem described in #55921. + ui = ty::UniverseIndex::ROOT; self.canonicalize_ty_var( CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)), @@ -447,10 +445,8 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { // `ConstVar(vid)` is unresolved, track its universe index in the // canonicalized result Err(mut ui) => { - if !self.infcx.unwrap().tcx.sess.opts.debugging_opts.chalk { - // FIXME: perf problem described in #55921. - ui = ty::UniverseIndex::ROOT; - } + // FIXME: perf problem described in #55921. + ui = ty::UniverseIndex::ROOT; return self.canonicalize_const_var( CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) }, ct, diff --git a/src/librustc_infer/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs index fc9f3bb0767..b7278ecd5e4 100644 --- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs +++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs @@ -751,7 +751,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let dummy_source = graph.add_node(()); let dummy_sink = graph.add_node(()); - for (constraint, _) in &self.data.constraints { + for constraint in self.data.constraints.keys() { match *constraint { Constraint::VarSubVar(a_id, b_id) => { graph.add_edge( diff --git a/src/librustc_infer/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs index 74ffdc7a4f0..bbd4f3b3550 100644 --- a/src/librustc_infer/infer/region_constraints/leak_check.rs +++ b/src/librustc_infer/infer/region_constraints/leak_check.rs @@ -34,7 +34,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { assert!(self.in_snapshot()); // Go through each placeholder that we created. - for (_, &placeholder_region) in placeholder_map { + for &placeholder_region in placeholder_map.values() { // Find the universe this placeholder inhabits. let placeholder = match placeholder_region { ty::RePlaceholder(p) => p, diff --git a/src/librustc_infer/traits/chalk_fulfill.rs b/src/librustc_infer/traits/chalk_fulfill.rs deleted file mode 100644 index 82fa683a290..00000000000 --- a/src/librustc_infer/traits/chalk_fulfill.rs +++ /dev/null @@ -1,159 +0,0 @@ -use crate::infer::canonical::OriginalQueryValues; -use crate::infer::InferCtxt; -use crate::traits::query::NoSolution; -use crate::traits::{ - Environment, FulfillmentError, FulfillmentErrorCode, InEnvironment, ObligationCause, - PredicateObligation, SelectionError, TraitEngine, -}; -use rustc::ty::{self, Ty}; -use rustc_data_structures::fx::FxHashSet; - -pub use rustc::traits::ChalkCanonicalGoal as CanonicalGoal; - -pub struct FulfillmentContext<'tcx> { - obligations: FxHashSet<InEnvironment<'tcx, PredicateObligation<'tcx>>>, -} - -impl FulfillmentContext<'tcx> { - crate fn new() -> Self { - FulfillmentContext { obligations: FxHashSet::default() } - } -} - -fn in_environment( - infcx: &InferCtxt<'_, 'tcx>, - obligation: PredicateObligation<'tcx>, -) -> InEnvironment<'tcx, PredicateObligation<'tcx>> { - assert!(!infcx.is_in_snapshot()); - let obligation = infcx.resolve_vars_if_possible(&obligation); - - let environment = match obligation.param_env.def_id { - Some(def_id) => infcx.tcx.environment(def_id), - None if obligation.param_env.caller_bounds.is_empty() => { - Environment { clauses: ty::List::empty() } - } - _ => bug!("non-empty `ParamEnv` with no def-id"), - }; - - InEnvironment { environment, goal: obligation } -} - -impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { - fn normalize_projection_type( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - _param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::ProjectionTy<'tcx>, - _cause: ObligationCause<'tcx>, - ) -> Ty<'tcx> { - infcx.tcx.mk_ty(ty::Projection(projection_ty)) - } - - fn register_predicate_obligation( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - obligation: PredicateObligation<'tcx>, - ) { - self.obligations.insert(in_environment(infcx, obligation)); - } - - fn select_all_or_error( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec<FulfillmentError<'tcx>>> { - self.select_where_possible(infcx)?; - - if self.obligations.is_empty() { - Ok(()) - } else { - let errors = self - .obligations - .iter() - .map(|obligation| FulfillmentError { - obligation: obligation.goal.clone(), - code: FulfillmentErrorCode::CodeAmbiguity, - points_at_arg_span: false, - }) - .collect(); - Err(errors) - } - } - - fn select_where_possible( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec<FulfillmentError<'tcx>>> { - let mut errors = Vec::new(); - let mut next_round = FxHashSet::default(); - let mut making_progress; - - loop { - making_progress = false; - - // We iterate over all obligations, and record if we are able - // to unambiguously prove at least one obligation. - for obligation in self.obligations.drain() { - let mut orig_values = OriginalQueryValues::default(); - let canonical_goal = infcx.canonicalize_query( - &InEnvironment { - environment: obligation.environment, - goal: obligation.goal.predicate, - }, - &mut orig_values, - ); - - match infcx.tcx.evaluate_goal(canonical_goal) { - Ok(response) => { - if response.is_proven() { - making_progress = true; - - match infcx.instantiate_query_response_and_region_obligations( - &obligation.goal.cause, - obligation.goal.param_env, - &orig_values, - &response, - ) { - Ok(infer_ok) => next_round.extend( - infer_ok - .obligations - .into_iter() - .map(|obligation| in_environment(infcx, obligation)), - ), - - Err(_err) => errors.push(FulfillmentError { - obligation: obligation.goal, - code: FulfillmentErrorCode::CodeSelectionError( - SelectionError::Unimplemented, - ), - points_at_arg_span: false, - }), - } - } else { - // Ambiguous: retry at next round. - next_round.insert(obligation); - } - } - - Err(NoSolution) => errors.push(FulfillmentError { - obligation: obligation.goal, - code: FulfillmentErrorCode::CodeSelectionError( - SelectionError::Unimplemented, - ), - points_at_arg_span: false, - }), - } - } - next_round = std::mem::replace(&mut self.obligations, next_round); - - if !making_progress { - break; - } - } - - if errors.is_empty() { Ok(()) } else { Err(errors) } - } - - fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> { - self.obligations.iter().map(|obligation| obligation.goal.clone()).collect() - } -} diff --git a/src/librustc_infer/traits/engine.rs b/src/librustc_infer/traits/engine.rs index ba144379616..e23810dd161 100644 --- a/src/librustc_infer/traits/engine.rs +++ b/src/librustc_infer/traits/engine.rs @@ -3,7 +3,7 @@ use crate::traits::Obligation; use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_hir::def_id::DefId; -use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError}; +use super::{FulfillmentContext, FulfillmentError}; use super::{ObligationCause, PredicateObligation}; pub trait TraitEngine<'tcx>: 'tcx { @@ -78,11 +78,7 @@ impl<T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { } impl dyn TraitEngine<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> Box<Self> { - if tcx.sess.opts.debugging_opts.chalk { - Box::new(ChalkFulfillmentContext::new()) - } else { - Box::new(FulfillmentContext::new()) - } + pub fn new(_tcx: TyCtxt<'tcx>) -> Box<Self> { + Box::new(FulfillmentContext::new()) } } diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs index 7a84a5f5c72..63c3f827c2e 100644 --- a/src/librustc_infer/traits/error_reporting/mod.rs +++ b/src/librustc_infer/traits/error_reporting/mod.rs @@ -812,21 +812,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } ty::Predicate::WellFormed(ty) => { - if !self.tcx.sess.opts.debugging_opts.chalk { - // WF predicates cannot themselves make - // errors. They can only block due to - // ambiguity; otherwise, they always - // degenerate into other obligations - // (which may fail). - span_bug!(span, "WF predicate not satisfied for {:?}", ty); - } else { - // FIXME: we'll need a better message which takes into account - // which bounds actually failed to hold. - self.tcx.sess.struct_span_err( - span, - &format!("the type `{}` is not well-formed (chalk)", ty), - ) - } + // WF predicates cannot themselves make + // errors. They can only block due to + // ambiguity; otherwise, they always + // degenerate into other obligations + // (which may fail). + span_bug!(span, "WF predicate not satisfied for {:?}", ty); } ty::Predicate::ConstEvaluatable(..) => { diff --git a/src/librustc_infer/traits/error_reporting/suggestions.rs b/src/librustc_infer/traits/error_reporting/suggestions.rs index ed6cfa51cdf..d05955fb858 100644 --- a/src/librustc_infer/traits/error_reporting/suggestions.rs +++ b/src/librustc_infer/traits/error_reporting/suggestions.rs @@ -401,9 +401,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { let refs_number = snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count(); - if let Some('\'') = - snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next() - { + if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) { // Do not suggest removal of borrow from type arguments. return; } @@ -464,9 +462,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { let refs_number = snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count(); - if let Some('\'') = - snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next() - { + if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) { // Do not suggest removal of borrow from type arguments. return; } diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index 2815a77882a..61702d74f1a 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -4,7 +4,6 @@ #[allow(dead_code)] pub mod auto_trait; -mod chalk_fulfill; pub mod codegen; mod coherence; mod engine; @@ -74,10 +73,6 @@ pub use self::util::{ supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits, }; -pub use self::chalk_fulfill::{ - CanonicalGoal as ChalkCanonicalGoal, FulfillmentContext as ChalkFulfillmentContext, -}; - pub use rustc::traits::*; /// Whether to skip the leak check, as part of a future compatibility warning step. diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs index a79cbfd5e17..4c312c9fce2 100644 --- a/src/librustc_infer/traits/select.rs +++ b/src/librustc_infer/traits/select.rs @@ -2917,15 +2917,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { trait_ref, )?); - // FIXME: Chalk - - if !self.tcx().sess.opts.debugging_opts.chalk { - obligations.push(Obligation::new( - obligation.cause.clone(), - obligation.param_env, - ty::Predicate::ClosureKind(closure_def_id, substs, kind), - )); - } + obligations.push(Obligation::new( + obligation.cause.clone(), + obligation.param_env, + ty::Predicate::ClosureKind(closure_def_id, substs, kind), + )); Ok(VtableClosureData { closure_def_id, substs: substs, nested: obligations }) } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 6e606230b63..1ee581e64aa 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -15,7 +15,7 @@ dot = { path = "../libgraphviz", package = "graphviz" } itertools = "0.8" log = "0.4" log_settings = "0.1.1" -polonius-engine = "0.11.0" +polonius-engine = "0.12.0" rustc = { path = "../librustc" } rustc_ast_pretty = { path = "../librustc_ast_pretty" } rustc_attr = { path = "../librustc_attr" } diff --git a/src/librustc_mir/borrow_check/facts.rs b/src/librustc_mir/borrow_check/facts.rs index 827ccb1c857..cd8139b17b4 100644 --- a/src/librustc_mir/borrow_check/facts.rs +++ b/src/librustc_mir/borrow_check/facts.rs @@ -71,16 +71,16 @@ impl AllFactsExt for AllFacts { killed, outlives, invalidates, - var_used, - var_defined, - var_drop_used, - var_uses_region, - var_drops_region, - child, - path_belongs_to_var, - initialized_at, - moved_out_at, - path_accessed_at, + var_used_at, + var_defined_at, + var_dropped_at, + use_of_var_derefs_origin, + drop_of_var_derefs_origin, + child_path, + path_is_var, + path_assigned_at_base, + path_moved_at_base, + path_accessed_at_base, known_subset, ]) } diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index 2201abe4b92..ba1b322524e 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -86,15 +86,18 @@ fn populate_polonius_move_facts( body: &Body<'_>, ) { all_facts - .path_belongs_to_var + .path_is_var .extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (m, v))); for (child, move_path) in move_data.move_paths.iter_enumerated() { - all_facts - .child - .extend(move_path.parents(&move_data.move_paths).map(|(parent, _)| (child, parent))); + if let Some(parent) = move_path.parent { + all_facts.child_path.push((child, parent)); + } } + let fn_entry_start = location_table + .start_index(Location { block: BasicBlock::from_u32(0u32), statement_index: 0 }); + // initialized_at for init in move_data.inits.iter() { match init.location { @@ -115,28 +118,37 @@ fn populate_polonius_move_facts( // the successors, but not in the unwind block. let first_statement = Location { block: successor, statement_index: 0 }; all_facts - .initialized_at + .path_assigned_at_base .push((init.path, location_table.start_index(first_statement))); } } else { // In all other cases, the initialization just happens at the // midpoint, like any other effect. - all_facts.initialized_at.push((init.path, location_table.mid_index(location))); + all_facts + .path_assigned_at_base + .push((init.path, location_table.mid_index(location))); } } // Arguments are initialized on function entry InitLocation::Argument(local) => { assert!(body.local_kind(local) == LocalKind::Arg); - let fn_entry = Location { block: BasicBlock::from_u32(0u32), statement_index: 0 }; - all_facts.initialized_at.push((init.path, location_table.start_index(fn_entry))); + all_facts.path_assigned_at_base.push((init.path, fn_entry_start)); } } } + for (local, &path) in move_data.rev_lookup.iter_locals_enumerated() { + if body.local_kind(local) != LocalKind::Arg { + // Non-arguments start out deinitialised; we simulate this with an + // initial move: + all_facts.path_moved_at_base.push((path, fn_entry_start)); + } + } + // moved_out_at // deinitialisation is assumed to always happen! all_facts - .moved_out_at + .path_moved_at_base .extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source)))); } diff --git a/src/librustc_mir/borrow_check/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/type_check/liveness/polonius.rs index 055415f2872..407e0628b6e 100644 --- a/src/librustc_mir/borrow_check/type_check/liveness/polonius.rs +++ b/src/librustc_mir/borrow_check/type_check/liveness/polonius.rs @@ -12,12 +12,12 @@ type VarPointRelation = Vec<(Local, LocationIndex)>; type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>; struct UseFactsExtractor<'me> { - var_defined: &'me mut VarPointRelation, - var_used: &'me mut VarPointRelation, + var_defined_at: &'me mut VarPointRelation, + var_used_at: &'me mut VarPointRelation, location_table: &'me LocationTable, - var_drop_used: &'me mut Vec<(Local, Location)>, + var_dropped_at: &'me mut VarPointRelation, move_data: &'me MoveData<'me>, - path_accessed_at: &'me mut PathPointRelation, + path_accessed_at_base: &'me mut PathPointRelation, } // A Visitor to walk through the MIR and extract point-wise facts @@ -28,22 +28,22 @@ impl UseFactsExtractor<'_> { fn insert_def(&mut self, local: Local, location: Location) { debug!("UseFactsExtractor::insert_def()"); - self.var_defined.push((local, self.location_to_index(location))); + self.var_defined_at.push((local, self.location_to_index(location))); } fn insert_use(&mut self, local: Local, location: Location) { debug!("UseFactsExtractor::insert_use()"); - self.var_used.push((local, self.location_to_index(location))); + self.var_used_at.push((local, self.location_to_index(location))); } fn insert_drop_use(&mut self, local: Local, location: Location) { debug!("UseFactsExtractor::insert_drop_use()"); - self.var_drop_used.push((local, location)); + self.var_dropped_at.push((local, self.location_to_index(location))); } fn insert_path_access(&mut self, path: MovePathIndex, location: Location) { debug!("UseFactsExtractor::insert_path_access({:?}, {:?})", path, location); - self.path_accessed_at.push((path, self.location_to_index(location))); + self.path_accessed_at_base.push((path, self.location_table.start_index(location))); } fn place_to_mpi(&self, place: &Place<'_>) -> Option<MovePathIndex> { @@ -88,51 +88,54 @@ pub(super) fn populate_access_facts( body: ReadOnlyBodyAndCache<'_, 'tcx>, location_table: &LocationTable, move_data: &MoveData<'_>, - drop_used: &mut Vec<(Local, Location)>, + dropped_at: &mut Vec<(Local, Location)>, ) { debug!("populate_access_facts()"); if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { let mut extractor = UseFactsExtractor { - var_defined: &mut facts.var_defined, - var_used: &mut facts.var_used, - var_drop_used: drop_used, - path_accessed_at: &mut facts.path_accessed_at, + var_defined_at: &mut facts.var_defined_at, + var_used_at: &mut facts.var_used_at, + var_dropped_at: &mut facts.var_dropped_at, + path_accessed_at_base: &mut facts.path_accessed_at_base, location_table, move_data, }; extractor.visit_body(body); - facts.var_drop_used.extend( - drop_used.iter().map(|&(local, location)| (local, location_table.mid_index(location))), + facts.var_dropped_at.extend( + dropped_at.iter().map(|&(local, location)| (local, location_table.mid_index(location))), ); for (local, local_decl) in body.local_decls.iter_enumerated() { - debug!("add var_uses_regions facts - local={:?}, type={:?}", local, local_decl.ty); + debug!( + "add use_of_var_derefs_origin facts - local={:?}, type={:?}", + local, local_decl.ty + ); let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation"); let universal_regions = &typeck.borrowck_context.universal_regions; typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| { let region_vid = universal_regions.to_region_vid(region); - facts.var_uses_region.push((local, region_vid)); + facts.use_of_var_derefs_origin.push((local, region_vid)); }); } } } // For every potentially drop()-touched region `region` in `local`'s type -// (`kind`), emit a Polonius `var_drops_region(local, region)` fact. -pub(super) fn add_var_drops_regions( +// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact. +pub(super) fn add_drop_of_var_derefs_origin( typeck: &mut TypeChecker<'_, 'tcx>, local: Local, kind: &GenericArg<'tcx>, ) { - debug!("add_var_drops_region(local={:?}, kind={:?}", local, kind); + debug!("add_drop_of_var_derefs_origin(local={:?}, kind={:?}", local, kind); if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation"); let universal_regions = &typeck.borrowck_context.universal_regions; typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| { let region_vid = universal_regions.to_region_vid(drop_live_region); - facts.var_drops_region.push((local, region_vid)); + facts.drop_of_var_derefs_origin.push((local, region_vid)); }); } } diff --git a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs index 4c8deb0ecf8..baa9d1d212e 100644 --- a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs @@ -484,7 +484,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { for &kind in &drop_data.dropck_result.kinds { Self::make_all_regions_live(self.elements, &mut self.typeck, kind, live_at); - polonius::add_var_drops_regions(&mut self.typeck, dropped_local, &kind); + polonius::add_drop_of_var_derefs_origin(&mut self.typeck, dropped_local, &kind); } } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 1a0be582ce6..3cbb0667ff3 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -202,7 +202,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Char => { // `u8` to `char` cast - debug_assert_eq!(v as u8 as u128, v); + assert_eq!(v as u8 as u128, v); Ok(Scalar::from_uint(v, Size::from_bytes(4))) } diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index cd7a419af95..f2ee5e047a8 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -234,7 +234,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitXor => (Scalar::from_uint(l ^ r, size), left_layout.ty), Add | Sub | Mul | Rem | Div => { - debug_assert!(!left_layout.abi.is_signed()); + assert!(!left_layout.abi.is_signed()); let op: fn(u128, u128) -> (u128, bool) = match bin_op { Add => u128::overflowing_add, Sub => u128::overflowing_sub, diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 7d59c0181a8..f298a6677d6 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -287,7 +287,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.eval_terminator(terminator)?; if !self.stack.is_empty() { // This should change *something* - debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb); + assert!(self.cur_frame() != old_stack || self.frame().block != old_bb); if let Some(block) = self.frame().block { info!("// executing {:?}", block); } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 53e10f86a2c..08d4ae34afb 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -172,7 +172,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } let caller_arg = caller_arg.next().ok_or_else(|| err_unsup!(FunctionArgCountMismatch))?; if rust_abi { - debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out"); + assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out"); } // Now, check if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) { diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 263883d5639..50ba3e93895 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -144,16 +144,16 @@ fn wrapping_range_contains(r: &RangeInclusive<u128>, test: u128) -> bool { // "expected something <in the given range>" makes sense. fn wrapping_range_format(r: &RangeInclusive<u128>, max_hi: u128) -> String { let (lo, hi) = r.clone().into_inner(); - debug_assert!(hi <= max_hi); + assert!(hi <= max_hi); if lo > hi { format!("less or equal to {}, or greater or equal to {}", hi, lo) } else if lo == hi { format!("equal to {}", lo) } else if lo == 0 { - debug_assert!(hi < max_hi, "should not be printing if the range covers everything"); + assert!(hi < max_hi, "should not be printing if the range covers everything"); format!("less or equal to {}", hi) } else if hi == max_hi { - debug_assert!(lo > 0, "should not be printing if the range covers everything"); + assert!(lo > 0, "should not be printing if the range covers everything"); format!("greater or equal to {}", lo) } else { format!("in the range {:?}", r) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index f6a93363dc1..862a7ef1e73 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -824,11 +824,8 @@ fn find_vtable_types_for_unsizing<'tcx>( (&ty::Adt(source_adt_def, source_substs), &ty::Adt(target_adt_def, target_substs)) => { assert_eq!(source_adt_def, target_adt_def); - let kind = monomorphize::custom_coerce_unsize_info(tcx, source_ty, target_ty); - - let coerce_index = match kind { - CustomCoerceUnsized::Struct(i) => i, - }; + let CustomCoerceUnsized::Struct(coerce_index) = + monomorphize::custom_coerce_unsize_info(tcx, source_ty, target_ty); let source_fields = &source_adt_def.non_enum_variant().fields; let target_fields = &target_adt_def.non_enum_variant().fields; diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 1d502e52de4..73bc038ea15 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -1252,7 +1252,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // this may resolve to either a value or a type, but for documentation // purposes it's good enough to just favor one over the other. self.r.per_ns(|this, ns| { - if let Some(binding) = source_bindings[ns].get().ok() { + if let Ok(binding) = source_bindings[ns].get() { this.import_res_map.entry(directive.id).or_default()[ns] = Some(binding.res()); } }); @@ -1293,7 +1293,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None }; self.r.per_ns(|this, ns| { - if let Some(binding) = source_bindings[ns].get().ok() { + if let Ok(binding) = source_bindings[ns].get() { if binding.res() == Res::Err { return; } diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 463452e45ce..193b6d75935 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -347,7 +347,7 @@ fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap { lifetime_uses: &mut Default::default(), missing_named_lifetime_spots: vec![], }; - for (_, item) in &krate.items { + for item in krate.items.values() { visitor.visit_item(item); } } diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index d3163fa3564..a1ecf4e8528 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -922,8 +922,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "tell the linker to strip debuginfo when building without debuginfo enabled."), share_generics: Option<bool> = (None, parse_opt_bool, [TRACKED], "make the current crate share its generic instantiations"), - chalk: bool = (false, parse_bool, [TRACKED], - "enable the experimental Chalk-based trait solving engine"), no_parallel_llvm: bool = (false, parse_bool, [UNTRACKED], "don't run LLVM in parallel (while keeping codegen-units and ThinLTO)"), no_leak_check: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index 39601ad7622..e0bbaf730a5 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -689,7 +689,7 @@ impl SourceMap { whitespace_found = true; } - if whitespace_found && !c.is_whitespace() { false } else { true } + !whitespace_found || c.is_whitespace() }) } diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index 3fdbb4e6805..0dc3ad29833 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -17,6 +17,5 @@ rustc_macros = { path = "../librustc_macros" } rustc_target = { path = "../librustc_target" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } -chalk-engine = { version = "0.9.0", default-features=false } smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_infer = { path = "../librustc_infer" } diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs deleted file mode 100644 index 240a93f0900..00000000000 --- a/src/librustc_traits/chalk_context/mod.rs +++ /dev/null @@ -1,638 +0,0 @@ -mod program_clauses; -mod resolvent_ops; -mod unify; - -use chalk_engine::fallible::Fallible; -use chalk_engine::forest::Forest; -use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause, Literal}; -use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use rustc::ty::query::Providers; -use rustc::ty::subst::{GenericArg, GenericArgKind}; -use rustc::ty::{self, TyCtxt}; -use rustc_infer::infer::canonical::{ - Canonical, CanonicalVarValues, Certainty, OriginalQueryValues, QueryRegionConstraints, - QueryResponse, -}; -use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime, TyCtxtInferExt}; -use rustc_infer::traits::{ - self, ChalkCanonicalGoal, ChalkContextLift, Clause, DomainGoal, Environment, ExClauseFold, - Goal, GoalKind, InEnvironment, QuantifierKind, -}; -use rustc_macros::{Lift, TypeFoldable}; -use rustc_span::DUMMY_SP; - -use std::fmt::{self, Debug}; -use std::marker::PhantomData; - -use self::unify::*; - -#[derive(Copy, Clone, Debug)] -crate struct ChalkArenas<'tcx> { - _phantom: PhantomData<&'tcx ()>, -} - -#[derive(Copy, Clone)] -crate struct ChalkContext<'tcx> { - _arenas: ChalkArenas<'tcx>, - tcx: TyCtxt<'tcx>, -} - -#[derive(Copy, Clone)] -crate struct ChalkInferenceContext<'cx, 'tcx> { - infcx: &'cx InferCtxt<'cx, 'tcx>, -} - -#[derive(Copy, Clone, Debug)] -crate struct UniverseMap; - -crate type RegionConstraint<'tcx> = ty::OutlivesPredicate<GenericArg<'tcx>, ty::Region<'tcx>>; - -#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, Lift)] -crate struct ConstrainedSubst<'tcx> { - subst: CanonicalVarValues<'tcx>, - constraints: Vec<RegionConstraint<'tcx>>, -} - -impl context::Context for ChalkArenas<'tcx> { - type CanonicalExClause = Canonical<'tcx, ChalkExClause<'tcx>>; - - type CanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>; - - // u-canonicalization not yet implemented - type UCanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>; - - type CanonicalConstrainedSubst = Canonical<'tcx, ConstrainedSubst<'tcx>>; - - // u-canonicalization not yet implemented - type UniverseMap = UniverseMap; - - type Solution = Canonical<'tcx, QueryResponse<'tcx, ()>>; - - type InferenceNormalizedSubst = CanonicalVarValues<'tcx>; - - type GoalInEnvironment = InEnvironment<'tcx, Goal<'tcx>>; - - type RegionConstraint = RegionConstraint<'tcx>; - - type Substitution = CanonicalVarValues<'tcx>; - - type Environment = Environment<'tcx>; - - type Goal = Goal<'tcx>; - - type DomainGoal = DomainGoal<'tcx>; - - type BindersGoal = ty::Binder<Goal<'tcx>>; - - type Parameter = GenericArg<'tcx>; - - type ProgramClause = Clause<'tcx>; - - type ProgramClauses = Vec<Clause<'tcx>>; - - type UnificationResult = UnificationResult<'tcx>; - - type Variance = ty::Variance; - - fn goal_in_environment( - env: &Environment<'tcx>, - goal: Goal<'tcx>, - ) -> InEnvironment<'tcx, Goal<'tcx>> { - env.with(goal) - } -} - -impl context::AggregateOps<ChalkArenas<'tcx>> for ChalkContext<'tcx> { - fn make_solution( - &self, - root_goal: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - mut simplified_answers: impl context::AnswerStream<ChalkArenas<'tcx>>, - ) -> Option<Canonical<'tcx, QueryResponse<'tcx, ()>>> { - use chalk_engine::SimplifiedAnswer; - - debug!("make_solution(root_goal = {:?})", root_goal); - - if simplified_answers.peek_answer().is_none() { - return None; - } - - let SimplifiedAnswer { subst: constrained_subst, ambiguous } = - simplified_answers.next_answer().unwrap(); - - debug!("make_solution: ambiguous flag = {}", ambiguous); - - let ambiguous = simplified_answers.peek_answer().is_some() || ambiguous; - - let solution = constrained_subst.unchecked_map(|cs| match ambiguous { - true => QueryResponse { - var_values: cs.subst.make_identity(self.tcx), - region_constraints: QueryRegionConstraints::default(), - certainty: Certainty::Ambiguous, - value: (), - }, - - false => QueryResponse { - var_values: cs.subst, - region_constraints: QueryRegionConstraints::default(), - - // FIXME: restore this later once we get better at handling regions - // region_constraints: cs.constraints - // .into_iter() - // .map(|c| ty::Binder::bind(c)) - // .collect(), - certainty: Certainty::Proven, - value: (), - }, - }); - - debug!("make_solution: solution = {:?}", solution); - - Some(solution) - } -} - -impl context::ContextOps<ChalkArenas<'tcx>> for ChalkContext<'tcx> { - /// Returns `true` if this is a coinductive goal: basically proving that an auto trait - /// is implemented or proving that a trait reference is well-formed. - fn is_coinductive(&self, goal: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>) -> bool { - use rustc::traits::{WellFormed, WhereClause}; - - let mut goal = goal.value.goal; - loop { - match goal { - GoalKind::DomainGoal(domain_goal) => match domain_goal { - DomainGoal::WellFormed(WellFormed::Trait(..)) => return true, - DomainGoal::Holds(WhereClause::Implemented(trait_predicate)) => { - return self.tcx.trait_is_auto(trait_predicate.def_id()); - } - _ => return false, - }, - - GoalKind::Quantified(_, bound_goal) => goal = *bound_goal.skip_binder(), - _ => return false, - } - } - } - - /// Creates an inference table for processing a new goal and instantiate that goal - /// in that context, returning "all the pieces". - /// - /// More specifically: given a u-canonical goal `arg`, creates a - /// new inference table `T` and populates it with the universes - /// found in `arg`. Then, creates a substitution `S` that maps - /// each bound variable in `arg` to a fresh inference variable - /// from T. Returns: - /// - /// - the table `T`, - /// - the substitution `S`, - /// - the environment and goal found by substitution `S` into `arg`. - fn instantiate_ucanonical_goal<R>( - &self, - arg: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - op: impl context::WithInstantiatedUCanonicalGoal<ChalkArenas<'tcx>, Output = R>, - ) -> R { - self.tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, arg, |ref infcx, arg, subst| { - let chalk_infcx = &mut ChalkInferenceContext { infcx }; - op.with(chalk_infcx, subst, arg.environment, arg.goal) - }) - } - - fn instantiate_ex_clause<R>( - &self, - _num_universes: usize, - arg: &Canonical<'tcx, ChalkExClause<'tcx>>, - op: impl context::WithInstantiatedExClause<ChalkArenas<'tcx>, Output = R>, - ) -> R { - self.tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &arg.upcast(), |ref infcx, arg, _| { - let chalk_infcx = &mut ChalkInferenceContext { infcx }; - op.with(chalk_infcx, arg) - }) - } - - /// Returns `true` if this solution has no region constraints. - fn empty_constraints(ccs: &Canonical<'tcx, ConstrainedSubst<'tcx>>) -> bool { - ccs.value.constraints.is_empty() - } - - fn inference_normalized_subst_from_ex_clause( - canon_ex_clause: &'a Canonical<'tcx, ChalkExClause<'tcx>>, - ) -> &'a CanonicalVarValues<'tcx> { - &canon_ex_clause.value.subst - } - - fn inference_normalized_subst_from_subst( - canon_subst: &'a Canonical<'tcx, ConstrainedSubst<'tcx>>, - ) -> &'a CanonicalVarValues<'tcx> { - &canon_subst.value.subst - } - - fn canonical( - u_canon: &'a Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - ) -> &'a Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>> { - u_canon - } - - fn is_trivial_substitution( - u_canon: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>, - ) -> bool { - let subst = &canonical_subst.value.subst; - assert_eq!(u_canon.variables.len(), subst.var_values.len()); - subst.var_values.iter_enumerated().all(|(cvar, kind)| match kind.unpack() { - GenericArgKind::Lifetime(r) => match r { - &ty::ReLateBound(debruijn, br) => { - debug_assert_eq!(debruijn, ty::INNERMOST); - cvar == br.assert_bound_var() - } - _ => false, - }, - GenericArgKind::Type(ty) => match ty.kind { - ty::Bound(debruijn, bound_ty) => { - debug_assert_eq!(debruijn, ty::INNERMOST); - cvar == bound_ty.var - } - _ => false, - }, - GenericArgKind::Const(ct) => match ct.val { - ty::ConstKind::Bound(debruijn, bound_ct) => { - debug_assert_eq!(debruijn, ty::INNERMOST); - cvar == bound_ct - } - _ => false, - }, - }) - } - - fn num_universes(canon: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>) -> usize { - canon.max_universe.index() + 1 - } - - /// Convert a goal G *from* the canonical universes *into* our - /// local universes. This will yield a goal G' that is the same - /// but for the universes of universally quantified names. - fn map_goal_from_canonical( - _map: &UniverseMap, - value: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - ) -> Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>> { - *value // FIXME universe maps not implemented yet - } - - fn map_subst_from_canonical( - _map: &UniverseMap, - value: &Canonical<'tcx, ConstrainedSubst<'tcx>>, - ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> { - value.clone() // FIXME universe maps not implemented yet - } -} - -impl context::InferenceTable<ChalkArenas<'tcx>, ChalkArenas<'tcx>> - for ChalkInferenceContext<'cx, 'tcx> -{ - fn into_goal(&self, domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> { - self.infcx.tcx.mk_goal(GoalKind::DomainGoal(domain_goal)) - } - - fn cannot_prove(&self) -> Goal<'tcx> { - self.infcx.tcx.mk_goal(GoalKind::CannotProve) - } - - fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> { - match *goal { - GoalKind::Implies(hypotheses, goal) => { - HhGoal::Implies(hypotheses.iter().cloned().collect(), goal) - } - GoalKind::And(left, right) => HhGoal::And(left, right), - GoalKind::Not(subgoal) => HhGoal::Not(subgoal), - GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d), - GoalKind::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder), - GoalKind::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder), - GoalKind::Subtype(a, b) => HhGoal::Unify(ty::Variance::Covariant, a.into(), b.into()), - GoalKind::CannotProve => HhGoal::CannotProve, - } - } - - fn add_clauses( - &mut self, - env: &Environment<'tcx>, - clauses: Vec<Clause<'tcx>>, - ) -> Environment<'tcx> { - Environment { - clauses: self - .infcx - .tcx - .mk_clauses(env.clauses.iter().cloned().chain(clauses.into_iter())), - } - } -} - -impl context::TruncateOps<ChalkArenas<'tcx>, ChalkArenas<'tcx>> - for ChalkInferenceContext<'cx, 'tcx> -{ - fn truncate_goal( - &mut self, - _subgoal: &InEnvironment<'tcx, Goal<'tcx>>, - ) -> Option<InEnvironment<'tcx, Goal<'tcx>>> { - None // FIXME we should truncate at some point! - } - - fn truncate_answer( - &mut self, - _subst: &CanonicalVarValues<'tcx>, - ) -> Option<CanonicalVarValues<'tcx>> { - None // FIXME we should truncate at some point! - } -} - -impl context::UnificationOps<ChalkArenas<'tcx>, ChalkArenas<'tcx>> - for ChalkInferenceContext<'cx, 'tcx> -{ - fn program_clauses( - &self, - environment: &Environment<'tcx>, - goal: &DomainGoal<'tcx>, - ) -> Vec<Clause<'tcx>> { - self.program_clauses_impl(environment, goal) - } - - fn instantiate_binders_universally(&mut self, arg: &ty::Binder<Goal<'tcx>>) -> Goal<'tcx> { - self.infcx.replace_bound_vars_with_placeholders(arg).0 - } - - fn instantiate_binders_existentially(&mut self, arg: &ty::Binder<Goal<'tcx>>) -> Goal<'tcx> { - self.infcx - .replace_bound_vars_with_fresh_vars( - DUMMY_SP, - LateBoundRegionConversionTime::HigherRankedType, - arg, - ) - .0 - } - - fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box<dyn Debug + 'v> { - let string = format!("{:?}", self.infcx.resolve_vars_if_possible(value)); - Box::new(string) - } - - fn canonicalize_goal( - &mut self, - value: &InEnvironment<'tcx, Goal<'tcx>>, - ) -> Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>> { - let mut _orig_values = OriginalQueryValues::default(); - self.infcx.canonicalize_query(value, &mut _orig_values) - } - - fn canonicalize_ex_clause( - &mut self, - value: &ChalkExClause<'tcx>, - ) -> Canonical<'tcx, ChalkExClause<'tcx>> { - self.infcx.canonicalize_response(value) - } - - fn canonicalize_constrained_subst( - &mut self, - subst: CanonicalVarValues<'tcx>, - constraints: Vec<RegionConstraint<'tcx>>, - ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> { - self.infcx.canonicalize_response(&ConstrainedSubst { subst, constraints }) - } - - fn u_canonicalize_goal( - &mut self, - value: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - ) -> (Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, UniverseMap) { - (*value, UniverseMap) - } - - fn invert_goal( - &mut self, - _value: &InEnvironment<'tcx, Goal<'tcx>>, - ) -> Option<InEnvironment<'tcx, Goal<'tcx>>> { - panic!("goal inversion not yet implemented") - } - - fn unify_parameters( - &mut self, - environment: &Environment<'tcx>, - variance: ty::Variance, - a: &GenericArg<'tcx>, - b: &GenericArg<'tcx>, - ) -> Fallible<UnificationResult<'tcx>> { - self.infcx.commit_if_ok(|_| { - unify(self.infcx, *environment, variance, a, b) - .map_err(|_| chalk_engine::fallible::NoSolution) - }) - } - - fn sink_answer_subset( - &self, - value: &Canonical<'tcx, ConstrainedSubst<'tcx>>, - ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> { - value.clone() - } - - fn lift_delayed_literal( - &self, - value: DelayedLiteral<ChalkArenas<'tcx>>, - ) -> DelayedLiteral<ChalkArenas<'tcx>> { - match self.infcx.tcx.lift(&value) { - Some(literal) => literal, - None => bug!("cannot lift {:?}", value), - } - } - - fn into_ex_clause( - &mut self, - result: UnificationResult<'tcx>, - ex_clause: &mut ChalkExClause<'tcx>, - ) { - into_ex_clause(result, ex_clause); - } -} - -crate fn into_ex_clause(result: UnificationResult<'tcx>, ex_clause: &mut ChalkExClause<'tcx>) { - ex_clause.subgoals.extend(result.goals.into_iter().map(Literal::Positive)); - - // FIXME: restore this later once we get better at handling regions - let _ = result.constraints.len(); // trick `-D dead-code` - // ex_clause.constraints.extend(result.constraints); -} - -type ChalkHhGoal<'tcx> = HhGoal<ChalkArenas<'tcx>>; - -type ChalkExClause<'tcx> = ExClause<ChalkArenas<'tcx>>; - -impl Debug for ChalkContext<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ChalkContext") - } -} - -impl Debug for ChalkInferenceContext<'cx, 'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ChalkInferenceContext") - } -} - -impl ChalkContextLift<'tcx> for ChalkArenas<'a> { - type LiftedExClause = ChalkExClause<'tcx>; - type LiftedDelayedLiteral = DelayedLiteral<ChalkArenas<'tcx>>; - type LiftedLiteral = Literal<ChalkArenas<'tcx>>; - - fn lift_ex_clause_to_tcx( - ex_clause: &ChalkExClause<'a>, - tcx: TyCtxt<'tcx>, - ) -> Option<Self::LiftedExClause> { - Some(ChalkExClause { - subst: tcx.lift(&ex_clause.subst)?, - delayed_literals: tcx.lift(&ex_clause.delayed_literals)?, - constraints: tcx.lift(&ex_clause.constraints)?, - subgoals: tcx.lift(&ex_clause.subgoals)?, - }) - } - - fn lift_delayed_literal_to_tcx( - literal: &DelayedLiteral<ChalkArenas<'a>>, - tcx: TyCtxt<'tcx>, - ) -> Option<Self::LiftedDelayedLiteral> { - Some(match literal { - DelayedLiteral::CannotProve(()) => DelayedLiteral::CannotProve(()), - DelayedLiteral::Negative(index) => DelayedLiteral::Negative(*index), - DelayedLiteral::Positive(index, subst) => { - DelayedLiteral::Positive(*index, tcx.lift(subst)?) - } - }) - } - - fn lift_literal_to_tcx( - literal: &Literal<ChalkArenas<'a>>, - tcx: TyCtxt<'tcx>, - ) -> Option<Self::LiftedLiteral> { - Some(match literal { - Literal::Negative(goal) => Literal::Negative(tcx.lift(goal)?), - Literal::Positive(goal) => Literal::Positive(tcx.lift(goal)?), - }) - } -} - -impl ExClauseFold<'tcx> for ChalkArenas<'tcx> { - fn fold_ex_clause_with<F: TypeFolder<'tcx>>( - ex_clause: &ChalkExClause<'tcx>, - folder: &mut F, - ) -> ChalkExClause<'tcx> { - ExClause { - subst: ex_clause.subst.fold_with(folder), - delayed_literals: ex_clause.delayed_literals.fold_with(folder), - constraints: ex_clause.constraints.fold_with(folder), - subgoals: ex_clause.subgoals.fold_with(folder), - } - } - - fn visit_ex_clause_with<V: TypeVisitor<'tcx>>( - ex_clause: &ExClause<Self>, - visitor: &mut V, - ) -> bool { - let ExClause { subst, delayed_literals, constraints, subgoals } = ex_clause; - subst.visit_with(visitor) - || delayed_literals.visit_with(visitor) - || constraints.visit_with(visitor) - || subgoals.visit_with(visitor) - } -} - -trait Upcast<'tcx>: 'tcx { - type Upcasted: 'tcx; - - fn upcast(&self) -> Self::Upcasted; -} - -impl<'tcx> Upcast<'tcx> for DelayedLiteral<ChalkArenas<'tcx>> { - type Upcasted = DelayedLiteral<ChalkArenas<'tcx>>; - - fn upcast(&self) -> Self::Upcasted { - match self { - &DelayedLiteral::CannotProve(..) => DelayedLiteral::CannotProve(()), - &DelayedLiteral::Negative(index) => DelayedLiteral::Negative(index), - DelayedLiteral::Positive(index, subst) => { - DelayedLiteral::Positive(*index, subst.clone()) - } - } - } -} - -impl<'tcx> Upcast<'tcx> for Literal<ChalkArenas<'tcx>> { - type Upcasted = Literal<ChalkArenas<'tcx>>; - - fn upcast(&self) -> Self::Upcasted { - match self { - &Literal::Negative(goal) => Literal::Negative(goal), - &Literal::Positive(goal) => Literal::Positive(goal), - } - } -} - -impl<'tcx> Upcast<'tcx> for ExClause<ChalkArenas<'tcx>> { - type Upcasted = ExClause<ChalkArenas<'tcx>>; - - fn upcast(&self) -> Self::Upcasted { - ExClause { - subst: self.subst.clone(), - delayed_literals: self.delayed_literals.iter().map(|l| l.upcast()).collect(), - constraints: self.constraints.clone(), - subgoals: self.subgoals.iter().map(|g| g.upcast()).collect(), - } - } -} - -impl<'tcx, T> Upcast<'tcx> for Canonical<'tcx, T> -where - T: Upcast<'tcx>, -{ - type Upcasted = Canonical<'tcx, T::Upcasted>; - - fn upcast(&self) -> Self::Upcasted { - Canonical { - max_universe: self.max_universe, - value: self.value.upcast(), - variables: self.variables, - } - } -} - -crate fn provide(p: &mut Providers<'_>) { - *p = Providers { evaluate_goal, ..*p }; -} - -crate fn evaluate_goal<'tcx>( - tcx: TyCtxt<'tcx>, - goal: ChalkCanonicalGoal<'tcx>, -) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, traits::query::NoSolution> { - use crate::lowering::Lower; - use rustc::traits::WellFormed; - - let goal = goal.unchecked_map(|goal| InEnvironment { - environment: goal.environment, - goal: match goal.goal { - ty::Predicate::WellFormed(ty) => { - tcx.mk_goal(GoalKind::DomainGoal(DomainGoal::WellFormed(WellFormed::Ty(ty)))) - } - - ty::Predicate::Subtype(predicate) => tcx.mk_goal(GoalKind::Quantified( - QuantifierKind::Universal, - predicate.map_bound(|pred| tcx.mk_goal(GoalKind::Subtype(pred.a, pred.b))), - )), - - other => tcx.mk_goal(GoalKind::from_poly_domain_goal(other.lower(), tcx)), - }, - }); - - debug!("evaluate_goal(goal = {:?})", goal); - - let context = ChalkContext { _arenas: ChalkArenas { _phantom: PhantomData }, tcx }; - - let mut forest = Forest::new(context); - let solution = forest.solve(&goal); - - debug!("evaluate_goal: solution = {:?}", solution); - - solution.map(|ok| Ok(&*tcx.arena.alloc(ok))).unwrap_or(Err(traits::query::NoSolution)) -} diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs deleted file mode 100644 index 7512cbbd882..00000000000 --- a/src/librustc_traits/chalk_context/program_clauses/builtin.rs +++ /dev/null @@ -1,316 +0,0 @@ -use crate::generic_types; -use crate::lowering::Lower; -use rustc::traits::{Clause, GoalKind, ProgramClause, ProgramClauseCategory}; -use rustc::ty::subst::{GenericArg, InternalSubsts, Subst}; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc_hir as hir; -use rustc_hir::def_id::DefId; - -/// Returns a predicate of the form -/// `Implemented(ty: Trait) :- Implemented(nested: Trait)...` -/// where `Trait` is specified by `trait_def_id`. -fn builtin_impl_clause( - tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>, - nested: &[GenericArg<'tcx>], - trait_def_id: DefId, -) -> ProgramClause<'tcx> { - ProgramClause { - goal: ty::TraitPredicate { - trait_ref: ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) }, - } - .lower(), - hypotheses: tcx.mk_goals( - nested - .iter() - .cloned() - .map(|nested_ty| ty::TraitRef { - def_id: trait_def_id, - substs: tcx.mk_substs_trait(nested_ty.expect_ty(), &[]), - }) - .map(|trait_ref| ty::TraitPredicate { trait_ref }) - .map(|pred| GoalKind::DomainGoal(pred.lower())) - .map(|goal_kind| tcx.mk_goal(goal_kind)), - ), - category: ProgramClauseCategory::Other, - } -} - -crate fn assemble_builtin_unsize_impls<'tcx>( - tcx: TyCtxt<'tcx>, - unsize_def_id: DefId, - source: Ty<'tcx>, - target: Ty<'tcx>, - clauses: &mut Vec<Clause<'tcx>>, -) { - match (&source.kind, &target.kind) { - (ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => { - if data_a.principal_def_id() != data_b.principal_def_id() - || data_b.auto_traits().any(|b| data_a.auto_traits().all(|a| a != b)) - { - return; - } - - // FIXME: rules for trait upcast - } - - (_, &ty::Dynamic(..)) => { - // FIXME: basically, we should have something like: - // ``` - // forall<T> { - // Implemented(T: Unsize< for<...> dyn Trait<...> >) :- - // for<...> Implemented(T: Trait<...>). - // } - // ``` - // The question is: how to correctly handle the higher-ranked - // `for<...>` binder in order to have a generic rule? - // (Having generic rules is useful for caching, as we may be able - // to turn this function and others into tcx queries later on). - } - - (ty::Array(_, length), ty::Slice(_)) => { - let ty_param = generic_types::bound(tcx, 0); - let array_ty = tcx.mk_ty(ty::Array(ty_param, length)); - let slice_ty = tcx.mk_ty(ty::Slice(ty_param)); - - // `forall<T> { Implemented([T; N]: Unsize<[T]>). }` - let clause = ProgramClause { - goal: ty::TraitPredicate { - trait_ref: ty::TraitRef { - def_id: unsize_def_id, - substs: tcx.mk_substs_trait(array_ty, &[slice_ty.into()]), - }, - } - .lower(), - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::Other, - }; - - clauses.push(Clause::ForAll(ty::Binder::bind(clause))); - } - - (ty::Infer(ty::TyVar(_)), _) | (_, ty::Infer(ty::TyVar(_))) => { - // FIXME: ambiguous - } - - (ty::Adt(def_id_a, ..), ty::Adt(def_id_b, ..)) => { - if def_id_a != def_id_b { - return; - } - - // FIXME: rules for struct unsizing - } - - (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => { - if tys_a.len() != tys_b.len() { - return; - } - - // FIXME: rules for tuple unsizing - } - - _ => (), - } -} - -crate fn assemble_builtin_sized_impls<'tcx>( - tcx: TyCtxt<'tcx>, - sized_def_id: DefId, - ty: Ty<'tcx>, - clauses: &mut Vec<Clause<'tcx>>, -) { - let mut push_builtin_impl = |ty: Ty<'tcx>, nested: &[GenericArg<'tcx>]| { - let clause = builtin_impl_clause(tcx, ty, nested, sized_def_id); - // Bind innermost bound vars that may exist in `ty` and `nested`. - clauses.push(Clause::ForAll(ty::Binder::bind(clause))); - }; - - match &ty.kind { - // Non parametric primitive types. - ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::Infer(ty::IntVar(_)) - | ty::Infer(ty::FloatVar(_)) - | ty::Error - | ty::Never => push_builtin_impl(ty, &[]), - - // These ones are always `Sized`. - &ty::Array(_, length) => { - push_builtin_impl(tcx.mk_ty(ty::Array(generic_types::bound(tcx, 0), length)), &[]); - } - ty::RawPtr(ptr) => { - push_builtin_impl(generic_types::raw_ptr(tcx, ptr.mutbl), &[]); - } - &ty::Ref(_, _, mutbl) => { - push_builtin_impl(generic_types::ref_ty(tcx, mutbl), &[]); - } - ty::FnPtr(fn_ptr) => { - let fn_ptr = fn_ptr.skip_binder(); - let fn_ptr = generic_types::fn_ptr( - tcx, - fn_ptr.inputs_and_output.len(), - fn_ptr.c_variadic, - fn_ptr.unsafety, - fn_ptr.abi, - ); - push_builtin_impl(fn_ptr, &[]); - } - &ty::FnDef(def_id, ..) => { - push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]); - } - &ty::Closure(def_id, ..) => { - push_builtin_impl(generic_types::closure(tcx, def_id), &[]); - } - &ty::Generator(def_id, ..) => { - push_builtin_impl(generic_types::generator(tcx, def_id), &[]); - } - - // `Sized` if the last type is `Sized` (because else we will get a WF error anyway). - &ty::Tuple(type_list) => { - let type_list = generic_types::type_list(tcx, type_list.len()); - push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &type_list); - } - - // Struct def - ty::Adt(adt_def, _) => { - let substs = InternalSubsts::bound_vars_for_item(tcx, adt_def.did); - let adt = tcx.mk_ty(ty::Adt(adt_def, substs)); - let sized_constraint = adt_def - .sized_constraint(tcx) - .iter() - .map(|ty| GenericArg::from(ty.subst(tcx, substs))) - .collect::<Vec<_>>(); - push_builtin_impl(adt, &sized_constraint); - } - - // Artificially trigger an ambiguity by adding two possible types to - // unify against. - ty::Infer(ty::TyVar(_)) => { - push_builtin_impl(tcx.types.i32, &[]); - push_builtin_impl(tcx.types.f32, &[]); - } - - ty::Projection(_projection_ty) => { - // FIXME: add builtin impls from the associated type values found in - // trait impls of `projection_ty.trait_ref(tcx)`. - } - - // The `Sized` bound can only come from the environment. - ty::Param(..) | ty::Placeholder(..) | ty::UnnormalizedProjection(..) => (), - - // Definitely not `Sized`. - ty::Foreign(..) | ty::Str | ty::Slice(..) | ty::Dynamic(..) | ty::Opaque(..) => (), - - ty::Bound(..) - | ty::GeneratorWitness(..) - | ty::Infer(ty::FreshTy(_)) - | ty::Infer(ty::FreshIntTy(_)) - | ty::Infer(ty::FreshFloatTy(_)) => bug!("unexpected type {:?}", ty), - } -} - -crate fn assemble_builtin_copy_clone_impls<'tcx>( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, - ty: Ty<'tcx>, - clauses: &mut Vec<Clause<'tcx>>, -) { - let mut push_builtin_impl = |ty: Ty<'tcx>, nested: &[GenericArg<'tcx>]| { - let clause = builtin_impl_clause(tcx, ty, nested, trait_def_id); - // Bind innermost bound vars that may exist in `ty` and `nested`. - clauses.push(Clause::ForAll(ty::Binder::bind(clause))); - }; - - match &ty.kind { - // Implementations provided in libcore. - ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::RawPtr(..) - | ty::Never - | ty::Ref(_, _, hir::Mutability::Not) => (), - - // Non parametric primitive types. - ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) | ty::Error => { - push_builtin_impl(ty, &[]) - } - - // These implement `Copy`/`Clone` if their element types do. - &ty::Array(_, length) => { - let element_ty = generic_types::bound(tcx, 0); - push_builtin_impl( - tcx.mk_ty(ty::Array(element_ty, length)), - &[GenericArg::from(element_ty)], - ); - } - &ty::Tuple(type_list) => { - let type_list = generic_types::type_list(tcx, type_list.len()); - push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list); - } - &ty::Closure(def_id, ..) => { - let closure_ty = generic_types::closure(tcx, def_id); - let upvar_tys: Vec<_> = match &closure_ty.kind { - ty::Closure(_, substs) => substs - .as_closure() - .upvar_tys(def_id, tcx) - .map(|ty| GenericArg::from(ty)) - .collect(), - _ => bug!(), - }; - push_builtin_impl(closure_ty, &upvar_tys); - } - - // These ones are always `Clone`. - ty::FnPtr(fn_ptr) => { - let fn_ptr = fn_ptr.skip_binder(); - let fn_ptr = generic_types::fn_ptr( - tcx, - fn_ptr.inputs_and_output.len(), - fn_ptr.c_variadic, - fn_ptr.unsafety, - fn_ptr.abi, - ); - push_builtin_impl(fn_ptr, &[]); - } - &ty::FnDef(def_id, ..) => { - push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]); - } - - // These depend on whatever user-defined impls might exist. - ty::Adt(_, _) => (), - - // Artificially trigger an ambiguity by adding two possible types to - // unify against. - ty::Infer(ty::TyVar(_)) => { - push_builtin_impl(tcx.types.i32, &[]); - push_builtin_impl(tcx.types.f32, &[]); - } - - ty::Projection(_projection_ty) => { - // FIXME: add builtin impls from the associated type values found in - // trait impls of `projection_ty.trait_ref(tcx)`. - } - - // The `Copy`/`Clone` bound can only come from the environment. - ty::Param(..) | ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::Opaque(..) => (), - - // Definitely not `Copy`/`Clone`. - ty::Dynamic(..) - | ty::Foreign(..) - | ty::Generator(..) - | ty::Str - | ty::Slice(..) - | ty::Ref(_, _, hir::Mutability::Mut) => (), - - ty::Bound(..) - | ty::GeneratorWitness(..) - | ty::Infer(ty::FreshTy(_)) - | ty::Infer(ty::FreshIntTy(_)) - | ty::Infer(ty::FreshFloatTy(_)) => bug!("unexpected type {:?}", ty), - } -} diff --git a/src/librustc_traits/chalk_context/program_clauses/mod.rs b/src/librustc_traits/chalk_context/program_clauses/mod.rs deleted file mode 100644 index 38a4a729648..00000000000 --- a/src/librustc_traits/chalk_context/program_clauses/mod.rs +++ /dev/null @@ -1,300 +0,0 @@ -mod builtin; -mod primitive; - -use super::ChalkInferenceContext; -use rustc::traits::{ - Clause, DomainGoal, Environment, FromEnv, ProgramClause, ProgramClauseCategory, WellFormed, -}; -use rustc::ty::{self, TyCtxt}; -use rustc_hir::def_id::DefId; -use std::iter; - -use self::builtin::*; -use self::primitive::*; - -fn assemble_clauses_from_impls<'tcx>( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, - clauses: &mut Vec<Clause<'tcx>>, -) { - tcx.for_each_impl(trait_def_id, |impl_def_id| { - clauses.extend(tcx.program_clauses_for(impl_def_id).into_iter().cloned()); - }); -} - -fn assemble_clauses_from_assoc_ty_values<'tcx>( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, - clauses: &mut Vec<Clause<'tcx>>, -) { - tcx.for_each_impl(trait_def_id, |impl_def_id| { - for def_id in tcx.associated_item_def_ids(impl_def_id).iter() { - clauses.extend(tcx.program_clauses_for(*def_id).into_iter().cloned()); - } - }); -} - -impl ChalkInferenceContext<'cx, 'tcx> { - pub(super) fn program_clauses_impl( - &self, - environment: &Environment<'tcx>, - goal: &DomainGoal<'tcx>, - ) -> Vec<Clause<'tcx>> { - use rustc::infer::canonical::OriginalQueryValues; - use rustc::traits::WhereClause::*; - - let goal = self.infcx.resolve_vars_if_possible(goal); - - debug!("program_clauses(goal = {:?})", goal); - - let mut clauses = match goal { - DomainGoal::Holds(Implemented(trait_predicate)) => { - // These come from: - // * implementations of the trait itself (rule `Implemented-From-Impl`) - // * the trait decl (rule `Implemented-From-Env`) - - let mut clauses = vec![]; - - assemble_clauses_from_impls(self.infcx.tcx, trait_predicate.def_id(), &mut clauses); - - if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() { - assemble_builtin_sized_impls( - self.infcx.tcx, - trait_predicate.def_id(), - trait_predicate.self_ty(), - &mut clauses, - ); - } - - if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().unsize_trait() { - let source = trait_predicate.self_ty(); - let target = trait_predicate.trait_ref.substs.type_at(1); - assemble_builtin_unsize_impls( - self.infcx.tcx, - trait_predicate.def_id(), - source, - target, - &mut clauses, - ); - } - - if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().copy_trait() { - assemble_builtin_copy_clone_impls( - self.infcx.tcx, - trait_predicate.def_id(), - trait_predicate.self_ty(), - &mut clauses, - ); - } - - if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().clone_trait() { - // For all builtin impls, the conditions for `Copy` and - // `Clone` are the same. - assemble_builtin_copy_clone_impls( - self.infcx.tcx, - trait_predicate.def_id(), - trait_predicate.self_ty(), - &mut clauses, - ); - } - - // FIXME: we need to add special rules for other builtin impls: - // * `Generator` - // * `FnOnce` / `FnMut` / `Fn` - // * trait objects - // * auto traits - - // Rule `Implemented-From-Env` will be computed from the environment. - clauses - } - - DomainGoal::Holds(ProjectionEq(projection_predicate)) => { - // These come from: - // * the assoc type definition (rule `ProjectionEq-Placeholder`) - // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`) - // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`) - // * implied bounds from type definitions (rule `Implied-Bound-From-Type`) - - let clauses = self - .infcx - .tcx - .program_clauses_for(projection_predicate.projection_ty.item_def_id) - .into_iter() - // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize` - .filter(|clause| clause.category() == ProgramClauseCategory::Other) - .cloned() - .collect::<Vec<_>>(); - - // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed - // from the environment. - clauses - } - - // For outlive requirements, just assume they hold. `ResolventOps::resolvent_clause` - // will register them as actual region constraints later. - DomainGoal::Holds(RegionOutlives(..)) | DomainGoal::Holds(TypeOutlives(..)) => { - vec![Clause::Implies(ProgramClause { - goal, - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::Other, - })] - } - - DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => { - // These come from -- the trait decl (rule `WellFormed-TraitRef`). - self.infcx - .tcx - .program_clauses_for(trait_predicate.def_id()) - .into_iter() - // only select `WellFormed-TraitRef` - .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed) - .cloned() - .collect() - } - - DomainGoal::WellFormed(WellFormed::Ty(ty)) => { - // These come from: - // * the associated type definition if `ty` refers to an unnormalized - // associated type (rule `WellFormed-AssocTy`) - // * custom rules for built-in types - // * the type definition otherwise (rule `WellFormed-Type`) - let clauses = match ty.kind { - ty::Projection(data) => self.infcx.tcx.program_clauses_for(data.item_def_id), - - // These types are always WF. - ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::Str - | ty::Param(..) - | ty::Placeholder(..) - | ty::Error - | ty::Never => { - let wf_clause = ProgramClause { - goal, - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::Implies(wf_clause); - - self.infcx.tcx.mk_clauses(iter::once(wf_clause)) - } - - // Always WF (recall that we do not check for parameters to be WF). - ty::RawPtr(ptr) => wf_clause_for_raw_ptr(self.infcx.tcx, ptr.mutbl), - - // Always WF (recall that we do not check for parameters to be WF). - ty::FnPtr(fn_ptr) => { - let fn_ptr = fn_ptr.skip_binder(); - wf_clause_for_fn_ptr( - self.infcx.tcx, - fn_ptr.inputs_and_output.len(), - fn_ptr.c_variadic, - fn_ptr.unsafety, - fn_ptr.abi, - ) - } - - // WF if inner type is `Sized`. - ty::Slice(..) => wf_clause_for_slice(self.infcx.tcx), - - // WF if inner type is `Sized`. - ty::Array(_, length) => wf_clause_for_array(self.infcx.tcx, length), - - // WF if all types but the last one are `Sized`. - ty::Tuple(types) => wf_clause_for_tuple(self.infcx.tcx, types.len()), - - // WF if `sub_ty` outlives `region`. - ty::Ref(_, _, mutbl) => wf_clause_for_ref(self.infcx.tcx, mutbl), - - ty::FnDef(def_id, ..) => wf_clause_for_fn_def(self.infcx.tcx, def_id), - - ty::Dynamic(..) => { - // FIXME: no rules yet for trait objects - ty::List::empty() - } - - ty::Adt(def, ..) => self.infcx.tcx.program_clauses_for(def.did), - - // FIXME: these are probably wrong - ty::Foreign(def_id) - | ty::Closure(def_id, ..) - | ty::Generator(def_id, ..) - | ty::Opaque(def_id, ..) => self.infcx.tcx.program_clauses_for(def_id), - - // Artificially trigger an ambiguity. - ty::Infer(..) => { - let tcx = self.infcx.tcx; - let types = [tcx.types.i32, tcx.types.u32, tcx.types.f32, tcx.types.f64]; - let clauses = types - .iter() - .cloned() - .map(|ty| ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(ty)), - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::WellFormed, - }) - .map(|clause| Clause::Implies(clause)); - tcx.mk_clauses(clauses) - } - - ty::GeneratorWitness(..) | ty::UnnormalizedProjection(..) | ty::Bound(..) => { - bug!("unexpected type {:?}", ty) - } - }; - - clauses - .into_iter() - .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed) - .cloned() - .collect() - } - - DomainGoal::FromEnv(FromEnv::Trait(..)) => { - // These come from: - // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`) - // * implied bounds from type definitions (rule `Implied-Bound-From-Type`) - // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`, - // `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`) - - // All of these rules are computed in the environment. - vec![] - } - - DomainGoal::FromEnv(FromEnv::Ty(..)) => { - // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only - // comes from the environment). - vec![] - } - - DomainGoal::Normalize(projection_predicate) => { - // These come from -- assoc ty values (rule `Normalize-From-Impl`). - let mut clauses = vec![]; - - assemble_clauses_from_assoc_ty_values( - self.infcx.tcx, - projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id, - &mut clauses, - ); - - clauses - } - }; - - debug!("program_clauses: clauses = {:?}", clauses); - debug!("program_clauses: adding clauses from environment = {:?}", environment); - - let mut _orig_query_values = OriginalQueryValues::default(); - let canonical_environment = - self.infcx.canonicalize_query(environment, &mut _orig_query_values).value; - let env_clauses = self.infcx.tcx.program_clauses_for_env(canonical_environment); - - debug!("program_clauses: env_clauses = {:?}", env_clauses); - - clauses.extend(env_clauses.into_iter().cloned()); - clauses.extend(environment.clauses.iter().cloned()); - clauses - } -} diff --git a/src/librustc_traits/chalk_context/program_clauses/primitive.rs b/src/librustc_traits/chalk_context/program_clauses/primitive.rs deleted file mode 100644 index ae4afe58436..00000000000 --- a/src/librustc_traits/chalk_context/program_clauses/primitive.rs +++ /dev/null @@ -1,168 +0,0 @@ -use crate::generic_types; -use crate::lowering::Lower; -use rustc::traits::{ - Clause, Clauses, DomainGoal, GoalKind, ProgramClause, ProgramClauseCategory, WellFormed, -}; -use rustc::ty::{self, TyCtxt}; -use rustc_hir as hir; -use rustc_hir::def_id::DefId; -use rustc_target::spec::abi; -use std::iter; - -crate fn wf_clause_for_raw_ptr(tcx: TyCtxt<'_>, mutbl: hir::Mutability) -> Clauses<'_> { - let ptr_ty = generic_types::raw_ptr(tcx, mutbl); - - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)), - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::Implies(wf_clause); - - // `forall<T> { WellFormed(*const T). }` - tcx.mk_clauses(iter::once(wf_clause)) -} - -crate fn wf_clause_for_fn_ptr( - tcx: TyCtxt<'_>, - arity_and_output: usize, - variadic: bool, - unsafety: hir::Unsafety, - abi: abi::Abi, -) -> Clauses<'_> { - let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, variadic, unsafety, abi); - - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)), - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); - - // `forall <T1, ..., Tn+1> { WellFormed(for<> fn(T1, ..., Tn) -> Tn+1). }` - // where `n + 1` == `arity_and_output` - tcx.mk_clauses(iter::once(wf_clause)) -} - -crate fn wf_clause_for_slice(tcx: TyCtxt<'_>) -> Clauses<'_> { - let ty = generic_types::bound(tcx, 0); - let slice_ty = tcx.mk_slice(ty); - - let sized_trait = match tcx.lang_items().sized_trait() { - Some(def_id) => def_id, - None => return ty::List::empty(), - }; - let sized_implemented = - ty::TraitRef { def_id: sized_trait, substs: tcx.mk_substs_trait(ty, ty::List::empty()) }; - let sized_implemented: DomainGoal<'_> = - ty::TraitPredicate { trait_ref: sized_implemented }.lower(); - - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(slice_ty)), - hypotheses: tcx.mk_goals(iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); - - // `forall<T> { WellFormed([T]) :- Implemented(T: Sized). }` - tcx.mk_clauses(iter::once(wf_clause)) -} - -crate fn wf_clause_for_array<'tcx>( - tcx: TyCtxt<'tcx>, - length: &'tcx ty::Const<'tcx>, -) -> Clauses<'tcx> { - let ty = generic_types::bound(tcx, 0); - let array_ty = tcx.mk_ty(ty::Array(ty, length)); - - let sized_trait = match tcx.lang_items().sized_trait() { - Some(def_id) => def_id, - None => return ty::List::empty(), - }; - let sized_implemented = - ty::TraitRef { def_id: sized_trait, substs: tcx.mk_substs_trait(ty, ty::List::empty()) }; - let sized_implemented: DomainGoal<'_> = - ty::TraitPredicate { trait_ref: sized_implemented }.lower(); - - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(array_ty)), - hypotheses: tcx.mk_goals(iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); - - // `forall<T> { WellFormed([T; length]) :- Implemented(T: Sized). }` - tcx.mk_clauses(iter::once(wf_clause)) -} - -crate fn wf_clause_for_tuple(tcx: TyCtxt<'_>, arity: usize) -> Clauses<'_> { - let type_list = generic_types::type_list(tcx, arity); - let tuple_ty = tcx.mk_ty(ty::Tuple(type_list)); - - let sized_trait = match tcx.lang_items().sized_trait() { - Some(def_id) => def_id, - None => return ty::List::empty(), - }; - - // If `arity == 0` (i.e. the unit type) or `arity == 1`, this list of - // hypotheses is actually empty. - let sized_implemented = type_list[0..std::cmp::max(arity, 1) - 1] - .iter() - .map(|ty| ty::TraitRef { - def_id: sized_trait, - substs: tcx.mk_substs_trait(ty.expect_ty(), ty::List::empty()), - }) - .map(|trait_ref| ty::TraitPredicate { trait_ref }) - .map(|predicate| predicate.lower()); - - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(tuple_ty)), - hypotheses: tcx.mk_goals( - sized_implemented.map(|domain_goal| tcx.mk_goal(GoalKind::DomainGoal(domain_goal))), - ), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); - - // ``` - // forall<T1, ..., Tn-1, Tn> { - // WellFormed((T1, ..., Tn)) :- - // Implemented(T1: Sized), - // ... - // Implemented(Tn-1: Sized). - // } - // ``` - tcx.mk_clauses(iter::once(wf_clause)) -} - -crate fn wf_clause_for_ref(tcx: TyCtxt<'_>, mutbl: hir::Mutability) -> Clauses<'_> { - let region = tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))); - let ty = generic_types::bound(tcx, 1); - let ref_ty = tcx.mk_ref(region, ty::TypeAndMut { ty, mutbl }); - - let outlives: DomainGoal<'_> = ty::OutlivesPredicate(ty, region).lower(); - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)), - hypotheses: tcx.mk_goals(iter::once(tcx.mk_goal(outlives.into_goal()))), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); - - // `forall<'a, T> { WellFormed(&'a T) :- Outlives(T: 'a). }` - tcx.mk_clauses(iter::once(wf_clause)) -} - -crate fn wf_clause_for_fn_def(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> { - let fn_def = generic_types::fn_def(tcx, def_id); - - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(fn_def)), - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); - - // `forall <T1, ..., Tn+1> { WellFormed(fn some_fn(T1, ..., Tn) -> Tn+1). }` - // where `def_id` maps to the `some_fn` function definition - tcx.mk_clauses(iter::once(wf_clause)) -} diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs deleted file mode 100644 index 796ce6085fd..00000000000 --- a/src/librustc_traits/chalk_context/resolvent_ops.rs +++ /dev/null @@ -1,297 +0,0 @@ -use chalk_engine::fallible::{Fallible, NoSolution}; -use chalk_engine::{context, ExClause, Literal}; -use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; -use rustc::ty::subst::GenericArg; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime}; -use rustc_infer::traits::{ - Clause, DomainGoal, Environment, Goal, GoalKind, InEnvironment, ProgramClause, WhereClause, -}; -use rustc_span::DUMMY_SP; - -use super::unify::*; -use super::{ChalkArenas, ChalkExClause, ChalkInferenceContext, ConstrainedSubst}; - -impl context::ResolventOps<ChalkArenas<'tcx>, ChalkArenas<'tcx>> - for ChalkInferenceContext<'cx, 'tcx> -{ - fn resolvent_clause( - &mut self, - environment: &Environment<'tcx>, - goal: &DomainGoal<'tcx>, - subst: &CanonicalVarValues<'tcx>, - clause: &Clause<'tcx>, - ) -> Fallible<Canonical<'tcx, ChalkExClause<'tcx>>> { - use chalk_engine::context::UnificationOps; - - debug!("resolvent_clause(goal = {:?}, clause = {:?})", goal, clause); - - let result = self.infcx.probe(|_| { - let ProgramClause { goal: consequence, hypotheses, .. } = match clause { - Clause::Implies(program_clause) => *program_clause, - Clause::ForAll(program_clause) => { - self.infcx - .replace_bound_vars_with_fresh_vars( - DUMMY_SP, - LateBoundRegionConversionTime::HigherRankedType, - program_clause, - ) - .0 - } - }; - - let result = - unify(self.infcx, *environment, ty::Variance::Invariant, goal, &consequence) - .map_err(|_| NoSolution)?; - - let mut ex_clause = ExClause { - subst: subst.clone(), - delayed_literals: vec![], - constraints: vec![], - subgoals: vec![], - }; - - self.into_ex_clause(result, &mut ex_clause); - - ex_clause.subgoals.extend(hypotheses.iter().map(|g| match g { - GoalKind::Not(g) => Literal::Negative(environment.with(*g)), - g => Literal::Positive(environment.with(*g)), - })); - - // If we have a goal of the form `T: 'a` or `'a: 'b`, then just - // assume it is true (no subgoals) and register it as a constraint - // instead. - match goal { - DomainGoal::Holds(WhereClause::RegionOutlives(pred)) => { - assert_eq!(ex_clause.subgoals.len(), 0); - ex_clause.constraints.push(ty::OutlivesPredicate(pred.0.into(), pred.1)); - } - - DomainGoal::Holds(WhereClause::TypeOutlives(pred)) => { - assert_eq!(ex_clause.subgoals.len(), 0); - ex_clause.constraints.push(ty::OutlivesPredicate(pred.0.into(), pred.1)); - } - - _ => (), - }; - - let canonical_ex_clause = self.canonicalize_ex_clause(&ex_clause); - Ok(canonical_ex_clause) - }); - - debug!("resolvent_clause: result = {:?}", result); - result - } - - fn apply_answer_subst( - &mut self, - ex_clause: ChalkExClause<'tcx>, - selected_goal: &InEnvironment<'tcx, Goal<'tcx>>, - answer_table_goal: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - canonical_answer_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>, - ) -> Fallible<ChalkExClause<'tcx>> { - debug!( - "apply_answer_subst(ex_clause = {:?}, selected_goal = {:?})", - self.infcx.resolve_vars_if_possible(&ex_clause), - self.infcx.resolve_vars_if_possible(selected_goal) - ); - - let (answer_subst, _) = self - .infcx - .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, canonical_answer_subst); - - let mut substitutor = AnswerSubstitutor { - infcx: self.infcx, - environment: selected_goal.environment, - answer_subst: answer_subst.subst, - binder_index: ty::INNERMOST, - ex_clause, - }; - - substitutor.relate(&answer_table_goal.value, &selected_goal).map_err(|_| NoSolution)?; - - let mut ex_clause = substitutor.ex_clause; - ex_clause.constraints.extend(answer_subst.constraints); - - debug!("apply_answer_subst: ex_clause = {:?}", ex_clause); - Ok(ex_clause) - } -} - -struct AnswerSubstitutor<'cx, 'tcx> { - infcx: &'cx InferCtxt<'cx, 'tcx>, - environment: Environment<'tcx>, - answer_subst: CanonicalVarValues<'tcx>, - binder_index: ty::DebruijnIndex, - ex_clause: ChalkExClause<'tcx>, -} - -impl AnswerSubstitutor<'cx, 'tcx> { - fn unify_free_answer_var( - &mut self, - answer_var: ty::BoundVar, - pending: GenericArg<'tcx>, - ) -> RelateResult<'tcx, ()> { - let answer_param = &self.answer_subst.var_values[answer_var]; - let pending = - &ty::fold::shift_out_vars(self.infcx.tcx, &pending, self.binder_index.as_u32()); - - super::into_ex_clause( - unify(self.infcx, self.environment, ty::Variance::Invariant, answer_param, pending)?, - &mut self.ex_clause, - ); - - Ok(()) - } -} - -impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - - fn param_env(&self) -> ty::ParamEnv<'tcx> { - // FIXME(oli-obk): learn chalk and create param envs - ty::ParamEnv::empty() - } - - fn tag(&self) -> &'static str { - "chalk_context::answer_substitutor" - } - - fn a_is_expected(&self) -> bool { - true - } - - fn relate_with_variance<T: Relate<'tcx>>( - &mut self, - _variance: ty::Variance, - a: &T, - b: &T, - ) -> RelateResult<'tcx, T> { - // We don't care about variance. - self.relate(a, b) - } - - fn binders<T: Relate<'tcx>>( - &mut self, - a: &ty::Binder<T>, - b: &ty::Binder<T>, - ) -> RelateResult<'tcx, ty::Binder<T>> { - self.binder_index.shift_in(1); - let result = self.relate(a.skip_binder(), b.skip_binder())?; - self.binder_index.shift_out(1); - Ok(ty::Binder::bind(result)) - } - - fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - let b = self.infcx.shallow_resolve(b); - debug!("AnswerSubstitutor::tys(a = {:?}, b = {:?})", a, b); - - if let &ty::Bound(debruijn, bound_ty) = &a.kind { - // Free bound var - if debruijn == self.binder_index { - self.unify_free_answer_var(bound_ty.var, b.into())?; - return Ok(b); - } - } - - match (&a.kind, &b.kind) { - (&ty::Bound(a_debruijn, a_bound), &ty::Bound(b_debruijn, b_bound)) => { - assert_eq!(a_debruijn, b_debruijn); - assert_eq!(a_bound.var, b_bound.var); - Ok(a) - } - - // Those should have been canonicalized away. - (ty::Placeholder(..), _) => { - bug!("unexpected placeholder ty in `AnswerSubstitutor`: {:?} ", a); - } - - // Everything else should just be a perfect match as well, - // and we forbid inference variables. - _ => match ty::relate::super_relate_tys(self, a, b) { - Ok(ty) => Ok(ty), - Err(err) => bug!("type mismatch in `AnswerSubstitutor`: {}", err), - }, - } - } - - fn regions( - &mut self, - a: ty::Region<'tcx>, - b: ty::Region<'tcx>, - ) -> RelateResult<'tcx, ty::Region<'tcx>> { - let b = match b { - &ty::ReVar(vid) => self - .infcx - .inner - .borrow_mut() - .unwrap_region_constraints() - .opportunistic_resolve_var(self.infcx.tcx, vid), - - other => other, - }; - - if let &ty::ReLateBound(debruijn, bound) = a { - // Free bound region - if debruijn == self.binder_index { - self.unify_free_answer_var(bound.assert_bound_var(), b.into())?; - return Ok(b); - } - } - - match (a, b) { - (&ty::ReLateBound(a_debruijn, a_bound), &ty::ReLateBound(b_debruijn, b_bound)) => { - assert_eq!(a_debruijn, b_debruijn); - assert_eq!(a_bound.assert_bound_var(), b_bound.assert_bound_var()); - } - - (ty::ReStatic, ty::ReStatic) | (ty::ReErased, ty::ReErased) => (), - - (ty::ReEmpty(a_ui), ty::ReEmpty(b_ui)) => { - assert_eq!(a_ui, b_ui); - } - - (&ty::ReFree(a_free), &ty::ReFree(b_free)) => { - assert_eq!(a_free, b_free); - } - - _ => bug!("unexpected regions in `AnswerSubstitutor`: {:?}, {:?}", a, b), - } - - Ok(a) - } - - fn consts( - &mut self, - a: &'tcx ty::Const<'tcx>, - b: &'tcx ty::Const<'tcx>, - ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), .. } = a { - if *debruijn == self.binder_index { - self.unify_free_answer_var(*bound_ct, b.into())?; - return Ok(b); - } - } - - match (a, b) { - ( - ty::Const { val: ty::ConstKind::Bound(a_debruijn, a_bound), .. }, - ty::Const { val: ty::ConstKind::Bound(b_debruijn, b_bound), .. }, - ) => { - assert_eq!(a_debruijn, b_debruijn); - assert_eq!(a_bound, b_bound); - Ok(a) - } - - // Everything else should just be a perfect match as well, - // and we forbid inference variables. - _ => match ty::relate::super_relate_consts(self, a, b) { - Ok(ct) => Ok(ct), - Err(err) => bug!("const mismatch in `AnswerSubstitutor`: {}", err), - }, - } - } -} diff --git a/src/librustc_traits/chalk_context/unify.rs b/src/librustc_traits/chalk_context/unify.rs deleted file mode 100644 index 3274a301bb6..00000000000 --- a/src/librustc_traits/chalk_context/unify.rs +++ /dev/null @@ -1,85 +0,0 @@ -use rustc::ty; -use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; -use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; -use rustc_infer::infer::{InferCtxt, RegionVariableOrigin}; -use rustc_infer::traits::{DomainGoal, Environment, Goal, InEnvironment}; -use rustc_span::DUMMY_SP; - -crate struct UnificationResult<'tcx> { - crate goals: Vec<InEnvironment<'tcx, Goal<'tcx>>>, - crate constraints: Vec<super::RegionConstraint<'tcx>>, -} - -crate fn unify<'me, 'tcx, T: Relate<'tcx>>( - infcx: &'me InferCtxt<'me, 'tcx>, - environment: Environment<'tcx>, - variance: ty::Variance, - a: &T, - b: &T, -) -> RelateResult<'tcx, UnificationResult<'tcx>> { - debug!( - "unify( - a = {:?}, - b = {:?}, - environment = {:?}, - )", - a, b, environment - ); - - let mut delegate = ChalkTypeRelatingDelegate::new(infcx, environment); - - TypeRelating::new(infcx, &mut delegate, variance).relate(a, b)?; - - debug!("unify: goals = {:?}, constraints = {:?}", delegate.goals, delegate.constraints); - - Ok(UnificationResult { goals: delegate.goals, constraints: delegate.constraints }) -} - -struct ChalkTypeRelatingDelegate<'me, 'tcx> { - infcx: &'me InferCtxt<'me, 'tcx>, - environment: Environment<'tcx>, - goals: Vec<InEnvironment<'tcx, Goal<'tcx>>>, - constraints: Vec<super::RegionConstraint<'tcx>>, -} - -impl ChalkTypeRelatingDelegate<'me, 'tcx> { - fn new(infcx: &'me InferCtxt<'me, 'tcx>, environment: Environment<'tcx>) -> Self { - Self { infcx, environment, goals: Vec::new(), constraints: Vec::new() } - } -} - -impl TypeRelatingDelegate<'tcx> for &mut ChalkTypeRelatingDelegate<'_, 'tcx> { - fn create_next_universe(&mut self) -> ty::UniverseIndex { - self.infcx.create_next_universe() - } - - fn next_existential_region_var(&mut self, _was_placeholder: bool) -> ty::Region<'tcx> { - self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP)) - } - - fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> { - self.infcx.tcx.mk_region(ty::RePlaceholder(placeholder)) - } - - fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { - self.infcx - .next_region_var_in_universe(RegionVariableOrigin::MiscVariable(DUMMY_SP), universe) - } - - fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) { - self.constraints.push(ty::OutlivesPredicate(sup.into(), sub)); - } - - fn push_domain_goal(&mut self, domain_goal: DomainGoal<'tcx>) { - let goal = self.environment.with(self.infcx.tcx.mk_goal(domain_goal.into_goal())); - self.goals.push(goal); - } - - fn normalization() -> NormalizationStrategy { - NormalizationStrategy::Lazy - } - - fn forbid_inference_vars() -> bool { - false - } -} diff --git a/src/librustc_traits/generic_types.rs b/src/librustc_traits/generic_types.rs deleted file mode 100644 index 44a2c5464cd..00000000000 --- a/src/librustc_traits/generic_types.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Utilities for creating generic types with bound vars in place of parameter values. - -use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc_hir as hir; -use rustc_hir::def_id::DefId; -use rustc_target::spec::abi; - -crate fn bound(tcx: TyCtxt<'tcx>, index: u32) -> Ty<'tcx> { - let ty = ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(index).into()); - tcx.mk_ty(ty) -} - -crate fn raw_ptr(tcx: TyCtxt<'tcx>, mutbl: hir::Mutability) -> Ty<'tcx> { - tcx.mk_ptr(ty::TypeAndMut { ty: bound(tcx, 0), mutbl }) -} - -crate fn fn_ptr( - tcx: TyCtxt<'tcx>, - arity_and_output: usize, - c_variadic: bool, - unsafety: hir::Unsafety, - abi: abi::Abi, -) -> Ty<'tcx> { - let inputs_and_output = tcx.mk_type_list( - (0..arity_and_output) - .map(|i| ty::BoundVar::from(i)) - // DebruijnIndex(1) because we are going to inject these in a `PolyFnSig` - .map(|var| tcx.mk_ty(ty::Bound(ty::DebruijnIndex::from(1usize), var.into()))), - ); - - let fn_sig = ty::Binder::bind(ty::FnSig { inputs_and_output, c_variadic, unsafety, abi }); - tcx.mk_fn_ptr(fn_sig) -} - -crate fn type_list(tcx: TyCtxt<'tcx>, arity: usize) -> SubstsRef<'tcx> { - tcx.mk_substs( - (0..arity) - .map(|i| ty::BoundVar::from(i)) - .map(|var| tcx.mk_ty(ty::Bound(ty::INNERMOST, var.into()))) - .map(|ty| GenericArg::from(ty)), - ) -} - -crate fn ref_ty(tcx: TyCtxt<'tcx>, mutbl: hir::Mutability) -> Ty<'tcx> { - let region = tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))); - - tcx.mk_ref(region, ty::TypeAndMut { ty: bound(tcx, 1), mutbl }) -} - -crate fn fn_def(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { - tcx.mk_ty(ty::FnDef(def_id, InternalSubsts::bound_vars_for_item(tcx, def_id))) -} - -crate fn closure(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { - tcx.mk_closure(def_id, InternalSubsts::bound_vars_for_item(tcx, def_id)) -} - -crate fn generator(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { - tcx.mk_generator( - def_id, - InternalSubsts::bound_vars_for_item(tcx, def_id), - hir::Movability::Movable, - ) -} diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs index fefe82fdece..894e3ef3a8f 100644 --- a/src/librustc_traits/lib.rs +++ b/src/librustc_traits/lib.rs @@ -11,10 +11,8 @@ extern crate log; #[macro_use] extern crate rustc; -mod chalk_context; mod dropck_outlives; mod evaluate_obligation; -mod generic_types; mod implied_outlives_bounds; pub mod lowering; mod normalize_erasing_regions; @@ -28,7 +26,6 @@ pub fn provide(p: &mut Providers<'_>) { evaluate_obligation::provide(p); implied_outlives_bounds::provide(p); lowering::provide(p); - chalk_context::provide(p); normalize_projection_ty::provide(p); normalize_erasing_regions::provide(p); type_op::provide(p); diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index d466bbcca79..6bc29d0493e 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -252,11 +252,8 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // 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), - traits::Reveal::UserFacing, - tcx.sess.opts.debugging_opts.chalk.then_some(def_id), - ); + let unnormalized_env = + ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing, None); let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| { tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index bef14d3f4a3..199b476cb9a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1652,7 +1652,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } for (projection_bound, _) in &bounds.projection_bounds { - for (_, def_ids) in &mut associated_types { + for def_ids in associated_types.values_mut() { def_ids.remove(&projection_bound.projection_def_id()); } } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 0c5f3d3e99d..3a2a315a102 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -236,8 +236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // FIXME? Other potential candidate methods: `as_ref` and // `as_mut`? - .find(|a| a.check_name(sym::rustc_conversion_suggestion)) - .is_some() + .any(|a| a.check_name(sym::rustc_conversion_suggestion)) }); methods @@ -526,7 +525,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // we may want to suggest removing a `&`. if !sm.span_to_filename(expr.span).is_real() { if let Ok(code) = sm.span_to_snippet(sp) { - if code.chars().next() == Some('&') { + if code.starts_with('&') { return Some(( sp, "consider removing the borrow", diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index fcded27463e..778eee3586b 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -23,14 +23,11 @@ impl InherentOverlapChecker<'tcx> { let impl_items2 = self.tcx.associated_items(impl2); for item1 in impl_items1.in_definition_order() { - let collision = impl_items2 - .filter_by_name_unhygienic(item1.ident.name) - .find(|item2| { - // Symbols and namespace match, compare hygienically. - item1.kind.namespace() == item2.kind.namespace() - && item1.ident.modern() == item2.ident.modern() - }) - .is_some(); + let collision = impl_items2.filter_by_name_unhygienic(item1.ident.name).any(|item2| { + // Symbols and namespace match, compare hygienically. + item1.kind.namespace() == item2.kind.namespace() + && item1.ident.modern() == item2.ident.modern() + }); if collision { return true; diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 8965c6860c4..2da18e06d99 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -137,13 +137,15 @@ pub struct System; #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl AllocRef for System { #[inline] - unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> { - NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr) + unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> { + NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr).map(|p| (p, layout.size())) } #[inline] - unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> { - NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr) + unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> { + NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)) + .ok_or(AllocErr) + .map(|p| (p, layout.size())) } #[inline] @@ -157,8 +159,10 @@ unsafe impl AllocRef for System { ptr: NonNull<u8>, layout: Layout, new_size: usize, - ) -> Result<NonNull<u8>, AllocErr> { - NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr) + ) -> Result<(NonNull<u8>, usize), AllocErr> { + NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)) + .ok_or(AllocErr) + .map(|p| (p, new_size)) } } diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index a59d7f0263b..57cba6b1f7a 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -901,7 +901,7 @@ impl ToSocketAddrs for str { type Iter = vec::IntoIter<SocketAddr>; fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> { // try to parse as a regular SocketAddr first - if let Some(addr) = self.parse().ok() { + if let Ok(addr) = self.parse() { return Ok(vec![addr].into_iter()); } diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 79b0dc02978..b37675e0a0a 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -280,7 +280,7 @@ impl Socket { }; let mut timeout = libc::timeval { tv_sec: secs, - tv_usec: (dur.subsec_nanos() / 1000) as libc::suseconds_t, + tv_usec: dur.subsec_micros() as libc::suseconds_t, }; if timeout.tv_sec == 0 && timeout.tv_usec == 0 { timeout.tv_usec = 1; diff --git a/src/test/compile-fail/chalkify/chalk_initial_program.rs b/src/test/compile-fail/chalkify/chalk_initial_program.rs deleted file mode 100644 index df25bad622b..00000000000 --- a/src/test/compile-fail/chalkify/chalk_initial_program.rs +++ /dev/null @@ -1,16 +0,0 @@ -// compile-flags: -Z chalk - -trait Foo { } - -impl Foo for i32 { } - -impl Foo for u32 { } - -fn gimme<F: Foo>() { } - -// Note: this also tests that `std::process::Termination` is implemented for `()`. -fn main() { - gimme::<i32>(); - gimme::<u32>(); - gimme::<f32>(); //~ERROR the trait bound `f32: Foo` is not satisfied -} diff --git a/src/test/compile-fail/chalkify/generic_impls.rs b/src/test/compile-fail/chalkify/generic_impls.rs deleted file mode 100644 index d70c6f8055d..00000000000 --- a/src/test/compile-fail/chalkify/generic_impls.rs +++ /dev/null @@ -1,18 +0,0 @@ -// compile-flags: -Z chalk - -trait Foo { } - -impl<T> Foo for (T, u32) { } - -fn gimme<F: Foo>() { } - -fn foo<T>() { - gimme::<(T, u32)>(); - gimme::<(Option<T>, u32)>(); - gimme::<(Option<T>, f32)>(); //~ ERROR -} - -fn main() { - gimme::<(i32, u32)>(); - gimme::<(i32, f32)>(); //~ ERROR -} diff --git a/src/test/compile-fail/chalkify/impl_wf.rs b/src/test/compile-fail/chalkify/impl_wf.rs deleted file mode 100644 index 6bb4cf86e79..00000000000 --- a/src/test/compile-fail/chalkify/impl_wf.rs +++ /dev/null @@ -1,39 +0,0 @@ -// compile-flags: -Z chalk - -trait Foo: Sized { } - -trait Bar { - type Item: Foo; -} - -impl Foo for i32 { } - -impl Foo for str { } -//~^ ERROR the size for values of type `str` cannot be known at compilation time - -// Implicit `T: Sized` bound. -impl<T> Foo for Option<T> { } - -impl Bar for () { - type Item = i32; -} - -impl<T> Bar for Option<T> { - type Item = Option<T>; -} - -impl Bar for f32 { -//~^ ERROR the trait bound `f32: Foo` is not satisfied - type Item = f32; - //~^ ERROR the trait bound `f32: Foo` is not satisfied -} - -trait Baz<U: ?Sized> where U: Foo { } - -impl Baz<i32> for i32 { } - -impl Baz<f32> for f32 { } -//~^ ERROR the trait bound `f32: Foo` is not satisfied - -fn main() { -} diff --git a/src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs b/src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs deleted file mode 100644 index 861f86e6165..00000000000 --- a/src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs +++ /dev/null @@ -1,28 +0,0 @@ -// compile-flags: -Z chalk - -#![feature(trivial_bounds)] - -trait Bar { - fn foo(); -} -trait Foo: Bar { } - -struct S where S: Foo; - -impl Foo for S { -} - -fn bar<T: Bar>() { - T::foo(); -} - -fn foo<T: Foo>() { - bar::<T>() -} - -fn main() { - // For some reason, the error is duplicated... - - foo::<S>() //~ ERROR the type `S` is not well-formed (chalk) - //~^ ERROR the type `S` is not well-formed (chalk) -} diff --git a/src/test/compile-fail/chalkify/type_wf.rs b/src/test/compile-fail/chalkify/type_wf.rs deleted file mode 100644 index d1aa975ddc2..00000000000 --- a/src/test/compile-fail/chalkify/type_wf.rs +++ /dev/null @@ -1,24 +0,0 @@ -// compile-flags: -Z chalk - -trait Foo { } - -struct S<T: Foo> { - x: T, -} - -impl Foo for i32 { } -impl<T> Foo for Option<T> { } - -fn main() { - let s = S { - x: 5, - }; - - let s = S { //~ ERROR the trait bound `{float}: Foo` is not satisfied - x: 5.0, - }; - - let s = S { - x: Some(5.0), - }; -} diff --git a/src/test/run-make-fulldeps/issue-69368/Makefile b/src/test/run-make-fulldeps/issue-69368/Makefile new file mode 100644 index 00000000000..dbb044d8f5d --- /dev/null +++ b/src/test/run-make-fulldeps/issue-69368/Makefile @@ -0,0 +1,18 @@ +-include ../tools.mk + +# Test that previously triggered a linker failure with root cause +# similar to one found in the issue #69368. +# +# The crate that provides oom lang item is missing some other lang +# items. Necessary to prevent the use of start-group / end-group. +# +# The weak lang items are defined in a separate compilation units, +# so that linker could omit them if not used. +# +# The crates that need those weak lang items are dependencies of +# crates that provide them. + +all: + $(RUSTC) a.rs + $(RUSTC) b.rs + $(RUSTC) c.rs diff --git a/src/test/run-make-fulldeps/issue-69368/a.rs b/src/test/run-make-fulldeps/issue-69368/a.rs new file mode 100644 index 00000000000..726db874637 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-69368/a.rs @@ -0,0 +1,16 @@ +#![crate_type = "rlib"] +#![feature(lang_items)] +#![feature(panic_unwind)] +#![no_std] + +extern crate panic_unwind; + +#[panic_handler] +pub fn panic_handler(_: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[no_mangle] +extern "C" fn __rust_drop_panic() -> ! { + loop {} +} diff --git a/src/test/run-make-fulldeps/issue-69368/b.rs b/src/test/run-make-fulldeps/issue-69368/b.rs new file mode 100644 index 00000000000..4d6af026656 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-69368/b.rs @@ -0,0 +1,8 @@ +#![crate_type = "rlib"] +#![feature(alloc_error_handler)] +#![no_std] + +#[alloc_error_handler] +pub fn error_handler(_: core::alloc::Layout) -> ! { + panic!(); +} diff --git a/src/test/run-make-fulldeps/issue-69368/c.rs b/src/test/run-make-fulldeps/issue-69368/c.rs new file mode 100644 index 00000000000..729c4249a05 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-69368/c.rs @@ -0,0 +1,34 @@ +#![crate_type = "bin"] +#![feature(start)] +#![no_std] + +extern crate alloc; +extern crate a; +extern crate b; + +use alloc::vec::Vec; +use core::alloc::*; + +struct Allocator; + +unsafe impl GlobalAlloc for Allocator { + unsafe fn alloc(&self, _: Layout) -> *mut u8 { + loop {} + } + + unsafe fn dealloc(&self, _: *mut u8, _: Layout) { + loop {} + } +} + +#[global_allocator] +static ALLOCATOR: Allocator = Allocator; + +#[start] +fn main(argc: isize, _argv: *const *const u8) -> isize { + let mut v = Vec::new(); + for i in 0..argc { + v.push(i); + } + v.iter().sum() +} diff --git a/src/test/ui/allocator/custom.rs b/src/test/ui/allocator/custom.rs index 0b1f6d5a96e..c275db14b42 100644 --- a/src/test/ui/allocator/custom.rs +++ b/src/test/ui/allocator/custom.rs @@ -37,7 +37,7 @@ fn main() { unsafe { let layout = Layout::from_size_align(4, 2).unwrap(); - let ptr = Global.alloc(layout.clone()).unwrap(); + let (ptr, _) = Global.alloc(layout.clone()).unwrap(); helper::work_with(&ptr); assert_eq!(HITS.load(Ordering::SeqCst), n + 1); Global.dealloc(ptr, layout.clone()); @@ -49,7 +49,7 @@ fn main() { drop(s); assert_eq!(HITS.load(Ordering::SeqCst), n + 4); - let ptr = System.alloc(layout.clone()).unwrap(); + let (ptr, _) = System.alloc(layout.clone()).unwrap(); assert_eq!(HITS.load(Ordering::SeqCst), n + 4); helper::work_with(&ptr); System.dealloc(ptr, layout); diff --git a/src/test/ui/allocator/xcrate-use.rs b/src/test/ui/allocator/xcrate-use.rs index 37b28c195df..e4746d1a7ec 100644 --- a/src/test/ui/allocator/xcrate-use.rs +++ b/src/test/ui/allocator/xcrate-use.rs @@ -20,13 +20,13 @@ fn main() { let n = GLOBAL.0.load(Ordering::SeqCst); let layout = Layout::from_size_align(4, 2).unwrap(); - let ptr = Global.alloc(layout.clone()).unwrap(); + let (ptr, _) = Global.alloc(layout.clone()).unwrap(); helper::work_with(&ptr); assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1); Global.dealloc(ptr, layout.clone()); assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); - let ptr = System.alloc(layout.clone()).unwrap(); + let (ptr, _) = System.alloc(layout.clone()).unwrap(); assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); helper::work_with(&ptr); System.dealloc(ptr, layout); diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr index df1151d876c..82b2d32d09d 100644 --- a/src/test/ui/associated-type-bounds/duplicate.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.stderr @@ -728,3 +728,4 @@ LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; error: aborting due to 96 previous errors +For more information about this error, try `rustc --explain E0719`. diff --git a/src/test/ui/chalkify/builtin-copy-clone.rs b/src/test/ui/chalkify/builtin-copy-clone.rs deleted file mode 100644 index d403514b553..00000000000 --- a/src/test/ui/chalkify/builtin-copy-clone.rs +++ /dev/null @@ -1,44 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -// Test that `Clone` is correctly implemented for builtin types. - -#[derive(Copy, Clone)] -struct S(i32); - -fn test_clone<T: Clone>(arg: T) { - let _ = arg.clone(); -} - -fn test_copy<T: Copy>(arg: T) { - let _ = arg; - let _ = arg; -} - -fn test_copy_clone<T: Copy + Clone>(arg: T) { - test_copy(arg); - test_clone(arg); -} - -fn foo() { } - -fn main() { - test_copy_clone(foo); - let f: fn() = foo; - test_copy_clone(f); - // FIXME: add closures when they're considered WF - test_copy_clone([1; 56]); - test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); - test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, true, 'a', 1.1)); - test_copy_clone(()); - test_copy_clone(((1, 1), (1, 1, 1), (1.1, 1, 1, 'a'), ())); - - let a = ( - (S(1), S(0)), - ( - (S(0), S(0), S(1)), - S(0) - ) - ); - test_copy_clone(a); -} diff --git a/src/test/ui/chalkify/inherent_impl.rs b/src/test/ui/chalkify/inherent_impl.rs deleted file mode 100644 index 44e120c1eeb..00000000000 --- a/src/test/ui/chalkify/inherent_impl.rs +++ /dev/null @@ -1,42 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -trait Foo { } - -impl Foo for i32 { } - -struct S<T: Foo> { - x: T, -} - -fn only_foo<T: Foo>(_x: &T) { } - -impl<T> S<T> { - // Test that we have the correct environment inside an inherent method. - fn dummy_foo(&self) { - only_foo(&self.x) - } -} - -trait Bar { } -impl Bar for u32 { } - -fn only_bar<T: Bar>() { } - -impl<T> S<T> { - // Test that the environment of `dummy_bar` adds up with the environment - // of the inherent impl. - fn dummy_bar<U: Bar>(&self) { - only_foo(&self.x); - only_bar::<U>(); - } -} - -fn main() { - let s = S { - x: 5, - }; - - s.dummy_foo(); - s.dummy_bar::<u32>(); -} diff --git a/src/test/ui/chalkify/lower_env1.rs b/src/test/ui/chalkify/lower_env1.rs deleted file mode 100644 index afb6bddbf26..00000000000 --- a/src/test/ui/chalkify/lower_env1.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(rustc_attrs)] -#![allow(dead_code)] - -trait Foo { } - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -trait Bar where Self: Foo { } - -#[rustc_dump_env_program_clauses] //~ ERROR program clause dump -fn bar<T: Bar + ?Sized>() { -} - -fn main() { -} diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr deleted file mode 100644 index bc426e0707b..00000000000 --- a/src/test/ui/chalkify/lower_env1.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error: program clause dump - --> $DIR/lower_env1.rs:6:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<Self> { FromEnv(Self: Foo) :- FromEnv(Self: Bar). } - = note: forall<Self> { Implemented(Self: Bar) :- FromEnv(Self: Bar). } - = note: forall<Self> { WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). } - -error: program clause dump - --> $DIR/lower_env1.rs:9:1 - | -LL | #[rustc_dump_env_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<Self> { FromEnv(Self: Foo) :- FromEnv(Self: Bar). } - = note: forall<Self> { Implemented(Self: Bar) :- FromEnv(Self: Bar). } - = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). } - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/chalkify/lower_env2.rs b/src/test/ui/chalkify/lower_env2.rs deleted file mode 100644 index a067575a9cf..00000000000 --- a/src/test/ui/chalkify/lower_env2.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![feature(rustc_attrs)] -#![allow(dead_code)] - -trait Foo { } - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -struct S<'a, T: ?Sized> where T: Foo { - data: &'a T, -} - -#[rustc_dump_env_program_clauses] //~ ERROR program clause dump -fn bar<T: Foo>(_x: S<'_, T>) { // note that we have an implicit `T: Sized` bound -} - -fn main() { -} diff --git a/src/test/ui/chalkify/lower_env2.stderr b/src/test/ui/chalkify/lower_env2.stderr deleted file mode 100644 index 613a568a854..00000000000 --- a/src/test/ui/chalkify/lower_env2.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: program clause dump - --> $DIR/lower_env2.rs:6:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). } - = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). } - = note: forall<'a, T> { WellFormed(S<'a, T>) :- WellFormed(T: Foo), TypeOutlives(T: 'a). } - -error: program clause dump - --> $DIR/lower_env2.rs:11:1 - | -LL | #[rustc_dump_env_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). } - = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). } - = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). } - = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). } - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/chalkify/lower_env3.rs b/src/test/ui/chalkify/lower_env3.rs deleted file mode 100644 index 61ed3cbb277..00000000000 --- a/src/test/ui/chalkify/lower_env3.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![feature(rustc_attrs)] -#![allow(dead_code)] - -trait Foo { - #[rustc_dump_env_program_clauses] //~ ERROR program clause dump - fn foo(&self); -} - -impl<T> Foo for T where T: Clone { - #[rustc_dump_env_program_clauses] //~ ERROR program clause dump - fn foo(&self) { - } -} - -fn main() { -} diff --git a/src/test/ui/chalkify/lower_env3.stderr b/src/test/ui/chalkify/lower_env3.stderr deleted file mode 100644 index a1fc83bfea8..00000000000 --- a/src/test/ui/chalkify/lower_env3.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: program clause dump - --> $DIR/lower_env3.rs:5:5 - | -LL | #[rustc_dump_env_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). } - -error: program clause dump - --> $DIR/lower_env3.rs:10:5 - | -LL | #[rustc_dump_env_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<Self> { FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone). } - = note: forall<Self> { Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone). } - = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). } - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/chalkify/lower_impl.rs b/src/test/ui/chalkify/lower_impl.rs deleted file mode 100644 index 1bd44a9f498..00000000000 --- a/src/test/ui/chalkify/lower_impl.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![feature(rustc_attrs)] - -trait Foo { } - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -impl<T: 'static> Foo for T where T: Iterator<Item = i32> { } - -trait Bar { - type Assoc; -} - -impl<T> Bar for T where T: Iterator<Item = i32> { - #[rustc_dump_program_clauses] //~ ERROR program clause dump - type Assoc = Vec<T>; -} - -fn main() { - println!("hello"); -} diff --git a/src/test/ui/chalkify/lower_impl.stderr b/src/test/ui/chalkify/lower_impl.stderr deleted file mode 100644 index d6827fbff3d..00000000000 --- a/src/test/ui/chalkify/lower_impl.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: program clause dump - --> $DIR/lower_impl.rs:5:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<T> { Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T: 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). } - -error: program clause dump - --> $DIR/lower_impl.rs:13:5 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<T> { Normalize(<T as Bar>::Assoc -> std::vec::Vec<T>) :- Implemented(T: Bar). } - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/chalkify/lower_struct.rs b/src/test/ui/chalkify/lower_struct.rs deleted file mode 100644 index aecccea5c14..00000000000 --- a/src/test/ui/chalkify/lower_struct.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -struct Foo<'a, T> where Box<T>: Clone { - _x: std::marker::PhantomData<&'a T>, -} - -fn main() { } diff --git a/src/test/ui/chalkify/lower_struct.stderr b/src/test/ui/chalkify/lower_struct.stderr deleted file mode 100644 index 0331c2fca16..00000000000 --- a/src/test/ui/chalkify/lower_struct.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: program clause dump - --> $DIR/lower_struct.rs:3:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<'a, T> { FromEnv(T: std::marker::Sized) :- FromEnv(Foo<'a, T>). } - = note: forall<'a, T> { FromEnv(std::boxed::Box<T>: std::clone::Clone) :- FromEnv(Foo<'a, T>). } - = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(Foo<'a, T>). } - = note: forall<'a, T> { WellFormed(Foo<'a, T>) :- WellFormed(T: std::marker::Sized), WellFormed(std::boxed::Box<T>: std::clone::Clone), TypeOutlives(T: 'a). } - -error: aborting due to previous error - diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs deleted file mode 100644 index 0e1956022f9..00000000000 --- a/src/test/ui/chalkify/lower_trait.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(rustc_attrs)] - -trait Bar { } - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -trait Foo<S, T: ?Sized> { - #[rustc_dump_program_clauses] //~ ERROR program clause dump - type Assoc: Bar + ?Sized; -} - -fn main() { - println!("hello"); -} diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr deleted file mode 100644 index ed3bded398a..00000000000 --- a/src/test/ui/chalkify/lower_trait.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error: program clause dump - --> $DIR/lower_trait.rs:5:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<Self, S, T> { FromEnv(<Self as Foo<S, T>>::Assoc: Bar) :- FromEnv(Self: Foo<S, T>). } - = note: forall<Self, S, T> { FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T>). } - = note: forall<Self, S, T> { Implemented(Self: Foo<S, T>) :- FromEnv(Self: Foo<S, T>). } - = note: forall<Self, S, T> { WellFormed(Self: Foo<S, T>) :- Implemented(Self: Foo<S, T>), WellFormed(S: std::marker::Sized), WellFormed(<Self as Foo<S, T>>::Assoc: Bar). } - -error: program clause dump - --> $DIR/lower_trait.rs:7:5 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<Self, S, T, ^3> { ProjectionEq(<Self as Foo<S, T>>::Assoc == ^3) :- Normalize(<Self as Foo<S, T>>::Assoc -> ^3). } - = note: forall<Self, S, T> { FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)). } - = note: forall<Self, S, T> { ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)). } - = note: forall<Self, S, T> { WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- WellFormed(Self: Foo<S, T>). } - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.rs b/src/test/ui/chalkify/lower_trait_higher_rank.rs deleted file mode 100644 index 715f09632bd..00000000000 --- a/src/test/ui/chalkify/lower_trait_higher_rank.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -trait Foo<F: ?Sized> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8 -{ -} - -fn main() { - println!("hello"); -} diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.stderr b/src/test/ui/chalkify/lower_trait_higher_rank.stderr deleted file mode 100644 index 79bbc9fa6b3..00000000000 --- a/src/test/ui/chalkify/lower_trait_higher_rank.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: program clause dump - --> $DIR/lower_trait_higher_rank.rs:3:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<'a, Self, F> { FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>). } - = note: forall<'a, Self, F> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>). } - = note: forall<Self, F> { Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>). } - = note: forall<Self, F> { WellFormed(Self: Foo<F>) :- Implemented(Self: Foo<F>), forall<'a> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<'a> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) }. } - -error: aborting due to previous error - diff --git a/src/test/ui/chalkify/lower_trait_where_clause.rs b/src/test/ui/chalkify/lower_trait_where_clause.rs deleted file mode 100644 index 78fa39f1dc1..00000000000 --- a/src/test/ui/chalkify/lower_trait_where_clause.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(rustc_attrs)] - -use std::borrow::Borrow; - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -trait Foo<'a, 'b, T, U> -where - T: Borrow<U> + ?Sized, - U: ?Sized + 'b, - 'a: 'b, - Box<T>:, // NOTE(#53696) this checks an empty list of bounds. -{ -} - -fn main() { - println!("hello"); -} diff --git a/src/test/ui/chalkify/lower_trait_where_clause.stderr b/src/test/ui/chalkify/lower_trait_where_clause.stderr deleted file mode 100644 index 408f3712a70..00000000000 --- a/src/test/ui/chalkify/lower_trait_where_clause.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: program clause dump - --> $DIR/lower_trait_where_clause.rs:5:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<'a, 'b, Self, T, U> { FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). } - = note: forall<'a, 'b, Self, T, U> { Implemented(Self: Foo<'a, 'b, T, U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). } - = note: forall<'a, 'b, Self, T, U> { RegionOutlives('a: 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). } - = note: forall<'a, 'b, Self, T, U> { TypeOutlives(U: 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). } - = note: forall<'a, 'b, Self, T, U> { TypeOutlives(std::boxed::Box<T>: '<empty>) :- FromEnv(Self: Foo<'a, 'b, T, U>). } - = note: forall<'a, 'b, Self, T, U> { WellFormed(Self: Foo<'a, 'b, T, U>) :- Implemented(Self: Foo<'a, 'b, T, U>), WellFormed(T: std::borrow::Borrow<U>), TypeOutlives(U: 'b), RegionOutlives('a: 'b), TypeOutlives(std::boxed::Box<T>: '<empty>). } - -error: aborting due to previous error - diff --git a/src/test/ui/chalkify/projection.rs b/src/test/ui/chalkify/projection.rs deleted file mode 100644 index d6a8dd7a4a2..00000000000 --- a/src/test/ui/chalkify/projection.rs +++ /dev/null @@ -1,25 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -trait Foo { } - -trait Bar { - type Item: Foo; -} - -impl Foo for i32 { } -impl Bar for i32 { - type Item = i32; -} - -fn only_foo<T: Foo>() { } - -fn only_bar<T: Bar>() { - // `T` implements `Bar` hence `<T as Bar>::Item` must also implement `Bar` - only_foo::<T::Item>() -} - -fn main() { - only_bar::<i32>(); - only_foo::<<i32 as Bar>::Item>(); -} diff --git a/src/test/ui/chalkify/super_trait.rs b/src/test/ui/chalkify/super_trait.rs deleted file mode 100644 index eeff9fd9b80..00000000000 --- a/src/test/ui/chalkify/super_trait.rs +++ /dev/null @@ -1,19 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -trait Foo { } -trait Bar: Foo { } - -impl Foo for i32 { } -impl Bar for i32 { } - -fn only_foo<T: Foo>() { } - -fn only_bar<T: Bar>() { - // `T` implements `Bar` hence `T` must also implement `Foo` - only_foo::<T>() -} - -fn main() { - only_bar::<i32>() -} diff --git a/src/test/ui/chalkify/trait_implied_bound.rs b/src/test/ui/chalkify/trait_implied_bound.rs deleted file mode 100644 index 8a2e1cf5990..00000000000 --- a/src/test/ui/chalkify/trait_implied_bound.rs +++ /dev/null @@ -1,18 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -trait Foo { } -trait Bar<U> where U: Foo { } - -impl Foo for i32 { } -impl Bar<i32> for i32 { } - -fn only_foo<T: Foo>() { } - -fn only_bar<U, T: Bar<U>>() { - only_foo::<U>() -} - -fn main() { - only_bar::<i32, i32>() -} diff --git a/src/test/ui/chalkify/type_implied_bound.rs b/src/test/ui/chalkify/type_implied_bound.rs deleted file mode 100644 index 8673f5319bd..00000000000 --- a/src/test/ui/chalkify/type_implied_bound.rs +++ /dev/null @@ -1,29 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -trait Eq { } -trait Hash: Eq { } - -impl Eq for i32 { } -impl Hash for i32 { } - -struct Set<T: Hash> { - _x: T, -} - -fn only_eq<T: Eq>() { } - -fn take_a_set<T>(_: &Set<T>) { - // `Set<T>` is an input type of `take_a_set`, hence we know that - // `T` must implement `Hash`, and we know in turn that `T` must - // implement `Eq`. - only_eq::<T>() -} - -fn main() { - let set = Set { - _x: 5, - }; - - take_a_set(&set); -} diff --git a/src/test/ui/chalkify/type_inference.rs b/src/test/ui/chalkify/type_inference.rs deleted file mode 100644 index 62a53ec0317..00000000000 --- a/src/test/ui/chalkify/type_inference.rs +++ /dev/null @@ -1,26 +0,0 @@ -// compile-flags: -Z chalk - -trait Foo { } -impl Foo for i32 { } - -trait Bar { } -impl Bar for i32 { } -impl Bar for u32 { } - -fn only_foo<T: Foo>(_x: T) { } - -fn only_bar<T: Bar>(_x: T) { } - -fn main() { - let x = 5.0; - - // The only type which implements `Foo` is `i32`, so the chalk trait solver - // is expecting a variable of type `i32`. This behavior differs from the - // old-style trait solver. I guess this will change, that's why I'm - // adding that test. - only_foo(x); //~ ERROR mismatched types - - // Here we have two solutions so we get back the behavior of the old-style - // trait solver. - only_bar(x); //~ ERROR the trait bound `{float}: Bar` is not satisfied -} diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr deleted file mode 100644 index b8152caf3d2..00000000000 --- a/src/test/ui/chalkify/type_inference.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/type_inference.rs:21:14 - | -LL | only_foo(x); - | ^ expected `i32`, found floating-point number - -error[E0277]: the trait bound `{float}: Bar` is not satisfied - --> $DIR/type_inference.rs:25:5 - | -LL | fn only_bar<T: Bar>(_x: T) { } - | -------- --- required by this bound in `only_bar` -... -LL | only_bar(x); - | ^^^^^^^^ the trait `Bar` is not implemented for `{float}` - | - = help: the following implementations were found: - <i32 as Bar> - <u32 as Bar> - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-65675.rs b/src/test/ui/const-generics/issues/issue-65675.rs deleted file mode 100644 index 3ca527313f9..00000000000 --- a/src/test/ui/const-generics/issues/issue-65675.rs +++ /dev/null @@ -1,10 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -pub struct Foo<T, const N: usize>([T; N]); -impl<T, const N: usize> Foo<T, {N}> {} - -fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-65675.stderr b/src/test/ui/const-generics/issues/issue-65675.stderr deleted file mode 100644 index 60b388e6278..00000000000 --- a/src/test/ui/const-generics/issues/issue-65675.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/issue-65675.rs:4:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - diff --git a/src/test/ui/error-codes/E0719.stderr b/src/test/ui/error-codes/E0719.stderr index a046fbfc3d0..0e4bbf083ba 100644 --- a/src/test/ui/error-codes/E0719.stderr +++ b/src/test/ui/error-codes/E0719.stderr @@ -16,3 +16,4 @@ LL | fn test() -> Box<dyn Iterator<Item = (), Item = Unit>> { error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0719`. diff --git a/src/test/ui/realloc-16687.rs b/src/test/ui/realloc-16687.rs index 425aa83e70a..eb6224ad1bb 100644 --- a/src/test/ui/realloc-16687.rs +++ b/src/test/ui/realloc-16687.rs @@ -41,13 +41,13 @@ unsafe fn test_triangle() -> bool { println!("allocate({:?})", layout); } - let ret = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + let (ptr, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); if PRINT { - println!("allocate({:?}) = {:?}", layout, ret); + println!("allocate({:?}) = {:?}", layout, ptr); } - ret.cast().as_ptr() + ptr.cast().as_ptr() } unsafe fn deallocate(ptr: *mut u8, layout: Layout) { @@ -63,16 +63,16 @@ unsafe fn test_triangle() -> bool { println!("reallocate({:?}, old={:?}, new={:?})", ptr, old, new); } - let ret = Global.realloc(NonNull::new_unchecked(ptr), old, new.size()) + let (ptr, _) = Global.realloc(NonNull::new_unchecked(ptr), old, new.size()) .unwrap_or_else(|_| handle_alloc_error( Layout::from_size_align_unchecked(new.size(), old.align()) )); if PRINT { println!("reallocate({:?}, old={:?}, new={:?}) = {:?}", - ptr, old, new, ret); + ptr, old, new, ptr); } - ret.cast().as_ptr() + ptr.cast().as_ptr() } fn idx_to_size(i: usize) -> usize { (i+1) * 10 } diff --git a/src/test/ui/regions/regions-mock-codegen.rs b/src/test/ui/regions/regions-mock-codegen.rs index f50b1c8b17f..fe3a864fe4b 100644 --- a/src/test/ui/regions/regions-mock-codegen.rs +++ b/src/test/ui/regions/regions-mock-codegen.rs @@ -24,29 +24,29 @@ struct Ccx { x: isize } -fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> { +fn alloc(_bcx: &arena) -> &Bcx<'_> { unsafe { let layout = Layout::new::<Bcx>(); - let ptr = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + let (ptr, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); &*(ptr.as_ptr() as *const _) } } -fn h<'a>(bcx : &'a Bcx<'a>) -> &'a Bcx<'a> { +fn h<'a>(bcx: &'a Bcx<'a>) -> &'a Bcx<'a> { return alloc(bcx.fcx.arena); } -fn g(fcx : &Fcx) { - let bcx = Bcx { fcx: fcx }; +fn g(fcx: &Fcx) { + let bcx = Bcx { fcx }; let bcx2 = h(&bcx); unsafe { Global.dealloc(NonNull::new_unchecked(bcx2 as *const _ as *mut _), Layout::new::<Bcx>()); } } -fn f(ccx : &Ccx) { +fn f(ccx: &Ccx) { let a = arena(()); - let fcx = Fcx { arena: &a, ccx: ccx }; + let fcx = Fcx { arena: &a, ccx }; return g(&fcx); } |
