# Original downloaded here came from
# http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe
- script: |
- powershell -Command "iwr -outf %TEMP%\LLVM-7.0.0-win64.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/LLVM-7.0.0-win64.exe"
+ powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf %TEMP%\LLVM-7.0.0-win64.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/LLVM-7.0.0-win64.exe"
set CLANG_DIR=%CD%\citools\clang-rust
%TEMP%\LLVM-7.0.0-win64.exe /S /NCRC /D=%CLANG_DIR%
set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=%CLANG_DIR%\bin\clang-cl.exe
- script: |
md sccache
- powershell -Command "iwr -outf sccache\sccache.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc"
+ powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf sccache\sccache.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc"
echo ##vso[task.prependpath]%CD%\sccache
displayName: Install sccache (Windows)
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
# Note that we don't literally overwrite the gdb.exe binary because it appears
# to just use gdborig.exe, so that's the binary we deal with instead.
- script: |
- powershell -Command "iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%"
+ powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%"
7z x -y %MINGW_ARCHIVE% > nul
- powershell -Command "iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe"
+ powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe"
mv 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_DIR%\bin\gdborig.exe
echo ##vso[task.prependpath]%CD%\%MINGW_DIR%\bin
condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['MINGW_URL'],''))
# Note that this is originally from the github releases patch of Ninja
- script: |
md ninja
- powershell -Command "iwr -outf 2017-03-15-ninja-win.zip https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-03-15-ninja-win.zip"
+ powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-03-15-ninja-win.zip https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-03-15-ninja-win.zip"
7z x -oninja 2017-03-15-ninja-win.zip
del 2017-03-15-ninja-win.zip
set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja
[[package]]
name = "hashbrown"
-version = "0.3.0"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"core 0.0.0",
"dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
"panic_abort 0.0.0",
"panic_unwind 0.0.0",
"checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454"
"checksum handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d89ec99d1594f285d4590fc32bac5f75cdab383f1123d504d27862c644a807dd"
"checksum handlebars 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d82e5750d8027a97b9640e3fefa66bbaf852a35228e1c90790efd13c4b09c166"
-"checksum hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "570178d5e4952010d138b0f1d581271ff3a02406d990f887d1e87e3d6e43b0ac"
+"checksum hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9529213c67695ca2d146e6f263b7b72df8fa973368beadf767e8ed80c03f2f36"
"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82"
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
"checksum home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80dff82fb58cfbbc617fb9a9184b010be0529201553cda50ad04372bc2333aff"
book!(
EditionGuide, "src/doc/edition-guide", "edition-guide", RustbookVersion::MdBook2;
EmbeddedBook, "src/doc/embedded-book", "embedded-book", RustbookVersion::MdBook2;
- Nomicon, "src/doc/nomicon", "nomicon", RustbookVersion::MdBook1;
+ Nomicon, "src/doc/nomicon", "nomicon", RustbookVersion::MdBook2;
Reference, "src/doc/reference", "reference", RustbookVersion::MdBook1;
RustByExample, "src/doc/rust-by-example", "rust-by-example", RustbookVersion::MdBook1;
RustcBook, "src/doc/rustc", "rustc", RustbookVersion::MdBook1;
- RustdocBook, "src/doc/rustdoc", "rustdoc", RustbookVersion::MdBook1;
+ RustdocBook, "src/doc/rustdoc", "rustdoc", RustbookVersion::MdBook2;
);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
target: self.target,
name: INTERNER.intern_str("unstable-book"),
src: builder.md_doc_out(self.target),
- version: RustbookVersion::MdBook1,
+ version: RustbookVersion::MdBook2,
})
}
}
An argument of "list" will print a list of possible "rustdoc passes", and other
arguments will be the name of which passes to run in addition to the defaults.
-For more details on passes, see [the chapter on them](passes.html).
+For more details on passes, see [the chapter on them](passes.md).
See also `--no-defaults`.
removes those defaults, allowing you to use `--passes` to specify
exactly which passes you want.
-For more details on passes, see [the chapter on them](passes.html).
+For more details on passes, see [the chapter on them](passes.md).
See also `--passes`.
```
This flag will run your code examples as tests. For more, see [the chapter
-on documentation tests](documentation-tests.html).
+on documentation tests](documentation-tests.md).
See also `--test-args`.
```
This flag will pass options to the test runner when running documentation tests.
-For more, see [the chapter on documentation tests](documentation-tests.html).
+For more, see [the chapter on documentation tests](documentation-tests.md).
See also `--test`.
In addition to the passes below, check out the docs for these flags:
-* [`--passes`](command-line-arguments.html#a--passes-add-more-rustdoc-passes)
-* [`--no-defaults`](command-line-arguments.html#a--no-defaults-dont-run-default-passes)
+* [`--passes`](command-line-arguments.md#--passes-add-more-rustdoc-passes)
+* [`--no-defaults`](command-line-arguments.md#--no-defaults-dont-run-default-passes)
## Default passes
[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
If you need more power and don't mind losing some of the niceties of
-`asm!`, check out [global_asm](language-features/global-asm.html).
+`asm!`, check out [global_asm](global-asm.md).
[#29641]: https://github.com/rust-lang/rust/issues/29641
-See also [`box_syntax`](language-features/box-syntax.html)
+See also [`box_syntax`](box-syntax.md)
------------------------
[#49733]: https://github.com/rust-lang/rust/issues/49733
-See also [`box_patterns`](language-features/box-patterns.html)
+See also [`box_patterns`](box-patterns.md)
------------------------
If you don't need quite as much power and flexibility as
`global_asm!` provides, and you don't mind restricting your inline
assembly to `fn` bodies only, you might try the
-[asm](language-features/asm.html) feature instead.
+[asm](asm.md) feature instead.
also requires enabling the library feature `compiler_builtins_lib`. You can read
more about this [here][compiler-builtins-lib].
-[compiler-builtins-lib]: library-features/compiler-builtins-lib.html
+[compiler-builtins-lib]: ../library-features/compiler-builtins-lib.md
## More about the language items
[`XID_start`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Start%3A%5D&abb=on&g=&i=
[`XID_continue`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Continue%3A%5D&abb=on&g=&i=
-[strict keywords]: ../reference/keywords.html#strict-keywords
+[strict keywords]: ../../reference/keywords.md#strict-keywords
[`plugin`] and `rustc_private` features as well. For more details, see
their docs.
-[`plugin`]: language-features/plugin.html
+[`plugin`]: plugin.md
------------------------
This feature is part of "compiler plugins." It will often be used with the
[`plugin_registrar`] and `rustc_private` features.
-[`plugin_registrar`]: language-features/plugin-registrar.html
+[`plugin_registrar`]: plugin-registrar.md
------------------------
Plugins can extend Rust's syntax in various ways. One kind of syntax extension
is the procedural macro. These are invoked the same way as [ordinary
-macros](../book/macros.html), but the expansion is performed by arbitrary Rust
+macros](../../book/macros.md), but the expansion is performed by arbitrary Rust
code that manipulates syntax trees at
compile time.
a way to define new literal syntax for any data type.
In addition to procedural macros, you can define new
-[`derive`](../reference/attributes/derive.html)-like attributes and other kinds
+[`derive`](../../reference/attributes/derive.md)-like attributes and other kinds
of extensions. See `Registry::register_syntax_extension` and the
`SyntaxExtension` enum. For a more involved macro example, see
[`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs).
# Lint plugins
Plugins can extend [Rust's lint
-infrastructure](../reference/attributes/diagnostics.html#lint-check-attributes) with
+infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with
additional checks for code style, safety, etc. Now let's write a plugin
[`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs)
that warns about any item named `lintme`.
to access type information.
Lints defined by plugins are controlled by the usual [attributes and compiler
-flags](../reference/attributes/diagnostics.html#lint-check-attributes), e.g.
+flags](../../reference/attributes/diagnostics.md#lint-check-attributes), e.g.
`#[allow(test_lint)]` or `-A test-lint`. These identifiers are derived from the
first argument to `declare_lint!`, with appropriate case and punctuation
conversion.
The tracking issue for this feature is [#29625]
-See Also: [`fn_traits`](library-features/fn-traits.html)
+See Also: [`fn_traits`](../library-features/fn-traits.md)
[#29625]: https://github.com/rust-lang/rust/issues/29625
The tracking issue for this feature is [#29625]
-See Also: [`unboxed_closures`](language-features/unboxed-closures.html)
+See Also: [`unboxed_closures`](../language-features/unboxed-closures.md)
[#29625]: https://github.com/rust-lang/rust/issues/29625
Before the introduction of [`unsized_locals`][unsized_locals], we had been unable to provide the former impls. That means, unlike `&dyn Fn()` or `&mut dyn FnMut()` we could not use `Box<dyn FnOnce()>` at that time.
-[unsized_locals]: language-features/unsized-locals.html
+[unsized_locals]: ../language-features/unsized-locals.md
`FnBox()` is an alternative approach to `Box<dyn FnBox()>` is delegated to `FnBox::call_box` which doesn't need unsized locals. As we now have `Box<dyn FnOnce()>` working, the `fnbox` feature is going to be removed.
The `box_syntax` feature [has a chapter][box] describing how to use it.
-[box]: language-features/box-syntax.html
+[box]: language-features/box-syntax.md
Because this documentation relates to unstable features, we make no guarantees
that what is contained here is accurate or up to date. It's developed on a
#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)]
#![feature(alloc_layout_extra)]
#![feature(try_trait)]
-#![feature(iter_nth_back)]
// Allow testing this library
///
/// Using `AsMut` as trait bound for a generic function we can accept all mutable references
/// that can be converted to type `&mut T`. Because [`Box<T>`] implements `AsMut<T>` we can
-/// write a function `add_one`that takes all arguments that can be converted to `&mut u64`.
-/// Because [`Box<T>`] implements `AsMut<T>` `add_one` accepts arguments of type
+/// write a function `add_one` that takes all arguments that can be converted to `&mut u64`.
+/// Because [`Box<T>`] implements `AsMut<T>`, `add_one` accepts arguments of type
/// `&mut Box<u64>` as well:
///
/// ```
/// Basic usage:
///
/// ```
- /// #![feature(iter_nth_back)]
/// let a = [1, 2, 3];
/// assert_eq!(a.iter().nth_back(2), Some(&1));
/// ```
/// Calling `nth_back()` multiple times doesn't rewind the iterator:
///
/// ```
- /// #![feature(iter_nth_back)]
/// let a = [1, 2, 3];
///
/// let mut iter = a.iter();
/// Returning `None` if there are less than `n + 1` elements:
///
/// ```
- /// #![feature(iter_nth_back)]
/// let a = [1, 2, 3];
/// assert_eq!(a.iter().nth_back(10), None);
/// ```
#[inline]
- #[unstable(feature = "iter_nth_back", issue = "56995")]
+ #[stable(feature = "iter_nth_back", since = "1.37.0")]
fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
for x in self.rev() {
if n == 0 { return Some(x) }
#![feature(const_str_len)]
#![feature(const_int_conversion)]
#![feature(const_transmute)]
-#![feature(reverse_bits)]
#![feature(non_exhaustive)]
#![feature(structural_match)]
#![feature(abi_unadjusted)]
Basic usage:
```
-#![feature(reverse_bits)]
-
let n = ", $swap_op, stringify!($SelfT), ";
let m = n.reverse_bits();
assert_eq!(m, ", $reversed, ");
```"),
- #[unstable(feature = "reverse_bits", issue = "48763")]
- #[rustc_const_unstable(feature = "const_int_conversion")]
+ #[stable(feature = "reverse_bits", since = "1.37.0")]
#[inline]
#[must_use]
pub const fn reverse_bits(self) -> Self {
Basic usage:
```
-#![feature(reverse_bits)]
-
let n = ", $swap_op, stringify!($SelfT), ";
let m = n.reverse_bits();
assert_eq!(m, ", $reversed, ");
```"),
- #[unstable(feature = "reverse_bits", issue = "48763")]
+ #[stable(feature = "reverse_bits", since = "1.37.0")]
#[inline]
#[must_use]
pub const fn reverse_bits(self) -> Self {
/// Basic usage:
///
/// ```
- /// #![feature(reverse_bits)]
/// use std::num::Wrapping;
///
/// let n = Wrapping(0b0000000_01010101i16);
/// assert_eq!(m.0 as u16, 0b10101010_00000000);
/// assert_eq!(m, Wrapping(-22016));
/// ```
- #[unstable(feature = "reverse_bits", issue = "48763")]
+ #[stable(feature = "reverse_bits", since = "1.37.0")]
#[inline]
#[must_use]
pub const fn reverse_bits(self) -> Self {
/// * Values of type `&T` are coerced to values of type `&U`
/// * `T` implicitly implements all the (immutable) methods of the type `U`.
///
-/// For more details, visit [the chapter in *The Rust Programming Language*]
-/// [book] as well as the reference sections on [the dereference operator]
-/// [ref-deref-op], [method resolution] and [type coercions].
+/// For more details, visit [the chapter in *The Rust Programming Language*][book]
+/// as well as the reference sections on [the dereference operator][ref-deref-op],
+/// [method resolution] and [type coercions].
///
/// [book]: ../../book/ch15-02-deref.html
/// [`DerefMut`]: trait.DerefMut.html
/// * Values of type `&mut T` are coerced to values of type `&mut U`
/// * `T` implicitly implements all the (mutable) methods of the type `U`.
///
-/// For more details, visit [the chapter in *The Rust Programming Language*]
-/// [book] as well as the reference sections on [the dereference operator]
-/// [ref-deref-op], [method resolution] and [type coercions].
+/// For more details, visit [the chapter in *The Rust Programming Language*][book]
+/// as well as the reference sections on [the dereference operator][ref-deref-op],
+/// [method resolution] and [type coercions].
///
/// [book]: ../../book/ch15-02-deref.html
/// [`Deref`]: trait.Deref.html
#![feature(fmt_internals)]
#![feature(hashmap_internals)]
#![feature(is_sorted)]
-#![feature(iter_nth_back)]
#![feature(iter_once_with)]
#![feature(pattern)]
#![feature(range_is_empty)]
#![feature(test)]
#![feature(trusted_len)]
#![feature(try_trait)]
-#![feature(reverse_bits)]
#![feature(inner_deref)]
#![feature(slice_internals)]
#![feature(slice_partition_dedup)]
macro_rules! arena_types {
($macro:path, $args:tt, $tcx:lifetime) => (
$macro!($args, [
+ [] layouts: rustc::ty::layout::LayoutDetails,
+ [] generics: rustc::ty::Generics,
+ [] trait_def: rustc::ty::TraitDef,
+ [] adt_def: rustc::ty::AdtDef,
+ [] steal_mir: rustc::ty::steal::Steal<rustc::mir::Body<$tcx>>,
+ [] mir: rustc::mir::Body<$tcx>,
+ [] tables: rustc::ty::TypeckTables<$tcx>,
+ [] const_allocs: rustc::mir::interpret::Allocation,
[] vtable_method: Option<(
rustc::hir::def_id::DefId,
rustc::ty::subst::SubstsRef<$tcx>
ty::ReClosureBound(vid) => {
vid.hash_stable(hcx, hasher);
}
- ty::ReLateBound(..) |
ty::ReVar(..) |
ty::RePlaceholder(..) => {
bug!("StableHasher: unexpected region {:?}", *self)
format!("the anonymous lifetime #{} defined on", idx + 1),
self.hir().span_by_hir_id(node),
),
- ty::BrFresh(_) => (
- "an anonymous lifetime defined on".to_owned(),
- self.hir().span_by_hir_id(node),
- ),
_ => (
format!("the lifetime {} as defined on", region),
cm.def_span(self.hir().span_by_hir_id(node)),
use rustc_data_structures::unify as ut;
use crate::ty::ReStatic;
use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::{BrFresh, ReLateBound, ReVar};
+use crate::ty::{ReLateBound, ReVar};
use crate::ty::{Region, RegionVid};
use std::collections::BTreeMap;
-use std::{cmp, fmt, mem, u32};
+use std::{cmp, fmt, mem};
use std::ops::Range;
mod leak_check;
/// exist). This prevents us from making many such regions.
glbs: CombineMap<'tcx>,
- /// Global counter used during the GLB algorithm to create unique
- /// names for fresh bound regions
- bound_count: u32,
-
/// The undo log records actions that might later be undone.
///
/// Note: `num_open_snapshots` is used to track if we are actively
data,
lubs,
glbs,
- bound_count: _,
undo_log: _,
num_open_snapshots: _,
unification_table,
}
}
- pub fn new_bound(
- &mut self,
- tcx: TyCtxt<'_, '_, 'tcx>,
- debruijn: ty::DebruijnIndex,
- ) -> Region<'tcx> {
- // Creates a fresh bound variable for use in GLB computations.
- // See discussion of GLB computation in the large comment at
- // the top of this file for more details.
- //
- // This computation is potentially wrong in the face of
- // rollover. It's conceivable, if unlikely, that one might
- // wind up with accidental capture for nested functions in
- // that case, if the outer function had bound regions created
- // a very long time before and the inner function somehow
- // wound up rolling over such that supposedly fresh
- // identifiers were in fact shadowed. For now, we just assert
- // that there is no rollover -- eventually we should try to be
- // robust against this possibility, either by checking the set
- // of bound identifiers that appear in a given expression and
- // ensure that we generate one that is distinct, or by
- // changing the representation of bound regions in a fn
- // declaration
-
- let sc = self.bound_count;
- self.bound_count = sc + 1;
-
- if sc >= self.bound_count {
- bug!("rollover in RegionInference new_bound()");
- }
-
- tcx.mk_region(ReLateBound(debruijn, BrFresh(sc)))
- }
-
fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
// cannot add constraints once regions are resolved
debug!(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
alloc_id: AllocId,
) -> Result<(), E::Error> {
- let alloc_kind: AllocKind<'tcx> =
+ let alloc: GlobalAlloc<'tcx> =
tcx.alloc_map.lock().get(alloc_id).expect("no value for AllocId");
- match alloc_kind {
- AllocKind::Memory(alloc) => {
+ match alloc {
+ GlobalAlloc::Memory(alloc) => {
trace!("encoding {:?} with {:#?}", alloc_id, alloc);
AllocDiscriminant::Alloc.encode(encoder)?;
alloc.encode(encoder)?;
}
- AllocKind::Function(fn_instance) => {
+ GlobalAlloc::Function(fn_instance) => {
trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
AllocDiscriminant::Fn.encode(encoder)?;
fn_instance.encode(encoder)?;
}
- AllocKind::Static(did) => {
+ GlobalAlloc::Static(did) => {
// referring to statics doesn't need to know about their allocations,
// just about its DefId
AllocDiscriminant::Static.encode(encoder)?;
assert!(alloc_id.is_none());
trace!("creating extern static alloc id at");
let did = DefId::decode(decoder)?;
- let alloc_id = decoder.tcx().alloc_map.lock().intern_static(did);
+ let alloc_id = decoder.tcx().alloc_map.lock().create_static_alloc(did);
Ok(alloc_id)
}
}
}
}
+/// An allocation in the global (tcx-managed) memory can be either a function pointer,
+/// a static, or a "real" allocation with some data in it.
#[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable, HashStable)]
-pub enum AllocKind<'tcx> {
+pub enum GlobalAlloc<'tcx> {
/// The alloc ID is used as a function pointer
Function(Instance<'tcx>),
/// The alloc ID points to a "lazy" static variable that did not get computed (yet).
pub struct AllocMap<'tcx> {
/// Lets you know what an `AllocId` refers to.
- id_to_kind: FxHashMap<AllocId, AllocKind<'tcx>>,
+ alloc_map: FxHashMap<AllocId, GlobalAlloc<'tcx>>,
- /// Used to ensure that statics only get one associated `AllocId`.
- type_interner: FxHashMap<AllocKind<'tcx>, AllocId>,
+ /// Used to ensure that statics and functions only get one associated `AllocId`.
+ /// Should never contain a `GlobalAlloc::Memory`!
+ /// FIXME: Should we just have two separate dedup maps for statics and functions each?
+ dedup: FxHashMap<GlobalAlloc<'tcx>, AllocId>,
/// The `AllocId` to assign to the next requested ID.
/// Always incremented, never gets smaller.
impl<'tcx> AllocMap<'tcx> {
pub fn new() -> Self {
AllocMap {
- id_to_kind: Default::default(),
- type_interner: Default::default(),
+ alloc_map: Default::default(),
+ dedup: Default::default(),
next_id: AllocId(0),
}
}
next
}
- fn intern(&mut self, alloc_kind: AllocKind<'tcx>) -> AllocId {
- if let Some(&alloc_id) = self.type_interner.get(&alloc_kind) {
+ /// Reserve 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(&mut self, alloc: GlobalAlloc<'tcx>) -> AllocId {
+ match alloc {
+ GlobalAlloc::Function(..) | GlobalAlloc::Static(..) => {},
+ GlobalAlloc::Memory(..) => bug!("Trying to dedup-reserve memory with real data!"),
+ }
+ if let Some(&alloc_id) = self.dedup.get(&alloc) {
return alloc_id;
}
let id = self.reserve();
- debug!("creating alloc_kind {:?} with id {}", alloc_kind, id);
- self.id_to_kind.insert(id, alloc_kind.clone());
- self.type_interner.insert(alloc_kind, id);
+ debug!("creating alloc {:?} with id {}", alloc, id);
+ self.alloc_map.insert(id, alloc.clone());
+ self.dedup.insert(alloc, id);
id
}
+ /// 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(&mut 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(&mut 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
if is_generic {
// Get a fresh ID
let id = self.reserve();
- self.id_to_kind.insert(id, AllocKind::Function(instance));
+ self.alloc_map.insert(id, GlobalAlloc::Function(instance));
id
} else {
// Deduplicate
- self.intern(AllocKind::Function(instance))
+ self.reserve_and_set_dedup(GlobalAlloc::Function(instance))
}
}
+ /// Intern the `Allocation` and return a new `AllocId`, even if there's already an identical
+ /// `Allocation` with a different `AllocId`.
+ /// 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(&mut self, mem: &'tcx Allocation) -> AllocId {
+ let id = self.reserve();
+ self.set_alloc_id_memory(id, mem);
+ id
+ }
+
/// Returns `None` in case the `AllocId` is dangling. An `InterpretCx` can still have a
/// local `Allocation` for that `AllocId`, but having such an `AllocId` in a constant is
/// illegal and will likely ICE.
/// 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(&self, id: AllocId) -> Option<AllocKind<'tcx>> {
- self.id_to_kind.get(&id).cloned()
+ pub fn get(&self, id: AllocId) -> Option<GlobalAlloc<'tcx>> {
+ self.alloc_map.get(&id).cloned()
}
/// Panics if the `AllocId` does not refer to an `Allocation`
pub fn unwrap_memory(&self, id: AllocId) -> &'tcx Allocation {
match self.get(id) {
- Some(AllocKind::Memory(mem)) => mem,
+ Some(GlobalAlloc::Memory(mem)) => mem,
_ => bug!("expected allocation id {} to point to memory", id),
}
}
- /// 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 intern_static(&mut self, static_id: DefId) -> AllocId {
- self.intern(AllocKind::Static(static_id))
- }
-
- /// Intern the `Allocation` and return a new `AllocId`, even if there's already an identical
- /// `Allocation` with a different `AllocId`.
- // FIXME: is this really necessary? Can we ensure `FOO` and `BAR` being different after codegen
- // in `static FOO: u32 = 42; static BAR: u32 = 42;` even if they reuse the same allocation
- // inside rustc?
- pub fn allocate(&mut self, mem: &'tcx Allocation) -> AllocId {
- let id = self.reserve();
- self.set_alloc_id_memory(id, mem);
- id
- }
-
/// Freeze 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(&mut self, id: AllocId, mem: &'tcx Allocation) {
- if let Some(old) = self.id_to_kind.insert(id, AllocKind::Memory(mem)) {
+ if let Some(old) = self.alloc_map.insert(id, GlobalAlloc::Memory(mem)) {
bug!("tried to set allocation id {}, but it was already existing as {:#?}", id, old);
}
}
/// Freeze 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(&mut self, id: AllocId, mem: &'tcx Allocation) {
- self.id_to_kind.insert_same(id, AllocKind::Memory(mem));
+ self.alloc_map.insert_same(id, GlobalAlloc::Memory(mem));
}
}
load_cached(tcx, id) {
let generics: Option<ty::Generics> = tcx.queries.on_disk_cache
.try_load_query_result(tcx, id);
- generics.map(|x| tcx.alloc_generics(x))
+ generics.map(|x| &*tcx.arena.alloc(x))
}
}
load_cached(tcx, id) {
let mir: Option<crate::mir::Body<'tcx>> = tcx.queries.on_disk_cache
.try_load_query_result(tcx, id);
- mir.map(|x| tcx.alloc_mir(x))
+ mir.map(|x| &*tcx.arena.alloc(x))
}
}
}
.queries.on_disk_cache
.try_load_query_result(tcx, id);
- typeck_tables.map(|tables| tcx.alloc_tables(tables))
+ typeck_tables.map(|tables| &*tcx.arena.alloc(tables))
}
}
}
}
// already reported in the query
- ConstEvalFailure(_) => {
- self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error");
+ ConstEvalFailure(err) => {
+ self.tcx.sess.delay_span_bug(
+ span,
+ &format!("constant in type had an ignored error: {:?}", err),
+ );
return;
}
use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
StableHasher, StableHasherResult,
StableVec};
-use arena::{TypedArena, SyncDroplessArena};
+use arena::SyncDroplessArena;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal};
use std::any::Any;
use crate::hir;
-pub struct AllArenas<'tcx> {
- pub global: WorkerLocal<GlobalArenas<'tcx>>,
+pub struct AllArenas {
pub interner: SyncDroplessArena,
}
-impl<'tcx> AllArenas<'tcx> {
+impl AllArenas {
pub fn new() -> Self {
AllArenas {
- global: WorkerLocal::new(|_| GlobalArenas::default()),
interner: SyncDroplessArena::default(),
}
}
}
-/// Internal storage
-#[derive(Default)]
-pub struct GlobalArenas<'tcx> {
- // internings
- layout: TypedArena<LayoutDetails>,
-
- // references
- generics: TypedArena<ty::Generics>,
- trait_def: TypedArena<ty::TraitDef>,
- adt_def: TypedArena<ty::AdtDef>,
- steal_mir: TypedArena<Steal<Body<'tcx>>>,
- mir: TypedArena<Body<'tcx>>,
- tables: TypedArena<ty::TypeckTables<'tcx>>,
- /// miri allocations
- const_allocs: TypedArena<interpret::Allocation>,
-}
-
type InternedSet<'tcx, T> = Lock<FxHashMap<Interned<'tcx, T>, ()>>;
pub struct CtxtInterners<'tcx> {
pub struct GlobalCtxt<'tcx> {
pub arena: WorkerLocal<Arena<'tcx>>,
- global_arenas: &'tcx WorkerLocal<GlobalArenas<'tcx>>,
+
global_interners: CtxtInterners<'tcx>,
cstore: &'tcx CrateStoreDyn,
&self.hir_map
}
- pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics {
- self.global_arenas.generics.alloc(generics)
- }
-
pub fn alloc_steal_mir(self, mir: Body<'gcx>) -> &'gcx Steal<Body<'gcx>> {
- self.global_arenas.steal_mir.alloc(Steal::new(mir))
- }
-
- pub fn alloc_mir(self, mir: Body<'gcx>) -> &'gcx Body<'gcx> {
- self.global_arenas.mir.alloc(mir)
- }
-
- pub fn alloc_tables(self, tables: ty::TypeckTables<'gcx>) -> &'gcx ty::TypeckTables<'gcx> {
- self.global_arenas.tables.alloc(tables)
- }
-
- pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef {
- self.global_arenas.trait_def.alloc(def)
+ self.arena.alloc(Steal::new(mir))
}
pub fn alloc_adt_def(self,
repr: ReprOptions)
-> &'gcx ty::AdtDef {
let def = ty::AdtDef::new(self, did, kind, variants, repr);
- self.global_arenas.adt_def.alloc(def)
+ self.arena.alloc(def)
}
pub fn intern_const_alloc(self, alloc: Allocation) -> &'gcx Allocation {
self.allocation_interner.borrow_mut().intern(alloc, |alloc| {
- self.global_arenas.const_allocs.alloc(alloc)
+ self.arena.alloc(alloc)
})
}
// create an allocation that just contains these bytes
let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes, ());
let alloc = self.intern_const_alloc(alloc);
- self.alloc_map.lock().allocate(alloc)
+ self.alloc_map.lock().create_memory_alloc(alloc)
}
pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability {
self.stability_interner.borrow_mut().intern(stab, |stab| {
- self.global_interners.arena.alloc(stab)
+ self.arena.alloc(stab)
})
}
pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails {
self.layout_interner.borrow_mut().intern(layout, |layout| {
- self.global_arenas.layout.alloc(layout)
+ self.arena.alloc(layout)
})
}
cstore: &'tcx CrateStoreDyn,
local_providers: ty::query::Providers<'tcx>,
extern_providers: ty::query::Providers<'tcx>,
- arenas: &'tcx AllArenas<'tcx>,
+ arenas: &'tcx AllArenas,
resolutions: ty::Resolutions,
hir: hir_map::Map<'tcx>,
on_disk_query_result_cache: query::OnDiskCache<'tcx>,
sess: s,
cstore,
arena: WorkerLocal::new(|_| Arena::default()),
- global_arenas: &arenas.global,
global_interners: interners,
dep_graph,
common,
}
}
+ let count = count.assert_usize(tcx).ok_or(LayoutError::Unknown(ty))?;
let element = self.layout_of(element)?;
- let count = count.unwrap_usize(tcx);
let size = element.size.checked_mul(count, dl)
.ok_or(LayoutError::SizeOverflow(ty))?;
pub use self::binding::BindingMode;
pub use self::binding::BindingMode::*;
-pub use self::context::{TyCtxt, FreeRegionInfo, GlobalArenas, AllArenas, tls, keep_local};
+pub use self::context::{TyCtxt, FreeRegionInfo, AllArenas, tls, keep_local};
pub use self::context::{Lift, TypeckTables, CtxtInterners, GlobalCtxt};
pub use self::context::{
UserTypeAnnotationIndex, UserType, CanonicalUserType,
br
}
ty::BrAnon(_) |
- ty::BrFresh(_) |
ty::BrEnv => {
let name = loop {
let name = name_by_region_index(region_index);
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
- ty::BrFresh(n) => write!(f, "BrFresh({:?})", n),
ty::BrNamed(did, name) => {
write!(f, "BrNamed({:?}:{:?}, {})",
did.krate, did.index, name)
/// the event of shadowing.
BrNamed(DefId, InternedString),
- /// Fresh bound identifiers created during GLB computations.
- BrFresh(u32),
-
/// Anonymous region for the implicit env pointer parameter
/// to a closure
BrEnv,
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_target::spec::{HasTargetSpec, Target};
use std::borrow::Cow;
+use std::ffi::CStr;
use std::ops::{Deref, Range};
use std::ptr;
use std::iter::TrustedLen;
}
}
-// This is a really awful way to get a zero-length c-string, but better (and a
-// lot more efficient) than doing str::as_c_str("", ...) every time.
-fn noname() -> *const c_char {
- static CNULL: c_char = 0;
- &CNULL
-}
+// FIXME(eddyb) use a checked constructor when they become `const fn`.
+const EMPTY_C_STR: &CStr = unsafe {
+ CStr::from_bytes_with_nul_unchecked(b"\0")
+};
+
+/// Empty string, to be used where LLVM expects an instruction name, indicating
+/// that the instruction is to be left unnamed (i.e. numbered, in textual IR).
+// FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer.
+const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr();
impl BackendTypes for Builder<'_, 'll, 'tcx> {
type Value = <CodegenCx<'ll, 'tcx> as BackendTypes>::Value;
type CodegenCx = CodegenCx<'ll, 'tcx>;
}
+macro_rules! builder_methods_for_value_instructions {
+ ($($name:ident($($arg:ident),*) => $llvm_capi:ident),+ $(,)?) => {
+ $(fn $name(&mut self, $($arg: &'ll Value),*) -> &'ll Value {
+ unsafe {
+ llvm::$llvm_capi(self.llbuilder, $($arg,)* UNNAMED)
+ }
+ })*
+ }
+}
+
impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn new_block<'b>(
cx: &'a CodegenCx<'ll, 'tcx>,
then,
catch,
bundle,
- noname())
+ UNNAMED)
}
}
}
}
- /* Arithmetic */
- fn add(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn fadd(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
- }
+ builder_methods_for_value_instructions! {
+ add(a, b) => LLVMBuildAdd,
+ fadd(a, b) => LLVMBuildFAdd,
+ sub(a, b) => LLVMBuildSub,
+ fsub(a, b) => LLVMBuildFSub,
+ mul(a, b) => LLVMBuildMul,
+ fmul(a, b) => LLVMBuildFMul,
+ udiv(a, b) => LLVMBuildUDiv,
+ exactudiv(a, b) => LLVMBuildExactUDiv,
+ sdiv(a, b) => LLVMBuildSDiv,
+ exactsdiv(a, b) => LLVMBuildExactSDiv,
+ fdiv(a, b) => LLVMBuildFDiv,
+ urem(a, b) => LLVMBuildURem,
+ srem(a, b) => LLVMBuildSRem,
+ frem(a, b) => LLVMBuildFRem,
+ shl(a, b) => LLVMBuildShl,
+ lshr(a, b) => LLVMBuildLShr,
+ ashr(a, b) => LLVMBuildAShr,
+ and(a, b) => LLVMBuildAnd,
+ or(a, b) => LLVMBuildOr,
+ xor(a, b) => LLVMBuildXor,
+ neg(x) => LLVMBuildNeg,
+ fneg(x) => LLVMBuildFNeg,
+ not(x) => LLVMBuildNot,
}
fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe {
- let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname());
+ let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, UNNAMED);
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
- fn sub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn fsub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
- }
- }
-
fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe {
- let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
+ let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, UNNAMED);
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
- fn mul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn fmul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
- }
- }
-
fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe {
- let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname());
+ let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, UNNAMED);
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
-
- fn udiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn exactudiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn sdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn exactsdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn fdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname())
- }
- }
-
fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe {
- let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname());
+ let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, UNNAMED);
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
- fn urem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn srem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn frem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname())
- }
- }
-
fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe {
- let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname());
+ let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, UNNAMED);
llvm::LLVMRustSetHasUnsafeAlgebra(instr);
instr
}
}
- fn shl(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn lshr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn ashr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn and(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn or(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn xor(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname())
- }
- }
-
- fn neg(&mut self, v: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildNeg(self.llbuilder, v, noname())
- }
- }
-
- fn fneg(&mut self, v: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildFNeg(self.llbuilder, v, noname())
- }
- }
-
- fn not(&mut self, v: &'ll Value) -> &'ll Value {
- unsafe {
- llvm::LLVMBuildNot(self.llbuilder, v, noname())
- }
- }
-
fn checked_binop(
&mut self,
oop: OverflowOp,
fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
unsafe {
let alloca = if name.is_empty() {
- llvm::LLVMBuildAlloca(self.llbuilder, ty, noname())
+ llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED)
} else {
let name = SmallCStr::new(name);
llvm::LLVMBuildAlloca(self.llbuilder, ty,
align: Align) -> &'ll Value {
unsafe {
let alloca = if name.is_empty() {
- llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, noname())
+ llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, UNNAMED)
} else {
let name = SmallCStr::new(name);
llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len,
fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value {
unsafe {
- let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
+ let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED);
llvm::LLVMSetAlignment(load, align.bytes() as c_uint);
load
}
fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value {
unsafe {
- let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
+ let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED);
llvm::LLVMSetVolatile(load, llvm::True);
load
}
let load = llvm::LLVMRustBuildAtomicLoad(
self.llbuilder,
ptr,
- noname(),
+ UNNAMED,
AtomicOrdering::from_generic(order),
);
// LLVM requires the alignment of atomic loads to be at least the size of the type.
fn gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
unsafe {
llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
- indices.len() as c_uint, noname())
+ indices.len() as c_uint, UNNAMED)
}
}
fn inbounds_gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
unsafe {
llvm::LLVMBuildInBoundsGEP(
- self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname())
+ self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, UNNAMED)
}
}
fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value {
assert_eq!(idx as c_uint as u64, idx);
unsafe {
- llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
+ llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, UNNAMED)
}
}
/* Casts */
fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname())
+ llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,UNNAMED)
}
}
fn uitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn sitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn fptrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn fpext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn ptrtoint(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn inttoptr(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, UNNAMED)
}
}
fn icmp(&mut self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
let op = llvm::IntPredicate::from_generic(op);
unsafe {
- llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
+ llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED)
}
}
fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
unsafe {
- llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
+ llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED)
}
}
else_val: &'ll Value,
) -> &'ll Value {
unsafe {
- llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
+ llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, UNNAMED)
}
}
#[allow(dead_code)]
fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
+ llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED)
}
}
fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
unsafe {
- llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
+ llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, UNNAMED)
}
}
fn extract_value(&mut self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
assert_eq!(idx as c_uint as u64, idx);
unsafe {
- llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname())
+ llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, UNNAMED)
}
}
assert_eq!(idx as c_uint as u64, idx);
unsafe {
llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
- noname())
+ UNNAMED)
}
}
num_clauses: usize) -> &'ll Value {
unsafe {
llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn,
- num_clauses as c_uint, noname())
+ num_clauses as c_uint, UNNAMED)
}
}
llfn,
args.as_ptr() as *const &llvm::Value,
args.len() as c_uint,
- bundle, noname()
+ bundle, UNNAMED
)
}
}
fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname())
+ llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED)
}
}
idx: &'ll Value,
) -> &'ll Value {
unsafe {
- llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
+ llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, UNNAMED)
}
}
mask: &'ll Value,
) -> &'ll Value {
unsafe {
- llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
+ llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, UNNAMED)
}
}
pub fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
unsafe {
- llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
+ llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED)
}
}
fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
assert_eq!(vals.len(), bbs.len());
let phi = unsafe {
- llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
+ llvm::LLVMBuildPhi(self.llbuilder, ty, UNNAMED)
};
unsafe {
llvm::LLVMAddIncoming(phi, vals.as_ptr(),
use crate::consts::const_alloc_to_llvm;
use rustc::ty::layout::{HasDataLayout, LayoutOf, self, TyLayout, Size};
-use rustc::mir::interpret::{Scalar, AllocKind, Allocation};
+use rustc::mir::interpret::{Scalar, GlobalAlloc, Allocation};
use rustc_codegen_ssa::mir::place::PlaceRef;
use libc::{c_uint, c_char};
Scalar::Ptr(ptr) => {
let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
let base_addr = match alloc_kind {
- Some(AllocKind::Memory(alloc)) => {
+ Some(GlobalAlloc::Memory(alloc)) => {
let init = const_alloc_to_llvm(self, alloc);
if alloc.mutability == Mutability::Mutable {
self.static_addr_of_mut(init, alloc.align, None)
self.static_addr_of(init, alloc.align, None)
}
}
- Some(AllocKind::Function(fn_instance)) => {
+ Some(GlobalAlloc::Function(fn_instance)) => {
self.get_fn(fn_instance)
}
- Some(AllocKind::Static(def_id)) => {
+ Some(GlobalAlloc::Static(def_id)) => {
assert!(self.tcx.is_static(def_id));
self.get_static(def_id)
}
let (size, align) = cx.size_and_align_of(array_or_slice_type);
let upper_bound = match array_or_slice_type.sty {
- ty::Array(_, len) => {
- len.unwrap_usize(cx.tcx) as c_longlong
- }
+ ty::Array(_, len) => len.unwrap_usize(cx.tcx) as c_longlong,
_ => -1
};
#![feature(box_patterns)]
#![feature(box_syntax)]
+#![feature(const_cstr_unchecked)]
#![feature(crate_visibility_modifier)]
#![feature(custom_attribute)]
#![feature(extern_types)]
@irinagpopa started to parametrize the types of `rustc_codegen_llvm` by a generic `Value` type, implemented in LLVM by a reference `&'ll Value`. This work has been extended to all structures inside the `mir` folder and elsewhere, as well as for LLVM's `BasicBlock` and `Type` types.
-The two most important structures for the LLVM codegen are `CodegenCx` and `Builder`. They are parametrized by multiple liftime parameters and the type for `Value`.
+The two most important structures for the LLVM codegen are `CodegenCx` and `Builder`. They are parametrized by multiple lifetime parameters and the type for `Value`.
```rust
struct CodegenCx<'ll, 'tcx: 'll> {
_ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout)
};
let a = Scalar::from(Pointer::new(
- bx.tcx().alloc_map.lock().allocate(data),
+ bx.tcx().alloc_map.lock().create_memory_alloc(data),
Size::from_bytes(start as u64),
)).into();
let a_llval = bx.scalar_to_backend(
declare_lint! {
pub ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
- Allow,
+ Warn,
"`...` range patterns are deprecated"
}
provide! { <'tcx> tcx, def_id, other, cdata,
type_of => { cdata.get_type(def_id.index, tcx) }
generics_of => {
- tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess))
+ tcx.arena.alloc(cdata.get_generics(def_id.index, tcx.sess))
}
predicates_of => { tcx.arena.alloc(cdata.get_predicates(def_id.index, tcx)) }
predicates_defined_on => {
}
super_predicates_of => { tcx.arena.alloc(cdata.get_super_predicates(def_id.index, tcx)) }
trait_def => {
- tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess))
+ tcx.arena.alloc(cdata.get_trait_def(def_id.index, tcx.sess))
}
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
adt_destructor => {
bug!("get_optimized_mir: missing MIR for `{:?}`", def_id)
});
- let mir = tcx.alloc_mir(mir);
+ let mir = tcx.arena.alloc(mir);
mir
}
}
}
- ty::BoundRegion::BrAnon(_) | ty::BoundRegion::BrFresh(_) => None,
+ ty::BoundRegion::BrAnon(_) => None,
},
ty::ReLateBound(..)
},
(StaticKind::Promoted(promoted_1), StaticKind::Promoted(promoted_2)) => {
if promoted_1 == promoted_2 {
- if let ty::Array(_, size) = s1.ty.sty {
- if size.unwrap_usize(tcx) == 0 {
+ if let ty::Array(_, len) = s1.ty.sty {
+ if let Some(0) = len.assert_usize(tcx) {
// Ignore conflicts with promoted [T; 0].
debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
return Overlap::Disjoint;
use super::{
Pointer, AllocId, Allocation, GlobalId, AllocationExtra,
- EvalResult, Scalar, InterpError, AllocKind, PointerArithmetic,
+ EvalResult, Scalar, InterpError, GlobalAlloc, PointerArithmetic,
Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg, InboundsCheck,
};
None => {
// Deallocating static memory -- always an error
return match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
- Some(AllocKind::Function(..)) => err!(DeallocatedWrongMemoryKind(
+ Some(GlobalAlloc::Function(..)) => err!(DeallocatedWrongMemoryKind(
"function".to_string(),
format!("{:?}", kind),
)),
- Some(AllocKind::Static(..)) |
- Some(AllocKind::Memory(..)) => err!(DeallocatedWrongMemoryKind(
+ Some(GlobalAlloc::Static(..)) |
+ Some(GlobalAlloc::Memory(..)) => err!(DeallocatedWrongMemoryKind(
"static".to_string(),
format!("{:?}", kind),
)),
) -> EvalResult<'tcx, Cow<'tcx, Allocation<M::PointerTag, M::AllocExtra>>> {
let alloc = tcx.alloc_map.lock().get(id);
let def_id = match alloc {
- Some(AllocKind::Memory(mem)) => {
+ Some(GlobalAlloc::Memory(mem)) => {
// We got tcx memory. Let the machine figure out whether and how to
// turn that into memory with the right pointer tag.
return Ok(M::adjust_static_allocation(mem, memory_extra))
}
- Some(AllocKind::Function(..)) => {
+ Some(GlobalAlloc::Function(..)) => {
return err!(DerefFunctionPointer)
}
- Some(AllocKind::Static(did)) => {
+ Some(GlobalAlloc::Static(did)) => {
did
}
None =>
}
// Could also be a fn ptr or extern static
match self.tcx.alloc_map.lock().get(id) {
- Some(AllocKind::Function(..)) => Ok((Size::ZERO, Align::from_bytes(1).unwrap())),
- Some(AllocKind::Static(did)) => {
+ Some(GlobalAlloc::Function(..)) => Ok((Size::ZERO, Align::from_bytes(1).unwrap())),
+ Some(GlobalAlloc::Static(did)) => {
// The only way `get` couldn't have worked here is if this is an extern static
assert!(self.tcx.is_foreign_item(did));
// Use size and align of the type
}
trace!("reading fn ptr: {}", ptr.alloc_id);
match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
- Some(AllocKind::Function(instance)) => Ok(instance),
+ Some(GlobalAlloc::Function(instance)) => Ok(instance),
_ => Err(InterpError::ExecuteMemory.into()),
}
}
Err(()) => {
// static alloc?
match self.tcx.alloc_map.lock().get(id) {
- Some(AllocKind::Memory(alloc)) => {
+ Some(GlobalAlloc::Memory(alloc)) => {
self.dump_alloc_helper(
&mut allocs_seen, &mut allocs_to_print,
msg, alloc, " (immutable)".to_owned()
);
}
- Some(AllocKind::Function(func)) => {
+ Some(GlobalAlloc::Function(func)) => {
trace!("{} {}", msg, func);
}
- Some(AllocKind::Static(did)) => {
+ Some(GlobalAlloc::Static(did)) => {
trace!("{} {:?}", msg, did);
}
None => {
}
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
- /// Try reading an immediate in memory; this is interesting particularly for ScalarPair.
+ /// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`.
/// Returns `None` if the layout does not permit loading this as a value.
fn try_read_immediate_from_mplace(
&self,
Ok(OpTy { op, layout })
}
- /// Every place can be read from, so we can turm them into an operand
+ /// Every place can be read from, so we can turn them into an operand
#[inline(always)]
pub fn place_to_op(
&self,
}
/// Evaluate the operand, returning a place where you can then find the data.
- /// if you already know the layout, you can save two some table lookups
+ /// If you already know the layout, you can save two table lookups
/// by passing it in here.
pub fn eval_operand(
&self,
ConstValue::Slice { data, start, end } =>
Operand::Immediate(Immediate::ScalarPair(
Scalar::from(Pointer::new(
- self.tcx.alloc_map.lock().allocate(data),
+ self.tcx.alloc_map.lock().create_memory_alloc(data),
Size::from_bytes(start as u64),
)).with_default_tag().into(),
Scalar::from_uint(
Ok(place)
}
- /// Offset a pointer to project to a field. Unlike place_field, this is always
- /// possible without allocating, so it can take &self. Also return the field's layout.
+ /// Offset a pointer to project to a field. Unlike `place_field`, this is always
+ /// possible without allocating, so it can take `&self`. Also return the field's layout.
/// This supports both struct and array fields.
#[inline(always)]
pub fn mplace_field(
// want! This way, computing statics works concistently between codegen
// and miri: They use the same query to eventually obtain a `ty::Const`
// and use that for further computation.
- let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id());
+ let alloc = self.tcx.alloc_map.lock().create_static_alloc(cid.instance.def_id());
MPlaceTy::from_aligned_ptr(Pointer::from(alloc).with_default_tag(), layout)
}
})
}
/// Write an immediate to memory.
- /// If you use this you are responsible for validating that things git copied at the
+ /// If you use this you are responsible for validating that things got copied at the
/// right type.
fn write_immediate_to_mplace_no_validate(
&mut self,
/// Copies the data from an operand to a place. This does not support transmuting!
/// Use `copy_op_transmute` if the layouts could disagree.
- /// Also, if you use this you are responsible for validating that things git copied at the
+ /// Also, if you use this you are responsible for validating that things get copied at the
/// right type.
fn copy_op_no_validate(
&mut self,
use rustc::ty;
use rustc_data_structures::fx::FxHashSet;
use rustc::mir::interpret::{
- Scalar, AllocKind, EvalResult, InterpError, CheckInAllocMsg,
+ Scalar, GlobalAlloc, EvalResult, InterpError, CheckInAllocMsg,
};
use super::{
"integer pointer in non-ZST reference", self.path);
// Skip validation entirely for some external statics
let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id);
- if let Some(AllocKind::Static(did)) = alloc_kind {
+ if let Some(GlobalAlloc::Static(did)) = alloc_kind {
// `extern static` cannot be validated as they have no body.
// FIXME: Statics from other crates are also skipped.
// They might be checked at a different type, but for now we
/// is an indirect operand.
/// It will error if the bits at the destination do not match the ones described by the layout.
///
- /// `ref_tracking` can be None to avoid recursive checking below references.
+ /// `ref_tracking` can be `None` to avoid recursive checking below references.
/// This also toggles between "run-time" (no recursion) and "compile-time" (with recursion)
/// validation (e.g., pointer values are fine in integers at runtime).
pub fn validate_operand(
#![feature(unicode_internals)]
#![feature(step_trait)]
#![feature(slice_concat_ext)]
-#![feature(reverse_bits)]
#![feature(try_blocks)]
#![recursion_limit="256"]
use rustc::mir::{self, Location, Place, PlaceBase, Promoted, Static, StaticKind};
use rustc::mir::visit::Visitor as MirVisitor;
use rustc::mir::mono::MonoItem;
-use rustc::mir::interpret::{Scalar, GlobalId, AllocKind, ErrorHandled};
+use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled};
use crate::monomorphize::{self, Instance};
use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
) {
let alloc_kind = tcx.alloc_map.lock().get(alloc_id);
match alloc_kind {
- Some(AllocKind::Static(did)) => {
- let instance = Instance::mono(tcx, did);
+ Some(GlobalAlloc::Static(def_id)) => {
+ let instance = Instance::mono(tcx, def_id);
if should_monomorphize_locally(tcx, &instance) {
- trace!("collecting static {:?}", did);
- output.push(MonoItem::Static(did));
+ trace!("collecting static {:?}", def_id);
+ output.push(MonoItem::Static(def_id));
}
}
- Some(AllocKind::Memory(alloc)) => {
+ Some(GlobalAlloc::Memory(alloc)) => {
trace!("collecting {:?} with {:#?}", alloc_id, alloc);
for &((), inner) in alloc.relocations.values() {
collect_miri(tcx, inner, output);
}
},
- Some(AllocKind::Function(fn_instance)) => {
+ Some(GlobalAlloc::Function(fn_instance)) => {
if should_monomorphize_locally(tcx, &fn_instance) {
trace!("collecting {:?} with {:#?}", alloc_id, fn_instance);
output.push(create_fn_mono_item(fn_instance));
collect_miri(tcx, id, output);
}
}
- ConstValue::Unevaluated(did, substs) => {
+ ConstValue::Unevaluated(def_id, substs) => {
let param_env = ty::ParamEnv::reveal_all();
let substs = tcx.subst_and_normalize_erasing_regions(
param_substs,
);
let instance = ty::Instance::resolve(tcx,
param_env,
- did,
+ def_id,
substs).unwrap();
let cid = GlobalId {
Ok(val) => collect_const(tcx, val, param_substs, output),
Err(ErrorHandled::Reported) => {},
Err(ErrorHandled::TooGeneric) => span_bug!(
- tcx.def_span(did), "collection encountered polymorphic constant",
+ tcx.def_span(def_id), "collection encountered polymorphic constant",
),
}
}
debug!("make_shim({:?}) = {:?}", instance, result);
- tcx.alloc_mir(result)
+ tcx.arena.alloc(result)
}
#[derive(Copy, Clone, Debug, PartialEq)]
&add_call_guards::CriticalCallEdges,
&dump_mir::Marker("PreCodegen"),
]);
- tcx.alloc_mir(mir)
+ tcx.arena.alloc(mir)
}
} else if let ty::Array(_, len) = ty.sty {
// FIXME(eddyb) the `cx.mode == Mode::Fn` condition
// seems unnecessary, given that this is merely a ZST.
- if !(len.unwrap_usize(cx.tcx) == 0 && cx.mode == Mode::Fn) {
- return true;
+ match len.assert_usize(cx.tcx) {
+ Some(0) if cx.mode == Mode::Fn => {},
+ _ => return true,
}
} else {
return true;
for br in late_bound_in_ret.difference(&late_bound_in_args) {
let lifetime_name = match *br {
ty::BrNamed(_, name) => format!("lifetime `{}`,", name),
- ty::BrAnon(_) | ty::BrFresh(_) | ty::BrEnv => "an anonymous lifetime".to_string(),
+ ty::BrAnon(_) | ty::BrEnv => "an anonymous lifetime".to_string(),
};
let mut err = struct_span_err!(tcx.sess,
decl.output.span(),
let expected_ty = self.structurally_resolved_type(pat.span, expected);
let (inner_ty, slice_ty) = match expected_ty.sty {
ty::Array(inner_ty, size) => {
- let size = size.unwrap_usize(tcx);
- let min_len = before.len() as u64 + after.len() as u64;
- if slice.is_none() {
- if min_len != size {
- struct_span_err!(
- tcx.sess, pat.span, E0527,
- "pattern requires {} elements but array has {}",
- min_len, size)
- .span_label(pat.span, format!("expected {} elements", size))
+ if let Some(size) = size.assert_usize(tcx) {
+ let min_len = before.len() as u64 + after.len() as u64;
+ if slice.is_none() {
+ if min_len != size {
+ struct_span_err!(
+ tcx.sess, pat.span, E0527,
+ "pattern requires {} elements but array has {}",
+ min_len, size)
+ .span_label(pat.span, format!("expected {} elements", size))
+ .emit();
+ }
+ (inner_ty, tcx.types.err)
+ } else if let Some(rest) = size.checked_sub(min_len) {
+ (inner_ty, tcx.mk_array(inner_ty, rest))
+ } else {
+ struct_span_err!(tcx.sess, pat.span, E0528,
+ "pattern requires at least {} elements but array has {}",
+ min_len, size)
+ .span_label(pat.span,
+ format!("pattern cannot match array of {} elements", size))
.emit();
+ (inner_ty, tcx.types.err)
}
- (inner_ty, tcx.types.err)
- } else if let Some(rest) = size.checked_sub(min_len) {
- (inner_ty, tcx.mk_array(inner_ty, rest))
} else {
- struct_span_err!(tcx.sess, pat.span, E0528,
- "pattern requires at least {} elements but array has {}",
- min_len, size)
- .span_label(pat.span,
- format!("pattern cannot match array of {} elements", size))
- .emit();
+ struct_span_err!(
+ tcx.sess,
+ pat.span,
+ E0730,
+ "cannot pattern-match on an array without a fixed length",
+ ).emit();
(inner_ty, tcx.types.err)
}
}
item_def_id, wbcx.tables
);
- self.tcx.alloc_tables(wbcx.tables)
+ self.tcx.arena.alloc(wbcx.tables)
}
}
let is_marker = tcx.has_attr(def_id, sym::marker);
let def_path_hash = tcx.def_path_hash(def_id);
let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, def_path_hash);
- tcx.alloc_trait_def(def)
+ tcx.arena.alloc(def)
}
fn has_late_bound_regions<'a, 'tcx>(
.map(|param| (param.def_id, param.index))
.collect();
- tcx.alloc_generics(ty::Generics {
+ tcx.arena.alloc(ty::Generics {
parent: parent_def_id,
parent_count,
params,
```
"##,
+E0730: r##"
+An array without a fixed length was pattern-matched.
+
+Example of erroneous code:
+
+```compile_fail,E0730
+#![feature(const_generics)]
+
+fn is_123<const N: usize>(x: [u32; N]) -> bool {
+ match x {
+ [1, 2, 3] => true, // error: cannot pattern-match on an
+ // array without a fixed length
+ _ => false
+ }
+}
+```
+
+Ensure that the pattern is consistent with the size of the matched
+array. Additional elements can be matched with `..`:
+
+```
+#![feature(slice_patterns)]
+
+let r = &[1, 2, 3, 4];
+match r {
+ &[a, b, ..] => { // ok!
+ println!("a={}, b={}", a, b);
+ }
+}
+```
+"##,
+
}
register_diagnostics! {
}
}
if attrs.len() > 0 {
- write!(w, "<div class=\"docblock attributes{}\">{}</div>",
+ write!(w, "<span class=\"docblock attributes{}\">{}</span>",
if top { " top-attr" } else { "" }, &attrs)?;
}
Ok(())
compiler_builtins = { version = "0.1.15" }
profiler_builtins = { path = "../libprofiler_builtins", optional = true }
unwind = { path = "../libunwind" }
-hashbrown = { version = "0.3.0", features = ['rustc-dep-of-std'] }
+hashbrown = { version = "0.4.0", features = ['rustc-dep-of-std'] }
[dependencies.backtrace]
version = "0.3.25"
/// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
/// ```
fn from(err: String) -> Box<dyn Error + Send + Sync> {
- #[derive(Debug)]
struct StringError(String);
impl Error for StringError {
}
}
+ // Purposefully skip printing "StringError(..)"
+ impl Debug for StringError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ Debug::fmt(&self.0, f)
+ }
+ }
+
Box::new(StringError(err))
}
}
///
/// The following return false:
///
- /// - private address (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16)
- /// - the loopback address (127.0.0.0/8)
- /// - the link-local address (169.254.0.0/16)
- /// - the broadcast address (255.255.255.255/32)
- /// - test addresses used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24)
- /// - the unspecified address (0.0.0.0)
+ /// - private addresses (see [`is_private()`](#method.is_private))
+ /// - the loopback address (see [`is_loopback()`](#method.is_loopback))
+ /// - the link-local address (see [`is_link_local()`](#method.is_link_local))
+ /// - the broadcast address (see [`is_broadcast()`](#method.is_broadcast))
+ /// - addresses used for documentation (see [`is_documentation()`](#method.is_documentation))
+ /// - the unspecified address (see [`is_unspecified()`](#method.is_unspecified)), and the whole
+ /// 0.0.0.0/8 block
+ /// - addresses reserved for future protocols (see
+ /// [`is_ietf_protocol_assignment()`](#method.is_ietf_protocol_assignment), except
+ /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
+ /// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved)
+ /// - addresses reserved for networking devices benchmarking (see
+ /// [`is_benchmarking`](#method.is_benchmarking))
///
/// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
/// [`true`]: ../../std/primitive.bool.html
/// use std::net::Ipv4Addr;
///
/// fn main() {
+ /// // private addresses are not global
/// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
/// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
/// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
+ ///
+ /// // the 0.0.0.0/8 block is not global
+ /// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false);
+ /// // in particular, the unspecified address is not global
/// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false);
+ ///
+ /// // the loopback address is not global
+ /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false);
+ ///
+ /// // link local addresses are not global
+ /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
+ ///
+ /// // the broadcast address is not global
+ /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false);
+ ///
+ /// // the broadcast address is not global
+ /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
+ /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
+ /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
+ ///
+ /// // shared addresses are not global
+ /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
+ ///
+ /// // addresses reserved for protocol assignment are not global
+ /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false);
+ /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false);
+ ///
+ /// // addresses reserved for future use are not global
+ /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
+ ///
+ /// // addresses reserved for network devices benchmarking are not global
+ /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
+ ///
+ /// // All the other addresses are global
+ /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
/// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
/// }
/// ```
pub fn is_global(&self) -> bool {
- !self.is_private() && !self.is_loopback() && !self.is_link_local() &&
- !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified()
+ // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
+ // globally routable addresses in the 192.0.0.0/24 range.
+ if u32::from(*self) == 0xc0000009 || u32::from(*self) == 0xc000000a {
+ return true;
+ }
+ !self.is_private()
+ && !self.is_loopback()
+ && !self.is_link_local()
+ && !self.is_broadcast()
+ && !self.is_documentation()
+ && !self.is_shared()
+ && !self.is_ietf_protocol_assignment()
+ && !self.is_reserved()
+ && !self.is_benchmarking()
+ // Make sure the address is not in 0.0.0.0/8
+ && self.octets()[0] != 0
+ }
+
+ /// Returns [`true`] if this address is part of the Shared Address Space defined in
+ /// [IETF RFC 6598] (`100.64.0.0/10`).
+ ///
+ /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
+ /// [`true`]: ../../std/primitive.bool.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::Ipv4Addr;
+ ///
+ /// fn main() {
+ /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true);
+ /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
+ /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
+ /// }
+ /// ```
+ pub fn is_shared(&self) -> bool {
+ self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
+ }
+
+ /// Returns [`true`] if this address is part of `192.0.0.0/24`, which is reserved to
+ /// IANA for IETF protocol assignments, as documented in [IETF RFC 6890].
+ ///
+ /// Note that parts of this block are in use:
+ ///
+ /// - `192.0.0.8/32` is the "IPv4 dummy address" (see [IETF RFC 7600])
+ /// - `192.0.0.9/32` is the "Port Control Protocol Anycast" (see [IETF RFC 7723])
+ /// - `192.0.0.10/32` is used for NAT traversal (see [IETF RFC 8155])
+ ///
+ /// [IETF RFC 6890]: https://tools.ietf.org/html/rfc6890
+ /// [IETF RFC 7600]: https://tools.ietf.org/html/rfc7600
+ /// [IETF RFC 7723]: https://tools.ietf.org/html/rfc7723
+ /// [IETF RFC 8155]: https://tools.ietf.org/html/rfc8155
+ /// [`true`]: ../../std/primitive.bool.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::Ipv4Addr;
+ ///
+ /// fn main() {
+ /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_ietf_protocol_assignment(), true);
+ /// assert_eq!(Ipv4Addr::new(192, 0, 0, 8).is_ietf_protocol_assignment(), true);
+ /// assert_eq!(Ipv4Addr::new(192, 0, 0, 9).is_ietf_protocol_assignment(), true);
+ /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_ietf_protocol_assignment(), true);
+ /// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false);
+ /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false);
+ /// }
+ /// ```
+ pub fn is_ietf_protocol_assignment(&self) -> bool {
+ self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0
+ }
+
+ /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for
+ /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
+ /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
+ ///
+ /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
+ /// [errate 423]: https://www.rfc-editor.org/errata/eid423
+ /// [`true`]: ../../std/primitive.bool.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::Ipv4Addr;
+ ///
+ /// fn main() {
+ /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false);
+ /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true);
+ /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
+ /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
+ /// }
+ /// ```
+ pub fn is_benchmarking(&self) -> bool {
+ self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
+ }
+
+ /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112]
+ /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the
+ /// broadcast address `255.255.255.255`, but this implementation explicitely excludes it, since
+ /// it is obviously not reserved for future use.
+ ///
+ /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
+ /// [`true`]: ../../std/primitive.bool.html
+ ///
+ /// # Warning
+ ///
+ /// As IANA assigns new addresses, this method will be
+ /// updated. This may result in non-reserved addresses being
+ /// treated as reserved in code that relies on an outdated version
+ /// of this method.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ /// use std::net::Ipv4Addr;
+ ///
+ /// fn main() {
+ /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true);
+ /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true);
+ ///
+ /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false);
+ /// // The broadcast address is not considered as reserved for future use by this
+ /// // implementation
+ /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
+ /// }
+ /// ```
+ pub fn is_reserved(&self) -> bool {
+ self.octets()[0] & 240 == 240 && !self.is_broadcast()
}
/// Returns [`true`] if this is a multicast address (224.0.0.0/4).
}
}
- /// Returns [`true`] if this is a unique local address (fc00::/7).
+ /// Returns [`true`] if this is a unique local address (`fc00::/7`).
///
/// This property is defined in [IETF RFC 4193].
///
(self.segments()[0] & 0xfe00) == 0xfc00
}
- /// Returns [`true`] if the address is unicast and link-local (fe80::/10).
+ /// Returns [`true`] if the address is a unicast link-local address (`fe80::/64`).
///
- /// This property is defined in [IETF RFC 4291].
+ /// A common mis-conception is to think that "unicast link-local addresses start with
+ /// `fe80::`", but the [IETF RFC 4291] actually defines a stricter format for these addresses:
+ ///
+ /// ```no_rust
+ /// | 10 |
+ /// | bits | 54 bits | 64 bits |
+ /// +----------+-------------------------+----------------------------+
+ /// |1111111010| 0 | interface ID |
+ /// +----------+-------------------------+----------------------------+
+ /// ```
+ ///
+ /// This method validates the format defined in the RFC and won't recognize the following
+ /// addresses such as `fe80:0:0:1::` or `fe81::` as unicast link-local addresses for example.
+ /// If you need a less strict validation use [`is_unicast_link_local()`] instead.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ip)]
+ ///
+ /// use std::net::Ipv6Addr;
+ ///
+ /// fn main() {
+ /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0);
+ /// assert!(ip.is_unicast_link_local_strict());
+ ///
+ /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff);
+ /// assert!(ip.is_unicast_link_local_strict());
+ ///
+ /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0);
+ /// assert!(!ip.is_unicast_link_local_strict());
+ /// assert!(ip.is_unicast_link_local());
+ ///
+ /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0);
+ /// assert!(!ip.is_unicast_link_local_strict());
+ /// assert!(ip.is_unicast_link_local());
+ /// }
+ /// ```
+ ///
+ /// # See also
+ ///
+ /// - [IETF RFC 4291 section 2.5.6]
+ /// - [RFC 4291 errata 4406]
+ /// - [`is_unicast_link_local()`]
///
/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+ /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
/// [`true`]: ../../std/primitive.bool.html
+ /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
+ /// [`is_unicast_link_local()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local
+ ///
+ pub fn is_unicast_link_local_strict(&self) -> bool {
+ (self.segments()[0] & 0xffff) == 0xfe80
+ && (self.segments()[1] & 0xffff) == 0
+ && (self.segments()[2] & 0xffff) == 0
+ && (self.segments()[3] & 0xffff) == 0
+ }
+
+ /// Returns [`true`] if the address is a unicast link-local address (`fe80::/10`).
+ ///
+ /// This method returns [`true`] for addresses in the range reserved by [RFC 4291 section 2.4],
+ /// i.e. addresses with the following format:
+ ///
+ /// ```no_rust
+ /// | 10 |
+ /// | bits | 54 bits | 64 bits |
+ /// +----------+-------------------------+----------------------------+
+ /// |1111111010| arbitratry value | interface ID |
+ /// +----------+-------------------------+----------------------------+
+ /// ```
+ ///
+ /// As a result, this method consider addresses such as `fe80:0:0:1::` or `fe81::` to be
+ /// unicast link-local addresses, whereas [`is_unicast_link_local_strict()`] does not. If you
+ /// need a strict validation fully compliant with the RFC, use
+ /// [`is_unicast_link_local_strict()`].
///
/// # Examples
///
/// use std::net::Ipv6Addr;
///
/// fn main() {
- /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(),
- /// false);
- /// assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
+ /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0);
+ /// assert!(ip.is_unicast_link_local());
+ ///
+ /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff);
+ /// assert!(ip.is_unicast_link_local());
+ ///
+ /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0);
+ /// assert!(ip.is_unicast_link_local());
+ /// assert!(!ip.is_unicast_link_local_strict());
+ ///
+ /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0);
+ /// assert!(ip.is_unicast_link_local());
+ /// assert!(!ip.is_unicast_link_local_strict());
/// }
/// ```
+ ///
+ /// # See also
+ ///
+ /// - [IETF RFC 4291 section 2.4]
+ /// - [RFC 4291 errata 4406]
+ ///
+ /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
+ /// [`true`]: ../../std/primitive.bool.html
+ /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
+ /// [`is_unicast_link_local_strict()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local_strict
+ ///
pub fn is_unicast_link_local(&self) -> bool {
(self.segments()[0] & 0xffc0) == 0xfe80
}
- /// Returns [`true`] if this is a deprecated unicast site-local address
- /// (fec0::/10).
+ /// Returns [`true`] if this is a deprecated unicast site-local address (fec0::/10). The
+ /// unicast site-local address format is defined in [RFC 4291 section 2.5.7] as:
+ ///
+ /// ```no_rust
+ /// | 10 |
+ /// | bits | 54 bits | 64 bits |
+ /// +----------+-------------------------+----------------------------+
+ /// |1111111011| subnet ID | interface ID |
+ /// +----------+-------------------------+----------------------------+
+ /// ```
///
/// [`true`]: ../../std/primitive.bool.html
+ /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
///
/// # Examples
///
/// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true);
/// }
/// ```
+ ///
+ /// # Warning
+ ///
+ /// As per [RFC 3879], the whole `FEC0::/10` prefix is
+ /// deprecated. New software must not support site-local
+ /// addresses.
+ ///
+ /// [RFC 3879]: https://tools.ietf.org/html/rfc3879
pub fn is_unicast_site_local(&self) -> bool {
(self.segments()[0] & 0xffc0) == 0xfec0
}
///
/// - the loopback address
/// - the link-local addresses
- /// - the (deprecated) site-local addresses
/// - unique local addresses
/// - the unspecified address
/// - the address range reserved for documentation
///
+ /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7]
+ ///
+ /// ```no_rust
+ /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer
+ /// be supported in new implementations (i.e., new implementations must treat this prefix as
+ /// Global Unicast).
+ /// ```
+ ///
/// [`true`]: ../../std/primitive.bool.html
+ /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
///
/// # Examples
///
/// ```
pub fn is_unicast_global(&self) -> bool {
!self.is_multicast()
- && !self.is_loopback() && !self.is_unicast_link_local()
- && !self.is_unicast_site_local() && !self.is_unique_local()
- && !self.is_unspecified() && !self.is_documentation()
+ && !self.is_loopback()
+ && !self.is_unicast_link_local()
+ && !self.is_unique_local()
+ && !self.is_unspecified()
+ && !self.is_documentation()
}
/// Returns the address's multicast scope if the address is multicast.
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests {
use crate::net::*;
- use crate::net::Ipv6MulticastScope::*;
use crate::net::test::{tsa, sa6, sa4};
+ use crate::str::FromStr;
#[test]
fn test_from_str_ipv4() {
#[test]
fn ip_properties() {
- fn check4(octets: &[u8; 4], unspec: bool, loopback: bool,
- global: bool, multicast: bool, documentation: bool) {
- let ip = IpAddr::V4(Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]));
- assert_eq!(ip.is_unspecified(), unspec);
- assert_eq!(ip.is_loopback(), loopback);
- assert_eq!(ip.is_global(), global);
- assert_eq!(ip.is_multicast(), multicast);
- assert_eq!(ip.is_documentation(), documentation);
+ macro_rules! ip {
+ ($s:expr) => {
+ IpAddr::from_str($s).unwrap()
+ }
}
- fn check6(str_addr: &str, unspec: bool, loopback: bool,
- global: bool, u_doc: bool, mcast: bool) {
- let ip = IpAddr::V6(str_addr.parse().unwrap());
- assert_eq!(ip.is_unspecified(), unspec);
- assert_eq!(ip.is_loopback(), loopback);
- assert_eq!(ip.is_global(), global);
- assert_eq!(ip.is_documentation(), u_doc);
- assert_eq!(ip.is_multicast(), mcast);
+ macro_rules! check {
+ ($s:expr) => {
+ check!($s, 0);
+ };
+
+ ($s:expr, $mask:expr) => {{
+ let unspec: u8 = 1 << 0;
+ let loopback: u8 = 1 << 1;
+ let global: u8 = 1 << 2;
+ let multicast: u8 = 1 << 3;
+ let doc: u8 = 1 << 4;
+
+ if ($mask & unspec) == unspec {
+ assert!(ip!($s).is_unspecified());
+ } else {
+ assert!(!ip!($s).is_unspecified());
+ }
+
+ if ($mask & loopback) == loopback {
+ assert!(ip!($s).is_loopback());
+ } else {
+ assert!(!ip!($s).is_loopback());
+ }
+
+ if ($mask & global) == global {
+ assert!(ip!($s).is_global());
+ } else {
+ assert!(!ip!($s).is_global());
+ }
+
+ if ($mask & multicast) == multicast {
+ assert!(ip!($s).is_multicast());
+ } else {
+ assert!(!ip!($s).is_multicast());
+ }
+
+ if ($mask & doc) == doc {
+ assert!(ip!($s).is_documentation());
+ } else {
+ assert!(!ip!($s).is_documentation());
+ }
+ }}
}
- // address unspec loopbk global multicast doc
- check4(&[0, 0, 0, 0], true, false, false, false, false);
- check4(&[0, 0, 0, 1], false, false, true, false, false);
- check4(&[0, 1, 0, 0], false, false, true, false, false);
- check4(&[10, 9, 8, 7], false, false, false, false, false);
- check4(&[127, 1, 2, 3], false, true, false, false, false);
- check4(&[172, 31, 254, 253], false, false, false, false, false);
- check4(&[169, 254, 253, 242], false, false, false, false, false);
- check4(&[192, 0, 2, 183], false, false, false, false, true);
- check4(&[192, 1, 2, 183], false, false, true, false, false);
- check4(&[192, 168, 254, 253], false, false, false, false, false);
- check4(&[198, 51, 100, 0], false, false, false, false, true);
- check4(&[203, 0, 113, 0], false, false, false, false, true);
- check4(&[203, 2, 113, 0], false, false, true, false, false);
- check4(&[224, 0, 0, 0], false, false, true, true, false);
- check4(&[239, 255, 255, 255], false, false, true, true, false);
- check4(&[255, 255, 255, 255], false, false, false, false, false);
-
- // address unspec loopbk global doc mcast
- check6("::", true, false, false, false, false);
- check6("::1", false, true, false, false, false);
- check6("::0.0.0.2", false, false, true, false, false);
- check6("1::", false, false, true, false, false);
- check6("fc00::", false, false, false, false, false);
- check6("fdff:ffff::", false, false, false, false, false);
- check6("fe80:ffff::", false, false, false, false, false);
- check6("febf:ffff::", false, false, false, false, false);
- check6("fec0::", false, false, false, false, false);
- check6("ff01::", false, false, false, false, true);
- check6("ff02::", false, false, false, false, true);
- check6("ff03::", false, false, false, false, true);
- check6("ff04::", false, false, false, false, true);
- check6("ff05::", false, false, false, false, true);
- check6("ff08::", false, false, false, false, true);
- check6("ff0e::", false, false, true, false, true);
- check6("2001:db8:85a3::8a2e:370:7334", false, false, false, true, false);
- check6("102:304:506:708:90a:b0c:d0e:f10", false, false, true, false, false);
+ let unspec: u8 = 1 << 0;
+ let loopback: u8 = 1 << 1;
+ let global: u8 = 1 << 2;
+ let multicast: u8 = 1 << 3;
+ let doc: u8 = 1 << 4;
+
+ check!("0.0.0.0", unspec);
+ check!("0.0.0.1");
+ check!("0.1.0.0");
+ check!("10.9.8.7");
+ check!("127.1.2.3", loopback);
+ check!("172.31.254.253");
+ check!("169.254.253.242");
+ check!("192.0.2.183", doc);
+ check!("192.1.2.183", global);
+ check!("192.168.254.253");
+ check!("198.51.100.0", doc);
+ check!("203.0.113.0", doc);
+ check!("203.2.113.0", global);
+ check!("224.0.0.0", global|multicast);
+ check!("239.255.255.255", global|multicast);
+ check!("255.255.255.255");
+ // make sure benchmarking addresses are not global
+ check!("198.18.0.0");
+ check!("198.18.54.2");
+ check!("198.19.255.255");
+ // make sure addresses reserved for protocol assignment are not global
+ check!("192.0.0.0");
+ check!("192.0.0.255");
+ check!("192.0.0.100");
+ // make sure reserved addresses are not global
+ check!("240.0.0.0");
+ check!("251.54.1.76");
+ check!("254.255.255.255");
+ // make sure shared addresses are not global
+ check!("100.64.0.0");
+ check!("100.127.255.255");
+ check!("100.100.100.0");
+
+ check!("::", unspec);
+ check!("::1", loopback);
+ check!("::0.0.0.2", global);
+ check!("1::", global);
+ check!("fc00::");
+ check!("fdff:ffff::");
+ check!("fe80:ffff::");
+ check!("febf:ffff::");
+ check!("fec0::", global);
+ check!("ff01::", multicast);
+ check!("ff02::", multicast);
+ check!("ff03::", multicast);
+ check!("ff04::", multicast);
+ check!("ff05::", multicast);
+ check!("ff08::", multicast);
+ check!("ff0e::", global|multicast);
+ check!("2001:db8:85a3::8a2e:370:7334", doc);
+ check!("102:304:506:708:90a:b0c:d0e:f10", global);
}
#[test]
fn ipv4_properties() {
- fn check(octets: &[u8; 4], unspec: bool, loopback: bool,
- private: bool, link_local: bool, global: bool,
- multicast: bool, broadcast: bool, documentation: bool) {
- let ip = Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]);
- assert_eq!(octets, &ip.octets());
-
- assert_eq!(ip.is_unspecified(), unspec);
- assert_eq!(ip.is_loopback(), loopback);
- assert_eq!(ip.is_private(), private);
- assert_eq!(ip.is_link_local(), link_local);
- assert_eq!(ip.is_global(), global);
- assert_eq!(ip.is_multicast(), multicast);
- assert_eq!(ip.is_broadcast(), broadcast);
- assert_eq!(ip.is_documentation(), documentation);
+ macro_rules! ip {
+ ($s:expr) => {
+ Ipv4Addr::from_str($s).unwrap()
+ }
}
- // address unspec loopbk privt linloc global multicast brdcast doc
- check(&[0, 0, 0, 0], true, false, false, false, false, false, false, false);
- check(&[0, 0, 0, 1], false, false, false, false, true, false, false, false);
- check(&[0, 1, 0, 0], false, false, false, false, true, false, false, false);
- check(&[10, 9, 8, 7], false, false, true, false, false, false, false, false);
- check(&[127, 1, 2, 3], false, true, false, false, false, false, false, false);
- check(&[172, 31, 254, 253], false, false, true, false, false, false, false, false);
- check(&[169, 254, 253, 242], false, false, false, true, false, false, false, false);
- check(&[192, 0, 2, 183], false, false, false, false, false, false, false, true);
- check(&[192, 1, 2, 183], false, false, false, false, true, false, false, false);
- check(&[192, 168, 254, 253], false, false, true, false, false, false, false, false);
- check(&[198, 51, 100, 0], false, false, false, false, false, false, false, true);
- check(&[203, 0, 113, 0], false, false, false, false, false, false, false, true);
- check(&[203, 2, 113, 0], false, false, false, false, true, false, false, false);
- check(&[224, 0, 0, 0], false, false, false, false, true, true, false, false);
- check(&[239, 255, 255, 255], false, false, false, false, true, true, false, false);
- check(&[255, 255, 255, 255], false, false, false, false, false, false, true, false);
+ macro_rules! check {
+ ($s:expr) => {
+ check!($s, 0);
+ };
+
+ ($s:expr, $mask:expr) => {{
+ let unspec: u16 = 1 << 0;
+ let loopback: u16 = 1 << 1;
+ let private: u16 = 1 << 2;
+ let link_local: u16 = 1 << 3;
+ let global: u16 = 1 << 4;
+ let multicast: u16 = 1 << 5;
+ let broadcast: u16 = 1 << 6;
+ let documentation: u16 = 1 << 7;
+ let benchmarking: u16 = 1 << 8;
+ let ietf_protocol_assignment: u16 = 1 << 9;
+ let reserved: u16 = 1 << 10;
+ let shared: u16 = 1 << 11;
+
+ if ($mask & unspec) == unspec {
+ assert!(ip!($s).is_unspecified());
+ } else {
+ assert!(!ip!($s).is_unspecified());
+ }
+
+ if ($mask & loopback) == loopback {
+ assert!(ip!($s).is_loopback());
+ } else {
+ assert!(!ip!($s).is_loopback());
+ }
+
+ if ($mask & private) == private {
+ assert!(ip!($s).is_private());
+ } else {
+ assert!(!ip!($s).is_private());
+ }
+
+ if ($mask & link_local) == link_local {
+ assert!(ip!($s).is_link_local());
+ } else {
+ assert!(!ip!($s).is_link_local());
+ }
+
+ if ($mask & global) == global {
+ assert!(ip!($s).is_global());
+ } else {
+ assert!(!ip!($s).is_global());
+ }
+
+ if ($mask & multicast) == multicast {
+ assert!(ip!($s).is_multicast());
+ } else {
+ assert!(!ip!($s).is_multicast());
+ }
+
+ if ($mask & broadcast) == broadcast {
+ assert!(ip!($s).is_broadcast());
+ } else {
+ assert!(!ip!($s).is_broadcast());
+ }
+
+ if ($mask & documentation) == documentation {
+ assert!(ip!($s).is_documentation());
+ } else {
+ assert!(!ip!($s).is_documentation());
+ }
+
+ if ($mask & benchmarking) == benchmarking {
+ assert!(ip!($s).is_benchmarking());
+ } else {
+ assert!(!ip!($s).is_benchmarking());
+ }
+
+ if ($mask & ietf_protocol_assignment) == ietf_protocol_assignment {
+ assert!(ip!($s).is_ietf_protocol_assignment());
+ } else {
+ assert!(!ip!($s).is_ietf_protocol_assignment());
+ }
+
+ if ($mask & reserved) == reserved {
+ assert!(ip!($s).is_reserved());
+ } else {
+ assert!(!ip!($s).is_reserved());
+ }
+
+ if ($mask & shared) == shared {
+ assert!(ip!($s).is_shared());
+ } else {
+ assert!(!ip!($s).is_shared());
+ }
+ }}
+ }
+
+ let unspec: u16 = 1 << 0;
+ let loopback: u16 = 1 << 1;
+ let private: u16 = 1 << 2;
+ let link_local: u16 = 1 << 3;
+ let global: u16 = 1 << 4;
+ let multicast: u16 = 1 << 5;
+ let broadcast: u16 = 1 << 6;
+ let documentation: u16 = 1 << 7;
+ let benchmarking: u16 = 1 << 8;
+ let ietf_protocol_assignment: u16 = 1 << 9;
+ let reserved: u16 = 1 << 10;
+ let shared: u16 = 1 << 11;
+
+ check!("0.0.0.0", unspec);
+ check!("0.0.0.1");
+ check!("0.1.0.0");
+ check!("10.9.8.7", private);
+ check!("127.1.2.3", loopback);
+ check!("172.31.254.253", private);
+ check!("169.254.253.242", link_local);
+ check!("192.0.2.183", documentation);
+ check!("192.1.2.183", global);
+ check!("192.168.254.253", private);
+ check!("198.51.100.0", documentation);
+ check!("203.0.113.0", documentation);
+ check!("203.2.113.0", global);
+ check!("224.0.0.0", global|multicast);
+ check!("239.255.255.255", global|multicast);
+ check!("255.255.255.255", broadcast);
+ check!("198.18.0.0", benchmarking);
+ check!("198.18.54.2", benchmarking);
+ check!("198.19.255.255", benchmarking);
+ check!("192.0.0.0", ietf_protocol_assignment);
+ check!("192.0.0.255", ietf_protocol_assignment);
+ check!("192.0.0.100", ietf_protocol_assignment);
+ check!("240.0.0.0", reserved);
+ check!("251.54.1.76", reserved);
+ check!("254.255.255.255", reserved);
+ check!("100.64.0.0", shared);
+ check!("100.127.255.255", shared);
+ check!("100.100.100.0", shared);
}
#[test]
fn ipv6_properties() {
- fn check(str_addr: &str, octets: &[u8; 16], unspec: bool, loopback: bool,
- unique_local: bool, global: bool,
- u_link_local: bool, u_site_local: bool, u_global: bool, u_doc: bool,
- m_scope: Option<Ipv6MulticastScope>) {
- let ip: Ipv6Addr = str_addr.parse().unwrap();
- assert_eq!(str_addr, ip.to_string());
- assert_eq!(&ip.octets(), octets);
- assert_eq!(Ipv6Addr::from(*octets), ip);
-
- assert_eq!(ip.is_unspecified(), unspec);
- assert_eq!(ip.is_loopback(), loopback);
- assert_eq!(ip.is_unique_local(), unique_local);
- assert_eq!(ip.is_global(), global);
- assert_eq!(ip.is_unicast_link_local(), u_link_local);
- assert_eq!(ip.is_unicast_site_local(), u_site_local);
- assert_eq!(ip.is_unicast_global(), u_global);
- assert_eq!(ip.is_documentation(), u_doc);
- assert_eq!(ip.multicast_scope(), m_scope);
- assert_eq!(ip.is_multicast(), m_scope.is_some());
+ macro_rules! ip {
+ ($s:expr) => {
+ Ipv6Addr::from_str($s).unwrap()
+ }
+ }
+
+ macro_rules! check {
+ ($s:expr, &[$($octet:expr),*], $mask:expr) => {
+ assert_eq!($s, ip!($s).to_string());
+ let octets = &[$($octet),*];
+ assert_eq!(&ip!($s).octets(), octets);
+ assert_eq!(Ipv6Addr::from(*octets), ip!($s));
+
+ let unspecified: u16 = 1 << 0;
+ let loopback: u16 = 1 << 1;
+ let unique_local: u16 = 1 << 2;
+ let global: u16 = 1 << 3;
+ let unicast_link_local: u16 = 1 << 4;
+ let unicast_link_local_strict: u16 = 1 << 5;
+ let unicast_site_local: u16 = 1 << 6;
+ let unicast_global: u16 = 1 << 7;
+ let documentation: u16 = 1 << 8;
+ let multicast_interface_local: u16 = 1 << 9;
+ let multicast_link_local: u16 = 1 << 10;
+ let multicast_realm_local: u16 = 1 << 11;
+ let multicast_admin_local: u16 = 1 << 12;
+ let multicast_site_local: u16 = 1 << 13;
+ let multicast_organization_local: u16 = 1 << 14;
+ let multicast_global: u16 = 1 << 15;
+ let multicast: u16 = multicast_interface_local
+ | multicast_admin_local
+ | multicast_global
+ | multicast_link_local
+ | multicast_realm_local
+ | multicast_site_local
+ | multicast_organization_local;
+
+ if ($mask & unspecified) == unspecified {
+ assert!(ip!($s).is_unspecified());
+ } else {
+ assert!(!ip!($s).is_unspecified());
+ }
+ if ($mask & loopback) == loopback {
+ assert!(ip!($s).is_loopback());
+ } else {
+ assert!(!ip!($s).is_loopback());
+ }
+ if ($mask & unique_local) == unique_local {
+ assert!(ip!($s).is_unique_local());
+ } else {
+ assert!(!ip!($s).is_unique_local());
+ }
+ if ($mask & global) == global {
+ assert!(ip!($s).is_global());
+ } else {
+ assert!(!ip!($s).is_global());
+ }
+ if ($mask & unicast_link_local) == unicast_link_local {
+ assert!(ip!($s).is_unicast_link_local());
+ } else {
+ assert!(!ip!($s).is_unicast_link_local());
+ }
+ if ($mask & unicast_link_local_strict) == unicast_link_local_strict {
+ assert!(ip!($s).is_unicast_link_local_strict());
+ } else {
+ assert!(!ip!($s).is_unicast_link_local_strict());
+ }
+ if ($mask & unicast_site_local) == unicast_site_local {
+ assert!(ip!($s).is_unicast_site_local());
+ } else {
+ assert!(!ip!($s).is_unicast_site_local());
+ }
+ if ($mask & unicast_global) == unicast_global {
+ assert!(ip!($s).is_unicast_global());
+ } else {
+ assert!(!ip!($s).is_unicast_global());
+ }
+ if ($mask & documentation) == documentation {
+ assert!(ip!($s).is_documentation());
+ } else {
+ assert!(!ip!($s).is_documentation());
+ }
+ if ($mask & multicast) != 0 {
+ assert!(ip!($s).multicast_scope().is_some());
+ assert!(ip!($s).is_multicast());
+ } else {
+ assert!(ip!($s).multicast_scope().is_none());
+ assert!(!ip!($s).is_multicast());
+ }
+ if ($mask & multicast_interface_local) == multicast_interface_local {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::InterfaceLocal);
+ }
+ if ($mask & multicast_link_local) == multicast_link_local {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::LinkLocal);
+ }
+ if ($mask & multicast_realm_local) == multicast_realm_local {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::RealmLocal);
+ }
+ if ($mask & multicast_admin_local) == multicast_admin_local {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::AdminLocal);
+ }
+ if ($mask & multicast_site_local) == multicast_site_local {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::SiteLocal);
+ }
+ if ($mask & multicast_organization_local) == multicast_organization_local {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::OrganizationLocal);
+ }
+ if ($mask & multicast_global) == multicast_global {
+ assert_eq!(ip!($s).multicast_scope().unwrap(),
+ Ipv6MulticastScope::Global);
+ }
+ }
}
- // unspec loopbk uniqlo global unill unisl uniglo doc mscope
- check("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- true, false, false, false, false, false, false, false, None);
- check("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
- false, true, false, false, false, false, false, false, None);
- check("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
- false, false, false, true, false, false, true, false, None);
- check("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, false, true, false, false, true, false, None);
- check("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, true, false, false, false, false, false, None);
- check("fdff:ffff::", &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, true, false, false, false, false, false, None);
- check("fe80:ffff::", &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, false, false, true, false, false, false, None);
- check("febf:ffff::", &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, false, false, true, false, false, false, None);
- check("fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, false, false, false, true, false, false, None);
- check("ff01::", &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, false, false, false, false, false, false, Some(InterfaceLocal));
- check("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, false, false, false, false, false, false, Some(LinkLocal));
- check("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, false, false, false, false, false, false, Some(RealmLocal));
- check("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, false, false, false, false, false, false, Some(AdminLocal));
- check("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, false, false, false, false, false, false, Some(SiteLocal));
- check("ff08::", &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, false, false, false, false, false, false, Some(OrganizationLocal));
- check("ff0e::", &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- false, false, false, true, false, false, false, false, Some(Global));
- check("2001:db8:85a3::8a2e:370:7334",
- &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
- false, false, false, false, false, false, false, true, None);
- check("102:304:506:708:90a:b0c:d0e:f10",
- &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
- false, false, false, true, false, false, true, false, None);
+ let unspecified: u16 = 1 << 0;
+ let loopback: u16 = 1 << 1;
+ let unique_local: u16 = 1 << 2;
+ let global: u16 = 1 << 3;
+ let unicast_link_local: u16 = 1 << 4;
+ let unicast_link_local_strict: u16 = 1 << 5;
+ let unicast_site_local: u16 = 1 << 6;
+ let unicast_global: u16 = 1 << 7;
+ let documentation: u16 = 1 << 8;
+ let multicast_interface_local: u16 = 1 << 9;
+ let multicast_link_local: u16 = 1 << 10;
+ let multicast_realm_local: u16 = 1 << 11;
+ let multicast_admin_local: u16 = 1 << 12;
+ let multicast_site_local: u16 = 1 << 13;
+ let multicast_organization_local: u16 = 1 << 14;
+ let multicast_global: u16 = 1 << 15;
+
+ check!("::",
+ &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unspecified);
+
+ check!("::1",
+ &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
+ loopback);
+
+ check!("::0.0.0.2",
+ &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
+ global | unicast_global);
+
+ check!("1::",
+ &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ global | unicast_global);
+
+ check!("fc00::",
+ &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unique_local);
+
+ check!("fdff:ffff::",
+ &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unique_local);
+
+ check!("fe80:ffff::",
+ &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unicast_link_local);
+
+ check!("fe80::",
+ &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unicast_link_local|unicast_link_local_strict);
+
+ check!("febf:ffff::",
+ &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unicast_link_local);
+
+ check!("febf::",
+ &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unicast_link_local);
+
+ check!("febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
+ &[0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
+ unicast_link_local);
+
+ check!("fe80::ffff:ffff:ffff:ffff",
+ &[0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
+ unicast_link_local|unicast_link_local_strict);
+
+ check!("fe80:0:0:1::",
+ &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
+ unicast_link_local);
+
+ check!("fec0::",
+ &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ unicast_site_local|unicast_global|global);
+
+ check!("ff01::",
+ &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_interface_local);
+
+ check!("ff02::",
+ &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_link_local);
+
+ check!("ff03::",
+ &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_realm_local);
+
+ check!("ff04::",
+ &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_admin_local);
+
+ check!("ff05::",
+ &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_site_local);
+
+ check!("ff08::",
+ &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_organization_local);
+
+ check!("ff0e::",
+ &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ multicast_global | global);
+
+ check!("2001:db8:85a3::8a2e:370:7334",
+ &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
+ documentation);
+
+ check!("102:304:506:708:90a:b0c:d0e:f10",
+ &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
+ global| unicast_global);
}
#[test]
}
/// Represents the #[stable], #[unstable], #[rustc_{deprecated,const_unstable}] attributes.
-#[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Stability {
pub level: StabilityLevel,
pub feature: Symbol,
}
/// The available stability levels.
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
pub enum StabilityLevel {
// Reason for the current stability level and the relevant rust-lang issue
Unstable { reason: Option<Symbol>, issue: u32 },
}
}
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
pub struct RustcDeprecation {
pub since: Symbol,
pub reason: Symbol,
Applicability::MaybeIncorrect,
);
} else {
- err.note("type ascription is a nightly-only feature that lets \
- you annotate an expression with a type: `<expr>: <type>`")
+ err.note("#![feature(type_ascription)] lets you annotate an \
+ expression with a type: `<expr>: <type>`")
.span_note(
lhs_span,
"this expression expects an ascribed type after the colon",
return Ok(Some(item));
}
- // `unsafe async fn` or `async fn`
- if (
- self.check_keyword(kw::Unsafe) &&
- self.is_keyword_ahead(1, &[kw::Async])
- ) || (
- self.check_keyword(kw::Async) &&
- self.is_keyword_ahead(1, &[kw::Fn])
- )
- {
- // ASYNC FUNCTION ITEM
- let unsafety = self.parse_unsafety();
- self.expect_keyword(kw::Async)?;
- let async_span = self.prev_span;
- self.expect_keyword(kw::Fn)?;
- let fn_span = self.prev_span;
- let (ident, item_, extra_attrs) =
- self.parse_item_fn(unsafety,
- respan(async_span, IsAsync::Async {
- closure_id: ast::DUMMY_NODE_ID,
- return_impl_trait_id: ast::DUMMY_NODE_ID,
- arguments: Vec::new(),
- }),
- respan(fn_span, Constness::NotConst),
- Abi::Rust)?;
- let prev_span = self.prev_span;
- let item = self.mk_item(lo.to(prev_span),
- ident,
- item_,
- visibility,
- maybe_append(attrs, extra_attrs));
- if self.span.rust_2015() {
- self.diagnostic().struct_span_err_with_code(
- async_span,
- "`async fn` is not permitted in the 2015 edition",
- DiagnosticId::Error("E0670".into())
- ).emit();
+ // Parse `async unsafe? fn`.
+ if self.check_keyword(kw::Async) {
+ let async_span = self.span;
+ if self.is_keyword_ahead(1, &[kw::Fn])
+ || self.is_keyword_ahead(2, &[kw::Fn])
+ {
+ // ASYNC FUNCTION ITEM
+ self.bump(); // `async`
+ let unsafety = self.parse_unsafety(); // `unsafe`?
+ self.expect_keyword(kw::Fn)?; // `fn`
+ let fn_span = self.prev_span;
+ let (ident, item_, extra_attrs) =
+ self.parse_item_fn(unsafety,
+ respan(async_span, IsAsync::Async {
+ closure_id: ast::DUMMY_NODE_ID,
+ return_impl_trait_id: ast::DUMMY_NODE_ID,
+ arguments: Vec::new(),
+ }),
+ respan(fn_span, Constness::NotConst),
+ Abi::Rust)?;
+ let prev_span = self.prev_span;
+ let item = self.mk_item(lo.to(prev_span),
+ ident,
+ item_,
+ visibility,
+ maybe_append(attrs, extra_attrs));
+ if self.span.rust_2015() {
+ self.diagnostic().struct_span_err_with_code(
+ async_span,
+ "`async fn` is not permitted in the 2015 edition",
+ DiagnosticId::Error("E0670".into())
+ ).emit();
+ }
+ return Ok(Some(item));
}
- return Ok(Some(item));
}
if self.check_keyword(kw::Unsafe) &&
self.is_keyword_ahead(1, &[kw::Trait, kw::Auto])
if desc.allow_fail {
TrAllowedFail
} else {
- TrFailedMsg(format!("Panic did not include expected string '{}'", msg))
+ TrFailedMsg(format!("panic did not include expected string '{}'", msg))
}
}
}
panic!("an error message");
}
let expected = "foobar";
- let failed_msg = "Panic did not include expected string";
+ let failed_msg = "panic did not include expected string";
let desc = TestDescAndFn {
desc: TestDesc {
name: StaticTestName("whatever"),
-Subproject commit 4efebe31651d5520bcba968878dbb8a4971d2045
+Subproject commit 788592fb2740d560d0614a77035b319b9d07aa38
// run-pass
#![allow(dead_code, unreachable_patterns)]
+#![allow(ellipsis_inclusive_range_patterns)]
struct Foo;
<Foo as HasNum>::NUM ... <Foo>::NUM => true,
_ => false,
});
+
+ assert!(match 2 {
+ Foo::NUM ..= 3 => true,
+ _ => false,
+ });
+ assert!(match 0 {
+ -1 ..= <Foo as HasNum>::NUM => true,
+ _ => false,
+ });
+ assert!(match 1 {
+ <Foo as HasNum>::NUM ..= <Foo>::NUM => true,
+ _ => false,
+ });
}
// run-pass
// Parsing of range patterns
+#![allow(ellipsis_inclusive_range_patterns)]
+
const NUM1: i32 = 10;
mod m {
if let NUM1 ... m::NUM2 = 10 {} else { panic!() }
if let ::NUM1 ... ::m::NUM2 = 11 {} else { panic!() }
if let -13 ... -10 = 12 { panic!() } else {}
+
+ if let NUM1 ..= m::NUM2 = 10 {} else { panic!() }
+ if let ::NUM1 ..= ::m::NUM2 = 11 {} else { panic!() }
+ if let -13 ..= -10 = 12 { panic!() } else {}
}
-#![feature(const_int_conversion, reverse_bits)]
+#![feature(const_int_conversion)]
const REVERSE: u32 = 0x12345678_u32.reverse_bits();
const FROM_BE_BYTES: i32 = i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
data: RefCell::new(vec![])
}
}
- fn alloc(&self) -> Ptr {
+ fn alloc(&self) -> Ptr<'_> {
self.cur_ops.set(self.cur_ops.get() + 1);
if self.cur_ops.get() == self.failing_op {
data.push(true);
Ptr(addr, self)
}
+ // FIXME(#47949) Any use of this indicates a bug in rustc: we should never
+ // be leaking values in the cases here.
+ //
+ // Creates a `Ptr<'_>` and checks that the allocated value is leaked if the
+ // `failing_op` is in the list of exception.
+ fn alloc_leaked(&self, exceptions: Vec<usize>) -> Ptr<'_> {
+ let ptr = self.alloc();
+
+ if exceptions.iter().any(|operation| *operation == self.failing_op) {
+ let mut data = self.data.borrow_mut();
+ data[ptr.0] = false;
+ }
+ ptr
+ }
}
struct Ptr<'a>(usize, &'a Allocator);
let[_, _y..] = ar;
}
+fn panic_after_return(a: &Allocator) -> Ptr<'_> {
+ // Panic in the drop of `p` or `q` can leak
+ let exceptions = vec![8, 9];
+ a.alloc();
+ let p = a.alloc();
+ {
+ a.alloc();
+ let p = a.alloc();
+ // FIXME (#47949) We leak values when we panic in a destructor after
+ // evaluating an expression with `rustc_mir::build::Builder::into`.
+ a.alloc_leaked(exceptions)
+ }
+}
+
+fn panic_after_return_expr(a: &Allocator) -> Ptr<'_> {
+ // Panic in the drop of `p` or `q` can leak
+ let exceptions = vec![8, 9];
+ a.alloc();
+ let p = a.alloc();
+ {
+ a.alloc();
+ let q = a.alloc();
+ // FIXME (#47949)
+ return a.alloc_leaked(exceptions);
+ }
+}
+
+fn panic_after_init(a: &Allocator) {
+ // Panic in the drop of `r` can leak
+ let exceptions = vec![8];
+ a.alloc();
+ let p = a.alloc();
+ let q = {
+ a.alloc();
+ let r = a.alloc();
+ // FIXME (#47949)
+ a.alloc_leaked(exceptions)
+ };
+}
+
+fn panic_after_init_temp(a: &Allocator) {
+ // Panic in the drop of `r` can leak
+ let exceptions = vec![8];
+ a.alloc();
+ let p = a.alloc();
+ {
+ a.alloc();
+ let r = a.alloc();
+ // FIXME (#47949)
+ a.alloc_leaked(exceptions)
+ };
+}
+
+fn panic_after_init_by_loop(a: &Allocator) {
+ // Panic in the drop of `r` can leak
+ let exceptions = vec![8];
+ a.alloc();
+ let p = a.alloc();
+ let q = loop {
+ a.alloc();
+ let r = a.alloc();
+ // FIXME (#47949)
+ break a.alloc_leaked(exceptions);
+ };
+}
+
fn run_test<F>(mut f: F)
where F: FnMut(&Allocator)
{
run_test(|a| slice_pattern_reassign(a));
run_test(|a| subslice_pattern_reassign(a));
+ run_test(|a| {
+ panic_after_return(a);
+ });
+ run_test(|a| {
+ panic_after_return_expr(a);
+ });
+ run_test(|a| panic_after_init(a));
+ run_test(|a| panic_after_init_temp(a));
+ run_test(|a| panic_after_init_by_loop(a));
+
run_test_nopanic(|a| union1(a));
}
// Test old and new syntax for inclusive range patterns.
+#![allow(ellipsis_inclusive_range_patterns)]
+
fn main() {
assert!(match 42 { 0 ... 100 => true, _ => false });
assert!(match 42 { 0 ..= 100 => true, _ => false });
// run-pass
#![allow(illegal_floating_point_literal_pattern)] // FIXME #41620
+#![allow(ellipsis_inclusive_range_patterns)]
// regression test for the model lexer handling the DOTDOTDOT syntax (#15877)
#![allow(dead_code)]
fn test1(x: i8) -> i32 {
match x {
- 1...10 => 0,
+ 1..=10 => 0,
_ => 1,
}
}
// ignore-tidy-linelength
pub trait Foo {
- // @has foo/trait.Foo.html '//h3[@id="tymethod.foo"]//div[@class="docblock attributes"]' '#[must_use]'
+ // @has foo/trait.Foo.html '//h3[@id="tymethod.foo"]//span[@class="docblock attributes"]' '#[must_use]'
#[must_use]
fn foo();
}
pub struct Bar;
impl Bar {
- // @has foo/struct.Bar.html '//h4[@id="method.bar"]//div[@class="docblock attributes"]' '#[must_use]'
+ // @has foo/struct.Bar.html '//h4[@id="method.bar"]//span[@class="docblock attributes"]' '#[must_use]'
#[must_use]
pub fn bar() {}
- // @has foo/struct.Bar.html '//h4[@id="method.bar2"]//div[@class="docblock attributes"]' '#[must_use]'
+ // @has foo/struct.Bar.html '//h4[@id="method.bar2"]//span[@class="docblock attributes"]' '#[must_use]'
#[must_use]
pub fn bar2() {}
}
}
}
-unsafe async fn unsafe_async_fn(x: u8) -> u8 {
+async unsafe fn unsafe_async_fn(x: u8) -> u8 {
wake_and_yield_once().await;
x
}
}
}
-unsafe async fn unsafe_async_fn(x: u8) -> u8 {
+async unsafe fn unsafe_async_fn(x: u8) -> u8 {
await!(wake_and_yield_once());
x
}
--- /dev/null
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct Foo<T, const N: usize>([T; {N}]);
+
+impl<T, const N: usize> Foo<T, {N}> {
+ fn foo(&self) -> usize {
+ {N}
+ }
+}
+
+fn main() {
+ let foo = Foo([0u32; 21]);
+ assert_eq!(foo.0, [0u32; 21]);
+ assert_eq!(foo.foo(), 21);
+}
--- /dev/null
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+ --> $DIR/const-generic-array-wrapper.rs:3:12
+ |
+LL | #![feature(const_generics)]
+ | ^^^^^^^^^^^^^^
+
--- /dev/null
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::mem;
+
+fn foo<const SIZE: usize>() {
+ let arr: [u8; SIZE] = unsafe {
+ let mut array: [u8; SIZE] = mem::uninitialized();
+ array
+ };
+}
+
+fn main() {}
--- /dev/null
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+ --> $DIR/issue-61422.rs:3:12
+ |
+LL | #![feature(const_generics)]
+ | ^^^^^^^^^^^^^^
+
--- /dev/null
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::ops::AddAssign;
+
+fn inc<T: AddAssign + Clone, const N: usize>(v: &mut [T; N]) -> &mut [T; N] {
+ for x in v.iter_mut() {
+ *x += x.clone();
+ }
+ v
+}
+
+fn main() {
+ let mut v = [1, 2, 3];
+ inc(&mut v);
+ assert_eq!(v, [2, 4, 6]);
+}
--- /dev/null
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+ --> $DIR/mut-ref-const-param-array.rs:3:12
+ |
+LL | #![feature(const_generics)]
+ | ^^^^^^^^^^^^^^
+
--- /dev/null
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::mem::MaybeUninit;
+
+#[repr(transparent)]
+pub struct MaybeUninitWrapper<const N: usize>(MaybeUninit<[u64; N]>);
+
+fn main() {}
--- /dev/null
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+ --> $DIR/transparent-maybeunit-array-wrapper.rs:3:12
+ |
+LL | #![feature(const_generics)]
+ | ^^^^^^^^^^^^^^
+
-#![feature(reverse_bits)]
-
fn main() {
let x: &'static i32 = &(5_i32.reverse_bits());
//~^ ERROR temporary value dropped while borrowed
error[E0716]: temporary value dropped while borrowed
- --> $DIR/const-int-conversion.rs:4:28
+ --> $DIR/const-int-conversion.rs:2:28
|
LL | let x: &'static i32 = &(5_i32.reverse_bits());
| ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/const-int-conversion.rs:6:28
+ --> $DIR/const-int-conversion.rs:4:28
|
LL | let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]));
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/const-int-conversion.rs:8:28
+ --> $DIR/const-int-conversion.rs:6:28
|
LL | let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]));
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/const-int-conversion.rs:10:28
+ --> $DIR/const-int-conversion.rs:8:28
|
LL | let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0])));
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/const-int-conversion.rs:12:29
+ --> $DIR/const-int-conversion.rs:10:29
|
LL | let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes());
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/const-int-conversion.rs:14:29
+ --> $DIR/const-int-conversion.rs:12:29
|
LL | let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes());
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/const-int-conversion.rs:16:29
+ --> $DIR/const-int-conversion.rs:14:29
|
LL | let d: &'static [u8] = &(i32::min_value().to_be().to_ne_bytes());
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
--- /dev/null
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn is_123<const N: usize>(x: [u32; N]) -> bool {
+ match x {
+ [1, 2, 3] => true, //~ ERROR cannot pattern-match on an array without a fixed length
+ _ => false
+ }
+}
+
+fn main() {}
--- /dev/null
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+ --> $DIR/E0730.rs:1:12
+ |
+LL | #![feature(const_generics)]
+ | ^^^^^^^^^^^^^^
+
+error[E0730]: cannot pattern-match on an array without a fixed length
+ --> $DIR/E0730.rs:6:9
+ |
+LL | [1, 2, 3] => true,
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0730`.
// run-rustfix
// ignore-wasm32 no external library to link to.
-// compile-flags: -g -Z continue-parse-after-error
+// compile-flags: -g
#![feature(rustc_private)]
extern crate libc;
// run-rustfix
// ignore-wasm32 no external library to link to.
-// compile-flags: -g -Z continue-parse-after-error
+// compile-flags: -g
#![feature(rustc_private)]
extern crate libc;
-// compile-flags: -Z continue-parse-after-error
// ignore-tidy-tab
fn main() {
error: incorrect unicode escape sequence
- --> $DIR/format-string-error-2.rs:78:20
+ --> $DIR/format-string-error-2.rs:77:20
|
LL | println!("\x7B}\u8 {", 1);
| ^^-
| help: format of unicode escape sequences uses braces: `\u{8}`
error: invalid format string: expected `'}'`, found `'a'`
- --> $DIR/format-string-error-2.rs:6:5
+ --> $DIR/format-string-error-2.rs:5:5
|
LL | format!("{
| - because of this opening brace
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: expected `'}'`, found `'b'`
- --> $DIR/format-string-error-2.rs:10:5
+ --> $DIR/format-string-error-2.rs:9:5
|
LL | format!("{ \
| - because of this opening brace
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: expected `'}'`, found `'\'`
- --> $DIR/format-string-error-2.rs:12:18
+ --> $DIR/format-string-error-2.rs:11:18
|
LL | format!(r#"{ \
| - ^ expected `}` in format string
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: expected `'}'`, found `'\'`
- --> $DIR/format-string-error-2.rs:16:18
+ --> $DIR/format-string-error-2.rs:15:18
|
LL | format!(r#"{ \n
| - ^ expected `}` in format string
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: expected `'}'`, found `'e'`
- --> $DIR/format-string-error-2.rs:22:5
+ --> $DIR/format-string-error-2.rs:21:5
|
LL | format!("{ \n
| - because of this opening brace
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: expected `'}'`, found `'a'`
- --> $DIR/format-string-error-2.rs:26:5
+ --> $DIR/format-string-error-2.rs:25:5
|
LL | {
| - because of this opening brace
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: expected `'}'`, found `'a'`
- --> $DIR/format-string-error-2.rs:30:5
+ --> $DIR/format-string-error-2.rs:29:5
|
LL | {
| - because of this opening brace
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: expected `'}'`, found `'b'`
- --> $DIR/format-string-error-2.rs:36:5
+ --> $DIR/format-string-error-2.rs:35:5
|
LL | { \
| - because of this opening brace
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: expected `'}'`, found `'b'`
- --> $DIR/format-string-error-2.rs:41:5
+ --> $DIR/format-string-error-2.rs:40:5
|
LL | { \
| - because of this opening brace
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: expected `'}'`, found `'\'`
- --> $DIR/format-string-error-2.rs:46:8
+ --> $DIR/format-string-error-2.rs:45:8
|
LL | raw { \
| - ^ expected `}` in format string
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: expected `'}'`, found `'\'`
- --> $DIR/format-string-error-2.rs:51:8
+ --> $DIR/format-string-error-2.rs:50:8
|
LL | raw { \n
| - ^ expected `}` in format string
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: expected `'}'`, found `'e'`
- --> $DIR/format-string-error-2.rs:58:5
+ --> $DIR/format-string-error-2.rs:57:5
|
LL | { \n
| - because of this opening brace
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: expected `'}'`, found `'a'`
- --> $DIR/format-string-error-2.rs:68:5
+ --> $DIR/format-string-error-2.rs:67:5
|
LL | {
| - because of this opening brace
= note: if you intended to print `{`, you can escape it using `{{`
error: 1 positional argument in format string, but no arguments were given
- --> $DIR/format-string-error-2.rs:71:17
+ --> $DIR/format-string-error-2.rs:70:17
|
LL | println!("\t{}");
| ^^
error: invalid format string: expected `'}'` but string was terminated
- --> $DIR/format-string-error-2.rs:75:27
+ --> $DIR/format-string-error-2.rs:74:27
|
LL | println!("\x7B}\u{8} {", 1);
| -^ expected `'}'` in format string
= note: if you intended to print `{`, you can escape it using `{{`
error: invalid format string: unmatched `}` found
- --> $DIR/format-string-error-2.rs:82:21
+ --> $DIR/format-string-error-2.rs:81:21
|
LL | println!(r#"\x7B}\u{8} {"#, 1);
| ^ unmatched `}` in format string
= note: if you intended to print `}`, you can escape it using `}}`
error: invalid format string: unmatched `}` found
- --> $DIR/format-string-error-2.rs:85:21
+ --> $DIR/format-string-error-2.rs:84:21
|
LL | println!(r#"\x7B}\u8 {"#, 1);
| ^ unmatched `}` in format string
-// compile-flags: -Z parse-only -Z continue-parse-after-error
+// compile-flags: -Z parse-only
fn f() -> impl A + {} // OK
fn f() -> impl A + B {} // OK
LL | println!("{}", a: &mut 4);
| ^ expecting a type here because of type ascription
|
- = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+ = note: #![feature(type_ascription)] lets you annotate an expression with a type: `<expr>: <type>`
note: this expression expects an ascribed type after the colon
--> $DIR/issue-22644.rs:34:20
|
-// compile-flags: -Z continue-parse-after-error
-
enum Bird {
pub Duck,
//~^ ERROR unnecessary visibility qualifier
error: unnecessary visibility qualifier
- --> $DIR/issue-28433.rs:4:5
+ --> $DIR/issue-28433.rs:2:5
|
LL | pub Duck,
| ^^^ `pub` not permitted here
error: unnecessary visibility qualifier
- --> $DIR/issue-28433.rs:7:5
+ --> $DIR/issue-28433.rs:5:5
|
LL | pub(crate) Dove
| ^^^^^^^^^^ `pub` not permitted here
LL | Test::Drill(field: 42);
| ^^ expecting a type here because of type ascription
|
- = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+ = note: #![feature(type_ascription)] lets you annotate an expression with a type: `<expr>: <type>`
note: this expression expects an ascribed type after the colon
--> $DIR/issue-34255-1.rs:8:17
|
-// compile-flags: -Z continue-parse-after-error
-
struct Foo<Self>(Self);
//~^ ERROR expected identifier, found keyword `Self`
//~^^ ERROR E0392
error: expected identifier, found keyword `Self`
- --> $DIR/issue-36638.rs:3:12
+ --> $DIR/issue-36638.rs:1:12
|
LL | struct Foo<Self>(Self);
| ^^^^ expected identifier, found keyword
error: expected identifier, found keyword `Self`
- --> $DIR/issue-36638.rs:7:11
+ --> $DIR/issue-36638.rs:5:11
|
LL | trait Bar<Self> {}
| ^^^^ expected identifier, found keyword
error[E0392]: parameter `Self` is never used
- --> $DIR/issue-36638.rs:3:12
+ --> $DIR/issue-36638.rs:1:12
|
LL | struct Foo<Self>(Self);
| ^^^^ unused parameter
LL | loop { break 'label: loop { break 'label 42; }; }
| ^^^^ expecting a type here because of type ascription
|
- = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+ = note: #![feature(type_ascription)] lets you annotate an expression with a type: `<expr>: <type>`
note: this expression expects an ascribed type after the colon
--> $DIR/lifetime_starts_expressions.rs:6:12
|
// compile-pass
+#![allow(ellipsis_inclusive_range_patterns)]
#![allow(unreachable_patterns)]
#![allow(unused_variables)]
#![warn(unused_parens)]
fn main() {
+ match 1 {
+ (_) => {} //~ WARNING: unnecessary parentheses around pattern
+ (y) => {} //~ WARNING: unnecessary parentheses around pattern
+ (ref r) => {} //~ WARNING: unnecessary parentheses around pattern
+ (e @ 1...2) => {} //~ WARNING: unnecessary parentheses around outer pattern
+ (1...2) => {} // Non ambiguous range pattern should not warn
+ e @ (3...4) => {} // Non ambiguous range pattern should not warn
+ }
+
+ match &1 {
+ (e @ &(1...2)) => {} //~ WARNING: unnecessary parentheses around outer pattern
+ &(_) => {} //~ WARNING: unnecessary parentheses around pattern
+ e @ &(1...2) => {} // Ambiguous range pattern should not warn
+ &(1...2) => {} // Ambiguous range pattern should not warn
+ }
+
+ match &1 {
+ e @ &(1...2) | e @ &(3...4) => {} // Complex ambiguous pattern should not warn
+ &_ => {}
+ }
+
match 1 {
(_) => {} //~ WARNING: unnecessary parentheses around pattern
(y) => {} //~ WARNING: unnecessary parentheses around pattern
}
match &1 {
- (e @ &(1...2)) => {} //~ WARNING: unnecessary parentheses around outer pattern
+ (e @ &(1..=2)) => {} //~ WARNING: unnecessary parentheses around outer pattern
&(_) => {} //~ WARNING: unnecessary parentheses around pattern
- e @ &(1...2) => {} // Ambiguous range pattern should not warn
+ e @ &(1..=2) => {} // Ambiguous range pattern should not warn
&(1..=2) => {} // Ambiguous range pattern should not warn
}
match &1 {
- e @ &(1...2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn
+ e @ &(1..=2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn
&_ => {}
}
}
warning: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:9:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:10:9
|
LL | (_) => {}
| ^^^ help: remove these parentheses
|
note: lint level defined here
- --> $DIR/issue-54538-unused-parens-lint.rs:5:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:6:9
|
LL | #![warn(unused_parens)]
| ^^^^^^^^^^^^^
warning: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:10:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:11:9
|
LL | (y) => {}
| ^^^ help: remove these parentheses
warning: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:11:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:12:9
|
LL | (ref r) => {}
| ^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:12:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:13:9
|
-LL | (e @ 1..=2) => {}
+LL | (e @ 1...2) => {}
| ^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:18:9
+ --> $DIR/issue-54538-unused-parens-lint.rs:19:9
|
LL | (e @ &(1...2)) => {}
| ^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around pattern
- --> $DIR/issue-54538-unused-parens-lint.rs:19:10
+ --> $DIR/issue-54538-unused-parens-lint.rs:20:10
+ |
+LL | &(_) => {}
+ | ^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:31:9
+ |
+LL | (_) => {}
+ | ^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:32:9
+ |
+LL | (y) => {}
+ | ^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:33:9
+ |
+LL | (ref r) => {}
+ | ^^^^^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:34:9
+ |
+LL | (e @ 1..=2) => {}
+ | ^^^^^^^^^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:40:9
+ |
+LL | (e @ &(1..=2)) => {}
+ | ^^^^^^^^^^^^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+ --> $DIR/issue-54538-unused-parens-lint.rs:41:10
|
LL | &(_) => {}
| ^^^ help: remove these parentheses
fn main() {
match 5 {
- 1 ... 10 => { }
- 5 ... 6 => { }
+ 1 ..= 10 => { }
+ 5 ..= 6 => { }
_ => {}
};
match 5 {
- 3 ... 6 => { }
- 4 ... 6 => { }
+ 3 ..= 6 => { }
+ 4 ..= 6 => { }
_ => {}
};
match 5 {
- 4 ... 6 => { }
- 4 ... 6 => { }
+ 4 ..= 6 => { }
+ 4 ..= 6 => { }
_ => {}
};
match 'c' {
- 'A' ... 'z' => {}
- 'a' ... 'z' => {}
+ 'A' ..= 'z' => {}
+ 'a' ..= 'z' => {}
_ => {}
};
match 1.0f64 {
- 0.01f64 ... 6.5f64 => {}
+ 0.01f64 ..= 6.5f64 => {}
0.02f64 => {}
_ => {}
};
error: unreachable pattern
--> $DIR/match-range-fail-dominate.rs:12:7
|
-LL | 5 ... 6 => { }
+LL | 5 ..= 6 => { }
| ^^^^^^^
|
note: lint level defined here
error: unreachable pattern
--> $DIR/match-range-fail-dominate.rs:18:7
|
-LL | 4 ... 6 => { }
+LL | 4 ..= 6 => { }
| ^^^^^^^
error: unreachable pattern
--> $DIR/match-range-fail-dominate.rs:24:7
|
-LL | 4 ... 6 => { }
+LL | 4 ..= 6 => { }
| ^^^^^^^
error: unreachable pattern
--> $DIR/match-range-fail-dominate.rs:30:7
|
-LL | 'a' ... 'z' => {}
+LL | 'a' ..= 'z' => {}
| ^^^^^^^^^^^
warning: floating-point types cannot be used in patterns
--> $DIR/match-range-fail-dominate.rs:35:7
|
-LL | 0.01f64 ... 6.5f64 => {}
+LL | 0.01f64 ..= 6.5f64 => {}
| ^^^^^^^
|
= note: #[warn(illegal_floating_point_literal_pattern)] on by default
warning: floating-point types cannot be used in patterns
--> $DIR/match-range-fail-dominate.rs:35:19
|
-LL | 0.01f64 ... 6.5f64 => {}
+LL | 0.01f64 ..= 6.5f64 => {}
| ^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: floating-point types cannot be used in patterns
--> $DIR/match-range-fail-dominate.rs:35:7
|
-LL | 0.01f64 ... 6.5f64 => {}
+LL | 0.01f64 ..= 6.5f64 => {}
| ^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
fn digits(x: u8) -> u32 {
match x {
- OneDigit::FIRST...OneDigit::LAST => 1,
- TwoDigits::FIRST...TwoDigits::LAST => 2,
- ThreeDigits::FIRST...ThreeDigits::LAST => 3,
+ OneDigit::FIRST..=OneDigit::LAST => 1,
+ TwoDigits::FIRST..=TwoDigits::LAST => 2,
+ ThreeDigits::FIRST..=ThreeDigits::LAST => 3,
_ => unreachable!(),
}
}
-// compile-flags: -Z continue-parse-after-error
-
// Test you can't use a higher-ranked trait bound inside of a qualified
// path (just won't parse).
error: expected identifier, found keyword `for`
- --> $DIR/associated-types-project-from-hrtb-explicit.rs:12:21
+ --> $DIR/associated-types-project-from-hrtb-explicit.rs:10:21
|
LL | fn foo2<I>(x: <I as for<'x> Foo<&'x isize>>::A)
| ^^^ expected identifier, found keyword
| ^^^^^
error: expected one of `::` or `>`, found `Foo`
- --> $DIR/associated-types-project-from-hrtb-explicit.rs:12:29
+ --> $DIR/associated-types-project-from-hrtb-explicit.rs:10:29
|
LL | fn foo2<I>(x: <I as for<'x> Foo<&'x isize>>::A)
| ^^^ expected one of `::` or `>` here
-// compile-flags: -Z continue-parse-after-error
-
-
extern
"C"suffix //~ ERROR suffixes on an ABI spec are invalid
fn foo() {}
error: suffixes on an ABI spec are invalid
- --> $DIR/bad-lit-suffixes.rs:5:5
+ --> $DIR/bad-lit-suffixes.rs:2:5
|
LL | "C"suffix
| ^^^^^^^^^ invalid suffix `suffix`
error: suffixes on an ABI spec are invalid
- --> $DIR/bad-lit-suffixes.rs:9:5
+ --> $DIR/bad-lit-suffixes.rs:6:5
|
LL | "C"suffix
| ^^^^^^^^^ invalid suffix `suffix`
error: suffixes on a string literal are invalid
- --> $DIR/bad-lit-suffixes.rs:13:5
+ --> $DIR/bad-lit-suffixes.rs:10:5
|
LL | ""suffix;
| ^^^^^^^^ invalid suffix `suffix`
error: suffixes on a byte string literal are invalid
- --> $DIR/bad-lit-suffixes.rs:14:5
+ --> $DIR/bad-lit-suffixes.rs:11:5
|
LL | b""suffix;
| ^^^^^^^^^ invalid suffix `suffix`
error: suffixes on a string literal are invalid
- --> $DIR/bad-lit-suffixes.rs:15:5
+ --> $DIR/bad-lit-suffixes.rs:12:5
|
LL | r#""#suffix;
| ^^^^^^^^^^^ invalid suffix `suffix`
error: suffixes on a byte string literal are invalid
- --> $DIR/bad-lit-suffixes.rs:16:5
+ --> $DIR/bad-lit-suffixes.rs:13:5
|
LL | br#""#suffix;
| ^^^^^^^^^^^^ invalid suffix `suffix`
error: suffixes on a char literal are invalid
- --> $DIR/bad-lit-suffixes.rs:17:5
+ --> $DIR/bad-lit-suffixes.rs:14:5
|
LL | 'a'suffix;
| ^^^^^^^^^ invalid suffix `suffix`
error: suffixes on a byte literal are invalid
- --> $DIR/bad-lit-suffixes.rs:18:5
+ --> $DIR/bad-lit-suffixes.rs:15:5
|
LL | b'a'suffix;
| ^^^^^^^^^^ invalid suffix `suffix`
error: invalid width `1024` for integer literal
- --> $DIR/bad-lit-suffixes.rs:20:5
+ --> $DIR/bad-lit-suffixes.rs:17:5
|
LL | 1234u1024;
| ^^^^^^^^^
= help: valid widths are 8, 16, 32, 64 and 128
error: invalid width `1024` for integer literal
- --> $DIR/bad-lit-suffixes.rs:21:5
+ --> $DIR/bad-lit-suffixes.rs:18:5
|
LL | 1234i1024;
| ^^^^^^^^^
= help: valid widths are 8, 16, 32, 64 and 128
error: invalid width `1024` for float literal
- --> $DIR/bad-lit-suffixes.rs:22:5
+ --> $DIR/bad-lit-suffixes.rs:19:5
|
LL | 1234f1024;
| ^^^^^^^^^
= help: valid widths are 32 and 64
error: invalid width `1024` for float literal
- --> $DIR/bad-lit-suffixes.rs:23:5
+ --> $DIR/bad-lit-suffixes.rs:20:5
|
LL | 1234.5f1024;
| ^^^^^^^^^^^
= help: valid widths are 32 and 64
error: invalid suffix `suffix` for integer literal
- --> $DIR/bad-lit-suffixes.rs:25:5
+ --> $DIR/bad-lit-suffixes.rs:22:5
|
LL | 1234suffix;
| ^^^^^^^^^^ invalid suffix `suffix`
= help: the suffix must be one of the integral types (`u32`, `isize`, etc)
error: invalid suffix `suffix` for integer literal
- --> $DIR/bad-lit-suffixes.rs:26:5
+ --> $DIR/bad-lit-suffixes.rs:23:5
|
LL | 0b101suffix;
| ^^^^^^^^^^^ invalid suffix `suffix`
= help: the suffix must be one of the integral types (`u32`, `isize`, etc)
error: invalid suffix `suffix` for float literal
- --> $DIR/bad-lit-suffixes.rs:27:5
+ --> $DIR/bad-lit-suffixes.rs:24:5
|
LL | 1.0suffix;
| ^^^^^^^^^ invalid suffix `suffix`
= help: valid suffixes are `f32` and `f64`
error: invalid suffix `suffix` for float literal
- --> $DIR/bad-lit-suffixes.rs:28:5
+ --> $DIR/bad-lit-suffixes.rs:25:5
|
LL | 1.0e10suffix;
| ^^^^^^^^^^^^ invalid suffix `suffix`
-// compile-flags: -Z parse-only -Z continue-parse-after-error
+// compile-flags: -Z parse-only
struct S<
T: 'a + Tr, // OK
-// compile-flags: -Z continue-parse-after-error
-
struct X {
a: u8 /** document a */,
//~^ ERROR found a documentation comment that doesn't document anything
error[E0585]: found a documentation comment that doesn't document anything
- --> $DIR/doc-after-struct-field.rs:4:11
+ --> $DIR/doc-after-struct-field.rs:2:11
|
LL | a: u8 /** document a */,
| ^^^^^^^^^^^^^^^^^
= help: doc comments must come before what they document, maybe a comment was intended with `//`?
error[E0585]: found a documentation comment that doesn't document anything
- --> $DIR/doc-after-struct-field.rs:10:11
+ --> $DIR/doc-after-struct-field.rs:8:11
|
LL | a: u8 /// document a
| ^^^^^^^^^^^^^^
-// compile-flags: -Z continue-parse-after-error
-
fn main() {
/// document
//~^ ERROR found a documentation comment that doesn't document anything
error[E0585]: found a documentation comment that doesn't document anything
- --> $DIR/doc-before-fn-rbrace.rs:4:5
+ --> $DIR/doc-before-fn-rbrace.rs:2:5
|
LL | /// document
| ^^^^^^^^^^^^
-// compile-flags: -Z continue-parse-after-error
-
fn /// document
foo() {}
//~^^ ERROR expected identifier, found doc comment `/// document`
error: expected identifier, found doc comment `/// document`
- --> $DIR/doc-before-identifier.rs:3:4
+ --> $DIR/doc-before-identifier.rs:1:4
|
LL | fn /// document
| ^^^^^^^^^^^^ expected identifier, found doc comment
-// compile-flags: -Z continue-parse-after-error
-
mod Foo {
/// document
//~^ ERROR expected item after doc comment
error: expected item after doc comment
- --> $DIR/doc-before-mod-rbrace.rs:4:5
+ --> $DIR/doc-before-mod-rbrace.rs:2:5
|
LL | /// document
| ^^^^^^^^^^^^ this doc comment doesn't document anything
-// compile-flags: -Z continue-parse-after-error
-
struct X {
a: u8,
/// document
error[E0585]: found a documentation comment that doesn't document anything
- --> $DIR/doc-before-struct-rbrace-1.rs:5:5
+ --> $DIR/doc-before-struct-rbrace-1.rs:3:5
|
LL | /// document
| ^^^^^^^^^^^^
-// compile-flags: -Z continue-parse-after-error
-
struct X {
a: u8 /// document
//~^ ERROR found a documentation comment that doesn't document anything
error[E0585]: found a documentation comment that doesn't document anything
- --> $DIR/doc-before-struct-rbrace-2.rs:4:11
+ --> $DIR/doc-before-struct-rbrace-2.rs:2:11
|
LL | a: u8 /// document
| ^^^^^^^^^^^^
-// compile-flags: -Z continue-parse-after-error
-
struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found keyword `where`
fn main() {}
error: expected item, found keyword `where`
- --> $DIR/issue-17904-2.rs:3:24
+ --> $DIR/issue-17904-2.rs:1:24
|
LL | struct Bar<T> { x: T } where T: Copy
| ^^^^^ expected item
-// compile-flags: -Z continue-parse-after-error
-
struct Baz<U> where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax.
struct Baz<U> where U: Eq(U) -> R; // Notice this parses as well.
struct Baz<U>(U) where U: Eq; // This rightfully signals no error as well.
error: expected one of `:`, `==`, or `=`, found `;`
- --> $DIR/issue-17904.rs:6:33
+ --> $DIR/issue-17904.rs:4:33
|
LL | struct Foo<T> where T: Copy, (T);
| ^ expected one of `:`, `==`, or `=` here
-// compile-flags: -Z continue-parse-after-error
-
trait Trait<T> { type Item; }
pub fn test<W, I: Trait<Item=(), W> >() {}
error: associated type bindings must be declared after generic parameters
- --> $DIR/issue-32214.rs:5:25
+ --> $DIR/issue-32214.rs:3:25
|
LL | pub fn test<W, I: Trait<Item=(), W> >() {}
| -------^^^
-// compile-flags: -Z continue-parse-after-error
-
pub fn test() {
foo(|_|) //~ ERROR expected expression, found `)`
}
error: expected expression, found `)`
- --> $DIR/issue-32505.rs:4:12
+ --> $DIR/issue-32505.rs:2:12
|
LL | foo(|_|)
| ^ expected expression
-// compile-flags: -Z continue-parse-after-error
-
fn main() {
0b121; //~ ERROR invalid digit for a base 2 literal
0b10_10301; //~ ERROR invalid digit for a base 2 literal
error: invalid digit for a base 2 literal
- --> $DIR/lex-bad-binary-literal.rs:4:8
+ --> $DIR/lex-bad-binary-literal.rs:2:8
|
LL | 0b121;
| ^
error: invalid digit for a base 2 literal
- --> $DIR/lex-bad-binary-literal.rs:5:12
+ --> $DIR/lex-bad-binary-literal.rs:3:12
|
LL | 0b10_10301;
| ^
error: invalid digit for a base 2 literal
- --> $DIR/lex-bad-binary-literal.rs:6:7
+ --> $DIR/lex-bad-binary-literal.rs:4:7
|
LL | 0b30;
| ^
error: invalid digit for a base 2 literal
- --> $DIR/lex-bad-binary-literal.rs:7:7
+ --> $DIR/lex-bad-binary-literal.rs:5:7
|
LL | 0b41;
| ^
error: invalid digit for a base 2 literal
- --> $DIR/lex-bad-binary-literal.rs:8:7
+ --> $DIR/lex-bad-binary-literal.rs:6:7
|
LL | 0b5;
| ^
error: invalid digit for a base 2 literal
- --> $DIR/lex-bad-binary-literal.rs:9:7
+ --> $DIR/lex-bad-binary-literal.rs:7:7
|
LL | 0b6;
| ^
error: invalid digit for a base 2 literal
- --> $DIR/lex-bad-binary-literal.rs:10:7
+ --> $DIR/lex-bad-binary-literal.rs:8:7
|
LL | 0b7;
| ^
error: invalid digit for a base 2 literal
- --> $DIR/lex-bad-binary-literal.rs:11:7
+ --> $DIR/lex-bad-binary-literal.rs:9:7
|
LL | 0b8;
| ^
error: invalid digit for a base 2 literal
- --> $DIR/lex-bad-binary-literal.rs:12:7
+ --> $DIR/lex-bad-binary-literal.rs:10:7
|
LL | 0b9;
| ^
-// compile-flags: -Z continue-parse-after-error
-
fn main() {
0o1.0; //~ ERROR: octal float literal is not supported
0o2f32; //~ ERROR: octal float literal is not supported
error: octal float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:4:5
+ --> $DIR/lex-bad-numeric-literals.rs:2:5
|
LL | 0o1.0;
| ^^^^^
error: octal float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:6:5
+ --> $DIR/lex-bad-numeric-literals.rs:4:5
|
LL | 0o3.0f32;
| ^^^^^
error: octal float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:7:5
+ --> $DIR/lex-bad-numeric-literals.rs:5:5
|
LL | 0o4e4;
| ^^^^^
error: octal float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:8:5
+ --> $DIR/lex-bad-numeric-literals.rs:6:5
|
LL | 0o5.0e5;
| ^^^^^^^
error: octal float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:9:5
+ --> $DIR/lex-bad-numeric-literals.rs:7:5
|
LL | 0o6e6f32;
| ^^^^^
error: octal float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:10:5
+ --> $DIR/lex-bad-numeric-literals.rs:8:5
|
LL | 0o7.0e7f64;
| ^^^^^^^
error: hexadecimal float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:11:5
+ --> $DIR/lex-bad-numeric-literals.rs:9:5
|
LL | 0x8.0e+9;
| ^^^^^^^^
error: hexadecimal float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:12:5
+ --> $DIR/lex-bad-numeric-literals.rs:10:5
|
LL | 0x9.0e-9;
| ^^^^^^^^
error: no valid digits found for number
- --> $DIR/lex-bad-numeric-literals.rs:13:5
+ --> $DIR/lex-bad-numeric-literals.rs:11:5
|
LL | 0o;
| ^^
error: expected at least one digit in exponent
- --> $DIR/lex-bad-numeric-literals.rs:14:8
+ --> $DIR/lex-bad-numeric-literals.rs:12:8
|
LL | 1e+;
| ^
error: hexadecimal float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:15:5
+ --> $DIR/lex-bad-numeric-literals.rs:13:5
|
LL | 0x539.0;
| ^^^^^^^
error: no valid digits found for number
- --> $DIR/lex-bad-numeric-literals.rs:20:5
+ --> $DIR/lex-bad-numeric-literals.rs:18:5
|
LL | 0x;
| ^^
error: no valid digits found for number
- --> $DIR/lex-bad-numeric-literals.rs:21:5
+ --> $DIR/lex-bad-numeric-literals.rs:19:5
|
LL | 0xu32;
| ^^
error: no valid digits found for number
- --> $DIR/lex-bad-numeric-literals.rs:22:5
+ --> $DIR/lex-bad-numeric-literals.rs:20:5
|
LL | 0ou32;
| ^^
error: no valid digits found for number
- --> $DIR/lex-bad-numeric-literals.rs:23:5
+ --> $DIR/lex-bad-numeric-literals.rs:21:5
|
LL | 0bu32;
| ^^
error: no valid digits found for number
- --> $DIR/lex-bad-numeric-literals.rs:24:5
+ --> $DIR/lex-bad-numeric-literals.rs:22:5
|
LL | 0b;
| ^^
error: octal float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:26:5
+ --> $DIR/lex-bad-numeric-literals.rs:24:5
|
LL | 0o123.456;
| ^^^^^^^^^
error: binary float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:28:5
+ --> $DIR/lex-bad-numeric-literals.rs:26:5
|
LL | 0b111.101;
| ^^^^^^^^^
error: octal float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:5:5
+ --> $DIR/lex-bad-numeric-literals.rs:3:5
|
LL | 0o2f32;
| ^^^^^^ not supported
error: integer literal is too large
- --> $DIR/lex-bad-numeric-literals.rs:16:5
+ --> $DIR/lex-bad-numeric-literals.rs:14:5
|
LL | 9900000000000000000000000000999999999999999999999999999999;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: integer literal is too large
- --> $DIR/lex-bad-numeric-literals.rs:18:5
+ --> $DIR/lex-bad-numeric-literals.rs:16:5
|
LL | 9900000000000000000000000000999999999999999999999999999999;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: octal float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:25:5
+ --> $DIR/lex-bad-numeric-literals.rs:23:5
|
LL | 0o123f64;
| ^^^^^^^^ not supported
error: binary float literal is not supported
- --> $DIR/lex-bad-numeric-literals.rs:27:5
+ --> $DIR/lex-bad-numeric-literals.rs:25:5
|
LL | 0b101f64;
| ^^^^^^^^ not supported
-// compile-flags: -Z continue-parse-after-error
-
fn main() {
0o18; //~ ERROR invalid digit for a base 8 literal
0o1234_9_5670; //~ ERROR invalid digit for a base 8 literal
error: invalid digit for a base 8 literal
- --> $DIR/lex-bad-octal-literal.rs:4:8
+ --> $DIR/lex-bad-octal-literal.rs:2:8
|
LL | 0o18;
| ^
error: invalid digit for a base 8 literal
- --> $DIR/lex-bad-octal-literal.rs:5:12
+ --> $DIR/lex-bad-octal-literal.rs:3:12
|
LL | 0o1234_9_5670;
| ^
-// compile-flags: -Z continue-parse-after-error
-
macro_rules! ignored_item {
() => {
fn foo() {}
error: macro expansion ignores token `,` and any following
- --> $DIR/macro-incomplete-parse.rs:7:9
+ --> $DIR/macro-incomplete-parse.rs:5:9
|
LL | ,
| ^
= note: the usage of `ignored_item!` is likely invalid in item context
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
- --> $DIR/macro-incomplete-parse.rs:12:14
+ --> $DIR/macro-incomplete-parse.rs:10:14
|
LL | () => ( 1,
| ^ expected one of `.`, `;`, `?`, `}`, or an operator here
| ---------------- in this macro invocation
error: macro expansion ignores token `,` and any following
- --> $DIR/macro-incomplete-parse.rs:18:14
+ --> $DIR/macro-incomplete-parse.rs:16:14
|
LL | () => ( 1, 2 )
| ^
-// compile-flags: -Z continue-parse-after-error
-
pub fn main() {
let s = "\u{lol}";
//~^ ERROR invalid character in unicode escape: l
error: invalid character in unicode escape: l
- --> $DIR/new-unicode-escapes-4.rs:4:17
+ --> $DIR/new-unicode-escapes-4.rs:2:17
|
LL | let s = "\u{lol}";
| ^
-// compile-flags: -Z continue-parse-after-error
-
trait A {
fn foo(*mut self); //~ ERROR cannot pass `self` by raw pointer
fn baz(*const self); //~ ERROR cannot pass `self` by raw pointer
error: cannot pass `self` by raw pointer
- --> $DIR/no-unsafe-self.rs:4:17
+ --> $DIR/no-unsafe-self.rs:2:17
|
LL | fn foo(*mut self);
| ^^^^ cannot pass `self` by raw pointer
error: cannot pass `self` by raw pointer
- --> $DIR/no-unsafe-self.rs:5:19
+ --> $DIR/no-unsafe-self.rs:3:19
|
LL | fn baz(*const self);
| ^^^^ cannot pass `self` by raw pointer
error: cannot pass `self` by raw pointer
- --> $DIR/no-unsafe-self.rs:6:13
+ --> $DIR/no-unsafe-self.rs:4:13
|
LL | fn bar(*self);
| ^^^^ cannot pass `self` by raw pointer
error: cannot pass `self` by raw pointer
- --> $DIR/no-unsafe-self.rs:11:17
+ --> $DIR/no-unsafe-self.rs:9:17
|
LL | fn foo(*mut self) { }
| ^^^^ cannot pass `self` by raw pointer
error: cannot pass `self` by raw pointer
- --> $DIR/no-unsafe-self.rs:12:19
+ --> $DIR/no-unsafe-self.rs:10:19
|
LL | fn baz(*const self) { }
| ^^^^ cannot pass `self` by raw pointer
error: cannot pass `self` by raw pointer
- --> $DIR/no-unsafe-self.rs:13:13
+ --> $DIR/no-unsafe-self.rs:11:13
|
LL | fn bar(*self) { }
| ^^^^ cannot pass `self` by raw pointer
-// compile-flags: -Z continue-parse-after-error
-
// Make sure that inclusive ranges with `...` syntax don't parse.
use std::ops::RangeToInclusive;
error: unexpected token: `...`
- --> $DIR/range_inclusive_dotdotdot.rs:8:12
+ --> $DIR/range_inclusive_dotdotdot.rs:6:12
|
LL | return ...1;
| ^^^
| ^^^
error: unexpected token: `...`
- --> $DIR/range_inclusive_dotdotdot.rs:14:13
+ --> $DIR/range_inclusive_dotdotdot.rs:12:13
|
LL | let x = ...0;
| ^^^
| ^^^
error: unexpected token: `...`
- --> $DIR/range_inclusive_dotdotdot.rs:18:14
+ --> $DIR/range_inclusive_dotdotdot.rs:16:14
|
LL | let x = 5...5;
| ^^^
| ^^^
error: unexpected token: `...`
- --> $DIR/range_inclusive_dotdotdot.rs:22:15
+ --> $DIR/range_inclusive_dotdotdot.rs:20:15
|
LL | for _ in 0...1 {}
| ^^^
-// compile-flags: -Z continue-parse-after-error
-
-
pub fn main() {
br"é"; //~ ERROR raw byte string must be ASCII
br##~"a"~##; //~ ERROR only `#` is allowed in raw string delimitation
error: raw byte string must be ASCII: \u{e9}
- --> $DIR/raw-byte-string-literals.rs:5:8
+ --> $DIR/raw-byte-string-literals.rs:2:8
|
LL | br"é";
| ^
error: found invalid character; only `#` is allowed in raw string delimitation: ~
- --> $DIR/raw-byte-string-literals.rs:6:6
+ --> $DIR/raw-byte-string-literals.rs:3:6
|
LL | br##~"a"~##;
| ^^^
-// compile-flags: -Z continue-parse-after-error
-
fn main() {
enum Test {
Very
error: missing comma
- --> $DIR/recover-enum.rs:5:13
+ --> $DIR/recover-enum.rs:3:13
|
LL | Very
| ^ help: missing comma
error: missing comma
- --> $DIR/recover-enum.rs:7:19
+ --> $DIR/recover-enum.rs:5:19
|
LL | Bad(usize)
| ^ help: missing comma
error: missing comma
- --> $DIR/recover-enum.rs:9:27
+ --> $DIR/recover-enum.rs:7:27
|
LL | Stuff { a: usize }
| ^ help: missing comma
-// compile-flags: -Z continue-parse-after-error
-
fn main() {
enum Test {
Var1,
error: expected type, found `{`
- --> $DIR/recover-enum2.rs:8:18
+ --> $DIR/recover-enum2.rs:6:18
|
LL | abc: {},
| ^
error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `{`
- --> $DIR/recover-enum2.rs:27:22
+ --> $DIR/recover-enum2.rs:25:22
|
LL | Nope(i32 {})
| ^ expected one of 7 possible tokens here
LL | let x = Enum::Foo(a: 3, b: 4);
| ^ expecting a type here because of type ascription
|
- = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+ = note: #![feature(type_ascription)] lets you annotate an expression with a type: `<expr>: <type>`
note: this expression expects an ascribed type after the colon
--> $DIR/recover-from-bad-variant.rs:7:23
|
-// compile-flags: -Z continue-parse-after-error
-
fn main() {
struct Test {
Very
error: expected `:`, found `Bad`
- --> $DIR/recover-struct.rs:6:9
+ --> $DIR/recover-struct.rs:4:9
|
LL | Very
| - expected `:`
-// compile-flags: -Z continue-parse-after-error
-
struct S {
let foo: (),
//~^ ERROR expected identifier, found keyword `let`
error: expected identifier, found keyword `let`
- --> $DIR/removed-syntax-field-let.rs:4:5
+ --> $DIR/removed-syntax-field-let.rs:2:5
|
LL | let foo: (),
| ^^^ expected identifier, found keyword
| ^^^^^
error: expected `:`, found `foo`
- --> $DIR/removed-syntax-field-let.rs:4:9
+ --> $DIR/removed-syntax-field-let.rs:2:9
|
LL | let foo: (),
| ^^^ expected `:`
// compile-pass
-// compile-flags: -Z continue-parse-after-error
#![feature(box_syntax)]
#![allow(bare_trait_objects)]
-// compile-flags: -Z continue-parse-after-error
-
-trait Foo {
-}
+trait Foo {}
struct Bar;
-impl Foo + Owned for Bar { //~ ERROR expected a trait, found type
-}
+impl Foo + Owned for Bar {} //~ ERROR expected a trait, found type
fn main() { }
error: expected a trait, found type
- --> $DIR/trait-bounds-not-on-impl.rs:8:6
+ --> $DIR/trait-bounds-not-on-impl.rs:5:6
|
-LL | impl Foo + Owned for Bar {
+LL | impl Foo + Owned for Bar {}
| ^^^^^^^^^^^
error: aborting due to previous error
-// compile-flags: -Z continue-parse-after-error
-
#![feature(optin_builtin_traits)]
#![allow(bare_trait_objects)]
error[E0178]: expected a path on the left-hand side of `+`, not `((Auto))`
- --> $DIR/trait-object-bad-parens.rs:9:16
+ --> $DIR/trait-object-bad-parens.rs:7:16
|
LL | let _: Box<((Auto)) + Auto>;
| ^^^^^^^^^^^^^^^ expected a path
error[E0178]: expected a path on the left-hand side of `+`, not `(Auto + Auto)`
- --> $DIR/trait-object-bad-parens.rs:11:16
+ --> $DIR/trait-object-bad-parens.rs:9:16
|
LL | let _: Box<(Auto + Auto) + Auto>;
| ^^^^^^^^^^^^^^^^^^^^ expected a path
error[E0178]: expected a path on the left-hand side of `+`, not `(Auto)`
- --> $DIR/trait-object-bad-parens.rs:13:16
+ --> $DIR/trait-object-bad-parens.rs:11:16
|
LL | let _: Box<(Auto +) + Auto>;
| ^^^^^^^^^^^^^^^ expected a path
error[E0178]: expected a path on the left-hand side of `+`, not `(dyn Auto)`
- --> $DIR/trait-object-bad-parens.rs:15:16
+ --> $DIR/trait-object-bad-parens.rs:13:16
|
LL | let _: Box<(dyn Auto) + Auto>;
| ^^^^^^^^^^^^^^^^^ expected a path
-// compile-flags: -Z continue-parse-after-error
-
#![allow(bare_trait_objects)]
trait Trait {}
error: parenthesized lifetime bounds are not supported
- --> $DIR/trait-object-lifetime-parens.rs:7:21
+ --> $DIR/trait-object-lifetime-parens.rs:5:21
|
LL | fn f<'a, T: Trait + ('a)>() {}
| ^^^^ help: remove the parentheses
error: parenthesized lifetime bounds are not supported
- --> $DIR/trait-object-lifetime-parens.rs:10:24
+ --> $DIR/trait-object-lifetime-parens.rs:8:24
|
LL | let _: Box<Trait + ('a)>;
| ^^^^ help: remove the parentheses
error: expected `:`, found `)`
- --> $DIR/trait-object-lifetime-parens.rs:11:19
+ --> $DIR/trait-object-lifetime-parens.rs:9:19
|
LL | let _: Box<('a) + Trait>;
| ^ expected `:`
error: chained comparison operators require parentheses
- --> $DIR/trait-object-lifetime-parens.rs:11:15
+ --> $DIR/trait-object-lifetime-parens.rs:9:15
|
LL | let _: Box<('a) + Trait>;
| ^^^^^^^^^^^^^^^
= help: or use `(...)` if you meant to specify fn arguments
error: expected type, found `'a`
- --> $DIR/trait-object-lifetime-parens.rs:11:17
+ --> $DIR/trait-object-lifetime-parens.rs:9:17
|
LL | let _: Box<('a) + Trait>;
| - ^^
-// compile-flags: -Z continue-parse-after-error
-
use std::any:: as foo; //~ ERROR expected identifier, found keyword `as`
//~^ ERROR: expected one of `::`, `;`, or `as`, found `foo`
error: expected identifier, found keyword `as`
- --> $DIR/use-as-where-use-ends-with-mod-sep.rs:3:16
+ --> $DIR/use-as-where-use-ends-with-mod-sep.rs:1:16
|
LL | use std::any:: as foo;
| ^^ expected identifier, found keyword
| ^^^^
error: expected one of `::`, `;`, or `as`, found `foo`
- --> $DIR/use-as-where-use-ends-with-mod-sep.rs:3:19
+ --> $DIR/use-as-where-use-ends-with-mod-sep.rs:1:19
|
LL | use std::any:: as foo;
| ^^^ expected one of `::`, `;`, or `as` here
-// compile-flags: -Z continue-parse-after-error
-
// Empty predicate list is OK
fn equal1<T>(_: &T, _: &T) -> bool where {
true
error: expected `:`, found `{`
- --> $DIR/where-clauses-no-bounds-or-predicates.rs:13:23
+ --> $DIR/where-clauses-no-bounds-or-predicates.rs:11:23
|
LL | fn foo<'a>() where 'a {}
| ^ expected `:`
-// compile-flags: -Z continue-parse-after-error
-
mod foo {
struct Self;
//~^ ERROR expected identifier, found keyword `Self`
error: expected identifier, found keyword `Self`
- --> $DIR/self_type_keyword.rs:4:10
+ --> $DIR/self_type_keyword.rs:2:10
|
LL | struct Self;
| ^^^^ expected identifier, found keyword
error: expected identifier, found keyword `Self`
- --> $DIR/self_type_keyword.rs:16:13
+ --> $DIR/self_type_keyword.rs:14:13
|
LL | ref Self => (),
| ^^^^ expected identifier, found keyword
error: expected identifier, found keyword `Self`
- --> $DIR/self_type_keyword.rs:18:13
+ --> $DIR/self_type_keyword.rs:16:13
|
LL | mut Self => (),
| ^^^^ expected identifier, found keyword
error: expected identifier, found keyword `Self`
- --> $DIR/self_type_keyword.rs:20:17
+ --> $DIR/self_type_keyword.rs:18:17
|
LL | ref mut Self => (),
| ^^^^ expected identifier, found keyword
error: expected identifier, found keyword `Self`
- --> $DIR/self_type_keyword.rs:24:15
+ --> $DIR/self_type_keyword.rs:22:15
|
LL | Foo { Self } => (),
| ^^^^ expected identifier, found keyword
error: expected identifier, found keyword `Self`
- --> $DIR/self_type_keyword.rs:30:26
+ --> $DIR/self_type_keyword.rs:28:26
|
LL | extern crate core as Self;
| ^^^^ expected identifier, found keyword
error: expected identifier, found keyword `Self`
- --> $DIR/self_type_keyword.rs:35:32
+ --> $DIR/self_type_keyword.rs:33:32
|
LL | use std::option::Option as Self;
| ^^^^ expected identifier, found keyword
error: expected identifier, found keyword `Self`
- --> $DIR/self_type_keyword.rs:40:11
+ --> $DIR/self_type_keyword.rs:38:11
|
LL | trait Self {}
| ^^^^ expected identifier, found keyword
error: lifetimes cannot use keyword names
- --> $DIR/self_type_keyword.rs:8:12
+ --> $DIR/self_type_keyword.rs:6:12
|
LL | struct Bar<'Self>;
| ^^^^^
error: cannot find macro `Self!` in this scope
- --> $DIR/self_type_keyword.rs:22:9
+ --> $DIR/self_type_keyword.rs:20:9
|
LL | Self!() => (),
| ^^^^
error[E0392]: parameter `'Self` is never used
- --> $DIR/self_type_keyword.rs:8:12
+ --> $DIR/self_type_keyword.rs:6:12
|
LL | struct Bar<'Self>;
| ^^^^^ unused parameter
// A few contrived examples where lifetime should (or should not) be parsed as an object type.
// Lifetimes parsed as types are still rejected later by semantic checks.
-// compile-flags: -Z continue-parse-after-error
-
// `'static` is a lifetime, `'static +` is a type, `'a` is a type
fn g() where
'static: 'static,
error[E0224]: at least one non-builtin trait is required for an object type
- --> $DIR/trait-object-vs-lifetime-2.rs:9:5
+ --> $DIR/trait-object-vs-lifetime-2.rs:7:5
|
LL | dyn 'static +: 'static + Copy,
| ^^^^^^^^^^^^^
LL | println!("test"): 0;
| ^ expecting a type here because of type ascription
|
- = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+ = note: #![feature(type_ascription)] lets you annotate an expression with a type: `<expr>: <type>`
note: this expression expects an ascribed type after the colon
--> $DIR/type-ascription-instead-of-statement-end.rs:9:5
|
-Subproject commit d2f51228152a139a2a8aaba59b8a4e68f498ff26
+Subproject commit f3087c37bf5d8491b72ce007b65a47c2d3c2e733