Auto merge of #75476 - JohnTitor:rollup-ap1rqf1, r=JohnTitor
Rollup of 11 pull requests Successful merges: - #75189 (Fix wasi::fs::OpenOptions to imply write when append is on) - #75201 (Fix some Clippy warnings in librustc_serialize) - #75372 (Fix suggestion to use lifetime in type and in assoc const) - #75400 (Fix minor things in the `f32` primitive docs) - #75449 (add regression test for #74739 (mir const-prop bug)) - #75451 (Clean up E0751 explanation) - #75455 (Use explicit path link in place for doc in time) - #75457 (Remove some dead variants in LLVM FFI) - #75466 (Move to intra doc links whenever possible within std/src/lib.rs) - #75469 (Switch to intra-doc links in `std/io/mod.rs`) - #75473 (Flip order of const & type) Failed merges: r? @ghost
This commit is contained in:
commit
9aa6cc025d
28 changed files with 464 additions and 217 deletions
|
@ -1212,7 +1212,7 @@ impl Initializer {
|
|||
///
|
||||
/// [`write`]: Self::write
|
||||
/// [`flush`]: Self::flush
|
||||
/// [`std::io`]: index.html
|
||||
/// [`std::io`]: self
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1590,8 +1590,6 @@ pub trait Seek {
|
|||
/// # Errors
|
||||
///
|
||||
/// Seeking to a negative offset is considered an error.
|
||||
///
|
||||
/// [`SeekFrom::Start`]: enum.SeekFrom.html#variant.Start
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
|
||||
|
||||
|
@ -1678,8 +1676,6 @@ pub trait Seek {
|
|||
/// Enumeration of possible methods to seek within an I/O object.
|
||||
///
|
||||
/// It is used by the [`Seek`] trait.
|
||||
///
|
||||
/// [`Seek`]: trait.Seek.html
|
||||
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub enum SeekFrom {
|
||||
|
@ -1759,11 +1755,9 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> R
|
|||
/// For example, [`File`] implements [`Read`], but not `BufRead`.
|
||||
/// [`BufReader`] to the rescue!
|
||||
///
|
||||
/// [`BufReader`]: struct.BufReader.html
|
||||
/// [`File`]: crate::fs::File
|
||||
/// [`read_line`]: Self::read_line
|
||||
/// [`lines`]: Self::lines
|
||||
/// [`Read`]: trait.Read.html
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::io::{self, BufReader};
|
||||
|
@ -1869,7 +1863,6 @@ pub trait BufRead: Read {
|
|||
/// present in `buf` and its length will have been adjusted appropriately.
|
||||
///
|
||||
/// [`fill_buf`]: Self::fill_buf
|
||||
/// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1877,8 +1870,6 @@ pub trait BufRead: Read {
|
|||
/// this example, we use [`Cursor`] to read all the bytes in a byte slice
|
||||
/// in hyphen delimited segments:
|
||||
///
|
||||
/// [`Cursor`]: struct.Cursor.html
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::{self, BufRead};
|
||||
///
|
||||
|
@ -1940,8 +1931,6 @@ pub trait BufRead: Read {
|
|||
/// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
|
||||
/// this example, we use [`Cursor`] to read all the lines in a byte slice:
|
||||
///
|
||||
/// [`Cursor`]: struct.Cursor.html
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::{self, BufRead};
|
||||
///
|
||||
|
@ -1996,8 +1985,6 @@ pub trait BufRead: Read {
|
|||
/// this example, we use [`Cursor`] to iterate over all hyphen delimited
|
||||
/// segments in a byte slice
|
||||
///
|
||||
/// [`Cursor`]: struct.Cursor.html
|
||||
///
|
||||
/// ```
|
||||
/// use std::io::{self, BufRead};
|
||||
///
|
||||
|
@ -2046,8 +2033,6 @@ pub trait BufRead: Read {
|
|||
/// # Errors
|
||||
///
|
||||
/// Each line of the iterator has the same error semantics as [`BufRead::read_line`].
|
||||
///
|
||||
/// [`BufRead::read_line`]: trait.BufRead.html#method.read_line
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn lines(self) -> Lines<Self>
|
||||
where
|
||||
|
@ -2062,7 +2047,7 @@ pub trait BufRead: Read {
|
|||
/// This struct is generally created by calling [`chain`] on a reader.
|
||||
/// Please see the documentation of [`chain`] for more details.
|
||||
///
|
||||
/// [`chain`]: trait.Read.html#method.chain
|
||||
/// [`chain`]: Read::chain
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Chain<T, U> {
|
||||
first: T,
|
||||
|
@ -2204,7 +2189,7 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
|
|||
/// This struct is generally created by calling [`take`] on a reader.
|
||||
/// Please see the documentation of [`take`] for more details.
|
||||
///
|
||||
/// [`take`]: trait.Read.html#method.take
|
||||
/// [`take`]: Read::take
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Take<T> {
|
||||
|
@ -2403,7 +2388,7 @@ impl<T: BufRead> BufRead for Take<T> {
|
|||
/// This struct is generally created by calling [`bytes`] on a reader.
|
||||
/// Please see the documentation of [`bytes`] for more details.
|
||||
///
|
||||
/// [`bytes`]: trait.Read.html#method.bytes
|
||||
/// [`bytes`]: Read::bytes
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Bytes<R> {
|
||||
|
@ -2433,7 +2418,7 @@ impl<R: Read> Iterator for Bytes<R> {
|
|||
/// This struct is generally created by calling [`split`] on a `BufRead`.
|
||||
/// Please see the documentation of [`split`] for more details.
|
||||
///
|
||||
/// [`split`]: trait.BufRead.html#method.split
|
||||
/// [`split`]: BufRead::split
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Split<B> {
|
||||
|
@ -2465,7 +2450,7 @@ impl<B: BufRead> Iterator for Split<B> {
|
|||
/// This struct is generally created by calling [`lines`] on a `BufRead`.
|
||||
/// Please see the documentation of [`lines`] for more details.
|
||||
///
|
||||
/// [`lines`]: trait.BufRead.html#method.lines
|
||||
/// [`lines`]: BufRead::lines
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Lines<B> {
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
//! * [`std::*` modules](#modules)
|
||||
//! * [Primitive types](#primitives)
|
||||
//! * [Standard macros](#macros)
|
||||
//! * [The Rust Prelude](prelude/index.html)
|
||||
//! * [The Rust Prelude]
|
||||
//!
|
||||
//! If this is your first time, the documentation for the standard library is
|
||||
//! written to be casually perused. Clicking on interesting things should
|
||||
|
@ -63,8 +63,8 @@
|
|||
//! So for example there is a [page for the primitive type
|
||||
//! `i32`](primitive.i32.html) that lists all the methods that can be called on
|
||||
//! 32-bit integers (very useful), and there is a [page for the module
|
||||
//! `std::i32`](i32/index.html) that documents the constant values [`MIN`] and
|
||||
//! [`MAX`](i32/constant.MAX.html) (rarely useful).
|
||||
//! `std::i32`] that documents the constant values [`MIN`] and [`MAX`] (rarely
|
||||
//! useful).
|
||||
//!
|
||||
//! Note the documentation for the primitives [`str`] and [`[T]`][slice] (also
|
||||
//! called 'slice'). Many method calls on [`String`] and [`Vec<T>`] are actually
|
||||
|
@ -152,48 +152,35 @@
|
|||
//! contains further primitive shared memory types, including [`atomic`] and
|
||||
//! [`mpsc`], which contains the channel types for message passing.
|
||||
//!
|
||||
//! [I/O]: io/index.html
|
||||
//! [`MIN`]: i32/constant.MIN.html
|
||||
//! [TCP]: net/struct.TcpStream.html
|
||||
//! [The Rust Prelude]: prelude/index.html
|
||||
//! [UDP]: net/struct.UdpSocket.html
|
||||
//! [`Arc`]: sync/struct.Arc.html
|
||||
//! [owned slice]: boxed/index.html
|
||||
//! [`Cell`]: cell/struct.Cell.html
|
||||
//! [`FromStr`]: str/trait.FromStr.html
|
||||
//! [`HashMap<K, V>`]: collections/struct.HashMap.html
|
||||
//! [`Iterator`]: iter/trait.Iterator.html
|
||||
//! [`Mutex`]: sync/struct.Mutex.html
|
||||
//! [`Option<T>`]: option/enum.Option.html
|
||||
//! [`Rc`]: rc/struct.Rc.html
|
||||
//! [`RefCell`]: cell/struct.RefCell.html
|
||||
//! [`Result<T, E>`]: result/enum.Result.html
|
||||
//! [`String`]: string/struct.String.html
|
||||
//! [`Vec<T>`]: vec/struct.Vec.html
|
||||
//! [array]: primitive.array.html
|
||||
//! [slice]: primitive.slice.html
|
||||
//! [`atomic`]: sync/atomic/index.html
|
||||
//! [`collections`]: collections/index.html
|
||||
//! [I/O]: io
|
||||
//! [`MIN`]: i32::MIN
|
||||
//! [`MAX`]: i32::MAX
|
||||
//! [page for the module `std::i32`]: crate::i32
|
||||
//! [TCP]: net::TcpStream
|
||||
//! [The Rust Prelude]: prelude
|
||||
//! [UDP]: net::UdpSocket
|
||||
//! [`Arc`]: sync::Arc
|
||||
//! [owned slice]: boxed
|
||||
//! [`Cell`]: cell::Cell
|
||||
//! [`FromStr`]: str::FromStr
|
||||
//! [`HashMap<K, V>`]: collections::HashMap
|
||||
//! [`Mutex`]: sync::Mutex
|
||||
//! [`Option<T>`]: option::Option
|
||||
//! [`Rc`]: rc::Rc
|
||||
//! [`RefCell`]: cell::RefCell
|
||||
//! [`Result<T, E>`]: result::Result
|
||||
//! [`Vec<T>`]: vec::Vec
|
||||
//! [`atomic`]: sync::atomic
|
||||
//! [`for`]: ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
|
||||
//! [`format!`]: macro.format.html
|
||||
//! [`fs`]: fs/index.html
|
||||
//! [`io`]: io/index.html
|
||||
//! [`iter`]: iter/index.html
|
||||
//! [`mpsc`]: sync/mpsc/index.html
|
||||
//! [`net`]: net/index.html
|
||||
//! [`option`]: option/index.html
|
||||
//! [`result`]: result/index.html
|
||||
//! [`std::cmp`]: cmp/index.html
|
||||
//! [`std::slice`]: slice/index.html
|
||||
//! [`str`]: primitive.str.html
|
||||
//! [`sync`]: sync/index.html
|
||||
//! [`thread`]: thread/index.html
|
||||
//! [`mpsc`]: sync::mpsc
|
||||
//! [`std::cmp`]: cmp
|
||||
//! [`std::slice`]: slice
|
||||
//! [`use std::env`]: env/index.html
|
||||
//! [`use`]: ../book/ch07-02-defining-modules-to-control-scope-and-privacy.html
|
||||
//! [crates.io]: https://crates.io
|
||||
//! [deref-coercions]: ../book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
|
||||
//! [files]: fs/struct.File.html
|
||||
//! [multithreading]: thread/index.html
|
||||
//! [files]: fs::File
|
||||
//! [multithreading]: thread
|
||||
//! [other]: #what-is-in-the-standard-library-documentation
|
||||
//! [primitive types]: ../book/ch03-02-data-types.html
|
||||
//! [rust-discord]: https://discord.gg/rust-lang
|
||||
|
|
|
@ -768,7 +768,8 @@ mod prim_tuple {}
|
|||
///
|
||||
/// This type can represent a wide range of decimal numbers, like `3.5`, `27`,
|
||||
/// `-113.75`, `0.0078125`, `34359738368`, `0`, `-1`. So unlike integer types
|
||||
/// (like `i32`), floating point types can represent non-integer numbers, too.
|
||||
/// (such as `i32`), floating point types can represent non-integer numbers,
|
||||
/// too.
|
||||
///
|
||||
/// However, being able to represent this wide range of numbers comes at the
|
||||
/// cost of precision: floats can only represent some of the real numbers and
|
||||
|
@ -779,15 +780,12 @@ mod prim_tuple {}
|
|||
/// often discard insignificant digits: `println!("{}", 1.0f32 / 5.0f32)` will
|
||||
/// print `0.2`.
|
||||
///
|
||||
/// The precision is better for numbers near 0 and worse for large numbers. For
|
||||
/// example, above 2<sup>24</sup>, not even all integers are representable.
|
||||
///
|
||||
/// Additionally, `f32` can represent a couple of special values:
|
||||
///
|
||||
/// - `-0`: this is just due to how floats are encoded. It is semantically
|
||||
/// equivalent to `0` and `-0.0 == 0.0` results in `true`.
|
||||
/// - [∞](#associatedconstant.INFINITY) and
|
||||
/// [-∞](#associatedconstant.NEG_INFINITY): these result from calculations
|
||||
/// [−∞](#associatedconstant.NEG_INFINITY): these result from calculations
|
||||
/// like `1.0 / 0.0`.
|
||||
/// - [NaN (not a number)](#associatedconstant.NAN): this value results from
|
||||
/// calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected
|
||||
|
|
|
@ -46,6 +46,7 @@ pub struct DirEntry {
|
|||
pub struct OpenOptions {
|
||||
read: bool,
|
||||
write: bool,
|
||||
append: bool,
|
||||
dirflags: wasi::Lookupflags,
|
||||
fdflags: wasi::Fdflags,
|
||||
oflags: wasi::Oflags,
|
||||
|
@ -270,8 +271,9 @@ impl OpenOptions {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn append(&mut self, set: bool) {
|
||||
self.fdflag(wasi::FDFLAGS_APPEND, set);
|
||||
pub fn append(&mut self, append: bool) {
|
||||
self.append = append;
|
||||
self.fdflag(wasi::FDFLAGS_APPEND, append);
|
||||
}
|
||||
|
||||
pub fn dsync(&mut self, set: bool) {
|
||||
|
@ -321,7 +323,7 @@ impl OpenOptions {
|
|||
base |= wasi::RIGHTS_FD_READ;
|
||||
base |= wasi::RIGHTS_FD_READDIR;
|
||||
}
|
||||
if self.write {
|
||||
if self.write || self.append {
|
||||
base |= wasi::RIGHTS_FD_WRITE;
|
||||
base |= wasi::RIGHTS_FD_DATASYNC;
|
||||
base |= wasi::RIGHTS_FD_ALLOCATE;
|
||||
|
|
|
@ -359,9 +359,7 @@ impl Add<Duration> for Instant {
|
|||
/// # Panics
|
||||
///
|
||||
/// This function may panic if the resulting point in time cannot be represented by the
|
||||
/// underlying data structure. See [`checked_add`] for a version without panic.
|
||||
///
|
||||
/// [`checked_add`]: Instant::checked_add
|
||||
/// underlying data structure. See [`Instant::checked_add`] for a version without panic.
|
||||
fn add(self, other: Duration) -> Instant {
|
||||
self.checked_add(other).expect("overflow when adding duration to instant")
|
||||
}
|
||||
|
@ -525,9 +523,7 @@ impl Add<Duration> for SystemTime {
|
|||
/// # Panics
|
||||
///
|
||||
/// This function may panic if the resulting point in time cannot be represented by the
|
||||
/// underlying data structure. See [`checked_add`] for a version without panic.
|
||||
///
|
||||
/// [`checked_add`]: SystemTime::checked_add
|
||||
/// underlying data structure. See [`SystemTime::checked_add`] for a version without panic.
|
||||
fn add(self, dur: Duration) -> SystemTime {
|
||||
self.checked_add(dur).expect("overflow when adding duration to instant")
|
||||
}
|
||||
|
|
|
@ -777,7 +777,7 @@ fn validate_generic_param_order<'a>(
|
|||
if sess.features_untracked().const_generics {
|
||||
", then consts and types"
|
||||
} else if sess.features_untracked().min_const_generics {
|
||||
", then consts, then types"
|
||||
", then types, then consts"
|
||||
} else {
|
||||
", then types"
|
||||
},
|
||||
|
|
|
@ -975,7 +975,6 @@ pub unsafe fn with_llvm_pmb(
|
|||
(llvm::CodeGenOptLevel::Default, ..) => {
|
||||
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
|
||||
}
|
||||
(llvm::CodeGenOptLevel::Other, ..) => bug!("CodeGenOptLevel::Other selected"),
|
||||
}
|
||||
|
||||
f(builder);
|
||||
|
|
|
@ -337,9 +337,6 @@ impl AtomicOrdering {
|
|||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub enum SynchronizationScope {
|
||||
// FIXME: figure out if this variant is needed at all.
|
||||
#[allow(dead_code)]
|
||||
Other,
|
||||
SingleThread,
|
||||
CrossThread,
|
||||
}
|
||||
|
@ -347,7 +344,6 @@ pub enum SynchronizationScope {
|
|||
impl SynchronizationScope {
|
||||
pub fn from_generic(sc: rustc_codegen_ssa::common::SynchronizationScope) -> Self {
|
||||
match sc {
|
||||
rustc_codegen_ssa::common::SynchronizationScope::Other => SynchronizationScope::Other,
|
||||
rustc_codegen_ssa::common::SynchronizationScope::SingleThread => {
|
||||
SynchronizationScope::SingleThread
|
||||
}
|
||||
|
@ -362,9 +358,6 @@ impl SynchronizationScope {
|
|||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub enum FileType {
|
||||
// FIXME: figure out if this variant is needed at all.
|
||||
#[allow(dead_code)]
|
||||
Other,
|
||||
AssemblyFile,
|
||||
ObjectFile,
|
||||
}
|
||||
|
@ -391,9 +384,6 @@ pub enum MetadataType {
|
|||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub enum AsmDialect {
|
||||
// FIXME: figure out if this variant is needed at all.
|
||||
#[allow(dead_code)]
|
||||
Other,
|
||||
Att,
|
||||
Intel,
|
||||
}
|
||||
|
@ -411,9 +401,6 @@ impl AsmDialect {
|
|||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[repr(C)]
|
||||
pub enum CodeGenOptLevel {
|
||||
// FIXME: figure out if this variant is needed at all.
|
||||
#[allow(dead_code)]
|
||||
Other,
|
||||
None,
|
||||
Less,
|
||||
Default,
|
||||
|
@ -513,9 +500,6 @@ pub enum DiagnosticLevel {
|
|||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub enum ArchiveKind {
|
||||
// FIXME: figure out if this variant is needed at all.
|
||||
#[allow(dead_code)]
|
||||
Other,
|
||||
K_GNU,
|
||||
K_BSD,
|
||||
K_DARWIN,
|
||||
|
|
|
@ -72,9 +72,6 @@ pub enum AtomicOrdering {
|
|||
}
|
||||
|
||||
pub enum SynchronizationScope {
|
||||
// FIXME: figure out if this variant is needed at all.
|
||||
#[allow(dead_code)]
|
||||
Other,
|
||||
SingleThread,
|
||||
CrossThread,
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ Erroneous code example:
|
|||
```compile_fail,E0751
|
||||
trait MyTrait {}
|
||||
impl MyTrait for i32 { }
|
||||
impl !MyTrait for i32 { }
|
||||
impl !MyTrait for i32 { } // error!
|
||||
```
|
||||
|
||||
Negative implementations are a promise that the trait will never be
|
||||
implemented for the given types.
|
||||
Negative implementations are a promise that the trait will never be implemented
|
||||
for the given types. Therefore, both cannot exists at the same time.
|
||||
|
|
|
@ -16,8 +16,8 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
|||
use rustc_hir::PrimTy;
|
||||
use rustc_session::config::nightly_options;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{BytePos, Span};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||
|
||||
use log::debug;
|
||||
|
||||
|
@ -33,6 +33,7 @@ enum AssocSuggestion {
|
|||
crate enum MissingLifetimeSpot<'tcx> {
|
||||
Generics(&'tcx hir::Generics<'tcx>),
|
||||
HigherRanked { span: Span, span_type: ForLifetimeSpanType },
|
||||
Static,
|
||||
}
|
||||
|
||||
crate enum ForLifetimeSpanType {
|
||||
|
@ -1195,6 +1196,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||
https://doc.rust-lang.org/nomicon/hrtb.html",
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if nightly_options::is_nightly_build()
|
||||
|
@ -1253,7 +1255,8 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||
err: &mut DiagnosticBuilder<'_>,
|
||||
span: Span,
|
||||
count: usize,
|
||||
lifetime_names: &FxHashSet<Ident>,
|
||||
lifetime_names: &FxHashSet<Symbol>,
|
||||
lifetime_spans: Vec<Span>,
|
||||
params: &[ElisionFailureInfo],
|
||||
) {
|
||||
let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok();
|
||||
|
@ -1267,11 +1270,60 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||
),
|
||||
);
|
||||
|
||||
let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| {
|
||||
let suggest_existing = |err: &mut DiagnosticBuilder<'_>,
|
||||
name: &str,
|
||||
formatter: &dyn Fn(&str) -> String| {
|
||||
if let Some(MissingLifetimeSpot::HigherRanked { span: for_span, span_type }) =
|
||||
self.missing_named_lifetime_spots.iter().rev().next()
|
||||
{
|
||||
// When we have `struct S<'a>(&'a dyn Fn(&X) -> &X);` we want to not only suggest
|
||||
// using `'a`, but also introduce the concept of HRLTs by suggesting
|
||||
// `struct S<'a>(&'a dyn for<'b> Fn(&X) -> &'b X);`. (#72404)
|
||||
let mut introduce_suggestion = vec![];
|
||||
|
||||
let a_to_z_repeat_n = |n| {
|
||||
(b'a'..=b'z').map(move |c| {
|
||||
let mut s = '\''.to_string();
|
||||
s.extend(std::iter::repeat(char::from(c)).take(n));
|
||||
s
|
||||
})
|
||||
};
|
||||
|
||||
// If all single char lifetime names are present, we wrap around and double the chars.
|
||||
let lt_name = (1..)
|
||||
.flat_map(a_to_z_repeat_n)
|
||||
.find(|lt| !lifetime_names.contains(&Symbol::intern(<)))
|
||||
.unwrap();
|
||||
let msg = format!(
|
||||
"consider making the {} lifetime-generic with a new `{}` lifetime",
|
||||
span_type.descr(),
|
||||
lt_name,
|
||||
);
|
||||
err.note(
|
||||
"for more information on higher-ranked polymorphism, visit \
|
||||
https://doc.rust-lang.org/nomicon/hrtb.html",
|
||||
);
|
||||
let for_sugg = span_type.suggestion(<_name);
|
||||
for param in params {
|
||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) {
|
||||
if snippet.starts_with('&') && !snippet.starts_with("&'") {
|
||||
introduce_suggestion
|
||||
.push((param.span, format!("&{} {}", lt_name, &snippet[1..])));
|
||||
} else if snippet.starts_with("&'_ ") {
|
||||
introduce_suggestion
|
||||
.push((param.span, format!("&{} {}", lt_name, &snippet[4..])));
|
||||
}
|
||||
}
|
||||
}
|
||||
introduce_suggestion.push((*for_span, for_sugg.to_string()));
|
||||
introduce_suggestion.push((span, formatter(<_name)));
|
||||
err.multipart_suggestion(&msg, introduce_suggestion, Applicability::MaybeIncorrect);
|
||||
}
|
||||
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
&format!("consider using the `{}` lifetime", lifetime_names.iter().next().unwrap()),
|
||||
sugg,
|
||||
formatter(name),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
};
|
||||
|
@ -1282,6 +1334,15 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||
let should_break;
|
||||
introduce_suggestion.push(match missing {
|
||||
MissingLifetimeSpot::Generics(generics) => {
|
||||
if generics.span == DUMMY_SP {
|
||||
// Account for malformed generics in the HIR. This shouldn't happen,
|
||||
// but if we make a mistake elsewhere, mainly by keeping something in
|
||||
// `missing_named_lifetime_spots` that we shouldn't, like associated
|
||||
// `const`s or making a mistake in the AST lowering we would provide
|
||||
// non-sensical suggestions. Guard against that by skipping these.
|
||||
// (#74264)
|
||||
continue;
|
||||
}
|
||||
msg = "consider introducing a named lifetime parameter".to_string();
|
||||
should_break = true;
|
||||
if let Some(param) = generics.params.iter().find(|p| match p.kind {
|
||||
|
@ -1308,6 +1369,42 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||
);
|
||||
(*span, span_type.suggestion("'a"))
|
||||
}
|
||||
MissingLifetimeSpot::Static => {
|
||||
let (span, sugg) = match snippet.as_deref() {
|
||||
Some("&") => (span.shrink_to_hi(), "'static ".to_owned()),
|
||||
Some("'_") => (span, "'static".to_owned()),
|
||||
Some(snippet) if !snippet.ends_with('>') => {
|
||||
if snippet == "" {
|
||||
(
|
||||
span,
|
||||
std::iter::repeat("'static")
|
||||
.take(count)
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
span.shrink_to_hi(),
|
||||
format!(
|
||||
"<{}>",
|
||||
std::iter::repeat("'static")
|
||||
.take(count)
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"consider using the `'static` lifetime",
|
||||
sugg.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
});
|
||||
for param in params {
|
||||
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) {
|
||||
|
@ -1328,19 +1425,19 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
match (lifetime_names.len(), lifetime_names.iter().next(), snippet.as_deref()) {
|
||||
(1, Some(name), Some("&")) => {
|
||||
suggest_existing(err, format!("&{} ", name));
|
||||
let lifetime_names: Vec<_> = lifetime_names.into_iter().collect();
|
||||
match (&lifetime_names[..], snippet.as_deref()) {
|
||||
([name], Some("&")) => {
|
||||
suggest_existing(err, &name.as_str()[..], &|name| format!("&{} ", name));
|
||||
}
|
||||
(1, Some(name), Some("'_")) => {
|
||||
suggest_existing(err, name.to_string());
|
||||
([name], Some("'_")) => {
|
||||
suggest_existing(err, &name.as_str()[..], &|n| n.to_string());
|
||||
}
|
||||
(1, Some(name), Some("")) => {
|
||||
suggest_existing(err, format!("{}, ", name).repeat(count));
|
||||
([name], Some("")) => {
|
||||
suggest_existing(err, &name.as_str()[..], &|n| format!("{}, ", n).repeat(count));
|
||||
}
|
||||
(1, Some(name), Some(snippet)) if !snippet.ends_with('>') => {
|
||||
suggest_existing(
|
||||
err,
|
||||
([name], Some(snippet)) if !snippet.ends_with('>') => {
|
||||
let f = |name: &str| {
|
||||
format!(
|
||||
"{}<{}>",
|
||||
snippet,
|
||||
|
@ -1348,21 +1445,37 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||
.take(count)
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ")
|
||||
),
|
||||
);
|
||||
)
|
||||
};
|
||||
suggest_existing(err, &name.as_str()[..], &f);
|
||||
}
|
||||
(0, _, Some("&")) if count == 1 => {
|
||||
([], Some("&")) if count == 1 => {
|
||||
suggest_new(err, "&'a ");
|
||||
}
|
||||
(0, _, Some("'_")) if count == 1 => {
|
||||
([], Some("'_")) if count == 1 => {
|
||||
suggest_new(err, "'a");
|
||||
}
|
||||
(0, _, Some(snippet)) if !snippet.ends_with('>') && count == 1 => {
|
||||
suggest_new(err, &format!("{}<'a>", snippet));
|
||||
([], Some(snippet)) if !snippet.ends_with('>') => {
|
||||
if snippet == "" {
|
||||
// This happens when we have `type Bar<'a> = Foo<T>` where we point at the space
|
||||
// before `T`. We will suggest `type Bar<'a> = Foo<'a, T>`.
|
||||
suggest_new(
|
||||
err,
|
||||
&std::iter::repeat("'a, ").take(count).collect::<Vec<_>>().join(""),
|
||||
);
|
||||
} else {
|
||||
suggest_new(
|
||||
err,
|
||||
&format!(
|
||||
"{}<{}>",
|
||||
snippet,
|
||||
std::iter::repeat("'a").take(count).collect::<Vec<_>>().join(", ")
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
(n, ..) if n > 1 => {
|
||||
let spans: Vec<Span> = lifetime_names.iter().map(|lt| lt.span).collect();
|
||||
err.span_note(spans, "these named lifetimes are available to use");
|
||||
(lts, ..) if lts.len() > 1 => {
|
||||
err.span_note(lifetime_spans, "these named lifetimes are available to use");
|
||||
if Some("") == snippet.as_deref() {
|
||||
// This happens when we have `Foo<T>` where we point at the space before `T`,
|
||||
// but this can be confusing so we give a suggestion with placeholders.
|
||||
|
|
|
@ -711,9 +711,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
|
||||
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
|
||||
use self::hir::TraitItemKind::*;
|
||||
self.missing_named_lifetime_spots.push((&trait_item.generics).into());
|
||||
match trait_item.kind {
|
||||
Fn(ref sig, _) => {
|
||||
self.missing_named_lifetime_spots.push((&trait_item.generics).into());
|
||||
let tcx = self.tcx;
|
||||
self.visit_early_late(
|
||||
Some(tcx.hir().get_parent_item(trait_item.hir_id)),
|
||||
|
@ -721,8 +721,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
&trait_item.generics,
|
||||
|this| intravisit::walk_trait_item(this, trait_item),
|
||||
);
|
||||
self.missing_named_lifetime_spots.pop();
|
||||
}
|
||||
Type(bounds, ref ty) => {
|
||||
self.missing_named_lifetime_spots.push((&trait_item.generics).into());
|
||||
let generics = &trait_item.generics;
|
||||
let mut index = self.next_early_index();
|
||||
debug!("visit_ty: index = {}", index);
|
||||
|
@ -757,31 +759,35 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
this.visit_ty(ty);
|
||||
}
|
||||
});
|
||||
self.missing_named_lifetime_spots.pop();
|
||||
}
|
||||
Const(_, _) => {
|
||||
// Only methods and types support generics.
|
||||
assert!(trait_item.generics.params.is_empty());
|
||||
self.missing_named_lifetime_spots.push(MissingLifetimeSpot::Static);
|
||||
intravisit::walk_trait_item(self, trait_item);
|
||||
self.missing_named_lifetime_spots.pop();
|
||||
}
|
||||
}
|
||||
self.missing_named_lifetime_spots.pop();
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
||||
use self::hir::ImplItemKind::*;
|
||||
self.missing_named_lifetime_spots.push((&impl_item.generics).into());
|
||||
match impl_item.kind {
|
||||
Fn(ref sig, _) => {
|
||||
self.missing_named_lifetime_spots.push((&impl_item.generics).into());
|
||||
let tcx = self.tcx;
|
||||
self.visit_early_late(
|
||||
Some(tcx.hir().get_parent_item(impl_item.hir_id)),
|
||||
&sig.decl,
|
||||
&impl_item.generics,
|
||||
|this| intravisit::walk_impl_item(this, impl_item),
|
||||
)
|
||||
);
|
||||
self.missing_named_lifetime_spots.pop();
|
||||
}
|
||||
TyAlias(ref ty) => {
|
||||
let generics = &impl_item.generics;
|
||||
self.missing_named_lifetime_spots.push(generics.into());
|
||||
let mut index = self.next_early_index();
|
||||
let mut non_lifetime_count = 0;
|
||||
debug!("visit_ty: index = {}", index);
|
||||
|
@ -810,14 +816,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
this.visit_generics(generics);
|
||||
this.visit_ty(ty);
|
||||
});
|
||||
self.missing_named_lifetime_spots.pop();
|
||||
}
|
||||
Const(_, _) => {
|
||||
// Only methods and types support generics.
|
||||
assert!(impl_item.generics.params.is_empty());
|
||||
self.missing_named_lifetime_spots.push(MissingLifetimeSpot::Static);
|
||||
intravisit::walk_impl_item(self, impl_item);
|
||||
self.missing_named_lifetime_spots.pop();
|
||||
}
|
||||
}
|
||||
self.missing_named_lifetime_spots.pop();
|
||||
}
|
||||
|
||||
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
|
||||
|
@ -2315,6 +2323,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
let mut late_depth = 0;
|
||||
let mut scope = self.scope;
|
||||
let mut lifetime_names = FxHashSet::default();
|
||||
let mut lifetime_spans = vec![];
|
||||
let error = loop {
|
||||
match *scope {
|
||||
// Do not assign any resolution, it will be inferred.
|
||||
|
@ -2326,7 +2335,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
// collect named lifetimes for suggestions
|
||||
for name in lifetimes.keys() {
|
||||
if let hir::ParamName::Plain(name) = name {
|
||||
lifetime_names.insert(*name);
|
||||
lifetime_names.insert(name.name);
|
||||
lifetime_spans.push(name.span);
|
||||
}
|
||||
}
|
||||
late_depth += 1;
|
||||
|
@ -2344,12 +2354,24 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
}
|
||||
Elide::Exact(l) => l.shifted(late_depth),
|
||||
Elide::Error(ref e) => {
|
||||
if let Scope::Binder { ref lifetimes, .. } = s {
|
||||
// collect named lifetimes for suggestions
|
||||
for name in lifetimes.keys() {
|
||||
if let hir::ParamName::Plain(name) = name {
|
||||
lifetime_names.insert(*name);
|
||||
let mut scope = s;
|
||||
loop {
|
||||
match scope {
|
||||
Scope::Binder { ref lifetimes, s, .. } => {
|
||||
// Collect named lifetimes for suggestions.
|
||||
for name in lifetimes.keys() {
|
||||
if let hir::ParamName::Plain(name) = name {
|
||||
lifetime_names.insert(name.name);
|
||||
lifetime_spans.push(name.span);
|
||||
}
|
||||
}
|
||||
scope = s;
|
||||
}
|
||||
Scope::ObjectLifetimeDefault { ref s, .. }
|
||||
| Scope::Elision { ref s, .. } => {
|
||||
scope = s;
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
break Some(e);
|
||||
|
@ -2373,7 +2395,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
if let Some(params) = error {
|
||||
// If there's no lifetime available, suggest `'static`.
|
||||
if self.report_elision_failure(&mut err, params) && lifetime_names.is_empty() {
|
||||
lifetime_names.insert(Ident::with_dummy_span(kw::StaticLifetime));
|
||||
lifetime_names.insert(kw::StaticLifetime);
|
||||
}
|
||||
}
|
||||
self.add_missing_lifetime_specifiers_label(
|
||||
|
@ -2381,6 +2403,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
span,
|
||||
lifetime_refs.len(),
|
||||
&lifetime_names,
|
||||
lifetime_spans,
|
||||
error.map(|p| &p[..]).unwrap_or(&[]),
|
||||
);
|
||||
err.emit();
|
||||
|
|
|
@ -86,11 +86,9 @@ where
|
|||
{
|
||||
fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
|
||||
e.emit_map(self.len(), |e| {
|
||||
let mut i = 0;
|
||||
for (key, val) in self {
|
||||
for (i, (key, val)) in self.iter().enumerate() {
|
||||
e.emit_map_elt_key(i, |e| key.encode(e))?;
|
||||
e.emit_map_elt_val(i, |e| val.encode(e))?;
|
||||
i += 1;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
@ -121,10 +119,8 @@ where
|
|||
{
|
||||
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||
s.emit_seq(self.len(), |s| {
|
||||
let mut i = 0;
|
||||
for e in self {
|
||||
for (i, e) in self.iter().enumerate() {
|
||||
s.emit_seq_elt(i, |s| e.encode(s))?;
|
||||
i += 1;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
@ -154,11 +150,9 @@ where
|
|||
{
|
||||
fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
|
||||
e.emit_map(self.len(), |e| {
|
||||
let mut i = 0;
|
||||
for (key, val) in self {
|
||||
for (i, (key, val)) in self.iter().enumerate() {
|
||||
e.emit_map_elt_key(i, |e| key.encode(e))?;
|
||||
e.emit_map_elt_val(i, |e| val.encode(e))?;
|
||||
i += 1;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
@ -192,10 +186,8 @@ where
|
|||
{
|
||||
fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
|
||||
s.emit_seq(self.len(), |s| {
|
||||
let mut i = 0;
|
||||
for e in self {
|
||||
for (i, e) in self.iter().enumerate() {
|
||||
s.emit_seq_elt(i, |s| e.encode(s))?;
|
||||
i += 1;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
@ -227,11 +219,9 @@ where
|
|||
{
|
||||
fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
|
||||
e.emit_map(self.len(), |e| {
|
||||
let mut i = 0;
|
||||
for (key, val) in self {
|
||||
for (i, (key, val)) in self.iter().enumerate() {
|
||||
e.emit_map_elt_key(i, |e| key.encode(e))?;
|
||||
e.emit_map_elt_val(i, |e| val.encode(e))?;
|
||||
i += 1;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
@ -265,10 +255,8 @@ where
|
|||
{
|
||||
fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
|
||||
s.emit_seq(self.len(), |s| {
|
||||
let mut i = 0;
|
||||
for e in self {
|
||||
for (i, e) in self.iter().enumerate() {
|
||||
s.emit_seq_elt(i, |s| e.encode(s))?;
|
||||
i += 1;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
|
|
@ -78,19 +78,17 @@
|
|||
//! data_vector: Vec<u8>,
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let object = TestStruct {
|
||||
//! data_int: 1,
|
||||
//! data_str: "homura".to_string(),
|
||||
//! data_vector: vec![2,3,4,5],
|
||||
//! };
|
||||
//! let object = TestStruct {
|
||||
//! data_int: 1,
|
||||
//! data_str: "homura".to_string(),
|
||||
//! data_vector: vec![2,3,4,5],
|
||||
//! };
|
||||
//!
|
||||
//! // Serialize using `json::encode`
|
||||
//! let encoded = json::encode(&object).unwrap();
|
||||
//! // Serialize using `json::encode`
|
||||
//! let encoded = json::encode(&object).unwrap();
|
||||
//!
|
||||
//! // Deserialize using `json::decode`
|
||||
//! let decoded: TestStruct = json::decode(&encoded[..]).unwrap();
|
||||
//! }
|
||||
//! // Deserialize using `json::decode`
|
||||
//! let decoded: TestStruct = json::decode(&encoded[..]).unwrap();
|
||||
//! ```
|
||||
//!
|
||||
//! ## Using the `ToJson` trait
|
||||
|
@ -125,16 +123,14 @@
|
|||
//! val: Json,
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let num = ComplexNum { a: 0.0001, b: 12.539 };
|
||||
//! let data: String = json::encode(&ComplexNumRecord{
|
||||
//! uid: 1,
|
||||
//! dsc: "test".to_string(),
|
||||
//! val: num.to_json(),
|
||||
//! }).unwrap();
|
||||
//! println!("data: {}", data);
|
||||
//! // data: {"uid":1,"dsc":"test","val":"0.0001+12.539i"};
|
||||
//! }
|
||||
//! let num = ComplexNum { a: 0.0001, b: 12.539 };
|
||||
//! let data: String = json::encode(&ComplexNumRecord{
|
||||
//! uid: 1,
|
||||
//! dsc: "test".to_string(),
|
||||
//! val: num.to_json(),
|
||||
//! }).unwrap();
|
||||
//! println!("data: {}", data);
|
||||
//! // data: {"uid":1,"dsc":"test","val":"0.0001+12.539i"};
|
||||
//! ```
|
||||
//!
|
||||
//! ### Verbose example of `ToJson` usage
|
||||
|
@ -164,19 +160,17 @@
|
|||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! // Serialize using `ToJson`
|
||||
//! let input_data = TestStruct {
|
||||
//! data_int: 1,
|
||||
//! data_str: "madoka".to_string(),
|
||||
//! data_vector: vec![2,3,4,5],
|
||||
//! };
|
||||
//! let json_obj: Json = input_data.to_json();
|
||||
//! let json_str: String = json_obj.to_string();
|
||||
//! // Serialize using `ToJson`
|
||||
//! let input_data = TestStruct {
|
||||
//! data_int: 1,
|
||||
//! data_str: "madoka".to_string(),
|
||||
//! data_vector: vec![2,3,4,5],
|
||||
//! };
|
||||
//! let json_obj: Json = input_data.to_json();
|
||||
//! let json_str: String = json_obj.to_string();
|
||||
//!
|
||||
//! // Deserialize like before
|
||||
//! let decoded: TestStruct = json::decode(&json_str).unwrap();
|
||||
//! }
|
||||
//! // Deserialize like before
|
||||
//! let decoded: TestStruct = json::decode(&json_str).unwrap();
|
||||
//! ```
|
||||
|
||||
use self::DecoderError::*;
|
||||
|
@ -1269,34 +1263,22 @@ impl Json {
|
|||
|
||||
/// Returns `true` if the Json value is a `Number`.
|
||||
pub fn is_number(&self) -> bool {
|
||||
match *self {
|
||||
Json::I64(_) | Json::U64(_) | Json::F64(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(*self, Json::I64(_) | Json::U64(_) | Json::F64(_))
|
||||
}
|
||||
|
||||
/// Returns `true` if the Json value is a `i64`.
|
||||
pub fn is_i64(&self) -> bool {
|
||||
match *self {
|
||||
Json::I64(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(*self, Json::I64(_))
|
||||
}
|
||||
|
||||
/// Returns `true` if the Json value is a `u64`.
|
||||
pub fn is_u64(&self) -> bool {
|
||||
match *self {
|
||||
Json::U64(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(*self, Json::U64(_))
|
||||
}
|
||||
|
||||
/// Returns `true` if the Json value is a `f64`.
|
||||
pub fn is_f64(&self) -> bool {
|
||||
match *self {
|
||||
Json::F64(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(*self, Json::F64(_))
|
||||
}
|
||||
|
||||
/// If the Json value is a number, returns or cast it to a `i64`;
|
||||
|
@ -1416,6 +1398,7 @@ enum ParserState {
|
|||
/// structure of the JSON stream.
|
||||
///
|
||||
/// An example is `foo.bar[3].x`.
|
||||
#[derive(Default)]
|
||||
pub struct Stack {
|
||||
stack: Vec<InternalStackElement>,
|
||||
str_buffer: Vec<u8>,
|
||||
|
@ -1442,7 +1425,7 @@ enum InternalStackElement {
|
|||
|
||||
impl Stack {
|
||||
pub fn new() -> Stack {
|
||||
Stack { stack: Vec::new(), str_buffer: Vec::new() }
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Returns The number of elements in the Stack.
|
||||
|
@ -1547,10 +1530,7 @@ impl Stack {
|
|||
|
||||
// Used by Parser to test whether the top-most element is an index.
|
||||
fn last_is_index(&self) -> bool {
|
||||
match self.stack.last() {
|
||||
Some(InternalIndex(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.stack.last(), Some(InternalIndex(_)))
|
||||
}
|
||||
|
||||
// Used by Parser to increment the index of the top-most element.
|
||||
|
|
|
@ -118,13 +118,13 @@ impl serialize::Encoder for Encoder {
|
|||
|
||||
#[inline]
|
||||
fn emit_f64(&mut self, v: f64) -> EncodeResult {
|
||||
let as_u64: u64 = unsafe { ::std::mem::transmute(v) };
|
||||
let as_u64: u64 = v.to_bits();
|
||||
self.emit_u64(as_u64)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn emit_f32(&mut self, v: f32) -> EncodeResult {
|
||||
let as_u32: u32 = unsafe { ::std::mem::transmute(v) };
|
||||
let as_u32: u32 = v.to_bits();
|
||||
self.emit_u32(as_u32)
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ struct RustArchiveIterator {
|
|||
};
|
||||
|
||||
enum class LLVMRustArchiveKind {
|
||||
Other,
|
||||
GNU,
|
||||
BSD,
|
||||
DARWIN,
|
||||
|
|
|
@ -311,7 +311,6 @@ static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) {
|
|||
}
|
||||
|
||||
enum class LLVMRustCodeGenOptLevel {
|
||||
Other,
|
||||
None,
|
||||
Less,
|
||||
Default,
|
||||
|
@ -597,7 +596,6 @@ extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
|
|||
}
|
||||
|
||||
enum class LLVMRustFileType {
|
||||
Other,
|
||||
AssemblyFile,
|
||||
ObjectFile,
|
||||
};
|
||||
|
|
|
@ -366,7 +366,6 @@ LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
|
|||
}
|
||||
|
||||
enum class LLVMRustSynchronizationScope {
|
||||
Other,
|
||||
SingleThread,
|
||||
CrossThread,
|
||||
};
|
||||
|
@ -389,7 +388,6 @@ LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
|
|||
}
|
||||
|
||||
enum class LLVMRustAsmDialect {
|
||||
Other,
|
||||
Att,
|
||||
Intel,
|
||||
};
|
||||
|
|
|
@ -5,6 +5,11 @@ LL | fn elision<T: Fn() -> &i32>() {
|
|||
| ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider making the bound lifetime-generic with a new `'a` lifetime
|
||||
|
|
||||
LL | fn elision<T: for<'a> Fn() -> &'a i32>() {
|
||||
| ^^^^^^^ ^^^
|
||||
help: consider using the `'static` lifetime
|
||||
|
|
||||
LL | fn elision<T: Fn() -> &'static i32>() {
|
||||
|
|
|
@ -5,6 +5,11 @@ LL | fn elision(_: fn() -> &i32) {
|
|||
| ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider making the type lifetime-generic with a new `'a` lifetime
|
||||
|
|
||||
LL | fn elision(_: for<'a> fn() -> &'a i32) {
|
||||
| ^^^^^^^ ^^^
|
||||
help: consider using the `'static` lifetime
|
||||
|
|
||||
LL | fn elision(_: fn() -> &'static i32) {
|
||||
|
|
|
@ -2,7 +2,7 @@ error: type parameters must be declared prior to const parameters
|
|||
--> $DIR/needs-feature.rs:10:26
|
||||
|
|
||||
LL | struct A<const N: usize, T=u32>(T);
|
||||
| -----------------^----- help: reorder the parameters: lifetimes, then consts, then types: `<T, const N: usize>`
|
||||
| -----------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -51,6 +51,15 @@ error[E0106]: missing lifetime specifiers
|
|||
|
|
||||
LL | buzz: Buzz,
|
||||
| ^^^^ expected 2 lifetime parameters
|
||||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | struct Quux<'a> {
|
||||
LL | baz: Baz,
|
||||
LL |
|
||||
LL |
|
||||
LL | buzz: Buzz<'a, 'a>,
|
||||
|
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
14
src/test/ui/issues/issue-74739.rs
Normal file
14
src/test/ui/issues/issue-74739.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
// compile-flags: -O
|
||||
// run-pass
|
||||
|
||||
struct Foo {
|
||||
x: i32,
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let mut foo = Foo { x: 42 };
|
||||
let x = &mut foo.x;
|
||||
*x = 13;
|
||||
let y = foo;
|
||||
assert_eq!(y.x, 13); // used to print 42 due to mir-opt bug
|
||||
}
|
|
@ -6,8 +6,8 @@ LL | type Item = IteratorChunk<T, S>;
|
|||
|
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | type Item<'a> = IteratorChunk<<'a>T, S>;
|
||||
| ^^^^ ^^^^
|
||||
LL | type Item<'a> = IteratorChunk<'a, T, S>;
|
||||
| ^^^^ ^^^
|
||||
|
||||
error: `impl` item signature doesn't match `trait` item signature
|
||||
--> $DIR/issue-74918-missing-lifetime.rs:11:5
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
trait ZstAssert: Sized {
|
||||
const A: &str = ""; //~ ERROR missing lifetime specifier
|
||||
const B: S = S { s: &() }; //~ ERROR missing lifetime specifier
|
||||
const C: &'_ str = ""; //~ ERROR missing lifetime specifier
|
||||
const D: T = T { a: &(), b: &() }; //~ ERROR missing lifetime specifier
|
||||
}
|
||||
|
||||
struct S<'a> {
|
||||
s: &'a (),
|
||||
}
|
||||
struct T<'a, 'b> {
|
||||
a: &'a (),
|
||||
b: &'b (),
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,73 @@
|
|||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/missing-lifetime-in-assoc-const-type.rs:2:14
|
||||
|
|
||||
LL | const A: &str = "";
|
||||
| ^ expected named lifetime parameter
|
||||
|
|
||||
help: consider using the `'static` lifetime
|
||||
|
|
||||
LL | const A: &'static str = "";
|
||||
| ^^^^^^^
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | trait ZstAssert<'a>: Sized {
|
||||
LL | const A: &'a str = "";
|
||||
|
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/missing-lifetime-in-assoc-const-type.rs:3:14
|
||||
|
|
||||
LL | const B: S = S { s: &() };
|
||||
| ^ expected named lifetime parameter
|
||||
|
|
||||
help: consider using the `'static` lifetime
|
||||
|
|
||||
LL | const B: S<'static> = S { s: &() };
|
||||
| ^^^^^^^^^
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | trait ZstAssert<'a>: Sized {
|
||||
LL | const A: &str = "";
|
||||
LL | const B: S<'a> = S { s: &() };
|
||||
|
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/missing-lifetime-in-assoc-const-type.rs:4:15
|
||||
|
|
||||
LL | const C: &'_ str = "";
|
||||
| ^^ expected named lifetime parameter
|
||||
|
|
||||
help: consider using the `'static` lifetime
|
||||
|
|
||||
LL | const C: &'static str = "";
|
||||
| ^^^^^^^
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | trait ZstAssert<'a>: Sized {
|
||||
LL | const A: &str = "";
|
||||
LL | const B: S = S { s: &() };
|
||||
LL | const C: &'a str = "";
|
||||
|
|
||||
|
||||
error[E0106]: missing lifetime specifiers
|
||||
--> $DIR/missing-lifetime-in-assoc-const-type.rs:5:14
|
||||
|
|
||||
LL | const D: T = T { a: &(), b: &() };
|
||||
| ^ expected 2 lifetime parameters
|
||||
|
|
||||
help: consider using the `'static` lifetime
|
||||
|
|
||||
LL | const D: T<'static, 'static> = T { a: &(), b: &() };
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
help: consider introducing a named lifetime parameter
|
||||
|
|
||||
LL | trait ZstAssert<'a>: Sized {
|
||||
LL | const A: &str = "";
|
||||
LL | const B: S = S { s: &() };
|
||||
LL | const C: &'_ str = "";
|
||||
LL | const D: T<'a, 'a> = T { a: &(), b: &() };
|
||||
|
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
15
src/test/ui/suggestions/missing-lt-for-hrtb.rs
Normal file
15
src/test/ui/suggestions/missing-lt-for-hrtb.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
struct X<'a>(&'a ());
|
||||
struct S<'a>(&'a dyn Fn(&X) -> &X);
|
||||
//~^ ERROR missing lifetime specifier
|
||||
//~| ERROR missing lifetime specifier
|
||||
struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
|
||||
//~^ ERROR missing lifetime specifier
|
||||
//~| ERROR missing lifetime specifier
|
||||
|
||||
fn main() {
|
||||
let x = S(&|x| {
|
||||
println!("hi");
|
||||
x
|
||||
});
|
||||
x.0(&X(&()));
|
||||
}
|
63
src/test/ui/suggestions/missing-lt-for-hrtb.stderr
Normal file
63
src/test/ui/suggestions/missing-lt-for-hrtb.stderr
Normal file
|
@ -0,0 +1,63 @@
|
|||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/missing-lt-for-hrtb.rs:2:32
|
||||
|
|
||||
LL | struct S<'a>(&'a dyn Fn(&X) -> &X);
|
||||
| -- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider making the bound lifetime-generic with a new `'b` lifetime
|
||||
|
|
||||
LL | struct S<'a>(&'a dyn for<'b> Fn(&'b X) -> &'b X);
|
||||
| ^^^^^^^ ^^^^^ ^^^
|
||||
help: consider using the `'a` lifetime
|
||||
|
|
||||
LL | struct S<'a>(&'a dyn Fn(&X) -> &'a X);
|
||||
| ^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/missing-lt-for-hrtb.rs:2:33
|
||||
|
|
||||
LL | struct S<'a>(&'a dyn Fn(&X) -> &X);
|
||||
| -- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from
|
||||
= note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
|
||||
help: consider making the bound lifetime-generic with a new `'b` lifetime
|
||||
|
|
||||
LL | struct S<'a>(&'a dyn for<'b> Fn(&'b X) -> &X<'b>);
|
||||
| ^^^^^^^ ^^^^^ ^^^^^
|
||||
help: consider using the `'a` lifetime
|
||||
|
|
||||
LL | struct S<'a>(&'a dyn Fn(&X) -> &X<'a>);
|
||||
| ^^^^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/missing-lt-for-hrtb.rs:5:40
|
||||
|
|
||||
LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
|
||||
| -- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from
|
||||
note: these named lifetimes are available to use
|
||||
--> $DIR/missing-lt-for-hrtb.rs:5:10
|
||||
|
|
||||
LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
|
||||
| ^^ ^^
|
||||
|
||||
error[E0106]: missing lifetime specifier
|
||||
--> $DIR/missing-lt-for-hrtb.rs:5:41
|
||||
|
|
||||
LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
|
||||
| -- ^ expected named lifetime parameter
|
||||
|
|
||||
= help: this function's return type contains a borrowed value, but the signature does not say which one of argument 1's 2 lifetimes it is borrowed from
|
||||
note: these named lifetimes are available to use
|
||||
--> $DIR/missing-lt-for-hrtb.rs:5:10
|
||||
|
|
||||
LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &X);
|
||||
| ^^ ^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0106`.
|
Loading…
Add table
Add a link
Reference in a new issue