Auto merge of #76975 - RalfJung:rollup-s2wiuqr, r=RalfJung
Rollup of 15 pull requests Successful merges: - #76732 (Add docs for `BasicBlock`) - #76832 (Let backends define custom targets) - #76866 (Remove unused feature gates from library/ crates) - #76875 (Move to intra-doc links in library/alloc/src/collections/binary_heap.rs) - #76876 (Move to intra-doc links in collections/btree/map.rs and collections/linked_list.rs) - #76877 (Move to intra-doc links in collections/vec_deque.rs and collections/vec_deque/drain.rs) - #76878 (Move the version number to a plaintext file) - #76883 (README.md: Remove prompts from code blocks) - #76887 (Add missing examples on HashSet iter types) - #76890 (use matches!() macro for simple if let conditions) - #76891 (don't take `TyCtxt` by reference) - #76910 (transmute: use diagnostic item) - #76924 (Add tracking issue for feature(unix_socket_peek)) - #76926 (BTreeMap: code readability tweaks) - #76940 (Don't allow implementing trait directly on type-alias-impl-trait) Failed merges: r? `@ghost`
This commit is contained in:
commit
81e02708f1
26
README.md
26
README.md
|
@ -44,8 +44,8 @@ by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].
|
|||
2. Clone the [source] with `git`:
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/rust-lang/rust.git
|
||||
$ cd rust
|
||||
git clone https://github.com/rust-lang/rust.git
|
||||
cd rust
|
||||
```
|
||||
|
||||
[source]: https://github.com/rust-lang/rust
|
||||
|
@ -57,7 +57,7 @@ by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].
|
|||
Copy the default `config.toml.example` to `config.toml` to get started.
|
||||
|
||||
```sh
|
||||
$ cp config.toml.example config.toml
|
||||
cp config.toml.example config.toml
|
||||
```
|
||||
|
||||
If you plan to use `x.py install` to create an installation, it is recommended
|
||||
|
@ -68,7 +68,7 @@ by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].
|
|||
4. Build and install:
|
||||
|
||||
```sh
|
||||
$ ./x.py build && ./x.py install
|
||||
./x.py build && ./x.py install
|
||||
```
|
||||
|
||||
When complete, `./x.py install` will place several programs into
|
||||
|
@ -106,7 +106,7 @@ build.
|
|||
|
||||
```sh
|
||||
# Update package mirrors (may be needed if you have a fresh install of MSYS2)
|
||||
$ pacman -Sy pacman-mirrors
|
||||
pacman -Sy pacman-mirrors
|
||||
|
||||
# Install build tools needed for Rust. If you're building a 32-bit compiler,
|
||||
# then replace "x86_64" below with "i686". If you've already got git, python,
|
||||
|
@ -114,7 +114,7 @@ build.
|
|||
# that it is important that you do **not** use the 'python2', 'cmake' and 'ninja'
|
||||
# packages from the 'msys2' subsystem. The build has historically been known
|
||||
# to fail with these packages.
|
||||
$ pacman -S git \
|
||||
pacman -S git \
|
||||
make \
|
||||
diffutils \
|
||||
tar \
|
||||
|
@ -127,7 +127,7 @@ build.
|
|||
4. Navigate to Rust's source code (or clone it), then build it:
|
||||
|
||||
```sh
|
||||
$ ./x.py build && ./x.py install
|
||||
./x.py build && ./x.py install
|
||||
```
|
||||
|
||||
#### MSVC
|
||||
|
@ -145,7 +145,7 @@ With these dependencies installed, you can build the compiler in a `cmd.exe`
|
|||
shell with:
|
||||
|
||||
```sh
|
||||
> python x.py build
|
||||
python x.py build
|
||||
```
|
||||
|
||||
Currently, building Rust only works with some known versions of Visual Studio. If
|
||||
|
@ -154,8 +154,8 @@ you may need to force rustbuild to use an older version. This can be done
|
|||
by manually calling the appropriate vcvars file before running the bootstrap.
|
||||
|
||||
```batch
|
||||
> CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
> python x.py build
|
||||
CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
python x.py build
|
||||
```
|
||||
|
||||
#### Specifying an ABI
|
||||
|
@ -181,8 +181,8 @@ While it's not the recommended build system, this project also provides a
|
|||
configure script and makefile (the latter of which just invokes `x.py`).
|
||||
|
||||
```sh
|
||||
$ ./configure
|
||||
$ make && sudo make install
|
||||
./configure
|
||||
make && sudo make install
|
||||
```
|
||||
|
||||
When using the configure script, the generated `config.mk` file may override the
|
||||
|
@ -194,7 +194,7 @@ When using the configure script, the generated `config.mk` file may override the
|
|||
If you’d like to build the documentation, it’s almost the same:
|
||||
|
||||
```sh
|
||||
$ ./x.py doc
|
||||
./x.py doc
|
||||
```
|
||||
|
||||
The generated documentation will appear under `doc` in the `build` directory for
|
||||
|
|
|
@ -1931,7 +1931,7 @@ pub enum TyKind {
|
|||
|
||||
impl TyKind {
|
||||
pub fn is_implicit_self(&self) -> bool {
|
||||
if let TyKind::ImplicitSelf = *self { true } else { false }
|
||||
matches!(self, TyKind::ImplicitSelf)
|
||||
}
|
||||
|
||||
pub fn is_unit(&self) -> bool {
|
||||
|
@ -2227,7 +2227,7 @@ pub enum Async {
|
|||
|
||||
impl Async {
|
||||
pub fn is_async(self) -> bool {
|
||||
if let Async::Yes { .. } = self { true } else { false }
|
||||
matches!(self, Async::Yes { .. })
|
||||
}
|
||||
|
||||
/// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
|
||||
|
@ -2508,7 +2508,7 @@ pub enum VisibilityKind {
|
|||
|
||||
impl VisibilityKind {
|
||||
pub fn is_pub(&self) -> bool {
|
||||
if let VisibilityKind::Public = *self { true } else { false }
|
||||
matches!(self, VisibilityKind::Public)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -868,10 +868,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
.emit();
|
||||
}
|
||||
|
||||
if !bounds
|
||||
.iter()
|
||||
.any(|b| if let GenericBound::Trait(..) = *b { true } else { false })
|
||||
{
|
||||
if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) {
|
||||
self.err_handler().span_err(ty.span, "at least one trait must be specified");
|
||||
}
|
||||
|
||||
|
|
|
@ -160,10 +160,10 @@ pub enum StabilityLevel {
|
|||
|
||||
impl StabilityLevel {
|
||||
pub fn is_unstable(&self) -> bool {
|
||||
if let StabilityLevel::Unstable { .. } = *self { true } else { false }
|
||||
matches!(self, StabilityLevel::Unstable { .. })
|
||||
}
|
||||
pub fn is_stable(&self) -> bool {
|
||||
if let StabilityLevel::Stable { .. } = *self { true } else { false }
|
||||
matches!(self, StabilityLevel::Stable { .. })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1529,7 +1529,7 @@ impl<'a> TraitDef<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let is_tuple = if let ast::VariantData::Tuple(..) = struct_def { true } else { false };
|
||||
let is_tuple = matches!(struct_def, ast::VariantData::Tuple(..));
|
||||
match (just_spans.is_empty(), named_idents.is_empty()) {
|
||||
(false, false) => cx.span_bug(
|
||||
self.span,
|
||||
|
|
|
@ -15,6 +15,7 @@ use rustc_session::{
|
|||
};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::abi::LayoutOf;
|
||||
use rustc_target::spec::Target;
|
||||
|
||||
pub use rustc_data_structures::sync::MetadataRef;
|
||||
|
||||
|
@ -54,6 +55,12 @@ pub trait CodegenBackend {
|
|||
fn print_passes(&self) {}
|
||||
fn print_version(&self) {}
|
||||
|
||||
/// If this plugin provides additional builtin targets, provide the one enabled by the options here.
|
||||
/// Be careful: this is called *before* init() is called.
|
||||
fn target_override(&self, _opts: &config::Options) -> Option<Target> {
|
||||
None
|
||||
}
|
||||
|
||||
fn metadata_loader(&self) -> Box<MetadataLoaderDyn>;
|
||||
fn provide(&self, _providers: &mut Providers);
|
||||
fn provide_extern(&self, _providers: &mut Providers);
|
||||
|
|
|
@ -118,17 +118,15 @@ pub struct Annotation {
|
|||
impl Annotation {
|
||||
/// Whether this annotation is a vertical line placeholder.
|
||||
pub fn is_line(&self) -> bool {
|
||||
if let AnnotationType::MultilineLine(_) = self.annotation_type { true } else { false }
|
||||
matches!(self.annotation_type, AnnotationType::MultilineLine(_))
|
||||
}
|
||||
|
||||
pub fn is_multiline(&self) -> bool {
|
||||
match self.annotation_type {
|
||||
matches!(self.annotation_type,
|
||||
AnnotationType::Multiline(_)
|
||||
| AnnotationType::MultilineStart(_)
|
||||
| AnnotationType::MultilineLine(_)
|
||||
| AnnotationType::MultilineEnd(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
| AnnotationType::MultilineEnd(_))
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
|
|
|
@ -40,6 +40,7 @@ fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) {
|
|||
DiagnosticOutput::Default,
|
||||
Default::default(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
(sess, cfg)
|
||||
}
|
||||
|
|
|
@ -65,6 +65,10 @@ pub fn create_session(
|
|||
lint_caps: FxHashMap<lint::LintId, lint::Level>,
|
||||
descriptions: Registry,
|
||||
) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>) {
|
||||
let codegen_backend = get_codegen_backend(&sopts);
|
||||
// target_override is documented to be called before init(), so this is okay
|
||||
let target_override = codegen_backend.target_override(&sopts);
|
||||
|
||||
let mut sess = session::build_session(
|
||||
sopts,
|
||||
input_path,
|
||||
|
@ -72,9 +76,10 @@ pub fn create_session(
|
|||
diagnostic_output,
|
||||
lint_caps,
|
||||
file_loader,
|
||||
target_override,
|
||||
);
|
||||
|
||||
let codegen_backend = get_codegen_backend(&sess);
|
||||
codegen_backend.init(&sess);
|
||||
|
||||
let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg));
|
||||
add_configuration(&mut cfg, &mut sess, &*codegen_backend);
|
||||
|
@ -219,13 +224,13 @@ fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> {
|
||||
pub fn get_codegen_backend(sopts: &config::Options) -> Box<dyn CodegenBackend> {
|
||||
static INIT: Once = Once::new();
|
||||
|
||||
static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();
|
||||
|
||||
INIT.call_once(|| {
|
||||
let codegen_name = sess.opts.debugging_opts.codegen_backend.as_deref().unwrap_or("llvm");
|
||||
let codegen_name = sopts.debugging_opts.codegen_backend.as_deref().unwrap_or("llvm");
|
||||
let backend = match codegen_name {
|
||||
filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()),
|
||||
codegen_name => get_builtin_codegen_backend(codegen_name),
|
||||
|
@ -235,9 +240,7 @@ pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> {
|
|||
LOAD = backend;
|
||||
}
|
||||
});
|
||||
let backend = unsafe { LOAD() };
|
||||
backend.init(sess);
|
||||
backend
|
||||
unsafe { LOAD() }
|
||||
}
|
||||
|
||||
// This is used for rustdoc, but it uses similar machinery to codegen backend
|
||||
|
|
|
@ -1984,9 +1984,9 @@ impl ExplicitOutlivesRequirements {
|
|||
.filter_map(|(i, bound)| {
|
||||
if let hir::GenericBound::Outlives(lifetime) = bound {
|
||||
let is_inferred = match tcx.named_region(lifetime.hir_id) {
|
||||
Some(Region::Static) if infer_static => inferred_outlives
|
||||
.iter()
|
||||
.any(|r| if let ty::ReStatic = r { true } else { false }),
|
||||
Some(Region::Static) if infer_static => {
|
||||
inferred_outlives.iter().any(|r| matches!(r, ty::ReStatic))
|
||||
}
|
||||
Some(Region::EarlyBound(index, ..)) => inferred_outlives.iter().any(|r| {
|
||||
if let ty::ReEarlyBound(ebr) = r { ebr.index == index } else { false }
|
||||
}),
|
||||
|
@ -2078,9 +2078,10 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
|
|||
let mut lint_spans = Vec::new();
|
||||
|
||||
for param in hir_generics.params {
|
||||
let has_lifetime_bounds = param.bounds.iter().any(|bound| {
|
||||
if let hir::GenericBound::Outlives(_) = bound { true } else { false }
|
||||
});
|
||||
let has_lifetime_bounds = param
|
||||
.bounds
|
||||
.iter()
|
||||
.any(|bound| matches!(bound, hir::GenericBound::Outlives(_)));
|
||||
if !has_lifetime_bounds {
|
||||
continue;
|
||||
}
|
||||
|
@ -2349,13 +2350,6 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
|||
|
||||
/// Determine if this expression is a "dangerous initialization".
|
||||
fn is_dangerous_init(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<InitKind> {
|
||||
// `transmute` is inside an anonymous module (the `extern` block?);
|
||||
// `Invalid` represents the empty string and matches that.
|
||||
// FIXME(#66075): use diagnostic items. Somehow, that does not seem to work
|
||||
// on intrinsics right now.
|
||||
const TRANSMUTE_PATH: &[Symbol] =
|
||||
&[sym::core, sym::intrinsics, kw::Invalid, sym::transmute];
|
||||
|
||||
if let hir::ExprKind::Call(ref path_expr, ref args) = expr.kind {
|
||||
// Find calls to `mem::{uninitialized,zeroed}` methods.
|
||||
if let hir::ExprKind::Path(ref qpath) = path_expr.kind {
|
||||
|
@ -2365,7 +2359,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
|
|||
return Some(InitKind::Zeroed);
|
||||
} else if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, def_id) {
|
||||
return Some(InitKind::Uninit);
|
||||
} else if cx.match_def_path(def_id, TRANSMUTE_PATH) {
|
||||
} else if cx.tcx.is_diagnostic_item(sym::transmute, def_id) {
|
||||
if is_zero(&args[0]) {
|
||||
return Some(InitKind::Zeroed);
|
||||
}
|
||||
|
|
|
@ -720,6 +720,10 @@ impl<'tcx> LateContext<'tcx> {
|
|||
/// Anonymous scopes such as `extern` imports are matched with `kw::Invalid`;
|
||||
/// inherent `impl` blocks are matched with the name of the type.
|
||||
///
|
||||
/// Instead of using this method, it is often preferable to instead use
|
||||
/// `rustc_diagnostic_item` or a `lang_item`. This is less prone to errors
|
||||
/// as paths get invalidated if the target definition moves.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust,ignore (no context or def id available)
|
||||
|
|
|
@ -69,7 +69,7 @@ pub enum LibSource {
|
|||
|
||||
impl LibSource {
|
||||
pub fn is_some(&self) -> bool {
|
||||
if let LibSource::Some(_) = *self { true } else { false }
|
||||
matches!(self, LibSource::Some(_))
|
||||
}
|
||||
|
||||
pub fn option(&self) -> Option<PathBuf> {
|
||||
|
|
|
@ -17,7 +17,7 @@ use rustc_target::spec::PanicStrategy;
|
|||
impl<'tcx> TyCtxt<'tcx> {
|
||||
/// Returns the `DefId` for a given `LangItem`.
|
||||
/// If not found, fatally aborts compilation.
|
||||
pub fn require_lang_item(&self, lang_item: LangItem, span: Option<Span>) -> DefId {
|
||||
pub fn require_lang_item(self, lang_item: LangItem, span: Option<Span>) -> DefId {
|
||||
self.lang_items().require(lang_item).unwrap_or_else(|msg| {
|
||||
if let Some(span) = span {
|
||||
self.sess.span_fatal(span, &msg)
|
||||
|
@ -27,7 +27,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn fn_trait_kind_from_lang_item(&self, id: DefId) -> Option<ty::ClosureKind> {
|
||||
pub fn fn_trait_kind_from_lang_item(self, id: DefId) -> Option<ty::ClosureKind> {
|
||||
let items = self.lang_items();
|
||||
match Some(id) {
|
||||
x if x == items.fn_trait() => Some(ty::ClosureKind::Fn),
|
||||
|
@ -37,7 +37,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_weak_lang_item(&self, item_def_id: DefId) -> bool {
|
||||
pub fn is_weak_lang_item(self, item_def_id: DefId) -> bool {
|
||||
self.lang_items().is_weak_lang_item(item_def_id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -447,14 +447,14 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
///
|
||||
/// Make sure to call `set_alloc_id_memory` or `set_alloc_id_same_memory` before returning such
|
||||
/// an `AllocId` from a query.
|
||||
pub fn reserve_alloc_id(&self) -> AllocId {
|
||||
pub fn reserve_alloc_id(self) -> AllocId {
|
||||
self.alloc_map.lock().reserve()
|
||||
}
|
||||
|
||||
/// Reserves a new ID *if* this allocation has not been dedup-reserved before.
|
||||
/// Should only be used for function pointers and statics, we don't want
|
||||
/// to dedup IDs for "real" memory!
|
||||
fn reserve_and_set_dedup(&self, alloc: GlobalAlloc<'tcx>) -> AllocId {
|
||||
fn reserve_and_set_dedup(self, alloc: GlobalAlloc<'tcx>) -> AllocId {
|
||||
let mut alloc_map = self.alloc_map.lock();
|
||||
match alloc {
|
||||
GlobalAlloc::Function(..) | GlobalAlloc::Static(..) => {}
|
||||
|
@ -472,13 +472,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
/// Generates an `AllocId` for a static or return a cached one in case this function has been
|
||||
/// called on the same static before.
|
||||
pub fn create_static_alloc(&self, static_id: DefId) -> AllocId {
|
||||
pub fn create_static_alloc(self, static_id: DefId) -> AllocId {
|
||||
self.reserve_and_set_dedup(GlobalAlloc::Static(static_id))
|
||||
}
|
||||
|
||||
/// Generates an `AllocId` for a function. Depending on the function type,
|
||||
/// this might get deduplicated or assigned a new ID each time.
|
||||
pub fn create_fn_alloc(&self, instance: Instance<'tcx>) -> AllocId {
|
||||
pub fn create_fn_alloc(self, instance: Instance<'tcx>) -> AllocId {
|
||||
// Functions cannot be identified by pointers, as asm-equal functions can get deduplicated
|
||||
// by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be
|
||||
// duplicated across crates.
|
||||
|
@ -507,7 +507,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// Statics with identical content will still point to the same `Allocation`, i.e.,
|
||||
/// their data will be deduplicated through `Allocation` interning -- but they
|
||||
/// are different places in memory and as such need different IDs.
|
||||
pub fn create_memory_alloc(&self, mem: &'tcx Allocation) -> AllocId {
|
||||
pub fn create_memory_alloc(self, mem: &'tcx Allocation) -> AllocId {
|
||||
let id = self.reserve_alloc_id();
|
||||
self.set_alloc_id_memory(id, mem);
|
||||
id
|
||||
|
@ -519,7 +519,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// This function exists to allow const eval to detect the difference between evaluation-
|
||||
/// local dangling pointers and allocations in constants/statics.
|
||||
#[inline]
|
||||
pub fn get_global_alloc(&self, id: AllocId) -> Option<GlobalAlloc<'tcx>> {
|
||||
pub fn get_global_alloc(self, id: AllocId) -> Option<GlobalAlloc<'tcx>> {
|
||||
self.alloc_map.lock().alloc_map.get(&id).cloned()
|
||||
}
|
||||
|
||||
|
@ -529,7 +529,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// constants (as all constants must pass interning and validation that check for dangling
|
||||
/// ids), this function is frequently used throughout rustc, but should not be used within
|
||||
/// the miri engine.
|
||||
pub fn global_alloc(&self, id: AllocId) -> GlobalAlloc<'tcx> {
|
||||
pub fn global_alloc(self, id: AllocId) -> GlobalAlloc<'tcx> {
|
||||
match self.get_global_alloc(id) {
|
||||
Some(alloc) => alloc,
|
||||
None => bug!("could not find allocation for {}", id),
|
||||
|
@ -538,7 +538,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
/// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
|
||||
/// call this function twice, even with the same `Allocation` will ICE the compiler.
|
||||
pub fn set_alloc_id_memory(&self, id: AllocId, mem: &'tcx Allocation) {
|
||||
pub fn set_alloc_id_memory(self, id: AllocId, mem: &'tcx Allocation) {
|
||||
if let Some(old) = self.alloc_map.lock().alloc_map.insert(id, GlobalAlloc::Memory(mem)) {
|
||||
bug!("tried to set allocation ID {}, but it was already existing as {:#?}", id, old);
|
||||
}
|
||||
|
@ -546,7 +546,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
/// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called
|
||||
/// twice for the same `(AllocId, Allocation)` pair.
|
||||
fn set_alloc_id_same_memory(&self, id: AllocId, mem: &'tcx Allocation) {
|
||||
fn set_alloc_id_same_memory(self, id: AllocId, mem: &'tcx Allocation) {
|
||||
self.alloc_map.lock().alloc_map.insert_same(id, GlobalAlloc::Memory(mem));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1077,6 +1077,25 @@ pub struct VarDebugInfo<'tcx> {
|
|||
// BasicBlock
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
/// A node in the MIR [control-flow graph][CFG].
|
||||
///
|
||||
/// There are no branches (e.g., `if`s, function calls, etc.) within a basic block, which makes
|
||||
/// it easier to do [data-flow analyses] and optimizations. Instead, branches are represented
|
||||
/// as an edge in a graph between basic blocks.
|
||||
///
|
||||
/// Basic blocks consist of a series of [statements][Statement], ending with a
|
||||
/// [terminator][Terminator]. Basic blocks can have multiple predecessors and successors,
|
||||
/// however there is a MIR pass ([`CriticalCallEdges`]) that removes *critical edges*, which
|
||||
/// are edges that go from a multi-successor node to a multi-predecessor node. This pass is
|
||||
/// needed because some analyses require that there are no critical edges in the CFG.
|
||||
///
|
||||
/// Read more about basic blocks in the [rustc-dev-guide][guide-mir].
|
||||
///
|
||||
/// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg
|
||||
/// [data-flow analyses]:
|
||||
/// https://rustc-dev-guide.rust-lang.org/appendix/background.html#what-is-a-dataflow-analysis
|
||||
/// [`CriticalCallEdges`]: ../../rustc_mir/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
|
||||
/// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/
|
||||
pub struct BasicBlock {
|
||||
derive [HashStable]
|
||||
DEBUG_FORMAT = "bb{}",
|
||||
|
@ -1093,6 +1112,7 @@ impl BasicBlock {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// BasicBlockData and Terminator
|
||||
|
||||
/// See [`BasicBlock`] for documentation on what basic blocks are at a high level.
|
||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
|
||||
pub struct BasicBlockData<'tcx> {
|
||||
/// List of statements in this block.
|
||||
|
|
|
@ -1403,7 +1403,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
// Returns the `DefId` and the `BoundRegion` corresponding to the given region.
|
||||
pub fn is_suitable_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
|
||||
pub fn is_suitable_region(self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
|
||||
let (suitable_region_binding_scope, bound_region) = match *region {
|
||||
ty::ReFree(ref free_region) => {
|
||||
(free_region.scope.expect_local(), free_region.bound_region)
|
||||
|
@ -1433,7 +1433,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
/// Given a `DefId` for an `fn`, return all the `dyn` and `impl` traits in its return type.
|
||||
pub fn return_type_impl_or_dyn_traits(
|
||||
&self,
|
||||
self,
|
||||
scope_def_id: LocalDefId,
|
||||
) -> Vec<&'tcx hir::Ty<'tcx>> {
|
||||
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
|
||||
|
@ -1479,7 +1479,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
v.0
|
||||
}
|
||||
|
||||
pub fn return_type_impl_trait(&self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
|
||||
pub fn return_type_impl_trait(self, scope_def_id: LocalDefId) -> Option<(Ty<'tcx>, Span)> {
|
||||
// HACK: `type_of_def_id()` will fail on these (#55796), so return `None`.
|
||||
let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
|
||||
match self.hir().get(hir_id) {
|
||||
|
@ -1497,7 +1497,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
let ret_ty = self.type_of(scope_def_id);
|
||||
match ret_ty.kind() {
|
||||
ty::FnDef(_, _) => {
|
||||
let sig = ret_ty.fn_sig(*self);
|
||||
let sig = ret_ty.fn_sig(self);
|
||||
let output = self.erase_late_bound_regions(&sig.output());
|
||||
if output.is_impl_trait() {
|
||||
let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
|
||||
|
@ -1511,7 +1511,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
// Checks if the bound region is in Impl Item.
|
||||
pub fn is_bound_region_in_impl_item(&self, suitable_region_binding_scope: LocalDefId) -> bool {
|
||||
pub fn is_bound_region_in_impl_item(self, suitable_region_binding_scope: LocalDefId) -> bool {
|
||||
let container_id =
|
||||
self.associated_item(suitable_region_binding_scope.to_def_id()).container.id();
|
||||
if self.impl_trait_ref(container_id).is_some() {
|
||||
|
@ -1528,21 +1528,21 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
/// Determines whether identifiers in the assembly have strict naming rules.
|
||||
/// Currently, only NVPTX* targets need it.
|
||||
pub fn has_strict_asm_symbol_naming(&self) -> bool {
|
||||
pub fn has_strict_asm_symbol_naming(self) -> bool {
|
||||
self.sess.target.target.arch.contains("nvptx")
|
||||
}
|
||||
|
||||
/// Returns `&'static core::panic::Location<'static>`.
|
||||
pub fn caller_location_ty(&self) -> Ty<'tcx> {
|
||||
pub fn caller_location_ty(self) -> Ty<'tcx> {
|
||||
self.mk_imm_ref(
|
||||
self.lifetimes.re_static,
|
||||
self.type_of(self.require_lang_item(LangItem::PanicLocation, None))
|
||||
.subst(*self, self.mk_substs([self.lifetimes.re_static.into()].iter())),
|
||||
.subst(self, self.mk_substs([self.lifetimes.re_static.into()].iter())),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`).
|
||||
pub fn article_and_description(&self, def_id: DefId) -> (&'static str, &'static str) {
|
||||
pub fn article_and_description(self, def_id: DefId) -> (&'static str, &'static str) {
|
||||
match self.def_kind(def_id) {
|
||||
DefKind::Generator => match self.generator_kind(def_id).unwrap() {
|
||||
rustc_hir::GeneratorKind::Async(..) => ("an", "async closure"),
|
||||
|
|
|
@ -546,7 +546,7 @@ impl<T> Trait<T> for X {
|
|||
}
|
||||
|
||||
fn suggest_constraint(
|
||||
&self,
|
||||
self,
|
||||
db: &mut DiagnosticBuilder<'_>,
|
||||
msg: &str,
|
||||
body_owner_def_id: DefId,
|
||||
|
@ -554,14 +554,14 @@ impl<T> Trait<T> for X {
|
|||
ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
let assoc = self.associated_item(proj_ty.item_def_id);
|
||||
let trait_ref = proj_ty.trait_ref(*self);
|
||||
let trait_ref = proj_ty.trait_ref(self);
|
||||
if let Some(item) = self.hir().get_if_local(body_owner_def_id) {
|
||||
if let Some(hir_generics) = item.generics() {
|
||||
// Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
|
||||
// This will also work for `impl Trait`.
|
||||
let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
|
||||
let generics = self.generics_of(body_owner_def_id);
|
||||
generics.type_param(¶m_ty, *self).def_id
|
||||
generics.type_param(param_ty, self).def_id
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
|
@ -629,7 +629,7 @@ impl<T> Trait<T> for X {
|
|||
/// and the `impl`, we provide a generic `help` to constrain the assoc type or call an assoc
|
||||
/// fn that returns the type.
|
||||
fn expected_projection(
|
||||
&self,
|
||||
self,
|
||||
db: &mut DiagnosticBuilder<'_>,
|
||||
proj_ty: &ty::ProjectionTy<'tcx>,
|
||||
values: &ExpectedFound<Ty<'tcx>>,
|
||||
|
@ -734,7 +734,7 @@ fn foo(&self) -> Self::T { String::new() }
|
|||
}
|
||||
|
||||
fn point_at_methods_that_satisfy_associated_type(
|
||||
&self,
|
||||
self,
|
||||
db: &mut DiagnosticBuilder<'_>,
|
||||
assoc_container_id: DefId,
|
||||
current_method_ident: Option<Symbol>,
|
||||
|
@ -789,7 +789,7 @@ fn foo(&self) -> Self::T { String::new() }
|
|||
}
|
||||
|
||||
fn point_at_associated_type(
|
||||
&self,
|
||||
self,
|
||||
db: &mut DiagnosticBuilder<'_>,
|
||||
body_owner_def_id: DefId,
|
||||
found: Ty<'tcx>,
|
||||
|
|
|
@ -623,7 +623,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// Replaces any late-bound regions bound in `value` with
|
||||
/// free variants attached to `all_outlive_scope`.
|
||||
pub fn liberate_late_bound_regions<T>(
|
||||
&self,
|
||||
self,
|
||||
all_outlive_scope: DefId,
|
||||
value: &ty::Binder<T>,
|
||||
) -> T
|
||||
|
@ -644,7 +644,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
/// variables and equate `value` with something else, those
|
||||
/// variables will also be equated.
|
||||
pub fn collect_constrained_late_bound_regions<T>(
|
||||
&self,
|
||||
self,
|
||||
value: &Binder<T>,
|
||||
) -> FxHashSet<ty::BoundRegion>
|
||||
where
|
||||
|
@ -655,7 +655,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
|
||||
/// Returns a set of all late-bound regions that appear in `value` anywhere.
|
||||
pub fn collect_referenced_late_bound_regions<T>(
|
||||
&self,
|
||||
self,
|
||||
value: &Binder<T>,
|
||||
) -> FxHashSet<ty::BoundRegion>
|
||||
where
|
||||
|
@ -665,7 +665,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
fn collect_late_bound_regions<T>(
|
||||
&self,
|
||||
self,
|
||||
value: &Binder<T>,
|
||||
just_constraint: bool,
|
||||
) -> FxHashSet<ty::BoundRegion>
|
||||
|
|
|
@ -170,9 +170,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
});
|
||||
hasher.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TyCtxt<'tcx> {
|
||||
pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
|
||||
if let ty::Adt(def, substs) = *ty.kind() {
|
||||
for field in def.all_fields() {
|
||||
|
@ -526,22 +524,22 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
|
||||
/// Returns `true` if the node pointed to by `def_id` is a `static` item.
|
||||
pub fn is_static(&self, def_id: DefId) -> bool {
|
||||
pub fn is_static(self, def_id: DefId) -> bool {
|
||||
self.static_mutability(def_id).is_some()
|
||||
}
|
||||
|
||||
/// Returns `true` if this is a `static` item with the `#[thread_local]` attribute.
|
||||
pub fn is_thread_local_static(&self, def_id: DefId) -> bool {
|
||||
pub fn is_thread_local_static(self, def_id: DefId) -> bool {
|
||||
self.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL)
|
||||
}
|
||||
|
||||
/// Returns `true` if the node pointed to by `def_id` is a mutable `static` item.
|
||||
pub fn is_mutable_static(&self, def_id: DefId) -> bool {
|
||||
pub fn is_mutable_static(self, def_id: DefId) -> bool {
|
||||
self.static_mutability(def_id) == Some(hir::Mutability::Mut)
|
||||
}
|
||||
|
||||
/// Get the type of the pointer to the static that we use in MIR.
|
||||
pub fn static_ptr_ty(&self, def_id: DefId) -> Ty<'tcx> {
|
||||
pub fn static_ptr_ty(self, def_id: DefId) -> Ty<'tcx> {
|
||||
// Make sure that any constants in the static's type are evaluated.
|
||||
let static_ty = self.normalize_erasing_regions(ty::ParamEnv::empty(), self.type_of(def_id));
|
||||
|
||||
|
|
|
@ -115,9 +115,10 @@ impl OutlivesSuggestionBuilder {
|
|||
// should just replace 'a with 'static.
|
||||
// 3) Suggest unifying 'a with 'b if we have both 'a: 'b and 'b: 'a
|
||||
|
||||
if outlived.iter().any(|(_, outlived_name)| {
|
||||
if let RegionNameSource::Static = outlived_name.source { true } else { false }
|
||||
}) {
|
||||
if outlived
|
||||
.iter()
|
||||
.any(|(_, outlived_name)| matches!(outlived_name.source, RegionNameSource::Static))
|
||||
{
|
||||
suggested.push(SuggestedConstraint::Static(fr_name));
|
||||
} else {
|
||||
// We want to isolate out all lifetimes that should be unified and print out
|
||||
|
|
|
@ -92,7 +92,7 @@ pub enum TempState {
|
|||
impl TempState {
|
||||
pub fn is_promotable(&self) -> bool {
|
||||
debug!("is_promotable: self={:?}", self);
|
||||
if let TempState::Defined { .. } = *self { true } else { false }
|
||||
matches!(self, TempState::Defined { .. } )
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -281,8 +281,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
|
|||
|
||||
fn strip_nops(&mut self) {
|
||||
for blk in self.basic_blocks.iter_mut() {
|
||||
blk.statements
|
||||
.retain(|stmt| if let StatementKind::Nop = stmt.kind { false } else { true })
|
||||
blk.statements.retain(|stmt| !matches!(stmt.kind, StatementKind::Nop))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,8 +96,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
StmtKind::Let { remainder_scope, init_scope, pattern, initializer, lint_level } => {
|
||||
let ignores_expr_result =
|
||||
if let PatKind::Wild = *pattern.kind { true } else { false };
|
||||
let ignores_expr_result = matches!(*pattern.kind, PatKind::Wild);
|
||||
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
|
||||
|
||||
// Enter the remainder scope, i.e., the bindings' destruction scope.
|
||||
|
|
|
@ -1793,7 +1793,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
.flat_map(|(bindings, _)| bindings)
|
||||
.chain(&candidate.bindings)
|
||||
.filter(|binding| {
|
||||
if let BindingMode::ByValue = binding.binding_mode { true } else { false }
|
||||
matches!(binding.binding_mode, BindingMode::ByValue )
|
||||
});
|
||||
// Read all of the by reference bindings to ensure that the
|
||||
// place they refer to can't be modified by the guard.
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
|
||||
struct DiagnosticItemCollector<'tcx> {
|
||||
|
@ -100,6 +100,18 @@ fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> FxHashMap<Symbol, DefId> {
|
|||
|
||||
// Collect diagnostic items in this crate.
|
||||
tcx.hir().krate().visit_all_item_likes(&mut collector);
|
||||
// FIXME(visit_all_item_likes): Foreign items are not visited
|
||||
// here, so we have to manually look at them for now.
|
||||
for foreign_module in tcx.foreign_modules(LOCAL_CRATE) {
|
||||
for &foreign_item in foreign_module.foreign_items.iter() {
|
||||
match tcx.hir().get(tcx.hir().local_def_id_to_hir_id(foreign_item.expect_local())) {
|
||||
hir::Node::ForeignItem(item) => {
|
||||
collector.observe_item(item.attrs, item.hir_id);
|
||||
}
|
||||
item => bug!("unexpected foreign item {:?}", item),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
collector.items
|
||||
}
|
||||
|
|
|
@ -395,7 +395,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
|||
// so prefixes are prepended with crate root segment if necessary.
|
||||
// The root is prepended lazily, when the first non-empty prefix or terminating glob
|
||||
// appears, so imports in braced groups can have roots prepended independently.
|
||||
let is_glob = if let ast::UseTreeKind::Glob = use_tree.kind { true } else { false };
|
||||
let is_glob = matches!(use_tree.kind, ast::UseTreeKind::Glob);
|
||||
let crate_root = match prefix_iter.peek() {
|
||||
Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.rust_2015() => {
|
||||
Some(seg.ident.span.ctxt())
|
||||
|
|
|
@ -1034,7 +1034,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
let mut add_bindings_for_ns = |ns| {
|
||||
let parent_rib = self.ribs[ns]
|
||||
.iter()
|
||||
.rfind(|r| if let ItemRibKind(_) = r.kind { true } else { false })
|
||||
.rfind(|r| matches!(r.kind, ItemRibKind(_)))
|
||||
.expect("associated item outside of an item");
|
||||
seen_bindings
|
||||
.extend(parent_rib.bindings.iter().map(|(ident, _)| (*ident, ident.span)));
|
||||
|
|
|
@ -818,10 +818,11 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo
|
|||
user_cfg
|
||||
}
|
||||
|
||||
pub fn build_target_config(opts: &Options, error_format: ErrorOutputType) -> Config {
|
||||
let target = Target::search(&opts.target_triple).unwrap_or_else(|e| {
|
||||
pub fn build_target_config(opts: &Options, target_override: Option<Target>) -> Config {
|
||||
let target_result = target_override.map_or_else(|| Target::search(&opts.target_triple), Ok);
|
||||
let target = target_result.unwrap_or_else(|e| {
|
||||
early_error(
|
||||
error_format,
|
||||
opts.error_format,
|
||||
&format!(
|
||||
"Error loading target specification: {}. \
|
||||
Use `--print target-list` for a list of built-in targets",
|
||||
|
@ -835,7 +836,7 @@ pub fn build_target_config(opts: &Options, error_format: ErrorOutputType) -> Con
|
|||
"32" => 32,
|
||||
"64" => 64,
|
||||
w => early_error(
|
||||
error_format,
|
||||
opts.error_format,
|
||||
&format!(
|
||||
"target specification was invalid: \
|
||||
unrecognized target-pointer-width {}",
|
||||
|
|
|
@ -1234,6 +1234,7 @@ pub fn build_session(
|
|||
diagnostics_output: DiagnosticOutput,
|
||||
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
|
||||
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
|
||||
target_override: Option<Target>,
|
||||
) -> Session {
|
||||
// FIXME: This is not general enough to make the warning lint completely override
|
||||
// normal diagnostic warnings, since the warning lint can also be denied and changed
|
||||
|
@ -1253,7 +1254,7 @@ pub fn build_session(
|
|||
DiagnosticOutput::Raw(write) => Some(write),
|
||||
};
|
||||
|
||||
let target_cfg = config::build_target_config(&sopts, sopts.error_format);
|
||||
let target_cfg = config::build_target_config(&sopts, target_override);
|
||||
let host_triple = TargetTriple::from_triple(config::host_triple());
|
||||
let host = Target::search(&host_triple).unwrap_or_else(|e| {
|
||||
early_error(sopts.error_format, &format!("Error loading host specification: {}", e))
|
||||
|
|
|
@ -439,9 +439,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// This is maybe too permissive, since it allows
|
||||
// `let u = &raw const Box::new((1,)).0`, which creates an
|
||||
// immediately dangling raw pointer.
|
||||
self.typeck_results.borrow().adjustments().get(base.hir_id).map_or(false, |x| {
|
||||
x.iter().any(|adj| if let Adjust::Deref(_) = adj.kind { true } else { false })
|
||||
})
|
||||
self.typeck_results
|
||||
.borrow()
|
||||
.adjustments()
|
||||
.get(base.hir_id)
|
||||
.map_or(false, |x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_))))
|
||||
});
|
||||
if !is_named {
|
||||
self.tcx.sess.emit_err(AddressOfTemporaryTaken { span: oprnd.span })
|
||||
|
|
|
@ -230,6 +230,14 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if let ty::Opaque(def_id, _) = *trait_ref.self_ty().kind() {
|
||||
self.tcx
|
||||
.sess
|
||||
.struct_span_err(sp, "cannot implement trait on type alias impl trait")
|
||||
.span_note(self.tcx.def_span(def_id), "type alias impl trait defined here")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
//! [dijkstra]: https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
||||
//! [sssp]: https://en.wikipedia.org/wiki/Shortest_path_problem
|
||||
//! [dir_graph]: https://en.wikipedia.org/wiki/Directed_graph
|
||||
//! [`BinaryHeap`]: struct.BinaryHeap.html
|
||||
//!
|
||||
//! ```
|
||||
//! use std::cmp::Ordering;
|
||||
|
@ -240,10 +239,10 @@ use super::SpecExtend;
|
|||
/// The value for `push` is an expected cost; the method documentation gives a
|
||||
/// more detailed analysis.
|
||||
///
|
||||
/// [push]: #method.push
|
||||
/// [pop]: #method.pop
|
||||
/// [peek]: #method.peek
|
||||
/// [peek\_mut]: #method.peek_mut
|
||||
/// [push]: BinaryHeap::push
|
||||
/// [pop]: BinaryHeap::pop
|
||||
/// [peek]: BinaryHeap::peek
|
||||
/// [peek\_mut]: BinaryHeap::peek_mut
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct BinaryHeap<T> {
|
||||
data: Vec<T>,
|
||||
|
@ -255,8 +254,7 @@ pub struct BinaryHeap<T> {
|
|||
/// This `struct` is created by the [`peek_mut`] method on [`BinaryHeap`]. See
|
||||
/// its documentation for more.
|
||||
///
|
||||
/// [`peek_mut`]: struct.BinaryHeap.html#method.peek_mut
|
||||
/// [`BinaryHeap`]: struct.BinaryHeap.html
|
||||
/// [`peek_mut`]: BinaryHeap::peek_mut
|
||||
#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
|
||||
pub struct PeekMut<'a, T: 'a + Ord> {
|
||||
heap: &'a mut BinaryHeap<T>,
|
||||
|
@ -802,7 +800,7 @@ impl<T> BinaryHeap<T> {
|
|||
/// heap.push(4);
|
||||
/// ```
|
||||
///
|
||||
/// [`reserve`]: #method.reserve
|
||||
/// [`reserve`]: BinaryHeap::reserve
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn reserve_exact(&mut self, additional: usize) {
|
||||
self.data.reserve_exact(additional);
|
||||
|
@ -1057,11 +1055,10 @@ impl<T> Drop for Hole<'_, T> {
|
|||
|
||||
/// An iterator over the elements of a `BinaryHeap`.
|
||||
///
|
||||
/// This `struct` is created by the [`iter`] method on [`BinaryHeap`]. See its
|
||||
/// This `struct` is created by [`BinaryHeap::iter()`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`iter`]: struct.BinaryHeap.html#method.iter
|
||||
/// [`BinaryHeap`]: struct.BinaryHeap.html
|
||||
/// [`iter`]: BinaryHeap::iter
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Iter<'a, T: 'a> {
|
||||
iter: slice::Iter<'a, T>,
|
||||
|
@ -1122,11 +1119,10 @@ impl<T> FusedIterator for Iter<'_, T> {}
|
|||
|
||||
/// An owning iterator over the elements of a `BinaryHeap`.
|
||||
///
|
||||
/// This `struct` is created by the [`into_iter`] method on [`BinaryHeap`]
|
||||
/// This `struct` is created by [`BinaryHeap::into_iter()`]
|
||||
/// (provided by the `IntoIterator` trait). See its documentation for more.
|
||||
///
|
||||
/// [`into_iter`]: struct.BinaryHeap.html#method.into_iter
|
||||
/// [`BinaryHeap`]: struct.BinaryHeap.html
|
||||
/// [`into_iter`]: BinaryHeap::into_iter
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Clone)]
|
||||
pub struct IntoIter<T> {
|
||||
|
@ -1227,11 +1223,10 @@ unsafe impl<T: Ord> TrustedLen for IntoIterSorted<T> {}
|
|||
|
||||
/// A draining iterator over the elements of a `BinaryHeap`.
|
||||
///
|
||||
/// This `struct` is created by the [`drain`] method on [`BinaryHeap`]. See its
|
||||
/// This `struct` is created by [`BinaryHeap::drain()`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`drain`]: struct.BinaryHeap.html#method.drain
|
||||
/// [`BinaryHeap`]: struct.BinaryHeap.html
|
||||
/// [`drain`]: BinaryHeap::drain
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Drain<'a, T: 'a> {
|
||||
|
@ -1273,11 +1268,10 @@ impl<T> FusedIterator for Drain<'_, T> {}
|
|||
|
||||
/// A draining iterator over the elements of a `BinaryHeap`.
|
||||
///
|
||||
/// This `struct` is created by the [`drain_sorted`] method on [`BinaryHeap`]. See its
|
||||
/// This `struct` is created by [`BinaryHeap::drain_sorted()`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`drain_sorted`]: struct.BinaryHeap.html#method.drain_sorted
|
||||
/// [`BinaryHeap`]: struct.BinaryHeap.html
|
||||
/// [`drain_sorted`]: BinaryHeap::drain_sorted
|
||||
#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
|
||||
#[derive(Debug)]
|
||||
pub struct DrainSorted<'a, T: Ord> {
|
||||
|
|
|
@ -47,7 +47,6 @@ use UnderflowResult::*;
|
|||
/// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is
|
||||
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
|
||||
///
|
||||
/// [`Ord`]: core::cmp::Ord
|
||||
/// [`Cell`]: core::cell::Cell
|
||||
/// [`RefCell`]: core::cell::RefCell
|
||||
///
|
||||
|
@ -93,9 +92,10 @@ use UnderflowResult::*;
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// `BTreeMap` also implements an [`Entry API`](#method.entry), which allows
|
||||
/// for more complex methods of getting, setting, updating and removing keys and
|
||||
/// their values:
|
||||
/// `BTreeMap` also implements an [`Entry API`], which allows for more complex
|
||||
/// methods of getting, setting, updating and removing keys and their values:
|
||||
///
|
||||
/// [`Entry API`]: BTreeMap::entry
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::BTreeMap;
|
||||
|
@ -453,8 +453,6 @@ impl<K: Debug + Ord, V: Debug> Debug for Entry<'_, K, V> {
|
|||
|
||||
/// A view into a vacant entry in a `BTreeMap`.
|
||||
/// It is part of the [`Entry`] enum.
|
||||
///
|
||||
/// [`Entry`]: enum.Entry.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct VacantEntry<'a, K: 'a, V: 'a> {
|
||||
key: K,
|
||||
|
@ -474,8 +472,6 @@ impl<K: Debug + Ord, V> Debug for VacantEntry<'_, K, V> {
|
|||
|
||||
/// A view into an occupied entry in a `BTreeMap`.
|
||||
/// It is part of the [`Entry`] enum.
|
||||
///
|
||||
/// [`Entry`]: enum.Entry.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
|
||||
handle: Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV>,
|
||||
|
@ -815,7 +811,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
/// types that can be `==` without being identical. See the [module-level
|
||||
/// documentation] for more.
|
||||
///
|
||||
/// [module-level documentation]: index.html#insert-and-complex-keys
|
||||
/// [module-level documentation]: crate::collections#insert-and-complex-keys
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1719,7 +1715,7 @@ impl<'a, K: 'a, V: 'a> DrainFilterInner<'a, K, V> {
|
|||
/// Allow Debug implementations to predict the next element.
|
||||
pub(super) fn peek(&self) -> Option<(&K, &V)> {
|
||||
let edge = self.cur_leaf_edge.as_ref()?;
|
||||
edge.reborrow().next_kv().ok().map(|kv| kv.into_kv())
|
||||
edge.reborrow().next_kv().ok().map(Handle::into_kv)
|
||||
}
|
||||
|
||||
/// Implementation of a typical `DrainFilter::next` method, given the predicate.
|
||||
|
@ -2554,7 +2550,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
|
|||
/// If you need a reference to the `OccupiedEntry` that may outlive the
|
||||
/// destruction of the `Entry` value, see [`into_mut`].
|
||||
///
|
||||
/// [`into_mut`]: #method.into_mut
|
||||
/// [`into_mut`]: OccupiedEntry::into_mut
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -2584,7 +2580,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
|
|||
///
|
||||
/// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
|
||||
///
|
||||
/// [`get_mut`]: #method.get_mut
|
||||
/// [`get_mut`]: OccupiedEntry::get_mut
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
@ -218,7 +218,7 @@ impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::E
|
|||
let mut edge = self.forget_node_type();
|
||||
loop {
|
||||
edge = match edge.right_kv() {
|
||||
Ok(internal_kv) => return Ok(internal_kv),
|
||||
Ok(kv) => return Ok(kv),
|
||||
Err(last_edge) => match last_edge.into_node().ascend() {
|
||||
Ok(parent_edge) => parent_edge.forget_node_type(),
|
||||
Err(root) => return Err(root),
|
||||
|
@ -239,7 +239,7 @@ impl<BorrowType, K, V> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::E
|
|||
let mut edge = self.forget_node_type();
|
||||
loop {
|
||||
edge = match edge.left_kv() {
|
||||
Ok(internal_kv) => return Ok(internal_kv),
|
||||
Ok(kv) => return Ok(kv),
|
||||
Err(last_edge) => match last_edge.into_node().ascend() {
|
||||
Ok(parent_edge) => parent_edge.forget_node_type(),
|
||||
Err(root) => return Err(root),
|
||||
|
|
|
@ -929,14 +929,14 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
|
|||
/// The returned pointer points to the inserted value.
|
||||
fn insert(mut self, key: K, val: V) -> (InsertResult<'a, K, V, marker::Leaf>, *mut V) {
|
||||
if self.node.len() < CAPACITY {
|
||||
let ptr = self.insert_fit(key, val);
|
||||
let val_ptr = self.insert_fit(key, val);
|
||||
let kv = unsafe { Handle::new_kv(self.node, self.idx) };
|
||||
(InsertResult::Fit(kv), ptr)
|
||||
(InsertResult::Fit(kv), val_ptr)
|
||||
} else {
|
||||
let (middle_kv_idx, insertion) = splitpoint(self.idx);
|
||||
let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
|
||||
let (mut left, k, v, mut right) = middle.split();
|
||||
let ptr = match insertion {
|
||||
let val_ptr = match insertion {
|
||||
InsertionPlace::Left(insert_idx) => unsafe {
|
||||
Handle::new_edge(left.reborrow_mut(), insert_idx).insert_fit(key, val)
|
||||
},
|
||||
|
@ -948,7 +948,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, mark
|
|||
.insert_fit(key, val)
|
||||
},
|
||||
};
|
||||
(InsertResult::Split(SplitResult { left: left.forget_type(), k, v, right }), ptr)
|
||||
(InsertResult::Split(SplitResult { left: left.forget_type(), k, v, right }), val_ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ impl<T: fmt::Debug> fmt::Debug for IterMut<'_, T> {
|
|||
/// This `struct` is created by the [`into_iter`] method on [`LinkedList`]
|
||||
/// (provided by the `IntoIterator` trait). See its documentation for more.
|
||||
///
|
||||
/// [`into_iter`]: struct.LinkedList.html#method.into_iter
|
||||
/// [`into_iter`]: LinkedList::into_iter
|
||||
#[derive(Clone)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IntoIter<T> {
|
||||
|
|
|
@ -48,11 +48,11 @@ const MAXIMUM_ZST_CAPACITY: usize = 1 << (core::mem::size_of::<usize>() * 8 - 1)
|
|||
/// so that its elements do not wrap, and returns a mutable slice to the
|
||||
/// now-contiguous element sequence.
|
||||
///
|
||||
/// [`push_back`]: #method.push_back
|
||||
/// [`pop_front`]: #method.pop_front
|
||||
/// [`extend`]: #method.extend
|
||||
/// [`append`]: #method.append
|
||||
/// [`make_contiguous`]: #method.make_contiguous
|
||||
/// [`push_back`]: VecDeque::push_back
|
||||
/// [`pop_front`]: VecDeque::pop_front
|
||||
/// [`extend`]: VecDeque::extend
|
||||
/// [`append`]: VecDeque::append
|
||||
/// [`make_contiguous`]: VecDeque::make_contiguous
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "vecdeque_type")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct VecDeque<T> {
|
||||
|
@ -640,7 +640,7 @@ impl<T> VecDeque<T> {
|
|||
/// assert!(buf.capacity() >= 11);
|
||||
/// ```
|
||||
///
|
||||
/// [`reserve`]: #method.reserve
|
||||
/// [`reserve`]: VecDeque::reserve
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn reserve_exact(&mut self, additional: usize) {
|
||||
self.reserve(additional);
|
||||
|
@ -987,8 +987,10 @@ impl<T> VecDeque<T> {
|
|||
/// Returns a pair of slices which contain, in order, the contents of the
|
||||
/// `VecDeque`.
|
||||
///
|
||||
/// If [`make_contiguous`](#method.make_contiguous) was previously called, all elements
|
||||
/// of the `VecDeque` will be in the first slice and the second slice will be empty.
|
||||
/// If [`make_contiguous`] was previously called, all elements of the
|
||||
/// `VecDeque` will be in the first slice and the second slice will be empty.
|
||||
///
|
||||
/// [`make_contiguous`]: VecDeque::make_contiguous
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1020,8 +1022,10 @@ impl<T> VecDeque<T> {
|
|||
/// Returns a pair of slices which contain, in order, the contents of the
|
||||
/// `VecDeque`.
|
||||
///
|
||||
/// If [`make_contiguous`](#method.make_contiguous) was previously called, all elements
|
||||
/// of the `VecDeque` will be in the first slice and the second slice will be empty.
|
||||
/// If [`make_contiguous`] was previously called, all elements of the
|
||||
/// `VecDeque` will be in the first slice and the second slice will be empty.
|
||||
///
|
||||
/// [`make_contiguous`]: VecDeque::make_contiguous
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -2160,15 +2164,20 @@ impl<T> VecDeque<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Rearranges the internal storage of this deque so it is one contiguous slice, which is then returned.
|
||||
/// Rearranges the internal storage of this deque so it is one contiguous
|
||||
/// slice, which is then returned.
|
||||
///
|
||||
/// This method does not allocate and does not change the order of the inserted elements.
|
||||
/// As it returns a mutable slice, this can be used to sort or binary search a deque.
|
||||
/// This method does not allocate and does not change the order of the
|
||||
/// inserted elements. As it returns a mutable slice, this can be used to
|
||||
/// sort or binary search a deque.
|
||||
///
|
||||
/// Once the internal storage is contiguous, the [`as_slices`](#method.as_slices) and
|
||||
/// [`as_mut_slices`](#method.as_mut_slices) methods will return the entire contents of the
|
||||
/// Once the internal storage is contiguous, the [`as_slices`] and
|
||||
/// [`as_mut_slices`] methods will return the entire contents of the
|
||||
/// `VecDeque` in a single slice.
|
||||
///
|
||||
/// [`as_slices`]: VecDeque::as_slices
|
||||
/// [`as_mut_slices`]: VecDeque::as_mut_slices
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Sorting the content of a deque.
|
||||
|
@ -2495,8 +2504,7 @@ fn count(tail: usize, head: usize, size: usize) -> usize {
|
|||
/// This `struct` is created by the [`iter`] method on [`VecDeque`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`iter`]: struct.VecDeque.html#method.iter
|
||||
/// [`VecDeque`]: struct.VecDeque.html
|
||||
/// [`iter`]: VecDeque::iter
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Iter<'a, T: 'a> {
|
||||
ring: &'a [T],
|
||||
|
@ -2650,8 +2658,7 @@ impl<T> FusedIterator for Iter<'_, T> {}
|
|||
/// This `struct` is created by the [`iter_mut`] method on [`VecDeque`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`iter_mut`]: struct.VecDeque.html#method.iter_mut
|
||||
/// [`VecDeque`]: struct.VecDeque.html
|
||||
/// [`iter_mut`]: VecDeque::iter_mut
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IterMut<'a, T: 'a> {
|
||||
ring: &'a mut [T],
|
||||
|
@ -2756,8 +2763,7 @@ impl<T> FusedIterator for IterMut<'_, T> {}
|
|||
/// This `struct` is created by the [`into_iter`] method on [`VecDeque`]
|
||||
/// (provided by the `IntoIterator` trait). See its documentation for more.
|
||||
///
|
||||
/// [`into_iter`]: struct.VecDeque.html#method.into_iter
|
||||
/// [`VecDeque`]: struct.VecDeque.html
|
||||
/// [`into_iter`]: VecDeque::into_iter
|
||||
#[derive(Clone)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IntoIter<T> {
|
||||
|
|
|
@ -9,8 +9,7 @@ use super::{count, Iter, VecDeque};
|
|||
/// This `struct` is created by the [`drain`] method on [`VecDeque`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`drain`]: struct.VecDeque.html#method.drain
|
||||
/// [`VecDeque`]: struct.VecDeque.html
|
||||
/// [`drain`]: VecDeque::drain
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
pub struct Drain<'a, T: 'a> {
|
||||
pub(crate) after_tail: usize,
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![cfg_attr(not(test), feature(generator_trait))]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
#![cfg_attr(test, feature(new_uninit))]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(array_chunks)]
|
||||
#![feature(array_windows)]
|
||||
|
@ -81,7 +82,6 @@
|
|||
#![feature(arbitrary_self_types)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(btree_drain_filter)]
|
||||
#![feature(cfg_sanitize)]
|
||||
#![feature(cfg_target_has_atomic)]
|
||||
#![feature(coerce_unsized)]
|
||||
|
@ -89,10 +89,8 @@
|
|||
#![feature(const_generics)]
|
||||
#![feature(const_in_array_repeat_expressions)]
|
||||
#![feature(cow_is_borrowed)]
|
||||
#![feature(deque_range)]
|
||||
#![feature(dispatch_from_dyn)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(container_error_extra)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(exclusive_range_pattern)]
|
||||
|
@ -104,13 +102,9 @@
|
|||
#![feature(int_bits_const)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(layout_for_ptr)]
|
||||
#![feature(libc)]
|
||||
#![feature(map_first_last)]
|
||||
#![feature(map_into_keys_values)]
|
||||
#![feature(maybe_uninit_ref)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(new_uninit)]
|
||||
#![feature(nll)]
|
||||
#![feature(nonnull_slice_from_raw_parts)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
|
@ -125,10 +119,8 @@
|
|||
#![feature(slice_ptr_get)]
|
||||
#![feature(slice_ptr_len)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(std_internals)]
|
||||
#![feature(str_internals)]
|
||||
#![feature(trusted_len)]
|
||||
#![feature(try_reserve)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unicode_internals)]
|
||||
#![feature(unsafe_block_in_unsafe_fn)]
|
||||
|
|
|
@ -1071,6 +1071,7 @@ extern "rust-intrinsic" {
|
|||
// NOTE: While this makes the intrinsic const stable, we have some custom code in const fn
|
||||
// checks that prevent its use within `const fn`.
|
||||
#[rustc_const_stable(feature = "const_transmute", since = "1.46.0")]
|
||||
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "transmute")]
|
||||
pub fn transmute<T, U>(e: T) -> U;
|
||||
|
||||
/// Returns `true` if the actual type given as `T` requires drop
|
||||
|
|
|
@ -66,9 +66,7 @@
|
|||
#![feature(allow_internal_unstable)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(asm)]
|
||||
#![feature(bound_cloned)]
|
||||
#![feature(cfg_target_has_atomic)]
|
||||
#![feature(concat_idents)]
|
||||
#![feature(const_alloc_layout)]
|
||||
#![feature(const_discriminant)]
|
||||
#![feature(const_checked_int_methods)]
|
||||
|
@ -103,8 +101,6 @@
|
|||
#![feature(extern_types)]
|
||||
#![feature(fundamental)]
|
||||
#![feature(intrinsics)]
|
||||
#![feature(try_find)]
|
||||
#![feature(is_sorted)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(link_llvm_intrinsics)]
|
||||
#![feature(llvm_asm)]
|
||||
|
@ -116,7 +112,6 @@
|
|||
#![feature(optin_builtin_traits)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(prelude_import)]
|
||||
#![feature(ptr_as_uninit)]
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(simd_ffi)]
|
||||
|
@ -147,8 +142,6 @@
|
|||
#![feature(const_fn_transmute)]
|
||||
#![feature(abi_unadjusted)]
|
||||
#![feature(adx_target_feature)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(maybe_uninit_extra)]
|
||||
#![feature(external_doc)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(const_caller_location)]
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#![panic_runtime]
|
||||
#![allow(unused_features)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(libc)]
|
||||
#![feature(nll)]
|
||||
#![feature(panic_runtime)]
|
||||
#![feature(staged_api)]
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#![feature(core_intrinsics)]
|
||||
#![feature(int_bits_const)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(libc)]
|
||||
#![feature(nll)]
|
||||
#![feature(panic_unwind)]
|
||||
#![feature(staged_api)]
|
||||
|
|
|
@ -1173,6 +1173,16 @@ where
|
|||
/// See its documentation for more.
|
||||
///
|
||||
/// [`iter`]: HashSet::iter
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashSet;
|
||||
///
|
||||
/// let a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
|
||||
///
|
||||
/// let mut iter = a.iter();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Iter<'a, K: 'a> {
|
||||
base: base::Iter<'a, K>,
|
||||
|
@ -1184,6 +1194,16 @@ pub struct Iter<'a, K: 'a> {
|
|||
/// (provided by the `IntoIterator` trait). See its documentation for more.
|
||||
///
|
||||
/// [`into_iter`]: IntoIterator::into_iter
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashSet;
|
||||
///
|
||||
/// let a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
|
||||
///
|
||||
/// let mut iter = a.into_iter();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IntoIter<K> {
|
||||
base: base::IntoIter<K>,
|
||||
|
@ -1195,6 +1215,16 @@ pub struct IntoIter<K> {
|
|||
/// See its documentation for more.
|
||||
///
|
||||
/// [`drain`]: HashSet::drain
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashSet;
|
||||
///
|
||||
/// let mut a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
|
||||
///
|
||||
/// let mut drain = a.drain();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Drain<'a, K: 'a> {
|
||||
base: base::Drain<'a, K>,
|
||||
|
@ -1205,6 +1235,18 @@ pub struct Drain<'a, K: 'a> {
|
|||
/// This `struct` is created by the [`drain_filter`] method on [`HashSet`].
|
||||
///
|
||||
/// [`drain_filter`]: HashSet::drain_filter
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(hash_drain_filter)]
|
||||
///
|
||||
/// use std::collections::HashSet;
|
||||
///
|
||||
/// let mut a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
|
||||
///
|
||||
/// let mut drain_filtered = a.drain_filter(|v| v % 2 == 0);
|
||||
/// ```
|
||||
#[unstable(feature = "hash_drain_filter", issue = "59618")]
|
||||
pub struct DrainFilter<'a, K, F>
|
||||
where
|
||||
|
@ -1219,6 +1261,17 @@ where
|
|||
/// See its documentation for more.
|
||||
///
|
||||
/// [`intersection`]: HashSet::intersection
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashSet;
|
||||
///
|
||||
/// let a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
|
||||
/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
|
||||
///
|
||||
/// let mut intersection = a.intersection(&b);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Intersection<'a, T: 'a, S: 'a> {
|
||||
// iterator of the first set
|
||||
|
@ -1233,6 +1286,17 @@ pub struct Intersection<'a, T: 'a, S: 'a> {
|
|||
/// See its documentation for more.
|
||||
///
|
||||
/// [`difference`]: HashSet::difference
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashSet;
|
||||
///
|
||||
/// let a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
|
||||
/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
|
||||
///
|
||||
/// let mut difference = a.difference(&b);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Difference<'a, T: 'a, S: 'a> {
|
||||
// iterator of the first set
|
||||
|
@ -1247,6 +1311,17 @@ pub struct Difference<'a, T: 'a, S: 'a> {
|
|||
/// [`HashSet`]. See its documentation for more.
|
||||
///
|
||||
/// [`symmetric_difference`]: HashSet::symmetric_difference
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashSet;
|
||||
///
|
||||
/// let a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
|
||||
/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
|
||||
///
|
||||
/// let mut intersection = a.symmetric_difference(&b);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
|
||||
iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>,
|
||||
|
@ -1258,6 +1333,17 @@ pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
|
|||
/// See its documentation for more.
|
||||
///
|
||||
/// [`union`]: HashSet::union
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashSet;
|
||||
///
|
||||
/// let a: HashSet<u32> = vec![1, 2, 3].into_iter().collect();
|
||||
/// let b: HashSet<_> = [4, 2, 3, 4].iter().cloned().collect();
|
||||
///
|
||||
/// let mut union_iter = a.union(&b);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Union<'a, T: 'a, S: 'a> {
|
||||
iter: Chain<Iter<'a, T>, Difference<'a, T, S>>,
|
||||
|
|
|
@ -228,7 +228,6 @@
|
|||
#![feature(atomic_mut_ptr)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(c_variadic)]
|
||||
#![feature(can_vector)]
|
||||
#![feature(cfg_accessible)]
|
||||
#![feature(cfg_target_has_atomic)]
|
||||
#![feature(cfg_target_thread_local)]
|
||||
|
@ -261,14 +260,12 @@
|
|||
#![feature(gen_future)]
|
||||
#![feature(generator_trait)]
|
||||
#![feature(global_asm)]
|
||||
#![feature(hash_raw_entry)]
|
||||
#![feature(hashmap_internals)]
|
||||
#![feature(int_error_internals)]
|
||||
#![feature(int_error_matching)]
|
||||
#![feature(integer_atomics)]
|
||||
#![feature(into_future)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(libc)]
|
||||
#![feature(link_args)]
|
||||
#![feature(linkage)]
|
||||
#![feature(llvm_asm)]
|
||||
|
|
|
@ -667,7 +667,7 @@ impl UnixStream {
|
|||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "unix_socket_peek", issue = "none")]
|
||||
#[unstable(feature = "unix_socket_peek", issue = "76923")]
|
||||
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.peek(buf)
|
||||
}
|
||||
|
@ -1708,7 +1708,7 @@ impl UnixDatagram {
|
|||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "unix_socket_peek", issue = "none")]
|
||||
#[unstable(feature = "unix_socket_peek", issue = "76923")]
|
||||
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.peek(buf)
|
||||
}
|
||||
|
@ -1740,7 +1740,7 @@ impl UnixDatagram {
|
|||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "unix_socket_peek", issue = "none")]
|
||||
#[unstable(feature = "unix_socket_peek", issue = "76923")]
|
||||
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||
self.recv_from_flags(buf, libc::MSG_PEEK)
|
||||
}
|
||||
|
|
|
@ -12,9 +12,6 @@ use build_helper::output;
|
|||
|
||||
use crate::Build;
|
||||
|
||||
// The version number
|
||||
pub const CFG_RELEASE_NUM: &str = "1.48.0";
|
||||
|
||||
pub struct GitInfo {
|
||||
inner: Option<Info>,
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ use build_helper::{output, t};
|
|||
|
||||
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
|
||||
use crate::cache::{Interned, INTERNER};
|
||||
use crate::channel;
|
||||
use crate::compile;
|
||||
use crate::config::TargetSelection;
|
||||
use crate::tool::{self, Tool};
|
||||
|
@ -569,7 +568,7 @@ impl Step for Rustc {
|
|||
&page_dst,
|
||||
&[
|
||||
("<INSERT DATE HERE>", &month_year),
|
||||
("<INSERT VERSION HERE>", channel::CFG_RELEASE_NUM),
|
||||
("<INSERT VERSION HERE>", &builder.version),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -2301,9 +2300,9 @@ impl Step for Extended {
|
|||
}
|
||||
|
||||
fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
|
||||
let mut parts = channel::CFG_RELEASE_NUM.split('.');
|
||||
let mut parts = builder.version.split('.');
|
||||
cmd.env("CFG_RELEASE_INFO", builder.rust_version())
|
||||
.env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM)
|
||||
.env("CFG_RELEASE_NUM", &builder.version)
|
||||
.env("CFG_RELEASE", builder.rust_release())
|
||||
.env("CFG_VER_MAJOR", parts.next().unwrap())
|
||||
.env("CFG_VER_MINOR", parts.next().unwrap())
|
||||
|
|
|
@ -433,7 +433,7 @@ impl Step for Std {
|
|||
.arg("-Z")
|
||||
.arg("unstable-options")
|
||||
.arg("--resource-suffix")
|
||||
.arg(crate::channel::CFG_RELEASE_NUM)
|
||||
.arg(&builder.version)
|
||||
.arg("--index-page")
|
||||
.arg(&builder.src.join("src/doc/index.md"));
|
||||
|
||||
|
@ -659,7 +659,7 @@ impl Step for ErrorIndex {
|
|||
let mut index = tool::ErrorIndex::command(builder, self.compiler);
|
||||
index.arg("html");
|
||||
index.arg(out.join("error-index.html"));
|
||||
index.arg(crate::channel::CFG_RELEASE_NUM);
|
||||
index.arg(&builder.version);
|
||||
|
||||
builder.run(&mut index);
|
||||
}
|
||||
|
|
|
@ -218,6 +218,9 @@ pub struct Build {
|
|||
/// User-specified configuration from `config.toml`.
|
||||
config: Config,
|
||||
|
||||
// Version information
|
||||
version: String,
|
||||
|
||||
// Properties derived from the above configuration
|
||||
src: PathBuf,
|
||||
out: PathBuf,
|
||||
|
@ -380,6 +383,10 @@ impl Build {
|
|||
.unwrap()
|
||||
.to_path_buf();
|
||||
|
||||
let version = std::fs::read_to_string(src.join("src").join("version"))
|
||||
.expect("failed to read src/version");
|
||||
let version = version.trim();
|
||||
|
||||
let mut build = Build {
|
||||
initial_rustc: config.initial_rustc.clone(),
|
||||
initial_cargo: config.initial_cargo.clone(),
|
||||
|
@ -395,6 +402,7 @@ impl Build {
|
|||
targets: config.targets.clone(),
|
||||
|
||||
config,
|
||||
version: version.to_string(),
|
||||
src,
|
||||
out,
|
||||
|
||||
|
@ -433,8 +441,7 @@ impl Build {
|
|||
.next()
|
||||
.unwrap()
|
||||
.trim();
|
||||
let my_version = channel::CFG_RELEASE_NUM;
|
||||
if local_release.split('.').take(2).eq(my_version.split('.').take(2)) {
|
||||
if local_release.split('.').take(2).eq(version.split('.').take(2)) {
|
||||
build.verbose(&format!("auto-detected local-rebuild {}", local_release));
|
||||
build.local_rebuild = true;
|
||||
}
|
||||
|
@ -785,7 +792,7 @@ impl Build {
|
|||
|
||||
match which {
|
||||
GitRepo::Rustc => {
|
||||
let sha = self.rust_sha().unwrap_or(channel::CFG_RELEASE_NUM);
|
||||
let sha = self.rust_sha().unwrap_or(&self.version);
|
||||
Some(format!("/rustc/{}", sha))
|
||||
}
|
||||
GitRepo::Llvm => Some(String::from("/rustc/llvm")),
|
||||
|
@ -1016,7 +1023,7 @@ impl Build {
|
|||
|
||||
/// Returns the value of `release` above for Rust itself.
|
||||
fn rust_release(&self) -> String {
|
||||
self.release(channel::CFG_RELEASE_NUM)
|
||||
self.release(&self.version)
|
||||
}
|
||||
|
||||
/// Returns the "package version" for a component given the `num` release
|
||||
|
@ -1036,7 +1043,7 @@ impl Build {
|
|||
|
||||
/// Returns the value of `package_vers` above for Rust itself.
|
||||
fn rust_package_vers(&self) -> String {
|
||||
self.package_vers(channel::CFG_RELEASE_NUM)
|
||||
self.package_vers(&self.version)
|
||||
}
|
||||
|
||||
/// Returns the value of `package_vers` above for Cargo
|
||||
|
@ -1070,7 +1077,7 @@ impl Build {
|
|||
}
|
||||
|
||||
fn llvm_tools_package_vers(&self) -> String {
|
||||
self.package_vers(channel::CFG_RELEASE_NUM)
|
||||
self.package_vers(&self.version)
|
||||
}
|
||||
|
||||
fn llvm_tools_vers(&self) -> String {
|
||||
|
@ -1087,7 +1094,7 @@ impl Build {
|
|||
/// Note that this is a descriptive string which includes the commit date,
|
||||
/// sha, version, etc.
|
||||
fn rust_version(&self) -> String {
|
||||
self.rust_info.version(self, channel::CFG_RELEASE_NUM)
|
||||
self.rust_info.version(self, &self.version)
|
||||
}
|
||||
|
||||
/// Returns the full commit hash.
|
||||
|
|
|
@ -19,7 +19,6 @@ use std::process::Command;
|
|||
use build_helper::{output, t};
|
||||
|
||||
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
|
||||
use crate::channel;
|
||||
use crate::config::TargetSelection;
|
||||
use crate::util::{self, exe};
|
||||
use crate::GitRepo;
|
||||
|
@ -296,7 +295,7 @@ impl Step for Llvm {
|
|||
// release number on the dev channel.
|
||||
cfg.define("LLVM_VERSION_SUFFIX", "-rust-dev");
|
||||
} else {
|
||||
let suffix = format!("-rust-{}-{}", channel::CFG_RELEASE_NUM, builder.config.channel);
|
||||
let suffix = format!("-rust-{}-{}", builder.version, builder.config.channel);
|
||||
cfg.define("LLVM_VERSION_SUFFIX", suffix);
|
||||
}
|
||||
|
||||
|
|
|
@ -636,7 +636,7 @@ impl Step for RustdocJSStd {
|
|||
.arg("--crate-name")
|
||||
.arg("std")
|
||||
.arg("--resource-suffix")
|
||||
.arg(crate::channel::CFG_RELEASE_NUM)
|
||||
.arg(&builder.version)
|
||||
.arg("--doc-folder")
|
||||
.arg(builder.doc_out(self.target))
|
||||
.arg("--test-folder")
|
||||
|
|
|
@ -7,7 +7,6 @@ use std::process::{exit, Command};
|
|||
use build_helper::t;
|
||||
|
||||
use crate::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step};
|
||||
use crate::channel;
|
||||
use crate::channel::GitInfo;
|
||||
use crate::compile;
|
||||
use crate::config::TargetSelection;
|
||||
|
@ -255,7 +254,7 @@ pub fn prepare_tool_cargo(
|
|||
cargo.env("CFG_RELEASE", builder.rust_release());
|
||||
cargo.env("CFG_RELEASE_CHANNEL", &builder.config.channel);
|
||||
cargo.env("CFG_VERSION", builder.rust_version());
|
||||
cargo.env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM);
|
||||
cargo.env("CFG_RELEASE_NUM", &builder.version);
|
||||
|
||||
let info = GitInfo::new(builder.config.ignore_git, &dir);
|
||||
if let Some(sha) = info.sha() {
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// Regression test for issue #76202
|
||||
// Tests that we don't ICE when we have a trait impl on a TAIT.
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait Dummy {}
|
||||
impl Dummy for () {}
|
||||
|
||||
type F = impl Dummy;
|
||||
fn f() -> F {}
|
||||
|
||||
trait Test {
|
||||
fn test(self);
|
||||
}
|
||||
|
||||
impl Test for F { //~ ERROR cannot implement trait
|
||||
fn test(self) {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x: F = f();
|
||||
x.test();
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
error: cannot implement trait on type alias impl trait
|
||||
--> $DIR/issue-76202-trait-impl-for-tait.rs:16:1
|
||||
|
|
||||
LL | impl Test for F {
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: type alias impl trait defined here
|
||||
--> $DIR/issue-76202-trait-impl-for-tait.rs:9:10
|
||||
|
|
||||
LL | type F = impl Dummy;
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -0,0 +1 @@
|
|||
1.48.0
|
Loading…
Reference in New Issue