From: Manish Goregaokar Date: Mon, 20 Jul 2020 19:30:34 +0000 (-0700) Subject: Rollup merge of #74561 - RalfJung:backtrace, r=alexcrichton X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=df8d169c31b56a893b8a6d0caa3a5931b9b2f968;hp=4cbd265c119cb1a5eb92e98d2bb93466f05efa46;p=rust.git Rollup merge of #74561 - RalfJung:backtrace, r=alexcrichton update backtrace-rs Hopefully fixes https://github.com/rust-lang/rust/issues/74484 r? @alexcrichton --- diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md index 5e2e04c063b..93908e9190e 100644 --- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md +++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md @@ -26,6 +26,9 @@ of bugs: * Double-free, invalid free * Memory leaks +The memory leak detection is enabled by default on Linux, and can be enabled +with runtime flag `ASAN_OPTIONS=detect_leaks=1` on macOS. + AddressSanitizer is supported on the following targets: * `x86_64-apple-darwin` @@ -196,10 +199,6 @@ fn main() { ```shell $ export \ - CC=clang \ - CXX=clang++ \ - CFLAGS='-fsanitize=memory -fsanitize-memory-track-origins' \ - CXXFLAGS='-fsanitize=memory -fsanitize-memory-track-origins' \ RUSTFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins' \ RUSTDOCFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins' $ cargo clean diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index 15313e333ce..8398cfa3bd3 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -1,9 +1,9 @@ //! A priority queue implemented with a binary heap. //! -//! Insertion and popping the largest element have `O(log(n))` time complexity. -//! Checking the largest element is `O(1)`. Converting a vector to a binary heap -//! can be done in-place, and has `O(n)` complexity. A binary heap can also be -//! converted to a sorted vector in-place, allowing it to be used for an `O(n * log(n))` +//! Insertion and popping the largest element have *O*(log(*n*)) time complexity. +//! Checking the largest element is *O*(1). Converting a vector to a binary heap +//! can be done in-place, and has *O*(*n*) complexity. A binary heap can also be +//! converted to a sorted vector in-place, allowing it to be used for an *O*(*n* \* log(*n*)) //! in-place heapsort. //! //! # Examples @@ -235,7 +235,7 @@ /// /// | [push] | [pop] | [peek]/[peek\_mut] | /// |--------|-----------|--------------------| -/// | O(1)~ | O(log(n)) | O(1) | +/// | O(1)~ | *O*(log(*n*)) | *O*(1) | /// /// The value for `push` is an expected cost; the method documentation gives a /// more detailed analysis. @@ -398,7 +398,7 @@ pub fn with_capacity(capacity: usize) -> BinaryHeap { /// /// # Time complexity /// - /// Cost is `O(1)` in the worst case. + /// Cost is *O*(1) in the worst case. #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub fn peek_mut(&mut self) -> Option> { if self.is_empty() { None } else { Some(PeekMut { heap: self, sift: true }) } @@ -422,7 +422,7 @@ pub fn peek_mut(&mut self) -> Option> { /// /// # Time complexity /// - /// The worst case cost of `pop` on a heap containing *n* elements is `O(log(n))`. + /// The worst case cost of `pop` on a heap containing *n* elements is *O*(log(*n*)). #[stable(feature = "rust1", since = "1.0.0")] pub fn pop(&mut self) -> Option { self.data.pop().map(|mut item| { @@ -455,15 +455,15 @@ pub fn pop(&mut self) -> Option { /// /// The expected cost of `push`, averaged over every possible ordering of /// the elements being pushed, and over a sufficiently large number of - /// pushes, is `O(1)`. This is the most meaningful cost metric when pushing + /// pushes, is *O*(1). This is the most meaningful cost metric when pushing /// elements that are *not* already in any sorted pattern. /// /// The time complexity degrades if elements are pushed in predominantly /// ascending order. In the worst case, elements are pushed in ascending - /// sorted order and the amortized cost per push is `O(log(n))` against a heap + /// sorted order and the amortized cost per push is *O*(log(*n*)) against a heap /// containing *n* elements. /// - /// The worst case cost of a *single* call to `push` is `O(n)`. The worst case + /// The worst case cost of a *single* call to `push` is *O*(*n*). The worst case /// occurs when capacity is exhausted and needs a resize. The resize cost /// has been amortized in the previous figures. #[stable(feature = "rust1", since = "1.0.0")] @@ -643,7 +643,7 @@ fn better_to_rebuild(len1: usize, len2: usize) -> bool { /// The remaining elements will be removed on drop in heap order. /// /// Note: - /// * `.drain_sorted()` is `O(n * log(n))`; much slower than `.drain()`. + /// * `.drain_sorted()` is *O*(*n* \* log(*n*)); much slower than `.drain()`. /// You should use the latter for most cases. /// /// # Examples @@ -756,7 +756,7 @@ pub fn into_iter_sorted(self) -> IntoIterSorted { /// /// # Time complexity /// - /// Cost is `O(1)` in the worst case. + /// Cost is *O*(1) in the worst case. #[stable(feature = "rust1", since = "1.0.0")] pub fn peek(&self) -> Option<&T> { self.data.get(0) @@ -1312,7 +1312,7 @@ unsafe impl TrustedLen for DrainSorted<'_, T> {} impl From> for BinaryHeap { /// Converts a `Vec` into a `BinaryHeap`. /// - /// This conversion happens in-place, and has `O(n)` time complexity. + /// This conversion happens in-place, and has *O*(*n*) time complexity. fn from(vec: Vec) -> BinaryHeap { let mut heap = BinaryHeap { data: vec }; heap.rebuild(); diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index 36b5785fdf6..1f875f6c521 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -404,7 +404,7 @@ pub const fn new() -> Self { /// This reuses all the nodes from `other` and moves them into `self`. After /// this operation, `other` becomes empty. /// - /// This operation should compute in `O(1)` time and `O(1)` memory. + /// This operation should compute in *O*(1) time and *O*(1) memory. /// /// # Examples /// @@ -561,7 +561,7 @@ pub fn cursor_back_mut(&mut self) -> CursorMut<'_, T> { /// Returns `true` if the `LinkedList` is empty. /// - /// This operation should compute in `O(1)` time. + /// This operation should compute in *O*(1) time. /// /// # Examples /// @@ -582,7 +582,7 @@ pub fn is_empty(&self) -> bool { /// Returns the length of the `LinkedList`. /// - /// This operation should compute in `O(1)` time. + /// This operation should compute in *O*(1) time. /// /// # Examples /// @@ -608,7 +608,7 @@ pub fn len(&self) -> usize { /// Removes all elements from the `LinkedList`. /// - /// This operation should compute in `O(n)` time. + /// This operation should compute in *O*(*n*) time. /// /// # Examples /// @@ -751,7 +751,7 @@ pub fn back_mut(&mut self) -> Option<&mut T> { /// Adds an element first in the list. /// - /// This operation should compute in `O(1)` time. + /// This operation should compute in *O*(1) time. /// /// # Examples /// @@ -774,7 +774,7 @@ pub fn push_front(&mut self, elt: T) { /// Removes the first element and returns it, or `None` if the list is /// empty. /// - /// This operation should compute in `O(1)` time. + /// This operation should compute in *O*(1) time. /// /// # Examples /// @@ -797,7 +797,7 @@ pub fn pop_front(&mut self) -> Option { /// Appends an element to the back of a list. /// - /// This operation should compute in `O(1)` time. + /// This operation should compute in *O*(1) time. /// /// # Examples /// @@ -817,7 +817,7 @@ pub fn push_back(&mut self, elt: T) { /// Removes the last element from a list and returns it, or `None` if /// it is empty. /// - /// This operation should compute in `O(1)` time. + /// This operation should compute in *O*(1) time. /// /// # Examples /// @@ -838,7 +838,7 @@ pub fn pop_back(&mut self) -> Option { /// Splits the list into two at the given index. Returns everything after the given index, /// including the index. /// - /// This operation should compute in `O(n)` time. + /// This operation should compute in *O*(*n*) time. /// /// # Panics /// @@ -894,7 +894,7 @@ pub fn split_off(&mut self, at: usize) -> LinkedList { /// Removes the element at the given index and returns it. /// - /// This operation should compute in `O(n)` time. + /// This operation should compute in *O*(*n*) time. /// /// # Panics /// Panics if at >= len diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 2efb94e8afe..fa65d6ce8d7 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1,7 +1,7 @@ //! A double-ended queue implemented with a growable ring buffer. //! -//! This queue has `O(1)` amortized inserts and removals from both ends of the -//! container. It also has `O(1)` indexing like a vector. The contained elements +//! This queue has *O*(1) amortized inserts and removals from both ends of the +//! container. It also has *O*(1) indexing like a vector. The contained elements //! are not required to be copyable, and the queue will be sendable if the //! contained type is sendable. @@ -1512,7 +1512,7 @@ fn is_contiguous(&self) -> bool { /// Removes an element from anywhere in the `VecDeque` and returns it, /// replacing it with the first element. /// - /// This does not preserve ordering, but is `O(1)`. + /// This does not preserve ordering, but is *O*(1). /// /// Returns `None` if `index` is out of bounds. /// @@ -1547,7 +1547,7 @@ pub fn swap_remove_front(&mut self, index: usize) -> Option { /// Removes an element from anywhere in the `VecDeque` and returns it, replacing it with the /// last element. /// - /// This does not preserve ordering, but is `O(1)`. + /// This does not preserve ordering, but is *O*(1). /// /// Returns `None` if `index` is out of bounds. /// @@ -2331,7 +2331,7 @@ pub fn make_contiguous(&mut self) -> &mut [T] { /// /// # Complexity /// - /// Takes `O(min(mid, len() - mid))` time and no extra space. + /// Takes `*O*(min(mid, len() - mid))` time and no extra space. /// /// # Examples /// @@ -2374,7 +2374,7 @@ pub fn rotate_left(&mut self, mid: usize) { /// /// # Complexity /// - /// Takes `O(min(k, len() - k))` time and no extra space. + /// Takes `*O*(min(k, len() - k))` time and no extra space. /// /// # Examples /// @@ -3076,7 +3076,7 @@ impl From> for Vec { /// [`Vec`]: crate::vec::Vec /// [`VecDeque`]: crate::collections::VecDeque /// - /// This never needs to re-allocate, but does need to do `O(n)` data movement if + /// This never needs to re-allocate, but does need to do *O*(*n*) data movement if /// the circular buffer doesn't happen to be at the beginning of the allocation. /// /// # Examples @@ -3084,7 +3084,7 @@ impl From> for Vec { /// ``` /// use std::collections::VecDeque; /// - /// // This one is O(1). + /// // This one is *O*(1). /// let deque: VecDeque<_> = (1..5).collect(); /// let ptr = deque.as_slices().0.as_ptr(); /// let vec = Vec::from(deque); diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 1c3879c40c2..15f10df9a45 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1162,7 +1162,7 @@ pub fn pop(&mut self) -> Option { /// Removes a [`char`] from this `String` at a byte position and returns it. /// - /// This is an `O(n)` operation, as it requires copying every element in the + /// This is an *O*(*n*) operation, as it requires copying every element in the /// buffer. /// /// # Panics @@ -1262,7 +1262,7 @@ pub fn retain(&mut self, mut f: F) /// Inserts a character into this `String` at a byte position. /// - /// This is an `O(n)` operation as it requires copying every element in the + /// This is an *O*(*n*) operation as it requires copying every element in the /// buffer. /// /// # Panics @@ -1309,7 +1309,7 @@ unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) { /// Inserts a string slice into this `String` at a byte position. /// - /// This is an `O(n)` operation as it requires copying every element in the + /// This is an *O*(*n*) operation as it requires copying every element in the /// buffer. /// /// # Panics @@ -1971,7 +1971,7 @@ fn hash(&self, hasher: &mut H) { /// /// This consumes the `String` on the left-hand side and re-uses its buffer (growing it if /// necessary). This is done to avoid allocating a new `String` and copying the entire contents on -/// every operation, which would lead to `O(n^2)` running time when building an `n`-byte string by +/// every operation, which would lead to *O*(*n*^2) running time when building an *n*-byte string by /// repeated concatenation. /// /// The string on the right-hand side is only borrowed; its contents are copied into the returned diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 061d1ea6b1c..9fb7296ce31 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -242,7 +242,7 @@ pub mod consts { /// The full circle constant (τ) /// /// Equal to 2π. - #[unstable(feature = "tau_constant", issue = "66770")] + #[stable(feature = "tau_constant", since = "1.47.0")] pub const TAU: f32 = 6.28318530717958647692528676655900577_f32; /// π/2 diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index b0df4d64f6e..bcb6cd40846 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -242,7 +242,7 @@ pub mod consts { /// The full circle constant (τ) /// /// Equal to 2π. - #[unstable(feature = "tau_constant", issue = "66770")] + #[stable(feature = "tau_constant", since = "1.47.0")] pub const TAU: f64 = 6.28318530717958647692528676655900577_f64; /// π/2 diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index d86f39c4550..179038d1977 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -39,7 +39,7 @@ /// [`Iterator`]: ../iter/trait.IntoIterator.html /// [slicing index]: ../slice/trait.SliceIndex.html #[doc(alias = "..")] -#[derive(Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFull; @@ -71,7 +71,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { /// assert_eq!(arr[1..=3], [ 1,2,3 ]); /// ``` #[doc(alias = "..")] -#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 +#[derive(Clone, Default, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct Range { /// The lower bound of the range (inclusive). diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 20b2c3d3c96..210ac078b4f 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1672,7 +1672,7 @@ pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result(&mut self, mut compare: F) /// elements. /// /// This sort is unstable (i.e., may reorder equal elements), in-place - /// (i.e., does not allocate), and `O(m * n * log(n))` worst-case, where the key function is - /// `O(m)`. + /// (i.e., does not allocate), and *O*(m \* *n* \* log(*n*)) worst-case, where the key function is + /// *O*(*m*). /// /// # Current implementation /// @@ -1803,7 +1803,7 @@ pub fn sort_unstable_by_key(&mut self, mut f: F) /// This reordering has the additional property that any value at position `i < index` will be /// less than or equal to any value at a position `j > index`. Additionally, this reordering is /// unstable (i.e. any number of equal elements may end up at position `index`), in-place - /// (i.e. does not allocate), and `O(n)` worst-case. This function is also/ known as "kth + /// (i.e. does not allocate), and *O*(*n*) worst-case. This function is also/ known as "kth /// element" in other libraries. It returns a triplet of the following values: all elements less /// than the one at the given index, the value at the given index, and all elements greater than /// the one at the given index. @@ -1852,7 +1852,7 @@ pub fn partition_at_index(&mut self, index: usize) -> (&mut [T], &mut T, &mut [T /// This reordering has the additional property that any value at position `i < index` will be /// less than or equal to any value at a position `j > index` using the comparator function. /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at - /// position `index`), in-place (i.e. does not allocate), and `O(n)` worst-case. This function + /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function /// is also known as "kth element" in other libraries. It returns a triplet of the following /// values: all elements less than the one at the given index, the value at the given index, /// and all elements greater than the one at the given index, using the provided comparator @@ -1906,7 +1906,7 @@ pub fn partition_at_index_by( /// This reordering has the additional property that any value at position `i < index` will be /// less than or equal to any value at a position `j > index` using the key extraction function. /// Additionally, this reordering is unstable (i.e. any number of equal elements may end up at - /// position `index`), in-place (i.e. does not allocate), and `O(n)` worst-case. This function + /// position `index`), in-place (i.e. does not allocate), and *O*(*n*) worst-case. This function /// is also known as "kth element" in other libraries. It returns a triplet of the following /// values: all elements less than the one at the given index, the value at the given index, and /// all elements greater than the one at the given index, using the provided key extraction diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index 8b2ac294764..972a33d6489 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -121,7 +121,7 @@ fn shift_tail(v: &mut [T], is_less: &mut F) /// Partially sorts a slice by shifting several out-of-order elements around. /// -/// Returns `true` if the slice is sorted at the end. This function is `O(n)` worst-case. +/// Returns `true` if the slice is sorted at the end. This function is *O*(*n*) worst-case. #[cold] fn partial_insertion_sort(v: &mut [T], is_less: &mut F) -> bool where @@ -168,7 +168,7 @@ fn partial_insertion_sort(v: &mut [T], is_less: &mut F) -> bool false } -/// Sorts a slice using insertion sort, which is `O(n^2)` worst-case. +/// Sorts a slice using insertion sort, which is *O*(*n*^2) worst-case. fn insertion_sort(v: &mut [T], is_less: &mut F) where F: FnMut(&T, &T) -> bool, @@ -178,7 +178,7 @@ fn insertion_sort(v: &mut [T], is_less: &mut F) } } -/// Sorts `v` using heapsort, which guarantees `O(n * log(n))` worst-case. +/// Sorts `v` using heapsort, which guarantees *O*(*n* \* log(*n*)) worst-case. #[cold] pub fn heapsort(v: &mut [T], is_less: &mut F) where @@ -751,7 +751,7 @@ fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T } } -/// Sorts `v` using pattern-defeating quicksort, which is `O(n * log(n))` worst-case. +/// Sorts `v` using pattern-defeating quicksort, which is *O*(*n* \* log(*n*)) worst-case. pub fn quicksort(v: &mut [T], mut is_less: F) where F: FnMut(&T, &T) -> bool, diff --git a/src/librustc_data_structures/sorted_map/index_map.rs b/src/librustc_data_structures/sorted_map/index_map.rs index b7005ccdc99..2bb421a47ef 100644 --- a/src/librustc_data_structures/sorted_map/index_map.rs +++ b/src/librustc_data_structures/sorted_map/index_map.rs @@ -7,8 +7,8 @@ use crate::stable_hasher::{HashStable, StableHasher}; use rustc_index::vec::{Idx, IndexVec}; -/// An indexed multi-map that preserves insertion order while permitting both `O(log n)` lookup of -/// an item by key and `O(1)` lookup by index. +/// An indexed multi-map that preserves insertion order while permitting both *O*(log *n*) lookup of +/// an item by key and *O*(1) lookup by index. /// /// This data structure is a hybrid of an [`IndexVec`] and a [`SortedMap`]. Like `IndexVec`, /// `SortedIndexMultiMap` assigns a typed index to each item while preserving insertion order. @@ -20,7 +20,7 @@ /// items will be yielded in insertion order. /// /// Unlike a general-purpose map like `BTreeSet` or `HashSet`, `SortedMap` and -/// `SortedIndexMultiMap` require `O(n)` time to insert a single item. This is because we may need +/// `SortedIndexMultiMap` require *O*(*n*) time to insert a single item. This is because we may need /// to insert into the middle of the sorted array. Users should avoid mutating this data structure /// in-place. /// diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index bbbd8359f01..279c65ce03d 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -453,6 +453,7 @@ E0768: include_str!("./error_codes/E0768.md"), E0769: include_str!("./error_codes/E0769.md"), E0770: include_str!("./error_codes/E0770.md"), +E0771: include_str!("./error_codes/E0771.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard diff --git a/src/librustc_error_codes/error_codes/E0771.md b/src/librustc_error_codes/error_codes/E0771.md new file mode 100644 index 00000000000..824a955f6b3 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0771.md @@ -0,0 +1,23 @@ +A non-`'static` lifetime was used in a const generic. This is currently not +allowed. + +Erroneous code example: + +```compile_fail,E0771 +#![feature(const_generics)] + +fn function_with_str<'a, const STRING: &'a str>() {} // error! +``` + +To fix this issue, the lifetime in the const generic need to be changed to +`'static`: + +``` +#![feature(const_generics)] + +fn function_with_str() {} // ok! +``` + +For more information, see [GitHub issue #74052]. + +[GitHub issue #74052]: https://github.com/rust-lang/rust/issues/74052 diff --git a/src/librustc_index/bit_set.rs b/src/librustc_index/bit_set.rs index 3e1d4b68c6f..dd2fbaf6a94 100644 --- a/src/librustc_index/bit_set.rs +++ b/src/librustc_index/bit_set.rs @@ -772,7 +772,7 @@ pub fn contains(&self, row: R, column: C) -> bool { } /// Returns those indices that are true in rows `a` and `b`. This - /// is an O(n) operation where `n` is the number of elements + /// is an *O*(*n*) operation where *n* is the number of elements /// (somewhat independent from the actual size of the /// intersection, in particular). pub fn intersect_rows(&self, row1: R, row2: R) -> Vec { diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index 4dd8723bd72..f479a030d63 100644 --- a/src/librustc_middle/query/mod.rs +++ b/src/librustc_middle/query/mod.rs @@ -103,9 +103,13 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String { /// // ^ While calling `opt_const_param_of` for other bodies returns `None`. /// } /// ``` + // It looks like caching this query on disk actually slightly + // worsened performance in #74376. + // + // Once const generics are more prevalently used, we might want to + // consider only caching calls returning `Some`. query opt_const_param_of(key: LocalDefId) -> Option { desc { |tcx| "computing the optional const parameter of `{}`", tcx.def_path_str(key.to_def_id()) } - // FIXME(#74113): consider storing this query on disk. } /// Records the type of every item. diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index ed88e549692..261c2031364 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1500,11 +1500,17 @@ fn resolve_pattern_inner( pat_src: PatternSource, bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet); 1]>, ) { + let is_tuple_struct_pat = matches!(pat.kind, PatKind::TupleStruct(_, _)); + // Visit all direct subpatterns of this pattern. pat.walk(&mut |pat| { debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind); match pat.kind { - PatKind::Ident(bmode, ident, ref sub) => { + // In tuple struct patterns ignore the invalid `ident @ ...`. + // It will be handled as an error by the AST lowering. + PatKind::Ident(bmode, ident, ref sub) + if !(is_tuple_struct_pat && sub.as_ref().filter(|p| p.is_rest()).is_some()) => + { // First try to resolve the identifier as some existing entity, // then fall back to a fresh binding. let has_sub = sub.is_some(); diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 9323c15a941..c86b4141847 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -1141,6 +1141,24 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { err.emit(); } + // FIXME(const_generics): This patches over a ICE caused by non-'static lifetimes in const + // generics. We are disallowing this until we can decide on how we want to handle non-'static + // lifetimes in const generics. See issue #74052 for discussion. + crate fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &hir::Lifetime) { + let mut err = struct_span_err!( + self.tcx.sess, + lifetime_ref.span, + E0771, + "use of non-static lifetime `{}` in const generic", + lifetime_ref + ); + err.note( + "for more information, see issue #74052 \ + ", + ); + err.emit(); + } + crate fn is_trait_ref_fn_scope(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) -> bool { if let def::Res::Def(_, did) = trait_ref.trait_ref.path.res { if [ diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 567db8edec9..6009e48a54f 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -173,6 +173,8 @@ struct NamedRegionMap { /// Used to disallow the use of in-band lifetimes in `fn` or `Fn` syntax. is_in_fn_syntax: bool, + is_in_const_generic: bool, + /// List of labels in the function/method currently under analysis. labels_in_fn: Vec, @@ -333,6 +335,7 @@ fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap { scope: ROOT_SCOPE, trait_ref_hack: false, is_in_fn_syntax: false, + is_in_const_generic: false, labels_in_fn: vec![], xcrate_object_lifetime_defaults: Default::default(), lifetime_uses: &mut Default::default(), @@ -828,6 +831,10 @@ fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { self.insert_lifetime(lifetime_ref, Region::Static); return; } + if self.is_in_const_generic && lifetime_ref.name != LifetimeName::Error { + self.emit_non_static_lt_in_const_generic_error(lifetime_ref); + return; + } self.resolve_lifetime_ref(lifetime_ref); } @@ -860,8 +867,11 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) { } } GenericParamKind::Const { ref ty, .. } => { + let was_in_const_generic = self.is_in_const_generic; + self.is_in_const_generic = true; walk_list!(self, visit_param_bound, param.bounds); self.visit_ty(&ty); + self.is_in_const_generic = was_in_const_generic; } } } @@ -1317,6 +1327,7 @@ fn with(&mut self, wrap_scope: Scope<'_>, f: F) scope: &wrap_scope, trait_ref_hack: self.trait_ref_hack, is_in_fn_syntax: self.is_in_fn_syntax, + is_in_const_generic: self.is_in_const_generic, labels_in_fn, xcrate_object_lifetime_defaults, lifetime_uses, diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 845a4fcafc2..dabae6cbc41 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -15,7 +15,7 @@ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; use rustc_session::parse::feature_err; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; use rustc_trait_selection::opaque_types::may_define_opaque_type; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -142,8 +142,8 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { _ => unreachable!(), } } - hir::ItemKind::Fn(..) => { - check_item_fn(tcx, item); + hir::ItemKind::Fn(ref sig, ..) => { + check_item_fn(tcx, item.hir_id, item.ident, item.span, sig.decl); } hir::ItemKind::Static(ref ty, ..) => { check_item_type(tcx, item.hir_id, ty.span, false); @@ -153,8 +153,14 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) { } hir::ItemKind::ForeignMod(ref module) => { for it in module.items.iter() { - if let hir::ForeignItemKind::Static(ref ty, ..) = it.kind { - check_item_type(tcx, it.hir_id, ty.span, true); + match it.kind { + hir::ForeignItemKind::Fn(ref decl, ..) => { + check_item_fn(tcx, it.hir_id, it.ident, it.span, decl) + } + hir::ForeignItemKind::Static(ref ty, ..) => { + check_item_type(tcx, it.hir_id, ty.span, true) + } + hir::ForeignItemKind::Type => (), } } } @@ -303,7 +309,7 @@ fn check_associated_item( fcx, item.ident.span, sig, - hir_sig, + hir_sig.decl, item.def_id, &mut implied_bounds, ); @@ -564,22 +570,24 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { } } -fn check_item_fn(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { - for_item(tcx, item).with_fcx(|fcx, tcx| { - let def_id = fcx.tcx.hir().local_def_id(item.hir_id); +fn check_item_fn( + tcx: TyCtxt<'_>, + item_id: hir::HirId, + ident: Ident, + span: Span, + decl: &hir::FnDecl<'_>, +) { + for_id(tcx, item_id, span).with_fcx(|fcx, tcx| { + let def_id = fcx.tcx.hir().local_def_id(item_id); let sig = fcx.tcx.fn_sig(def_id); - let sig = fcx.normalize_associated_types_in(item.span, &sig); + let sig = fcx.normalize_associated_types_in(span, &sig); let mut implied_bounds = vec![]; - let hir_sig = match &item.kind { - ItemKind::Fn(sig, ..) => sig, - _ => bug!("expected `ItemKind::Fn`, found `{:?}`", item.kind), - }; check_fn_or_method( tcx, fcx, - item.ident.span, + ident.span, sig, - hir_sig, + decl, def_id.to_def_id(), &mut implied_bounds, ); @@ -835,28 +843,28 @@ fn check_fn_or_method<'fcx, 'tcx>( fcx: &FnCtxt<'fcx, 'tcx>, span: Span, sig: ty::PolyFnSig<'tcx>, - hir_sig: &hir::FnSig<'_>, + hir_decl: &hir::FnDecl<'_>, def_id: DefId, implied_bounds: &mut Vec>, ) { let sig = fcx.normalize_associated_types_in(span, &sig); let sig = fcx.tcx.liberate_late_bound_regions(def_id, &sig); - for (&input_ty, span) in sig.inputs().iter().zip(hir_sig.decl.inputs.iter().map(|t| t.span)) { + for (&input_ty, span) in sig.inputs().iter().zip(hir_decl.inputs.iter().map(|t| t.span)) { fcx.register_wf_obligation(input_ty.into(), span, ObligationCauseCode::MiscObligation); } implied_bounds.extend(sig.inputs()); fcx.register_wf_obligation( sig.output().into(), - hir_sig.decl.output.span(), + hir_decl.output.span(), ObligationCauseCode::ReturnType, ); // FIXME(#25759) return types should not be implied bounds implied_bounds.push(sig.output()); - check_where_clauses(tcx, fcx, span, def_id, Some((sig.output(), hir_sig.decl.output.span()))); + check_where_clauses(tcx, fcx, span, def_id, Some((sig.output(), hir_decl.output.span()))); } /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index ec534aa925d..c3b54f14614 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1927,7 +1927,7 @@ fn extend, Span)>>(&mut self, iter: let re_root_empty = tcx.lifetimes.re_root_empty; let predicate = ty::OutlivesPredicate(ty, re_root_empty); predicates.push(( - ty::PredicateKind::TypeOutlives(ty::Binder::dummy(predicate)) + ty::PredicateKind::TypeOutlives(ty::Binder::bind(predicate)) .to_predicate(tcx), span, )); diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 38709b445ef..850a4b3cbc2 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1511,6 +1511,11 @@ h4 > .important-traits { #main > .line-numbers { margin-top: 0; } + + .important-traits .important-traits-tooltiptext { + left: 0; + top: 100%; + } } @media print { diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index e0ab7170ea8..96ba5c46a3c 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -237,16 +237,6 @@ a { #crate-search+.search-input:focus { box-shadow: 0 0 0 1px #148099,0 0 0 2px transparent; - color: #ffffff; - background-color: #141920; - box-shadow: none; - transition: box-shadow 150ms ease-in-out; - border-radius: 4px; - margin-left: 8px; -} - -#crate-search+.search-input:focus { - box-shadow: 0px 6px 20px 0px black; } .search-focus:disabled { @@ -318,12 +308,12 @@ a.test-arrow { font-size: 100%; color: #788797; border-radius: 4px; - background-color: rgba(255, 255, 255, 0); + background-color: rgba(57, 175, 215, 0.09); } a.test-arrow:hover { - background-color: rgba(242, 151, 24, 0.05); - color: #ffb44c; + background-color: rgba(57, 175, 215, 0.368); + color: #c5c5c5; } .toggle-label { diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index cc6663bebd3..b6488ae61b1 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -86,7 +86,7 @@ //! cost are suffixed with a `~`. //! //! All amortized costs are for the potential need to resize when capacity is -//! exhausted. If a resize occurs it will take O(n) time. Our collections never +//! exhausted. If a resize occurs it will take *O*(*n*) time. Our collections never //! automatically shrink, so removal operations aren't amortized. Over a //! sufficiently large series of operations, the average cost per operation will //! deterministically equal the given cost. diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 11b8f953be4..02de3fff29f 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -224,10 +224,7 @@ all(target_vendor = "fortanix", target_env = "sgx"), feature(slice_index_methods, coerce_unsized, sgx_platform, ptr_wrapping_offset_from) )] -#![cfg_attr( - all(test, target_vendor = "fortanix", target_env = "sgx"), - feature(fixed_size_array, maybe_uninit_extra) -)] +#![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array))] // std is implemented with unstable features, many of which are internal // compiler details that will never be stable // NB: the following list is sorted to minimize merge conflicts. diff --git a/src/test/ui/const-generics/const-argument-non-static-lifetime.rs b/src/test/ui/const-generics/const-argument-non-static-lifetime.rs new file mode 100644 index 00000000000..bc09ba2ab55 --- /dev/null +++ b/src/test/ui/const-generics/const-argument-non-static-lifetime.rs @@ -0,0 +1,17 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete +#![allow(dead_code)] + +fn test() {} + +fn wow<'a>() -> &'a () { + test::<{ + let _: &'a (); + 3 + }>(); + &() +} + +fn main() {} diff --git a/src/test/ui/const-generics/const-argument-non-static-lifetime.stderr b/src/test/ui/const-generics/const-argument-non-static-lifetime.stderr new file mode 100644 index 00000000000..53a7550090d --- /dev/null +++ b/src/test/ui/const-generics/const-argument-non-static-lifetime.stderr @@ -0,0 +1,11 @@ +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/const-argument-non-static-lifetime.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information + +warning: 1 warning emitted + diff --git a/src/test/ui/error-codes/E0771.rs b/src/test/ui/error-codes/E0771.rs new file mode 100644 index 00000000000..ba359271940 --- /dev/null +++ b/src/test/ui/error-codes/E0771.rs @@ -0,0 +1,8 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete + +fn function_with_str<'a, const STRING: &'a str>() {} //~ ERROR E0771 + +fn main() { + function_with_str::<"Hello, world!">() +} diff --git a/src/test/ui/error-codes/E0771.stderr b/src/test/ui/error-codes/E0771.stderr new file mode 100644 index 00000000000..60220be6b57 --- /dev/null +++ b/src/test/ui/error-codes/E0771.stderr @@ -0,0 +1,20 @@ +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/E0771.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information + +error[E0771]: use of non-static lifetime `'a` in const generic + --> $DIR/E0771.rs:4:41 + | +LL | fn function_with_str<'a, const STRING: &'a str>() {} + | ^^ + | + = note: for more information, see issue #74052 + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0771`. diff --git a/src/test/ui/issues/issue-74539.rs b/src/test/ui/issues/issue-74539.rs new file mode 100644 index 00000000000..75632d11c1d --- /dev/null +++ b/src/test/ui/issues/issue-74539.rs @@ -0,0 +1,12 @@ +enum E { + A(u8, u8), +} + +fn main() { + let e = E::A(2, 3); + match e { + E::A(x @ ..) => { //~ ERROR `x @` is not allowed in a tuple + x //~ ERROR cannot find value `x` in this scope + } + }; +} diff --git a/src/test/ui/issues/issue-74539.stderr b/src/test/ui/issues/issue-74539.stderr new file mode 100644 index 00000000000..94526dcd7cb --- /dev/null +++ b/src/test/ui/issues/issue-74539.stderr @@ -0,0 +1,21 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-74539.rs:9:13 + | +LL | x + | ^ help: a local variable with a similar name exists: `e` + +error: `x @` is not allowed in a tuple struct + --> $DIR/issue-74539.rs:8:14 + | +LL | E::A(x @ ..) => { + | ^^^^^^ this is only allowed in slice patterns + | + = help: remove this and bind each tuple field independently +help: if you don't need to use the contents of x, discard the tuple's remaining fields + | +LL | E::A(..) => { + | ^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/lint/lint-ctypes.rs b/src/test/ui/lint/lint-ctypes.rs index bdf95350c70..f485766bcd3 100644 --- a/src/test/ui/lint/lint-ctypes.rs +++ b/src/test/ui/lint/lint-ctypes.rs @@ -7,6 +7,7 @@ use std::marker::PhantomData; +trait Bar { } trait Mirror { type It: ?Sized; } impl Mirror for T { type It = Self; } #[repr(C)] @@ -53,7 +54,7 @@ pub struct StructWithProjectionAndLifetime<'a>( pub fn char_type(p: char); //~ ERROR uses type `char` pub fn i128_type(p: i128); //~ ERROR uses type `i128` pub fn u128_type(p: u128); //~ ERROR uses type `u128` - pub fn trait_type(p: &dyn Clone); //~ ERROR uses type `dyn std::clone::Clone` + pub fn trait_type(p: &dyn Bar); //~ ERROR uses type `dyn Bar` pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)` pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)` pub fn zero_size(p: ZeroSize); //~ ERROR uses type `ZeroSize` diff --git a/src/test/ui/lint/lint-ctypes.stderr b/src/test/ui/lint/lint-ctypes.stderr index 13b9adca3f9..a54226a7fc4 100644 --- a/src/test/ui/lint/lint-ctypes.stderr +++ b/src/test/ui/lint/lint-ctypes.stderr @@ -1,5 +1,5 @@ error: `extern` block uses type `Foo`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:46:28 + --> $DIR/lint-ctypes.rs:47:28 | LL | pub fn ptr_type1(size: *const Foo); | ^^^^^^^^^^ not FFI-safe @@ -12,13 +12,13 @@ LL | #![deny(improper_ctypes)] = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/lint-ctypes.rs:24:1 + --> $DIR/lint-ctypes.rs:25:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^^ error: `extern` block uses type `Foo`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:47:28 + --> $DIR/lint-ctypes.rs:48:28 | LL | pub fn ptr_type2(size: *const Foo); | ^^^^^^^^^^ not FFI-safe @@ -26,13 +26,13 @@ LL | pub fn ptr_type2(size: *const Foo); = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct = note: this struct has unspecified layout note: the type is defined here - --> $DIR/lint-ctypes.rs:24:1 + --> $DIR/lint-ctypes.rs:25:1 | LL | pub struct Foo; | ^^^^^^^^^^^^^^^ error: `extern` block uses type `[u32]`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:48:26 + --> $DIR/lint-ctypes.rs:49:26 | LL | pub fn slice_type(p: &[u32]); | ^^^^^^ not FFI-safe @@ -41,7 +41,7 @@ LL | pub fn slice_type(p: &[u32]); = note: slices have no C equivalent error: `extern` block uses type `str`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:49:24 + --> $DIR/lint-ctypes.rs:50:24 | LL | pub fn str_type(p: &str); | ^^^^ not FFI-safe @@ -50,7 +50,7 @@ LL | pub fn str_type(p: &str); = note: string slices have no C equivalent error: `extern` block uses type `std::boxed::Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:50:24 + --> $DIR/lint-ctypes.rs:51:24 | LL | pub fn box_type(p: Box); | ^^^^^^^^ not FFI-safe @@ -59,7 +59,7 @@ LL | pub fn box_type(p: Box); = note: this struct has unspecified layout error: `extern` block uses type `std::option::Option>`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:51:28 + --> $DIR/lint-ctypes.rs:52:28 | LL | pub fn opt_box_type(p: Option>); | ^^^^^^^^^^^^^^^^ not FFI-safe @@ -68,7 +68,7 @@ LL | pub fn opt_box_type(p: Option>); = note: enum has no representation hint error: `extern` block uses type `char`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:53:25 + --> $DIR/lint-ctypes.rs:54:25 | LL | pub fn char_type(p: char); | ^^^^ not FFI-safe @@ -77,7 +77,7 @@ LL | pub fn char_type(p: char); = note: the `char` type has no C equivalent error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:54:25 + --> $DIR/lint-ctypes.rs:55:25 | LL | pub fn i128_type(p: i128); | ^^^^ not FFI-safe @@ -85,23 +85,23 @@ LL | pub fn i128_type(p: i128); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:55:25 + --> $DIR/lint-ctypes.rs:56:25 | LL | pub fn u128_type(p: u128); | ^^^^ not FFI-safe | = note: 128-bit integers don't currently have a known stable ABI -error: `extern` block uses type `dyn std::clone::Clone`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:56:26 +error: `extern` block uses type `dyn Bar`, which is not FFI-safe + --> $DIR/lint-ctypes.rs:57:26 | -LL | pub fn trait_type(p: &dyn Clone); - | ^^^^^^^^^^ not FFI-safe +LL | pub fn trait_type(p: &dyn Bar); + | ^^^^^^^^ not FFI-safe | = note: trait objects have no C equivalent error: `extern` block uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:57:26 + --> $DIR/lint-ctypes.rs:58:26 | LL | pub fn tuple_type(p: (i32, i32)); | ^^^^^^^^^^ not FFI-safe @@ -110,7 +110,7 @@ LL | pub fn tuple_type(p: (i32, i32)); = note: tuples have unspecified layout error: `extern` block uses type `(i32, i32)`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:58:27 + --> $DIR/lint-ctypes.rs:59:27 | LL | pub fn tuple_type2(p: I32Pair); | ^^^^^^^ not FFI-safe @@ -119,7 +119,7 @@ LL | pub fn tuple_type2(p: I32Pair); = note: tuples have unspecified layout error: `extern` block uses type `ZeroSize`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:59:25 + --> $DIR/lint-ctypes.rs:60:25 | LL | pub fn zero_size(p: ZeroSize); | ^^^^^^^^ not FFI-safe @@ -127,26 +127,26 @@ LL | pub fn zero_size(p: ZeroSize); = help: consider adding a member to this struct = note: this struct has no fields note: the type is defined here - --> $DIR/lint-ctypes.rs:20:1 + --> $DIR/lint-ctypes.rs:21:1 | LL | pub struct ZeroSize; | ^^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `ZeroSizeWithPhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:60:33 + --> $DIR/lint-ctypes.rs:61:33 | LL | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = note: composed only of `PhantomData` note: the type is defined here - --> $DIR/lint-ctypes.rs:43:1 + --> $DIR/lint-ctypes.rs:44:1 | LL | pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `extern` block uses type `std::marker::PhantomData`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:63:12 + --> $DIR/lint-ctypes.rs:64:12 | LL | -> ::std::marker::PhantomData; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -154,7 +154,7 @@ LL | -> ::std::marker::PhantomData; = note: composed only of `PhantomData` error: `extern` block uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:64:23 + --> $DIR/lint-ctypes.rs:65:23 | LL | pub fn fn_type(p: RustFn); | ^^^^^^ not FFI-safe @@ -163,7 +163,7 @@ LL | pub fn fn_type(p: RustFn); = note: this function pointer has Rust-specific calling convention error: `extern` block uses type `fn()`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:65:24 + --> $DIR/lint-ctypes.rs:66:24 | LL | pub fn fn_type2(p: fn()); | ^^^^ not FFI-safe @@ -172,7 +172,7 @@ LL | pub fn fn_type2(p: fn()); = note: this function pointer has Rust-specific calling convention error: `extern` block uses type `std::boxed::Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:66:28 + --> $DIR/lint-ctypes.rs:67:28 | LL | pub fn fn_contained(p: RustBadRet); | ^^^^^^^^^^ not FFI-safe @@ -181,7 +181,7 @@ LL | pub fn fn_contained(p: RustBadRet); = note: this struct has unspecified layout error: `extern` block uses type `i128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:67:32 + --> $DIR/lint-ctypes.rs:68:32 | LL | pub fn transparent_i128(p: TransparentI128); | ^^^^^^^^^^^^^^^ not FFI-safe @@ -189,7 +189,7 @@ LL | pub fn transparent_i128(p: TransparentI128); = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `str`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:68:31 + --> $DIR/lint-ctypes.rs:69:31 | LL | pub fn transparent_str(p: TransparentStr); | ^^^^^^^^^^^^^^ not FFI-safe @@ -198,7 +198,7 @@ LL | pub fn transparent_str(p: TransparentStr); = note: string slices have no C equivalent error: `extern` block uses type `std::boxed::Box`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:69:30 + --> $DIR/lint-ctypes.rs:70:30 | LL | pub fn transparent_fn(p: TransparentBadFn); | ^^^^^^^^^^^^^^^^ not FFI-safe @@ -207,7 +207,7 @@ LL | pub fn transparent_fn(p: TransparentBadFn); = note: this struct has unspecified layout error: `extern` block uses type `[u8; 8]`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:70:27 + --> $DIR/lint-ctypes.rs:71:27 | LL | pub fn raw_array(arr: [u8; 8]); | ^^^^^^^ not FFI-safe @@ -216,7 +216,7 @@ LL | pub fn raw_array(arr: [u8; 8]); = note: passing raw arrays by value is not FFI-safe error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:72:34 + --> $DIR/lint-ctypes.rs:73:34 | LL | pub static static_u128_type: u128; | ^^^^ not FFI-safe @@ -224,7 +224,7 @@ LL | pub static static_u128_type: u128; = note: 128-bit integers don't currently have a known stable ABI error: `extern` block uses type `u128`, which is not FFI-safe - --> $DIR/lint-ctypes.rs:73:40 + --> $DIR/lint-ctypes.rs:74:40 | LL | pub static static_u128_array_type: [u128; 16]; | ^^^^^^^^^^ not FFI-safe diff --git a/src/test/ui/traits/issue-72410.rs b/src/test/ui/traits/issue-72410.rs new file mode 100644 index 00000000000..c95f1dfdca5 --- /dev/null +++ b/src/test/ui/traits/issue-72410.rs @@ -0,0 +1,18 @@ +// Regression test for #72410, this should be used with debug assertion enabled. + +// should be fine +pub trait Foo { + fn map() + where + Self: Sized, + for<'a> &'a mut [u8]: ; +} + +// should fail +pub trait Bar { + fn map() + where for<'a> &'a mut [dyn Bar]: ; + //~^ ERROR: the trait `Bar` cannot be made into an object +} + +fn main() {} diff --git a/src/test/ui/traits/issue-72410.stderr b/src/test/ui/traits/issue-72410.stderr new file mode 100644 index 00000000000..1db2320841f --- /dev/null +++ b/src/test/ui/traits/issue-72410.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/issue-72410.rs:14:19 + | +LL | pub trait Bar { + | --- this trait cannot be made into an object... +LL | fn map() + | --- ...because associated function `map` has no `self` parameter +LL | where for<'a> &'a mut [dyn Bar]: ; + | ^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object + | +help: consider turning `map` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects + | +LL | where for<'a> &'a mut [dyn Bar]:, Self: Sized ; + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.rs b/src/test/ui/wf/wf-foreign-fn-decl-ret.rs new file mode 100644 index 00000000000..b9d956c0568 --- /dev/null +++ b/src/test/ui/wf/wf-foreign-fn-decl-ret.rs @@ -0,0 +1,18 @@ +pub trait Unsatisfied {} + +#[repr(transparent)] +pub struct Bar(T); + +pub trait Foo { + type Assoc; +} + +extern "C" { + pub fn lint_me() -> <() as Foo>::Assoc; + //~^ ERROR: the trait bound `(): Foo` is not satisfied [E0277] + + pub fn lint_me_aswell() -> Bar; + //~^ ERROR: the trait bound `u32: Unsatisfied` is not satisfied [E0277] +} + +fn main() {} diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr new file mode 100644 index 00000000000..9081b7929d9 --- /dev/null +++ b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/wf-foreign-fn-decl-ret.rs:11:5 + | +LL | pub fn lint_me() -> <() as Foo>::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + +error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied + --> $DIR/wf-foreign-fn-decl-ret.rs:14:32 + | +LL | pub struct Bar(T); + | ----------- required by this bound in `Bar` +... +LL | pub fn lint_me_aswell() -> Bar; + | ^^^^^^^^ the trait `Unsatisfied` is not implemented for `u32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 8b0983e89ad..c9c518e5e97 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 8b0983e89ad9a28b142eccf3755a8c9aaeb37852 +Subproject commit c9c518e5e9761bf35d466c47c57c3a1358b56b3c