[[package]]
name = "curl-sys"
-version = "0.4.45+curl-7.78.0"
+version = "0.4.48+curl-7.79.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de9e5a72b1c744eb5dd20b2be4d7eb84625070bb5c4ab9b347b70464ab1e62eb"
+checksum = "a6a77a741f832116da66aeb126b4f19190ecf46144a74a9bde43c2086f38da0e"
dependencies = [
"cc",
"libc",
+Rust 1.56.0 (2021-10-21)
+========================
+
+Language
+--------
+
+- [The 2021 Edition is now stable.][rust#88100]
+ See [the edition guide][rust-2021-edition-guide] for more details.
+- [You can now specify explicit discriminant values on any Rust enum.][rust#86860]
+- [The pattern in `binding @ pattern` can now also introduce new bindings.][rust#85305]
+- [Union field access is permitted in `const fn`.][rust#85769]
+
+[rust-2021-edition-guide]: https://doc.rust-lang.org/nightly/edition-guide/rust-2021/index.html
+
+Compiler
+--------
+
+- [Upgrade to LLVM 13.][rust#87570]
+- [Support memory, address, and thread sanitizers on aarch64-unknown-freebsd.][rust#88023]
+- [Allow specifying a deployment target version for all iOS targets][rust#87699]
+- [Warnings can be forced on with `--force-warn`.][rust#87472]
+ This feature is primarily intended for usage by `cargo fix`, rather than end users.
+- [Promote `aarch64-apple-ios-sim` to Tier 2\*.][rust#87760]
+- [Add `powerpc-unknown-freebsd` at Tier 3\*.][rust#87370]
+
+\* Refer to Rust's [platform support page][platform-support-doc] for more
+information on Rust's tiered platform support.
+
+Libraries
+---------
+
+- [Allow writing of incomplete UTF-8 sequences via stdout/stderr on Windows.][rust#83342]
+ The Windows console still requires valid Unicode, but this change allows
+ splitting a UTF-8 character across multiple write calls. This allows, for
+ instance, programs that just read and write data buffers (e.g. copying a file
+ to stdout) without regard for Unicode or character boundaries.
+- [Prefer `AtomicU{64,128}` over Mutex for Instant backsliding protection.][rust#83093]
+ For this use case, atomics scale much better under contention.
+- [Implement `Extend<(A, B)>` for `(Extend<A>, Extend<B>)`][rust#85835]
+- [impl Default, Copy, Clone for std::io::Sink and std::io::Empty][rust#86744]
+- [`impl From<[(K, V); N]>` for all collections.][rust#84111]
+- [Remove `P: Unpin` bound on impl Future for Pin.][rust#81363]
+- [Treat invalid environment variable names as non-existent.][rust#86183]
+ Previously, the environment functions would panic if given a variable name
+ with an internal null character or equal sign (`=`). Now, these functions will
+ just treat such names as non-existent variables, since the OS cannot represent
+ the existence of a variable with such a name.
+
+Stabilised APIs
+---------------
+
+- [`std::os::unix::fs::chroot`]
+- [`Iterator::intersperse`]
+- [`Iterator::intersperse_with`]
+- [`UnsafeCell::raw_get`]
+- [`BufWriter::into_parts`]
+- [`core::panic::{UnwindSafe, RefUnwindSafe, AssertUnwindSafe}`]
+ These APIs were previously stable in `std`, but are now also available in `core`.
+- [`Vec::shrink_to`]
+- [`String::shrink_to`]
+- [`OsString::shrink_to`]
+- [`PathBuf::shrink_to`]
+- [`BinaryHeap::shrink_to`]
+- [`VecDeque::shrink_to`]
+- [`HashMap::shrink_to`]
+- [`HashSet::shrink_to`]
+- [`task::ready!`]
+
+These APIs are now usable in const contexts:
+
+- [`std::mem::transmute`]
+- [`[T]::first`][`slice::first`]
+- [`[T]::split_first`][`slice::split_first`]
+- [`[T]::last`][`slice::last`]
+- [`[T]::split_last`][`slice::split_last`]
+
+Cargo
+-----
+
+- [Cargo supports specifying a minimum supported Rust version in Cargo.toml.][`rust-version`]
+ This has no effect at present on dependency version selection.
+ We encourage crates to specify their minimum supported Rust version, and we encourage CI systems
+ that support Rust code to include a crate's specified minimum version in the text matrix for that
+ crate by default.
+
+Compatibility notes
+-------------------
+
+- [Update to new argument parsing rules on Windows.][rust#87580]
+ This adjusts Rust's standard library to match the behavior of the standard
+ libraries for C/C++. The rules have changed slightly over time, and this PR
+ brings us to the latest set of rules (changed in 2008).
+- [Disallow the aapcs calling convention on aarch64][rust#88399]
+ This was already not supported by LLVM; this change surfaces this lack of
+ support with a better error message.
+- [Make `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` warn by default][rust#87385]
+- [Warn when an escaped newline skips multiple lines.][rust#87671]
+- [Calls to `libc::getpid` / `std::process::id` from `Command::pre_exec`
+ may return different values on glibc <= 2.24.][rust#81825]
+ Rust now invokes the `clone3` system call directly, when available, to use new functionality
+ available via that system call. Older versions of glibc cache the result of `getpid`, and only
+ update that cache when calling glibc's clone/fork functions, so a direct system call bypasses
+ that cache update. glibc 2.25 and newer no longer cache `getpid` for exactly this reason.
+
+Internal changes
+----------------
+These changes provide no direct user facing benefits, but represent significant
+improvements to the internals and overall performance of rustc
+and related tools.
+
+- [LLVM is compiled with PGO in published x86_64-unknown-linux-gnu artifacts.][rust#88069]
+ This improves the performance of most Rust builds.
+- [Unify representation of macros in internal data structures.][rust#88019]
+ This change fixes a host of bugs with the handling of macros by the compiler,
+ as well as rustdoc.
+
+[`std::os::unix::fs::chroot`]: https://doc.rust-lang.org/stable/std/os/unix/fs/fn.chroot.html
+[`Iterator::intersperse`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.intersperse
+[`Iterator::intersperse_with`]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.intersperse
+[`UnsafeCell::raw_get`]: https://doc.rust-lang.org/stable/std/cell/struct.UnsafeCell.html#method.raw_get
+[`BufWriter::into_parts`]: https://doc.rust-lang.org/stable/std/io/struct.BufWriter.html#method.into_parts
+[`core::panic::{UnwindSafe, RefUnwindSafe, AssertUnwindSafe}`]: https://github.com/rust-lang/rust/pull/84662
+[`Vec::shrink_to`]: https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.shrink_to
+[`String::shrink_to`]: https://doc.rust-lang.org/stable/std/string/struct.String.html#method.shrink_to
+[`OsString::shrink_to`]: https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.shrink_to
+[`PathBuf::shrink_to`]: https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#method.shrink_to
+[`BinaryHeap::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/struct.BinaryHeap.html#method.shrink_to
+[`VecDeque::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.shrink_to
+[`HashMap::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/hash_map/struct.HashMap.html#method.shrink_to
+[`HashSet::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/hash_set/struct.HashSet.html#method.shrink_to
+[`task::ready!`]: https://doc.rust-lang.org/stable/std/task/macro.ready.html
+[`std::mem::transmute`]: https://doc.rust-lang.org/stable/std/mem/fn.transmute.html
+[`slice::first`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.first
+[`slice::split_first`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_first
+[`slice::last`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.last
+[`slice::split_last`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_last
+[`rust-version`]: https://doc.rust-lang.org/nightly/cargo/reference/manifest.html#the-rust-version-field
+[rust#87671]: https://github.com/rust-lang/rust/pull/87671
+[rust#86183]: https://github.com/rust-lang/rust/pull/86183
+[rust#87385]: https://github.com/rust-lang/rust/pull/87385
+[rust#88100]: https://github.com/rust-lang/rust/pull/88100
+[rust#86860]: https://github.com/rust-lang/rust/pull/86860
+[rust#84039]: https://github.com/rust-lang/rust/pull/84039
+[rust#86492]: https://github.com/rust-lang/rust/pull/86492
+[rust#88363]: https://github.com/rust-lang/rust/pull/88363
+[rust#85305]: https://github.com/rust-lang/rust/pull/85305
+[rust#87832]: https://github.com/rust-lang/rust/pull/87832
+[rust#88069]: https://github.com/rust-lang/rust/pull/88069
+[rust#87472]: https://github.com/rust-lang/rust/pull/87472
+[rust#87699]: https://github.com/rust-lang/rust/pull/87699
+[rust#87570]: https://github.com/rust-lang/rust/pull/87570
+[rust#88023]: https://github.com/rust-lang/rust/pull/88023
+[rust#87760]: https://github.com/rust-lang/rust/pull/87760
+[rust#87370]: https://github.com/rust-lang/rust/pull/87370
+[rust#87580]: https://github.com/rust-lang/rust/pull/87580
+[rust#83342]: https://github.com/rust-lang/rust/pull/83342
+[rust#83093]: https://github.com/rust-lang/rust/pull/83093
+[rust#88177]: https://github.com/rust-lang/rust/pull/88177
+[rust#88548]: https://github.com/rust-lang/rust/pull/88548
+[rust#88551]: https://github.com/rust-lang/rust/pull/88551
+[rust#88299]: https://github.com/rust-lang/rust/pull/88299
+[rust#88220]: https://github.com/rust-lang/rust/pull/88220
+[rust#85835]: https://github.com/rust-lang/rust/pull/85835
+[rust#86879]: https://github.com/rust-lang/rust/pull/86879
+[rust#86744]: https://github.com/rust-lang/rust/pull/86744
+[rust#84662]: https://github.com/rust-lang/rust/pull/84662
+[rust#86593]: https://github.com/rust-lang/rust/pull/86593
+[rust#81050]: https://github.com/rust-lang/rust/pull/81050
+[rust#81363]: https://github.com/rust-lang/rust/pull/81363
+[rust#84111]: https://github.com/rust-lang/rust/pull/84111
+[rust#85769]: https://github.com/rust-lang/rust/pull/85769#issuecomment-854363720
+[rust#88490]: https://github.com/rust-lang/rust/pull/88490
+[rust#88269]: https://github.com/rust-lang/rust/pull/88269
+[rust#84176]: https://github.com/rust-lang/rust/pull/84176
+[rust#88399]: https://github.com/rust-lang/rust/pull/88399
+[rust#88227]: https://github.com/rust-lang/rust/pull/88227
+[rust#88200]: https://github.com/rust-lang/rust/pull/88200
+[rust#82776]: https://github.com/rust-lang/rust/pull/82776
+[rust#88077]: https://github.com/rust-lang/rust/pull/88077
+[rust#87728]: https://github.com/rust-lang/rust/pull/87728
+[rust#87050]: https://github.com/rust-lang/rust/pull/87050
+[rust#87619]: https://github.com/rust-lang/rust/pull/87619
+[rust#81825]: https://github.com/rust-lang/rust/pull/81825#issuecomment-808406918
+[rust#88019]: https://github.com/rust-lang/rust/pull/88019
+
Version 1.55.0 (2021-09-09)
============================
- [Upgrade to Unicode 10.0.0][42999]
- [Reimplemented `{f32, f64}::{min, max}` in Rust instead of using CMath.][42430]
- [Skip the main thread's manual stack guard on Linux][43072]
-- [Iterator::nth for `ops::{Range, RangeFrom}` is now done in O(1) time][43077]
+- [Iterator::nth for `ops::{Range, RangeFrom}` is now done in *O*(1) time][43077]
- [`#[repr(align(N))]` attribute max number is now 2^31 - 1.][43097] This was
previously 2^15.
- [`{OsStr, Path}::Display` now avoids allocations where possible][42613]
algorithm][s].
* [`std::io::copy` allows `?Sized` arguments][cc].
* The `Windows`, `Chunks`, and `ChunksMut` iterators over slices all
- [override `count`, `nth` and `last` with an O(1)
+ [override `count`, `nth` and `last` with an *O*(1)
implementation][it].
* [`Default` is implemented for arrays up to `[T; 32]`][d].
* [`IntoRawFd` has been added to the Unix-specific prelude,
* The `Default` implementation for `Arc` [no longer requires `Sync +
Send`][arc].
* [The `Iterator` methods `count`, `nth`, and `last` have been
- overridden for slices to have O(1) performance instead of O(n)][si].
+ overridden for slices to have *O*(1) performance instead of *O*(*n*)][si].
* Incorrect handling of paths on Windows has been improved in both the
compiler and the standard library.
* [`AtomicPtr` gained a `Default` implementation][ap].
[package]
name = "rustc-main"
version = "0.0.0"
-edition = '2018'
+edition = "2021"
[dependencies]
rustc_driver = { path = "../rustc_driver" }
[package]
name = "rustc_apfloat"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
bitflags = "1.2.1"
[package]
name = "rustc_arena"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
rustc_data_structures = { path = "../rustc_data_structures" }
[package]
name = "rustc_ast"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_ast_lowering"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
0,
ParenthesizedGenericArgs::Err,
ImplTraitContext::disallowed(),
- None,
));
let args = self.lower_exprs(args);
hir::ExprKind::MethodCall(
let mut generic_args = vec![];
for (idx, arg) in args.into_iter().enumerate() {
if legacy_args_idx.contains(&idx) {
- let parent_def_id = self.current_hir_id_owner.0;
+ let parent_def_id = self.current_hir_id_owner;
let node_id = self.resolver.next_node_id();
// Add a definition for the in-band const def.
impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
fn visit_item(&mut self, item: &'a Item) {
- self.lctx.allocate_hir_id_counter(item.id);
let hir_id = self.lctx.with_hir_id_owner(item.id, |lctx| {
- lctx.without_in_scope_lifetime_defs(|lctx| {
- let hir_item = lctx.lower_item(item);
- lctx.insert_item(hir_item)
- })
+ let node = lctx.without_in_scope_lifetime_defs(|lctx| lctx.lower_item(item));
+ hir::OwnerNode::Item(node)
});
self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
}
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
- self.lctx.allocate_hir_id_counter(item.id);
self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt {
- AssocCtxt::Trait => {
- let hir_item = lctx.lower_trait_item(item);
- lctx.insert_trait_item(hir_item);
- }
- AssocCtxt::Impl => {
- let hir_item = lctx.lower_impl_item(item);
- lctx.insert_impl_item(hir_item);
- }
+ AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
+ AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)),
});
visit::walk_assoc_item(self, item, ctxt);
}
fn visit_foreign_item(&mut self, item: &'a ForeignItem) {
- self.lctx.allocate_hir_id_counter(item.id);
self.lctx.with_hir_id_owner(item.id, |lctx| {
- let hir_item = lctx.lower_foreign_item(item);
- lctx.insert_foreign_item(hir_item);
+ hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))
});
visit::walk_foreign_item(self, item);
// only used when lowering a child item of a trait or impl.
fn with_parent_item_lifetime_defs<T>(
&mut self,
- parent_hir_id: hir::ItemId,
+ parent_hir_id: LocalDefId,
f: impl FnOnce(&mut Self) -> T,
) -> T {
let old_len = self.in_scope_lifetimes.len();
- let parent_generics = match self.owners[parent_hir_id.def_id].unwrap().expect_item().kind {
+ let parent_generics = match self.owners[parent_hir_id].unwrap().expect_item().kind {
hir::ItemKind::Impl(hir::Impl { ref generics, .. })
| hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params,
_ => &[],
}
}
- pub fn lower_item(&mut self, i: &Item) -> hir::Item<'hir> {
+ fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> {
let mut ident = i.ident;
- let mut vis = self.lower_visibility(&i.vis, None);
+ let mut vis = self.lower_visibility(&i.vis);
let hir_id = self.lower_node_id(i.id);
let attrs = self.lower_attrs(hir_id, &i.attrs);
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, &mut vis, &i.kind);
- hir::Item {
+ let item = hir::Item {
def_id: hir_id.expect_owner(),
ident: self.lower_ident(ident),
kind,
vis,
span: self.lower_span(i.span),
- }
+ };
+ self.arena.alloc(item)
}
fn lower_item_kind(
// Essentially a single `use` which imports two names is desugared into
// two imports.
for new_node_id in [id1, id2] {
- // Associate an HirId to both ids even if there is no resolution.
- let new_id = self.allocate_hir_id_counter(new_node_id);
-
- let res = if let Some(res) = resolutions.next() { res } else { continue };
+ let new_id = self.resolver.local_def_id(new_node_id);
+ let res = if let Some(res) = resolutions.next() {
+ res
+ } else {
+ // Associate an HirId to both ids even if there is no resolution.
+ let _old = self
+ .node_id_to_hir_id
+ .insert(new_node_id, hir::HirId::make_owner(new_id));
+ debug_assert!(_old.is_none());
+ continue;
+ };
let ident = *ident;
let mut path = path.clone();
for seg in &mut path.segments {
self.with_hir_id_owner(new_node_id, |this| {
let res = this.lower_res(res);
- let path = this.lower_path_extra(res, &path, ParamMode::Explicit, None);
+ let path = this.lower_path_extra(res, &path, ParamMode::Explicit);
let kind = hir::ItemKind::Use(path, hir::UseKind::Single);
let vis = this.rebuild_vis(&vis);
if let Some(attrs) = attrs {
this.attrs.insert(hir::HirId::make_owner(new_id), attrs);
}
- this.insert_item(hir::Item {
+ let item = hir::Item {
def_id: new_id,
ident: this.lower_ident(ident),
kind,
vis,
span: this.lower_span(span),
- });
+ };
+ hir::OwnerNode::Item(this.arena.alloc(item))
});
}
- let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit, None);
+ let path = self.lower_path_extra(ret_res, &path, ParamMode::Explicit);
hir::ItemKind::Use(path, hir::UseKind::Single)
}
UseTreeKind::Glob => {
// Add all the nested `PathListItem`s to the HIR.
for &(ref use_tree, id) in trees {
- let new_hir_id = self.allocate_hir_id_counter(id);
+ let new_hir_id = self.resolver.local_def_id(id);
let mut prefix = prefix.clone();
this.attrs.insert(hir::HirId::make_owner(new_hir_id), attrs);
}
- this.insert_item(hir::Item {
+ let item = hir::Item {
def_id: new_hir_id,
ident: this.lower_ident(ident),
kind,
vis,
span: this.lower_span(use_tree.span),
- });
+ };
+ hir::OwnerNode::Item(this.arena.alloc(item))
});
}
let res = self.expect_full_res_from_use(id).next().unwrap_or(Res::Err);
let res = self.lower_res(res);
- let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit, None);
+ let path = self.lower_path_extra(res, &prefix, ParamMode::Explicit);
hir::ItemKind::Use(path, hir::UseKind::ListStem)
}
}
respan(self.lower_span(vis.span), vis_kind)
}
- fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> {
+ fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
let hir_id = self.lower_node_id(i.id);
let def_id = hir_id.expect_owner();
self.lower_attrs(hir_id, &i.attrs);
- hir::ForeignItem {
+ let item = hir::ForeignItem {
def_id,
ident: self.lower_ident(i.ident),
kind: match i.kind {
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
},
- vis: self.lower_visibility(&i.vis, None),
+ vis: self.lower_visibility(&i.vis),
span: self.lower_span(i.span),
- }
+ };
+ self.arena.alloc(item)
}
- fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> {
+ fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
hir::ForeignItemRef {
- id: hir::ForeignItemId { def_id: self.allocate_hir_id_counter(i.id) },
+ id: hir::ForeignItemId { def_id: self.resolver.local_def_id(i.id) },
ident: self.lower_ident(i.ident),
span: self.lower_span(i.span),
- vis: self.lower_visibility(&i.vis, Some(i.id)),
}
}
// FIXME(jseyfried): positional field hygiene.
None => Ident::new(sym::integer(index), self.lower_span(f.span)),
},
- vis: self.lower_visibility(&f.vis, None),
+ vis: self.lower_visibility(&f.vis),
ty,
}
}
- fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> {
+ fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
let hir_id = self.lower_node_id(i.id);
let trait_item_def_id = hir_id.expect_owner();
};
self.lower_attrs(hir_id, &i.attrs);
- hir::TraitItem {
+ let item = hir::TraitItem {
def_id: trait_item_def_id,
ident: self.lower_ident(i.ident),
generics,
kind,
span: self.lower_span(i.span),
- }
+ };
+ self.arena.alloc(item)
}
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
self.expr(span, hir::ExprKind::Err, AttrVec::new())
}
- fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
+ fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
let impl_item_def_id = self.resolver.local_def_id(i.id);
let (generics, kind) = match &i.kind {
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
let hir_id = self.lower_node_id(i.id);
self.lower_attrs(hir_id, &i.attrs);
- hir::ImplItem {
+ let item = hir::ImplItem {
def_id: hir_id.expect_owner(),
ident: self.lower_ident(i.ident),
generics,
- vis: self.lower_visibility(&i.vis, None),
+ vis: self.lower_visibility(&i.vis),
defaultness,
kind,
span: self.lower_span(i.span),
- }
+ };
+ self.arena.alloc(item)
}
- fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef<'hir> {
+ fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
// Since `default impl` is not yet implemented, this is always true in impls.
let has_value = true;
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
hir::ImplItemRef {
- id: hir::ImplItemId { def_id: self.allocate_hir_id_counter(i.id) },
+ id: hir::ImplItemId { def_id: self.resolver.local_def_id(i.id) },
ident: self.lower_ident(i.ident),
span: self.lower_span(i.span),
- vis: self.lower_visibility(&i.vis, Some(i.id)),
defaultness,
kind: match &i.kind {
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
/// lowered. This can happen during `lower_impl_item_ref()` where we need to
/// lower a `Visibility` value although we haven't lowered the owning
/// `ImplItem` in question yet.
- fn lower_visibility(
- &mut self,
- v: &Visibility,
- explicit_owner: Option<NodeId>,
- ) -> hir::Visibility<'hir> {
+ fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility<'hir> {
let node = match v.kind {
VisibilityKind::Public => hir::VisibilityKind::Public,
VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
VisibilityKind::Restricted { ref path, id } => {
debug!("lower_visibility: restricted path id = {:?}", id);
- let lowered_id = if let Some(owner) = explicit_owner {
- self.lower_node_id_with_owner(id, owner)
- } else {
- self.lower_node_id(id)
- };
- let res = self.expect_full_res(id);
- let res = self.lower_res(res);
+ let lowered_id = self.lower_node_id(id);
hir::VisibilityKind::Restricted {
- path: self.lower_path_extra(res, path, ParamMode::Explicit, explicit_owner),
+ path: self.lower_path(id, path, ParamMode::Explicit),
hir_id: lowered_id,
}
}
mod pat;
mod path;
-const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
-
rustc_hir::arena_types!(rustc_arena::declare_arena, 'tcx);
struct LoweringContext<'a, 'hir: 'a> {
/// vector.
in_scope_lifetimes: Vec<ParamName>,
- current_hir_id_owner: (LocalDefId, u32),
- item_local_id_counters: NodeMap<u32>,
+ current_hir_id_owner: LocalDefId,
+ item_local_id_counter: hir::ItemLocalId,
node_id_to_hir_id: IndexVec<NodeId, Option<hir::HirId>>,
allow_try_trait: Option<Lrc<[Symbol]>>,
is_in_trait_impl: false,
is_in_dyn_type: false,
anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
- current_hir_id_owner: (CRATE_DEF_ID, 0),
- item_local_id_counters: Default::default(),
+ current_hir_id_owner: CRATE_DEF_ID,
+ item_local_id_counter: hir::ItemLocalId::new(0),
node_id_to_hir_id: IndexVec::new(),
generator_kind: None,
task_context: None,
impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> {
- self.lower_node_id(CRATE_NODE_ID);
- debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == Some(hir::CRATE_HIR_ID));
+ debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID);
visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
- let module = self.arena.alloc(self.lower_mod(&c.items, c.span));
- self.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
- self.owners.ensure_contains_elem(CRATE_DEF_ID, || None);
- self.owners[CRATE_DEF_ID] = Some(hir::OwnerNode::Crate(module));
+ self.with_hir_id_owner(CRATE_NODE_ID, |lctx| {
+ let module = lctx.lower_mod(&c.items, c.span);
+ lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs);
+ hir::OwnerNode::Crate(lctx.arena.alloc(module))
+ });
let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
for (k, v) in self.resolver.take_trait_map().into_iter() {
self.arena.alloc(krate)
}
- fn insert_item(&mut self, item: hir::Item<'hir>) -> hir::ItemId {
- let id = item.item_id();
- let item = self.arena.alloc(item);
- self.owners.ensure_contains_elem(id.def_id, || None);
- self.owners[id.def_id] = Some(hir::OwnerNode::Item(item));
- id
- }
-
- fn insert_foreign_item(&mut self, item: hir::ForeignItem<'hir>) -> hir::ForeignItemId {
- let id = item.foreign_item_id();
- let item = self.arena.alloc(item);
- self.owners.ensure_contains_elem(id.def_id, || None);
- self.owners[id.def_id] = Some(hir::OwnerNode::ForeignItem(item));
- id
- }
-
- fn insert_impl_item(&mut self, item: hir::ImplItem<'hir>) -> hir::ImplItemId {
- let id = item.impl_item_id();
- let item = self.arena.alloc(item);
- self.owners.ensure_contains_elem(id.def_id, || None);
- self.owners[id.def_id] = Some(hir::OwnerNode::ImplItem(item));
- id
- }
-
- fn insert_trait_item(&mut self, item: hir::TraitItem<'hir>) -> hir::TraitItemId {
- let id = item.trait_item_id();
- let item = self.arena.alloc(item);
- self.owners.ensure_contains_elem(id.def_id, || None);
- self.owners[id.def_id] = Some(hir::OwnerNode::TraitItem(item));
- id
- }
-
- fn allocate_hir_id_counter(&mut self, owner: NodeId) -> LocalDefId {
- // Set up the counter if needed.
- self.item_local_id_counters.entry(owner).or_insert(0);
- // Always allocate the first `HirId` for the owner itself.
- let lowered = self.lower_node_id_with_owner(owner, owner);
- debug_assert_eq!(lowered.local_id.as_u32(), 0);
- lowered.owner
- }
-
fn create_stable_hashing_context(&self) -> LoweringHasher<'_> {
LoweringHasher {
source_map: CachingSourceMapView::new(self.sess.source_map()),
}
}
- fn lower_node_id_generic(
+ fn with_hir_id_owner(
&mut self,
- ast_node_id: NodeId,
- alloc_hir_id: impl FnOnce(&mut Self) -> hir::HirId,
- ) -> hir::HirId {
- assert_ne!(ast_node_id, DUMMY_NODE_ID);
-
- let min_size = ast_node_id.as_usize() + 1;
+ owner: NodeId,
+ f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>,
+ ) -> LocalDefId {
+ let def_id = self.resolver.local_def_id(owner);
- if min_size > self.node_id_to_hir_id.len() {
- self.node_id_to_hir_id.resize(min_size, None);
- }
+ // Always allocate the first `HirId` for the owner itself.
+ let _old = self.node_id_to_hir_id.insert(owner, hir::HirId::make_owner(def_id));
+ debug_assert_eq!(_old, None);
- if let Some(existing_hir_id) = self.node_id_to_hir_id[ast_node_id] {
- existing_hir_id
- } else {
- // Generate a new `HirId`.
- let hir_id = alloc_hir_id(self);
- self.node_id_to_hir_id[ast_node_id] = Some(hir_id);
+ let current_owner = std::mem::replace(&mut self.current_hir_id_owner, def_id);
+ let current_local_counter =
+ std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));
- hir_id
- }
- }
+ let item = f(self);
- fn with_hir_id_owner<T>(&mut self, owner: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
- let counter = self
- .item_local_id_counters
- .insert(owner, HIR_ID_COUNTER_LOCKED)
- .unwrap_or_else(|| panic!("no `item_local_id_counters` entry for {:?}", owner));
- let def_id = self.resolver.local_def_id(owner);
- let old_owner = std::mem::replace(&mut self.current_hir_id_owner, (def_id, counter));
- let ret = f(self);
- let (new_def_id, new_counter) =
- std::mem::replace(&mut self.current_hir_id_owner, old_owner);
+ self.current_hir_id_owner = current_owner;
+ self.item_local_id_counter = current_local_counter;
- debug_assert!(def_id == new_def_id);
- debug_assert!(new_counter >= counter);
+ let _old = self.owners.insert(def_id, item);
+ debug_assert!(_old.is_none());
- let prev = self.item_local_id_counters.insert(owner, new_counter).unwrap();
- debug_assert!(prev == HIR_ID_COUNTER_LOCKED);
- ret
+ def_id
}
/// This method allocates a new `HirId` for the given `NodeId` and stores it in
/// `HirIdValidator` later on, which makes sure that all `NodeId`s got mapped
/// properly. Calling the method twice with the same `NodeId` is fine though.
fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId {
- self.lower_node_id_generic(ast_node_id, |this| {
- let &mut (owner, ref mut local_id_counter) = &mut this.current_hir_id_owner;
- let local_id = *local_id_counter;
- *local_id_counter += 1;
- hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) }
- })
- }
-
- fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> hir::HirId {
- self.lower_node_id_generic(ast_node_id, |this| {
- let local_id_counter = this
- .item_local_id_counters
- .get_mut(&owner)
- .expect("called `lower_node_id_with_owner` before `allocate_hir_id_counter`");
- let local_id = *local_id_counter;
-
- // We want to be sure not to modify the counter in the map while it
- // is also on the stack. Otherwise we'll get lost updates when writing
- // back from the stack to the map.
- debug_assert!(local_id != HIR_ID_COUNTER_LOCKED);
-
- *local_id_counter += 1;
- let owner = this.resolver.opt_local_def_id(owner).expect(
- "you forgot to call `create_def` or are lowering node-IDs \
- that do not belong to the current owner",
- );
+ assert_ne!(ast_node_id, DUMMY_NODE_ID);
- hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) }
+ *self.node_id_to_hir_id.get_or_insert_with(ast_node_id, || {
+ // Generate a new `HirId`.
+ let owner = self.current_hir_id_owner;
+ let local_id = self.item_local_id_counter;
+ self.item_local_id_counter.increment_by(1);
+ hir::HirId { owner, local_id }
})
}
fn lower_res(&mut self, res: Res<NodeId>) -> Res {
res.map_id(|id| {
- self.lower_node_id_generic(id, |_| {
+ self.node_id_to_hir_id.get(id).copied().flatten().unwrap_or_else(|| {
panic!("expected `NodeId` to be lowered already for res {:#?}", res);
})
})
/// Mark a span as relative to the current owning item.
fn lower_span(&self, span: Span) -> Span {
if self.sess.opts.debugging_opts.incremental_relative_spans {
- span.with_parent(Some(self.current_hir_id_owner.0))
+ span.with_parent(Some(self.current_hir_id_owner))
} else {
// Do not make spans relative when not using incremental compilation.
span
// wouldn't have been added yet.
let generics = this.lower_generics_mut(
generics,
- ImplTraitContext::Universal(&mut params, this.current_hir_id_owner.0),
+ ImplTraitContext::Universal(&mut params, this.current_hir_id_owner),
);
let res = f(this, &mut params);
(params, (generics, res))
}
AssocTyConstraintKind::Bound { ref bounds } => {
let mut capturable_lifetimes;
- let mut parent_def_id = self.current_hir_id_owner.0;
+ let mut parent_def_id = self.current_hir_id_owner;
// Piggy-back on the `impl Trait` context to figure out the correct behavior.
let (desugar_to_impl_trait, itctx) = match itctx {
// We are in the return position:
// Construct an AnonConst where the expr is the "ty"'s path.
- let parent_def_id = self.current_hir_id_owner.0;
+ let parent_def_id = self.current_hir_id_owner;
let node_id = self.resolver.next_node_id();
// Add a definition for the in-band const def.
// frequently opened issues show.
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
- let opaque_ty_def_id = self.allocate_hir_id_counter(opaque_ty_node_id);
+ let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id);
- let collected_lifetimes = self.with_hir_id_owner(opaque_ty_node_id, move |lctx| {
+ let mut collected_lifetimes = Vec::new();
+ self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
let hir_bounds = lower_bounds(lctx);
- let collected_lifetimes = lifetimes_from_impl_trait_bounds(
+ collected_lifetimes = lifetimes_from_impl_trait_bounds(
opaque_ty_node_id,
&hir_bounds,
capturable_lifetimes,
};
trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id);
- lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span);
-
- collected_lifetimes
+ lctx.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span)
});
let lifetimes =
opaque_ty_item: hir::OpaqueTy<'hir>,
span: Span,
opaque_ty_span: Span,
- ) {
+ ) -> hir::OwnerNode<'hir> {
let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item);
// Generate an `type Foo = impl Trait;` declaration.
trace!("registering opaque type with id {:#?}", opaque_ty_id);
vis: respan(self.lower_span(span.shrink_to_lo()), hir::VisibilityKind::Inherited),
span: self.lower_span(opaque_ty_span),
};
-
- // Insert the item into the global item list. This usually happens
- // automatically for all AST items. But this opaque type item
- // does not actually exist in the AST.
- self.insert_item(opaque_ty_item);
+ hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
}
fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] {
if let Some((_, ibty)) = &mut in_band_ty_params {
this.lower_ty_direct(
¶m.ty,
- ImplTraitContext::Universal(ibty, this.current_hir_id_owner.0),
+ ImplTraitContext::Universal(ibty, this.current_hir_id_owner),
)
} else {
this.lower_ty_direct(¶m.ty, ImplTraitContext::disallowed())
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None);
- let opaque_ty_def_id = self.allocate_hir_id_counter(opaque_ty_node_id);
+ let opaque_ty_def_id = self.resolver.local_def_id(opaque_ty_node_id);
// When we create the opaque type for this async fn, it is going to have
// to capture all the lifetimes involved in the signature (including in the
// grow.
let input_lifetimes_count = self.in_scope_lifetimes.len() + self.lifetimes_to_define.len();
- let lifetime_params = self.with_hir_id_owner(opaque_ty_node_id, |this| {
+ let mut lifetime_params = Vec::new();
+ self.with_hir_id_owner(opaque_ty_node_id, |this| {
// We have to be careful to get elision right here. The
// idea is that we create a lifetime parameter for each
// lifetime in the return type. So, given a return type
//
// Note: this must be done after lowering the output type,
// as the output type may introduce new in-band lifetimes.
- let lifetime_params: Vec<(Span, ParamName)> = this
+ lifetime_params = this
.in_scope_lifetimes
.iter()
.cloned()
};
trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
- this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span);
-
- lifetime_params
+ this.generate_opaque_type(opaque_ty_def_id, opaque_ty_item, span, opaque_ty_span)
});
// As documented above on the variable
num_lifetimes,
parenthesized_generic_args,
itctx.reborrow(),
- None,
)
},
)),
0,
ParenthesizedGenericArgs::Err,
itctx.reborrow(),
- None,
));
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
res: Res,
p: &Path,
param_mode: ParamMode,
- explicit_owner: Option<NodeId>,
) -> &'hir hir::Path<'hir> {
self.arena.alloc(hir::Path {
res,
0,
ParenthesizedGenericArgs::Err,
ImplTraitContext::disallowed(),
- explicit_owner,
)
})),
span: self.lower_span(p.span),
) -> &'hir hir::Path<'hir> {
let res = self.expect_full_res(id);
let res = self.lower_res(res);
- self.lower_path_extra(res, p, param_mode, None)
+ self.lower_path_extra(res, p, param_mode)
}
crate fn lower_path_segment(
expected_lifetimes: usize,
parenthesized_generic_args: ParenthesizedGenericArgs,
itctx: ImplTraitContext<'_, 'hir>,
- explicit_owner: Option<NodeId>,
) -> hir::PathSegment<'hir> {
debug!(
"path_span: {:?}, lower_path_segment(segment: {:?}, expected_lifetimes: {:?})",
}
let res = self.expect_full_res(segment.id);
- let id = if let Some(owner) = explicit_owner {
- self.lower_node_id_with_owner(segment.id, owner)
- } else {
- self.lower_node_id(segment.id)
- };
+ let id = self.lower_node_id(segment.id);
debug!(
"lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
segment.ident, segment.id, id,
[package]
name = "rustc_ast_passes"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
itertools = "0.9"
[package]
name = "rustc_ast_pretty"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_attr"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_borrowck"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
Rvalue::Use(ref operand)
| Rvalue::Repeat(ref operand, _)
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
- | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => {
+ | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
+ | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
self.consume_operand(location, operand)
}
Rvalue::Use(ref operand)
| Rvalue::Repeat(ref operand, _)
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)
- | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => {
+ | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
+ | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
self.consume_operand(location, (operand, span), flow_state)
}
+use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::vec_map::VecMap;
+use rustc_hir::OpaqueTyOrigin;
+use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
use rustc_infer::infer::InferCtxt;
+use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::opaque_types::InferCtxtExt;
pub(crate) fn infer_opaque_types(
&self,
infcx: &InferCtxt<'_, 'tcx>,
- opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
+ opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
span: Span,
) -> VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>> {
opaque_ty_decls
.into_iter()
- .map(|(opaque_type_key, concrete_type)| {
+ .filter_map(|(opaque_type_key, decl)| {
let substs = opaque_type_key.substs;
+ let concrete_type = decl.concrete_ty;
debug!(?concrete_type, ?substs);
let mut subst_regions = vec![self.universal_regions.fr_static];
universal_concrete_type,
span,
);
- (opaque_type_key, remapped_type)
+
+ check_opaque_type_parameter_valid(
+ infcx.tcx,
+ opaque_type_key,
+ OpaqueTypeDecl { concrete_ty: remapped_type, ..decl },
+ )
+ .then_some((opaque_type_key, remapped_type))
})
.collect()
}
})
}
}
+
+fn check_opaque_type_parameter_valid(
+ tcx: TyCtxt<'_>,
+ opaque_type_key: OpaqueTypeKey<'_>,
+ decl: OpaqueTypeDecl<'_>,
+) -> bool {
+ match decl.origin {
+ // No need to check return position impl trait (RPIT)
+ // because for type and const parameters they are correct
+ // by construction: we convert
+ //
+ // fn foo<P0..Pn>() -> impl Trait
+ //
+ // into
+ //
+ // type Foo<P0...Pn>
+ // fn foo<P0..Pn>() -> Foo<P0...Pn>.
+ //
+ // For lifetime parameters we convert
+ //
+ // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
+ //
+ // into
+ //
+ // type foo::<'p0..'pn>::Foo<'q0..'qm>
+ // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
+ //
+ // which would error here on all of the `'static` args.
+ OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true,
+ // Check these
+ OpaqueTyOrigin::TyAlias => {}
+ }
+ let span = decl.definition_span;
+ let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
+ let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
+ for (i, arg) in opaque_type_key.substs.iter().enumerate() {
+ let arg_is_param = match arg.unpack() {
+ GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
+ GenericArgKind::Lifetime(ty::ReStatic) => {
+ tcx.sess
+ .struct_span_err(span, "non-defining opaque type use in defining scope")
+ .span_label(
+ tcx.def_span(opaque_generics.param_at(i, tcx).def_id),
+ "cannot use static lifetime; use a bound lifetime \
+ instead or remove the lifetime parameter from the \
+ opaque type",
+ )
+ .emit();
+ return false;
+ }
+ GenericArgKind::Lifetime(lt) => {
+ matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_))
+ }
+ GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
+ };
+
+ if arg_is_param {
+ seen_params.entry(arg).or_default().push(i);
+ } else {
+ // Prevent `fn foo() -> Foo<u32>` from being defining.
+ let opaque_param = opaque_generics.param_at(i, tcx);
+ tcx.sess
+ .struct_span_err(span, "non-defining opaque type use in defining scope")
+ .span_note(
+ tcx.def_span(opaque_param.def_id),
+ &format!(
+ "used non-generic {} `{}` for generic parameter",
+ opaque_param.kind.descr(),
+ arg,
+ ),
+ )
+ .emit();
+ return false;
+ }
+ }
+
+ for (_, indices) in seen_params {
+ if indices.len() > 1 {
+ let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
+ let spans: Vec<_> = indices
+ .into_iter()
+ .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
+ .collect();
+ tcx.sess
+ .struct_span_err(span, "non-defining opaque type use in defining scope")
+ .span_note(spans, &format!("{} used multiple times", descr))
+ .emit();
+ return false;
+ }
+ }
+ true
+}
category: ConstraintCategory,
) {
self.prove_predicates(
- Some(ty::PredicateKind::Trait(ty::TraitPredicate {
+ Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
- })),
+ }))),
locations,
category,
);
use rustc_hir::lang_items::LangItem;
use rustc_index::vec::{Idx, IndexVec};
use rustc_infer::infer::canonical::QueryRegionConstraints;
+use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
use rustc_infer::infer::outlives::env::RegionBoundPairs;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{
opaque_type_values
.into_iter()
- .filter_map(|(opaque_type_key, decl)| {
- let mut revealed_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
- if revealed_ty.has_infer_types_or_consts() {
+ .filter_map(|(opaque_type_key, mut decl)| {
+ decl.concrete_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
+ if decl.concrete_ty.has_infer_types_or_consts() {
infcx.tcx.sess.delay_span_bug(
body.span,
- &format!("could not resolve {:#?}", revealed_ty.kind()),
+ &format!("could not resolve {:#?}", decl.concrete_ty.kind()),
);
- revealed_ty = infcx.tcx.ty_error();
+ decl.concrete_ty = infcx.tcx.ty_error();
}
- let concrete_is_opaque = if let ty::Opaque(def_id, _) = revealed_ty.kind() {
+ let concrete_is_opaque = if let ty::Opaque(def_id, _) = decl.concrete_ty.kind()
+ {
*def_id == opaque_type_key.def_id
} else {
false
);
None
} else {
- Some((opaque_type_key, revealed_ty))
+ Some((opaque_type_key, decl))
}
})
.collect()
crate struct MirTypeckResults<'tcx> {
crate constraints: MirTypeckRegionConstraints<'tcx>,
crate universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
- crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
+ crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
}
/// A collection of region constraints that must be satisfied for the
}
self.prove_predicate(
- ty::PredicateKind::WellFormed(inferred_ty.into()).to_predicate(self.tcx()),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(inferred_ty.into()))
+ .to_predicate(self.tcx()),
Locations::All(span),
ConstraintCategory::TypeAnnotation,
);
obligations.obligations.push(traits::Obligation::new(
ObligationCause::dummy(),
param_env,
- ty::PredicateKind::WellFormed(revealed_ty.into()).to_predicate(infcx.tcx),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(revealed_ty.into()))
+ .to_predicate(infcx.tcx),
));
obligations.add(
infcx
self.check_call_dest(body, term, &sig, destination, term_location);
self.prove_predicates(
- sig.inputs_and_output.iter().map(|ty| ty::PredicateKind::WellFormed(ty.into())),
+ sig.inputs_and_output
+ .iter()
+ .map(|ty| ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()))),
term_location.to_locations(),
ConstraintCategory::Boring,
);
}
}
- Rvalue::NullaryOp(_, ty) => {
- // Even with unsized locals cannot box an unsized value.
- if self.unsized_feature_enabled() {
- let span = body.source_info(location).span;
- self.ensure_place_sized(ty, span);
- }
-
+ Rvalue::NullaryOp(_, ty) | Rvalue::ShallowInitBox(_, ty) => {
let trait_ref = ty::TraitRef {
def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
substs: tcx.mk_substs_trait(ty, &[]),
| Rvalue::AddressOf(..)
| Rvalue::Len(..)
| Rvalue::Cast(..)
+ | Rvalue::ShallowInitBox(..)
| Rvalue::BinaryOp(..)
| Rvalue::CheckedBinaryOp(..)
| Rvalue::NullaryOp(..)
[package]
name = "rustc_builtin_macros"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
use rustc_ast as ast;
use rustc_ast::mut_visit::MutVisitor;
+use rustc_ast::ptr::P;
use rustc_ast::tokenstream::CanSynthesizeMissingTokens;
use rustc_ast::visit::Visitor;
use rustc_ast::{mut_visit, visit};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_expand::config::StripUnconfigured;
use rustc_expand::configure;
+use rustc_feature::Features;
use rustc_parse::parser::ForceCollect;
use rustc_session::utils::FlattenNonterminals;
-
-use rustc_ast::ptr::P;
+use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::Span;
use smallvec::SmallVec;
annotatable: Annotatable,
) -> Vec<Annotatable> {
check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
- vec![cfg_eval(ecx, annotatable)]
+ vec![cfg_eval(ecx.sess, ecx.ecfg.features, annotatable)]
}
-crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Annotatable {
- CfgEval {
- cfg: &mut StripUnconfigured {
- sess: ecx.sess,
- features: ecx.ecfg.features,
- config_tokens: true,
- },
- }
- .configure_annotatable(annotatable)
- // Since the item itself has already been configured by the `InvocationCollector`,
- // we know that fold result vector will contain exactly one element.
- .unwrap()
+crate fn cfg_eval(
+ sess: &Session,
+ features: Option<&Features>,
+ annotatable: Annotatable,
+) -> Annotatable {
+ CfgEval { cfg: &mut StripUnconfigured { sess, features, config_tokens: true } }
+ .configure_annotatable(annotatable)
+ // Since the item itself has already been configured by the `InvocationCollector`,
+ // we know that fold result vector will contain exactly one element.
+ .unwrap()
}
struct CfgEval<'a, 'b> {
use crate::cfg_eval::cfg_eval;
-use rustc_ast::{self as ast, attr, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
+use rustc_ast as ast;
+use rustc_ast::{attr, token, GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
use rustc_errors::{struct_span_err, Applicability};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
use rustc_feature::AttributeTemplate;
use rustc_parse::validate_attr;
use rustc_session::Session;
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
crate struct Expander;
return ExpandResult::Ready(vec![item]);
}
- let item = cfg_eval(ecx, item);
-
+ let (sess, features) = (ecx.sess, ecx.ecfg.features);
let result =
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
let template =
template,
);
- attr.meta_item_list()
+ let mut resolutions: Vec<_> = attr
+ .meta_item_list()
.unwrap_or_default()
.into_iter()
.filter_map(|nested_meta| match nested_meta {
report_path_args(sess, &meta);
meta.path
})
- .map(|path| (path, item.clone(), None))
- .collect()
+ .map(|path| (path, dummy_annotatable(), None))
+ .collect();
+
+ // Do not configure or clone items unless necessary.
+ match &mut resolutions[..] {
+ [] => {}
+ [(_, first_item, _), others @ ..] => {
+ *first_item = cfg_eval(sess, features, item.clone());
+ for (_, item, _) in others {
+ *item = first_item.clone();
+ }
+ }
+ }
+
+ resolutions
});
match result {
}
}
+// The cheapest `Annotatable` to construct.
+fn dummy_annotatable() -> Annotatable {
+ Annotatable::GenericParam(ast::GenericParam {
+ id: ast::DUMMY_NODE_ID,
+ ident: Ident::invalid(),
+ attrs: Default::default(),
+ bounds: Default::default(),
+ is_placeholder: false,
+ kind: GenericParamKind::Lifetime,
+ })
+}
+
fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
let item_kind = match item {
Annotatable::Item(item) => Some(&item.kind),
p.clear_expected_tokens();
}
- // `Parser::expect` tries to recover using the
- // `Parser::unexpected_try_recover` function. This function is able
- // to recover if the expected token is a closing delimiter.
- //
- // As `,` is not a closing delimiter, it will always return an `Err`
- // variant.
- let mut err = p.expect(&token::Comma).unwrap_err();
-
- match token::TokenKind::Comma.similar_tokens() {
- Some(tks) if tks.contains(&p.token.kind) => {
- // If a similar token is found, then it may be a typo. We
- // consider it as a comma, and continue parsing.
- err.emit();
- p.bump();
+ match p.expect(&token::Comma) {
+ Err(mut err) => {
+ match token::TokenKind::Comma.similar_tokens() {
+ Some(tks) if tks.contains(&p.token.kind) => {
+ // If a similar token is found, then it may be a typo. We
+ // consider it as a comma, and continue parsing.
+ err.emit();
+ p.bump();
+ }
+ // Otherwise stop the parsing and return the error.
+ _ => return Err(err),
+ }
+ }
+ Ok(recovered) => {
+ assert!(recovered);
}
- // Otherwise stop the parsing and return the error.
- _ => return Err(err),
}
}
first = false;
self.ecx.expr_match(self.macsp, head, vec![arm])
};
- let ident = Ident::from_str_and_span("args", self.macsp);
- let args_slice = self.ecx.expr_ident(self.macsp, ident);
+ let args_slice = self.ecx.expr_addr_of(self.macsp, args_match);
// Now create the fmt::Arguments struct with all our locals we created.
let (fn_name, fn_args) = if self.all_pieces_simple {
// nonstandard placeholders, if there are any.
let fmt = self.ecx.expr_vec_slice(self.macsp, self.pieces);
- ("new_v1_formatted", vec![pieces, args_slice, fmt])
+ let path = self.ecx.std_path(&[sym::fmt, sym::UnsafeArg, sym::new]);
+ let unsafe_arg = self.ecx.expr_call_global(self.macsp, path, Vec::new());
+ let unsafe_expr = self.ecx.expr_block(P(ast::Block {
+ stmts: vec![self.ecx.stmt_expr(unsafe_arg)],
+ id: ast::DUMMY_NODE_ID,
+ rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
+ span: self.macsp,
+ tokens: None,
+ could_be_bare_literal: false,
+ }));
+
+ ("new_v1_formatted", vec![pieces, args_slice, fmt, unsafe_expr])
};
let path = self.ecx.std_path(&[sym::fmt, sym::Arguments, Symbol::intern(fn_name)]);
- let arguments = self.ecx.expr_call_global(self.macsp, path, fn_args);
- let body = self.ecx.expr_block(P(ast::Block {
- stmts: vec![self.ecx.stmt_expr(arguments)],
- id: ast::DUMMY_NODE_ID,
- rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
- span: self.macsp,
- tokens: None,
- could_be_bare_literal: false,
- }));
-
- let ident = Ident::from_str_and_span("args", self.macsp);
- let binding_mode = ast::BindingMode::ByRef(ast::Mutability::Not);
- let pat = self.ecx.pat_ident_binding_mode(self.macsp, ident, binding_mode);
- let arm = self.ecx.arm(self.macsp, pat, body);
- self.ecx.expr_match(self.macsp, args_match, vec![arm])
+ self.ecx.expr_call_global(self.macsp, path, fn_args)
}
fn format_arg(
[package]
name = "rustc_codegen_cranelift"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[lib]
crate-type = ["dylib"]
let len = codegen_array_len(fx, place);
lval.write_cvalue(fx, CValue::by_val(len, usize_layout));
}
+ Rvalue::ShallowInitBox(ref operand, content_ty) => {
+ let content_ty = fx.monomorphize(content_ty);
+ let box_layout = fx.layout_of(fx.tcx.mk_box(content_ty));
+ let operand = codegen_operand(fx, operand);
+ let operand = operand.load_scalar(fx);
+ lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
+ }
Rvalue::NullaryOp(NullOp::Box, content_ty) => {
let usize_type = fx.clif_type(fx.tcx.types.usize).unwrap();
let content_ty = fx.monomorphize(content_ty);
#![feature(rustc_private)]
-extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_interface;
extern crate rustc_session;
[package]
name = "rustc_codegen_llvm"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
test = false
let mut function_features = codegen_fn_attrs
.target_features
.iter()
- .map(|f| {
+ .flat_map(|f| {
let feature = &f.as_str();
- format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature))
+ llvm_util::to_llvm_feature(cx.tcx.sess, feature)
+ .into_iter()
+ .map(|f| format!("+{}", f))
+ .collect::<Vec<String>>()
})
.chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x {
InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(),
drop(linker);
save_temp_bitcode(&cgcx, &module, "lto.input");
+ // Fat LTO also suffers from the invalid DWARF issue similar to Thin LTO.
+ // Here we rewrite all `DICompileUnit` pointers if there is only one `DICompileUnit`.
+ // This only works around the problem when codegen-units = 1.
+ // Refer to the comments in the `optimize_thin_module` function for more details.
+ let mut cu1 = ptr::null_mut();
+ let mut cu2 = ptr::null_mut();
+ unsafe { llvm::LLVMRustLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2) };
+ if !cu2.is_null() {
+ let _timer =
+ cgcx.prof.generic_activity_with_arg("LLVM_fat_lto_patch_debuginfo", &*module.name);
+ unsafe { llvm::LLVMRustLTOPatchDICompileUnit(llmod, cu1) };
+ save_temp_bitcode(cgcx, &module, "fat-lto-after-patch");
+ }
+
// Internalize everything below threshold to help strip out more modules and such.
unsafe {
let ptr = symbols_below_threshold.as_ptr();
// an error.
let mut cu1 = ptr::null_mut();
let mut cu2 = ptr::null_mut();
- llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
+ llvm::LLVMRustLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
if !cu2.is_null() {
let msg = "multiple source DICompileUnits found";
return Err(write::llvm_err(&diag_handler, msg));
let _timer = cgcx
.prof
.generic_activity_with_arg("LLVM_thin_lto_patch_debuginfo", thin_module.name());
- llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
+ llvm::LLVMRustLTOPatchDICompileUnit(llmod, cu1);
save_temp_bitcode(cgcx, &module, "thin-lto-after-patch");
}
}
pub(crate) fn should_use_new_llvm_pass_manager(config: &ModuleConfig) -> bool {
- // The new pass manager is disabled by default.
- config.new_llvm_pass_manager.unwrap_or(false)
+ // The new pass manager is enabled by default for LLVM >= 13.
+ // This matches Clang, which also enables it since Clang 13.
+ config.new_llvm_pass_manager.unwrap_or_else(|| llvm_util::get_version() >= (13, 0, 0))
}
pub(crate) unsafe fn optimize_with_new_llvm_pass_manager(
let arg_tys = sig.inputs();
let ret_ty = sig.output();
let name = tcx.item_name(def_id);
- let name_str = &*name.as_str();
let llret_ty = self.layout_of(ret_ty).llvm_type(self);
let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout);
&[args[0].immediate(), y],
)
}
- sym::ctlz_nonzero | sym::cttz_nonzero => {
+ sym::ctlz_nonzero => {
let y = self.const_bool(true);
- let llvm_name = &format!("llvm.{}.i{}", &name_str[..4], width);
+ let llvm_name = &format!("llvm.ctlz.i{}", width);
+ self.call_intrinsic(llvm_name, &[args[0].immediate(), y])
+ }
+ sym::cttz_nonzero => {
+ let y = self.const_bool(true);
+ let llvm_name = &format!("llvm.cttz.i{}", width);
self.call_intrinsic(llvm_name, &[args[0].immediate(), y])
}
sym::ctpop => self.call_intrinsic(
return;
}
- _ if name_str.starts_with("simd_") => {
+ _ if name.as_str().starts_with("simd_") => {
match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
Ok(llval) => llval,
Err(()) => return,
let sig =
tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx));
let arg_tys = sig.inputs();
- let name_str = &*name.as_str();
if name == sym::simd_select_bitmask {
let in_ty = arg_tys[0];
));
}
- if let Some(stripped) = name_str.strip_prefix("simd_shuffle") {
+ if let Some(stripped) = name.as_str().strip_prefix("simd_shuffle") {
// If this intrinsic is the older "simd_shuffleN" form, simply parse the integer.
// If there is no suffix, use the index array length.
let n: u64 = if stripped.is_empty() {
len: usize,
out_len: &mut usize,
) -> *const u8;
- pub fn LLVMRustThinLTOGetDICompileUnit(
- M: &Module,
- CU1: &mut *mut c_void,
- CU2: &mut *mut c_void,
- );
- pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void);
+ pub fn LLVMRustLTOGetDICompileUnit(M: &Module, CU1: &mut *mut c_void, CU2: &mut *mut c_void);
+ pub fn LLVMRustLTOPatchDICompileUnit(M: &Module, CU: *mut c_void);
pub fn LLVMRustLinkerNew(M: &'a Module) -> &'a mut Linker<'a>;
pub fn LLVMRustLinkerAdd(
// Though note that Rust can also be build with an external precompiled version of LLVM
// which might lead to failures if the oldest tested / supported LLVM version
// doesn't yet support the relevant intrinsics
-pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
+pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> Vec<&'a str> {
let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
match (arch, s) {
- ("x86", "pclmulqdq") => "pclmul",
- ("x86", "rdrand") => "rdrnd",
- ("x86", "bmi1") => "bmi",
- ("x86", "cmpxchg16b") => "cx16",
- ("x86", "avx512vaes") => "vaes",
- ("x86", "avx512gfni") => "gfni",
- ("x86", "avx512vpclmulqdq") => "vpclmulqdq",
- ("aarch64", "fp") => "fp-armv8",
- ("aarch64", "fp16") => "fullfp16",
- ("aarch64", "fhm") => "fp16fml",
- ("aarch64", "rcpc2") => "rcpc-immo",
- ("aarch64", "dpb") => "ccpp",
- ("aarch64", "dpb2") => "ccdp",
- ("aarch64", "frintts") => "fptoint",
- ("aarch64", "fcma") => "complxnum",
- (_, s) => s,
+ ("x86", "sse4.2") => {
+ if get_version() >= (14, 0, 0) {
+ vec!["sse4.2", "crc32"]
+ } else {
+ vec!["sse4.2"]
+ }
+ }
+ ("x86", "pclmulqdq") => vec!["pclmul"],
+ ("x86", "rdrand") => vec!["rdrnd"],
+ ("x86", "bmi1") => vec!["bmi"],
+ ("x86", "cmpxchg16b") => vec!["cx16"],
+ ("x86", "avx512vaes") => vec!["vaes"],
+ ("x86", "avx512gfni") => vec!["gfni"],
+ ("x86", "avx512vpclmulqdq") => vec!["vpclmulqdq"],
+ ("aarch64", "fp") => vec!["fp-armv8"],
+ ("aarch64", "fp16") => vec!["fullfp16"],
+ ("aarch64", "fhm") => vec!["fp16fml"],
+ ("aarch64", "rcpc2") => vec!["rcpc-immo"],
+ ("aarch64", "dpb") => vec!["ccpp"],
+ ("aarch64", "dpb2") => vec!["ccdp"],
+ ("aarch64", "frintts") => vec!["fptoint"],
+ ("aarch64", "fcma") => vec!["complxnum"],
+ (_, s) => vec![s],
}
}
},
)
.filter(|feature| {
- let llvm_feature = to_llvm_feature(sess, feature);
- let cstr = CString::new(llvm_feature).unwrap();
- unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) }
+ for llvm_feature in to_llvm_feature(sess, feature) {
+ let cstr = CString::new(llvm_feature).unwrap();
+ if unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) } {
+ return true;
+ }
+ }
+ false
})
.map(|feature| Symbol::intern(feature))
.collect()
let mut rustc_target_features = supported_target_features(sess)
.iter()
.filter_map(|(feature, _gate)| {
- let llvm_feature = to_llvm_feature(sess, *feature);
- // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
- target_features.binary_search_by_key(&llvm_feature, |(f, _d)| *f).ok().map(|index| {
- let (_f, desc) = target_features.remove(index);
- (*feature, desc)
- })
+ for llvm_feature in to_llvm_feature(sess, *feature) {
+ // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
+ match target_features.binary_search_by_key(&llvm_feature, |(f, _d)| (*f)).ok().map(
+ |index| {
+ let (_f, desc) = target_features.remove(index);
+ (*feature, desc)
+ },
+ ) {
+ Some(v) => return Some(v),
+ None => {}
+ }
+ }
+ None
})
.collect::<Vec<_>>();
rustc_target_features.extend_from_slice(&[(
let filter = |s: &str| {
if s.is_empty() {
- return None;
+ return vec![];
}
let feature = if s.starts_with('+') || s.starts_with('-') {
&s[1..]
} else {
- return Some(s.to_string());
+ return vec![s.to_string()];
};
// Rustc-specific feature requests like `+crt-static` or `-crt-static`
// are not passed down to LLVM.
if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
- return None;
+ return vec![];
}
// ... otherwise though we run through `to_llvm_feature` feature when
// passing requests down to LLVM. This means that all in-language
// features also work on the command line instead of having two
// different names when the LLVM name and the Rust name differ.
- Some(format!("{}{}", &s[..1], to_llvm_feature(sess, feature)))
+ to_llvm_feature(sess, feature).iter().map(|f| format!("{}{}", &s[..1], f)).collect()
};
// Features implied by an implicit or explicit `--target`.
- features.extend(sess.target.features.split(',').filter_map(&filter));
+ features.extend(sess.target.features.split(',').flat_map(&filter));
// -Ctarget-features
- features.extend(sess.opts.cg.target_feature.split(',').filter_map(&filter));
+ features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter));
features
}
use rustc_codegen_ssa::traits::*;
use rustc_middle::bug;
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
-use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
use rustc_target::abi::{Int, Pointer, F32, F64};
// in problematically distinct types due to HRTB and subtyping (see #47638).
// ty::Dynamic(..) |
ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str => {
- let mut name = with_no_trimmed_paths(|| layout.ty.to_string());
+ let mut name =
+ with_no_visible_paths(|| with_no_trimmed_paths(|| layout.ty.to_string()));
if let (&ty::Adt(def, _), &Variants::Single { index }) =
(layout.ty.kind(), &layout.variants)
{
[package]
name = "rustc_codegen_ssa"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
test = false
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::{self, SwitchTargets};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
-use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
use rustc_span::source_map::Span;
use rustc_span::{sym, Symbol};
UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false),
};
if do_panic {
- let msg_str = with_no_trimmed_paths(|| {
- if layout.abi.is_uninhabited() {
- // Use this error even for the other intrinsics as it is more precise.
- format!("attempted to instantiate uninhabited type `{}`", ty)
- } else if intrinsic == ZeroValid {
- format!("attempted to zero-initialize type `{}`, which is invalid", ty)
- } else {
- format!("attempted to leave type `{}` uninitialized, which is invalid", ty)
- }
+ let msg_str = with_no_visible_paths(|| {
+ with_no_trimmed_paths(|| {
+ if layout.abi.is_uninhabited() {
+ // Use this error even for the other intrinsics as it is more precise.
+ format!("attempted to instantiate uninhabited type `{}`", ty)
+ } else if intrinsic == ZeroValid {
+ format!("attempted to zero-initialize type `{}`, which is invalid", ty)
+ } else {
+ format!(
+ "attempted to leave type `{}` uninitialized, which is invalid",
+ ty
+ )
+ }
+ })
});
let msg = bx.const_str(Symbol::intern(&msg_str));
let location = self.get_caller_location(bx, source_info).immediate();
self.codegen_argument(&mut bx, op, &mut llargs, &fn_abi.args[i]);
}
- if let Some(tup) = untuple {
+ let num_untupled = untuple.map(|tup| {
self.codegen_arguments_untupled(
&mut bx,
tup,
&mut llargs,
&fn_abi.args[first_args.len()..],
)
- }
+ });
let needs_location =
instance.map_or(false, |i| i.def.requires_caller_location(self.cx.tcx()));
if needs_location {
+ let mir_args = if let Some(num_untupled) = num_untupled {
+ first_args.len() + num_untupled
+ } else {
+ args.len()
+ };
assert_eq!(
fn_abi.args.len(),
- args.len() + 1,
- "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR",
+ mir_args + 1,
+ "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR: {:?} {:?} {:?}",
+ instance,
+ fn_span,
+ fn_abi,
);
let location =
self.get_caller_location(&mut bx, mir::SourceInfo { span: fn_span, ..source_info });
operand: &mir::Operand<'tcx>,
llargs: &mut Vec<Bx::Value>,
args: &[ArgAbi<'tcx, Ty<'tcx>>],
- ) {
+ ) -> usize {
let tuple = self.codegen_operand(bx, operand);
// Handle both by-ref and immediate tuples.
self.codegen_argument(bx, op, llargs, &args[i]);
}
}
+ tuple.layout.fields.count()
}
fn get_caller_location(
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir;
use rustc_middle::ty;
+use rustc_middle::ty::layout::LayoutOf;
use rustc_session::config::DebugInfo;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{BytePos, Span};
+use rustc_target::abi::Abi;
use rustc_target::abi::Size;
use super::operand::{OperandRef, OperandValue};
{
let arg_index = place.local.index() - 1;
if target_is_msvc {
- // Rust compiler decomposes every &str or slice argument into two components:
- // a pointer to the memory address where the data is stored and a usize representing
- // the length of the str (or slice). These components will later be used to reconstruct
- // the original argument inside the body of the function that owns it (see the
- // definition of debug_introduce_local for more details).
- //
- // Since the original argument is declared inside a function rather than being passed
- // in as an argument, it must be marked as a LocalVariable for MSVC debuggers to visualize
- // its data correctly. (See issue #81894 for an in-depth description of the problem).
- match *var_ty.kind() {
- ty::Ref(_, inner_type, _) => match *inner_type.kind() {
- ty::Slice(_) | ty::Str => VariableKind::LocalVariable,
- _ => VariableKind::ArgumentVariable(arg_index + 1),
- },
- _ => VariableKind::ArgumentVariable(arg_index + 1),
+ // ScalarPair parameters are spilled to the stack so they need to
+ // be marked as a `LocalVariable` for MSVC debuggers to visualize
+ // their data correctly. (See #81894 & #88625)
+ let var_ty_layout = self.cx.layout_of(var_ty);
+ if let Abi::ScalarPair(_, _) = var_ty_layout.abi {
+ VariableKind::LocalVariable
+ } else {
+ VariableKind::ArgumentVariable(arg_index + 1)
}
} else {
// FIXME(eddyb) shouldn't `ArgumentVariable` indices be
///////////////////////////////////////////////////////////////////////////
+#[instrument(level = "debug", skip(cx))]
pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx,
instance: Instance<'tcx>,
let mut idx = 0;
let mut llarg_idx = fx.fn_abi.ret.is_indirect() as usize;
+ let mut num_untupled = None;
+
let args = mir
.args_iter()
.enumerate()
let pr_field = place.project_field(bx, i);
bx.store_fn_arg(arg, &mut llarg_idx, pr_field);
}
+ assert_eq!(
+ None,
+ num_untupled.replace(tupled_arg_tys.len()),
+ "Replaced existing num_tupled"
+ );
return LocalRef::Place(place);
}
.collect::<Vec<_>>();
if fx.instance.def.requires_caller_location(bx.tcx()) {
+ let mir_args = if let Some(num_untupled) = num_untupled {
+ // Subtract off the tupled argument that gets 'expanded'
+ args.len() - 1 + num_untupled
+ } else {
+ args.len()
+ };
assert_eq!(
fx.fn_abi.args.len(),
- args.len() + 1,
- "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR",
+ mir_args + 1,
+ "#[track_caller] instance {:?} must have 1 more argument in their ABI than in their MIR",
+ fx.instance
);
let arg = fx.fn_abi.args.last().unwrap();
OperandRef::new_zst(&mut bx, self.cx.layout_of(self.monomorphize(ty)));
(bx, operand)
}
+ mir::Rvalue::ShallowInitBox(ref operand, content_ty) => {
+ let operand = self.codegen_operand(&mut bx, operand);
+ let lloperand = operand.immediate();
+
+ let content_ty = self.monomorphize(content_ty);
+ let box_layout = bx.cx().layout_of(bx.tcx().mk_box(content_ty));
+ let llty_ptr = bx.cx().backend_type(box_layout);
+
+ let val = bx.pointercast(lloperand, llty_ptr);
+ let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout };
+ (bx, operand)
+ }
}
}
mir::Rvalue::AddressOf(..) |
mir::Rvalue::Len(..) |
mir::Rvalue::Cast(..) | // (*)
+ mir::Rvalue::ShallowInitBox(..) | // (*)
mir::Rvalue::BinaryOp(..) |
mir::Rvalue::CheckedBinaryOp(..) |
mir::Rvalue::UnaryOp(..) |
[package]
name = "rustc_const_eval"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
}
+ ShallowInitBox(ref operand, _) => {
+ let src = self.eval_operand(operand, None)?;
+ let v = self.read_immediate(&src)?;
+ self.write_immediate(*v, &dest)?;
+ }
+
Cast(cast_kind, ref operand, cast_ty) => {
let src = self.eval_operand(operand, None)?;
let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty);
///
macro_rules! try_validation {
($e:expr, $where:expr,
- $( $( $p:pat )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? ),+ $(,)?
+ $( $( $p:pat_param )|+ => { $( $what_fmt:expr ),+ } $( expected { $( $expected_fmt:expr ),+ } )? ),+ $(,)?
) => {{
match $e {
Ok(x) => x,
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation),
+ Rvalue::ShallowInitBox(_, _) => {}
Rvalue::UnaryOp(_, ref operand) => {
let ty = operand.ty(self.body, self.tcx);
return;
}
+ if Some(callee) == tcx.lang_items().exchange_malloc_fn() {
+ self.check_op(ops::HeapAllocation);
+ return;
+ }
+
// `async` blocks get lowered to `std::future::from_generator(/* a closure */)`.
let is_async_block = Some(callee) == tcx.lang_items().from_generator_fn();
if is_async_block {
Rvalue::Use(operand)
| Rvalue::Repeat(operand, _)
| Rvalue::UnaryOp(_, operand)
- | Rvalue::Cast(_, operand, _) => in_operand::<Q, _>(cx, in_local, operand),
+ | Rvalue::Cast(_, operand, _)
+ | Rvalue::ShallowInitBox(operand, _) => in_operand::<Q, _>(cx, in_local, operand),
Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
in_operand::<Q, _>(cx, in_local, lhs) || in_operand::<Q, _>(cx, in_local, rhs)
NullOp::AlignOf => {}
},
+ Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable),
+
Rvalue::UnaryOp(op, operand) => {
match op {
// These operations can never fail.
[package]
name = "rustc_data_structures"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
//! Also computes as the resulting DAG if each SCC is replaced with a
//! node in the graph. This uses [Tarjan's algorithm](
//! https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm)
-//! that completes in *O(n)* time.
+//! that completes in *O*(*n*) time.
use crate::fx::FxHashSet;
use crate::graph::vec_graph::VecGraph;
#![feature(extend_one)]
#![feature(hash_raw_entry)]
#![feature(in_band_lifetimes)]
-#![feature(iter_map_while)]
#![feature(maybe_uninit_uninit_array)]
#![feature(min_specialization)]
#![feature(never_type)]
pub use index_map::SortedIndexMultiMap;
/// `SortedMap` is a data structure with similar characteristics as BTreeMap but
-/// slightly different trade-offs: lookup, insertion, and removal are O(log(N))
+/// slightly different trade-offs: lookup, insertion, and removal are *O*(log(*n*))
/// and elements can be iterated in order cheaply.
///
/// `SortedMap` can be faster than a `BTreeMap` for small sizes (<50) since it
#[track_caller]
pub fn borrow(&self) -> MappedReadGuard<'_, T> {
- ReadGuard::map(self.value.borrow(), |opt| match *opt {
- None => panic!("attempted to read from stolen value"),
- Some(ref v) => v,
- })
+ let borrow = self.value.borrow();
+ if let None = &*borrow {
+ panic!("attempted to read from stolen value: {}", std::any::type_name::<T>());
+ }
+ ReadGuard::map(borrow, |opt| opt.as_ref().unwrap())
}
#[track_caller]
[package]
name = "rustc_driver"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
crate-type = ["dylib"]
[package]
name = "rustc_error_codes"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[package]
name = "rustc_errors"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
#[macro_use]
extern crate rustc_macros;
+#[macro_use]
+extern crate tracing;
+
pub use emitter::ColorConfig;
-use tracing::debug;
use Level::*;
use emitter::{is_case_difference, Emitter, EmitterWriter};
let mut error_codes = self
.emitted_diagnostic_codes
.iter()
- .filter_map(|x| {
- match &x {
+ .filter_map(|x| match &x {
DiagnosticId::Error(s)
- if let Ok(Some(_explanation)) = registry.try_find_description(s) =>
+ if registry.try_find_description(s).map_or(false, |o| o.is_some()) =>
{
Some(s.clone())
}
_ => None,
- }
})
.collect::<Vec<_>>();
if !error_codes.is_empty() {
[package]
name = "rustc_expand"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
build = false
[lib]
use rustc_ast::{token, Attribute, Inline, Item};
use rustc_errors::{struct_span_err, DiagnosticBuilder};
use rustc_parse::new_parser_from_file;
+use rustc_parse::validate_attr;
use rustc_session::parse::ParseSess;
use rustc_session::Session;
use rustc_span::symbol::{sym, Ident};
dir_path: &Path,
) -> Option<PathBuf> {
// Extract path string from first `#[path = "path_string"]` attribute.
- let path_string = sess.first_attr_value_str_by_name(attrs, sym::path)?.as_str();
+ let first_path = attrs.iter().find(|at| at.has_name(sym::path))?;
+ let path_string = match first_path.value_str() {
+ Some(s) => s.as_str(),
+ None => {
+ // This check is here mainly to catch attempting to use a macro,
+ // such as #[path = concat!(...)]. This isn't currently supported
+ // because otherwise the InvocationCollector would need to defer
+ // loading a module until the #[path] attribute was expanded, and
+ // it doesn't support that (and would likely add a bit of
+ // complexity). Usually bad forms are checked in AstValidator (via
+ // `check_builtin_attribute`), but by the time that runs the macro
+ // is expanded, and it doesn't give an error.
+ validate_attr::emit_fatal_malformed_builtin_attribute(
+ &sess.parse_sess,
+ first_path,
+ sym::path,
+ );
+ }
+ };
// On windows, the base path might have the form
// `\\?\foo\bar` in which case it does not tolerate
}
// Synthesize a new symbol that includes the minus sign.
- let symbol = Symbol::intern(&s[..1 + lit.symbol.len()]);
+ let symbol = Symbol::intern(&s[..1 + lit.symbol.as_str().len()]);
lit = token::Lit::new(lit.kind, symbol, lit.suffix);
}
[package]
name = "rustc_feature"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
(accepted, const_fn_union, "1.56.0", Some(51909), None),
/// Allows explicit discriminants on non-unit enum variants.
(accepted, arbitrary_enum_discriminant, "1.56.0", Some(60553), None),
+ /// Allows macro attributes to observe output of `#[derive]`.
+ (accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None),
// -------------------------------------------------------------------------
// feature-group-end: accepted features
/// Lessens the requirements for structs to implement `Unsize`.
(active, relaxed_struct_unsize, "1.51.0", Some(81793), None),
- /// Allows macro attributes to observe output of `#[derive]`.
- (active, macro_attributes_in_derive_output, "1.51.0", Some(81119), None),
-
/// Allows associated types in inherent impls.
(incomplete, inherent_associated_types, "1.52.0", Some(8995), None),
/// Allows `let...else` statements.
(active, let_else, "1.56.0", Some(87335), None),
+ /// Allows the `#[must_not_suspend]` attribute.
+ (active, must_not_suspend, "1.57.0", Some(83310), None),
+
+ /// Allows `#[track_caller]` on closures and generators.
+ (active, closure_track_caller, "1.57.0", Some(87417), None),
+
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)),
ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)),
ungated!(must_use, Normal, template!(Word, NameValueStr: "reason")),
+ gated!(
+ must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), must_not_suspend,
+ experimental!(must_not_suspend)
+ ),
// FIXME(#14407)
ungated!(
deprecated, Normal,
[package]
name = "rustc_fs_util"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[package]
name = "rustc_graphviz"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[package]
name = "rustc_hir"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[] pat_field: rustc_hir::PatField<$tcx>,
[] fn_decl: rustc_hir::FnDecl<$tcx>,
[] foreign_item: rustc_hir::ForeignItem<$tcx>,
- [few] foreign_item_ref: rustc_hir::ForeignItemRef<$tcx>,
+ [few] foreign_item_ref: rustc_hir::ForeignItemRef,
[] impl_item: rustc_hir::ImplItem<$tcx>,
- [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
+ [] impl_item_ref: rustc_hir::ImplItemRef,
[] item: rustc_hir::Item<$tcx>,
[few] inline_asm: rustc_hir::InlineAsm<$tcx>,
[few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
/// A module.
Mod(Mod<'hir>),
/// An external module, e.g. `extern { .. }`.
- ForeignMod { abi: Abi, items: &'hir [ForeignItemRef<'hir>] },
+ ForeignMod { abi: Abi, items: &'hir [ForeignItemRef] },
/// Module-level inline assembly (from `global_asm!`).
GlobalAsm(&'hir InlineAsm<'hir>),
/// A type alias, e.g., `type Foo = Bar<u8>`.
pub of_trait: Option<TraitRef<'hir>>,
pub self_ty: &'hir Ty<'hir>,
- pub items: &'hir [ImplItemRef<'hir>],
+ pub items: &'hir [ImplItemRef],
}
impl ItemKind<'_> {
/// passes to find the impl they want without loading the ID (which
/// means fewer edges in the incremental compilation graph).
#[derive(Debug, HashStable_Generic)]
-pub struct ImplItemRef<'hir> {
+pub struct ImplItemRef {
pub id: ImplItemId,
#[stable_hasher(project(name))]
pub ident: Ident,
pub kind: AssocItemKind,
pub span: Span,
- pub vis: Visibility<'hir>,
pub defaultness: Defaultness,
}
/// passes to find the impl they want without loading the ID (which
/// means fewer edges in the incremental compilation graph).
#[derive(Debug, HashStable_Generic)]
-pub struct ForeignItemRef<'hir> {
+pub struct ForeignItemRef {
pub id: ForeignItemId,
#[stable_hasher(project(name))]
pub ident: Ident,
pub span: Span,
- pub vis: Visibility<'hir>,
}
#[derive(Debug)]
fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) {
walk_impl_item(self, ii)
}
- fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef<'v>) {
+ fn visit_foreign_item_ref(&mut self, ii: &'v ForeignItemRef) {
walk_foreign_item_ref(self, ii)
}
- fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef<'v>) {
+ fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) {
walk_impl_item_ref(self, ii)
}
fn visit_trait_ref(&mut self, t: &'v TraitRef<'v>) {
pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>(
visitor: &mut V,
- foreign_item_ref: &'v ForeignItemRef<'v>,
+ foreign_item_ref: &'v ForeignItemRef,
) {
// N.B., deliberately force a compilation error if/when new fields are added.
- let ForeignItemRef { id, ident, span: _, ref vis } = *foreign_item_ref;
+ let ForeignItemRef { id, ident, span: _ } = *foreign_item_ref;
visitor.visit_nested_foreign_item(id);
visitor.visit_ident(ident);
- visitor.visit_vis(vis);
}
-pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef<'v>) {
+pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) {
// N.B., deliberately force a compilation error if/when new fields are added.
- let ImplItemRef { id, ident, ref kind, span: _, ref vis, ref defaultness } = *impl_item_ref;
+ let ImplItemRef { id, ident, ref kind, span: _, ref defaultness } = *impl_item_ref;
visitor.visit_nested_impl_item(id);
visitor.visit_ident(ident);
visitor.visit_associated_item_kind(kind);
- visitor.visit_vis(vis);
visitor.visit_defaultness(defaultness);
}
[package]
name = "rustc_hir_pretty"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_incremental"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_index"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
}
fn ensure_row(&mut self, row: R) -> &mut HybridBitSet<C> {
- // Instantiate any missing rows up to and including row `row` with an
- // empty HybridBitSet.
- self.rows.ensure_contains_elem(row, || None);
-
+ // Instantiate any missing rows up to and including row `row` with an empty HybridBitSet.
// Then replace row `row` with a full HybridBitSet if necessary.
- let num_columns = self.num_columns;
- self.rows[row].get_or_insert_with(|| HybridBitSet::new_empty(num_columns))
+ self.rows.get_or_insert_with(row, || HybridBitSet::new_empty(self.num_columns))
}
/// Sets the cell at `(row, column)` to true. Put another way, insert
}
}
+/// `IndexVec` is often used as a map, so it provides some map-like APIs.
+impl<I: Idx, T> IndexVec<I, Option<T>> {
+ #[inline]
+ pub fn insert(&mut self, index: I, value: T) -> Option<T> {
+ self.ensure_contains_elem(index, || None);
+ self[index].replace(value)
+ }
+
+ #[inline]
+ pub fn get_or_insert_with(&mut self, index: I, value: impl FnOnce() -> T) -> &mut T {
+ self.ensure_contains_elem(index, || None);
+ self[index].get_or_insert_with(value)
+ }
+}
+
impl<I: Idx, T: Clone> IndexVec<I, T> {
#[inline]
pub fn resize(&mut self, new_len: usize, value: T) {
[package]
name = "rustc_infer"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
self.obligations.push(Obligation {
cause: self.cause.clone(),
param_env: self.param_env,
- predicate: ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(sup, sub))
- .to_predicate(self.infcx.tcx),
+ predicate: ty::Binder::dummy(ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
+ sup, sub,
+ )))
+ .to_predicate(self.infcx.tcx),
recursion_depth: 0,
});
}
// is also useful to track which value is the "expected" value in
// terms of error reporting.
+use super::equate::Equate;
use super::glb::Glb;
use super::lub::Lub;
use super::sub::Sub;
use super::unify_key::replace_if_possible;
use super::unify_key::{ConstVarValue, ConstVariableValue};
use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use super::{equate::Equate, type_variable::Diverging};
use super::{InferCtxt, MiscVariable, TypeTrace};
use crate::traits::{Obligation, PredicateObligations};
self.obligations.push(Obligation::new(
self.trace.cause.clone(),
self.param_env,
- ty::PredicateKind::WellFormed(b_ty.into()).to_predicate(self.infcx.tcx),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(b_ty.into()))
+ .to_predicate(self.infcx.tcx),
));
}
self.obligations.push(Obligation::new(
self.trace.cause.clone(),
self.param_env,
- predicate.to_predicate(self.tcx()),
+ ty::Binder::dummy(predicate).to_predicate(self.tcx()),
));
}
}
.inner
.borrow_mut()
.type_variables()
- .new_var(self.for_universe, Diverging::NotDiverging, origin);
+ .new_var(self.for_universe, origin);
let u = self.tcx().mk_ty_var(new_var_id);
// Record that we replaced `vid` with `new_var_id` as part of a generalization
let origin =
*self.infcx.inner.borrow_mut().type_variables().var_origin(vid);
- let new_var_id = self.infcx.inner.borrow_mut().type_variables().new_var(
- self.for_universe,
- Diverging::NotDiverging,
- origin,
- );
+ let new_var_id = self
+ .infcx
+ .inner
+ .borrow_mut()
+ .type_variables()
+ .new_var(self.for_universe, origin);
let u = self.tcx().mk_ty_var(new_var_id);
debug!(
"ConstInferUnifier: replacing original vid={:?} with new={:?}",
//! inference graph arose so that we can explain to the user what gave
//! rise to a particular error.
//!
-//! The basis of the system are the "origin" types. An "origin" is the
+//! The system is based around a set of "origin" types. An "origin" is the
//! reason that a constraint or inference variable arose. There are
//! different "origin" enums for different kinds of constraints/variables
//! (e.g., `TypeOrigin`, `RegionVariableOrigin`). An origin always has
use self::region_constraints::{
RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot,
};
-use self::type_variable::{Diverging, TypeVariableOrigin, TypeVariableOriginKind};
+use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
pub mod at;
pub mod canonical;
pub mod nll_relate;
pub mod opaque_types;
pub mod outlives;
+mod projection;
pub mod region_constraints;
pub mod resolve;
mod sub;
t.fold_with(&mut self.freshener())
}
- /// Returns whether `ty` is a diverging type variable or not.
- /// (If `ty` is not a type variable at all, returns not diverging.)
- ///
- /// No attempt is made to resolve `ty`.
- pub fn type_var_diverges(&'a self, ty: Ty<'_>) -> Diverging {
- match *ty.kind() {
- ty::Infer(ty::TyVar(vid)) => self.inner.borrow_mut().type_variables().var_diverges(vid),
- _ => Diverging::NotDiverging,
- }
- }
-
/// Returns the origin of the type variable identified by `vid`, or `None`
/// if this is not a type variable.
///
})
}
- pub fn next_ty_var_id(&self, diverging: Diverging, origin: TypeVariableOrigin) -> TyVid {
- self.inner.borrow_mut().type_variables().new_var(self.universe(), diverging, origin)
+ /// Number of type variables created so far.
+ pub fn num_ty_vars(&self) -> usize {
+ self.inner.borrow_mut().type_variables().num_vars()
+ }
+
+ pub fn next_ty_var_id(&self, origin: TypeVariableOrigin) -> TyVid {
+ self.inner.borrow_mut().type_variables().new_var(self.universe(), origin)
}
pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
- self.tcx.mk_ty_var(self.next_ty_var_id(Diverging::NotDiverging, origin))
+ self.tcx.mk_ty_var(self.next_ty_var_id(origin))
}
pub fn next_ty_var_in_universe(
origin: TypeVariableOrigin,
universe: ty::UniverseIndex,
) -> Ty<'tcx> {
- let vid = self.inner.borrow_mut().type_variables().new_var(
- universe,
- Diverging::NotDiverging,
- origin,
- );
+ let vid = self.inner.borrow_mut().type_variables().new_var(universe, origin);
self.tcx.mk_ty_var(vid)
}
- pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
- self.tcx.mk_ty_var(self.next_ty_var_id(Diverging::Diverges, origin))
- }
-
pub fn next_const_var(
&self,
ty: Ty<'tcx>,
// as the substitutions for the default, `(T, U)`.
let ty_var_id = self.inner.borrow_mut().type_variables().new_var(
self.universe(),
- Diverging::NotDiverging,
TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeParameterDefinition(
param.name,
//! constituents)
use crate::infer::combine::ConstEquateRelation;
-use crate::infer::type_variable::Diverging;
use crate::infer::InferCtxt;
use crate::infer::{ConstVarValue, ConstVariableValue};
use rustc_data_structures::fx::FxHashMap;
// Replacing with a new variable in the universe `self.universe`,
// it will be unified later with the original type variable in
// the universe `_universe`.
- let new_var_id =
- variables.new_var(self.universe, Diverging::NotDiverging, origin);
+ let new_var_id = variables.new_var(self.universe, origin);
let u = self.tcx().mk_ty_var(new_var_id);
debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
--- /dev/null
+use rustc_middle::traits::ObligationCause;
+use rustc_middle::ty::{self, ToPredicate, Ty};
+
+use crate::traits::{Obligation, PredicateObligation};
+
+use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use super::InferCtxt;
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+ /// Instead of normalizing an associated type projection,
+ /// this function generates an inference variable and registers
+ /// an obligation that this inference variable must be the result
+ /// of the given projection. This allows us to proceed with projections
+ /// while they cannot be resolved yet due to missing information or
+ /// simply due to the lack of access to the trait resolution machinery.
+ pub fn infer_projection(
+ &self,
+ param_env: ty::ParamEnv<'tcx>,
+ projection_ty: ty::ProjectionTy<'tcx>,
+ cause: ObligationCause<'tcx>,
+ recursion_depth: usize,
+ obligations: &mut Vec<PredicateObligation<'tcx>>,
+ ) -> Ty<'tcx> {
+ let def_id = projection_ty.item_def_id;
+ let ty_var = self.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::NormalizeProjectionType,
+ span: self.tcx.def_span(def_id),
+ });
+ let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
+ let obligation = Obligation::with_depth(
+ cause,
+ recursion_depth,
+ param_env,
+ projection.to_predicate(self.tcx),
+ );
+ obligations.push(obligation);
+ ty_var
+ }
+}
self.fields.obligations.push(Obligation::new(
self.fields.trace.cause.clone(),
self.fields.param_env,
- ty::PredicateKind::Subtype(ty::SubtypePredicate {
+ ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
a_is_expected: self.a_is_expected,
a,
b,
- })
+ }))
.to_predicate(self.tcx()),
));
SubstitutionPlaceholder,
AutoDeref,
AdjustmentType,
- DivergingFn,
+
+ /// In type check, when we are type checking a function that
+ /// returns `-> dyn Foo`, we substitute a type variable for the
+ /// return type for diagnostic purposes.
+ DynReturnFn,
LatticeVariable,
}
pub(crate) struct TypeVariableData {
origin: TypeVariableOrigin,
- diverging: Diverging,
-}
-
-#[derive(Copy, Clone, Debug)]
-pub enum Diverging {
- NotDiverging,
- Diverges,
}
#[derive(Copy, Clone, Debug)]
}
impl<'tcx> TypeVariableTable<'_, 'tcx> {
- /// Returns the diverges flag given when `vid` was created.
- ///
- /// Note that this function does not return care whether
- /// `vid` has been unified with something else or not.
- pub fn var_diverges(&self, vid: ty::TyVid) -> Diverging {
- self.storage.values.get(vid.index()).diverging
- }
-
/// Returns the origin that was given when `vid` was created.
///
/// Note that this function does not return care whether
pub fn new_var(
&mut self,
universe: ty::UniverseIndex,
- diverging: Diverging,
origin: TypeVariableOrigin,
) -> ty::TyVid {
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
let sub_key = self.sub_relations().new_key(());
assert_eq!(eq_key.vid, sub_key);
- let index = self.values().push(TypeVariableData { origin, diverging });
+ let index = self.values().push(TypeVariableData { origin });
assert_eq!(eq_key.vid.as_u32(), index as u32);
- debug!(
- "new_var(index={:?}, universe={:?}, diverging={:?}, origin={:?}",
- eq_key.vid, universe, diverging, origin,
- );
+ debug!("new_var(index={:?}, universe={:?}, origin={:?}", eq_key.vid, universe, origin,);
eq_key.vid
}
use crate::infer::InferCtxt;
use crate::traits::Obligation;
+use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, ToPredicate, Ty, WithConstness};
cause,
recursion_depth: 0,
param_env,
- predicate: trait_ref.without_const().to_predicate(infcx.tcx),
+ predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(infcx.tcx),
},
);
}
}
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
+
+ fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships>;
}
pub trait TraitEngineExt<'tcx> {
None
}
})
+ .map(ty::Binder::dummy)
.map(|predicate_kind| predicate_kind.to_predicate(tcx))
.filter(|&predicate| visited.insert(predicate))
.map(|predicate| {
[package]
name = "rustc_interface"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(internal_output_capture)]
+#![feature(thread_spawn_unchecked)]
#![feature(nll)]
#![feature(once_cell)]
#![recursion_limit = "256"]
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
use rustc_mir_build as mir_build;
-use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
+use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
use rustc_passes::{self, hir_stats, layout_test};
use rustc_plugin_impl as plugin;
use rustc_query_impl::{OnDiskCache, Queries as TcxQueries};
use rustc_session::lint;
use rustc_session::output::{filename_for_input, filename_for_metadata};
use rustc_session::search_paths::PathKind;
-use rustc_session::Session;
-use rustc_span::symbol::{Ident, Symbol};
+use rustc_session::{Limit, Session};
+use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::FileName;
use rustc_trait_selection::traits;
use rustc_typeck as typeck;
// Create the config for macro expansion
let features = sess.features_untracked();
- let recursion_limit =
- rustc_middle::middle::limits::get_recursion_limit(&krate.attrs, &sess);
+ let recursion_limit = get_recursion_limit(&krate.attrs, &sess);
let cfg = rustc_expand::expand::ExpansionConfig {
features: Some(&features),
recursion_limit,
codegen
}
+
+fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
+ if let Some(attr) = krate_attrs
+ .iter()
+ .find(|attr| attr.has_name(sym::recursion_limit) && attr.value_str().is_none())
+ {
+ // This is here mainly to check for using a macro, such as
+ // #![recursion_limit = foo!()]. That is not supported since that
+ // would require expanding this while in the middle of expansion,
+ // which needs to know the limit before expanding. Otherwise,
+ // validation would normally be caught in AstValidator (via
+ // `check_builtin_attribute`), but by the time that runs the macro
+ // is expanded, and it doesn't give an error.
+ validate_attr::emit_fatal_malformed_builtin_attribute(
+ &sess.parse_sess,
+ attr,
+ sym::recursion_limit,
+ );
+ }
+ rustc_middle::middle::limits::get_recursion_limit(krate_attrs, sess)
+}
use rustc_metadata::dynamic_lib::DynamicLibrary;
#[cfg(parallel_compiler)]
use rustc_middle::ty::tls;
+use rustc_parse::validate_attr;
#[cfg(parallel_compiler)]
use rustc_query_impl::QueryCtxt;
use rustc_resolve::{self, Resolver};
/// for `'static` bounds.
#[cfg(not(parallel_compiler))]
pub fn scoped_thread<F: FnOnce() -> R + Send, R: Send>(cfg: thread::Builder, f: F) -> R {
- struct Ptr(*mut ());
- unsafe impl Send for Ptr {}
- unsafe impl Sync for Ptr {}
-
- let mut f = Some(f);
- let run = Ptr(&mut f as *mut _ as *mut ());
- let mut result = None;
- let result_ptr = Ptr(&mut result as *mut _ as *mut ());
-
- let thread = cfg.spawn(move || {
- let run = unsafe { (*(run.0 as *mut Option<F>)).take().unwrap() };
- let result = unsafe { &mut *(result_ptr.0 as *mut Option<R>) };
- *result = Some(run());
- });
-
- match thread.unwrap().join() {
- Ok(()) => result.unwrap(),
- Err(p) => panic::resume_unwind(p),
+ // SAFETY: join() is called immediately, so any closure captures are still
+ // alive.
+ match unsafe { cfg.spawn_unchecked(f) }.unwrap().join() {
+ Ok(v) => v,
+ Err(e) => panic::resume_unwind(e),
}
}
}
pub(crate) fn check_attr_crate_type(
- _sess: &Session,
+ sess: &Session,
attrs: &[ast::Attribute],
lint_buffer: &mut LintBuffer,
) {
);
}
}
+ } else {
+ // This is here mainly to check for using a macro, such as
+ // #![crate_type = foo!()]. That is not supported since the
+ // crate type needs to be known very early in compilation long
+ // before expansion. Otherwise, validation would normally be
+ // caught in AstValidator (via `check_builtin_attribute`), but
+ // by the time that runs the macro is expanded, and it doesn't
+ // give an error.
+ validate_attr::emit_fatal_malformed_builtin_attribute(
+ &sess.parse_sess,
+ a,
+ sym::crate_type,
+ );
}
}
}
name = "rustc_lexer"
version = "0.1.0"
license = "MIT OR Apache-2.0"
-edition = "2018"
+edition = "2021"
repository = "https://github.com/rust-lang/rust/"
description = """
[package]
name = "rustc_lint"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
if_chain = "1.0"
///
/// ### Example
///
- /// ```rust
+ /// ```rust,edition2018
/// # #![allow(unused)]
/// [1, 2, 3].into_iter().for_each(|n| { *n; });
/// ```
///
/// ### Example
///
- /// ```rust
+ /// ```rust,edition2018
/// let x = 123;
/// match x {
/// 0...100 => {}
UNUSED_LABELS,
UNUSED_PARENS,
UNUSED_BRACES,
+ MUST_NOT_SUSPEND,
REDUNDANT_SEMICOLONS
);
///
/// ### Example
///
- /// ```rust,no_run
+ /// ```rust,no_run,edition2018
/// panic!("{}");
/// panic!(123);
/// ```
[package]
name = "rustc_lint_defs"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
rustc_ast = { path = "../rustc_ast" }
"imports that are never used"
}
+declare_lint! {
+ /// The `must_not_suspend` lint guards against values that shouldn't be held across suspend points
+ /// (`.await`)
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// #![feature(must_not_suspend)]
+ ///
+ /// #[must_not_suspend]
+ /// struct SyncThing {}
+ ///
+ /// async fn yield_now() {}
+ ///
+ /// pub async fn uhoh() {
+ /// let guard = SyncThing {};
+ /// yield_now().await;
+ /// }
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// The `must_not_suspend` lint detects values that are marked with the `#[must_not_suspend]`
+ /// attribute being held across suspend points. A "suspend" point is usually a `.await` in an async
+ /// function.
+ ///
+ /// This attribute can be used to mark values that are semantically incorrect across suspends
+ /// (like certain types of timers), values that have async alternatives, and values that
+ /// regularly cause problems with the `Send`-ness of async fn's returned futures (like
+ /// `MutexGuard`'s)
+ ///
+ pub MUST_NOT_SUSPEND,
+ Warn,
+ "use of a `#[must_not_suspend]` value across a yield point",
+}
+
declare_lint! {
/// The `unused_extern_crates` lint guards against `extern crate` items
/// that are never used.
///
/// ### Example
///
- /// ```rust
+ /// ```rust,edition2018
/// trait Trait { }
///
/// fn takes_trait_object(_: Box<Trait>) {
CENUM_IMPL_DROP_CAST,
CONST_EVALUATABLE_UNCHECKED,
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
+ MUST_NOT_SUSPEND,
UNINHABITED_STATIC,
FUNCTION_ITEM_REFERENCES,
USELESS_DEPRECATED,
///
/// ### Example
///
- /// ```rust,compile_fail
+ /// ```rust,edition2018,compile_fail
/// #![deny(rust_2021_prefixes_incompatible_syntax)]
///
/// macro_rules! m {
///
/// This lint suggests to add whitespace between the `z` and `"hey"` tokens
/// to keep them separated in Rust 2021.
+ // Allow this lint -- rustdoc doesn't yet support threading edition into this lint's parser.
+ #[allow(rustdoc::invalid_rust_codeblocks)]
pub RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
Allow,
"identifiers that will be parsed as a prefix in Rust 2021",
[package]
name = "rustc_llvm"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[features]
static-libstdcpp = []
#endif
bool NeedThinLTOBufferPasses = UseThinLTOBuffers;
if (!NoPrepopulatePasses) {
- if (OptLevel == OptimizationLevel::O0) {
+ // The pre-link pipelines don't support O0 and require using budilO0DefaultPipeline() instead.
+ // At the same time, the LTO pipelines do support O0 and using them is required.
+ bool IsLTO = OptStage == LLVMRustOptStage::ThinLTO || OptStage == LLVMRustOptStage::FatLTO;
+ if (OptLevel == OptimizationLevel::O0 && !IsLTO) {
#if LLVM_VERSION_GE(12, 0)
for (const auto &C : PipelineStartEPCallbacks)
PB.registerPipelineStartEPCallback(C);
// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
// the comment in `back/lto.rs` for why this exists.
extern "C" void
-LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod,
+LLVMRustLTOGetDICompileUnit(LLVMModuleRef Mod,
DICompileUnit **A,
DICompileUnit **B) {
Module *M = unwrap(Mod);
// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
// the comment in `back/lto.rs` for why this exists.
extern "C" void
-LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
+LLVMRustLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
Module *M = unwrap(Mod);
// If the original source module didn't have a `DICompileUnit` then try to
[package]
name = "rustc_macros"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[lib]
proc-macro = true
[package]
name = "rustc_metadata"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
//! should be used when linking each output type requested in this session. This
//! generally follows this set of rules:
//!
-//! 1. Each library must appear exactly once in the output.
-//! 2. Each rlib contains only one library (it's just an object file)
-//! 3. Each dylib can contain more than one library (due to static linking),
-//! and can also bring in many dynamic dependencies.
+//! 1. Each library must appear exactly once in the output.
+//! 2. Each rlib contains only one library (it's just an object file)
+//! 3. Each dylib can contain more than one library (due to static linking),
+//! and can also bring in many dynamic dependencies.
//!
//! With these constraints in mind, it's generally a very difficult problem to
//! find a solution that's not "all rlibs" or "all dylibs". I have suspicions
//!
//! The current selection algorithm below looks mostly similar to:
//!
-//! 1. If static linking is required, then require all upstream dependencies
-//! to be available as rlibs. If not, generate an error.
-//! 2. If static linking is requested (generating an executable), then
-//! attempt to use all upstream dependencies as rlibs. If any are not
-//! found, bail out and continue to step 3.
-//! 3. Static linking has failed, at least one library must be dynamically
-//! linked. Apply a heuristic by greedily maximizing the number of
-//! dynamically linked libraries.
-//! 4. Each upstream dependency available as a dynamic library is
-//! registered. The dependencies all propagate, adding to a map. It is
-//! possible for a dylib to add a static library as a dependency, but it
-//! is illegal for two dylibs to add the same static library as a
-//! dependency. The same dylib can be added twice. Additionally, it is
-//! illegal to add a static dependency when it was previously found as a
-//! dylib (and vice versa)
-//! 5. After all dynamic dependencies have been traversed, re-traverse the
-//! remaining dependencies and add them statically (if they haven't been
-//! added already).
+//! 1. If static linking is required, then require all upstream dependencies
+//! to be available as rlibs. If not, generate an error.
+//! 2. If static linking is requested (generating an executable), then
+//! attempt to use all upstream dependencies as rlibs. If any are not
+//! found, bail out and continue to step 3.
+//! 3. Static linking has failed, at least one library must be dynamically
+//! linked. Apply a heuristic by greedily maximizing the number of
+//! dynamically linked libraries.
+//! 4. Each upstream dependency available as a dynamic library is
+//! registered. The dependencies all propagate, adding to a map. It is
+//! possible for a dylib to add a static library as a dependency, but it
+//! is illegal for two dylibs to add the same static library as a
+//! dependency. The same dylib can be added twice. Additionally, it is
+//! illegal to add a static dependency when it was previously found as a
+//! dylib (and vice versa)
+//! 5. After all dynamic dependencies have been traversed, re-traverse the
+//! remaining dependencies and add them statically (if they haven't been
+//! added already).
//!
//! While not perfect, this algorithm should help support use-cases such as leaf
//! dependencies being static while the larger tree of inner dependencies are
let all_crates_available_as_rlib = tcx
.crates(())
.iter()
- .cloned()
+ .copied()
.filter_map(|cnum| {
if tcx.dep_kind(cnum).macros_only() {
return None;
// All crates are available in an rlib format, so we're just going to link
// everything in explicitly so long as it's actually required.
- let last_crate = tcx.crates(()).len();
- let mut ret = (1..last_crate + 1)
- .map(|cnum| {
- if tcx.dep_kind(CrateNum::new(cnum)) == CrateDepKind::Explicit {
+ let mut ret = tcx
+ .crates(())
+ .iter()
+ .map(|&cnum| {
+ if tcx.dep_kind(cnum) == CrateDepKind::Explicit {
Linkage::Static
} else {
Linkage::NotLinked
}
}
- fn i686_arg_list_size(&self, item: &hir::ForeignItemRef<'_>) -> usize {
+ fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize {
let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
self.tcx
.type_of(item.id.def_id)
.sum()
}
- fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef<'_>) -> DllImport {
+ fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport {
let calling_convention = if self.tcx.sess.target.arch == "x86" {
match abi {
Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C,
// traversal, but not globally minimal across all crates.
let bfs_queue = &mut VecDeque::new();
- // Preferring shortest paths alone does not guarantee a
- // deterministic result; so sort by crate num to avoid
- // hashtable iteration non-determinism. This only makes
- // things as deterministic as crate-nums assignment is,
- // which is to say, its not deterministic in general. But
- // we believe that libstd is consistently assigned crate
- // num 1, so it should be enough to resolve #46112.
- let mut crates: Vec<CrateNum> = (*tcx.crates(())).to_owned();
- crates.sort();
-
- for &cnum in crates.iter() {
+ for &cnum in tcx.crates(()) {
// Ignore crates without a corresponding local `extern crate` item.
if tcx.missing_extern_crate_item(cnum) {
continue;
bfs_queue.push_back(DefId { krate: cnum, index: CRATE_DEF_INDEX });
}
- // (restrict scope of mutable-borrow of `visible_parent_map`)
- {
- let visible_parent_map = &mut visible_parent_map;
- let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| {
- if child.vis != ty::Visibility::Public {
- return;
- }
+ let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| {
+ if child.vis != ty::Visibility::Public {
+ return;
+ }
- if let Some(child) = child.res.opt_def_id() {
- match visible_parent_map.entry(child) {
- Entry::Occupied(mut entry) => {
- // If `child` is defined in crate `cnum`, ensure
- // that it is mapped to a parent in `cnum`.
- if child.is_local() && entry.get().is_local() {
- entry.insert(parent);
- }
- }
- Entry::Vacant(entry) => {
+ if let Some(child) = child.res.opt_def_id() {
+ match visible_parent_map.entry(child) {
+ Entry::Occupied(mut entry) => {
+ // If `child` is defined in crate `cnum`, ensure
+ // that it is mapped to a parent in `cnum`.
+ if child.is_local() && entry.get().is_local() {
entry.insert(parent);
- bfs_queue.push_back(child);
}
}
+ Entry::Vacant(entry) => {
+ entry.insert(parent);
+ bfs_queue.push_back(child);
+ }
}
- };
+ }
+ };
- while let Some(def) = bfs_queue.pop_front() {
- for child in tcx.item_children(def).iter() {
- add_child(bfs_queue, child, def);
- }
+ while let Some(def) = bfs_queue.pop_front() {
+ for child in tcx.item_children(def).iter() {
+ add_child(bfs_queue, child, def);
}
}
fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> {
empty_proc_macro!(self);
- let crates = self.tcx.crates(());
- let mut deps = crates
+ let deps = self
+ .tcx
+ .crates(())
.iter()
.map(|&cnum| {
let dep = CrateDep {
})
.collect::<Vec<_>>();
- deps.sort_by_key(|&(cnum, _)| cnum);
-
{
// Sanity-check the crate numbers
let mut expected_cnum = 1;
[package]
name = "rustc_middle"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
self.visit_nested_trait_item(id);
}
- fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef<'hir>) {
+ fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) {
// Do not visit the duplicate information in ImplItemRef. We want to
// map the actual nodes, not the duplicate ones in the *Ref.
- let ImplItemRef { id, ident: _, kind: _, span: _, vis: _, defaultness: _ } = *ii;
+ let ImplItemRef { id, ident: _, kind: _, span: _, defaultness: _ } = *ii;
self.visit_nested_impl_item(id);
}
- fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef<'hir>) {
+ fn visit_foreign_item_ref(&mut self, fi: &'hir ForeignItemRef) {
// Do not visit the duplicate information in ForeignItemRef. We want to
// map the actual nodes, not the duplicate ones in the *Ref.
- let ForeignItemRef { id, ident: _, span: _, vis: _ } = *fi;
+ let ForeignItemRef { id, ident: _, span: _ } = *fi;
self.visit_nested_foreign_item(id);
}
/// An iterator that walks up the ancestor tree of a given `HirId`.
/// Constructed using `tcx.hir().parent_iter(hir_id)`.
-pub struct ParentHirIterator<'map, 'hir> {
+pub struct ParentHirIterator<'hir> {
current_id: HirId,
- map: &'map Map<'hir>,
+ map: Map<'hir>,
}
-impl<'hir> Iterator for ParentHirIterator<'_, 'hir> {
+impl<'hir> Iterator for ParentHirIterator<'hir> {
type Item = (HirId, Node<'hir>);
fn next(&mut self) -> Option<Self::Item> {
/// An iterator that walks up the ancestor tree of a given `HirId`.
/// Constructed using `tcx.hir().parent_owner_iter(hir_id)`.
-pub struct ParentOwnerIterator<'map, 'hir> {
+pub struct ParentOwnerIterator<'hir> {
current_id: HirId,
- map: &'map Map<'hir>,
+ map: Map<'hir>,
}
-impl<'hir> Iterator for ParentOwnerIterator<'_, 'hir> {
+impl<'hir> Iterator for ParentOwnerIterator<'hir> {
type Item = (HirId, OwnerNode<'hir>);
fn next(&mut self) -> Option<Self::Item> {
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
- pub fn parent_iter(&self, current_id: HirId) -> ParentHirIterator<'_, 'hir> {
+ pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> {
ParentHirIterator { current_id, map: self }
}
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
- pub fn parent_owner_iter(&self, current_id: HirId) -> ParentOwnerIterator<'_, 'hir> {
+ pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> {
ParentOwnerIterator { current_id, map: self }
}
use crate::ich;
use crate::middle::cstore::CrateStore;
-use crate::ty::{fast_reject, TyCtxt};
+use crate::ty::TyCtxt;
use rustc_ast as ast;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::Lrc;
use rustc_hir as hir;
use rustc_span::symbol::Symbol;
use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData};
-use smallvec::SmallVec;
-use std::cmp::Ord;
-
fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty());
ich::IGNORED_ATTRIBUTES.iter().copied().collect()
}
impl rustc_session::HashStableContext for StableHashingContext<'a> {}
-
-pub fn hash_stable_trait_impls<'a>(
- hcx: &mut StableHashingContext<'a>,
- hasher: &mut StableHasher,
- blanket_impls: &[DefId],
- non_blanket_impls: &FxHashMap<fast_reject::SimplifiedType, Vec<DefId>>,
-) {
- {
- let mut blanket_impls: SmallVec<[_; 8]> =
- blanket_impls.iter().map(|&def_id| hcx.def_path_hash(def_id)).collect();
-
- if blanket_impls.len() > 1 {
- blanket_impls.sort_unstable();
- }
-
- blanket_impls.hash_stable(hcx, hasher);
- }
-
- {
- let mut keys: SmallVec<[_; 8]> =
- non_blanket_impls.keys().map(|k| (k, k.map_def(|d| hcx.def_path_hash(d)))).collect();
- keys.sort_unstable_by(|&(_, ref k1), &(_, ref k2)| k1.cmp(k2));
- keys.len().hash_stable(hcx, hasher);
- for (key, ref stable_key) in keys {
- stable_key.hash_stable(hcx, hasher);
- let mut impls: SmallVec<[_; 8]> =
- non_blanket_impls[key].iter().map(|&impl_id| hcx.def_path_hash(impl_id)).collect();
-
- if impls.len() > 1 {
- impls.sort_unstable();
- }
-
- impls.hash_stable(hcx, hasher);
- }
- }
-}
ty::ReFree(ref free_region) => {
free_region.hash_stable(hcx, hasher);
}
- ty::ReVar(..) | ty::RePlaceholder(..) => {
+ ty::RePlaceholder(p) => {
+ p.hash_stable(hcx, hasher);
+ }
+ ty::ReVar(..) => {
bug!("StableHasher: unexpected region {:?}", *self)
}
}
//! ICH - Incremental Compilation Hash
-pub use self::hcx::{
- hash_stable_trait_impls, NodeIdHashingMode, StableHashingContext, StableHashingContextProvider,
-};
+pub use self::hcx::{NodeIdHashingMode, StableHashingContext, StableHashingContextProvider};
use rustc_span::symbol::{sym, Symbol};
mod hcx;
/// ```
///
/// With the HIR tree (calls numbered for expository purposes)
- /// ```
+ ///
+ /// ```text
/// Call#0(foo, [Call#1(f), Yield(y), Call#2(bar, Call#3(g))])
/// ```
///
/// that `Foo` has a destructor. These rvalues can be optimized
/// away after type-checking and before lowering.
Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
+
+ /// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
+ ///
+ /// This is different a normal transmute because dataflow analysis will treat the box
+ /// as initialized but its content as uninitialized.
+ ShallowInitBox(Operand<'tcx>, Ty<'tcx>),
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
}),
}
}
+
+ ShallowInitBox(ref place, ref ty) => {
+ write!(fmt, "ShallowInitBox({:?}, {:?})", place, ty)
+ }
}
}
}
tcx.mk_generator(did, substs, movability)
}
},
+ Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty),
}
}
/// whether its only shallowly initialized (`Rvalue::Box`).
pub fn initialization_state(&self) -> RvalueInitializationState {
match *self {
- Rvalue::NullaryOp(NullOp::Box, _) => RvalueInitializationState::Shallow,
+ Rvalue::NullaryOp(NullOp::Box, _) | Rvalue::ShallowInitBox(_, _) => {
+ RvalueInitializationState::Shallow
+ }
_ => RvalueInitializationState::Deep,
}
}
});
Aggregate(kind, fields.fold_with(folder))
}
+ ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder), ty.fold_with(folder)),
}
}
}
fields.visit_with(visitor)
}
+ ShallowInitBox(ref op, ty) => {
+ op.visit_with(visitor)?;
+ ty.visit_with(visitor)
+ }
}
}
}
ty::InstanceDef::VtableShim(_def_id) |
ty::InstanceDef::ReifyShim(_def_id) |
ty::InstanceDef::Virtual(_def_id, _) |
- ty::InstanceDef::ClosureOnceShim { call_once: _def_id } |
+ ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } |
ty::InstanceDef::DropGlue(_def_id, None) => {}
ty::InstanceDef::FnPtrShim(_def_id, ty) |
self.visit_operand(operand, location);
}
}
+
+ Rvalue::ShallowInitBox(operand, ty) => {
+ self.visit_operand(operand, location);
+ self.visit_ty(ty, TyContext::Location(location));
+ }
}
}
desc { "computing the inferred outlives predicates for items in this crate" }
}
- /// Maps from an impl/trait `DefId to a list of the `DefId`s of its items.
+ /// Maps from an impl/trait `DefId` to a list of the `DefId`s of its items.
query associated_item_def_ids(key: DefId) -> &'tcx [DefId] {
desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) }
}
-use crate::ich::{self, StableHashingContext};
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::fold::TypeFoldable;
use crate::ty::{self, TyCtxt};
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorReported;
use rustc_hir::def_id::{DefId, DefIdMap};
use rustc_span::symbol::Ident;
/// Children of a given impl, grouped into blanket/non-blanket varieties as is
/// done in `TraitDef`.
-#[derive(Default, TyEncodable, TyDecodable, Debug)]
+#[derive(Default, TyEncodable, TyDecodable, Debug, HashStable)]
pub struct Children {
// Impls of a trait (or specializations of a given impl). To allow for
// quicker lookup, the impls are indexed by a simplified version of their
// `Self` type: impls with a simplifiable `Self` are stored in
- // `nonblanket_impls` keyed by it, while all other impls are stored in
+ // `non_blanket_impls` keyed by it, while all other impls are stored in
// `blanket_impls`.
//
// A similar division is used within `TraitDef`, but the lists there collect
// together *all* the impls for a trait, and are populated prior to building
// the specialization graph.
/// Impls of the trait.
- pub nonblanket_impls: FxHashMap<SimplifiedType, Vec<DefId>>,
+ pub non_blanket_impls: FxIndexMap<SimplifiedType, Vec<DefId>>,
/// Blanket impls associated with the trait.
pub blanket_impls: Vec<DefId>,
})
}
}
-
-impl<'a> HashStable<StableHashingContext<'a>> for Children {
- fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
- let Children { ref nonblanket_impls, ref blanket_impls } = *self;
-
- ich::hash_stable_trait_impls(hcx, hasher, blanket_impls, nonblanket_impls);
- }
-}
/// `<[FnMut closure] as FnOnce>::call_once`.
///
/// The `DefId` is the ID of the `call_once` method in `FnOnce`.
- ClosureOnceShim { call_once: DefId },
+ ClosureOnceShim { call_once: DefId, track_caller: bool },
/// `core::ptr::drop_in_place::<T>`.
///
| InstanceDef::FnPtrShim(def_id, _)
| InstanceDef::Virtual(def_id, _)
| InstanceDef::Intrinsic(def_id)
- | InstanceDef::ClosureOnceShim { call_once: def_id }
+ | InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
| InstanceDef::DropGlue(def_id, _)
| InstanceDef::CloneShim(def_id, _) => def_id,
}
| InstanceDef::FnPtrShim(def_id, _)
| InstanceDef::Virtual(def_id, _)
| InstanceDef::Intrinsic(def_id)
- | InstanceDef::ClosureOnceShim { call_once: def_id }
+ | InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ }
| InstanceDef::DropGlue(def_id, _)
| InstanceDef::CloneShim(def_id, _) => ty::WithOptConstParam::unknown(def_id),
}
| InstanceDef::Virtual(def_id, _) => {
tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
}
+ InstanceDef::ClosureOnceShim { call_once: _, track_caller } => track_caller,
_ => false,
}
}
substs: SubstsRef<'tcx>,
) -> Option<Instance<'tcx>> {
debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
+ // Use either `resolve_closure` or `resolve_for_vtable`
+ assert!(!tcx.is_closure(def_id), "Called `resolve_for_fn_ptr` on closure: {:?}", def_id);
Instance::resolve(tcx, param_env, def_id, substs).ok().flatten().map(|mut resolved| {
match resolved.def {
InstanceDef::Item(def) if resolved.def.requires_caller_location(tcx) => {
})
)
{
- debug!(
- " => vtable fn pointer created for function with #[track_caller]"
- );
- resolved.def = InstanceDef::ReifyShim(def.did);
+ if tcx.is_closure(def.did) {
+ debug!(" => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}",
+ def.did, def_id, substs);
+
+ // Create a shim for the `FnOnce/FnMut/Fn` method we are calling
+ // - unlike functions, invoking a closure always goes through a
+ // trait.
+ resolved = Instance { def: InstanceDef::ReifyShim(def_id), substs };
+ } else {
+ debug!(
+ " => vtable fn pointer created for function with #[track_caller]: {:?}", def.did
+ );
+ resolved.def = InstanceDef::ReifyShim(def.did);
+ }
}
}
InstanceDef::Virtual(def_id, _) => {
.find(|it| it.kind == ty::AssocKind::Fn)
.unwrap()
.def_id;
- let def = ty::InstanceDef::ClosureOnceShim { call_once };
+ let track_caller =
+ tcx.codegen_fn_attrs(closure_did).flags.contains(CodegenFnAttrFlags::TRACK_CALLER);
+ let def = ty::InstanceDef::ClosureOnceShim { call_once, track_caller };
let self_ty = tcx.mk_closure(closure_did, substs);
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
}
-impl<'tcx> ToPolyTraitRef<'tcx> for TraitRef<'tcx> {
- fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> {
- ty::Binder::dummy(*self)
- }
-}
-
impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> {
self.map_bound_ref(|trait_pred| trait_pred.trait_ref)
}
}
-impl ToPredicate<'tcx> for PredicateKind<'tcx> {
- #[inline(always)]
- fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- tcx.mk_predicate(Binder::dummy(self))
- }
-}
-
-impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
- fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
- PredicateKind::Trait(ty::TraitPredicate {
- trait_ref: self.value,
- constness: self.constness,
- })
- .to_predicate(tcx)
- }
-}
-
impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> {
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
self.value
fmt::Display::fmt(&self.name, fmt)
}
}
+
+#[derive(Debug, Default, Copy, Clone)]
+pub struct FoundRelationships {
+ /// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo`
+ /// obligation, where:
+ ///
+ /// * `Foo` is not `Sized`
+ /// * `(): Foo` may be satisfied
+ pub self_in_trait: bool,
+ /// This is true if we identified that this Ty (`?T`) is found in a `<_ as
+ /// _>::AssocType = ?T`
+ pub output: bool,
+}
static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = const { Cell::new(false) };
static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
static NO_QUERIES: Cell<bool> = const { Cell::new(false) };
+ static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
}
/// Avoids running any queries during any prints that occur
})
}
+/// Prevent selection of visible paths. `Display` impl of DefId will prefer visible (public) reexports of types as paths.
+pub fn with_no_visible_paths<F: FnOnce() -> R, R>(f: F) -> R {
+ NO_VISIBLE_PATH.with(|flag| {
+ let old = flag.replace(true);
+ let result = f();
+ flag.set(old);
+ result
+ })
+}
+
/// The "region highlights" are used to control region printing during
/// specific error messages. When a "region highlight" is enabled, it
/// gives an alternate way to print specific regions. For now, we
/// from at least one local module, and returns `true`. If the crate defining `def_id` is
/// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
fn try_print_visible_def_path(self, def_id: DefId) -> Result<(Self, bool), Self::Error> {
+ if NO_VISIBLE_PATH.with(|flag| flag.get()) {
+ return Ok((self, false));
+ }
+
let mut callers = Vec::new();
self.try_print_visible_def_path_recur(def_id, &mut callers)
}
get_slice_bytes(&tcx, a_val) == get_slice_bytes(&tcx, b_val)
}
+ (ConstValue::ByRef { alloc: alloc_a, .. }, ConstValue::ByRef { alloc: alloc_b, .. })
+ if a.ty.is_ref() || b.ty.is_ref() =>
+ {
+ if a.ty.is_ref() && b.ty.is_ref() {
+ alloc_a == alloc_b
+ } else {
+ false
+ }
+ }
(ConstValue::ByRef { .. }, ConstValue::ByRef { .. }) => {
let a_destructured = tcx.destructure_const(relation.param_env().and(a));
let b_destructured = tcx.destructure_const(relation.param_env().and(b));
Some(ty::InstanceDef::FnPtrShim(def_id, tcx.lift(ty)?))
}
ty::InstanceDef::Virtual(def_id, n) => Some(ty::InstanceDef::Virtual(def_id, n)),
- ty::InstanceDef::ClosureOnceShim { call_once } => {
- Some(ty::InstanceDef::ClosureOnceShim { call_once })
+ ty::InstanceDef::ClosureOnceShim { call_once, track_caller } => {
+ Some(ty::InstanceDef::ClosureOnceShim { call_once, track_caller })
}
ty::InstanceDef::DropGlue(def_id, ty) => {
Some(ty::InstanceDef::DropGlue(def_id, tcx.lift(ty)?))
Intrinsic(did) => Intrinsic(did.fold_with(folder)),
FnPtrShim(did, ty) => FnPtrShim(did.fold_with(folder), ty.fold_with(folder)),
Virtual(did, i) => Virtual(did.fold_with(folder), i),
- ClosureOnceShim { call_once } => {
- ClosureOnceShim { call_once: call_once.fold_with(folder) }
+ ClosureOnceShim { call_once, track_caller } => {
+ ClosureOnceShim { call_once: call_once.fold_with(folder), track_caller }
}
DropGlue(did, ty) => DropGlue(did.fold_with(folder), ty.fold_with(folder)),
CloneShim(did, ty) => CloneShim(did.fold_with(folder), ty.fold_with(folder)),
did.visit_with(visitor)?;
ty.visit_with(visitor)
}
- ClosureOnceShim { call_once } => call_once.visit_with(visitor),
+ ClosureOnceShim { call_once, track_caller: _ } => call_once.visit_with(visitor),
}
}
}
/// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
/// are the parameters defined on trait.
- pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> TraitRef<'tcx> {
- TraitRef { def_id, substs: InternalSubsts::identity_for_item(tcx, def_id) }
+ pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> Binder<'tcx, TraitRef<'tcx>> {
+ ty::Binder::dummy(TraitRef {
+ def_id,
+ substs: InternalSubsts::identity_for_item(tcx, def_id),
+ })
}
#[inline]
matches!(self.kind(), Infer(TyVar(_)))
}
+ #[inline]
+ pub fn ty_vid(&self) -> Option<ty::TyVid> {
+ match self.kind() {
+ &Infer(TyVar(vid)) => Some(vid),
+ _ => None,
+ }
+ }
+
#[inline]
pub fn is_ty_infer(&self) -> bool {
matches!(self.kind(), Infer(_))
-use crate::ich::{self, StableHashingContext};
use crate::traits::specialization_graph;
use crate::ty::fast_reject;
use crate::ty::fold::TypeFoldable;
use rustc_hir::def_id::DefId;
use rustc_hir::definitions::DefPathHash;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorReported;
use rustc_macros::HashStable;
AlwaysApplicable,
}
-#[derive(Default, Debug)]
+#[derive(Default, Debug, HashStable)]
pub struct TraitImpls {
blanket_impls: Vec<DefId>,
/// Impls indexed by their simplified self type, for fast lookup.
- non_blanket_impls: FxHashMap<fast_reject::SimplifiedType, Vec<DefId>>,
+ non_blanket_impls: FxIndexMap<fast_reject::SimplifiedType, Vec<DefId>>,
}
impl TraitImpls {
impls
}
-
-impl<'a> HashStable<StableHashingContext<'a>> for TraitImpls {
- fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
- let TraitImpls { ref blanket_impls, ref non_blanket_impls } = *self;
-
- ich::hash_stable_trait_impls(hcx, hasher, blanket_impls, non_blanket_impls);
- }
-}
[package]
name = "rustc_mir_build"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
use crate::build::expr::as_place::PlaceBase;
use crate::build::expr::category::{Category, RvalueFunc};
use crate::build::{BlockAnd, BlockAndExtension, Builder};
+use rustc_hir::lang_items::LangItem;
use rustc_middle::middle::region;
use rustc_middle::mir::AssertKind;
use rustc_middle::mir::Place;
}
ExprKind::Box { value } => {
let value = &this.thir[value];
+ let tcx = this.tcx;
+
+ // `exchange_malloc` is unsafe but box is safe, so need a new scope.
+ let synth_scope = this.new_source_scope(
+ expr_span,
+ LintLevel::Inherited,
+ Some(Safety::BuiltinUnsafe),
+ );
+ let synth_info = SourceInfo { span: expr_span, scope: synth_scope };
+
+ let size = this.temp(tcx.types.usize, expr_span);
+ this.cfg.push_assign(
+ block,
+ synth_info,
+ size,
+ Rvalue::NullaryOp(NullOp::SizeOf, value.ty),
+ );
+
+ let align = this.temp(tcx.types.usize, expr_span);
+ this.cfg.push_assign(
+ block,
+ synth_info,
+ align,
+ Rvalue::NullaryOp(NullOp::AlignOf, value.ty),
+ );
+
+ // malloc some memory of suitable size and align:
+ let exchange_malloc = Operand::function_handle(
+ tcx,
+ tcx.require_lang_item(LangItem::ExchangeMalloc, Some(expr_span)),
+ ty::List::empty(),
+ expr_span,
+ );
+ let storage = this.temp(tcx.mk_mut_ptr(tcx.types.u8), expr_span);
+ let success = this.cfg.start_new_block();
+ this.cfg.terminate(
+ block,
+ synth_info,
+ TerminatorKind::Call {
+ func: exchange_malloc,
+ args: vec![Operand::Move(size), Operand::Move(align)],
+ destination: Some((Place::from(storage), success)),
+ cleanup: None,
+ from_hir_call: false,
+ fn_span: expr_span,
+ },
+ );
+ this.diverge_from(block);
+ block = success;
+
// The `Box<T>` temporary created here is not a part of the HIR,
// and therefore is not considered during generator auto-trait
// determination. See the comment about `box` at `yield_in_scope`.
this.schedule_drop_storage_and_value(expr_span, scope, result);
}
- // malloc some memory of suitable type (thus far, uninitialized):
- let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
+ // Transmute `*mut u8` to the box (thus far, uninitialized):
+ let box_ = Rvalue::ShallowInitBox(Operand::Move(Place::from(storage)), value.ty);
this.cfg.push_assign(block, source_info, Place::from(result), box_);
// initialize the box contents:
let body_owner_kind = tcx.hir().body_owner_kind(id);
let typeck_results = tcx.typeck_opt_const_arg(def);
- // Ensure unsafeck is ran before we steal the THIR.
+ // Ensure unsafeck and abstract const building is ran before we steal the THIR.
+ // We can't use `ensure()` for `thir_abstract_const` as it doesn't compute the query
+ // if inputs are green. This can cause ICEs when calling `thir_abstract_const` after
+ // THIR has been stolen if we haven't computed this query yet.
match def {
ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => {
tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did));
- tcx.ensure().thir_abstract_const_of_const_arg((did, const_param_did));
+ drop(tcx.thir_abstract_const_of_const_arg((did, const_param_did)));
}
ty::WithOptConstParam { did, const_param_did: None } => {
tcx.ensure().thir_check_unsafety(did);
- tcx.ensure().thir_abstract_const(did);
+ drop(tcx.thir_abstract_const(did));
}
}
&& !self.saw_const_match_lint.get()
{
self.saw_const_match_lint.set(true);
- let msg = format!(
- "to use a constant of type `{}` in a pattern, \
- `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
- cv.ty, cv.ty,
- );
tcx.struct_span_lint_hir(
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
id,
span,
- |lint| lint.build(&msg).emit(),
+ |lint| {
+ let msg = format!(
+ "to use a constant of type `{}` in a pattern, \
+ `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
+ cv.ty, cv.ty,
+ );
+ lint.build(&msg).emit()
+ },
);
}
// Since we are behind a reference, we can just bubble the error up so we get a
[package]
name = "rustc_mir_dataflow"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
}
mir::Rvalue::Cast(..)
+ | mir::Rvalue::ShallowInitBox(..)
| mir::Rvalue::Use(..)
| mir::Rvalue::ThreadLocalRef(..)
| mir::Rvalue::Repeat(..)
Rvalue::Use(ref operand)
| Rvalue::Repeat(ref operand, _)
| Rvalue::Cast(_, ref operand, _)
+ | Rvalue::ShallowInitBox(ref operand, _)
| Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand),
Rvalue::BinaryOp(ref _binop, box (ref lhs, ref rhs))
| Rvalue::CheckedBinaryOp(ref _binop, box (ref lhs, ref rhs)) => {
[package]
name = "rustc_mir_transform"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
| Rvalue::Repeat(..)
| Rvalue::Len(..)
| Rvalue::Cast(..)
+ | Rvalue::ShallowInitBox(..)
| Rvalue::Discriminant(..)
| Rvalue::NullaryOp(..) => {}
}
[package]
name = "coverage_test_macros"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
proc-macro = true
}
Rvalue::Cast(..)
+ | Rvalue::ShallowInitBox(..)
| Rvalue::Use(..)
| Rvalue::Repeat(..)
| Rvalue::Len(..)
| Rvalue::AddressOf(_, _)
| Rvalue::Cast(_, Operand::Constant(_), _)
| Rvalue::NullaryOp(_, _)
+ | Rvalue::ShallowInitBox(_, _)
| Rvalue::UnaryOp(_, Operand::Constant(_)) => return true,
// These rvalues make things ambiguous
| Rvalue::ThreadLocalRef(_)
| Rvalue::AddressOf(_, _)
| Rvalue::NullaryOp(_, _)
+ | Rvalue::ShallowInitBox(_, _)
| Rvalue::UnaryOp(_, Operand::Constant(_))
| Rvalue::Cast(_, Operand::Constant(_), _)
=> return None,
ty::InstanceDef::ReifyShim(def_id) => {
build_call_shim(tcx, instance, None, CallKind::Direct(def_id))
}
- ty::InstanceDef::ClosureOnceShim { call_once: _ } => {
+ ty::InstanceDef::ClosureOnceShim { call_once: _, track_caller: _ } => {
let fn_mut = tcx.require_lang_item(LangItem::FnMut, None);
let call_mut = tcx
.associated_items(fn_mut)
[package]
name = "rustc_monomorphize"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_parse"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
use std::iter::once;
use std::ops::Range;
-use rustc_errors::{Applicability, Handler};
+use rustc_errors::{pluralize, Applicability, Handler};
use rustc_lexer::unescape::{EscapeError, Mode};
use rustc_span::{BytePos, Span};
.emit();
}
EscapeError::MoreThanOneChar => {
- let (prefix, msg) = if mode.is_bytes() {
- ("b", "if you meant to write a byte string literal, use double quotes")
- } else {
- ("", "if you meant to write a `str` literal, use double quotes")
- };
+ use unicode_normalization::{char::is_combining_mark, UnicodeNormalization};
- handler
- .struct_span_err(
- span_with_quotes,
- "character literal may only contain one codepoint",
- )
- .span_suggestion(
+ let mut has_help = false;
+ let mut handler = handler.struct_span_err(
+ span_with_quotes,
+ "character literal may only contain one codepoint",
+ );
+
+ if lit.chars().skip(1).all(|c| is_combining_mark(c)) {
+ let escaped_marks =
+ lit.chars().skip(1).map(|c| c.escape_default().to_string()).collect::<Vec<_>>();
+ handler.span_note(
+ span,
+ &format!(
+ "this `{}` is followed by the combining mark{} `{}`",
+ lit.chars().next().unwrap(),
+ pluralize!(escaped_marks.len()),
+ escaped_marks.join(""),
+ ),
+ );
+ let normalized = lit.nfc().to_string();
+ if normalized.chars().count() == 1 {
+ has_help = true;
+ handler.span_suggestion(
+ span,
+ &format!(
+ "consider using the normalized form `{}` of this character",
+ normalized.chars().next().unwrap().escape_default()
+ ),
+ normalized,
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+
+ if !has_help {
+ let (prefix, msg) = if mode.is_bytes() {
+ ("b", "if you meant to write a byte string literal, use double quotes")
+ } else {
+ ("", "if you meant to write a `str` literal, use double quotes")
+ };
+
+ handler.span_suggestion(
span_with_quotes,
msg,
format!("{}\"{}\"", prefix, lit),
Applicability::MachineApplicable,
- )
- .emit();
+ );
+ }
+
+ handler.emit();
}
EscapeError::EscapeOnlyChar => {
let (c, char_span) = last_char();
#![feature(box_patterns)]
#![recursion_limit = "256"]
+#[macro_use]
+extern crate tracing;
+
use rustc_ast as ast;
use rustc_ast::token::{self, Nonterminal, Token, TokenKind};
use rustc_ast::tokenstream::{self, AttributesData, CanSynthesizeMissingTokens, LazyTokenStream};
self.struct_span_err(sp, &msg)
.span_suggestion_short(sp, "change this to `;`", ";".to_string(), appl)
.emit();
- return Ok(false);
+ return Ok(true);
} else if self.look_ahead(0, |t| {
t == &token::CloseDelim(token::Brace)
|| (
.span_label(self.token.span, "unexpected token")
.span_suggestion_short(sp, "add `;` here", ";".to_string(), appl)
.emit();
- return Ok(false);
+ return Ok(true);
}
}
/// If we encounter a parser state that looks like the user has written a `struct` literal with
/// parentheses instead of braces, recover the parser state and provide suggestions.
+ #[instrument(skip(self, seq, snapshot), level = "trace")]
fn maybe_recover_struct_lit_bad_delims(
&mut self,
lo: Span,
pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
self.parse_opt_lit().ok_or_else(|| {
+ if let token::Interpolated(inner) = &self.token.kind {
+ let expr = match inner.as_ref() {
+ token::NtExpr(expr) => Some(expr),
+ token::NtLiteral(expr) => Some(expr),
+ _ => None,
+ };
+ if let Some(expr) = expr {
+ if matches!(expr.kind, ExprKind::Err) {
+ self.diagnostic()
+ .delay_span_bug(self.token.span, &"invalid interpolated expression");
+ return self.diagnostic().struct_dummy();
+ }
+ }
+ }
let msg = format!("unexpected token: {}", super::token_descr(&self.token));
self.struct_span_err(self.token.span, &msg)
})
self.expect(&token::Not)?; // `!`
let ident = self.parse_ident()?;
+
+ if self.eat(&token::Not) {
+ // Handle macro_rules! foo!
+ let span = self.prev_token.span;
+ self.struct_span_err(span, "macro names aren't followed by a `!`")
+ .span_suggestion(
+ span,
+ "remove the `!`",
+ "".to_owned(),
+ Applicability::MachineApplicable,
+ )
+ .emit();
+ }
+
let body = self.parse_mac_args()?;
self.eat_semi_for_macro_if_needed(&body);
self.complain_if_pub_macro(vis, true);
use rustc_ast::tokenstream::{DelimSpan, TokenTree};
use rustc_ast::{self as ast, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
-use rustc_errors::{Applicability, PResult};
+use rustc_errors::{Applicability, FatalError, PResult};
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
use rustc_session::parse::ParseSess;
// Some special attributes like `cfg` must be checked
// before the generic check, so we skip them here.
let should_skip = |name| name == sym::cfg;
- // Some of previously accepted forms were used in practice,
- // report them as warnings for now.
- let should_warn = |name| {
- name == sym::doc
- || name == sym::ignore
- || name == sym::inline
- || name == sym::link
- || name == sym::test
- || name == sym::bench
- };
match parse_meta(sess, attr) {
Ok(meta) => {
if !should_skip(name) && !is_attr_template_compatible(&template, &meta.kind) {
- let error_msg = format!("malformed `{}` attribute input", name);
- let mut msg = "attribute must be of the form ".to_owned();
- let mut suggestions = vec![];
- let mut first = true;
- if template.word {
- first = false;
- let code = format!("#[{}]", name);
- msg.push_str(&format!("`{}`", &code));
- suggestions.push(code);
- }
- if let Some(descr) = template.list {
- if !first {
- msg.push_str(" or ");
- }
- first = false;
- let code = format!("#[{}({})]", name, descr);
- msg.push_str(&format!("`{}`", &code));
- suggestions.push(code);
- }
- if let Some(descr) = template.name_value_str {
- if !first {
- msg.push_str(" or ");
- }
- let code = format!("#[{} = \"{}\"]", name, descr);
- msg.push_str(&format!("`{}`", &code));
- suggestions.push(code);
- }
- if should_warn(name) {
- sess.buffer_lint(
- &ILL_FORMED_ATTRIBUTE_INPUT,
- meta.span,
- ast::CRATE_NODE_ID,
- &msg,
- );
- } else {
- sess.span_diagnostic
- .struct_span_err(meta.span, &error_msg)
- .span_suggestions(
- meta.span,
- if suggestions.len() == 1 {
- "must be of the form"
- } else {
- "the following are the possible correct uses"
- },
- suggestions.into_iter(),
- Applicability::HasPlaceholders,
- )
- .emit();
- }
+ emit_malformed_attribute(sess, attr, name, template);
}
}
Err(mut err) => {
}
}
}
+
+fn emit_malformed_attribute(
+ sess: &ParseSess,
+ attr: &Attribute,
+ name: Symbol,
+ template: AttributeTemplate,
+) {
+ // Some of previously accepted forms were used in practice,
+ // report them as warnings for now.
+ let should_warn = |name| {
+ matches!(name, sym::doc | sym::ignore | sym::inline | sym::link | sym::test | sym::bench)
+ };
+
+ let error_msg = format!("malformed `{}` attribute input", name);
+ let mut msg = "attribute must be of the form ".to_owned();
+ let mut suggestions = vec![];
+ let mut first = true;
+ let inner = if attr.style == ast::AttrStyle::Inner { "!" } else { "" };
+ if template.word {
+ first = false;
+ let code = format!("#{}[{}]", inner, name);
+ msg.push_str(&format!("`{}`", &code));
+ suggestions.push(code);
+ }
+ if let Some(descr) = template.list {
+ if !first {
+ msg.push_str(" or ");
+ }
+ first = false;
+ let code = format!("#{}[{}({})]", inner, name, descr);
+ msg.push_str(&format!("`{}`", &code));
+ suggestions.push(code);
+ }
+ if let Some(descr) = template.name_value_str {
+ if !first {
+ msg.push_str(" or ");
+ }
+ let code = format!("#{}[{} = \"{}\"]", inner, name, descr);
+ msg.push_str(&format!("`{}`", &code));
+ suggestions.push(code);
+ }
+ if should_warn(name) {
+ sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, attr.span, ast::CRATE_NODE_ID, &msg);
+ } else {
+ sess.span_diagnostic
+ .struct_span_err(attr.span, &error_msg)
+ .span_suggestions(
+ attr.span,
+ if suggestions.len() == 1 {
+ "must be of the form"
+ } else {
+ "the following are the possible correct uses"
+ },
+ suggestions.into_iter(),
+ Applicability::HasPlaceholders,
+ )
+ .emit();
+ }
+}
+
+pub fn emit_fatal_malformed_builtin_attribute(
+ sess: &ParseSess,
+ attr: &Attribute,
+ name: Symbol,
+) -> ! {
+ let template = BUILTIN_ATTRIBUTE_MAP.get(&name).expect("builtin attr defined").2;
+ emit_malformed_attribute(sess, attr, name, template);
+ // This is fatal, otherwise it will likely cause a cascade of other errors
+ // (and an error here is expected to be very rare).
+ FatalError.raise()
+}
[package]
name = "rustc_parse_format"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
rustc_span = { path = "../rustc_span" }
[package]
name = "rustc_passes"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
tracing = "0.1"
sym::default_method_body_is_const => {
self.check_default_method_body_is_const(attr, span, target)
}
+ sym::must_not_suspend => self.check_must_not_suspend(&attr, span, target),
sym::rustc_const_unstable
| sym::rustc_const_stable
| sym::unstable
is_valid
}
+ /// Checks if `#[must_not_suspend]` is applied to a function. Returns `true` if valid.
+ fn check_must_not_suspend(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
+ match target {
+ Target::Struct | Target::Enum | Target::Union | Target::Trait => true,
+ _ => {
+ self.tcx
+ .sess
+ .struct_span_err(attr.span, "`must_not_suspend` attribute should be applied to a struct, enum, or trait")
+ .span_label(*span, "is not a struct, enum, or trait")
+ .emit();
+ false
+ }
+ }
+ }
+
/// Checks if `#[cold]` is applied to a non-function. Returns `true` if valid.
fn check_cold(&self, hir_id: HirId, attr: &Attribute, span: &Span, target: Target) {
match target {
self.hir_ids_seen.insert(hir_id.local_id);
}
- fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef<'hir>) {
+ fn visit_impl_item_ref(&mut self, _: &'hir hir::ImplItemRef) {
// Explicitly do nothing here. ImplItemRefs contain hir::Visibility
// values that actually belong to an ImplItem instead of the ItemKind::Impl
// we are currently in. So for those it's correct that they have a
// different owner.
}
- fn visit_foreign_item_ref(&mut self, _: &'hir hir::ForeignItemRef<'hir>) {
+ fn visit_foreign_item_ref(&mut self, _: &'hir hir::ForeignItemRef) {
// Explicitly do nothing here. ForeignItemRefs contain hir::Visibility
// values that actually belong to an ForeignItem instead of the ItemKind::ForeignMod
// we are currently in. So for those it's correct that they have a
name = "rustc_plugin_impl"
version = "0.0.0"
build = false
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_privacy"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
rustc_middle = { path = "../rustc_middle" }
}
hir::ItemKind::Impl(ref impl_) => {
for impl_item_ref in impl_.items {
- if impl_.of_trait.is_some() || impl_item_ref.vis.node.is_pub() {
+ if impl_.of_trait.is_some()
+ || self.tcx.visibility(impl_item_ref.id.def_id) == ty::Visibility::Public
+ {
self.update(impl_item_ref.id.def_id, item_level);
}
}
}
hir::ItemKind::ForeignMod { items, .. } => {
for foreign_item in items {
- if foreign_item.vis.node.is_pub() {
+ if self.tcx.visibility(foreign_item.id.def_id) == ty::Visibility::Public {
self.update(foreign_item.id.def_id, item_level);
}
}
// methods will be visible as `Public::foo`.
let mut found_pub_static = false;
for impl_item_ref in impl_.items {
- if self.item_is_public(impl_item_ref.id.def_id, &impl_item_ref.vis) {
+ if self.access_levels.is_reachable(impl_item_ref.id.def_id)
+ || self.tcx.visibility(impl_item_ref.id.def_id)
+ == ty::Visibility::Public
+ {
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
match impl_item_ref.kind {
AssocItemKind::Const => {
[package]
name = "rustc_query_impl"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
pub fn $name<$tcx>(tcx: QueryCtxt<$tcx>, key: query_keys::$name<$tcx>) -> QueryStackFrame {
let kind = dep_graph::DepKind::$name;
let name = stringify!($name);
- let description = ty::print::with_forced_impl_filename_line(
+ // Disable visible paths printing for performance reasons.
+ // Showing visible path instead of any path is not that important in production.
+ let description = ty::print::with_no_visible_paths(
+ || ty::print::with_forced_impl_filename_line(
// Force filename-line mode to avoid invoking `type_of` query.
|| queries::$name::describe(tcx, key)
- );
+ ));
let description = if tcx.sess.verbose() {
format!("{} [{}]", description, name)
} else {
[package]
name = "rustc_query_system"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_resolve"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
test = false
use crate::imports::{Import, ImportKind};
use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
-use crate::{CrateLint, Determinacy, PathResult, ResolutionError, VisResolutionError};
-use crate::{
- ExternPreludeEntry, ModuleOrUniformRoot, ParentScope, PerNS, Resolver, ResolverArenas,
-};
-use crate::{Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, Segment, ToNameBinding};
+use crate::{CrateLint, Determinacy, ExternPreludeEntry, Module, ModuleKind, ModuleOrUniformRoot};
+use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError};
+use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError};
use rustc_ast::visit::{self, AssocCtxt, Visitor};
use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
}
/// Walks up the tree of definitions starting at `def_id`,
- /// stopping at the first `DefKind::Mod` encountered
- fn nearest_parent_mod(&mut self, def_id: DefId) -> Module<'a> {
- let def_key = self.cstore().def_key(def_id);
-
- let mut parent_id = DefId {
- krate: def_id.krate,
- index: def_key.parent.expect("failed to get parent for module"),
- };
- // The immediate parent may not be a module
- // (e.g. `const _: () = { #[path = "foo.rs"] mod foo; };`)
- // Walk up the tree until we hit a module or the crate root.
- while parent_id.index != CRATE_DEF_INDEX
- && self.cstore().def_kind(parent_id) != DefKind::Mod
- {
- let parent_def_key = self.cstore().def_key(parent_id);
- parent_id.index = parent_def_key.parent.expect("failed to get parent for module");
+ /// stopping at the first encountered module.
+ /// Parent block modules for arbitrary def-ids are not recorded for the local crate,
+ /// and are not preserved in metadata for foreign crates, so block modules are never
+ /// returned by this function.
+ ///
+ /// For the local crate ignoring block modules may be incorrect, so use this method with care.
+ ///
+ /// For foreign crates block modules can be ignored without introducing observable differences,
+ /// moreover they has to be ignored right now because they are not kept in metadata.
+ /// Foreign parent modules are used for resolving names used by foreign macros with def-site
+ /// hygiene, therefore block module ignorability relies on macros with def-site hygiene and
+ /// block module parents being unreachable from other crates.
+ /// Reachable macros with block module parents exist due to `#[macro_export] macro_rules!`,
+ /// but they cannot use def-site hygiene, so the assumption holds
+ /// (<https://github.com/rust-lang/rust/pull/77984#issuecomment-712445508>).
+ fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'a> {
+ loop {
+ match self.get_module(def_id) {
+ Some(module) => return module,
+ None => {
+ def_id.index =
+ self.def_key(def_id).parent.expect("non-root `DefId` without parent")
+ }
+ }
}
- self.get_module(parent_id)
}
- pub fn get_module(&mut self, def_id: DefId) -> Module<'a> {
- // If this is a local module, it will be in `module_map`, no need to recalculate it.
- if let Some(def_id) = def_id.as_local() {
- return self.module_map[&def_id];
- }
+ pub fn expect_module(&mut self, def_id: DefId) -> Module<'a> {
+ self.get_module(def_id).expect("argument `DefId` is not a module")
+ }
- // Cache module resolution
- if let Some(&module) = self.extern_module_map.get(&def_id) {
- return module;
+ /// If `def_id` refers to a module (in resolver's sense, i.e. a module item, crate root, enum,
+ /// or trait), then this function returns that module's resolver representation, otherwise it
+ /// returns `None`.
+ /// FIXME: `Module`s for local enums and traits are not currently found.
+ crate fn get_module(&mut self, def_id: DefId) -> Option<Module<'a>> {
+ if let module @ Some(..) = self.module_map.get(&def_id) {
+ return module.copied();
}
- let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
- // This is the crate root
- (self.cstore().crate_name(def_id.krate), None)
- } else {
- let def_key = self.cstore().def_key(def_id);
- let name = def_key
- .disambiguated_data
- .data
- .get_opt_name()
- .expect("given a DefId that wasn't a module");
-
- let parent = Some(self.nearest_parent_mod(def_id));
- (name, parent)
- };
+ if !def_id.is_local() {
+ let def_kind = self.cstore().def_kind(def_id);
+ match def_kind {
+ DefKind::Mod | DefKind::Enum | DefKind::Trait => {
+ let def_key = self.cstore().def_key(def_id);
+ let parent = def_key.parent.map(|index| {
+ self.get_nearest_non_block_module(DefId { index, krate: def_id.krate })
+ });
+ let name = if def_id.index == CRATE_DEF_INDEX {
+ self.cstore().crate_name(def_id.krate)
+ } else {
+ def_key.disambiguated_data.data.get_opt_name().expect("module without name")
+ };
- // Allocate and return a new module with the information we found
- let kind = ModuleKind::Def(DefKind::Mod, def_id, name);
- let module = self.arenas.alloc_module(ModuleData::new(
- parent,
- kind,
- def_id,
- self.cstore().module_expansion_untracked(def_id, &self.session),
- self.cstore().get_span_untracked(def_id, &self.session),
- ));
- self.extern_module_map.insert(def_id, module);
- module
+ let module = self.arenas.new_module(
+ parent,
+ ModuleKind::Def(def_kind, def_id, name),
+ self.cstore().module_expansion_untracked(def_id, &self.session),
+ self.cstore().get_span_untracked(def_id, &self.session),
+ // FIXME: Account for `#[no_implicit_prelude]` attributes.
+ parent.map_or(false, |module| module.no_implicit_prelude),
+ );
+ self.module_map.insert(def_id, module);
+ Some(module)
+ }
+ _ => None,
+ }
+ } else {
+ None
+ }
}
- crate fn macro_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
- let def_id = match expn_id.expn_data().macro_def_id {
- Some(def_id) => def_id,
- None => {
- return expn_id
- .as_local()
- .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id))
- .unwrap_or(&self.graph_root);
- }
- };
- self.macro_def_scope_from_def_id(def_id)
+ crate fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> {
+ match expn_id.expn_data().macro_def_id {
+ Some(def_id) => self.macro_def_scope(def_id),
+ None => expn_id
+ .as_local()
+ .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id))
+ .unwrap_or(&self.graph_root),
+ }
}
- crate fn macro_def_scope_from_def_id(&mut self, def_id: DefId) -> Module<'a> {
+ crate fn macro_def_scope(&mut self, def_id: DefId) -> Module<'a> {
if let Some(id) = def_id.as_local() {
self.local_macro_def_scopes[&id]
} else {
- // This is not entirely correct - a `macro_rules!` macro may occur
- // inside a 'block' module:
- //
- // ```rust
- // const _: () = {
- // #[macro_export]
- // macro_rules! my_macro {
- // () => {};
- // }
- // `
- // We don't record this information for external crates, so
- // the module we compute here will be the closest 'mod' item
- // (not necesssarily the actual parent of the `macro_rules!`
- // macro). `macro_rules!` macros can't use def-site hygiene,
- // so this hopefully won't be a problem.
- //
- // See https://github.com/rust-lang/rust/pull/77984#issuecomment-712445508
- self.nearest_parent_mod(def_id)
+ self.get_nearest_non_block_module(def_id)
}
}
self.r.visibilities[&def_id.expect_local()]
}
// Otherwise, the visibility is restricted to the nearest parent `mod` item.
- _ => ty::Visibility::Restricted(self.parent_scope.module.nearest_parent_mod),
+ _ => ty::Visibility::Restricted(self.parent_scope.module.nearest_parent_mod()),
})
}
ast::VisibilityKind::Restricted { ref path, id, .. } => {
local_def_id,
);
self.r.extern_crate_map.insert(local_def_id, crate_id);
- self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX })
+ self.r.expect_module(crate_id.as_def_id())
};
let used = self.process_macro_use_imports(item, module);
}
ItemKind::Mod(..) => {
- let module_kind = ModuleKind::Def(DefKind::Mod, def_id, ident.name);
- let module = self.r.arenas.alloc_module(ModuleData {
- no_implicit_prelude: parent.no_implicit_prelude || {
- self.r.session.contains_name(&item.attrs, sym::no_implicit_prelude)
- },
- ..ModuleData::new(
- Some(parent),
- module_kind,
- def_id,
- expansion.to_expn_id(),
- item.span,
- )
- });
+ let module = self.r.arenas.new_module(
+ Some(parent),
+ ModuleKind::Def(DefKind::Mod, def_id, ident.name),
+ expansion.to_expn_id(),
+ item.span,
+ parent.no_implicit_prelude
+ || self.r.session.contains_name(&item.attrs, sym::no_implicit_prelude),
+ );
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
- self.r.module_map.insert(local_def_id, module);
+ self.r.module_map.insert(def_id, module);
// Descend into the module.
self.parent_scope.module = module;
}
ItemKind::Enum(_, _) => {
- let module_kind = ModuleKind::Def(DefKind::Enum, def_id, ident.name);
- let module = self.r.new_module(
- parent,
- module_kind,
- parent.nearest_parent_mod,
+ let module = self.r.arenas.new_module(
+ Some(parent),
+ ModuleKind::Def(DefKind::Enum, def_id, ident.name),
expansion.to_expn_id(),
item.span,
+ parent.no_implicit_prelude,
);
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
self.parent_scope.module = module;
ItemKind::Trait(..) => {
// Add all the items within to a new module.
- let module_kind = ModuleKind::Def(DefKind::Trait, def_id, ident.name);
- let module = self.r.new_module(
- parent,
- module_kind,
- parent.nearest_parent_mod,
+ let module = self.r.arenas.new_module(
+ Some(parent),
+ ModuleKind::Def(DefKind::Trait, def_id, ident.name),
expansion.to_expn_id(),
item.span,
+ parent.no_implicit_prelude,
);
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
self.parent_scope.module = module;
let parent = self.parent_scope.module;
let expansion = self.parent_scope.expansion;
if self.block_needs_anonymous_module(block) {
- let module = self.r.new_module(
- parent,
+ let module = self.r.arenas.new_module(
+ Some(parent),
ModuleKind::Block(block.id),
- parent.nearest_parent_mod,
expansion.to_expn_id(),
block.span,
+ parent.no_implicit_prelude,
);
self.r.block_map.insert(block.id, module);
self.parent_scope.module = module; // Descend into the block.
// Record primary definitions.
match res {
Res::Def(kind @ (DefKind::Mod | DefKind::Enum | DefKind::Trait), def_id) => {
- let module = self.r.new_module(
- parent,
+ let module = self.r.arenas.new_module(
+ Some(parent),
ModuleKind::Def(kind, def_id, ident.name),
- def_id,
expansion.to_expn_id(),
span,
+ // FIXME: Account for `#[no_implicit_prelude]` attributes.
+ parent.no_implicit_prelude,
);
self.r.define(parent, ident, TypeNS, (module, vis, span, expansion));
}
continue;
}
if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name) {
- let crate_root =
- self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
+ let crate_root = self.expect_module(crate_id.as_def_id());
suggestions.extend(self.lookup_import_candidates_from_module(
lookup_ident,
namespace,
candidates.iter().map(|c| path_names_to_string(&c.path)).collect();
path_strings.sort();
+ let core_path_strings =
+ path_strings.drain_filter(|p| p.starts_with("core::")).collect::<Vec<String>>();
+ path_strings.extend(core_path_strings);
path_strings.dedup();
let (determiner, kind) = if candidates.len() == 1 {
match ident.span.glob_adjust(module.expansion, glob_import.span) {
Some(Some(def)) => {
tmp_parent_scope =
- ParentScope { module: self.macro_def_scope(def), ..*parent_scope };
+ ParentScope { module: self.expn_def_scope(def), ..*parent_scope };
adjusted_parent_scope = &tmp_parent_scope;
}
Some(None) => {}
for import in module.glob_importers.borrow_mut().iter() {
let mut ident = key.ident;
let scope = match ident.span.reverse_glob_adjust(module.expansion, import.span) {
- Some(Some(def)) => self.macro_def_scope(def),
+ Some(Some(def)) => self.expn_def_scope(def),
Some(None) => import.parent_scope.module,
None => continue,
};
.collect::<Vec<_>>();
for (mut key, binding) in bindings {
let scope = match key.ident.span.reverse_glob_adjust(module.expansion, import.span) {
- Some(Some(def)) => self.r.macro_def_scope(def),
+ Some(Some(def)) => self.r.expn_def_scope(def),
Some(None) => import.parent_scope.module,
None => continue,
};
}
fn with_scope<T>(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
- let id = self.r.local_def_id(id);
- let module = self.r.module_map.get(&id).cloned(); // clones a reference
- if let Some(module) = module {
+ if let Some(module) = self.r.get_module(self.r.local_def_id(id).to_def_id()) {
// Move down in the graph.
let orig_module = replace(&mut self.parent_scope.module, module);
self.with_rib(ValueNS, ModuleRibKind(module), |this| {
if this.should_report_errs() {
let (err, candidates) = this.smart_resolve_report_errors(path, span, source, res);
- let def_id = this.parent_scope.module.nearest_parent_mod;
+ let def_id = this.parent_scope.module.nearest_parent_mod();
let instead = res.is_some();
let suggestion =
if res.is_none() { this.report_missing_type_error(path) } else { None };
drop(parent_err);
- let def_id = this.parent_scope.module.nearest_parent_mod;
+ let def_id = this.parent_scope.module.nearest_parent_mod();
if this.should_report_errs() {
this.r.use_injections.push(UseError {
_ => {}
}
let item = {
- let hir = tcx.hir();
- let mut parent_iter = hir.parent_iter(hir_id);
+ let mut parent_iter = tcx.hir().parent_iter(hir_id);
loop {
let node = parent_iter.next().map(|n| n.1);
match node {
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(box_patterns)]
+#![feature(drain_filter)]
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(format_args_capture)]
use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind};
use rustc_hir::def::Namespace::*;
use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
-use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefPathHash, LocalDefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefPathHash, LocalDefId};
+use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
use rustc_hir::TraitCandidate;
use rustc_index::vec::IndexVec;
/// What kind of module this is, because this may not be a `mod`.
kind: ModuleKind,
- /// The [`DefId`] of the nearest `mod` item ancestor (which may be this module).
- /// This may be the crate root.
- nearest_parent_mod: DefId,
-
/// Mapping between names and their (possibly in-progress) resolutions in this module.
/// Resolutions in modules from other crates are not populated until accessed.
lazy_resolutions: Resolutions<'a>,
fn new(
parent: Option<Module<'a>>,
kind: ModuleKind,
- nearest_parent_mod: DefId,
expansion: ExpnId,
span: Span,
+ no_implicit_prelude: bool,
) -> Self {
+ let is_foreign = match kind {
+ ModuleKind::Def(_, def_id, _) => !def_id.is_local(),
+ ModuleKind::Block(_) => false,
+ };
ModuleData {
parent,
kind,
- nearest_parent_mod,
lazy_resolutions: Default::default(),
- populate_on_access: Cell::new(!nearest_parent_mod.is_local()),
+ populate_on_access: Cell::new(is_foreign),
unexpanded_invocations: Default::default(),
- no_implicit_prelude: false,
+ no_implicit_prelude,
glob_importers: RefCell::new(Vec::new()),
globs: RefCell::new(Vec::new()),
traits: RefCell::new(None),
}
}
+ /// The [`DefId`] of the nearest `mod` item ancestor (which may be this module).
+ /// This may be the crate root.
+ fn nearest_parent_mod(&self) -> DefId {
+ match self.kind {
+ ModuleKind::Def(DefKind::Mod, def_id, _) => def_id,
+ _ => self.parent.expect("non-root module without parent").nearest_parent_mod(),
+ }
+ }
+
fn is_ancestor_of(&self, mut other: &Self) -> bool {
while !ptr::eq(self, other) {
if let Some(parent) = other.parent {
/// some AST passes can generate identifiers that only resolve to local or
/// language items.
empty_module: Module<'a>,
- module_map: FxHashMap<LocalDefId, Module<'a>>,
- extern_module_map: FxHashMap<DefId, Module<'a>>,
+ module_map: FxHashMap<DefId, Module<'a>>,
binding_parent_modules: FxHashMap<PtrKey<'a, NameBinding<'a>>, Module<'a>>,
underscore_disambiguator: u32,
}
impl<'a> ResolverArenas<'a> {
- fn alloc_module(&'a self, module: ModuleData<'a>) -> Module<'a> {
- let module = self.modules.alloc(module);
+ fn new_module(
+ &'a self,
+ parent: Option<Module<'a>>,
+ kind: ModuleKind,
+ expn_id: ExpnId,
+ span: Span,
+ no_implicit_prelude: bool,
+ ) -> Module<'a> {
+ let module =
+ self.modules.alloc(ModuleData::new(parent, kind, expn_id, span, no_implicit_prelude));
if module.def_id().map_or(true, |def_id| def_id.is_local()) {
self.local_modules.borrow_mut().push(module);
}
metadata_loader: Box<MetadataLoaderDyn>,
arenas: &'a ResolverArenas<'a>,
) -> Resolver<'a> {
- let root_local_def_id = LocalDefId { local_def_index: CRATE_DEF_INDEX };
- let root_def_id = root_local_def_id.to_def_id();
- let root_module_kind = ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty);
- let graph_root = arenas.alloc_module(ModuleData {
- no_implicit_prelude: session.contains_name(&krate.attrs, sym::no_implicit_prelude),
- ..ModuleData::new(None, root_module_kind, root_def_id, ExpnId::root(), krate.span)
- });
- let empty_module_kind = ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty);
- let empty_module = arenas.alloc_module(ModuleData {
- no_implicit_prelude: true,
- ..ModuleData::new(
- Some(graph_root),
- empty_module_kind,
- root_def_id,
- ExpnId::root(),
- DUMMY_SP,
- )
- });
+ let root_def_id = CRATE_DEF_ID.to_def_id();
+ let graph_root = arenas.new_module(
+ None,
+ ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty),
+ ExpnId::root(),
+ krate.span,
+ session.contains_name(&krate.attrs, sym::no_implicit_prelude),
+ );
+ let empty_module = arenas.new_module(
+ None,
+ ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty),
+ ExpnId::root(),
+ DUMMY_SP,
+ true,
+ );
let mut module_map = FxHashMap::default();
- module_map.insert(root_local_def_id, graph_root);
+ module_map.insert(root_def_id, graph_root);
let definitions = Definitions::new(session.local_stable_crate_id(), krate.span);
let root = definitions.get_root_def();
let mut visibilities = FxHashMap::default();
- visibilities.insert(root_local_def_id, ty::Visibility::Public);
+ visibilities.insert(CRATE_DEF_ID, ty::Visibility::Public);
let mut def_id_to_node_id = IndexVec::default();
assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), root);
empty_module,
module_map,
block_map: Default::default(),
- extern_module_map: FxHashMap::default(),
binding_parent_modules: FxHashMap::default(),
ast_transform_scopes: FxHashMap::default(),
import_ids
}
- fn new_module(
- &self,
- parent: Module<'a>,
- kind: ModuleKind,
- nearest_parent_mod: DefId,
- expn_id: ExpnId,
- span: Span,
- ) -> Module<'a> {
- let module = ModuleData::new(Some(parent), kind, nearest_parent_mod, expn_id, span);
- self.arenas.alloc_module(module)
- }
-
fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
let ident = ident.normalize_to_macros_2_0();
let disambiguator = if ident.name == kw::Underscore {
derive_fallback_lint_id: Option<NodeId>,
) -> Option<(Module<'a>, Option<NodeId>)> {
if !module.expansion.outer_expn_is_descendant_of(*ctxt) {
- return Some((self.macro_def_scope(ctxt.remove_mark()), None));
+ return Some((self.expn_def_scope(ctxt.remove_mark()), None));
}
if let ModuleKind::Block(..) = module.kind {
ModuleOrUniformRoot::Module(m) => {
if let Some(def) = ident.span.normalize_to_macros_2_0_and_adjust(m.expansion) {
tmp_parent_scope =
- ParentScope { module: self.macro_def_scope(def), ..*parent_scope };
+ ParentScope { module: self.expn_def_scope(def), ..*parent_scope };
adjusted_parent_scope = &tmp_parent_scope;
}
}
ctxt.adjust(ExpnId::root())
};
let module = match mark {
- Some(def) => self.macro_def_scope(def),
+ Some(def) => self.expn_def_scope(def),
None => {
debug!(
"resolve_crate_root({:?}): found no mark (ident.span = {:?})",
return self.graph_root;
}
};
- let module = self.get_module(DefId { index: CRATE_DEF_INDEX, ..module.nearest_parent_mod });
+ let module = self
+ .expect_module(module.def_id().map_or(LOCAL_CRATE, |def_id| def_id.krate).as_def_id());
debug!(
"resolve_crate_root({:?}): got module {:?} ({:?}) (ident.span = {:?})",
ident,
}
fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> {
- let mut module = self.get_module(module.nearest_parent_mod);
+ let mut module = self.expect_module(module.nearest_parent_mod());
while module.span.ctxt().normalize_to_macros_2_0() != *ctxt {
- let parent = module.parent.unwrap_or_else(|| self.macro_def_scope(ctxt.remove_mark()));
- module = self.get_module(parent.nearest_parent_mod);
+ let parent = module.parent.unwrap_or_else(|| self.expn_def_scope(ctxt.remove_mark()));
+ module = self.expect_module(parent.nearest_parent_mod());
}
module
}
}
fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
- vis.is_accessible_from(module.nearest_parent_mod, self)
+ vis.is_accessible_from(module.nearest_parent_mod(), self)
}
fn set_binding_parent_module(&mut self, binding: &'a NameBinding<'a>, module: Module<'a>) {
self.binding_parent_modules.get(&PtrKey(modularized)),
) {
(Some(macro_rules), Some(modularized)) => {
- macro_rules.nearest_parent_mod == modularized.nearest_parent_mod
+ macro_rules.nearest_parent_mod() == modularized.nearest_parent_mod()
&& modularized.is_ancestor_of(macro_rules)
}
_ => false,
} else {
self.crate_loader.maybe_process_path_extern(ident.name)?
};
- let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
+ let crate_root = self.expect_module(crate_id.as_def_id());
Some(
(crate_root, ty::Visibility::Public, DUMMY_SP, LocalExpnId::ROOT)
.to_name_binding(self.arenas),
tokens: None,
}
};
- let module = self.get_module(module_id);
+ let module = self.expect_module(module_id);
let parent_scope = &ParentScope::module(module, self);
let res = self.resolve_ast_path(&path, ns, parent_scope).map_err(|_| ())?;
Ok((path, res))
features: &[Symbol],
parent_module_id: Option<NodeId>,
) -> LocalExpnId {
- let parent_module = parent_module_id.map(|module_id| self.local_def_id(module_id));
+ let parent_module =
+ parent_module_id.map(|module_id| self.local_def_id(module_id).to_def_id());
let expn_id = LocalExpnId::fresh(
ExpnData::allow_unstable(
ExpnKind::AstPass(pass),
self.session.edition(),
features.into(),
None,
- parent_module.map(LocalDefId::to_def_id),
+ parent_module,
),
self.create_stable_hashing_context(),
);
- let parent_scope = parent_module
- .map_or(self.empty_module, |parent_def_id| self.module_map[&parent_def_id]);
+ let parent_scope =
+ parent_module.map_or(self.empty_module, |def_id| self.expect_module(def_id));
self.ast_transform_scopes.insert(expn_id, parent_scope);
expn_id
)?;
let span = invoc.span();
+ let def_id = res.opt_def_id();
invoc_id.set_expn_data(
ext.expn_data(
parent_scope.expansion,
span,
fast_print_path(path),
- res.opt_def_id(),
- res.opt_def_id().map(|macro_def_id| {
- self.macro_def_scope_from_def_id(macro_def_id).nearest_parent_mod
- }),
+ def_id,
+ def_id.map(|def_id| self.macro_def_scope(def_id).nearest_parent_mod()),
),
self.create_stable_hashing_context(),
);
- if let Res::Def(_, _) = res {
- // Gate macro attributes in `#[derive]` output.
- if !self.session.features_untracked().macro_attributes_in_derive_output
- && kind == MacroKind::Attr
- && ext.builtin_name != Some(sym::derive)
- {
- let mut expn_id = parent_scope.expansion;
- loop {
- // Helper attr table is a quick way to determine whether the attr is `derive`.
- if self.helper_attrs.contains_key(&expn_id) {
- feature_err(
- &self.session.parse_sess,
- sym::macro_attributes_in_derive_output,
- path.span,
- "macro attributes in `#[derive]` output are unstable",
- )
- .emit();
- break;
- } else {
- let expn_data = expn_id.expn_data();
- match expn_data.kind {
- ExpnKind::Root
- | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {
- break;
- }
- _ => expn_id = expn_data.parent.expect_local(),
- }
- }
- }
- }
- }
-
Ok(ext)
}
[package]
name = "rustc_save_analysis"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
tracing = "0.1"
[package]
name = "rustc_serialize"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
indexmap = "1"
[package]
name = "rustc_session"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
getopts = "0.2"
let mut fuel = self.optimization_fuel.lock();
ret = fuel.remaining != 0;
if fuel.remaining == 0 && !fuel.out_of_fuel {
- self.warn(&format!("optimization-fuel-exhausted: {}", msg()));
+ if self.diagnostic().can_emit_warnings() {
+ // We only call `msg` in case we can actually emit warnings.
+ // Otherwise, this could cause a `delay_good_path_bug` to
+ // trigger (issue #79546).
+ self.warn(&format!("optimization-fuel-exhausted: {}", msg()));
+ }
fuel.out_of_fuel = true;
} else if fuel.remaining > 0 {
fuel.remaining -= 1;
[package]
name = "rustc_span"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
#[macro_use]
extern crate rustc_macros;
+#[macro_use]
+extern crate tracing;
+
use rustc_data_structures::AtomicRef;
use rustc_macros::HashStable_Generic;
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
/// ^^^^^^^^^^^^^^^^^
/// ```
pub fn until(self, end: Span) -> Span {
- let span = self.data();
- let end = end.data();
+ // Most of this function's body is copied from `to`.
+ // We can't just do `self.to(end.shrink_to_lo())`,
+ // because to also does some magic where it uses min/max so
+ // it can handle overlapping spans. Some advanced mis-use of
+ // `until` with different ctxts makes this visible.
+ let span_data = self.data();
+ let end_data = end.data();
+ // FIXME(jseyfried): `self.ctxt` should always equal `end.ctxt` here (cf. issue #23480).
+ // Return the macro span on its own to avoid weird diagnostic output. It is preferable to
+ // have an incomplete span than a completely nonsensical one.
+ if span_data.ctxt != end_data.ctxt {
+ if span_data.ctxt == SyntaxContext::root() {
+ return end;
+ } else if end_data.ctxt == SyntaxContext::root() {
+ return self;
+ }
+ // Both spans fall within a macro.
+ // FIXME(estebank): check if it is the *same* macro.
+ }
Span::new(
- span.lo,
- end.lo,
- if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt },
- if span.parent == end.parent { span.parent } else { None },
+ span_data.lo,
+ end_data.lo,
+ if end_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt },
+ if span_data.parent == end_data.parent { span_data.parent } else { None },
)
}
f.lookup_line(sp.lo()) != f.lookup_line(sp.hi())
}
+ #[instrument(skip(self), level = "trace")]
pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> {
let lo = self.lookup_char_pos(sp.lo());
- debug!("span_to_lines: lo={:?}", lo);
+ trace!(?lo);
let hi = self.lookup_char_pos(sp.hi());
- debug!("span_to_lines: hi={:?}", hi);
+ trace!(?hi);
if lo.file.start_pos != hi.file.start_pos {
return Err(SpanLinesError::DistinctSources(DistinctSources {
begin: (lo.file.name.clone(), lo.file.start_pos),
TyCtxt,
TyKind,
Unknown,
+ UnsafeArg,
Vec,
Yield,
_DECLS,
clone_from,
closure,
closure_to_fn_coercion,
+ closure_track_caller,
cmp,
cmp_max,
cmp_min,
mul,
mul_assign,
mul_with_overflow,
+ must_not_suspend,
must_use,
mut_ptr,
mut_slice_ptr,
pub struct Symbol(SymbolIndex);
rustc_index::newtype_index! {
- pub struct SymbolIndex { .. }
+ struct SymbolIndex { .. }
}
impl Symbol {
self.0.as_u32()
}
- pub fn len(self) -> usize {
- with_session_globals(|session_globals| session_globals.symbol_interner.get(self).len())
- }
-
pub fn is_empty(self) -> bool {
self == kw::Empty
}
[package]
name = "rustc_symbol_mangling"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_target"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
bitflags = "1.2.1"
let mut base = super::apple_base::opts("macos");
base.cpu = "apple-a12".to_string();
base.max_atomic_width = Some(128);
- base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::LEAK | SanitizerSet::THREAD;
+
+ // FIXME: The leak sanitizer currently fails the tests, see #88132.
+ base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;
base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), "arm64".to_string()]);
base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
[package]
name = "rustc_trait_selection"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
let obligation = traits::Obligation::new(
cause.clone(),
self.param_env,
- trait_ref.without_const().to_predicate(tcx),
+ ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
);
if !self.infcx.predicate_may_hold(&obligation) {
debug!("overloaded_deref_ty: cannot match obligation");
cause: traits::ObligationCause::dummy(),
param_env,
recursion_depth: 0,
- predicate: trait_ref.without_const().to_predicate(self.tcx),
+ predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx),
};
self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr)
}
-use crate::infer::InferCtxtExt as _;
use crate::traits::{self, ObligationCause, PredicateObligation};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::Lrc;
}
impl<'a, 'tcx> Instantiator<'a, 'tcx> {
- #[instrument(level = "debug", skip(self))]
fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
let tcx = self.infcx.tcx;
value.fold_with(&mut BottomUpFolder {
})
}
+ #[instrument(skip(self), level = "debug")]
fn fold_opaque_ty(
&mut self,
ty: Ty<'tcx>,
let tcx = infcx.tcx;
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
- debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs);
-
// Use the same type variable if the exact same opaque type appears more
// than once in the return type (e.g., if it's passed to a type alias).
if let Some(opaque_defn) = infcx.inner.borrow().opaque_types.get(&opaque_type_key) {
- debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty);
+ debug!("re-using cached concrete type {:?}", opaque_defn.concrete_ty.kind());
return opaque_defn.concrete_ty;
}
+
let ty_var = infcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span: self.value_span,
});
- // Make sure that we are in fact defining the *entire* type
- // (e.g., `type Foo<T: Bound> = impl Bar;` needs to be
- // defined by a function like `fn foo<T: Bound>() -> Foo<T>`).
- debug!("instantiate_opaque_types: param_env={:#?}", self.param_env,);
- debug!("instantiate_opaque_types: generics={:#?}", tcx.generics_of(def_id),);
-
// Ideally, we'd get the span where *this specific `ty` came
// from*, but right now we just use the span from the overall
// value being folded. In simple cases like `-> impl Foo`,
infcx.opaque_types_vars.insert(ty_var, ty);
}
- debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
- self.compute_opaque_type_obligations(opaque_type_key);
-
- ty_var
- }
-
- fn compute_opaque_type_obligations(&mut self, opaque_type_key: OpaqueTypeKey<'tcx>) {
- let infcx = self.infcx;
- let tcx = infcx.tcx;
- let OpaqueTypeKey { def_id, substs } = opaque_type_key;
+ debug!("generated new type inference var {:?}", ty_var.kind());
let item_bounds = tcx.explicit_item_bounds(def_id);
- debug!("instantiate_opaque_types: bounds={:#?}", item_bounds);
- let bounds: Vec<_> =
- item_bounds.iter().map(|(bound, _)| bound.subst(tcx, substs)).collect();
-
- let param_env = tcx.param_env(def_id);
- let InferOk { value: bounds, obligations } = infcx.partially_normalize_associated_types_in(
- ObligationCause::misc(self.value_span, self.body_id),
- param_env,
- bounds,
- );
- self.obligations.extend(obligations);
- debug!("instantiate_opaque_types: bounds={:?}", bounds);
+ self.obligations.reserve(item_bounds.len());
+ for (predicate, _) in item_bounds {
+ debug!(?predicate);
+ let predicate = predicate.subst(tcx, substs);
+ debug!(?predicate);
+
+ // We can't normalize associated types from `rustc_infer`, but we can eagerly register inference variables for them.
+ let predicate = predicate.fold_with(&mut BottomUpFolder {
+ tcx,
+ ty_op: |ty| match ty.kind() {
+ ty::Projection(projection_ty) => infcx.infer_projection(
+ self.param_env,
+ *projection_ty,
+ ObligationCause::misc(self.value_span, self.body_id),
+ 0,
+ &mut self.obligations,
+ ),
+ _ => ty,
+ },
+ lt_op: |lt| lt,
+ ct_op: |ct| ct,
+ });
+ debug!(?predicate);
- for predicate in &bounds {
if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
if projection.ty.references_error() {
// No point on adding these obligations since there's a type error involved.
- return;
+ return tcx.ty_error();
}
}
- }
-
- self.obligations.reserve(bounds.len());
- for predicate in bounds {
// Change the predicate to refer to the type variable,
// which will be the concrete type instead of the opaque type.
// This also instantiates nested instances of `impl Trait`.
traits::ObligationCause::new(self.value_span, self.body_id, traits::OpaqueType);
// Require that the predicate holds for the concrete type.
- debug!("instantiate_opaque_types: predicate={:?}", predicate);
+ debug!(?predicate);
self.obligations.push(traits::Obligation::new(cause, self.param_env, predicate));
}
+
+ ty_var
}
}
/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
-pub fn may_define_opaque_type(
- tcx: TyCtxt<'_>,
- def_id: LocalDefId,
- opaque_hir_id: hir::HirId,
-) -> bool {
+fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool {
let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
// Named opaque types can be defined by any siblings or children of siblings.
ChalkEnvironmentAndGoal, FulfillmentError, FulfillmentErrorCode, ObligationCause,
PredicateObligation, SelectionError, TraitEngine,
};
-use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_middle::ty::{self, Ty};
pub struct FulfillmentContext<'tcx> {
obligations: FxIndexSet<PredicateObligation<'tcx>>,
+
+ relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>,
}
impl FulfillmentContext<'tcx> {
crate fn new() -> Self {
- FulfillmentContext { obligations: FxIndexSet::default() }
+ FulfillmentContext {
+ obligations: FxIndexSet::default(),
+ relationships: FxHashMap::default(),
+ }
}
}
assert!(!infcx.is_in_snapshot());
let obligation = infcx.resolve_vars_if_possible(obligation);
+ super::relationships::update(self, infcx, &obligation);
+
self.obligations.insert(obligation);
}
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
self.obligations.iter().cloned().collect()
}
+
+ fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
+ &mut self.relationships
+ }
}
let new_obligation = Obligation::new(
ObligationCause::dummy(),
param_env,
- new_trait_ref.without_const().to_predicate(self.tcx),
+ ty::Binder::dummy(new_trait_ref).without_const().to_predicate(self.tcx),
);
if self.predicate_must_hold_modulo_regions(&new_obligation) {
use crate::infer::{InferCtxt, TyOrConstInferVar};
+use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::obligation_forest::ProcessResult;
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
// A list of all obligations that have been registered with this
// fulfillment context.
predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
+
+ relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>,
+
// Should this fulfillment context register type-lives-for-region
// obligations on its parent infcx? In some cases, region
// obligations are either already known to hold (normalization) or
pub fn new() -> FulfillmentContext<'tcx> {
FulfillmentContext {
predicates: ObligationForest::new(),
+ relationships: FxHashMap::default(),
register_region_obligations: true,
usable_in_snapshot: false,
}
pub fn new_in_snapshot() -> FulfillmentContext<'tcx> {
FulfillmentContext {
predicates: ObligationForest::new(),
+ relationships: FxHashMap::default(),
register_region_obligations: true,
usable_in_snapshot: true,
}
pub fn new_ignoring_regions() -> FulfillmentContext<'tcx> {
FulfillmentContext {
predicates: ObligationForest::new(),
+ relationships: FxHashMap::default(),
register_region_obligations: false,
usable_in_snapshot: false,
}
assert!(!infcx.is_in_snapshot() || self.usable_in_snapshot);
+ super::relationships::update(self, infcx, &obligation);
+
self.predicates
.register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
}
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
self.predicates.map_pending_obligations(|o| o.obligation.clone())
}
+
+ fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships> {
+ &mut self.relationships
+ }
}
struct FulfillProcessor<'a, 'b, 'tcx> {
| ty::PredicateKind::Coerce(_)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..) => {
- let pred = infcx.replace_bound_vars_with_placeholders(binder);
+ let pred =
+ ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder));
ProcessResult::Changed(mk_pending(vec![
obligation.with(pred.to_predicate(self.selcx.tcx())),
]))
mod on_unimplemented;
mod project;
pub mod query;
+pub(crate) mod relationships;
mod select;
mod specialize;
mod structural_match;
infcx.tcx.def_path_str(def_id)
);
- let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) };
+ let trait_ref =
+ ty::Binder::dummy(ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) });
let obligation = Obligation {
param_env,
cause: ObligationCause::misc(span, hir::CRATE_HIR_ID),
trait_def_id: DefId,
supertraits_only: bool,
) -> SmallVec<[Span; 1]> {
- let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id));
+ let trait_ref = ty::TraitRef::identity(tcx, trait_def_id);
let predicates = if supertraits_only {
tcx.super_predicates_of(trait_def_id)
} else {
let trait_ref = ty::TraitRef::identity(tcx, trait_def_id);
- let trait_predicate = ty::Binder::dummy(ty::ExistentialPredicate::Trait(
- ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref),
- ));
+ let trait_predicate = trait_ref.map_bound(|trait_ref| {
+ ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref))
+ });
- let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref))
+ let mut associated_types = traits::supertraits(tcx, trait_ref)
.flat_map(|super_trait_ref| {
tcx.associated_items(super_trait_ref.def_id())
.in_definition_order()
let param_env = tcx.param_env(method.def_id);
// Self: Unsize<U>
- let unsize_predicate = ty::TraitRef {
+ let unsize_predicate = ty::Binder::dummy(ty::TraitRef {
def_id: unsize_did,
substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]),
- }
+ })
.without_const()
.to_predicate(tcx);
}
});
- ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate(tcx)
+ ty::Binder::dummy(ty::TraitRef { def_id: unsize_did, substs })
+ .without_const()
+ .to_predicate(tcx)
};
let caller_bounds: Vec<Predicate<'tcx>> = param_env
// Receiver: DispatchFromDyn<Receiver[Self => U]>
let obligation = {
- let predicate = ty::TraitRef {
+ let predicate = ty::Binder::dummy(ty::TraitRef {
def_id: dispatch_from_dyn_did,
substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]),
- }
+ })
.without_const()
.to_predicate(tcx);
// Compute supertraits of current trait lazily.
if self.supertraits.is_none() {
- let trait_ref =
- ty::Binder::dummy(ty::TraitRef::identity(self.tcx, self.trait_def_id));
+ let trait_ref = ty::TraitRef::identity(self.tcx, self.trait_def_id);
self.supertraits = Some(
traits::supertraits(self.tcx, trait_ref).map(|t| t.def_id()).collect(),
);
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
use rustc_middle::ty::subst::Subst;
-use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_span::symbol::sym;
use std::collections::BTreeMap;
// and a deferred predicate to resolve this when more type
// information is available.
- let tcx = selcx.infcx().tcx;
- let def_id = projection_ty.item_def_id;
- let ty_var = selcx.infcx().next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::NormalizeProjectionType,
- span: tcx.def_span(def_id),
- });
- let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, ty: ty_var });
- let obligation =
- Obligation::with_depth(cause, depth + 1, param_env, projection.to_predicate(tcx));
- obligations.push(obligation);
- ty_var
+ selcx.infcx().infer_projection(param_env, projection_ty, cause, depth + 1, obligations)
})
}
obligations: &mut Vec<PredicateObligation<'tcx>>,
) -> Result<Option<Ty<'tcx>>, InProgress> {
let infcx = selcx.infcx();
+ // Don't use the projection cache in intercrate mode -
+ // the `infcx` may be re-used between intercrate in non-intercrate
+ // mode, which could lead to using incorrect cache results.
+ let use_cache = !selcx.is_intercrate();
let projection_ty = infcx.resolve_vars_if_possible(projection_ty);
let cache_key = ProjectionCacheKey::new(projection_ty);
// bounds. It might be the case that we want two distinct caches,
// or else another kind of cache entry.
- let cache_result = infcx.inner.borrow_mut().projection_cache().try_start(cache_key);
+ let cache_result = if use_cache {
+ infcx.inner.borrow_mut().projection_cache().try_start(cache_key)
+ } else {
+ Ok(())
+ };
match cache_result {
Ok(()) => debug!("no cache"),
Err(ProjectionCacheEntry::Ambiguous) => {
// should ensure that, unless this happens within a snapshot that's
// rolled back, fulfillment or evaluation will notice the cycle.
- infcx.inner.borrow_mut().projection_cache().recur(cache_key);
+ if use_cache {
+ infcx.inner.borrow_mut().projection_cache().recur(cache_key);
+ }
return Err(InProgress);
}
Err(ProjectionCacheEntry::Recur) => {
.map_or(false, |res| res.must_apply_considering_regions())
});
- infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
+ if use_cache {
+ infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
+ }
obligations.extend(result.obligations);
Ok(Some(result.value))
}
Ok(ProjectedTy::NoProgress(projected_ty)) => {
debug!(?projected_ty, "opt_normalize_projection_type: no progress");
let result = Normalized { value: projected_ty, obligations: vec![] };
- infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
+ if use_cache {
+ infcx.inner.borrow_mut().projection_cache().insert_ty(cache_key, result.clone());
+ }
// No need to extend `obligations`.
Ok(Some(result.value))
}
Err(ProjectionTyError::TooManyCandidates) => {
debug!("opt_normalize_projection_type: too many candidates");
- infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
+ if use_cache {
+ infcx.inner.borrow_mut().projection_cache().ambiguous(cache_key);
+ }
Ok(None)
}
Err(ProjectionTyError::TraitSelectionError(_)) => {
// Trait`, which when processed will cause the error to be
// reported later
- infcx.inner.borrow_mut().projection_cache().error(cache_key);
+ if use_cache {
+ infcx.inner.borrow_mut().projection_cache().error(cache_key);
+ }
let result = normalize_to_error(selcx, param_env, projection_ty, cause, depth);
obligations.extend(result.obligations);
Ok(Some(result.value))
cause: ObligationCause<'tcx>,
depth: usize,
) -> NormalizedTy<'tcx> {
- let trait_ref = projection_ty.trait_ref(selcx.tcx()).to_poly_trait_ref();
+ let trait_ref = ty::Binder::dummy(projection_ty.trait_ref(selcx.tcx()));
let trait_obligation = Obligation {
cause,
recursion_depth: depth,
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
// start out by selecting the predicate `T as TraitRef<...>`:
- let poly_trait_ref = obligation.predicate.trait_ref(selcx.tcx()).to_poly_trait_ref();
+ let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx()));
let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate());
let _ = selcx.infcx().commit_if_ok(|_| {
let impl_source = match selcx.select(&trait_obligation) {
--- /dev/null
+use crate::infer::InferCtxt;
+use crate::traits::query::evaluate_obligation::InferCtxtExt;
+use crate::traits::{ObligationCause, PredicateObligation};
+use rustc_infer::traits::TraitEngine;
+use rustc_middle::ty::{self, ToPredicate};
+
+pub(crate) fn update<'tcx, T>(
+ engine: &mut T,
+ infcx: &InferCtxt<'_, 'tcx>,
+ obligation: &PredicateObligation<'tcx>,
+) where
+ T: TraitEngine<'tcx>,
+{
+ // (*) binder skipped
+ if let ty::PredicateKind::Trait(predicate) = obligation.predicate.kind().skip_binder() {
+ if let Some(ty) =
+ infcx.shallow_resolve(predicate.self_ty()).ty_vid().map(|t| infcx.root_var(t))
+ {
+ if infcx
+ .tcx
+ .lang_items()
+ .sized_trait()
+ .map_or(false, |st| st != predicate.trait_ref.def_id)
+ {
+ let new_self_ty = infcx.tcx.types.unit;
+
+ let trait_ref = ty::TraitRef {
+ substs: infcx
+ .tcx
+ .mk_substs_trait(new_self_ty, &predicate.trait_ref.substs[1..]),
+ ..predicate.trait_ref
+ };
+
+ // Then contstruct a new obligation with Self = () added
+ // to the ParamEnv, and see if it holds.
+ let o = rustc_infer::traits::Obligation::new(
+ ObligationCause::dummy(),
+ obligation.param_env,
+ obligation
+ .predicate
+ .kind()
+ .map_bound(|_| {
+ // (*) binder moved here
+ ty::PredicateKind::Trait(ty::TraitPredicate {
+ trait_ref,
+ constness: predicate.constness,
+ })
+ })
+ .to_predicate(infcx.tcx),
+ );
+ // Don't report overflow errors. Otherwise equivalent to may_hold.
+ if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) {
+ if result.may_apply() {
+ engine.relationships().entry(ty).or_default().self_in_trait = true;
+ }
+ }
+ }
+ }
+ }
+
+ if let ty::PredicateKind::Projection(predicate) = obligation.predicate.kind().skip_binder() {
+ // If the projection predicate (Foo::Bar == X) has X as a non-TyVid,
+ // we need to make it into one.
+ if let Some(vid) = predicate.ty.ty_vid() {
+ debug!("relationship: {:?}.output = true", vid);
+ engine.relationships().entry(vid).or_default().output = true;
+ }
+ }
+}
let placeholder_trait_predicate =
self.infcx().replace_bound_vars_with_placeholders(trait_predicate);
let placeholder_self_ty = placeholder_trait_predicate.self_ty();
+ let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
let (def_id, substs) = match *placeholder_self_ty.kind() {
ty::Projection(proj) => (proj.item_def_id, proj.substs),
ty::Opaque(def_id, substs) => (def_id, substs),
obligations.extend(self.infcx.commit_if_ok(|_| {
self.infcx
.at(&obligation.cause, obligation.param_env)
- .sup(placeholder_trait_predicate.trait_ref.to_poly_trait_ref(), candidate.value)
+ .sup(placeholder_trait_predicate.to_poly_trait_ref(), candidate.value)
.map(|InferOk { obligations, .. }| obligations)
.map_err(|_| Unimplemented)
})?);
obligations.push(Obligation::new(
obligation.cause.clone(),
obligation.param_env,
- ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)
+ ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind))
.to_predicate(self.tcx()),
));
}
);
// We can only make objects from sized types.
- let tr = ty::TraitRef::new(
+ let tr = ty::Binder::dummy(ty::TraitRef::new(
tcx.require_lang_item(LangItem::Sized, None),
tcx.mk_substs_trait(source, &[]),
- );
+ ));
nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx)));
// If the type is `Foo + 'a`, ensure that the type
self.infcx.tcx
}
+ pub fn is_intercrate(&self) -> bool {
+ self.intercrate
+ }
+
/// Returns `true` if the trait predicate is considerd `const` to this selection context.
pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
match pred.constness {
param_env: ty::ParamEnv<'tcx>,
cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
+ // Neither the global nor local cache is aware of intercrate
+ // mode, so don't do any caching. In particular, we might
+ // re-use the same `InferCtxt` with both an intercrate
+ // and non-intercrate `SelectionContext`
+ if self.intercrate {
+ return None;
+ }
let tcx = self.tcx();
let pred = &cache_fresh_trait_pred.skip_binder();
let trait_ref = pred.trait_ref;
&self,
result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>,
) -> bool {
+ // Neither the global nor local cache is aware of intercrate
+ // mode, so don't do any caching. In particular, we might
+ // re-use the same `InferCtxt` with both an intercrate
+ // and non-intercrate `SelectionContext`
+ if self.intercrate {
+ return false;
+ }
match result {
Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => !trait_ref.needs_infer(),
_ => true,
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st);
- self.nonblanket_impls.entry(st).or_default().push(impl_def_id)
+ self.non_blanket_impls.entry(st).or_default().push(impl_def_id)
} else {
debug!("insert_blindly: impl_def_id={:?} st=None", impl_def_id);
self.blanket_impls.push(impl_def_id)
let vec: &mut Vec<DefId>;
if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st);
- vec = self.nonblanket_impls.get_mut(&st).unwrap();
+ vec = self.non_blanket_impls.get_mut(&st).unwrap();
} else {
debug!("remove_existing: impl_def_id={:?} st=None", impl_def_id);
vec = &mut self.blanket_impls;
let self_ty = trait_ref.self_ty();
// FIXME: should postpone string formatting until we decide to actually emit.
- with_no_trimmed_paths(|| OverlapError {
- with_impl: possible_sibling,
- trait_desc: trait_ref.print_only_trait_path().to_string(),
- // Only report the `Self` type if it has at least
- // some outer concrete shell; otherwise, it's
- // not adding much information.
- self_desc: if self_ty.has_concrete_skeleton() {
- Some(self_ty.to_string())
- } else {
- None
- },
- intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
- involves_placeholder: overlap.involves_placeholder,
+ with_no_trimmed_paths(|| {
+ OverlapError {
+ with_impl: possible_sibling,
+ trait_desc: trait_ref.print_only_trait_path().to_string(),
+ // Only report the `Self` type if it has at least
+ // some outer concrete shell; otherwise, it's
+ // not adding much information.
+ self_desc: if self_ty.has_concrete_skeleton() {
+ Some(self_ty.to_string())
+ } else {
+ None
+ },
+ intercrate_ambiguity_causes: overlap.intercrate_ambiguity_causes,
+ involves_placeholder: overlap.involves_placeholder,
+ }
})
};
}
fn iter_children(children: &mut Children) -> impl Iterator<Item = DefId> + '_ {
- let nonblanket = children.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter());
+ let nonblanket = children.non_blanket_impls.iter().flat_map(|(_, v)| v.iter());
children.blanket_impls.iter().chain(nonblanket).cloned()
}
children: &mut Children,
st: SimplifiedType,
) -> impl Iterator<Item = DefId> + '_ {
- let nonblanket = children.nonblanket_impls.entry(st).or_default().iter();
+ let nonblanket = children.non_blanket_impls.entry(st).or_default().iter();
children.blanket_impls.iter().chain(nonblanket).cloned()
}
cause,
param_env,
recursion_depth,
- predicate: trait_ref.without_const().to_predicate(tcx),
+ predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx),
}
}
_ => return,
};
let fix_span =
- |impl_item_ref: &hir::ImplItemRef<'_>| match tcx.hir().impl_item(impl_item_ref.id).kind {
+ |impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind {
hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::TyAlias(ty) => ty.span,
_ => impl_item_ref.span,
};
new_cause,
depth,
param_env,
- ty::PredicateKind::WellFormed(arg).to_predicate(tcx),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx),
)
}),
);
cause.clone(),
depth,
param_env,
- ty::PredicateKind::WellFormed(arg).to_predicate(tcx),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx),
)
}),
);
cause,
self.recursion_depth,
self.param_env,
- trait_ref.without_const().to_predicate(self.infcx.tcx),
+ ty::Binder::dummy(trait_ref).without_const().to_predicate(self.infcx.tcx),
));
}
}
let obligations = self.nominal_obligations(uv.def.did, substs);
self.out.extend(obligations);
- let predicate = ty::PredicateKind::ConstEvaluatable(
+ let predicate = ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
ty::Unevaluated::new(uv.def, substs),
- )
+ ))
.to_predicate(self.tcx());
let cause = self.cause(traits::MiscObligation);
self.out.push(traits::Obligation::with_depth(
cause,
self.recursion_depth,
self.param_env,
- ty::PredicateKind::WellFormed(resolved_constant.into())
- .to_predicate(self.tcx()),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(
+ resolved_constant.into(),
+ ))
+ .to_predicate(self.tcx()),
));
}
}
cause,
depth,
param_env,
- ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(rty, r))
- .to_predicate(self.tcx()),
+ ty::Binder::dummy(ty::PredicateKind::TypeOutlives(
+ ty::OutlivesPredicate(rty, r),
+ ))
+ .to_predicate(self.tcx()),
));
}
}
cause.clone(),
depth,
param_env,
- ty::PredicateKind::ObjectSafe(did).to_predicate(tcx),
+ ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did))
+ .to_predicate(tcx),
)
}));
}
cause,
self.recursion_depth,
param_env,
- ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()))
+ .to_predicate(self.tcx()),
));
} else {
// Yes, resolved, proceed with the result.
[package]
name = "rustc_traits"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
tracing = "0.1"
self.relate(self_ty, Variance::Invariant, impl_self_ty)?;
self.prove_predicate(
- ty::PredicateKind::WellFormed(impl_self_ty.into()).to_predicate(self.tcx()),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()))
+ .to_predicate(self.tcx()),
span,
);
}
// type were ill-formed but did not appear in `ty`,
// which...could happen with normalization...
self.prove_predicate(
- ty::PredicateKind::WellFormed(ty.into()).to_predicate(self.tcx()),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(self.tcx()),
span,
);
Ok(())
[package]
name = "rustc_ty_utils"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
tracing = "0.1"
fn associated_item_from_impl_item_ref(
tcx: TyCtxt<'_>,
parent_def_id: LocalDefId,
- impl_item_ref: &hir::ImplItemRef<'_>,
+ impl_item_ref: &hir::ImplItemRef,
) -> ty::AssocItem {
let def_id = impl_item_ref.id.def_id;
let (kind, has_self) = match impl_item_ref.kind {
[package]
name = "rustc_type_ir"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
doctest = false
[package]
name = "rustc_typeck"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
test = false
let substs = InternalSubsts::for_item(tcx, def_id, |param, _| {
if let Some(i) = (param.index as usize).checked_sub(generics.parent_count) {
// Our own parameters are the resolved lifetimes.
- match param.kind {
- GenericParamDefKind::Lifetime
- if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] =>
- {
+ if let GenericParamDefKind::Lifetime = param.kind {
+ if let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] {
self.ast_region_to_region(lifetime, None).into()
+ } else {
+ bug!()
}
- _ => bug!(),
+ } else {
+ bug!()
}
} else {
match param.kind {
for o in obligations {
match o.predicate.kind().skip_binder() {
ty::PredicateKind::Trait(t) => {
- let pred = ty::PredicateKind::Trait(ty::TraitPredicate {
- trait_ref: ty::TraitRef {
- def_id: t.def_id(),
- substs: self.infcx.tcx.mk_substs_trait(outer_ty, &[]),
- },
- constness: t.constness,
- });
+ let pred =
+ ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
+ trait_ref: ty::TraitRef {
+ def_id: t.def_id(),
+ substs: self.infcx.tcx.mk_substs_trait(outer_ty, &[]),
+ },
+ constness: t.constness,
+ }));
let obl = Obligation::new(
o.cause.clone(),
self.param_env,
if borrow {
// Check for &self vs &mut self in the method signature. Since this is either
// the Fn or FnMut trait, it should be one of those.
- let (region, mutbl) =
- if let ty::Ref(r, _, mutbl) = method.sig.inputs()[0].kind() {
- (r, mutbl)
- } else {
- span_bug!(call_expr.span, "input to call/call_mut is not a ref?");
- };
+ let (region, mutbl) = if let ty::Ref(r, _, mutbl) =
+ method.sig.inputs()[0].kind()
+ {
+ (r, mutbl)
+ } else {
+ // The `fn`/`fn_mut` lang item is ill-formed, which should have
+ // caused an error elsewhere.
+ self.tcx
+ .sess
+ .delay_span_bug(call_expr.span, "input to call/call_mut is not a ref?");
+ return None;
+ };
let mutbl = match mutbl {
hir::Mutability::Not => AutoBorrowMutability::Not,
// we saw and assigning it to the expected return type. This isn't
// really expected to fail, since the coercions would have failed
// earlier when trying to find a LUB.
- //
- // However, the behavior around `!` is sort of complex. In the
- // event that the `actual_return_ty` comes back as `!`, that
- // indicates that the fn either does not return or "returns" only
- // values of type `!`. In this case, if there is an expected
- // return type that is *not* `!`, that should be ok. But if the
- // return type is being inferred, we want to "fallback" to `!`:
- //
- // let x = move || panic!();
- //
- // To allow for that, I am creating a type variable with diverging
- // fallback. This was deemed ever so slightly better than unifying
- // the return value with `!` because it allows for the caller to
- // make more assumptions about the return type (e.g., they could do
- //
- // let y: Option<u32> = Some(x());
- //
- // which would then cause this return type to become `u32`, not
- // `!`).
let coercion = fcx.ret_coercion.take().unwrap().into_inner();
let mut actual_return_ty = coercion.complete(&fcx);
- if actual_return_ty.is_never() {
- actual_return_ty = fcx.next_diverging_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::DivergingFn,
- span,
- });
+ debug!("actual_return_ty = {:?}", actual_return_ty);
+ if let ty::Dynamic(..) = declared_ret_ty.kind() {
+ // We have special-cased the case where the function is declared
+ // `-> dyn Foo` and we don't actually relate it to the
+ // `fcx.ret_coercion`, so just substitute a type variable.
+ actual_return_ty =
+ fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span });
+ debug!("actual_return_ty replaced with {:?}", actual_return_ty);
}
fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty);
full_impl_span: Span,
impl_id: LocalDefId,
impl_trait_ref: ty::TraitRef<'tcx>,
- impl_item_refs: &[hir::ImplItemRef<'_>],
+ impl_item_refs: &[hir::ImplItemRef],
) {
// If the trait reference itself is erroneous (so the compilation is going
// to fail), skip checking the items here -- the `impl_item` table in `tcx`
// Coercing from `!` to any type is allowed:
if a.is_never() {
- // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
- // type variable, we want `?T` to fallback to `!` if not
- // otherwise constrained. An example where this arises:
- //
- // let _: Option<?T> = Some({ return; });
- //
- // here, we would coerce from `!` to `?T`.
- return if b.is_ty_var() {
- // Micro-optimization: no need for this if `b` is
- // already resolved in some way.
- let diverging_ty = self.next_diverging_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::AdjustmentType,
- span: self.cause.span,
- });
- self.coerce_from_inference_variable(diverging_ty, b, simple(Adjust::NeverToAny))
- } else {
- success(simple(Adjust::NeverToAny)(b), b, vec![])
- };
+ return success(simple(Adjust::NeverToAny)(b), b, vec![]);
}
// Coercing *from* an unresolved inference variable means that
obligations.push(Obligation::new(
self.cause.clone(),
self.param_env,
- ty::PredicateKind::Coerce(ty::CoercePredicate {
+ ty::Binder::dummy(ty::PredicateKind::Coerce(ty::CoercePredicate {
a: source_ty,
b: target_ty,
- })
+ }))
.to_predicate(self.tcx()),
));
}
!self.typeck_results.borrow().adjustments().contains_key(expr.hir_id),
"expression with never type wound up being adjusted"
);
- let adj_ty = self.next_diverging_ty_var(TypeVariableOrigin {
+ let adj_ty = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::AdjustmentType,
span: expr.span,
});
use crate::check::FnCtxt;
-use rustc_infer::infer::type_variable::Diverging;
+use rustc_data_structures::{
+ fx::FxHashMap,
+ graph::WithSuccessors,
+ graph::{iterate::DepthFirstSearch, vec_graph::VecGraph},
+ stable_set::FxHashSet,
+};
use rustc_middle::ty::{self, Ty};
impl<'tcx> FnCtxt<'_, 'tcx> {
/// Performs type inference fallback, returning true if any fallback
/// occurs.
pub(super) fn type_inference_fallback(&self) -> bool {
+ debug!(
+ "type-inference-fallback start obligations: {:#?}",
+ self.fulfillment_cx.borrow_mut().pending_obligations()
+ );
+
// All type checking constraints were added, try to fallback unsolved variables.
self.select_obligations_where_possible(false, |_| {});
- let mut fallback_has_occurred = false;
+ debug!(
+ "type-inference-fallback post selection obligations: {:#?}",
+ self.fulfillment_cx.borrow_mut().pending_obligations()
+ );
+
+ // Check if we have any unsolved varibales. If not, no need for fallback.
+ let unsolved_variables = self.unsolved_variables();
+ if unsolved_variables.is_empty() {
+ return false;
+ }
+
+ let diverging_fallback = self.calculate_diverging_fallback(&unsolved_variables);
+
+ let mut fallback_has_occurred = false;
// We do fallback in two passes, to try to generate
// better error messages.
// The first time, we do *not* replace opaque types.
- for ty in &self.unsolved_variables() {
+ for ty in unsolved_variables {
debug!("unsolved_variable = {:?}", ty);
- fallback_has_occurred |= self.fallback_if_possible(ty);
+ fallback_has_occurred |= self.fallback_if_possible(ty, &diverging_fallback);
}
- // We now see if we can make progress. This might
- // cause us to unify inference variables for opaque types,
- // since we may have unified some other type variables
- // during the first phase of fallback.
- // This means that we only replace inference variables with their underlying
- // opaque types as a last resort.
+ // We now see if we can make progress. This might cause us to
+ // unify inference variables for opaque types, since we may
+ // have unified some other type variables during the first
+ // phase of fallback. This means that we only replace
+ // inference variables with their underlying opaque types as a
+ // last resort.
//
// In code like this:
//
//
// - Unconstrained floats are replaced with with `f64`.
//
- // - Non-numerics get replaced with `!` when `#![feature(never_type_fallback)]`
- // is enabled. Otherwise, they are replaced with `()`.
+ // - Non-numerics may get replaced with `()` or `!`, depending on
+ // how they were categorized by `calculate_diverging_fallback`
+ // (and the setting of `#![feature(never_type_fallback)]`).
+ //
+ // Fallback becomes very dubious if we have encountered
+ // type-checking errors. In that case, fallback to Error.
//
- // Fallback becomes very dubious if we have encountered type-checking errors.
- // In that case, fallback to Error.
// The return value indicates whether fallback has occurred.
- fn fallback_if_possible(&self, ty: Ty<'tcx>) -> bool {
+ fn fallback_if_possible(
+ &self,
+ ty: Ty<'tcx>,
+ diverging_fallback: &FxHashMap<Ty<'tcx>, Ty<'tcx>>,
+ ) -> bool {
// Careful: we do NOT shallow-resolve `ty`. We know that `ty`
- // is an unsolved variable, and we determine its fallback based
- // solely on how it was created, not what other type variables
- // it may have been unified with since then.
+ // is an unsolved variable, and we determine its fallback
+ // based solely on how it was created, not what other type
+ // variables it may have been unified with since then.
//
- // The reason this matters is that other attempts at fallback may
- // (in principle) conflict with this fallback, and we wish to generate
- // a type error in that case. (However, this actually isn't true right now,
- // because we're only using the builtin fallback rules. This would be
- // true if we were using user-supplied fallbacks. But it's still useful
- // to write the code to detect bugs.)
+ // The reason this matters is that other attempts at fallback
+ // may (in principle) conflict with this fallback, and we wish
+ // to generate a type error in that case. (However, this
+ // actually isn't true right now, because we're only using the
+ // builtin fallback rules. This would be true if we were using
+ // user-supplied fallbacks. But it's still useful to write the
+ // code to detect bugs.)
//
- // (Note though that if we have a general type variable `?T` that is then unified
- // with an integer type variable `?I` that ultimately never gets
- // resolved to a special integral type, `?T` is not considered unsolved,
- // but `?I` is. The same is true for float variables.)
+ // (Note though that if we have a general type variable `?T`
+ // that is then unified with an integer type variable `?I`
+ // that ultimately never gets resolved to a special integral
+ // type, `?T` is not considered unsolved, but `?I` is. The
+ // same is true for float variables.)
let fallback = match ty.kind() {
_ if self.is_tainted_by_errors() => self.tcx.ty_error(),
ty::Infer(ty::IntVar(_)) => self.tcx.types.i32,
ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64,
- _ => match self.type_var_diverges(ty) {
- Diverging::Diverges => self.tcx.mk_diverging_default(),
- Diverging::NotDiverging => return false,
+ _ => match diverging_fallback.get(&ty) {
+ Some(&fallback_ty) => fallback_ty,
+ None => return false,
},
};
debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
true
}
- /// Second round of fallback: Unconstrained type variables
- /// created from the instantiation of an opaque
- /// type fall back to the opaque type itself. This is a
- /// somewhat incomplete attempt to manage "identity passthrough"
- /// for `impl Trait` types.
+ /// Second round of fallback: Unconstrained type variables created
+ /// from the instantiation of an opaque type fall back to the
+ /// opaque type itself. This is a somewhat incomplete attempt to
+ /// manage "identity passthrough" for `impl Trait` types.
///
/// For example, in this code:
///
return false;
}
}
+
+ /// The "diverging fallback" system is rather complicated. This is
+ /// a result of our need to balance 'do the right thing' with
+ /// backwards compatibility.
+ ///
+ /// "Diverging" type variables are variables created when we
+ /// coerce a `!` type into an unbound type variable `?X`. If they
+ /// never wind up being constrained, the "right and natural" thing
+ /// is that `?X` should "fallback" to `!`. This means that e.g. an
+ /// expression like `Some(return)` will ultimately wind up with a
+ /// type like `Option<!>` (presuming it is not assigned or
+ /// constrained to have some other type).
+ ///
+ /// However, the fallback used to be `()` (before the `!` type was
+ /// added). Moreover, there are cases where the `!` type 'leaks
+ /// out' from dead code into type variables that affect live
+ /// code. The most common case is something like this:
+ ///
+ /// ```rust
+ /// match foo() {
+ /// 22 => Default::default(), // call this type `?D`
+ /// _ => return, // return has type `!`
+ /// } // call the type of this match `?M`
+ /// ```
+ ///
+ /// Here, coercing the type `!` into `?M` will create a diverging
+ /// type variable `?X` where `?X <: ?M`. We also have that `?D <:
+ /// ?M`. If `?M` winds up unconstrained, then `?X` will
+ /// fallback. If it falls back to `!`, then all the type variables
+ /// will wind up equal to `!` -- this includes the type `?D`
+ /// (since `!` doesn't implement `Default`, we wind up a "trait
+ /// not implemented" error in code like this). But since the
+ /// original fallback was `()`, this code used to compile with `?D
+ /// = ()`. This is somewhat surprising, since `Default::default()`
+ /// on its own would give an error because the types are
+ /// insufficiently constrained.
+ ///
+ /// Our solution to this dilemma is to modify diverging variables
+ /// so that they can *either* fallback to `!` (the default) or to
+ /// `()` (the backwards compatibility case). We decide which
+ /// fallback to use based on whether there is a coercion pattern
+ /// like this:
+ ///
+ /// ```
+ /// ?Diverging -> ?V
+ /// ?NonDiverging -> ?V
+ /// ?V != ?NonDiverging
+ /// ```
+ ///
+ /// Here `?Diverging` represents some diverging type variable and
+ /// `?NonDiverging` represents some non-diverging type
+ /// variable. `?V` can be any type variable (diverging or not), so
+ /// long as it is not equal to `?NonDiverging`.
+ ///
+ /// Intuitively, what we are looking for is a case where a
+ /// "non-diverging" type variable (like `?M` in our example above)
+ /// is coerced *into* some variable `?V` that would otherwise
+ /// fallback to `!`. In that case, we make `?V` fallback to `!`,
+ /// along with anything that would flow into `?V`.
+ ///
+ /// The algorithm we use:
+ /// * Identify all variables that are coerced *into* by a
+ /// diverging variable. Do this by iterating over each
+ /// diverging, unsolved variable and finding all variables
+ /// reachable from there. Call that set `D`.
+ /// * Walk over all unsolved, non-diverging variables, and find
+ /// any variable that has an edge into `D`.
+ fn calculate_diverging_fallback(
+ &self,
+ unsolved_variables: &[Ty<'tcx>],
+ ) -> FxHashMap<Ty<'tcx>, Ty<'tcx>> {
+ debug!("calculate_diverging_fallback({:?})", unsolved_variables);
+
+ let relationships = self.fulfillment_cx.borrow_mut().relationships().clone();
+
+ // Construct a coercion graph where an edge `A -> B` indicates
+ // a type variable is that is coerced
+ let coercion_graph = self.create_coercion_graph();
+
+ // Extract the unsolved type inference variable vids; note that some
+ // unsolved variables are integer/float variables and are excluded.
+ let unsolved_vids = unsolved_variables.iter().filter_map(|ty| ty.ty_vid());
+
+ // Compute the diverging root vids D -- that is, the root vid of
+ // those type variables that (a) are the target of a coercion from
+ // a `!` type and (b) have not yet been solved.
+ //
+ // These variables are the ones that are targets for fallback to
+ // either `!` or `()`.
+ let diverging_roots: FxHashSet<ty::TyVid> = self
+ .diverging_type_vars
+ .borrow()
+ .iter()
+ .map(|&ty| self.infcx.shallow_resolve(ty))
+ .filter_map(|ty| ty.ty_vid())
+ .map(|vid| self.infcx.root_var(vid))
+ .collect();
+ debug!(
+ "calculate_diverging_fallback: diverging_type_vars={:?}",
+ self.diverging_type_vars.borrow()
+ );
+ debug!("calculate_diverging_fallback: diverging_roots={:?}", diverging_roots);
+
+ // Find all type variables that are reachable from a diverging
+ // type variable. These will typically default to `!`, unless
+ // we find later that they are *also* reachable from some
+ // other type variable outside this set.
+ let mut roots_reachable_from_diverging = DepthFirstSearch::new(&coercion_graph);
+ let mut diverging_vids = vec![];
+ let mut non_diverging_vids = vec![];
+ for unsolved_vid in unsolved_vids {
+ let root_vid = self.infcx.root_var(unsolved_vid);
+ debug!(
+ "calculate_diverging_fallback: unsolved_vid={:?} root_vid={:?} diverges={:?}",
+ unsolved_vid,
+ root_vid,
+ diverging_roots.contains(&root_vid),
+ );
+ if diverging_roots.contains(&root_vid) {
+ diverging_vids.push(unsolved_vid);
+ roots_reachable_from_diverging.push_start_node(root_vid);
+
+ debug!(
+ "calculate_diverging_fallback: root_vid={:?} reaches {:?}",
+ root_vid,
+ coercion_graph.depth_first_search(root_vid).collect::<Vec<_>>()
+ );
+
+ // drain the iterator to visit all nodes reachable from this node
+ roots_reachable_from_diverging.complete_search();
+ } else {
+ non_diverging_vids.push(unsolved_vid);
+ }
+ }
+
+ debug!(
+ "calculate_diverging_fallback: roots_reachable_from_diverging={:?}",
+ roots_reachable_from_diverging,
+ );
+
+ // Find all type variables N0 that are not reachable from a
+ // diverging variable, and then compute the set reachable from
+ // N0, which we call N. These are the *non-diverging* type
+ // variables. (Note that this set consists of "root variables".)
+ let mut roots_reachable_from_non_diverging = DepthFirstSearch::new(&coercion_graph);
+ for &non_diverging_vid in &non_diverging_vids {
+ let root_vid = self.infcx.root_var(non_diverging_vid);
+ if roots_reachable_from_diverging.visited(root_vid) {
+ continue;
+ }
+ roots_reachable_from_non_diverging.push_start_node(root_vid);
+ roots_reachable_from_non_diverging.complete_search();
+ }
+ debug!(
+ "calculate_diverging_fallback: roots_reachable_from_non_diverging={:?}",
+ roots_reachable_from_non_diverging,
+ );
+
+ debug!("inherited: {:#?}", self.inh.fulfillment_cx.borrow_mut().pending_obligations());
+ debug!("obligations: {:#?}", self.fulfillment_cx.borrow_mut().pending_obligations());
+ debug!("relationships: {:#?}", relationships);
+
+ // For each diverging variable, figure out whether it can
+ // reach a member of N. If so, it falls back to `()`. Else
+ // `!`.
+ let mut diverging_fallback = FxHashMap::default();
+ diverging_fallback.reserve(diverging_vids.len());
+ for &diverging_vid in &diverging_vids {
+ let diverging_ty = self.tcx.mk_ty_var(diverging_vid);
+ let root_vid = self.infcx.root_var(diverging_vid);
+ let can_reach_non_diverging = coercion_graph
+ .depth_first_search(root_vid)
+ .any(|n| roots_reachable_from_non_diverging.visited(n));
+
+ let mut relationship = ty::FoundRelationships { self_in_trait: false, output: false };
+
+ for (vid, rel) in relationships.iter() {
+ if self.infcx.root_var(*vid) == root_vid {
+ relationship.self_in_trait |= rel.self_in_trait;
+ relationship.output |= rel.output;
+ }
+ }
+
+ if relationship.self_in_trait && relationship.output {
+ // This case falls back to () to ensure that the code pattern in
+ // src/test/ui/never_type/fallback-closure-ret.rs continues to
+ // compile when never_type_fallback is enabled.
+ //
+ // This rule is not readily explainable from first principles,
+ // but is rather intended as a patchwork fix to ensure code
+ // which compiles before the stabilization of never type
+ // fallback continues to work.
+ //
+ // Typically this pattern is encountered in a function taking a
+ // closure as a parameter, where the return type of that closure
+ // (checked by `relationship.output`) is expected to implement
+ // some trait (checked by `relationship.self_in_trait`). This
+ // can come up in non-closure cases too, so we do not limit this
+ // rule to specifically `FnOnce`.
+ //
+ // When the closure's body is something like `panic!()`, the
+ // return type would normally be inferred to `!`. However, it
+ // needs to fall back to `()` in order to still compile, as the
+ // trait is specifically implemented for `()` but not `!`.
+ //
+ // For details on the requirements for these relationships to be
+ // set, see the relationship finding module in
+ // compiler/rustc_trait_selection/src/traits/relationships.rs.
+ debug!("fallback to () - found trait and projection: {:?}", diverging_vid);
+ diverging_fallback.insert(diverging_ty, self.tcx.types.unit);
+ } else if can_reach_non_diverging {
+ debug!("fallback to () - reached non-diverging: {:?}", diverging_vid);
+ diverging_fallback.insert(diverging_ty, self.tcx.types.unit);
+ } else {
+ debug!("fallback to ! - all diverging: {:?}", diverging_vid);
+ diverging_fallback.insert(diverging_ty, self.tcx.mk_diverging_default());
+ }
+ }
+
+ diverging_fallback
+ }
+
+ /// Returns a graph whose nodes are (unresolved) inference variables and where
+ /// an edge `?A -> ?B` indicates that the variable `?A` is coerced to `?B`.
+ fn create_coercion_graph(&self) -> VecGraph<ty::TyVid> {
+ let pending_obligations = self.fulfillment_cx.borrow_mut().pending_obligations();
+ debug!("create_coercion_graph: pending_obligations={:?}", pending_obligations);
+ let coercion_edges: Vec<(ty::TyVid, ty::TyVid)> = pending_obligations
+ .into_iter()
+ .filter_map(|obligation| {
+ // The predicates we are looking for look like `Coerce(?A -> ?B)`.
+ // They will have no bound variables.
+ obligation.predicate.kind().no_bound_vars()
+ })
+ .filter_map(|atom| {
+ // We consider both subtyping and coercion to imply 'flow' from
+ // some position in the code `a` to a different position `b`.
+ // This is then used to determine which variables interact with
+ // live code, and as such must fall back to `()` to preserve
+ // soundness.
+ //
+ // In practice currently the two ways that this happens is
+ // coercion and subtyping.
+ let (a, b) = if let ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) = atom {
+ (a, b)
+ } else if let ty::PredicateKind::Subtype(ty::SubtypePredicate {
+ a_is_expected: _,
+ a,
+ b,
+ }) = atom
+ {
+ (a, b)
+ } else {
+ return None;
+ };
+
+ let a_vid = self.root_vid(a)?;
+ let b_vid = self.root_vid(b)?;
+ Some((a_vid, b_vid))
+ })
+ .collect();
+ debug!("create_coercion_graph: coercion_edges={:?}", coercion_edges);
+ let num_ty_vars = self.infcx.num_ty_vars();
+ VecGraph::new(num_ty_vars, coercion_edges)
+ }
+
+ /// If `ty` is an unresolved type variable, returns its root vid.
+ fn root_vid(&self, ty: Ty<'tcx>) -> Option<ty::TyVid> {
+ Some(self.infcx.root_var(self.infcx.shallow_resolve(ty).ty_vid()?))
+ }
}
return;
}
+ for a in &adj {
+ if let Adjust::NeverToAny = a.kind {
+ if a.target.is_ty_var() {
+ self.diverging_type_vars.borrow_mut().insert(a.target);
+ debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target);
+ }
+ }
+ }
+
let autoborrow_mut = adj.iter().any(|adj| {
matches!(
adj,
self.register_predicate(traits::Obligation::new(
cause,
self.param_env,
- ty::PredicateKind::WellFormed(arg).to_predicate(self.tcx),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx),
));
}
debug!("suggest_missing_return_type: return type {:?}", ty);
debug!("suggest_missing_return_type: expected type {:?}", ty);
let bound_vars = self.tcx.late_bound_vars(fn_id);
- let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
+ let ty = Binder::bind_with_vars(ty, bound_vars);
let ty = self.normalize_associated_types_in(sp, ty);
+ let ty = self.tcx.erase_late_bound_regions(ty);
if self.can_coerce(expected, ty) {
err.span_label(sp, format!("expected `{}` because of return type", expected));
return true;
use super::FnCtxt;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
+use rustc_errors::pluralize;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind};
use rustc_middle::middle::region::{self, YieldData};
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::symbol::sym;
use rustc_span::Span;
use smallvec::SmallVec;
+use tracing::debug;
struct InteriorVisitor<'a, 'tcx> {
fcx: &'a FnCtxt<'a, 'tcx>,
/// that they may succeed the said yield point in the post-order.
guard_bindings: SmallVec<[SmallVec<[HirId; 4]>; 1]>,
guard_bindings_set: HirIdSet,
+ linted_values: HirIdSet,
}
impl<'a, 'tcx> InteriorVisitor<'a, 'tcx> {
fn record(
&mut self,
ty: Ty<'tcx>,
+ hir_id: HirId,
scope: Option<region::Scope>,
expr: Option<&'tcx Expr<'tcx>>,
source_span: Span,
} else {
// Insert the type into the ordered set.
let scope_span = scope.map(|s| s.span(self.fcx.tcx, self.region_scope_tree));
+
+ if !self.linted_values.contains(&hir_id) {
+ check_must_not_suspend_ty(
+ self.fcx,
+ ty,
+ hir_id,
+ SuspendCheckData {
+ expr,
+ source_span,
+ yield_span: yield_data.span,
+ plural_len: 1,
+ ..Default::default()
+ },
+ );
+ self.linted_values.insert(hir_id);
+ }
+
self.types.insert(ty::GeneratorInteriorTypeCause {
span: source_span,
ty: &ty,
prev_unresolved_span: None,
guard_bindings: <_>::default(),
guard_bindings_set: <_>::default(),
+ linted_values: <_>::default(),
};
intravisit::walk_body(&mut visitor, body);
if let PatKind::Binding(..) = pat.kind {
let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id);
let ty = self.fcx.typeck_results.borrow().pat_ty(pat);
- self.record(ty, Some(scope), None, pat.span, false);
+ self.record(ty, pat.hir_id, Some(scope), None, pat.span, false);
}
}
// If there are adjustments, then record the final type --
// this is the actual value that is being produced.
if let Some(adjusted_ty) = self.fcx.typeck_results.borrow().expr_ty_adjusted_opt(expr) {
- self.record(adjusted_ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern);
+ self.record(
+ adjusted_ty,
+ expr.hir_id,
+ scope,
+ Some(expr),
+ expr.span,
+ guard_borrowing_from_pattern,
+ );
}
// Also record the unadjusted type (which is the only type if
tcx.mk_region(ty::RegionKind::ReErased),
ty::TypeAndMut { ty, mutbl: hir::Mutability::Not },
);
- self.record(ref_ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern);
+ self.record(
+ ref_ty,
+ expr.hir_id,
+ scope,
+ Some(expr),
+ expr.span,
+ guard_borrowing_from_pattern,
+ );
}
- self.record(ty, scope, Some(expr), expr.span, guard_borrowing_from_pattern);
+ self.record(
+ ty,
+ expr.hir_id,
+ scope,
+ Some(expr),
+ expr.span,
+ guard_borrowing_from_pattern,
+ );
} else {
self.fcx.tcx.sess.delay_span_bug(expr.span, "no type for node");
}
}
}
}
+
+#[derive(Default)]
+pub struct SuspendCheckData<'a, 'tcx> {
+ expr: Option<&'tcx Expr<'tcx>>,
+ source_span: Span,
+ yield_span: Span,
+ descr_pre: &'a str,
+ descr_post: &'a str,
+ plural_len: usize,
+}
+
+// Returns whether it emitted a diagnostic or not
+// Note that this fn and the proceding one are based on the code
+// for creating must_use diagnostics
+//
+// Note that this technique was chosen over things like a `Suspend` marker trait
+// as it is simpler and has precendent in the compiler
+pub fn check_must_not_suspend_ty<'tcx>(
+ fcx: &FnCtxt<'_, 'tcx>,
+ ty: Ty<'tcx>,
+ hir_id: HirId,
+ data: SuspendCheckData<'_, 'tcx>,
+) -> bool {
+ if ty.is_unit()
+ // FIXME: should this check `is_ty_uninhabited_from`. This query is not available in this stage
+ // of typeck (before ReVar and RePlaceholder are removed), but may remove noise, like in
+ // `must_use`
+ // || fcx.tcx.is_ty_uninhabited_from(fcx.tcx.parent_module(hir_id).to_def_id(), ty, fcx.param_env)
+ {
+ return false;
+ }
+
+ let plural_suffix = pluralize!(data.plural_len);
+
+ match *ty.kind() {
+ ty::Adt(..) if ty.is_box() => {
+ let boxed_ty = ty.boxed_ty();
+ let descr_pre = &format!("{}boxed ", data.descr_pre);
+ check_must_not_suspend_ty(fcx, boxed_ty, hir_id, SuspendCheckData { descr_pre, ..data })
+ }
+ ty::Adt(def, _) => check_must_not_suspend_def(fcx.tcx, def.did, hir_id, data),
+ // FIXME: support adding the attribute to TAITs
+ ty::Opaque(def, _) => {
+ let mut has_emitted = false;
+ for &(predicate, _) in fcx.tcx.explicit_item_bounds(def) {
+ // We only look at the `DefId`, so it is safe to skip the binder here.
+ if let ty::PredicateKind::Trait(ref poly_trait_predicate) =
+ predicate.kind().skip_binder()
+ {
+ let def_id = poly_trait_predicate.trait_ref.def_id;
+ let descr_pre = &format!("{}implementer{} of ", data.descr_pre, plural_suffix);
+ if check_must_not_suspend_def(
+ fcx.tcx,
+ def_id,
+ hir_id,
+ SuspendCheckData { descr_pre, ..data },
+ ) {
+ has_emitted = true;
+ break;
+ }
+ }
+ }
+ has_emitted
+ }
+ ty::Dynamic(binder, _) => {
+ let mut has_emitted = false;
+ for predicate in binder.iter() {
+ if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
+ let def_id = trait_ref.def_id;
+ let descr_post = &format!(" trait object{}{}", plural_suffix, data.descr_post);
+ if check_must_not_suspend_def(
+ fcx.tcx,
+ def_id,
+ hir_id,
+ SuspendCheckData { descr_post, ..data },
+ ) {
+ has_emitted = true;
+ break;
+ }
+ }
+ }
+ has_emitted
+ }
+ ty::Tuple(ref tys) => {
+ let mut has_emitted = false;
+ let spans = if let Some(hir::ExprKind::Tup(comps)) = data.expr.map(|e| &e.kind) {
+ debug_assert_eq!(comps.len(), tys.len());
+ comps.iter().map(|e| e.span).collect()
+ } else {
+ vec![]
+ };
+ for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() {
+ let descr_post = &format!(" in tuple element {}", i);
+ let span = *spans.get(i).unwrap_or(&data.source_span);
+ if check_must_not_suspend_ty(
+ fcx,
+ ty,
+ hir_id,
+ SuspendCheckData { descr_post, source_span: span, ..data },
+ ) {
+ has_emitted = true;
+ }
+ }
+ has_emitted
+ }
+ ty::Array(ty, len) => {
+ let descr_pre = &format!("{}array{} of ", data.descr_pre, plural_suffix);
+ check_must_not_suspend_ty(
+ fcx,
+ ty,
+ hir_id,
+ SuspendCheckData {
+ descr_pre,
+ plural_len: len.try_eval_usize(fcx.tcx, fcx.param_env).unwrap_or(0) as usize
+ + 1,
+ ..data
+ },
+ )
+ }
+ _ => false,
+ }
+}
+
+fn check_must_not_suspend_def(
+ tcx: TyCtxt<'_>,
+ def_id: DefId,
+ hir_id: HirId,
+ data: SuspendCheckData<'_, '_>,
+) -> bool {
+ for attr in tcx.get_attrs(def_id).iter() {
+ if attr.has_name(sym::must_not_suspend) {
+ tcx.struct_span_lint_hir(
+ rustc_session::lint::builtin::MUST_NOT_SUSPEND,
+ hir_id,
+ data.source_span,
+ |lint| {
+ let msg = format!(
+ "{}`{}`{} held across a suspend point, but should not be",
+ data.descr_pre,
+ tcx.def_path_str(def_id),
+ data.descr_post,
+ );
+ let mut err = lint.build(&msg);
+
+ // add span pointing to the offending yield/await
+ err.span_label(data.yield_span, "the value is held across this suspend point");
+
+ // Add optional reason note
+ if let Some(note) = attr.value_str() {
+ // FIXME(guswynn): consider formatting this better
+ err.span_note(data.source_span, ¬e.as_str());
+ }
+
+ // Add some quick suggestions on what to do
+ // FIXME: can `drop` work as a suggestion here as well?
+ err.span_help(
+ data.source_span,
+ "consider using a block (`{ ... }`) \
+ to shrink the value's scope, ending before the suspend point",
+ );
+
+ err.emit();
+ },
+ );
+
+ return true;
+ }
+ }
+ false
+}
use super::callee::DeferredCallResolution;
use super::MaybeInProgressTables;
+use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::{DefIdMap, LocalDefId};
use rustc_hir::HirIdMap;
pub(super) constness: hir::Constness,
pub(super) body_id: Option<hir::BodyId>,
+
+ /// Whenever we introduce an adjustment from `!` into a type variable,
+ /// we record that type variable here. This is later used to inform
+ /// fallback. See the `fallback` module for details.
+ pub(super) diverging_type_vars: RefCell<FxHashSet<Ty<'tcx>>>,
}
impl<'a, 'tcx> Deref for Inherited<'a, 'tcx> {
deferred_call_resolutions: RefCell::new(Default::default()),
deferred_cast_checks: RefCell::new(Vec::new()),
deferred_generator_interiors: RefCell::new(Vec::new()),
+ diverging_type_vars: RefCell::new(Default::default()),
constness,
body_id,
}
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::GenericParamDefKind;
-use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TypeFoldable, WithConstness};
+use rustc_middle::ty::{self, ToPredicate, Ty, TypeFoldable, WithConstness};
use rustc_span::symbol::Ident;
use rustc_span::Span;
use rustc_trait_selection::traits;
let trait_ref = ty::TraitRef::new(trait_def_id, substs);
// Construct an obligation
- let poly_trait_ref = trait_ref.to_poly_trait_ref();
+ let poly_trait_ref = ty::Binder::dummy(trait_ref);
let obligation = traits::Obligation::misc(
span,
self.body_id,
obligations.push(traits::Obligation::new(
cause,
self.param_env,
- ty::PredicateKind::WellFormed(method_ty.into()).to_predicate(tcx),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())).to_predicate(tcx),
));
let callee = MethodCallee { def_id, substs: trait_ref.substs, sig: fn_sig };
use rustc_middle::middle::stability;
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::GenericParamDefKind;
-use rustc_middle::ty::{
- self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
-};
+use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::lev_distance::{find_best_match_for_name, lev_distance};
if self.tcx.is_trait_alias(trait_def_id) {
// For trait aliases, assume all super-traits are relevant.
- let bounds = iter::once(trait_ref.to_poly_trait_ref());
+ let bounds = iter::once(ty::Binder::dummy(trait_ref));
self.elaborate_bounds(bounds, |this, new_trait_ref, item| {
let new_trait_ref = this.erase_late_bound_regions(new_trait_ref);
trait_ref: ty::TraitRef<'tcx>,
) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> {
let cause = traits::ObligationCause::misc(self.span, self.body_id);
- let predicate = trait_ref.to_poly_trait_ref().to_poly_trait_predicate();
+ let predicate = ty::Binder::dummy(trait_ref).to_poly_trait_predicate();
let obligation = traits::Obligation::new(cause, self.param_env, predicate);
traits::SelectionContext::new(self).select(&obligation)
}
}
}
}
- let predicate = trait_ref.without_const().to_predicate(self.tcx);
+ let predicate =
+ ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx);
let obligation = traits::Obligation::new(cause, self.param_env, predicate);
if !self.predicate_may_hold(&obligation) {
result = ProbeResult::NoMatch;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::ty::fast_reject::simplify_type;
use rustc_middle::ty::print::with_crate_prefix;
-use rustc_middle::ty::{
- self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
-};
+use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_span::lev_distance;
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{source_map, FileName, Span};
.into()],
);
let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
- let poly_trait_ref = trait_ref.to_poly_trait_ref();
+ let poly_trait_ref = ty::Binder::dummy(trait_ref);
let obligation = Obligation::misc(
span,
self.body_id,
}
}
- debug!("For closure={:?}, min_captures={:#?}", closure_def_id, root_var_min_capture_list);
+ debug!(
+ "For closure={:?}, min_captures before sorting={:?}",
+ closure_def_id, root_var_min_capture_list
+ );
+
+ // Now that we have the minimized list of captures, sort the captures by field id.
+ // This causes the closure to capture the upvars in the same order as the fields are
+ // declared which is also the drop order. Thus, in situations where we capture all the
+ // fields of some type, the obserable drop order will remain the same as it previously
+ // was even though we're dropping each capture individually.
+ // See https://github.com/rust-lang/project-rfc-2229/issues/42 and
+ // `src/test/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs`.
+ for (_, captures) in &mut root_var_min_capture_list {
+ captures.sort_by(|capture1, capture2| {
+ for (p1, p2) in capture1.place.projections.iter().zip(&capture2.place.projections) {
+ // We do not need to look at the `Projection.ty` fields here because at each
+ // step of the iteration, the projections will either be the same and therefore
+ // the types must be as well or the current projection will be different and
+ // we will return the result of comparing the field indexes.
+ match (p1.kind, p2.kind) {
+ // Paths are the same, continue to next loop.
+ (ProjectionKind::Deref, ProjectionKind::Deref) => {}
+ (ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _))
+ if i1 == i2 => {}
+
+ // Fields are different, compare them.
+ (ProjectionKind::Field(i1, _), ProjectionKind::Field(i2, _)) => {
+ return i1.cmp(&i2);
+ }
+
+ // We should have either a pair of `Deref`s or a pair of `Field`s.
+ // Anything else is a bug.
+ (
+ l @ (ProjectionKind::Deref | ProjectionKind::Field(..)),
+ r @ (ProjectionKind::Deref | ProjectionKind::Field(..)),
+ ) => bug!(
+ "ProjectionKinds Deref and Field were mismatched: ({:?}, {:?})",
+ l,
+ r
+ ),
+ (
+ l
+ @
+ (ProjectionKind::Index
+ | ProjectionKind::Subslice
+ | ProjectionKind::Deref
+ | ProjectionKind::Field(..)),
+ r
+ @
+ (ProjectionKind::Index
+ | ProjectionKind::Subslice
+ | ProjectionKind::Deref
+ | ProjectionKind::Field(..)),
+ ) => bug!(
+ "ProjectionKinds Index or Subslice were unexpected: ({:?}, {:?})",
+ l,
+ r
+ ),
+ }
+ }
+
+ unreachable!(
+ "we captured two identical projections: capture1 = {:?}, capture2 = {:?}",
+ capture1, capture2
+ );
+ });
+ }
+
+ debug!(
+ "For closure={:?}, min_captures after sorting={:#?}",
+ closure_def_id, root_var_min_capture_list
+ );
typeck_results.closure_min_captures.insert(closure_def_id, root_var_min_capture_list);
}
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
use rustc_ast as ast;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_hir::ItemKind;
use rustc_middle::hir::map as hir_map;
-use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
+use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
-use rustc_trait_selection::opaque_types::may_define_opaque_type;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc};
/// We do this check as a pre-pass before checking fn bodies because if these constraints are
/// not included it frequently leads to confusing errors in fn bodies. So it's better to check
/// the types first.
+#[instrument(skip(tcx), level = "debug")]
pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let item = tcx.hir().expect_item(hir_id);
debug!(
- "check_item_well_formed(it.def_id={:?}, it.name={})",
- item.def_id,
- tcx.def_path_str(def_id.to_def_id())
+ ?item.def_id,
+ item.name = ? tcx.def_path_str(def_id.to_def_id())
);
match item.kind {
};
check_object_unsafe_self_trait_by_name(tcx, &trait_item);
check_associated_item(tcx, trait_item.hir_id(), span, method_sig);
+
+ let encl_trait_hir_id = tcx.hir().get_parent_item(hir_id);
+ let encl_trait = tcx.hir().expect_item(encl_trait_hir_id);
+ let encl_trait_def_id = encl_trait.def_id.to_def_id();
+ let fn_lang_item_name = if Some(encl_trait_def_id) == tcx.lang_items().fn_trait() {
+ Some("fn")
+ } else if Some(encl_trait_def_id) == tcx.lang_items().fn_mut_trait() {
+ Some("fn_mut")
+ } else {
+ None
+ };
+
+ if let (Some(fn_lang_item_name), "call") =
+ (fn_lang_item_name, trait_item.ident.name.to_ident_string().as_str())
+ {
+ // We are looking at the `call` function of the `fn` or `fn_mut` lang item.
+ // Do some rudimentary sanity checking to avoid an ICE later (issue #83471).
+ if let Some(hir::FnSig { decl, span, .. }) = method_sig {
+ if let &[self_ty, _] = &decl.inputs {
+ if !matches!(self_ty.kind, hir::TyKind::Rptr(_, _)) {
+ tcx.sess
+ .struct_span_err(
+ self_ty.span,
+ &format!(
+ "first argument of `call` in `{}` lang item must be a reference",
+ fn_lang_item_name
+ ),
+ )
+ .emit();
+ }
+ } else {
+ tcx.sess
+ .struct_span_err(
+ *span,
+ &format!(
+ "`call` function in `{}` lang item takes exactly two arguments",
+ fn_lang_item_name
+ ),
+ )
+ .emit();
+ }
+ } else {
+ tcx.sess
+ .struct_span_err(
+ trait_item.span,
+ &format!(
+ "`call` trait item in `{}` lang item must be a function",
+ fn_lang_item_name
+ ),
+ )
+ .emit();
+ }
+ }
}
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
fcx.register_predicate(traits::Obligation::new(
cause,
fcx.param_env,
- ty::PredicateKind::ConstEvaluatable(ty::Unevaluated::new(
+ ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ty::Unevaluated::new(
ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
discr_substs,
- ))
+ )))
.to_predicate(tcx),
));
}
});
}
+#[instrument(skip(tcx, item))]
fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
- debug!("check_trait: {:?}", item.def_id);
+ debug!(?item.def_id);
let trait_def = tcx.trait_def(item.def_id);
if trait_def.is_marker
}
/// Checks where-clauses and inline bounds that are declared on `def_id`.
+#[instrument(skip(fcx), level = "debug")]
fn check_where_clauses<'tcx, 'fcx>(
fcx: &FnCtxt<'fcx, 'tcx>,
span: Span,
def_id: DefId,
return_ty: Option<(Ty<'tcx>, Span)>,
) {
- debug!("check_where_clauses(def_id={:?}, return_ty={:?})", def_id, return_ty);
let tcx = fcx.tcx;
let predicates = tcx.predicates_of(def_id);
let predicates = predicates.instantiate_identity(tcx);
- if let Some((mut return_ty, span)) = return_ty {
+ if let Some((return_ty, _)) = return_ty {
if return_ty.has_infer_types_or_consts() {
fcx.select_obligations_where_possible(false, |_| {});
- return_ty = fcx.resolve_vars_if_possible(return_ty);
}
- check_opaque_types(fcx, def_id.expect_local(), span, return_ty);
}
let predicates = fcx.normalize_associated_types_in(span, predicates);
- debug!("check_where_clauses: predicates={:?}", predicates.predicates);
+ debug!(?predicates.predicates);
assert_eq!(predicates.predicates.len(), predicates.spans.len());
let wf_obligations =
iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| {
check_where_clauses(fcx, span, def_id, Some((sig.output(), hir_decl.output.span())));
}
-/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
-/// laid for "higher-order pattern unification".
-/// This ensures that inference is tractable.
-/// In particular, definitions of opaque types can only use other generics as arguments,
-/// and they cannot repeat an argument. Example:
-///
-/// ```rust
-/// type Foo<A, B> = impl Bar<A, B>;
-///
-/// // Okay -- `Foo` is applied to two distinct, generic types.
-/// fn a<T, U>() -> Foo<T, U> { .. }
-///
-/// // Not okay -- `Foo` is applied to `T` twice.
-/// fn b<T>() -> Foo<T, T> { .. }
-///
-/// // Not okay -- `Foo` is applied to a non-generic type.
-/// fn b<T>() -> Foo<T, u32> { .. }
-/// ```
-///
-fn check_opaque_types<'fcx, 'tcx>(
- fcx: &FnCtxt<'fcx, 'tcx>,
- fn_def_id: LocalDefId,
- span: Span,
- ty: Ty<'tcx>,
-) {
- trace!("check_opaque_types(fn_def_id={:?}, ty={:?})", fn_def_id, ty);
- let tcx = fcx.tcx;
-
- ty.fold_with(&mut ty::fold::BottomUpFolder {
- tcx,
- ty_op: |ty| {
- if let ty::Opaque(def_id, substs) = *ty.kind() {
- trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs);
- let generics = tcx.generics_of(def_id);
-
- let opaque_hir_id = if let Some(local_id) = def_id.as_local() {
- tcx.hir().local_def_id_to_hir_id(local_id)
- } else {
- // Opaque types from other crates won't have defining uses in this crate.
- return ty;
- };
- if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) =
- tcx.hir().expect_item(opaque_hir_id).kind
- {
- // No need to check return position impl trait (RPIT)
- // because for type and const parameters they are correct
- // by construction: we convert
- //
- // fn foo<P0..Pn>() -> impl Trait
- //
- // into
- //
- // type Foo<P0...Pn>
- // fn foo<P0..Pn>() -> Foo<P0...Pn>.
- //
- // For lifetime parameters we convert
- //
- // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
- //
- // into
- //
- // type foo::<'p0..'pn>::Foo<'q0..'qm>
- // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
- //
- // which would error here on all of the `'static` args.
- return ty;
- }
- if !may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
- return ty;
- }
- trace!("check_opaque_types: may define, generics={:#?}", generics);
- let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
- for (i, arg) in substs.iter().enumerate() {
- let arg_is_param = match arg.unpack() {
- GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
-
- GenericArgKind::Lifetime(region) if let ty::ReStatic = region => {
- tcx.sess
- .struct_span_err(
- span,
- "non-defining opaque type use in defining scope",
- )
- .span_label(
- tcx.def_span(generics.param_at(i, tcx).def_id),
- "cannot use static lifetime; use a bound lifetime \
- instead or remove the lifetime parameter from the \
- opaque type",
- )
- .emit();
- continue;
- }
-
- GenericArgKind::Lifetime(_) => true,
-
- GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
- };
-
- if arg_is_param {
- seen_params.entry(arg).or_default().push(i);
- } else {
- // Prevent `fn foo() -> Foo<u32>` from being defining.
- let opaque_param = generics.param_at(i, tcx);
- tcx.sess
- .struct_span_err(span, "non-defining opaque type use in defining scope")
- .span_note(
- tcx.def_span(opaque_param.def_id),
- &format!(
- "used non-generic {} `{}` for generic parameter",
- opaque_param.kind.descr(),
- arg,
- ),
- )
- .emit();
- }
- } // for (arg, param)
-
- for (_, indices) in seen_params {
- if indices.len() > 1 {
- let descr = generics.param_at(indices[0], tcx).kind.descr();
- let spans: Vec<_> = indices
- .into_iter()
- .map(|i| tcx.def_span(generics.param_at(i, tcx).def_id))
- .collect();
- tcx.sess
- .struct_span_err(span, "non-defining opaque type use in defining scope")
- .span_note(spans, &format!("{} used multiple times", descr))
- .emit();
- }
- }
- } // if let Opaque
- ty
- },
- lt_op: |lt| lt,
- ct_op: |ct| ct,
- });
-}
-
const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
`self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
of the previous types except `Self`)";
cause: ObligationCause<'tcx>,
receiver_ty: Ty<'tcx>,
) -> bool {
- let trait_ref = ty::TraitRef {
+ let trait_ref = ty::Binder::dummy(ty::TraitRef {
def_id: receiver_trait_def_id,
substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]),
- };
+ });
let obligation = traits::Obligation::new(
cause,
hir_visit::NestedVisitorMap::OnlyBodies(self.tcx.hir())
}
+ #[instrument(skip(self, i), level = "debug")]
fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
- debug!("visit_item: {:?}", i);
+ trace!(?i);
self.tcx.ensure().check_item_well_formed(i.def_id);
hir_visit::walk_item(self, i);
}
+ #[instrument(skip(self, trait_item), level = "debug")]
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
- debug!("visit_trait_item: {:?}", trait_item);
+ trace!(?trait_item);
self.tcx.ensure().check_trait_item_well_formed(trait_item.def_id);
hir_visit::walk_trait_item(self, trait_item);
}
+ #[instrument(skip(self, impl_item), level = "debug")]
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
- debug!("visit_impl_item: {:?}", impl_item);
+ trace!(?impl_item);
self.tcx.ensure().check_impl_item_well_formed(impl_item.def_id);
hir_visit::walk_impl_item(self, impl_item);
}
lang: &str,
ty: &str,
span: Span,
- assoc_items: &[hir::ImplItemRef<'_>],
+ assoc_items: &[hir::ImplItemRef],
) {
match (lang_def_id, lang_def_id2) {
(Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => {
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::Discr;
use rustc_middle::ty::util::IntTypeExt;
-use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, Ty, TyCtxt};
use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness};
use rustc_session::lint;
use rustc_session::parse::feature_err;
match item.kind {
ItemKind::Impl(ref impl_) => {
if impl_.defaultness.is_default() {
- is_default_impl_trait = tcx.impl_trait_ref(def_id);
+ is_default_impl_trait = tcx
+ .impl_trait_ref(def_id)
+ .map(|trait_ref| ty::Binder::dummy(trait_ref));
}
&impl_.generics
}
// (see below). Recall that a default impl is not itself an impl, but rather a
// set of defaults that can be incorporated into another impl.
if let Some(trait_ref) = is_default_impl_trait {
- predicates.insert((
- trait_ref.to_poly_trait_ref().without_const().to_predicate(tcx),
- tcx.def_span(def_id),
- ));
+ predicates.insert((trait_ref.without_const().to_predicate(tcx), tcx.def_span(def_id)));
}
// Collect the region predicates that were declared inline as
}
_ => bug!(),
};
- let pred = ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
- .to_predicate(icx.tcx);
+ let pred = ty::Binder::dummy(ty::PredicateKind::RegionOutlives(
+ ty::OutlivesPredicate(r1, r2),
+ ))
+ .to_predicate(icx.tcx);
(pred, span)
}))
assert_eq!(uv.promoted, None);
let span = self.tcx.hir().span(c.hir_id);
self.preds.insert((
- ty::PredicateKind::ConstEvaluatable(uv.shrink()).to_predicate(self.tcx),
+ ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink()))
+ .to_predicate(self.tcx),
span,
));
}
} else if attr.has_name(sym::thread_local) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
} else if attr.has_name(sym::track_caller) {
- if tcx.is_closure(id) || tcx.fn_sig(id).abi() != abi::Abi::Rust {
+ if !tcx.is_closure(id) && tcx.fn_sig(id).abi() != abi::Abi::Rust {
struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI")
.emit();
}
+ if tcx.is_closure(id) && !tcx.features().closure_track_caller {
+ feature_err(
+ &tcx.sess.parse_sess,
+ sym::closure_track_caller,
+ attr.span,
+ "`#[track_caller]` on closures is currently unstable",
+ )
+ .emit();
+ }
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
} else if attr.has_name(sym::export_name) {
if let Some(s) = attr.value_str() {
-use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, ErrorReported, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::Visitor;
use rustc_hir::{HirId, Node};
use rustc_middle::hir::map::Map;
-use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, SubstsRef};
+use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
use rustc_span::symbol::Ident;
}
#[instrument(skip(tcx), level = "debug")]
+/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
+/// laid for "higher-order pattern unification".
+/// This ensures that inference is tractable.
+/// In particular, definitions of opaque types can only use other generics as arguments,
+/// and they cannot repeat an argument. Example:
+///
+/// ```rust
+/// type Foo<A, B> = impl Bar<A, B>;
+///
+/// // Okay -- `Foo` is applied to two distinct, generic types.
+/// fn a<T, U>() -> Foo<T, U> { .. }
+///
+/// // Not okay -- `Foo` is applied to `T` twice.
+/// fn b<T>() -> Foo<T, T> { .. }
+///
+/// // Not okay -- `Foo` is applied to a non-generic type.
+/// fn b<T>() -> Foo<T, u32> { .. }
+/// ```
+///
fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
use rustc_hir::{Expr, ImplItem, Item, TraitItem};
// FIXME(oli-obk): trace the actual span from inference to improve errors.
let span = self.tcx.def_span(def_id);
- // HACK(eddyb) this check shouldn't be needed, as `wfcheck`
- // performs the same checks, in theory, but I've kept it here
- // using `delay_span_bug`, just in case `wfcheck` slips up.
- let opaque_generics = self.tcx.generics_of(self.def_id);
- let mut used_params: FxHashSet<_> = FxHashSet::default();
- for (i, arg) in opaque_type_key.substs.iter().enumerate() {
- let arg_is_param = match arg.unpack() {
- GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
- GenericArgKind::Lifetime(lt) => {
- matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_))
- }
- GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
- };
-
- if arg_is_param {
- if !used_params.insert(arg) {
- // There was already an entry for `arg`, meaning a generic parameter
- // was used twice.
- self.tcx.sess.delay_span_bug(
- span,
- &format!(
- "defining opaque type use restricts opaque \
- type by using the generic parameter `{}` twice",
- arg,
- ),
- );
- }
- } else {
- let param = opaque_generics.param_at(i, self.tcx);
- self.tcx.sess.delay_span_bug(
- span,
- &format!(
- "defining opaque type use does not fully define opaque type: \
- generic parameter `{}` is specified as concrete {} `{}`",
- param.name,
- param.kind.descr(),
- arg,
- ),
- );
- }
- }
-
if let Some((prev_span, prev_ty)) = self.found {
- if *concrete_type != prev_ty {
+ if *concrete_type != prev_ty && !(*concrete_type, prev_ty).references_error() {
debug!(?span);
// Found different concrete types for the opaque type.
let mut err = self.tcx.sess.struct_span_err(
traits::Obligation::new(
cause,
self.param_env,
- ty::PredicateKind::WellFormed(tcx_ty.into()).to_predicate(self.tcx),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into()))
+ .to_predicate(self.tcx),
),
);
fn enforce_impl_params_are_constrained(
tcx: TyCtxt<'_>,
impl_def_id: LocalDefId,
- impl_item_refs: &[hir::ImplItemRef<'_>],
+ impl_item_refs: &[hir::ImplItemRef],
) {
// Every lifetime used in an associated type must be constrained.
let impl_self_ty = tcx.type_of(impl_def_id);
}
/// Enforce that we do not have two items in an impl with the same name.
-fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef<'_>]) {
+fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplItemRef]) {
let mut seen_type_items = FxHashMap::default();
let mut seen_value_items = FxHashMap::default();
for impl_item_ref in impl_item_refs {
|(ty::OutlivesPredicate(kind1, region2), &span)| {
match kind1.unpack() {
GenericArgKind::Type(ty1) => Some((
- ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty1, region2))
- .to_predicate(tcx),
+ ty::Binder::dummy(ty::PredicateKind::TypeOutlives(
+ ty::OutlivesPredicate(ty1, region2),
+ ))
+ .to_predicate(tcx),
span,
)),
GenericArgKind::Lifetime(region1) => Some((
- ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
- region1, region2,
+ ty::Binder::dummy(ty::PredicateKind::RegionOutlives(
+ ty::OutlivesPredicate(region1, region2),
))
.to_predicate(tcx),
span,
use crate::structured_errors::StructuredDiagnostic;
use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId};
use rustc_hir as hir;
+use rustc_middle::hir::map::fn_sig;
use rustc_middle::middle::resolve_lifetime::LifetimeScopeForPath;
use rustc_middle::ty::{self as ty, TyCtxt};
use rustc_session::Session;
&self,
num_params_to_take: usize,
) -> String {
+ let fn_sig = self.tcx.hir().get_if_local(self.def_id).and_then(|node| fn_sig(node));
+ let is_used_in_input = |def_id| {
+ fn_sig.map_or(false, |fn_sig| {
+ fn_sig.decl.inputs.iter().any(|ty| match ty.kind {
+ hir::TyKind::Path(hir::QPath::Resolved(
+ None,
+ hir::Path { res: hir::def::Res::Def(_, id), .. },
+ )) if *id == def_id => true,
+ _ => false,
+ })
+ })
+ };
self.gen_params
.params
.iter()
.skip(self.params_offset + self.num_provided_type_or_const_args())
.take(num_params_to_take)
- .map(|param| param.name.to_string())
+ .map(|param| match param.kind {
+ // This is being infered from the item's inputs, no need to set it.
+ ty::GenericParamDefKind::Type { .. } if is_used_in_input(param.def_id) => {
+ "_".to_string()
+ }
+ _ => param.name.to_string(),
+ })
.collect::<Vec<_>>()
.join(", ")
}
}
/// The allocator for unique pointers.
-// This function must not unwind. If it does, MIR codegen will fail.
#[cfg(all(not(no_global_oom_handling), not(test)))]
#[lang = "exchange_malloc"]
#[inline]
}
}
+#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Box<T> {
/// Creates a `Box<T>`, with the `Default` value for T.
}
}
+#[cfg(not(no_global_oom_handling))]
#[stable(feature = "box_from_array", since = "1.45.0")]
impl<T, const N: usize> From<[T; N]> for Box<[T]> {
/// Converts a `[T; N]` into a `Box<[T]>`
//! Insertion and popping the largest element have *O*(log(*n*)) time complexity.
//! Checking the largest element is *O*(1). Converting a vector to a binary heap
//! can be done in-place, and has *O*(*n*) complexity. A binary heap can also be
-//! converted to a sorted vector in-place, allowing it to be used for an *O*(*n* \* log(*n*))
+//! converted to a sorted vector in-place, allowing it to be used for an *O*(*n* * log(*n*))
//! in-place heapsort.
//!
//! # Examples
/// This will be a max-heap.
///
/// It is a logic error for an item to be modified in such a way that the
-/// item's ordering relative to any other item, as determined by the `Ord`
+/// item's ordering relative to any other item, as determined by the [`Ord`]
/// trait, changes while it is in the heap. This is normally only possible
-/// through `Cell`, `RefCell`, global state, I/O, or unsafe code. The
+/// through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. The
/// behavior resulting from such a logic error is not specified, but will
/// not result in undefined behavior. This could include panics, incorrect
/// results, aborts, memory leaks, and non-termination.
///
/// ## Min-heap
///
-/// Either `std::cmp::Reverse` or a custom `Ord` implementation can be used to
+/// Either [`core::cmp::Reverse`] or a custom [`Ord`] implementation can be used to
/// make `BinaryHeap` a min-heap. This makes `heap.pop()` return the smallest
/// value instead of the greatest one.
///
///
/// # Time complexity
///
-/// | [push] | [pop] | [peek]/[peek\_mut] |
-/// |--------|-----------|--------------------|
-/// | O(1)~ | *O*(log(*n*)) | *O*(1) |
+/// | [push] | [pop] | [peek]/[peek\_mut] |
+/// |---------|---------------|--------------------|
+/// | *O*(1)~ | *O*(log(*n*)) | *O*(1) |
///
/// The value for `push` is an expected cost; the method documentation gives a
/// more detailed analysis.
///
+/// [`core::cmp::Reverse`]: core::cmp::Reverse
+/// [`Ord`]: core::cmp::Ord
+/// [`Cell`]: core::cell::Cell
+/// [`RefCell`]: core::cell::RefCell
/// [push]: BinaryHeap::push
/// [pop]: BinaryHeap::pop
/// [peek]: BinaryHeap::peek
/// An owning iterator over the elements of a `BinaryHeap`.
///
/// This `struct` is created by [`BinaryHeap::into_iter()`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
+/// (provided by the [`IntoIterator`] trait). See its documentation for more.
///
/// [`into_iter`]: BinaryHeap::into_iter
+/// [`IntoIterator`]: core::iter::IntoIterator
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct IntoIter<T> {
/// An owning iterator over the entries of a `BTreeMap`.
///
/// This `struct` is created by the [`into_iter`] method on [`BTreeMap`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
+/// (provided by the [`IntoIterator`] trait). See its documentation for more.
///
/// [`into_iter`]: IntoIterator::into_iter
+/// [`IntoIterator`]: core::iter::IntoIterator
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_insignificant_dtor]
pub struct IntoIter<K, V> {
/// An owning iterator over the items of a `BTreeSet`.
///
/// This `struct` is created by the [`into_iter`] method on [`BTreeSet`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
+/// (provided by the [`IntoIterator`] trait). See its documentation for more.
///
/// [`into_iter`]: BTreeSet#method.into_iter
+/// [`IntoIterator`]: core::iter::IntoIterator
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct IntoIter<T> {
/// let list = LinkedList::from([1, 2, 3]);
/// ```
///
-/// NOTE: It is almost always better to use `Vec` or `VecDeque` because
+/// NOTE: It is almost always better to use [`Vec`] or [`VecDeque`] because
/// array-based containers are generally faster,
/// more memory efficient, and make better use of CPU cache.
+///
+/// [`Vec`]: crate::vec::Vec
+/// [`VecDeque`]: super::vec_deque::VecDeque
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "LinkedList")]
#[rustc_insignificant_dtor]
/// An owning iterator over the elements of a `LinkedList`.
///
/// This `struct` is created by the [`into_iter`] method on [`LinkedList`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
+/// (provided by the [`IntoIterator`] trait). See its documentation for more.
///
/// [`into_iter`]: LinkedList::into_iter
+/// [`IntoIterator`]: core::iter::IntoIterator
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<T> {
/// Returns `true` if the `LinkedList` contains an element equal to the
/// given value.
///
+ /// This operation should compute in *O*(*n*) time.
+ ///
/// # Examples
///
/// ```
/// Provides a reference to the front element, or `None` if the list is
/// empty.
///
+ /// This operation should compute in *O*(1) time.
+ ///
/// # Examples
///
/// ```
/// Provides a mutable reference to the front element, or `None` if the list
/// is empty.
///
+ /// This operation should compute in *O*(1) time.
+ ///
/// # Examples
///
/// ```
/// Provides a reference to the back element, or `None` if the list is
/// empty.
///
+ /// This operation should compute in *O*(1) time.
+ ///
/// # Examples
///
/// ```
/// Provides a mutable reference to the back element, or `None` if the list
/// is empty.
///
+ /// This operation should compute in *O*(1) time.
+ ///
/// # Examples
///
/// ```
/// An owning iterator over the elements of a `VecDeque`.
///
/// This `struct` is created by the [`into_iter`] method on [`VecDeque`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
+/// (provided by the [`IntoIterator`] trait). See its documentation for more.
///
/// [`into_iter`]: VecDeque::into_iter
+/// [`IntoIterator`]: core::iter::IntoIterator
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<
//! provides some helper methods.
//!
//! Additionally, the return value of this function is [`fmt::Result`] which is a
-//! type alias of [`Result`]`<(), `[`std::fmt::Error`]`>`. Formatting implementations
+//! type alias of <code>[Result]<(), [std::fmt::Error]></code>. Formatting implementations
//! should ensure that they propagate errors from the [`Formatter`] (e.g., when
//! calling [`write!`]). However, they should never return errors spuriously. That
//! is, a formatting implementation must and may only return an error if the
//! it would internally pass around this structure until it has been determined
//! where output should go to.
//!
-//! [`fmt::Result`]: Result
-//! [`Result`]: core::result::Result
-//! [`std::fmt::Error`]: Error
-//! [`write!`]: core::write
-//! [`write`]: core::write
-//! [`format!`]: crate::format
-//! [`to_string`]: crate::string::ToString
-//! [`writeln!`]: core::writeln
+//! [`fmt::Result`]: Result "fmt::Result"
+//! [Result]: core::result::Result "std::result::Result"
+//! [std::fmt::Error]: Error "fmt::Error"
+//! [`write`]: write() "fmt::write"
+//! [`to_string`]: crate::string::ToString::to_string "ToString::to_string"
//! [`write_fmt`]: ../../std/io/trait.Write.html#method.write_fmt
//! [`std::io::Write`]: ../../std/io/trait.Write.html
-//! [`print!`]: ../../std/macro.print.html
-//! [`println!`]: ../../std/macro.println.html
-//! [`eprint!`]: ../../std/macro.eprint.html
-//! [`eprintln!`]: ../../std/macro.eprintln.html
-//! [`format_args!`]: core::format_args
-//! [`fmt::Arguments`]: Arguments
-//! [`format`]: crate::format
+//! [`print!`]: ../../std/macro.print.html "print!"
+//! [`println!`]: ../../std/macro.println.html "println!"
+//! [`eprint!`]: ../../std/macro.eprint.html "eprint!"
+//! [`eprintln!`]: ../../std/macro.eprintln.html "eprintln!"
+//! [`fmt::Arguments`]: Arguments "fmt::Arguments"
+//! [`format`]: format() "fmt::format"
#![stable(feature = "rust1", since = "1.0.0")]
/// Consumes the `Rc`, returning the wrapped pointer.
///
/// To avoid a memory leak the pointer must be converted back to an `Rc` using
- /// [`Rc::from_raw`][from_raw].
- ///
- /// [from_raw]: Rc::from_raw
+ /// [`Rc::from_raw`].
///
/// # Examples
///
/// and alignment as `T`. This is trivially true if `U` is `T`.
/// Note that if `U` is not `T` but has the same size and alignment, this is
/// basically like transmuting references of different types. See
- /// [`mem::transmute`][transmute] for more information on what
+ /// [`mem::transmute`] for more information on what
/// restrictions apply in this case.
///
/// The user of `from_raw` has to make sure a specific value of `T` is only
/// even if the returned `Rc<T>` is never accessed.
///
/// [into_raw]: Rc::into_raw
- /// [transmute]: core::mem::transmute
///
/// # Examples
///
/// assert!(Rc::ptr_eq(&five, &same_five));
/// assert!(!Rc::ptr_eq(&five, &other_five));
/// ```
- ///
- /// [`ptr::eq`]: core::ptr::eq
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
this.ptr.as_ptr() == other.ptr.as_ptr()
}
/// `Weak` is a version of [`Rc`] that holds a non-owning reference to the
/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak`
-/// pointer, which returns an [`Option`]`<`[`Rc`]`<T>>`.
+/// pointer, which returns an <code>[Option]<[Rc]\<T>></code>.
///
/// Since a `Weak` reference does not count towards ownership, it will not
/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no
/// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
/// ```
///
- /// [`null`]: core::ptr::null
+ /// [`null`]: ptr::null
#[stable(feature = "rc_as_ptr", since = "1.45.0")]
pub fn as_ptr(&self) -> *const T {
let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);
/// let third = Rc::downgrade(&third_rc);
/// assert!(!first.ptr_eq(&third));
/// ```
- ///
- /// [`ptr::eq`]: core::ptr::eq
#[inline]
#[stable(feature = "weak_ptr_eq", since = "1.39.0")]
pub fn ptr_eq(&self, other: &Self) -> bool {
/// Constructs a new `Weak<T>`, without allocating any memory.
/// Calling [`upgrade`] on the return value always gives [`None`].
///
- /// [`None`]: Option
/// [`upgrade`]: Weak::upgrade
///
/// # Examples
///
/// # Examples
///
-/// You can create a `String` from [a literal string][`str`] with [`String::from`]:
+/// You can create a `String` from [a literal string][`&str`] with [`String::from`]:
///
/// [`String::from`]: From::from
///
/// println!("The first letter of s is {}", s[0]); // ERROR!!!
/// ```
///
-/// [`OsString`]: ../../std/ffi/struct.OsString.html
+/// [`OsString`]: ../../std/ffi/struct.OsString.html "ffi::OsString"
///
/// Indexing is intended to be a constant-time operation, but UTF-8 encoding
/// does not allow us to do this. Furthermore, it's not clear what sort of
///
/// # Deref
///
-/// `String`s implement [`Deref`]`<Target=str>`, and so inherit all of [`str`]'s
+/// `String` implements <code>[Deref]<Target = [str]></code>, and so inherits all of [`str`]'s
/// methods. In addition, this means that you can pass a `String` to a
/// function which takes a [`&str`] by using an ampersand (`&`):
///
/// to explicitly extract the string slice containing the string. The second
/// way changes `example_func(&example_string);` to
/// `example_func(&*example_string);`. In this case we are dereferencing a
-/// `String` to a [`str`][`&str`], then referencing the [`str`][`&str`] back to
+/// `String` to a [`str`], then referencing the [`str`] back to
/// [`&str`]. The second way is more idiomatic, however both work to do the
/// conversion explicitly rather than relying on the implicit conversion.
///
///
/// Here, there's no need to allocate more memory inside the loop.
///
-/// [`str`]: prim@str
-/// [`&str`]: prim@str
-/// [`Deref`]: core::ops::Deref
+/// [str]: prim@str "str"
+/// [`str`]: prim@str "str"
+/// [`&str`]: prim@str "&str"
+/// [Deref]: core::ops::Deref "ops::Deref"
+/// [`Deref`]: core::ops::Deref "ops::Deref"
/// [`as_str()`]: String::as_str
#[derive(PartialOrd, Eq, Ord)]
#[cfg_attr(not(test), rustc_diagnostic_item = "string_type")]
/// an analogue to `FromUtf8Error`, and you can get one from a `FromUtf8Error`
/// through the [`utf8_error`] method.
///
-/// [`Utf8Error`]: core::str::Utf8Error
-/// [`std::str`]: core::str
-/// [`&str`]: prim@str
-/// [`utf8_error`]: Self::utf8_error
+/// [`Utf8Error`]: str::Utf8Error "std::str::Utf8Error"
+/// [`std::str`]: core::str "std::str"
+/// [`&str`]: prim@str "&str"
+/// [`utf8_error`]: FromUtf8Error::utf8_error
///
/// # Examples
///
/// with this error.
///
/// [`from_utf8_unchecked`]: String::from_utf8_unchecked
- /// [`Vec<u8>`]: crate::vec::Vec
- /// [`&str`]: prim@str
+ /// [`Vec<u8>`]: crate::vec::Vec "Vec"
+ /// [`&str`]: prim@str "&str"
/// [`into_bytes`]: String::into_bytes
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
/// it's already valid UTF-8, we don't need a new allocation. This return
/// type allows us to handle both cases.
///
- /// [`Cow<'a, str>`]: crate::borrow::Cow
+ /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow"
///
/// # Examples
///
/// conversion requires a memory allocation.
///
/// [`from_utf8_lossy`]: String::from_utf8_lossy
- /// [`Cow<'a, str>`]: crate::borrow::Cow
+ /// [`Cow<'a, str>`]: crate::borrow::Cow "borrow::Cow"
/// [U+FFFD]: core::char::REPLACEMENT_CHARACTER
///
/// # Examples
unsafe { self.as_mut_vec() }.splice((start, end), replace_with.bytes());
}
- /// Converts this `String` into a [`Box`]`<`[`str`]`>`.
+ /// Converts this `String` into a <code>[Box]<[str]></code>.
///
/// This will drop any excess capacity.
///
- /// [`str`]: prim@str
+ /// [str]: prim@str "str"
///
/// # Examples
///
/// an analogue to `FromUtf8Error`. See its documentation for more details
/// on using it.
///
- /// [`std::str`]: core::str
- /// [`&str`]: prim@str
+ /// [`std::str`]: core::str "std::str"
+ /// [`&str`]: prim@str "&str"
///
/// # Examples
///
///
/// This alias exists for backwards compatibility, and may be eventually deprecated.
///
-/// [`Infallible`]: core::convert::Infallible
+/// [`Infallible`]: core::convert::Infallible "convert::Infallible"
#[stable(feature = "str_parse_error", since = "1.5.0")]
pub type ParseError = core::convert::Infallible;
/// assert_eq!(Cow::from("eggplant"), Cow::Borrowed("eggplant"));
/// ```
///
- /// [`Borrowed`]: crate::borrow::Cow::Borrowed
+ /// [`Borrowed`]: crate::borrow::Cow::Borrowed "borrow::Cow::Borrowed"
#[inline]
fn from(s: &'a str) -> Cow<'a, str> {
Cow::Borrowed(s)
/// assert_eq!(Cow::from(s), Cow::<'static, str>::Owned(s2));
/// ```
///
- /// [`Owned`]: crate::borrow::Cow::Owned
+ /// [`Owned`]: crate::borrow::Cow::Owned "borrow::Cow::Owned"
#[inline]
fn from(s: String) -> Cow<'a, str> {
Cow::Owned(s)
/// assert_eq!(Cow::from(&s), Cow::Borrowed("eggplant"));
/// ```
///
- /// [`Borrowed`]: crate::borrow::Cow::Borrowed
+ /// [`Borrowed`]: crate::borrow::Cow::Borrowed "borrow::Cow::Borrowed"
#[inline]
fn from(s: &'a String) -> Cow<'a, str> {
Cow::Borrowed(s.as_str())
/// first: after all, isn't the point of `Arc<T>` thread safety? The key is
/// this: `Arc<T>` makes it thread safe to have multiple ownership of the same
/// data, but it doesn't add thread safety to its data. Consider
-/// `Arc<`[`RefCell<T>`]`>`. [`RefCell<T>`] isn't [`Sync`], and if `Arc<T>` was always
-/// [`Send`], `Arc<`[`RefCell<T>`]`>` would be as well. But then we'd have a problem:
+/// <code>Arc<[RefCell\<T>]></code>. [`RefCell<T>`] isn't [`Sync`], and if `Arc<T>` was always
+/// [`Send`], <code>Arc<[RefCell\<T>]></code> would be as well. But then we'd have a problem:
/// [`RefCell<T>`] is not thread safe; it keeps track of the borrowing count using
/// non-atomic operations.
///
/// [deref]: core::ops::Deref
/// [downgrade]: Arc::downgrade
/// [upgrade]: Weak::upgrade
+/// [RefCell\<T>]: core::cell::RefCell
/// [`RefCell<T>`]: core::cell::RefCell
/// [`std::sync`]: ../../std/sync/index.html
/// [`Arc::clone(&from)`]: Arc::clone
///
/// Sharing a mutable [`AtomicUsize`]:
///
-/// [`AtomicUsize`]: core::sync::atomic::AtomicUsize
+/// [`AtomicUsize`]: core::sync::atomic::AtomicUsize "sync::atomic::AtomicUsize"
///
/// ```no_run
/// use std::sync::Arc;
/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the
/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak`
-/// pointer, which returns an [`Option`]`<`[`Arc`]`<T>>`.
+/// pointer, which returns an <code>[Option]<[Arc]\<T>></code>.
///
/// Since a `Weak` reference does not count towards ownership, it will not
/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no
/// assert_eq!(*zero, 0)
/// ```
///
- /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
+ /// [zeroed]: mem::MaybeUninit::zeroed
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_zeroed() -> Arc<mem::MaybeUninit<T>> {
/// assert_eq!(*values, [0, 0, 0])
/// ```
///
- /// [zeroed]: ../../std/mem/union.MaybeUninit.html#method.zeroed
+ /// [zeroed]: mem::MaybeUninit::zeroed
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "new_uninit", issue = "63291")]
pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
/// Calling this when the content is not yet fully initialized
/// causes immediate undefined behavior.
///
- /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init
+ /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init
///
/// # Examples
///
/// Calling this when the content is not yet fully initialized
/// causes immediate undefined behavior.
///
- /// [`MaybeUninit::assume_init`]: ../../std/mem/union.MaybeUninit.html#method.assume_init
+ /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init
///
/// # Examples
///
/// assert!(!Arc::ptr_eq(&five, &other_five));
/// ```
///
- /// [`ptr::eq`]: core::ptr::eq
+ /// [`ptr::eq`]: core::ptr::eq "ptr::eq"
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
this.ptr.as_ptr() == other.ptr.as_ptr()
}
/// // assert_eq!("hello", unsafe { &*weak.as_ptr() });
/// ```
///
- /// [`null`]: core::ptr::null
+ /// [`null`]: core::ptr::null "ptr::null"
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub fn as_ptr(&self) -> *const T {
let ptr: *mut ArcInner<T> = NonNull::as_ptr(self.ptr);
/// [`new`]: Weak::new
/// [`into_raw`]: Weak::into_raw
/// [`upgrade`]: Weak::upgrade
- /// [`forget`]: std::mem::forget
#[stable(feature = "weak_into_raw", since = "1.45.0")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
// See Weak::as_ptr for context on how the input pointer is derived.
/// assert!(!first.ptr_eq(&third));
/// ```
///
- /// [`ptr::eq`]: core::ptr::eq
+ /// [`ptr::eq`]: core::ptr::eq "ptr::eq"
#[inline]
#[stable(feature = "weak_ptr_eq", since = "1.39.0")]
pub fn ptr_eq(&self, other: &Self) -> bool {
//! A contiguous growable array type with heap-allocated contents, written
//! `Vec<T>`.
//!
-//! Vectors have `O(1)` indexing, amortized `O(1)` push (to the end) and
-//! `O(1)` pop (from the end).
+//! Vectors have *O*(1) indexing, amortized *O*(1) push (to the end) and
+//! *O*(1) pop (from the end).
//!
//! Vectors ensure they never allocate more than `isize::MAX` bytes.
//!
/// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized
/// types inside a `Vec`, it will not allocate space for them. *Note that in this case
/// the `Vec` might not report a [`capacity`] of 0*. `Vec` will allocate if and only
-/// if [`mem::size_of::<T>`]`() * capacity() > 0`. In general, `Vec`'s allocation
-/// details are very subtle — if you intend to allocate memory using a `Vec`
+/// if <code>[mem::size_of::\<T>]\() * [capacity]\() > 0</code>. In general, `Vec`'s allocation
+/// details are very subtle --- if you intend to allocate memory using a `Vec`
/// and use it for something else (either to pass to unsafe code, or to build your
/// own memory-backed collection), be sure to deallocate this memory by using
/// `from_raw_parts` to recover the `Vec` and then dropping it.
/// If a `Vec` *has* allocated memory, then the memory it points to is on the heap
/// (as defined by the allocator Rust is configured to use by default), and its
/// pointer points to [`len`] initialized, contiguous elements in order (what
-/// you would see if you coerced it to a slice), followed by [`capacity`]` -
-/// `[`len`] logically uninitialized, contiguous elements.
+/// you would see if you coerced it to a slice), followed by <code>[capacity] - [len]</code>
+/// logically uninitialized, contiguous elements.
///
/// A vector containing the elements `'a'` and `'b'` with capacity 4 can be
/// visualized as below. The top part is the `Vec` struct, it contains a
///
/// [`push`] and [`insert`] will never (re)allocate if the reported capacity is
/// sufficient. [`push`] and [`insert`] *will* (re)allocate if
-/// [`len`]` == `[`capacity`]. That is, the reported capacity is completely
+/// <code>[len] == [capacity]</code>. That is, the reported capacity is completely
/// accurate, and can be relied on. It can even be used to manually free the memory
/// allocated by a `Vec` if desired. Bulk insertion methods *may* reallocate, even
/// when not necessary.
///
/// `vec![x; n]`, `vec![a, b, c, d]`, and
/// [`Vec::with_capacity(n)`][`Vec::with_capacity`], will all produce a `Vec`
-/// with exactly the requested capacity. If [`len`]` == `[`capacity`],
+/// with exactly the requested capacity. If <code>[len] == [capacity]</code>,
/// (as is the case for the [`vec!`] macro), then a `Vec<T>` can be converted to
/// and from a [`Box<[T]>`][owned slice] without reallocating or moving the elements.
///
/// [`&str`]: type@str
/// [`shrink_to_fit`]: Vec::shrink_to_fit
/// [`shrink_to`]: Vec::shrink_to
+/// [capacity]: Vec::capacity
/// [`capacity`]: Vec::capacity
-/// [`mem::size_of::<T>`]: core::mem::size_of
+/// [mem::size_of::\<T>]: core::mem::size_of
+/// [len]: Vec::len
/// [`len`]: Vec::len
/// [`push`]: Vec::push
/// [`insert`]: Vec::insert
///
/// The removed element is replaced by the last element of the vector.
///
- /// This does not preserve ordering, but is O(1).
+ /// This does not preserve ordering, but is *O*(1).
///
/// # Panics
///
}
}
+#[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_from_array", since = "1.44.0")]
impl<T, const N: usize> From<[T; N]> for Vec<T> {
#[cfg(not(test))]
#![feature(binary_heap_retain)]
#![feature(binary_heap_as_slice)]
#![feature(inplace_iteration)]
-#![feature(iter_map_while)]
#![feature(slice_group_by)]
#![feature(slice_partition_dedup)]
#![feature(vec_spare_capacity)]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct EscapeDefault {
- range: Range<usize>,
+ range: Range<u8>,
data: [u8; 4],
}
impl Iterator for EscapeDefault {
type Item = u8;
fn next(&mut self) -> Option<u8> {
- self.range.next().map(|i| self.data[i])
+ self.range.next().map(|i| self.data[i as usize])
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.range.size_hint()
#[stable(feature = "rust1", since = "1.0.0")]
impl DoubleEndedIterator for EscapeDefault {
fn next_back(&mut self) -> Option<u8> {
- self.range.next_back().map(|i| self.data[i])
+ self.range.next_back().map(|i| self.data[i as usize])
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for EscapeDefault {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// SAFETY: ok because `escape_default` created only valid utf-8 data
- f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) })
+ f.write_str(unsafe {
+ from_utf8_unchecked(&self.data[(self.range.start as usize)..(self.range.end as usize)])
+ })
}
}
formatter: fn(&Opaque, &mut Formatter<'_>) -> Result,
}
+/// This struct represents the unsafety of constructing an `Arguments`.
+/// It exists, rather than an unsafe function, in order to simplify the expansion
+/// of `format_args!(..)` and reduce the scope of the `unsafe` block.
+#[allow(missing_debug_implementations)]
+#[doc(hidden)]
+#[non_exhaustive]
+#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
+pub struct UnsafeArg;
+
+impl UnsafeArg {
+ /// See documentation where `UnsafeArg` is required to know when it is safe to
+ /// create and use `UnsafeArg`.
+ #[doc(hidden)]
+ #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
+ #[inline(always)]
+ pub unsafe fn new() -> Self {
+ Self
+ }
+}
+
// This guarantees a single stable value for the function pointer associated with
// indices/counts in the formatting infrastructure.
//
#[inline]
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
#[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
- pub const unsafe fn new_v1(
- pieces: &'a [&'static str],
- args: &'a [ArgumentV1<'a>],
- ) -> Arguments<'a> {
+ pub const fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
panic!("invalid args");
}
}
/// This function is used to specify nonstandard formatting parameters.
- /// The `pieces` array must be at least as long as `fmt` to construct
- /// a valid Arguments structure. Also, any `Count` within `fmt` that is
- /// `CountIsParam` or `CountIsNextParam` has to point to an argument
- /// created with `argumentusize`. However, failing to do so doesn't cause
- /// unsafety, but will ignore invalid .
+ ///
+ /// An `UnsafeArg` is required because the following invariants must be held
+ /// in order for this function to be safe:
+ /// 1. The `pieces` slice must be at least as long as `fmt`.
+ /// 2. Every [`rt::v1::Argument::position`] value within `fmt` must be a
+ /// valid index of `args`.
+ /// 3. Every [`Count::Param`] within `fmt` must contain a valid index of
+ /// `args`.
+ #[cfg(not(bootstrap))]
+ #[doc(hidden)]
+ #[inline]
+ #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
+ #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
+ pub const fn new_v1_formatted(
+ pieces: &'a [&'static str],
+ args: &'a [ArgumentV1<'a>],
+ fmt: &'a [rt::v1::Argument],
+ _unsafe_arg: UnsafeArg,
+ ) -> Arguments<'a> {
+ Arguments { pieces, fmt: Some(fmt), args }
+ }
+
+ #[cfg(bootstrap)]
#[doc(hidden)]
#[inline]
#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
/// Padding after the end of something. Returned by `Formatter::padding`.
#[must_use = "don't forget to write the post padding"]
-struct PostPadding {
+pub(crate) struct PostPadding {
fill: char,
padding: usize,
}
}
/// Write this post padding.
- fn write(self, buf: &mut dyn Write) -> Result {
+ pub(crate) fn write(self, f: &mut Formatter<'_>) -> Result {
for _ in 0..self.padding {
- buf.write_char(self.fill)?;
+ f.buf.write_char(self.fill)?;
}
Ok(())
}
write_prefix(self, sign, prefix)?;
let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?;
self.buf.write_str(buf)?;
- post_padding.write(self.buf)?;
+ post_padding.write(self)?;
self.fill = old_fill;
self.align = old_align;
Ok(())
let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?;
write_prefix(self, sign, prefix)?;
self.buf.write_str(buf)?;
- post_padding.write(self.buf)
+ post_padding.write(self)
}
}
}
let align = rt::v1::Alignment::Left;
let post_padding = self.padding(width - chars_count, align)?;
self.buf.write_str(s)?;
- post_padding.write(self.buf)
+ post_padding.write(self)
}
}
}
/// Write the pre-padding and return the unwritten post-padding. Callers are
/// responsible for ensuring post-padding is written after the thing that is
/// being padded.
- fn padding(
+ pub(crate) fn padding(
&mut self,
padding: usize,
default: rt::v1::Alignment,
} else {
let post_padding = self.padding(width - len, align)?;
self.write_formatted_parts(&formatted)?;
- post_padding.write(self.buf)
+ post_padding.write(self)
};
self.fill = old_fill;
self.align = old_align;
/// [`map_while`]: Iterator::map_while
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
#[derive(Clone)]
pub struct MapWhile<I, P> {
iter: I,
}
}
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
impl<I: fmt::Debug, P> fmt::Debug for MapWhile<I, P> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MapWhile").field("iter", &self.iter).finish()
}
}
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
impl<B, I: Iterator, P> Iterator for MapWhile<I, P>
where
P: FnMut(I::Item) -> Option<B>,
#[stable(feature = "iter_intersperse", since = "1.56.0")]
pub use self::intersperse::{Intersperse, IntersperseWith};
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
pub use self::map_while::MapWhile;
#[unstable(feature = "trusted_random_access", issue = "none")]
//! ```
//!
//! An iterator has a method, [`next`], which when called, returns an
-//! [`Option`]`<Item>`. [`next`] will return [`Some(Item)`] as long as there
+//! <code>[Option]\<Item></code>. Calling [`next`] will return [`Some(Item)`] as long as there
//! are elements, and once they've all been exhausted, will return `None` to
//! indicate that iteration is finished. Individual iterators may choose to
//! resume iteration, and so calling [`next`] again may or may not eventually
pub use self::adapters::Copied;
#[stable(feature = "iterator_flatten", since = "1.29.0")]
pub use self::adapters::Flatten;
-#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+#[stable(feature = "iter_map_while", since = "1.57.0")]
pub use self::adapters::MapWhile;
#[unstable(feature = "inplace_iteration", issue = "none")]
pub use self::adapters::SourceIter;
/// Specifically, `size_hint()` returns a tuple where the first element
/// is the lower bound, and the second element is the upper bound.
///
- /// The second half of the tuple that is returned is an [`Option`]`<`[`usize`]`>`.
+ /// The second half of the tuple that is returned is an <code>[Option]<[usize]></code>.
/// A [`None`] here means that either there is no known upper bound, or the
/// upper bound is larger than [`usize`].
///
/// That said, the implementation should provide a correct estimation,
/// because otherwise it would be a violation of the trait's protocol.
///
- /// The default implementation returns `(0, `[`None`]`)` which is correct for any
+ /// The default implementation returns <code>(0, [None])</code> which is correct for any
/// iterator.
///
- /// [`usize`]: type@usize
- ///
/// # Examples
///
/// Basic usage:
/// The returned iterator might panic if the to-be-returned index would
/// overflow a [`usize`].
///
- /// [`usize`]: type@usize
/// [`zip`]: Iterator::zip
///
/// # Examples
/// Basic usage:
///
/// ```
- /// #![feature(iter_map_while)]
/// let a = [-1i32, 4, 0, 1];
///
/// let mut iter = a.iter().map_while(|x| 16i32.checked_div(*x));
/// Stopping after an initial [`None`]:
///
/// ```
- /// #![feature(iter_map_while)]
/// use std::convert::TryFrom;
///
/// let a = [0, 1, 2, -3, 4, 5, -6];
/// removed:
///
/// ```
- /// #![feature(iter_map_while)]
/// use std::convert::TryFrom;
///
/// let a = [1, 2, -3, 4];
///
/// [`fuse`]: Iterator::fuse
#[inline]
- #[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
+ #[stable(feature = "iter_map_while", since = "1.57.0")]
fn map_while<B, P>(self, predicate: P) -> MapWhile<Self, P>
where
Self: Sized,
/// The relative order of partitioned items is not maintained.
///
/// # Current implementation
+ ///
/// Current algorithms tries finding the first element for which the predicate evaluates
/// to false, and the last element for which it evaluates to true and repeatedly swaps them.
///
- /// Time Complexity: *O*(*N*)
+ /// Time complexity: *O*(*n*)
///
/// See also [`is_partitioned()`] and [`partition()`].
///
#[doc = concat!("let a: ", stringify!($SelfT)," = 8;")]
/// let b = 3;
///
- /// assert_eq!(a.div_floor(b), 2);
- /// assert_eq!(a.div_floor(-b), -3);
- /// assert_eq!((-a).div_floor(b), -3);
- /// assert_eq!((-a).div_floor(-b), 2);
+ /// assert_eq!(a.unstable_div_floor(b), 2);
+ /// assert_eq!(a.unstable_div_floor(-b), -3);
+ /// assert_eq!((-a).unstable_div_floor(b), -3);
+ /// assert_eq!((-a).unstable_div_floor(-b), 2);
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[rustc_inherit_overflow_checks]
- pub const fn div_floor(self, rhs: Self) -> Self {
+ pub const fn unstable_div_floor(self, rhs: Self) -> Self {
let d = self / rhs;
let r = self % rhs;
if (r > 0 && rhs < 0) || (r < 0 && rhs > 0) {
#[doc = concat!("let a: ", stringify!($SelfT)," = 8;")]
/// let b = 3;
///
- /// assert_eq!(a.div_ceil(b), 3);
- /// assert_eq!(a.div_ceil(-b), -2);
- /// assert_eq!((-a).div_ceil(b), -2);
- /// assert_eq!((-a).div_ceil(-b), 3);
+ /// assert_eq!(a.unstable_div_ceil(b), 3);
+ /// assert_eq!(a.unstable_div_ceil(-b), -2);
+ /// assert_eq!((-a).unstable_div_ceil(b), -2);
+ /// assert_eq!((-a).unstable_div_ceil(-b), 3);
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[rustc_inherit_overflow_checks]
- pub const fn div_ceil(self, rhs: Self) -> Self {
+ pub const fn unstable_div_ceil(self, rhs: Self) -> Self {
let d = self / rhs;
let r = self % rhs;
if (r > 0 && rhs > 0) || (r < 0 && rhs < 0) {
///
/// ```
/// #![feature(int_roundings)]
- #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")]
- #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")]
- #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(-8), 16);")]
- #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(-8), 16);")]
- #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(8), -16);")]
- #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(8), -16);")]
- #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").next_multiple_of(-8), -16);")]
- #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").next_multiple_of(-8), -24);")]
+ #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".unstable_next_multiple_of(8), 16);")]
+ #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".unstable_next_multiple_of(8), 24);")]
+ #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".unstable_next_multiple_of(-8), 16);")]
+ #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".unstable_next_multiple_of(-8), 16);")]
+ #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").unstable_next_multiple_of(8), -16);")]
+ #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").unstable_next_multiple_of(8), -16);")]
+ #[doc = concat!("assert_eq!((-16_", stringify!($SelfT), ").unstable_next_multiple_of(-8), -16);")]
+ #[doc = concat!("assert_eq!((-23_", stringify!($SelfT), ").unstable_next_multiple_of(-8), -24);")]
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[rustc_inherit_overflow_checks]
- pub const fn next_multiple_of(self, rhs: Self) -> Self {
+ pub const fn unstable_next_multiple_of(self, rhs: Self) -> Self {
// This would otherwise fail when calculating `r` when self == T::MIN.
if rhs == -1 {
return self;
///
/// ```
/// #![feature(int_roundings)]
- #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_floor(4), 1);")]
+ #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".unstable_div_floor(4), 1);")]
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[inline(always)]
#[rustc_inherit_overflow_checks]
- pub const fn div_floor(self, rhs: Self) -> Self {
+ pub const fn unstable_div_floor(self, rhs: Self) -> Self {
self / rhs
}
///
/// ```
/// #![feature(int_roundings)]
- #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".div_ceil(4), 2);")]
+ #[doc = concat!("assert_eq!(7_", stringify!($SelfT), ".unstable_div_ceil(4), 2);")]
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[inline]
#[rustc_inherit_overflow_checks]
- pub const fn div_ceil(self, rhs: Self) -> Self {
+ pub const fn unstable_div_ceil(self, rhs: Self) -> Self {
let d = self / rhs;
let r = self % rhs;
if r > 0 && rhs > 0 {
///
/// ```
/// #![feature(int_roundings)]
- #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".next_multiple_of(8), 16);")]
- #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".next_multiple_of(8), 24);")]
+ #[doc = concat!("assert_eq!(16_", stringify!($SelfT), ".unstable_next_multiple_of(8), 16);")]
+ #[doc = concat!("assert_eq!(23_", stringify!($SelfT), ".unstable_next_multiple_of(8), 24);")]
/// ```
#[unstable(feature = "int_roundings", issue = "88581")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[rustc_inherit_overflow_checks]
- pub const fn next_multiple_of(self, rhs: Self) -> Self {
+ pub const fn unstable_next_multiple_of(self, rhs: Self) -> Self {
match self % rhs {
0 => self,
r => self + (rhs - r)
//!
//! Rust's pointer types must always point to a valid location; there are
//! no "null" references. Instead, Rust has *optional* pointers, like
-//! the optional owned box, [`Option`]`<`[`Box<T>`]`>`.
+//! the optional owned box, <code>[Option]<[Box\<T>]></code>.
//!
-//! [`Box<T>`]: ../../std/boxed/struct.Box.html
+//! [Box\<T>]: ../../std/boxed/struct.Box.html
//!
//! The following example uses [`Option`] to create an optional box of
//! [`i32`]. Notice that in order to use the inner [`i32`] value, the
//!
//! ## Adapters for working with references
//!
-//! * [`as_ref`] converts from `&Option<T>` to `Option<&T>`
-//! * [`as_mut`] converts from `&mut Option<T>` to `Option<&mut T>`
-//! * [`as_deref`] converts from `&Option<T>` to `Option<&T::Target>`
-//! * [`as_deref_mut`] converts from `&mut Option<T>` to
-//! `Option<&mut T::Target>`
-//! * [`as_pin_ref`] converts from [`Pin`]`<&Option<T>>` to
-//! `Option<`[`Pin`]`<&T>>`
-//! * [`as_pin_mut`] converts from [`Pin`]`<&mut Option<T>>` to
-//! `Option<`[`Pin`]`<&mut T>>`
-//!
+//! * [`as_ref`] converts from <code>[&][][Option]\<T></code> to <code>[Option]<[&]T></code>
+//! * [`as_mut`] converts from <code>[&mut] [Option]\<T></code> to <code>[Option]<[&mut] T></code>
+//! * [`as_deref`] converts from <code>[&][][Option]\<T></code> to
+//! <code>[Option]<[&]T::[Target]></code>
+//! * [`as_deref_mut`] converts from <code>[&mut] [Option]\<T></code> to
+//! <code>[Option]<[&mut] T::[Target]></code>
+//! * [`as_pin_ref`] converts from <code>[Pin]<[&][][Option]\<T>></code> to
+//! <code>[Option]<[Pin]<[&]T>></code>
+//! * [`as_pin_mut`] converts from <code>[Pin]<[&mut] [Option]\<T>></code> to
+//! <code>[Option]<[Pin]<[&mut] T>></code>
+//!
+//! [&]: reference "shared reference"
+//! [&mut]: reference "mutable reference"
+//! [Target]: Deref::Target "ops::Deref::Target"
//! [`as_deref`]: Option::as_deref
//! [`as_deref_mut`]: Option::as_deref_mut
//! [`as_mut`]: Option::as_mut
///
/// # Examples
///
- /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, preserving the original.
- /// The [`map`] method takes the `self` argument by value, consuming the original,
+ /// Converts an <code>Option<[String]></code> into an <code>Option<[usize]></code>, preserving
+ /// the original. The [`map`] method takes the `self` argument by value, consuming the original,
/// so this technique uses `as_ref` to first take an `Option` to a reference
/// to the value inside the original.
///
/// [`map`]: Option::map
- /// [`String`]: ../../std/string/struct.String.html
+ /// [String]: ../../std/string/struct.String.html "String"
///
/// ```
/// let text: Option<String> = Some("Hello, world!".to_string());
}
}
- /// Converts from [`Pin`]`<&Option<T>>` to `Option<`[`Pin`]`<&T>>`.
+ /// Converts from <code>[Pin]<[&]Option\<T>></code> to <code>Option<[Pin]<[&]T>></code>.
+ ///
+ /// [&]: reference "shared reference"
#[inline]
#[stable(feature = "pin", since = "1.33.0")]
pub fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> {
unsafe { Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) }
}
- /// Converts from [`Pin`]`<&mut Option<T>>` to `Option<`[`Pin`]`<&mut T>>`.
+ /// Converts from <code>[Pin]<[&mut] Option\<T>></code> to <code>Option<[Pin]<[&mut] T>></code>.
+ ///
+ /// [&mut]: reference "mutable reference"
#[inline]
#[stable(feature = "pin", since = "1.33.0")]
pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> {
///
/// # Examples
///
- /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, consuming the original:
+ /// Converts an <code>Option<[String]></code> into an <code>Option<[usize]></code>, consuming
+ /// the original:
///
- /// [`String`]: ../../std/string/struct.String.html
+ /// [String]: ../../std/string/struct.String.html "String"
/// ```
/// let maybe_some_string = Some(String::from("Hello, World!"));
/// // `Option::map` takes self *by value*, consuming `maybe_some_string`
impl<T, E> Option<Result<T, E>> {
/// Transposes an `Option` of a [`Result`] into a [`Result`] of an `Option`.
///
- /// [`None`] will be mapped to [`Ok`]`(`[`None`]`)`.
- /// [`Some`]`(`[`Ok`]`(_))` and [`Some`]`(`[`Err`]`(_))` will be mapped to
- /// [`Ok`]`(`[`Some`]`(_))` and [`Err`]`(_)`.
+ /// [`None`] will be mapped to <code>[Ok]\([None])</code>.
+ /// <code>[Some]\([Ok]\(\_))</code> and <code>[Some]\([Err]\(\_))</code> will be mapped to
+ /// <code>[Ok]\([Some]\(\_))</code> and <code>[Err]\(\_)</code>.
///
/// # Examples
///
///
/// # Examples
///
- /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, preserving the original.
- /// The [`map`] method takes the `self` argument by value, consuming the original,
- /// so this technique uses `from` to first take an `Option` to a reference
+ /// Converts an <code>[Option]<[String]></code> into an <code>[Option]<[usize]></code>, preserving
+ /// the original. The [`map`] method takes the `self` argument by value, consuming the original,
+ /// so this technique uses `from` to first take an [`Option`] to a reference
/// to the value inside the original.
///
/// [`map`]: Option::map
- /// [`String`]: ../../std/string/struct.String.html
+ /// [String]: ../../std/string/struct.String.html "String"
///
/// ```
/// let s: Option<String> = Some(String::from("Hello, Rustaceans!"));
// truncation and padding (even though none is used here). Using
// Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
// output binary, saving up to a few kilobytes.
- panic_fmt(
- // SAFETY: Arguments::new_v1 is safe with exactly one str and zero args
- unsafe { fmt::Arguments::new_v1(&[expr], &[]) },
- );
+ panic_fmt(fmt::Arguments::new_v1(&[expr], &[]));
}
#[inline]
//! [Vec::push]: ../../std/vec/struct.Vec.html#method.push "Vec::push"
//! [Rc]: ../../std/rc/struct.Rc.html "rc::Rc"
//! [RefCell]: crate::cell::RefCell "cell::RefCell"
-//! [`drop`]: Drop::drop "Drop::drop"
+//! [`drop`]: Drop::drop
//! [VecDeque]: ../../std/collections/struct.VecDeque.html "collections::VecDeque"
//! [`ptr::write`]: crate::ptr::write "ptr::write"
//! [`Future`]: crate::future::Future "future::Future"
//! [drop-impl]: #drop-implementation
//! [drop-guarantee]: #drop-guarantee
//! [`poll`]: crate::future::Future::poll "future::Future::poll"
-//! [&]: ../../std/primitive.reference.html "shared reference"
-//! [&mut]: ../../std/primitive.reference.html "mutable reference"
+//! [&]: reference "shared reference"
+//! [&mut]: reference "mutable reference"
//! [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe"
#![stable(feature = "pin", since = "1.33.0")]
//! ```
//!
//! *Note: The actual definition of [`Write`] uses [`io::Result`], which
-//! is just a synonym for [`Result`]`<T, `[`io::Error`]`>`.*
+//! is just a synonym for <code>[Result]<T, [io::Error]></code>.*
//!
//! This method doesn't produce a value, but the write may
//! fail. It's crucial to handle the error case, and *not* write
//! early return of [`Err`] that it provides.
//!
//! [`expect`]: Result::expect
-//! [`Write`]: ../../std/io/trait.Write.html
-//! [`write_all`]: ../../std/io/trait.Write.html#method.write_all
-//! [`io::Result`]: ../../std/io/type.Result.html
+//! [`Write`]: ../../std/io/trait.Write.html "io::Write"
+//! [`write_all`]: ../../std/io/trait.Write.html#method.write_all "io::Write::write_all"
+//! [`io::Result`]: ../../std/io/type.Result.html "io::Result"
//! [`?`]: crate::ops::Try
//! [`Ok(T)`]: Ok
//! [`Err(E)`]: Err
-//! [`io::Error`]: ../../std/io/struct.Error.html
+//! [io::Error]: ../../std/io/struct.Error.html "io::Error"
//!
//! # Method overview
//!
/// Specifically, `size_hint()` returns a tuple where the first element
/// is the lower bound, and the second element is the upper bound.
///
- /// The second half of the tuple that is returned is an [`Option`]`<`[`usize`]`>`.
+ /// The second half of the tuple that is returned is an <code>[Option]<[usize]></code>.
/// A [`None`] here means that either there is no known upper bound, or the
/// upper bound is larger than [`usize`].
///
/// That said, the implementation should provide a correct estimation,
/// because otherwise it would be a violation of the trait's protocol.
///
- /// The default implementation returns `(0, `[`None`]`)` which is correct for any
+ /// The default implementation returns <code>(0, [None])</code> which is correct for any
/// stream.
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
///
/// # Examples
///
- /// Converts a `Poll<`[`String`]`>` into an `Poll<`[`usize`]`>`, consuming the original:
+ /// Converts a <code>Poll<[String]></code> into a <code>Poll<[usize]></code>, consuming
+ /// the original:
///
- /// [`String`]: ../../std/string/struct.String.html
+ /// [String]: ../../std/string/struct.String.html "String"
/// ```
/// # use core::task::Poll;
/// let poll_some_string = Poll::Ready(String::from("Hello, World!"));
/// `divisor` must not be above 100_000_000. It also should be a power
/// of 10, everything else doesn't make sense. `fractional_part` has
/// to be less than `10 * divisor`!
+ ///
+ /// A prefix and postfix may be added. The whole thing is padded
+ /// to the formatter's `width`, if specified.
fn fmt_decimal(
f: &mut fmt::Formatter<'_>,
mut integer_part: u64,
mut fractional_part: u32,
mut divisor: u32,
+ prefix: &str,
+ postfix: &str,
) -> fmt::Result {
// Encode the fractional part into a temporary buffer. The buffer
// only need to hold 9 elements, because `fractional_part` has to
// set, we only use all digits up to the last non-zero one.
let end = f.precision().map(|p| crate::cmp::min(p, 9)).unwrap_or(pos);
- // If we haven't emitted a single fractional digit and the precision
- // wasn't set to a non-zero value, we don't print the decimal point.
- if end == 0 {
- write!(f, "{}", integer_part)
- } else {
- // SAFETY: We are only writing ASCII digits into the buffer and it was
- // initialized with '0's, so it contains valid UTF8.
- let s = unsafe { crate::str::from_utf8_unchecked(&buf[..end]) };
+ // This closure emits the formatted duration without emitting any
+ // padding (padding is calculated below).
+ let emit_without_padding = |f: &mut fmt::Formatter<'_>| {
+ write!(f, "{}{}", prefix, integer_part)?;
+
+ // Write the decimal point and the fractional part (if any).
+ if end > 0 {
+ // SAFETY: We are only writing ASCII digits into the buffer and
+ // it was initialized with '0's, so it contains valid UTF8.
+ let s = unsafe { crate::str::from_utf8_unchecked(&buf[..end]) };
+
+ // If the user request a precision > 9, we pad '0's at the end.
+ let w = f.precision().unwrap_or(pos);
+ write!(f, ".{:0<width$}", s, width = w)?;
+ }
- // If the user request a precision > 9, we pad '0's at the end.
- let w = f.precision().unwrap_or(pos);
- write!(f, "{}.{:0<width$}", integer_part, s, width = w)
+ write!(f, "{}", postfix)
+ };
+
+ match f.width() {
+ None => {
+ // No `width` specified. There's no need to calculate the
+ // length of the output in this case, just emit it.
+ emit_without_padding(f)
+ }
+ Some(requested_w) => {
+ // A `width` was specified. Calculate the actual width of
+ // the output in order to calculate the required padding.
+ // It consists of 4 parts:
+ // 1. The prefix: is either "+" or "", so we can just use len().
+ // 2. The postfix: can be "µs" so we have to count UTF8 characters.
+ let mut actual_w = prefix.len() + postfix.chars().count();
+ // 3. The integer part:
+ if let Some(log) = integer_part.checked_log10() {
+ // integer_part is > 0, so has length log10(x)+1
+ actual_w += 1 + log as usize;
+ } else {
+ // integer_part is 0, so has length 1.
+ actual_w += 1;
+ }
+ // 4. The fractional part (if any):
+ if end > 0 {
+ let frac_part_w = f.precision().unwrap_or(pos);
+ actual_w += 1 + frac_part_w;
+ }
+
+ if requested_w <= actual_w {
+ // Output is already longer than `width`, so don't pad.
+ emit_without_padding(f)
+ } else {
+ // We need to add padding. Use the `Formatter::padding` helper function.
+ let default_align = crate::fmt::rt::v1::Alignment::Left;
+ let post_padding = f.padding(requested_w - actual_w, default_align)?;
+ emit_without_padding(f)?;
+ post_padding.write(f)
+ }
+ }
}
}
// Print leading '+' sign if requested
- if f.sign_plus() {
- write!(f, "+")?;
- }
+ let prefix = if f.sign_plus() { "+" } else { "" };
if self.secs > 0 {
- fmt_decimal(f, self.secs, self.nanos, NANOS_PER_SEC / 10)?;
- f.write_str("s")
+ fmt_decimal(f, self.secs, self.nanos, NANOS_PER_SEC / 10, prefix, "s")
} else if self.nanos >= NANOS_PER_MILLI {
fmt_decimal(
f,
(self.nanos / NANOS_PER_MILLI) as u64,
self.nanos % NANOS_PER_MILLI,
NANOS_PER_MILLI / 10,
- )?;
- f.write_str("ms")
+ prefix,
+ "ms",
+ )
} else if self.nanos >= NANOS_PER_MICRO {
fmt_decimal(
f,
(self.nanos / NANOS_PER_MICRO) as u64,
self.nanos % NANOS_PER_MICRO,
NANOS_PER_MICRO / 10,
- )?;
- f.write_str("µs")
+ prefix,
+ "µs",
+ )
} else {
- fmt_decimal(f, self.nanos as u64, 0, 1)?;
- f.write_str("ns")
+ fmt_decimal(f, self.nanos as u64, 0, 1, prefix, "ns")
}
}
}
#![feature(iter_partition_in_place)]
#![feature(iter_is_partitioned)]
#![feature(iter_order_by)]
-#![feature(iter_map_while)]
#![feature(const_mut_refs)]
#![feature(const_pin)]
#![feature(const_slice_from_raw_parts)]
fn test_div_floor() {
let a: $T = 8;
let b = 3;
- assert_eq!(a.div_floor(b), 2);
- assert_eq!(a.div_floor(-b), -3);
- assert_eq!((-a).div_floor(b), -3);
- assert_eq!((-a).div_floor(-b), 2);
+ assert_eq!(a.unstable_div_floor(b), 2);
+ assert_eq!(a.unstable_div_floor(-b), -3);
+ assert_eq!((-a).unstable_div_floor(b), -3);
+ assert_eq!((-a).unstable_div_floor(-b), 2);
}
#[test]
fn test_div_ceil() {
let a: $T = 8;
let b = 3;
- assert_eq!(a.div_ceil(b), 3);
- assert_eq!(a.div_ceil(-b), -2);
- assert_eq!((-a).div_ceil(b), -2);
- assert_eq!((-a).div_ceil(-b), 3);
+ assert_eq!(a.unstable_div_ceil(b), 3);
+ assert_eq!(a.unstable_div_ceil(-b), -2);
+ assert_eq!((-a).unstable_div_ceil(b), -2);
+ assert_eq!((-a).unstable_div_ceil(-b), 3);
}
#[test]
fn test_next_multiple_of() {
- assert_eq!((16 as $T).next_multiple_of(8), 16);
- assert_eq!((23 as $T).next_multiple_of(8), 24);
- assert_eq!((16 as $T).next_multiple_of(-8), 16);
- assert_eq!((23 as $T).next_multiple_of(-8), 16);
- assert_eq!((-16 as $T).next_multiple_of(8), -16);
- assert_eq!((-23 as $T).next_multiple_of(8), -16);
- assert_eq!((-16 as $T).next_multiple_of(-8), -16);
- assert_eq!((-23 as $T).next_multiple_of(-8), -24);
- assert_eq!(MIN.next_multiple_of(-1), MIN);
+ assert_eq!((16 as $T).unstable_next_multiple_of(8), 16);
+ assert_eq!((23 as $T).unstable_next_multiple_of(8), 24);
+ assert_eq!((16 as $T).unstable_next_multiple_of(-8), 16);
+ assert_eq!((23 as $T).unstable_next_multiple_of(-8), 16);
+ assert_eq!((-16 as $T).unstable_next_multiple_of(8), -16);
+ assert_eq!((-23 as $T).unstable_next_multiple_of(8), -16);
+ assert_eq!((-16 as $T).unstable_next_multiple_of(-8), -16);
+ assert_eq!((-23 as $T).unstable_next_multiple_of(-8), -24);
+ assert_eq!(MIN.unstable_next_multiple_of(-1), MIN);
}
#[test]
#[test]
fn test_div_floor() {
- assert_eq!((8 as $T).div_floor(3), 2);
+ assert_eq!((8 as $T).unstable_div_floor(3), 2);
}
#[test]
fn test_div_ceil() {
- assert_eq!((8 as $T).div_ceil(3), 3);
+ assert_eq!((8 as $T).unstable_div_ceil(3), 3);
}
#[test]
fn test_next_multiple_of() {
- assert_eq!((16 as $T).next_multiple_of(8), 16);
- assert_eq!((23 as $T).next_multiple_of(8), 24);
- assert_eq!(MAX.next_multiple_of(1), MAX);
+ assert_eq!((16 as $T).unstable_next_multiple_of(8), 16);
+ assert_eq!((23 as $T).unstable_next_multiple_of(8), 24);
+ assert_eq!(MAX.unstable_next_multiple_of(1), MAX);
}
#[test]
assert_eq!(format!("{:.2?}", Duration::new(8, 999_999_999)), "9.00s");
}
+#[test]
+fn debug_formatting_padding() {
+ assert_eq!("0ns ", format!("{:<9?}", Duration::new(0, 0)));
+ assert_eq!(" 0ns", format!("{:>9?}", Duration::new(0, 0)));
+ assert_eq!(" 0ns ", format!("{:^9?}", Duration::new(0, 0)));
+ assert_eq!("123ns ", format!("{:<9.0?}", Duration::new(0, 123)));
+ assert_eq!(" 123ns", format!("{:>9.0?}", Duration::new(0, 123)));
+ assert_eq!(" 123ns ", format!("{:^9.0?}", Duration::new(0, 123)));
+ assert_eq!("123.0ns ", format!("{:<9.1?}", Duration::new(0, 123)));
+ assert_eq!(" 123.0ns", format!("{:>9.1?}", Duration::new(0, 123)));
+ assert_eq!(" 123.0ns ", format!("{:^9.1?}", Duration::new(0, 123)));
+ assert_eq!("7.1µs ", format!("{:<9?}", Duration::new(0, 7_100)));
+ assert_eq!(" 7.1µs", format!("{:>9?}", Duration::new(0, 7_100)));
+ assert_eq!(" 7.1µs ", format!("{:^9?}", Duration::new(0, 7_100)));
+ assert_eq!("999.123456ms", format!("{:<9?}", Duration::new(0, 999_123_456)));
+ assert_eq!("999.123456ms", format!("{:>9?}", Duration::new(0, 999_123_456)));
+ assert_eq!("999.123456ms", format!("{:^9?}", Duration::new(0, 999_123_456)));
+ assert_eq!("5s ", format!("{:<9?}", Duration::new(5, 0)));
+ assert_eq!(" 5s", format!("{:>9?}", Duration::new(5, 0)));
+ assert_eq!(" 5s ", format!("{:^9?}", Duration::new(5, 0)));
+ assert_eq!("5.000000000000s", format!("{:<9.12?}", Duration::new(5, 0)));
+ assert_eq!("5.000000000000s", format!("{:>9.12?}", Duration::new(5, 0)));
+ assert_eq!("5.000000000000s", format!("{:^9.12?}", Duration::new(5, 0)));
+
+ // default alignment is left:
+ assert_eq!("5s ", format!("{:9?}", Duration::new(5, 0)));
+}
+
#[test]
fn debug_formatting_precision_high() {
assert_eq!(format!("{:.5?}", Duration::new(0, 23_678)), "23.67800µs");
# https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml
std_detect_file_io = ["std_detect/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std_detect/std_detect_dlsym_getauxval"]
+std_detect_env_override = ["std_detect/std_detect_env_override"]
[package.metadata.fortanix-sgx]
# Maximum possible number of threads when testing
/// An owning iterator over the entries of a `HashMap`.
///
/// This `struct` is created by the [`into_iter`] method on [`HashMap`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
+/// (provided by the [`IntoIterator`] trait). See its documentation for more.
///
/// [`into_iter`]: IntoIterator::into_iter
+/// [`IntoIterator`]: crate::iter::IntoIterator
///
/// # Example
///
/// An owning iterator over the items of a `HashSet`.
///
/// This `struct` is created by the [`into_iter`] method on [`HashSet`]
-/// (provided by the `IntoIterator` trait). See its documentation for more.
+/// (provided by the [`IntoIterator`] trait). See its documentation for more.
///
/// [`into_iter`]: IntoIterator::into_iter
+/// [`IntoIterator`]: crate::iter::IntoIterator
///
/// # Examples
///
//!
//! ## Sequences
//!
-//! | | get(i) | insert(i) | remove(i) | append | split_off(i) |
-//! |----------------|----------------|-----------------|----------------|--------|----------------|
-//! | [`Vec`] | O(1) | O(n-i)* | O(n-i) | O(m)* | O(n-i) |
-//! | [`VecDeque`] | O(1) | O(min(i, n-i))* | O(min(i, n-i)) | O(m)* | O(min(i, n-i)) |
-//! | [`LinkedList`] | O(min(i, n-i)) | O(min(i, n-i)) | O(min(i, n-i)) | O(1) | O(min(i, n-i)) |
+//! | | get(i) | insert(i) | remove(i) | append | split_off(i) |
+//! |----------------|------------------------|-------------------------|------------------------|-----------|------------------------|
+//! | [`Vec`] | *O*(1) | *O*(*n*-*i*)* | *O*(*n*-*i*) | *O*(*m*)* | *O*(*n*-*i*) |
+//! | [`VecDeque`] | *O*(1) | *O*(min(*i*, *n*-*i*))* | *O*(min(*i*, *n*-*i*)) | *O*(*m*)* | *O*(min(*i*, *n*-*i*)) |
+//! | [`LinkedList`] | *O*(min(*i*, *n*-*i*)) | *O*(min(*i*, *n*-*i*)) | *O*(min(*i*, *n*-*i*)) | *O*(1) | *O*(min(*i*, *n*-*i*)) |
//!
//! Note that where ties occur, [`Vec`] is generally going to be faster than [`VecDeque`], and
//! [`VecDeque`] is generally going to be faster than [`LinkedList`].
//!
//! For Sets, all operations have the cost of the equivalent Map operation.
//!
-//! | | get | insert | remove | range | append |
-//! |--------------|-----------|-----------|-----------|-----------|--------|
-//! | [`HashMap`] | O(1)~ | O(1)~* | O(1)~ | N/A | N/A |
-//! | [`BTreeMap`] | O(log(n)) | O(log(n)) | O(log(n)) | O(log(n)) | O(n+m) |
+//! | | get | insert | remove | range | append |
+//! |--------------|---------------|---------------|---------------|---------------|--------------|
+//! | [`HashMap`] | *O*(1)~ | *O*(1)~* | *O*(1)~ | N/A | N/A |
+//! | [`BTreeMap`] | *O*(log(*n*)) | *O*(log(*n*)) | *O*(log(*n*)) | *O*(log(*n*)) | *O*(*n*+*m*) |
//!
//! # Correct and Efficient Usage of Collections
//!
//! contents by-value. This is great when the collection itself is no longer
//! needed, and the values are needed elsewhere. Using `extend` with `into_iter`
//! is the main way that contents of one collection are moved into another.
-//! `extend` automatically calls `into_iter`, and takes any `T: `[`IntoIterator`].
+//! `extend` automatically calls `into_iter`, and takes any <code>T: [IntoIterator]</code>.
//! Calling `collect` on an iterator itself is also a great way to convert one
//! collection into another. Both of these methods should internally use the
//! capacity management tools discussed in the previous section to do this as
//! assert_eq!(map.keys().next().unwrap().b, "baz");
//! ```
//!
-//! [`IntoIterator`]: crate::iter::IntoIterator
+//! [IntoIterator]: crate::iter::IntoIterator "iter::IntoIterator"
#![stable(feature = "rust1", since = "1.0.0")]
use crate::str;
use crate::string;
use crate::sync::Arc;
+use crate::time;
/// `Error` is a trait representing the basic expectations for error values,
/// i.e., values of type `E` in [`Result<T, E>`].
impl Error for alloc::collections::TryReserveError {}
#[unstable(feature = "duration_checked_float", issue = "83400")]
-impl Error for core::time::FromSecsError {}
+impl Error for time::FromSecsError {}
// Copied from `any.rs`.
impl dyn Error + 'static {
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes ("nul characters") and that the final byte is 0 ("nul terminator").
///
-/// `CString` is to [`&CStr`] as [`String`] is to [`&str`]: the former
+/// `CString` is to <code>&[CStr]</code> as [`String`] is to <code>&[str]</code>: the former
/// in each pair are owned strings; the latter are borrowed
/// references.
///
/// # Creating a `CString`
///
/// A `CString` is created from either a byte slice or a byte vector,
-/// or anything that implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>` (for
+/// or anything that implements <code>[Into]<[Vec]<[u8]>></code> (for
/// example, you can build a `CString` straight out of a [`String`] or
-/// a [`&str`], since both implement that trait).
+/// a <code>&[str]</code>, since both implement that trait).
///
-/// The [`CString::new`] method will actually check that the provided `&[u8]`
+/// The [`CString::new`] method will actually check that the provided <code>&[[u8]]</code>
/// does not have 0 bytes in the middle, and return an error if it
/// finds one.
///
///
/// # Extracting a slice of the whole C string
///
-/// Alternatively, you can obtain a `&[`[`u8`]`]` slice from a
+/// Alternatively, you can obtain a <code>&[[u8]]</code> slice from a
/// `CString` with the [`CString::as_bytes`] method. Slices produced in this
/// way do *not* contain the trailing nul terminator. This is useful
/// when you will be calling an extern function that takes a `*const
/// You can of course get the slice's length with its
/// [`len`][slice::len] method.
///
-/// If you need a `&[`[`u8`]`]` slice *with* the nul terminator, you
+/// If you need a <code>&[[u8]]</code> slice *with* the nul terminator, you
/// can use [`CString::as_bytes_with_nul`] instead.
///
/// Once you have the kind of slice you need (with or without a nul
/// extern functions. See the documentation for that function for a
/// discussion on ensuring the lifetime of the raw pointer.
///
-/// [`&str`]: prim@str
+/// [str]: prim@str "str"
/// [`Deref`]: ops::Deref
-/// [`&CStr`]: CStr
///
/// # Examples
///
/// Representation of a borrowed C string.
///
/// This type represents a borrowed reference to a nul-terminated
-/// array of bytes. It can be constructed safely from a `&[`[`u8`]`]`
+/// array of bytes. It can be constructed safely from a <code>&[[u8]]</code>
/// slice, or unsafely from a raw `*const c_char`. It can then be
-/// converted to a Rust [`&str`] by performing UTF-8 validation, or
+/// converted to a Rust <code>&[str]</code> by performing UTF-8 validation, or
/// into an owned [`CString`].
///
-/// `&CStr` is to [`CString`] as [`&str`] is to [`String`]: the former
+/// `&CStr` is to [`CString`] as <code>&[str]</code> is to [`String`]: the former
/// in each pair are borrowed references; the latter are owned
/// strings.
///
/// println!("string: {}", my_string_safe());
/// ```
///
-/// [`&str`]: prim@str
+/// [str]: prim@str "str"
#[derive(Hash)]
#[cfg_attr(not(test), rustc_diagnostic_item = "CStr")]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe { ptr::read(&this.inner) }
}
- /// Converts a [`Vec`]`<u8>` to a [`CString`] without checking the
+ /// Converts a <code>[Vec]<[u8]></code> to a [`CString`] without checking the
/// invariants on the given [`Vec`].
///
/// # Safety
Self { inner: v.into_boxed_slice() }
}
- /// Attempts to converts a [`Vec`]`<u8>` to a [`CString`].
+ /// Attempts to converts a <code>[Vec]<[u8]></code> to a [`CString`].
///
/// Runtime checks are present to ensure there is only one nul byte in the
/// [`Vec`], its last element.
#[stable(feature = "cstring_into", since = "1.7.0")]
impl From<CString> for Vec<u8> {
- /// Converts a [`CString`] into a [`Vec`]`<u8>`.
+ /// Converts a [`CString`] into a <code>[Vec]<[u8]></code>.
///
/// The conversion consumes the [`CString`], and removes the terminating NUL byte.
#[inline]
#[stable(feature = "c_string_from_box", since = "1.18.0")]
impl From<Box<CStr>> for CString {
- /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
+ /// Converts a <code>[Box]<[CStr]></code> into a [`CString`] without copying or allocating.
#[inline]
fn from(s: Box<CStr>) -> CString {
s.into_c_string()
#[stable(feature = "cstring_from_vec_of_nonzerou8", since = "1.43.0")]
impl From<Vec<NonZeroU8>> for CString {
- /// Converts a [`Vec`]`<`[`NonZeroU8`]`>` into a [`CString`] without
+ /// Converts a <code>[Vec]<[NonZeroU8]></code> into a [`CString`] without
/// copying nor checking for inner null bytes.
#[inline]
fn from(v: Vec<NonZeroU8>) -> CString {
#[stable(feature = "box_from_c_string", since = "1.20.0")]
impl From<CString> for Box<CStr> {
- /// Converts a [`CString`] into a [`Box`]`<CStr>` without copying or allocating.
+ /// Converts a [`CString`] into a <code>[Box]<[CStr]></code> without copying or allocating.
#[inline]
fn from(s: CString) -> Box<CStr> {
s.into_boxed_c_str()
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Arc<CStr> {
- /// Converts a [`CString`] into an [`Arc`]`<CStr>` without copying or allocating.
+ /// Converts a [`CString`] into an <code>[Arc]<[CStr]></code> without copying or allocating.
#[inline]
fn from(s: CString) -> Arc<CStr> {
let arc: Arc<[u8]> = Arc::from(s.into_inner());
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Rc<CStr> {
- /// Converts a [`CString`] into an [`Rc`]`<CStr>` without copying or allocating.
+ /// Converts a [`CString`] into an <code>[Rc]<[CStr]></code> without copying or allocating.
#[inline]
fn from(s: CString) -> Rc<CStr> {
let rc: Rc<[u8]> = Rc::from(s.into_inner());
unsafe { &*(&self.inner as *const [c_char] as *const [u8]) }
}
- /// Yields a [`&str`] slice if the `CStr` contains valid UTF-8.
+ /// Yields a <code>&[str]</code> slice if the `CStr` contains valid UTF-8.
///
/// If the contents of the `CStr` are valid UTF-8 data, this
- /// function will return the corresponding [`&str`] slice. Otherwise,
+ /// function will return the corresponding <code>&[str]</code> slice. Otherwise,
/// it will return an error with details of where UTF-8 validation failed.
///
- /// [`&str`]: prim@str
+ /// [str]: prim@str "str"
///
/// # Examples
///
str::from_utf8(self.to_bytes())
}
- /// Converts a `CStr` into a [`Cow`]`<`[`str`]`>`.
+ /// Converts a `CStr` into a <code>[Cow]<[str]></code>.
///
/// If the contents of the `CStr` are valid UTF-8 data, this
- /// function will return a [`Cow`]`::`[`Borrowed`]`(`[`&str`]`)`
- /// with the corresponding [`&str`] slice. Otherwise, it will
+ /// function will return a <code>[Cow]::[Borrowed]\(&[str])</code>
+ /// with the corresponding <code>&[str]</code> slice. Otherwise, it will
/// replace any invalid UTF-8 sequences with
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
- /// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result.
+ /// <code>[Cow]::[Owned]\(&[str])</code> with the result.
///
- /// [`str`]: primitive@str
- /// [`&str`]: primitive@str
- /// [`Borrowed`]: Cow::Borrowed
- /// [`Owned`]: Cow::Owned
- /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
+ /// [str]: prim@str "str"
+ /// [Borrowed]: Cow::Borrowed
+ /// [Owned]: Cow::Owned
+ /// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER "std::char::REPLACEMENT_CHARACTER"
///
/// # Examples
///
String::from_utf8_lossy(self.to_bytes())
}
- /// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
+ /// Converts a <code>[Box]<[CStr]></code> into a [`CString`] without copying or allocating.
///
/// # Examples
///
//! terminator, so the buffer length is really `len+1` characters.
//! Rust strings don't have a nul terminator; their length is always
//! stored and does not need to be calculated. While in Rust
-//! accessing a string's length is a `O(1)` operation (because the
-//! length is stored); in C it is an `O(length)` operation because the
+//! accessing a string's length is an *O*(1) operation (because the
+//! length is stored); in C it is an *O*(*n*) operation because the
//! length needs to be computed by scanning the string for the nul
//! terminator.
//!
//! string: it is nul-terminated, and has no internal nul characters.
//! Rust code can create a [`CString`] out of a normal string (provided
//! that the string doesn't have nul characters in the middle), and
-//! then use a variety of methods to obtain a raw `*mut `[`u8`] that can
+//! then use a variety of methods to obtain a raw <code>\*mut [u8]</code> that can
//! then be passed as an argument to functions which use the C
//! conventions for strings.
//!
//! * **From C to Rust:** [`CStr`] represents a borrowed C string; it
-//! is what you would use to wrap a raw `*const `[`u8`] that you got from
+//! is what you would use to wrap a raw <code>\*const [u8]</code> that you got from
//! a C function. A [`CStr`] is guaranteed to be a nul-terminated array
//! of bytes. Once you have a [`CStr`], you can convert it to a Rust
-//! [`&str`][`str`] if it's valid UTF-8, or lossily convert it by adding
+//! <code>&[str]</code> if it's valid UTF-8, or lossily convert it by adding
//! replacement characters.
//!
//! [`OsString`] and [`OsStr`] are useful when you need to transfer
//! library, various APIs that transfer strings to/from the operating
//! system use [`OsString`] instead of plain strings. For example,
//! [`env::var_os()`] is used to query environment variables; it
-//! returns an [`Option`]`<`[`OsString`]`>`. If the environment variable
-//! exists you will get a [`Some`]`(os_string)`, which you can *then* try to
-//! convert to a Rust string. This yields a [`Result`], so that
+//! returns an <code>[Option]<[OsString]></code>. If the environment variable
+//! exists you will get a <code>[Some]\(os_string)</code>, which you can
+//! *then* try to convert to a Rust string. This yields a [`Result`], so that
//! your code can detect errors in case the environment variable did
//! not in fact contain valid Unicode data.
//!
//! ## On Unix
//!
//! On Unix, [`OsStr`] implements the
-//! `std::os::unix::ffi::`[`OsStrExt`][unix.OsStrExt] trait, which
+//! <code>std::os::unix::ffi::[OsStrExt][unix.OsStrExt]</code> trait, which
//! augments it with two methods, [`from_bytes`] and [`as_bytes`].
//! These do inexpensive conversions from and to UTF-8 byte slices.
//!
//! Additionally, on Unix [`OsString`] implements the
-//! `std::os::unix::ffi::`[`OsStringExt`][unix.OsStringExt] trait,
+//! <code>std::os::unix::ffi::[OsStringExt][unix.OsStringExt]</code> trait,
//! which provides [`from_vec`] and [`into_vec`] methods that consume
//! their arguments, and take or produce vectors of [`u8`].
//!
//! ## On Windows
//!
//! On Windows, [`OsStr`] implements the
-//! `std::os::windows::ffi::`[`OsStrExt`][windows.OsStrExt] trait,
+//! <code>std::os::windows::ffi::[OsStrExt][windows.OsStrExt]</code> trait,
//! which provides an [`encode_wide`] method. This provides an
//! iterator that can be [`collect`]ed into a vector of [`u16`].
//!
//! Additionally, on Windows [`OsString`] implements the
-//! `std::os::windows:ffi::`[`OsStringExt`][windows.OsStringExt]
+//! <code>std::os::windows:ffi::[OsStringExt][windows.OsStringExt]</code>
//! trait, which provides a [`from_wide`] method. The result of this
//! method is an [`OsString`] which can be round-tripped to a Windows
//! string losslessly.
//!
//! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
//! [Unicode code point]: https://www.unicode.org/glossary/#code_point
-//! [`env::set_var()`]: crate::env::set_var
-//! [`env::var_os()`]: crate::env::var_os
-//! [unix.OsStringExt]: crate::os::unix::ffi::OsStringExt
-//! [`from_vec`]: crate::os::unix::ffi::OsStringExt::from_vec
-//! [`into_vec`]: crate::os::unix::ffi::OsStringExt::into_vec
-//! [unix.OsStrExt]: crate::os::unix::ffi::OsStrExt
-//! [`from_bytes`]: crate::os::unix::ffi::OsStrExt::from_bytes
-//! [`as_bytes`]: crate::os::unix::ffi::OsStrExt::as_bytes
-//! [`OsStrExt`]: crate::os::unix::ffi::OsStrExt
-//! [windows.OsStrExt]: crate::os::windows::ffi::OsStrExt
-//! [`encode_wide`]: crate::os::windows::ffi::OsStrExt::encode_wide
-//! [`collect`]: crate::iter::Iterator::collect
-//! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt
-//! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide
+//! [`env::set_var()`]: crate::env::set_var "env::set_var"
+//! [`env::var_os()`]: crate::env::var_os "env::var_os"
+//! [unix.OsStringExt]: crate::os::unix::ffi::OsStringExt "os::unix::ffi::OsStringExt"
+//! [`from_vec`]: crate::os::unix::ffi::OsStringExt::from_vec "os::unix::ffi::OsStringExt::from_vec"
+//! [`into_vec`]: crate::os::unix::ffi::OsStringExt::into_vec "os::unix::ffi::OsStringExt::into_vec"
+//! [unix.OsStrExt]: crate::os::unix::ffi::OsStrExt "os::unix::ffi::OsStrExt"
+//! [`from_bytes`]: crate::os::unix::ffi::OsStrExt::from_bytes "os::unix::ffi::OsStrExt::from_bytes"
+//! [`as_bytes`]: crate::os::unix::ffi::OsStrExt::as_bytes "os::unix::ffi::OsStrExt::as_bytes"
+//! [`OsStrExt`]: crate::os::unix::ffi::OsStrExt "os::unix::ffi::OsStrExt"
+//! [windows.OsStrExt]: crate::os::windows::ffi::OsStrExt "os::windows::ffi::OsStrExt"
+//! [`encode_wide`]: crate::os::windows::ffi::OsStrExt::encode_wide "os::windows::ffi::OsStrExt::encode_wide"
+//! [`collect`]: crate::iter::Iterator::collect "iter::Iterator::collect"
+//! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt "os::windows::ffi::OsStringExt"
+//! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide "os::windows::ffi::OsStringExt::from_wide"
#![stable(feature = "rust1", since = "1.0.0")]
/// of this is that `OsString` instances are *not* `NUL` terminated; in order
/// to pass to e.g., Unix system call, you should create a [`CStr`].
///
-/// `OsString` is to [`&OsStr`] as [`String`] is to [`&str`]: the former
+/// `OsString` is to <code>&[OsStr]</code> as [`String`] is to <code>&[str]</code>: the former
/// in each pair are owned strings; the latter are borrowed
/// references.
///
/// # Creating an `OsString`
///
/// **From a Rust string**: `OsString` implements
-/// [`From`]`<`[`String`]`>`, so you can use `my_string.from` to
+/// <code>[From]<[String]></code>, so you can use <code>my_string.[into]\()</code> to
/// create an `OsString` from a normal Rust string.
///
/// **From slices:** Just like you can start with an empty Rust
-/// [`String`] and then [`String::push_str`] `&str`
+/// [`String`] and then [`String::push_str`] some <code>&[str]</code>
/// sub-string slices into it, you can create an empty `OsString` with
/// the [`OsString::new`] method and then push string slices into it with the
/// [`OsString::push`] method.
///
/// # Extracting a borrowed reference to the whole OS string
///
-/// You can use the [`OsString::as_os_str`] method to get an `&`[`OsStr`] from
+/// You can use the [`OsString::as_os_str`] method to get an <code>&[OsStr]</code> from
/// an `OsString`; this is effectively a borrowed reference to the
/// whole string.
///
/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
/// the traits which `OsString` implements for [conversions] from/to native representations.
///
-/// [`&OsStr`]: OsStr
-/// [`&str`]: str
/// [`CStr`]: crate::ffi::CStr
/// [conversions]: super#conversions
+/// [into]: Into::into
#[cfg_attr(not(test), rustc_diagnostic_item = "OsString")]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct OsString {
/// This type represents a borrowed reference to a string in the operating system's preferred
/// representation.
///
-/// `&OsStr` is to [`OsString`] as [`&str`] is to [`String`]: the former in each pair are borrowed
-/// references; the latter are owned strings.
+/// `&OsStr` is to [`OsString`] as <code>&[str]</code> is to [`String`]: the
+/// former in each pair are borrowed references; the latter are owned strings.
///
/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
/// the traits which `OsStr` implements for [conversions] from/to native representations.
///
-/// [`&str`]: str
/// [conversions]: super#conversions
#[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")]
#[stable(feature = "rust1", since = "1.0.0")]
self.inner.into_string().map_err(|buf| OsString { inner: buf })
}
- /// Extends the string with the given [`&OsStr`] slice.
- ///
- /// [`&OsStr`]: OsStr
+ /// Extends the string with the given <code>&[OsStr]</code> slice.
///
/// # Examples
///
unsafe { &mut *(inner as *mut Slice as *mut OsStr) }
}
- /// Yields a [`&str`] slice if the `OsStr` is valid Unicode.
+ /// Yields a <code>&[str]</code> slice if the `OsStr` is valid Unicode.
///
/// This conversion may entail doing a check for UTF-8 validity.
///
- /// [`&str`]: str
- ///
/// # Examples
///
/// ```
self.inner.to_str()
}
- /// Converts an `OsStr` to a [`Cow`]`<`[`str`]`>`.
+ /// Converts an `OsStr` to a <code>[Cow]<[str]></code>.
///
/// Any non-Unicode sequences are replaced with
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
self.inner.inner.len()
}
- /// Converts a [`Box`]`<OsStr>` into an [`OsString`] without copying or allocating.
+ /// Converts a <code>[Box]<[OsStr]></code> into an [`OsString`] without copying or allocating.
#[stable(feature = "into_boxed_os_str", since = "1.20.0")]
pub fn into_os_string(self: Box<OsStr>) -> OsString {
let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
#[stable(feature = "os_string_from_box", since = "1.18.0")]
impl From<Box<OsStr>> for OsString {
- /// Converts a [`Box`]`<`[`OsStr`]`>` into an [`OsString`] without copying or
+ /// Converts a <code>[Box]<[OsStr]></code> into an [`OsString`] without copying or
/// allocating.
#[inline]
fn from(boxed: Box<OsStr>) -> OsString {
#[stable(feature = "box_from_os_string", since = "1.20.0")]
impl From<OsString> for Box<OsStr> {
- /// Converts an [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
+ /// Converts an [`OsString`] into a <code>[Box]<[OsStr]></code> without copying or allocating.
#[inline]
fn from(s: OsString) -> Box<OsStr> {
s.into_boxed_os_str()
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Arc<OsStr> {
- /// Converts an [`OsString`] into an [`Arc`]`<OsStr>` without copying or allocating.
+ /// Converts an [`OsString`] into an <code>[Arc]<[OsStr]></code> without copying or allocating.
#[inline]
fn from(s: OsString) -> Arc<OsStr> {
let arc = s.inner.into_arc();
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Rc<OsStr> {
- /// Converts an [`OsString`] into an [`Rc`]`<OsStr>` without copying or allocating.
+ /// Converts an [`OsString`] into an <code>[Rc]<[OsStr]></code> without copying or allocating.
#[inline]
fn from(s: OsString) -> Rc<OsStr> {
let rc = s.inner.into_rc();
/// Iterator over the entries in a directory.
///
/// This iterator is returned from the [`read_dir`] function of this module and
-/// will yield instances of [`io::Result`]`<`[`DirEntry`]`>`. Through a [`DirEntry`]
+/// will yield instances of <code>[io::Result]<[DirEntry]></code>. Through a [`DirEntry`]
/// information like the entry's path and possibly other metadata can be
/// learned.
///
/// If a file is opened with both read and append access, beware that after
/// opening, and after every write, the position for reading may be set at the
/// end of the file. So, before writing, save the current position (using
- /// [`seek`]`(`[`SeekFrom`]`::`[`Current`]`(0))`), and restore it before the next read.
+ /// <code>[seek]\([SeekFrom]::[Current]\(0))</code>), and restore it before the next read.
///
/// ## Note
///
/// This function doesn't create the file if it doesn't exist. Use the
/// [`OpenOptions::create`] method to do so.
///
- /// [`write()`]: Write::write
- /// [`flush()`]: Write::flush
- /// [`seek`]: Seek::seek
- /// [`Current`]: SeekFrom::Current
+ /// [`write()`]: Write::write "io::Write::write"
+ /// [`flush()`]: Write::flush "io::Write::flush"
+ /// [seek]: Seek::seek "io::Seek::seek"
+ /// [Current]: SeekFrom::Current "io::SeekFrom::Current"
///
/// # Examples
///
/// Returns an iterator over the entries within a directory.
///
-/// The iterator will yield instances of [`io::Result`]`<`[`DirEntry`]`>`.
+/// The iterator will yield instances of <code>[io::Result]<[DirEntry]></code>.
/// New errors may be encountered after an iterator is initially constructed.
/// Entries for the current and parent directories (typically `.` and `..`) are
/// skipped.
/// *repeated* read calls to the same file or network socket. It does not
/// help when reading very large amounts at once, or reading just one or a few
/// times. It also provides no advantage when reading from a source that is
-/// already in memory, like a [`Vec`]`<u8>`.
+/// already in memory, like a <code>[Vec]\<u8></code>.
///
/// When the `BufReader<R>` is dropped, the contents of its buffer will be
/// discarded. Creating multiple instances of a `BufReader<R>` on the same
impl<R: Seek> Seek for BufReader<R> {
/// Seek to an offset, in bytes, in the underlying reader.
///
- /// The position used for seeking with [`SeekFrom::Current`]`(_)` is the
+ /// The position used for seeking with <code>[SeekFrom::Current]\(_)</code> is the
/// position the underlying reader would be at if the `BufReader<R>` had no
/// internal buffer.
///
///
/// See [`std::io::Seek`] for more details.
///
- /// Note: In the edge case where you're seeking with [`SeekFrom::Current`]`(n)`
+ /// Note: In the edge case where you're seeking with <code>[SeekFrom::Current]\(n)</code>
/// where `n` minus the internal buffer length overflows an `i64`, two
/// seeks will be performed instead of one. If the second seek returns
/// [`Err`], the underlying reader will be left at the same position it would
- /// have if you called `seek` with [`SeekFrom::Current`]`(0)`.
+ /// have if you called `seek` with <code>[SeekFrom::Current]\(0)</code>.
///
/// [`std::io::Seek`]: Seek
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
/// *repeated* write calls to the same file or network socket. It does not
/// help when writing very large amounts at once, or writing just one or a few
/// times. It also provides no advantage when writing to a destination that is
-/// in memory, like a [`Vec`]`<u8>`.
+/// in memory, like a <code>[Vec]\<u8></code>.
///
/// It is critical to call [`flush`] before `BufWriter<W>` is dropped. Though
/// dropping will attempt to flush the contents of the buffer, any errors
/// [`Seek`] implementation.
///
/// `Cursor`s are used with in-memory buffers, anything implementing
-/// [`AsRef`]`<[u8]>`, to allow them to implement [`Read`] and/or [`Write`],
+/// <code>[AsRef]<\[u8]></code>, to allow them to implement [`Read`] and/or [`Write`],
/// allowing these buffers to be used anywhere you might use a reader or writer
/// that does actual I/O.
///
/// The standard library implements some I/O traits on various types which
-/// are commonly used as a buffer, like `Cursor<`[`Vec`]`<u8>>` and
-/// `Cursor<`[`&[u8]`][bytes]`>`.
+/// are commonly used as a buffer, like <code>Cursor<[Vec]\<u8>></code> and
+/// <code>Cursor<[&\[u8\]][bytes]></code>.
///
/// # Examples
///
/// code, but use an in-memory buffer in our tests. We can do this with
/// `Cursor`:
///
-/// [bytes]: crate::slice
+/// [bytes]: crate::slice "slice"
/// [`File`]: crate::fs::File
///
/// ```no_run
/// Transforms this `Read` instance to an [`Iterator`] over its bytes.
///
- /// The returned type implements [`Iterator`] where the `Item` is
- /// [`Result`]`<`[`u8`]`, `[`io::Error`]`>`.
+ /// The returned type implements [`Iterator`] where the [`Item`] is
+ /// <code>[Result]<[u8], [io::Error]></code>.
/// The yielded item is [`Ok`] if a byte was successfully read and [`Err`]
/// otherwise. EOF is mapped to returning [`None`] from this iterator.
///
///
/// [`File`]s implement `Read`:
///
- /// [`File`]: crate::fs::File
- /// [`Result`]: crate::result::Result
- /// [`io::Error`]: self::Error
+ /// [`Item`]: Iterator::Item
+ /// [`File`]: crate::fs::File "fs::File"
+ /// [Result]: crate::result::Result "Result"
+ /// [io::Error]: self::Error "io::Error"
///
/// ```no_run
/// use std::io;
/// `byte`.
///
/// The iterator returned from this function will return instances of
- /// [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
+ /// <code>[io::Result]<[Vec]\<u8>></code>. Each vector returned will *not* have
/// the delimiter byte at the end.
///
/// This function will yield errors whenever [`read_until`] would have
/// also yielded an error.
///
- /// [`io::Result`]: self::Result
+ /// [io::Result]: self::Result "io::Result"
/// [`read_until`]: BufRead::read_until
///
/// # Examples
/// Returns an iterator over the lines of this reader.
///
/// The iterator returned from this function will yield instances of
- /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline
+ /// <code>[io::Result]<[String]></code>. Each string returned will *not* have a newline
/// byte (the `0xA` byte) or `CRLF` (`0xD`, `0xA` bytes) at the end.
///
- /// [`io::Result`]: self::Result
+ /// [io::Result]: self::Result "io::Result"
///
/// # Examples
///
/// Constructs a new handle to an empty reader.
///
-/// All reads from the returned reader will return [`Ok`]`(0)`.
+/// All reads from the returned reader will return <code>[Ok]\(0)</code>.
///
/// # Examples
///
///
/// * [`SocketAddr`]: [`to_socket_addrs`] is the identity function.
///
-/// * [`SocketAddrV4`], [`SocketAddrV6`], `(`[`IpAddr`]`, `[`u16`]`)`,
-/// `(`[`Ipv4Addr`]`, `[`u16`]`)`, `(`[`Ipv6Addr`]`, `[`u16`]`)`:
+/// * [`SocketAddrV4`], [`SocketAddrV6`], <code>([IpAddr], [u16])</code>,
+/// <code>([Ipv4Addr], [u16])</code>, <code>([Ipv6Addr], [u16])</code>:
/// [`to_socket_addrs`] constructs a [`SocketAddr`] trivially.
///
-/// * `(`[`&str`]`, `[`u16`]`)`: [`&str`] should be either a string representation
+/// * <code>(&[str], [u16])</code>: <code>&[str]</code> should be either a string representation
/// of an [`IpAddr`] address as expected by [`FromStr`] implementation or a host
/// name. [`u16`] is the port number.
///
-/// * [`&str`]: the string should be either a string representation of a
+/// * <code>&[str]</code>: the string should be either a string representation of a
/// [`SocketAddr`] as expected by its [`FromStr`] implementation or a string like
/// `<host_name>:<port>` pair where `<port>` is a [`u16`] value.
///
/// Addresses returned by the operating system that are not IP addresses are
/// silently ignored.
///
-/// [`FromStr`]: crate::str::FromStr
-/// [`&str`]: str
-/// [`TcpStream`]: crate::net::TcpStream
+/// [`FromStr`]: crate::str::FromStr "std::str::FromStr"
+/// [`TcpStream`]: crate::net::TcpStream "net::TcpStream"
/// [`to_socket_addrs`]: ToSocketAddrs::to_socket_addrs
-/// [`UdpSocket`]: crate::net::UdpSocket
+/// [`UdpSocket`]: crate::net::UdpSocket "net::UdpSocket"
///
/// # Examples
///
#[stable(feature = "rust1", since = "1.0.0")]
type Iter: Iterator<Item = SocketAddr>;
- /// Converts this object to an iterator of resolved `SocketAddr`s.
+ /// Converts this object to an iterator of resolved [`SocketAddr`]s.
///
/// The returned iterator might not actually yield any values depending on the
/// outcome of any resolution performed.
pub enum Shutdown {
/// The reading portion of the [`TcpStream`] should be shut down.
///
- /// All currently blocked and future [reads] will return [`Ok`]`(0)`.
+ /// All currently blocked and future [reads] will return <code>[Ok]\(0)</code>.
///
- /// [reads]: crate::io::Read
+ /// [reads]: crate::io::Read "io::Read"
#[stable(feature = "rust1", since = "1.0.0")]
Read,
/// The writing portion of the [`TcpStream`] should be shut down.
///
/// All currently blocked and future [writes] will return an error.
///
- /// [writes]: crate::io::Write
+ /// [writes]: crate::io::Write "io::Write"
#[stable(feature = "rust1", since = "1.0.0")]
Write,
/// Both the reading and the writing portions of the [`TcpStream`] should be shut down.
Equivalent to C's `char` type.
-[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. This type will always be either [`i8`] or [`u8`], as the type is defined as being one byte long.
+[C's `char` type] is completely unlike [Rust's `char` type]; while Rust's type represents a unicode scalar value, C's `char` type is just an ordinary integer. On modern architectures this type will always be either [`i8`] or [`u8`], as they use byte-addresses memory with 8-bit bytes.
C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information.
/// Returns an iterator over the entries within a directory.
///
- /// The iterator will yield instances of [`io::Result`]`<`[`fs::DirEntry`]`>`. New
+ /// The iterator will yield instances of <code>[io::Result]<[fs::DirEntry]></code>. New
/// errors may be encountered after an iterator is initially constructed.
///
/// This is an alias to [`fs::read_dir`].
// Returns true if blocking should proceed.
fn decrement(&self, token: SignalToken) -> StartResult {
unsafe {
- assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
+ assert_eq!(
+ self.to_wake.load(Ordering::SeqCst),
+ 0,
+ "This is a known bug in the Rust standard library. See https://github.com/rust-lang/rust/issues/39364"
+ );
let ptr = token.cast_to_usize();
self.to_wake.store(ptr, Ordering::SeqCst);
let mut info: c::FILE_BASIC_INFO = mem::zeroed();
let size = mem::size_of_val(&info);
cvt(c::GetFileInformationByHandleEx(
- self.handle.raw(),
+ self.handle.as_raw_handle(),
c::FileBasicInfo,
&mut info as *mut _ as *mut libc::c_void,
size as c::DWORD,
let mut info: c::FILE_STANDARD_INFO = mem::zeroed();
let size = mem::size_of_val(&info);
cvt(c::GetFileInformationByHandleEx(
- self.handle.raw(),
+ self.handle.as_raw_handle(),
c::FileStandardInfo,
&mut info as *mut _ as *mut libc::c_void,
size as c::DWORD,
use crate::io;
use crate::mem::ManuallyDrop;
+use crate::os::windows::io::FromRawHandle;
use crate::sys::c;
use crate::sys::handle::Handle;
fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result<usize> {
let handle = get_handle(handle_id)?;
- let handle = Handle::new(handle);
+ // SAFETY: The handle returned from `get_handle` must be valid and non-null.
+ let handle = unsafe { Handle::from_raw_handle(handle) };
ManuallyDrop::new(handle).write(data)
}
impl io::Read for Stdin {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let handle = get_handle(c::STD_INPUT_HANDLE)?;
- let handle = Handle::new(handle);
+ // SAFETY: The handle returned from `get_handle` must be valid and non-null.
+ let handle = unsafe { Handle::from_raw_handle(handle) };
ManuallyDrop::new(handle).read(buf)
}
}
#[stable(feature = "time", since = "1.3.0")]
pub use core::time::Duration;
+#[unstable(feature = "duration_checked_float", issue = "83400")]
+pub use core::time::FromSecsError;
+
/// A measurement of a monotonically nondecreasing clock.
/// Opaque and useful only with [`Duration`].
///
/// as the system clock being adjusted either forwards or backwards).
/// [`Instant`] can be used to measure elapsed time without this risk of failure.
///
- /// If successful, [`Ok`]`(`[`Duration`]`)` is returned where the duration represents
+ /// If successful, <code>[Ok]\([Duration])</code> is returned where the duration represents
/// the amount of time elapsed from the specified measurement to this one.
///
/// Returns an [`Err`] if `earlier` is later than `self`, and the error
///
/// This function may fail as the underlying system clock is susceptible to
/// drift and updates (e.g., the system clock could go backwards), so this
- /// function might not always succeed. If successful, [`Ok`]`(`[`Duration`]`)` is
+ /// function might not always succeed. If successful, <code>[Ok]\([Duration])</code> is
/// returned where the duration represents the amount of time elapsed from
/// this time measurement to the current time.
///
profiler = ["std/profiler"]
std_detect_file_io = ["std/std_detect_file_io"]
std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
+std_detect_env_override = ["std/std_detect_env_override"]
[package]
name = "bootstrap"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
build = "build.rs"
[lib]
let mut cargo = builder.cargo(
compiler,
Mode::Codegen,
- SourceType::Submodule,
+ SourceType::InTree,
target,
cargo_subcommand(builder.kind),
);
let out_dir = builder.cargo_out(compiler, Mode::Codegen, target);
- let mut cargo =
- builder.cargo(compiler, Mode::Codegen, SourceType::Submodule, target, "build");
+ let mut cargo = builder.cargo(compiler, Mode::Codegen, SourceType::InTree, target, "build");
cargo
.arg("--manifest-path")
.arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
cargo.rustdocflag("--document-private-items");
cargo.rustdocflag("--enable-index-page");
cargo.rustdocflag("--show-type-layout");
+ cargo.rustdocflag("--generate-link-to-definition");
cargo.rustdocflag("-Zunstable-options");
builder.run(&mut cargo.into());
}
{
eprintln!(
"
-Couldn't find required command: ninja
-You should install ninja, or set `ninja=false` in config.toml in the `[llvm]` section.
+Couldn't find required command: ninja (or ninja-build)
+
+You should install ninja as described at
+<https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages>,
+or set `ninja = false` in the `[llvm]` section of `config.toml`.
+Alternatively, set `download-ci-llvm = true` in that `[llvm]` section
+to download LLVM rather than building it.
"
);
std::process::exit(1);
host,
"test",
"src/tools/rustfmt",
- SourceType::Submodule,
+ SourceType::InTree,
&[],
);
[package]
name = "build_helper"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[lib]
path = "lib.rs"
`rustdoc` will disable this sorting and instead make it print the items in the order they appear in
the source.
+### `--show-type-layout`: add a section to each type's docs describing its memory layout
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc src/lib.rs -Z unstable-options --show-type-layout
+```
+
+When this flag is passed, rustdoc will add a "Layout" section at the bottom of
+each type's docs page that includes a summary of the type's memory layout as
+computed by rustc. For example, rustdoc will show the size in bytes that a value
+of that type will take in memory.
+
+Note that most layout information is **completely unstable** and may even differ
+between compilations.
+
### `--resource-suffix`: modifying the name of CSS/JavaScript in crate docs
Using this flag looks like this:
Public items that are not documented can be seen with the built-in `missing_docs` lint. Private
items that are not documented can be seen with Clippy's `missing_docs_in_private_items` lint.
-## `-w`/`--output-format`: output format
+### `-w`/`--output-format`: output format
When using
[`--show-coverage`](https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#--show-coverage-get-statistics-about-code-documentation-coverage),
--- /dev/null
+# `closure_track_caller`
+
+The tracking issue for this feature is: [#87417]
+
+[#87417]: https://github.com/rust-lang/rust/issues/87417
+
+------------------------
+
+Allows using the `#[track_caller]` attribute on closures and generators.
+Calls made to the closure or generator will have caller information
+available through `std::panic::Location::caller()`, just like using
+`#[track_caller]` on a function.
[package]
name = "test-float-parse"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
publish = false
[workspace]
[package]
name = "rustdoc"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[lib]
path = "lib.rs"
attrs: Default::default(),
visibility: Inherited,
def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
- kind: Box::new(ImplItem(Impl {
+ kind: box ImplItem(Impl {
span: Span::dummy(),
unsafety: hir::Unsafety::Normal,
generics: new_generics,
negative_polarity,
synthetic: true,
blanket_impl: None,
- })),
+ }),
cfg: None,
})
}
let (poly_trait, output) =
(data.0.as_ref().unwrap().clone(), data.1.as_ref().cloned().map(Box::new));
let new_ty = match poly_trait.trait_ {
- Type::ResolvedPath { ref path, ref did, ref is_generic } => {
+ Type::ResolvedPath { ref path, ref did } => {
let mut new_path = path.clone();
let last_segment =
new_path.segments.pop().expect("segments were empty");
.segments
.push(PathSegment { name: last_segment.name, args: new_params });
- Type::ResolvedPath {
- path: new_path,
- did: *did,
- is_generic: *is_generic,
- }
+ Type::ResolvedPath { path: new_path, did: *did }
}
_ => panic!("Unexpected data: {:?}, {:?}", ty, data),
};
Type::QPath { name: left_name, ref self_type, ref trait_, .. } => {
let ty = &*self_type;
match **trait_ {
- Type::ResolvedPath {
- path: ref trait_path,
- ref did,
- ref is_generic,
- } => {
+ Type::ResolvedPath { path: ref trait_path, ref did } => {
let mut new_trait_path = trait_path.clone();
if self.is_fn_ty(trait_) && left_name == sym::Output {
trait_: Type::ResolvedPath {
path: new_trait_path,
did: *did,
- is_generic: *is_generic,
},
generic_params: Vec::new(),
},
.instantiate(self.cx.tcx, impl_substs)
.predicates
.into_iter()
- .chain(Some(trait_ref.without_const().to_predicate(infcx.tcx)));
+ .chain(Some(
+ ty::Binder::dummy(trait_ref)
+ .without_const()
+ .to_predicate(infcx.tcx),
+ ));
for predicate in predicates {
debug!("testing predicate {:?}", predicate);
let obligation = traits::Obligation::new(
attrs: Default::default(),
visibility: Inherited,
def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
- kind: Box::new(ImplItem(Impl {
+ kind: box ImplItem(Impl {
span: Span::new(self.cx.tcx.def_span(impl_def_id)),
unsafety: hir::Unsafety::Normal,
generics: (
.clean(self.cx),
negative_polarity: false,
synthetic: false,
- blanket_impl: Some(Box::new(trait_ref.self_ty().clean(self.cx))),
- })),
+ blanket_impl: Some(box trait_ref.self_ty().clean(self.cx)),
+ }),
cfg: None,
});
}
let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs_clone);
cx.inlined.insert(did.into());
- let mut item = clean::Item::from_def_id_and_attrs_and_parts(
- did,
- Some(name),
- kind,
- Box::new(attrs),
- cx,
- cfg,
- );
+ let mut item =
+ clean::Item::from_def_id_and_attrs_and_parts(did, Some(name), kind, box attrs, cx, cfg);
if let Some(import_def_id) = import_def_id {
// The visibility needs to reflect the one from the reexport and not from the "source" DefId.
item.visibility = cx.tcx.visibility(import_def_id).clean(cx);
}
}
+ let document_hidden = cx.render_options.document_hidden;
let predicates = tcx.explicit_predicates_of(did);
let (trait_items, generics) = match impl_item {
Some(impl_) => (
impl_
.items
.iter()
- .map(|item| tcx.hir().impl_item(item.id).clean(cx))
+ .map(|item| tcx.hir().impl_item(item.id))
+ .filter(|item| {
+ // Filter out impl items whose corresponding trait item has `doc(hidden)`
+ // not to document such impl items.
+ // For inherent impls, we don't do any filtering, because that's already done in strip_hidden.rs.
+
+ // When `--document-hidden-items` is passed, we don't
+ // do any filtering, too.
+ if document_hidden {
+ return true;
+ }
+ if let Some(associated_trait) = associated_trait {
+ let assoc_kind = match item.kind {
+ hir::ImplItemKind::Const(..) => ty::AssocKind::Const,
+ hir::ImplItemKind::Fn(..) => ty::AssocKind::Fn,
+ hir::ImplItemKind::TyAlias(..) => ty::AssocKind::Type,
+ };
+ let trait_item = tcx
+ .associated_items(associated_trait.def_id)
+ .find_by_name_and_kind(
+ tcx,
+ item.ident,
+ assoc_kind,
+ associated_trait.def_id,
+ )
+ .unwrap(); // SAFETY: For all impl items there exists trait item that has the same name.
+ !tcx.get_attrs(trait_item.def_id).lists(sym::doc).has_word(sym::hidden)
+ } else {
+ true
+ }
+ })
+ .map(|item| item.clean(cx))
.collect::<Vec<_>>(),
impl_.generics.clean(cx),
),
synthetic: false,
blanket_impl: None,
}),
- Box::new(merged_attrs),
+ box merged_attrs,
cx,
cfg,
));
let prim_ty = clean::PrimitiveType::from(p);
items.push(clean::Item {
name: None,
- attrs: Box::new(clean::Attributes::default()),
+ attrs: box clean::Attributes::default(),
def_id: ItemId::Primitive(prim_ty, did.krate),
visibility: clean::Public,
- kind: Box::new(clean::ImportItem(clean::Import::new_simple(
+ kind: box clean::ImportItem(clean::Import::new_simple(
item.ident.name,
clean::ImportSource {
path: clean::Path {
did: None,
},
true,
- ))),
+ )),
cfg: None,
});
} else if let Some(i) = try_inline(cx, did, None, res, item.ident.name, None, visited) {
hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
- let trait_ref = ty::TraitRef::identity(cx.tcx, def_id);
+ let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder();
let generic_args = generic_args.clean(cx);
let bindings = match generic_args {
debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
- ResolvedPath { path, did: trait_ref.def_id, is_generic: false }
+ ResolvedPath { path, did: trait_ref.def_id }
}
}
Type::QPath {
name: cx.tcx.associated_item(self.item_def_id).ident.name,
self_def_id: self_type.def_id(),
- self_type: Box::new(self_type),
- trait_: Box::new(trait_),
+ self_type: box self_type,
+ trait_: box trait_,
}
}
}
Type::QPath {
name: p.segments.last().expect("segments were empty").ident.name,
self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
- self_type: Box::new(qself.clean(cx)),
- trait_: Box::new(resolve_type(cx, trait_path)),
+ self_type: box qself.clean(cx),
+ trait_: box resolve_type(cx, trait_path),
}
}
hir::QPath::TypeRelative(ref qself, ref segment) => {
Type::QPath {
name: segment.ident.name,
self_def_id: res.opt_def_id(),
- self_type: Box::new(qself.clean(cx)),
- trait_: Box::new(resolve_type(cx, trait_path)),
+ self_type: box qself.clean(cx),
+ trait_: box resolve_type(cx, trait_path),
}
}
hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
match self.kind {
TyKind::Never => Never,
- TyKind::Ptr(ref m) => RawPointer(m.mutbl, Box::new(m.ty.clean(cx))),
+ TyKind::Ptr(ref m) => RawPointer(m.mutbl, box m.ty.clean(cx)),
TyKind::Rptr(ref l, ref m) => {
// There are two times a `Fresh` lifetime can be created:
// 1. For `&'_ x`, written by the user. This corresponds to `lower_lifetime` in `rustc_ast_lowering`.
let elided =
l.is_elided() || matches!(l.name, LifetimeName::Param(ParamName::Fresh(_)));
let lifetime = if elided { None } else { Some(l.clean(cx)) };
- BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(m.ty.clean(cx)) }
+ BorrowedRef { lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx) }
}
- TyKind::Slice(ref ty) => Slice(Box::new(ty.clean(cx))),
+ TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
TyKind::Array(ref ty, ref length) => {
let def_id = cx.tcx.hir().local_def_id(length.hir_id);
// NOTE(min_const_generics): We can't use `const_eval_poly` for constants
let ct = ty::Const::from_anon_const(cx.tcx, def_id);
let param_env = cx.tcx.param_env(def_id);
let length = print_const(cx, ct.eval(cx.tcx, param_env));
- Array(Box::new(ty.clean(cx)), length)
+ Array(box ty.clean(cx), length)
}
TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
TyKind::OpaqueDef(item_id, _) => {
let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None };
DynTrait(bounds, lifetime)
}
- TyKind::BareFn(ref barefn) => BareFunction(Box::new(barefn.clean(cx))),
+ TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
// Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s.
TyKind::Infer | TyKind::Err => Infer,
TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind),
ty::Uint(uint_ty) => Primitive(uint_ty.into()),
ty::Float(float_ty) => Primitive(float_ty.into()),
ty::Str => Primitive(PrimitiveType::Str),
- ty::Slice(ty) => Slice(Box::new(ty.clean(cx))),
+ ty::Slice(ty) => Slice(box ty.clean(cx)),
ty::Array(ty, n) => {
let mut n = cx.tcx.lift(n).expect("array lift failed");
n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
let n = print_const(cx, n);
- Array(Box::new(ty.clean(cx)), n)
+ Array(box ty.clean(cx), n)
+ }
+ ty::RawPtr(mt) => RawPointer(mt.mutbl, box mt.ty.clean(cx)),
+ ty::Ref(r, ty, mutbl) => {
+ BorrowedRef { lifetime: r.clean(cx), mutability: mutbl, type_: box ty.clean(cx) }
}
- ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(mt.ty.clean(cx))),
- ty::Ref(r, ty, mutbl) => BorrowedRef {
- lifetime: r.clean(cx),
- mutability: mutbl,
- type_: Box::new(ty.clean(cx)),
- },
ty::FnDef(..) | ty::FnPtr(_) => {
let ty = cx.tcx.lift(*self).expect("FnPtr lift failed");
let sig = ty.fn_sig(cx.tcx);
let def_id = DefId::local(CRATE_DEF_INDEX);
- BareFunction(Box::new(BareFunctionDecl {
+ BareFunction(box BareFunctionDecl {
unsafety: sig.unsafety(),
generic_params: Vec::new(),
decl: (def_id, sig).clean(cx),
abi: sig.abi(),
- }))
+ })
}
ty::Adt(def, substs) => {
let did = def.did;
};
inline::record_extern_fqn(cx, did, kind);
let path = external_path(cx, did, false, vec![], substs);
- ResolvedPath { path, did, is_generic: false }
+ ResolvedPath { path, did }
}
ty::Foreign(did) => {
inline::record_extern_fqn(cx, did, ItemType::ForeignType);
let path = external_path(cx, did, false, vec![], InternalSubsts::empty());
- ResolvedPath { path, did, is_generic: false }
+ ResolvedPath { path, did }
}
ty::Dynamic(ref obj, ref reg) => {
// HACK: pick the first `did` as the `did` of the trait object. Someone
let path = external_path(cx, did, false, vec![], empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
let bound = PolyTrait {
- trait_: ResolvedPath { path, did, is_generic: false },
+ trait_: ResolvedPath { path, did },
generic_params: Vec::new(),
};
bounds.push(bound);
let path = external_path(cx, did, false, bindings, substs);
bounds.insert(
0,
- PolyTrait {
- trait_: ResolvedPath { path, did, is_generic: false },
- generic_params: Vec::new(),
- },
+ PolyTrait { trait_: ResolvedPath { path, did }, generic_params: Vec::new() },
);
DynTrait(bounds, lifetime)
// FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
vec![Item {
name: Some(name),
- attrs: Box::new(attrs.clean(cx)),
+ attrs: box attrs.clean(cx),
def_id: crate_def_id.into(),
visibility: krate.vis.clean(cx),
- kind: Box::new(ExternCrateItem { src: orig_name }),
+ kind: box ExternCrateItem { src: orig_name },
cfg: attrs.cfg(cx.sess()),
}]
}
def_id,
name,
kind,
- Box::new(ast_attrs.clean(cx)),
+ box ast_attrs.clean(cx),
cx,
ast_attrs.cfg(cx.sess()),
)
Item {
def_id: def_id.into(),
- kind: Box::new(kind),
+ kind: box kind,
name,
attrs,
visibility: cx.tcx.visibility(def_id).clean(cx),
let path = external_path(cx, did, false, vec![], empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
GenericBound::TraitBound(
- PolyTrait {
- trait_: ResolvedPath { path, did, is_generic: false },
- generic_params: Vec::new(),
- },
+ PolyTrait { trait_: ResolvedPath { path, did }, generic_params: Vec::new() },
hir::TraitBoundModifier::Maybe,
)
}
ResolvedPath {
path: Path,
did: DefId,
- /// `true` if is a `T::Name` path for associated types.
- is_generic: bool,
},
/// `dyn for<'a> Trait<'a> + Send + 'static`
DynTrait(Vec<PolyTrait>, Option<Lifetime>),
}
}
- crate fn is_generic(&self) -> bool {
- match *self {
- ResolvedPath { is_generic, .. } => is_generic,
+ /// Checks if this is a `T::Name` path for an associated type.
+ crate fn is_assoc_ty(&self) -> bool {
+ match self {
+ ResolvedPath { path, .. } => path.is_assoc_ty(),
_ => false,
}
}
String::from(if self.global { "::" } else { "" })
+ &self.segments.iter().map(|s| s.name.to_string()).collect::<Vec<_>>().join("::")
}
+
+ /// Checks if this is a `T::Name` path for an associated type.
+ crate fn is_assoc_ty(&self) -> bool {
+ match self.res {
+ Res::SelfTy(..) if self.segments.len() != 1 => true,
+ Res::Def(DefKind::TyParam, _) if self.segments.len() != 1 => true,
+ Res::Def(DefKind::AssocTy, _) => true,
+ _ => false,
+ }
+ }
}
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
crate fn strip_type(ty: Type) -> Type {
match ty {
- Type::ResolvedPath { path, did, is_generic } => {
- Type::ResolvedPath { path: strip_path(&path), did, is_generic }
- }
+ Type::ResolvedPath { path, did } => Type::ResolvedPath { path: strip_path(&path), did },
Type::DynTrait(mut bounds, lt) => {
let first = bounds.remove(0);
let stripped_trait = strip_type(first.trait_);
crate fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
debug!("resolve_type({:?})", path);
- let is_generic = match path.res {
- Res::PrimTy(p) => return Primitive(PrimitiveType::from(p)),
- Res::SelfTy(..) if path.segments.len() == 1 => {
- return Generic(kw::SelfUpper);
- }
- Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
- return Generic(path.segments[0].name);
+ match path.res {
+ Res::PrimTy(p) => Primitive(PrimitiveType::from(p)),
+ Res::SelfTy(..) if path.segments.len() == 1 => Generic(kw::SelfUpper),
+ Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name),
+ _ => {
+ let did = register_res(cx, path.res);
+ ResolvedPath { path, did }
}
- Res::SelfTy(..) | Res::Def(DefKind::TyParam | DefKind::AssocTy, _) => true,
- _ => false,
- };
- let did = register_res(cx, path.res);
- ResolvedPath { path, did, is_generic }
+ }
}
crate fn get_auto_trait_and_blanket_impls(
stderr: None,
lint_caps,
parse_sess_created: None,
- register_lints: Some(Box::new(crate::lint::register_lints)),
+ register_lints: Some(box crate::lint::register_lints),
override_queries: Some(|_sess, providers, _external_providers| {
// Most lints will require typechecking, so just don't run them.
providers.lint_mod = |_, _| {};
stderr: None,
lint_caps,
parse_sess_created: None,
- register_lints: Some(Box::new(crate::lint::register_lints)),
+ register_lints: Some(box crate::lint::register_lints),
override_queries: None,
make_codegen_backend: None,
registry: rustc_driver::diagnostics_registry(),
.supports_color();
let emitter =
- EmitterWriter::new(Box::new(io::sink()), None, false, false, false, None, false);
+ EmitterWriter::new(box io::sink(), None, false, false, false, None, false);
// FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
- let handler = Handler::with_emitter(false, None, Box::new(emitter));
+ let handler = Handler::with_emitter(false, None, box emitter);
let sess = ParseSess::with_span_handler(handler, sm);
let mut found_main = false;
no_run,
test_type: test::TestType::DocTest,
},
- testfn: test::DynTestFn(Box::new(move || {
+ testfn: test::DynTestFn(box move || {
let report_unused_externs = |uext| {
unused_externs.lock().unwrap().push(uext);
};
}
}
- panic::resume_unwind(Box::new(()));
+ panic::resume_unwind(box ());
}
- })),
+ }),
});
}
crate fn strip_item(mut item: Item) -> Item {
if !matches!(*item.kind, StrippedItem(..)) {
- item.kind = Box::new(StrippedItem(item.kind));
+ item.kind = box StrippedItem(item.kind);
}
item
}
/// don't override!
fn fold_item_recur(&mut self, mut item: Item) -> Item {
- item.kind = Box::new(match *item.kind {
- StrippedItem(box i) => StrippedItem(Box::new(self.fold_inner_recur(i))),
+ item.kind = box match *item.kind {
+ StrippedItem(box i) => StrippedItem(box self.fold_inner_recur(i)),
_ => self.fold_inner_recur(*item.kind),
- });
+ };
item
}
match *t {
clean::Generic(name) => write!(f, "{}", name),
- clean::ResolvedPath { did, ref path, is_generic } => {
+ clean::ResolvedPath { did, ref path } => {
// Paths like `T::Output` and `Self::Output` should be rendered with all segments.
- resolved_path(f, did, path, is_generic, use_absolute, cx)
+ resolved_path(f, did, path, path.is_assoc_ty(), use_absolute, cx)
}
clean::DynTrait(ref bounds, ref lt) => {
f.write_str("dyn ")?;
hir::Mutability::Mut => "mut",
hir::Mutability::Not => "const",
};
- match **t {
- clean::Generic(_) | clean::ResolvedPath { is_generic: true, .. } => {
- if f.alternate() {
- primitive_link(
- f,
- clean::PrimitiveType::RawPointer,
- &format!("*{} {:#}", m, t.print(cx)),
- cx,
- )
- } else {
- primitive_link(
- f,
- clean::PrimitiveType::RawPointer,
- &format!("*{} {}", m, t.print(cx)),
- cx,
- )
- }
- }
- _ => {
- primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m), cx)?;
- fmt::Display::fmt(&t.print(cx), f)
- }
+
+ if matches!(**t, clean::Generic(_)) || t.is_assoc_ty() {
+ let text = if f.alternate() {
+ format!("*{} {:#}", m, t.print(cx))
+ } else {
+ format!("*{} {}", m, t.print(cx))
+ };
+ primitive_link(f, clean::PrimitiveType::RawPointer, &text, cx)
+ } else {
+ primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m), cx)?;
+ fmt::Display::fmt(&t.print(cx), f)
}
}
clean::BorrowedRef { lifetime: ref l, mutability, type_: ref ty } => {
let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
for implementor in implementors {
match implementor.inner_impl().for_ {
- clean::ResolvedPath { ref path, did, is_generic: false, .. }
+ clean::ResolvedPath { ref path, did, .. }
| clean::BorrowedRef {
- type_: box clean::ResolvedPath { ref path, did, is_generic: false, .. },
- ..
- } => {
+ type_: box clean::ResolvedPath { ref path, did, .. }, ..
+ } if !path.is_assoc_ty() => {
let &mut (prev_did, ref mut has_duplicates) =
implementor_dups.entry(path.last()).or_insert((did, false));
if prev_did != did {
// If there's already another implementor that has the same abridged name, use the
// full path, for example in `std::iter::ExactSizeIterator`
let use_absolute = match implementor.inner_impl().for_ {
- clean::ResolvedPath { ref path, is_generic: false, .. }
- | clean::BorrowedRef {
- type_: box clean::ResolvedPath { ref path, is_generic: false, .. },
- ..
- } => implementor_dups[&path.last()].1,
+ clean::ResolvedPath { ref path, .. }
+ | clean::BorrowedRef { type_: box clean::ResolvedPath { ref path, .. }, .. }
+ if !path.is_assoc_ty() =>
+ {
+ implementor_dups[&path.last()].1
+ }
_ => false,
};
render_impl(
writeln!(
w,
"<div class=\"warning\"><p><strong>Note:</strong> Most layout information is \
- completely unstable and may be different between compiler versions and platforms. \
+ <strong>completely unstable</strong> and may even differ between compilations. \
The only exception is types with certain <code>repr(...)</code> attributes. \
Please see the Rust Reference’s \
<a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \
fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
use clean::Type::*;
match ty {
- ResolvedPath { path, did, is_generic: _ } => Type::ResolvedPath {
+ ResolvedPath { path, did } => Type::ResolvedPath {
name: path.whole_name(),
id: from_item_id(did.into()),
args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
+#![feature(box_syntax)]
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(test)]
impl<'a> From<ResolutionFailure<'a>> for ErrorKind<'a> {
fn from(err: ResolutionFailure<'a>) -> Self {
- ErrorKind::Resolve(Box::new(err))
+ ErrorKind::Resolve(box err)
}
}
let mut resolver = cx.resolver.borrow_mut();
let in_scope_traits = cx.module_trait_cache.entry(module).or_insert_with(|| {
resolver.access(|resolver| {
- let parent_scope = &ParentScope::module(resolver.get_module(module), resolver);
+ let parent_scope = &ParentScope::module(resolver.expect_module(module), resolver);
resolver
.traits_in_scope(None, parent_scope, SyntaxContext::root(), None)
.into_iter()
return None;
}
if let Some(did) = imp.for_.def_id() {
- if did.is_local() && !imp.for_.is_generic() && !self.retained.contains(&did.into())
+ if did.is_local() && !imp.for_.is_assoc_ty() && !self.retained.contains(&did.into())
{
debug!("ImplStripper: impl item for stripped type; removing");
return None;
-Subproject commit 86c7daa627aefda1371568b948eba21edf720747
+Subproject commit cba558df777a045b5657d56c29944e9e8fd3a776
[package]
name = "rustdoc-json-types"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[lib]
path = "lib.rs"
--- /dev/null
+// only-x86_64
+// assembly-output: emit-asm
+// compile-flags: --crate-type staticlib -Ctarget-feature=+sse4.2
+
+// CHECK-LABEL: banana
+// CHECK: crc32
+#[no_mangle]
+pub unsafe fn banana(v: u8) -> u32 {
+ use std::arch::x86_64::*;
+ let out = !0u32;
+ _mm_crc32_u8(out, v)
+}
//
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
// We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing
-// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/extern-drop-glue
+// incremental
+// compile-flags:-Zprint-mono-items=lazy
// compile-flags:-Zinline-in-all-cgus -Copt-level=0
#![allow(dead_code)]
//
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
-// compile-flags:-Zprint-mono-items=eager -Cincremental=tmp/partitioning-tests/extern-generic -Zshare-generics=y
+// incremental
+// compile-flags:-Zprint-mono-items=eager -Zshare-generics=y
#![allow(dead_code)]
#![crate_type="lib"]
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
-// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/incremental-merging
+// incremental
+// compile-flags:-Zprint-mono-items=lazy
// compile-flags:-Ccodegen-units=3
#![crate_type = "rlib"]
//
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
-// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/inlining-from-extern-crate
+// incremental
+// compile-flags:-Zprint-mono-items=lazy
// compile-flags:-Zinline-in-all-cgus
#![crate_type="lib"]
//
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
// We specify opt-level=0 because `drop_in_place` is `Internal` when optimizing
-// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-drop-glue
+// incremental
+// compile-flags:-Zprint-mono-items=lazy
// compile-flags:-Zinline-in-all-cgus -Copt-level=0
#![allow(dead_code)]
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
-// compile-flags:-Zprint-mono-items=eager -Cincremental=tmp/partitioning-tests/local-generic
+// incremental
+// compile-flags:-Zprint-mono-items=eager
#![allow(dead_code)]
#![crate_type="lib"]
//
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
-// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-inlining-but-not-all
+// incremental
+// compile-flags:-Zprint-mono-items=lazy
// compile-flags:-Zinline-in-all-cgus=no
#![allow(dead_code)]
//
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
-// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-inlining
+// incremental
+// compile-flags:-Zprint-mono-items=lazy
// compile-flags:-Zinline-in-all-cgus
#![allow(dead_code)]
//
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
-// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/local-transitive-inlining
+// incremental
+// compile-flags:-Zprint-mono-items=lazy
// compile-flags:-Zinline-in-all-cgus
#![allow(dead_code)]
// ignore-test
//
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
-// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/methods-are-with-self-type
+// incremental
+// compile-flags:-Zprint-mono-items=lazy
#![allow(dead_code)]
#![feature(start)]
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
-// compile-flags:-Zprint-mono-items=eager -Cincremental=tmp/partitioning-tests/regular-modules
+// incremental
+// compile-flags:-Zprint-mono-items=eager
#![allow(dead_code)]
#![crate_type="lib"]
// no-prefer-dynamic
// NOTE: We always compile this test with -Copt-level=0 because higher opt-levels
// prevent drop-glue from participating in share-generics.
-// compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Cincremental=tmp/partitioning-tests/shared-generics-exe -Copt-level=0
+// incremental
+// compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Copt-level=0
#![crate_type="rlib"]
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
-// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/statics
+// incremental
+// compile-flags:-Zprint-mono-items=lazy
#![crate_type="rlib"]
//
-// We specify -C incremental here because we want to test the partitioning for
+// We specify incremental here because we want to test the partitioning for
// incremental compilation
-// compile-flags:-Zprint-mono-items=lazy -Cincremental=tmp/partitioning-tests/vtable-through-const
+// incremental
+// compile-flags:-Zprint-mono-items=lazy
// compile-flags:-Zinline-in-all-cgus
// This test case makes sure, that references made through constants are
-// compile-flags: -Z panic-in-drop=abort -O
+// compile-flags: -Z panic-in-drop=abort -O -Z new-llvm-pass-manager=no
// Ensure that unwinding code paths are eliminated from the output after
// optimization.
+// This test uses -Z new-llvm-pass-manager=no, because the expected optimization does not happen
+// on targets using SEH exceptions (i.e. MSVC) anymore. The core issue is that Rust promises that
+// the drop_in_place() function can't unwind, but implements it in a way that *can*, because we
+// currently go out of our way to allow longjmps, which also use the unwinding mechanism on MSVC
+// targets. We should either forbid longjmps, or not assume nounwind, making this optimization
+// incompatible with the current behavior of running cleanuppads on longjmp unwinding.
+
+// CHECK-NOT: {{(call|invoke).*}}should_not_appear_in_output
+
#![crate_type = "lib"]
use std::any::Any;
use std::mem::forget;
}
}
-// CHECK-LABEL: normal_drop
-// CHECK-NOT: should_not_appear_in_output
#[no_mangle]
pub fn normal_drop(x: ExternDrop) {
let guard = AssertNeverDrop;
forget(guard);
}
-// CHECK-LABEL: indirect_drop
-// CHECK-NOT: should_not_appear_in_output
#[no_mangle]
pub fn indirect_drop(x: Box<dyn Any>) {
let guard = AssertNeverDrop;
--- /dev/null
+// only-x86_64
+// min-llvm-version: 14.0
+// compile-flags: -Copt-level=3
+
+#![crate_type = "lib"]
+
+#[cfg(target_arch = "x86_64")]
+#[target_feature(enable = "sse4.2")]
+#[no_mangle]
+pub unsafe fn crc32sse(v: u8) -> u32 {
+ use std::arch::x86_64::*;
+ let out = !0u32;
+ _mm_crc32_u8(out, v)
+}
+
+// CHECK: attributes #0 {{.*"target-features"="\+sse4.2,\+crc32"}}
// lldbr-check:(f64) *unique_val_interior_ref_2 = 26.5
#![allow(unused_variables)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let stack_val_interior_ref_2: &f64 = &stack_val.y;
let ref_to_unnamed: &SomeStruct = &SomeStruct { x: 11, y: 24.5 };
- let unique_val: Box<_> = box SomeStruct { x: 13, y: 26.5 };
+ let unique_val: Box<_> = Box::new(SomeStruct { x: 13, y: 26.5 });
let unique_val_ref: &SomeStruct = &*unique_val;
let unique_val_interior_ref_1: &isize = &unique_val.x;
let unique_val_interior_ref_2: &f64 = &unique_val.y;
#![allow(unused_variables)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let stack_val_ref: &(i16, f32) = &stack_val;
let ref_to_unnamed: &(i16, f32) = &(-15, -20f32);
- let unique_val: Box<(i16, f32)> = box (-17, -22f32);
+ let unique_val: Box<(i16, f32)> = Box::new((-17, -22f32));
let unique_val_ref: &(i16, f32) = &*unique_val;
zzz(); // #break
// lldbr-check:(f64) *f64_ref = 3.5
#![allow(unused_variables)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
fn main() {
- let bool_box: Box<bool> = box true;
+ let bool_box: Box<bool> = Box::new(true);
let bool_ref: &bool = &*bool_box;
- let int_box: Box<isize> = box -1;
+ let int_box: Box<isize> = Box::new(-1);
let int_ref: &isize = &*int_box;
- let char_box: Box<char> = box 'a';
+ let char_box: Box<char> = Box::new('a');
let char_ref: &char = &*char_box;
- let i8_box: Box<i8> = box 68;
+ let i8_box: Box<i8> = Box::new(68);
let i8_ref: &i8 = &*i8_box;
- let i16_box: Box<i16> = box -16;
+ let i16_box: Box<i16> = Box::new(-16);
let i16_ref: &i16 = &*i16_box;
- let i32_box: Box<i32> = box -32;
+ let i32_box: Box<i32> = Box::new(-32);
let i32_ref: &i32 = &*i32_box;
- let i64_box: Box<i64> = box -64;
+ let i64_box: Box<i64> = Box::new(-64);
let i64_ref: &i64 = &*i64_box;
- let uint_box: Box<usize> = box 1;
+ let uint_box: Box<usize> = Box::new(1);
let uint_ref: &usize = &*uint_box;
- let u8_box: Box<u8> = box 100;
+ let u8_box: Box<u8> = Box::new(100);
let u8_ref: &u8 = &*u8_box;
- let u16_box: Box<u16> = box 16;
+ let u16_box: Box<u16> = Box::new(16);
let u16_ref: &u16 = &*u16_box;
- let u32_box: Box<u32> = box 32;
+ let u32_box: Box<u32> = Box::new(32);
let u32_ref: &u32 = &*u32_box;
- let u64_box: Box<u64> = box 64;
+ let u64_box: Box<u64> = Box::new(64);
let u64_ref: &u64 = &*u64_box;
- let f32_box: Box<f32> = box 2.5;
+ let f32_box: Box<f32> = Box::new(2.5);
let f32_ref: &f32 = &*f32_box;
- let f64_box: Box<f64> = box 3.5;
+ let f64_box: Box<f64> = Box::new(3.5);
let f64_ref: &f64 = &*f64_box;
zzz(); // #break
// lldbr-check:((i32, f64)) *b = { 0 = 2 1 = 3.5 }
#![allow(unused_variables)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
fn main() {
- let a = box 1;
- let b = box (2, 3.5f64);
+ let a = Box::new(1);
+ let b = Box::new((2, 3.5f64));
zzz(); // #break
}
// lldbr-check:(boxed_struct::StructWithDestructor) *boxed_with_dtor = { x = 77 y = 777 z = 7777 w = 77777 }
#![allow(unused_variables)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
fn main() {
- let boxed_with_padding: Box<_> = box StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 };
-
- let boxed_with_dtor: Box<_> = box StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 };
+ let boxed_with_padding: Box<_> = Box::new(StructWithSomePadding {
+ x: 99,
+ y: 999,
+ z: 9999,
+ w: 99999,
+ });
+
+ let boxed_with_dtor: Box<_> = Box::new(StructWithDestructor {
+ x: 77,
+ y: 777,
+ z: 7777,
+ w: 77777,
+ });
zzz(); // #break
}
// lldbr-check:(i32) *y = 110
// lldb-command:continue
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
#![allow(unused_variables)]
#![feature(box_patterns)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
managed_box(&(34, 35));
borrowed_pointer(&(36, 37));
contained_borrowed_pointer((&38, 39));
- unique_pointer(box (40, 41, 42));
+ unique_pointer(Box::new((40, 41, 42)));
ref_binding((43, 44, 45));
ref_binding_in_tuple((46, (47, 48)));
ref_binding_in_struct(Struct { a: 49, b: 50 });
#![allow(unused_variables)]
#![feature(box_patterns)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
y: -300001.5,
z: true
},
- box 854237.5);
+ Box::new(854237.5));
for &(v1,
&Struct { x: x1, y: ref y1, z: z1 },
#![allow(unused_variables)]
#![feature(box_patterns)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let (&cc, _) = (&38, 39);
// unique pointer
- let box dd = box (40, 41, 42);
+ let box dd = Box::new((40, 41, 42));
// ref binding
let ref ee = (43, 44, 45);
// lldbr-check:(f32) arg2 = -10.5
// lldb-command:continue
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let _ = stack.self_by_ref(-1, 2_u16);
let _ = stack.self_by_val(-3, -4_i16);
- let owned: Box<_> = box Struct { x: 1234.5f64 };
+ let owned: Box<_> = Box::new(Struct { x: 1234.5f64 });
let _ = owned.self_by_ref(-5, -6_i32);
let _ = owned.self_by_val(-7, -8_i64);
let _ = owned.self_owned(-9, -10.5_f32);
// lldb-check:[...]$14 = -10
// lldb-command:continue
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
- let owned: Box<_> = box Enum::Variant1{ x: 1799, y: 1799 };
+ let owned: Box<_> = Box::new(Enum::Variant1{ x: 1799, y: 1799 });
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
// lldbr-check:(isize) arg2 = -10
// lldb-command:continue
-
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
- let owned: Box<_> = box Struct { x: 1234.5f64 };
+ let owned: Box<_> = Box::new(Struct { x: 1234.5f64 });
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
// lldbr-check:(isize) arg2 = -10
// lldb-command:continue
-
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
- let owned: Box<_> = box Struct { x: 200 };
+ let owned: Box<_> = Box::new(Struct { x: 200 });
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
// lldbr-check:(isize) arg2 = -10
// lldb-command:continue
-
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
- let owned: Box<_> = box Struct { x: 200 };
+ let owned: Box<_> = Box::new(Struct { x: 200 });
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
// lldbr-check:(isize) arg2 = -10
// lldb-command:continue
-
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
- let owned: Box<_> = box TupleStruct(200, -200.5);
+ let owned: Box<_> = Box::new(TupleStruct(200, -200.5));
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
--- /dev/null
+// only-cdb
+// compile-flags: -g
+
+// cdb-command: g
+
+// cdb-command: dx r1
+// cdb-check:r1 : (0xa..0xc) [Type: core::ops::range::Range<u32>]
+// cdb-command: dx r2
+// cdb-check:r2 : (0x14..0x1e) [Type: core::ops::range::Range<u64>]
+
+// cdb-command: g
+
+// cdb-command: dx r1
+// cdb-check:r1 : (0x9..0x64) [Type: core::ops::range::Range<u32>]
+// cdb-command: dx r2
+// cdb-check:r2 : (0xc..0x5a) [Type: core::ops::range::Range<u64>]
+
+// cdb-command: g
+
+// cdb-command: dx o1
+// cdb-check:o1 : Some [Type: enum$<core::option::Option<u32> >]
+// cdb-check: [variant] : Some
+// cdb-check: [+0x004] __0 : 0x4d2 [Type: [...]]
+// cdb-command: dx o2
+// cdb-check:o2 : Some [Type: enum$<core::option::Option<u64> >]
+// cdb-check: [variant] : Some
+// cdb-check: [+0x008] __0 : 0x162e [Type: unsigned __int64]
+
+// cdb-command: g
+
+// cdb-command: dx t1
+// cdb-check:t1 : (0xa, 0x14) [Type: tuple$<u32,u32>]
+// cdb-check: [0] : 0xa [Type: unsigned int]
+// cdb-check: [1] : 0x14 [Type: unsigned int]
+// cdb-command: dx t2
+// cdb-check:t2 : (0x1e, 0x28) [Type: tuple$<u64,u64>]
+// cdb-check: [0] : 0x1e [Type: unsigned __int64]
+// cdb-check: [1] : 0x28 [Type: unsigned __int64]
+
+// cdb-command: g
+
+// cdb-command: dx s
+// cdb-check:s : "this is a static str" [Type: str]
+// cdb-check: [len] : 0x14 [Type: unsigned [...]]
+// cdb-check: [chars]
+
+// cdb-command: g
+
+// cdb-command: dx s
+// cdb-check:s : { len=0x5 } [Type: slice$<u8>]
+// cdb-check: [len] : 0x5 [Type: unsigned [...]]
+// cdb-check: [0] : 0x1 [Type: unsigned char]
+// cdb-check: [1] : 0x2 [Type: unsigned char]
+// cdb-check: [2] : 0x3 [Type: unsigned char]
+// cdb-check: [3] : 0x4 [Type: unsigned char]
+// cdb-check: [4] : 0x5 [Type: unsigned char]
+
+use std::ops::Range;
+
+fn range(r1: Range<u32>, r2: Range<u64>) {
+ zzz(); // #break
+}
+
+fn range_mut(mut r1: Range<u32>, mut r2: Range<u64>) {
+ if r1.start == 9 {
+ r1.end = 100;
+ }
+
+ if r2.start == 12 {
+ r2.end = 90;
+ }
+
+ zzz(); // #break
+}
+
+fn option(o1: Option<u32>, o2: Option<u64>) {
+ zzz(); // #break
+}
+
+fn tuple(t1: (u32, u32), t2: (u64, u64)) {
+ zzz(); // #break
+}
+
+fn str(s: &str) {
+ zzz(); // #break
+}
+
+fn slice(s: &[u8]) {
+ zzz(); // #break
+}
+
+fn zzz() { }
+
+fn main() {
+ range(10..12, 20..30);
+ range_mut(9..20, 12..80);
+ option(Some(1234), Some(5678));
+ tuple((10, 20), (30, 40));
+ str("this is a static str");
+ slice(&[1, 2, 3, 4, 5]);
+}
// cdb-only
// min-cdb-version: 10.0.21287.1005
// compile-flags:-g
-// FIXME: Failed on update to 10.0.22000.1
-// ignore-windows
// === CDB TESTS ==================================================================================
//
// cdb-check:m,d [Type: std::sync::mutex::Mutex<i32>]
// cdb-check: [...] inner [Type: std::sys_common::mutex::MovableMutex]
// cdb-check: [...] poison [Type: std::sync::poison::Flag]
-// cdb-check: [...] data [Type: core::cell::UnsafeCell<i32>]
+// cdb-check: [...] data : 0 [Type: core::cell::UnsafeCell<i32>]
//
// cdb-command:dx m.data,d
-// cdb-check:m.data,d [Type: core::cell::UnsafeCell<i32>]
-// cdb-check: [...] value : 0 [Type: int]
+// cdb-check:m.data,d : 0 [Type: core::cell::UnsafeCell<i32>]
+// cdb-check: [<Raw View>] [Type: core::cell::UnsafeCell<i32>]
//
// cdb-command:dx lock,d
-// cdb-check:lock,d : Ok [Type: enum$<core::result::Result<std::sync::mutex::MutexGuard<i32>, enum$<std::sync::poison::TryLockError<std::sync::mutex::MutexGuard<i32> >, 0, 1, Poisoned> > >]
-// cdb-check: [...] variant$ : Ok (0) [Type: core::result::Result]
+// cdb-check:lock,d : Ok [Type: enum$<core::result::Result<std::sync::mutex::MutexGuard<i32>,enum$<std::sync::poison::TryLockError<std::sync::mutex::MutexGuard<i32> >, 0, 1, Poisoned> > >]
+// cdb-check: [variant] : Ok
// cdb-check: [...] __0 [Type: std::sync::mutex::MutexGuard<i32>]
use std::sync::Mutex;
// gdb-command:print long_cycle4.value
// gdb-check:$18 = 29.5
-// gdbr-command:print long_cycle_w_anonymous_types.value
+// gdbr-command:print long_cycle_w_anon_types.value
// gdb-check:$19 = 30
-// gdbr-command:print long_cycle_w_anonymous_types.next.val.value
+// gdbr-command:print long_cycle_w_anon_types.next.val.value
// gdb-check:$20 = 31
// gdb-command:continue
#![allow(unused_variables)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
use self::Opt::{Empty, Val};
+use std::boxed::Box as B;
enum Opt<T> {
Empty,
fn main() {
let stack_unique: UniqueNode<u16> = UniqueNode {
next: Val {
- val: box UniqueNode {
+ val: Box::new(UniqueNode {
next: Empty,
value: 1,
- }
+ })
},
value: 0,
};
- let unique_unique: Box<UniqueNode<u32>> = box UniqueNode {
+ let unique_unique: Box<UniqueNode<u32>> = Box::new(UniqueNode {
next: Val {
- val: box UniqueNode {
+ val: Box::new(UniqueNode {
next: Empty,
value: 3,
- }
+ })
},
value: 2,
- };
+ });
let vec_unique: [UniqueNode<f32>; 1] = [UniqueNode {
next: Val {
- val: box UniqueNode {
+ val: Box::new(UniqueNode {
next: Empty,
value: 7.5,
- }
+ })
},
value: 6.5,
}];
let borrowed_unique: &UniqueNode<f64> = &UniqueNode {
next: Val {
- val: box UniqueNode {
+ val: Box::new(UniqueNode {
next: Empty,
value: 9.5,
- }
+ })
},
value: 8.5,
};
// LONG CYCLE
let long_cycle1: LongCycle1<u16> = LongCycle1 {
- next: box LongCycle2 {
- next: box LongCycle3 {
- next: box LongCycle4 {
+ next: Box::new(LongCycle2 {
+ next: Box::new(LongCycle3 {
+ next: Box::new(LongCycle4 {
next: None,
value: 23,
- },
+ }),
value: 22,
- },
+ }),
value: 21
- },
+ }),
value: 20
};
let long_cycle2: LongCycle2<u32> = LongCycle2 {
- next: box LongCycle3 {
- next: box LongCycle4 {
+ next: Box::new(LongCycle3 {
+ next: Box::new(LongCycle4 {
next: None,
value: 26,
- },
+ }),
value: 25,
- },
+ }),
value: 24
};
let long_cycle3: LongCycle3<u64> = LongCycle3 {
- next: box LongCycle4 {
+ next: Box::new(LongCycle4 {
next: None,
value: 28,
- },
+ }),
value: 27,
};
// It's important that LongCycleWithAnonymousTypes is encountered only at the end of the
// `box` chain.
- let long_cycle_w_anonymous_types = box box box box box LongCycleWithAnonymousTypes {
+ let long_cycle_w_anon_types = B::new(B::new(B::new(B::new(B::new(LongCycleWithAnonymousTypes {
next: Val {
- val: box box box box box LongCycleWithAnonymousTypes {
+ val: Box::new(Box::new(Box::new(Box::new(Box::new(LongCycleWithAnonymousTypes {
next: Empty,
value: 31,
- }
+ })))))
},
value: 30
- };
+ })))));
zzz(); // #break
}
// lldbr-check:(isize) arg2 = -10
// lldb-command:continue
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let _ = stack.self_by_ref(-1, -2);
let _ = stack.self_by_val(-3, -4);
- let owned: Box<_> = box Struct { x: 200 };
+ let owned: Box<_> = Box::new(Struct { x: 200 });
let _ = owned.self_by_ref(-5, -6);
let _ = owned.self_by_val(-7, -8);
let _ = owned.self_owned(-9, -10);
// lldbr-check:(f32) arg2 = -10.5
// lldb-command:continue
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let _ = stack.self_by_ref(-1, 2_u16);
let _ = stack.self_by_val(-3, -4_i16);
- let owned: Box<_> = box Struct { x: 879 };
+ let owned: Box<_> = Box::new(Struct { x: 879 });
let _ = owned.self_by_ref(-5, -6_i32);
let _ = owned.self_by_val(-7, -8_i64);
let _ = owned.self_owned(-9, -10.5_f32);
// lldb-command:run
#![allow(unused_variables)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
fn main() {
let stack_struct = Struct { a:0, b: 1.0 };
let reference: &Trait = &stack_struct as &Trait;
- let unique: Box<Trait> = box Struct { a:2, b: 3.0 } as Box<Trait>;
+ let unique: Box<Trait> = Box::new(Struct { a:2, b: 3.0 }) as Box<Trait>;
}
// cdb-check:struct ForeignType2 * foreign2 = [...]
// cdb-check:struct ForeignType1 * foreign1 = [...]
-#![feature(box_syntax)]
#![allow(unused_variables)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
let tuple2 = ((Struct1, mod1::mod2::Struct3), mod1::Variant1, 'x');
// Box
- let box1 = (box 1f32, 0i32);
- let box2 = (box mod1::mod2::Variant2(1f32), 0i32);
+ let box1 = (Box::new(1f32), 0i32);
+ let box2 = (Box::new(mod1::mod2::Variant2(1f32)), 0i32);
// References
let ref1 = (&Struct1, 0i32);
let slice2 = &*vec2;
// Trait Objects
- let box_trait = (box 0_isize) as Box<dyn Trait1>;
+ let box_trait = Box::new(0_isize) as Box<dyn Trait1>;
let ref_trait = &0_isize as &dyn Trait1;
let mut mut_int1 = 0_isize;
let mut_ref_trait = (&mut mut_int1) as &mut dyn Trait1;
- let no_principal_trait = (box 0_isize) as Box<(dyn Send + Sync)>;
+ let no_principal_trait = Box::new(0_isize) as Box<(dyn Send + Sync)>;
let has_associated_type_trait = &0_isize as &(dyn Trait3<u32, AssocType = isize> + Send);
- let generic_box_trait = (box 0_isize) as Box<dyn Trait2<i32, mod1::Struct2>>;
+ let generic_box_trait = Box::new(0_isize) as Box<dyn Trait2<i32, mod1::Struct2>>;
let generic_ref_trait = (&0_isize) as &dyn Trait2<Struct1, Struct1>;
let mut generic_mut_ref_trait_impl = 0_isize;
// lldbr-check:(unique_enum::Univariant) *univariant = { TheOnlyCase = { = 123234 } }
#![allow(unused_variables)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
// 0b01111100011111000111110001111100 = 2088533116
// 0b0111110001111100 = 31868
// 0b01111100 = 124
- let the_a: Box<_> = box ABC::TheA { x: 0, y: 8970181431921507452 };
+ let the_a: Box<_> = Box::new(ABC::TheA { x: 0, y: 8970181431921507452 });
// 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
// 0b00010001000100010001000100010001 = 286331153
// 0b0001000100010001 = 4369
// 0b00010001 = 17
- let the_b: Box<_> = box ABC::TheB (0, 286331153, 286331153);
+ let the_b: Box<_> = Box::new(ABC::TheB (0, 286331153, 286331153));
- let univariant: Box<_> = box Univariant::TheOnlyCase(123234);
+ let univariant: Box<_> = Box::new(Univariant::TheOnlyCase(123234));
zzz(); // #break
}
// cdb-check:closure_local : 8 [Type: [...]]
#![allow(unused_variables)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
};
let struct_ref = &a_struct;
- let owned: Box<_> = box 6;
+ let owned: Box<_> = Box::new(6);
let mut closure = || {
let closure_local = 8;
// lldbr-check:(isize) *owned = 5
#![allow(unused_variables)]
-#![feature(box_syntax)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
c: 4
};
- let owned: Box<_> = box 5;
+ let owned: Box<_> = Box::new(5);
let closure = move || {
zzz(); // #break
// cdb-command: dx owned
// cdb-check:owned : 0x[...] : 6 [Type: [...] *]
-#![feature(box_syntax)]
#![allow(unused_variables)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]
};
let struct_ref = &a_struct;
- let owned: Box<_> = box 6;
+ let owned: Box<_> = Box::new(6);
{
let mut first_closure = || {
// Make function public --------------------------------------------------------
#[cfg(any(cfail1,cfail4))]
extern "C" {
- fn make_function_public(c: i32);
+ fn make_function_public(c: i32);
}
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg = "cfail2", except = "hir_owner")]
+#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
-#[rustc_clean(cfg = "cfail5", except = "hir_owner")]
+#[rustc_clean(cfg = "cfail5")]
#[rustc_clean(cfg = "cfail6")]
extern "C" {
pub fn make_function_public(c: i32);
// Change Method Privacy -------------------------------------------------------
#[cfg(any(cfail1,cfail4))]
impl Foo {
+ //------------------------------------------------------------------------------
+ //--------------------------
+ //------------------------------------------------------------------------------
+ //--------------------------
pub fn method_privacy() { }
}
#[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner")]
+#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
-#[rustc_clean(cfg="cfail5", except="hir_owner")]
+#[rustc_clean(cfg="cfail5")]
#[rustc_clean(cfg="cfail6")]
impl Foo {
#[rustc_clean(cfg="cfail2", except="associated_item,hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail3")]
- #[rustc_clean(cfg="cfail5", except="associated_item,hir_owner,hir_owner_nodes,optimized_mir")]
+ #[rustc_clean(cfg="cfail5", except="associated_item,hir_owner,hir_owner_nodes")]
#[rustc_clean(cfg="cfail6")]
- fn method_privacy() { }
+ fn method_privacy() { }
}
// Change Method Selfness -----------------------------------------------------------
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/box_expr.rs:6:11: 6:11
let _1: std::boxed::Box<S>; // in scope 0 at $DIR/box_expr.rs:7:9: 7:10
- let mut _2: std::boxed::Box<S>; // in scope 0 at $DIR/box_expr.rs:7:13: 7:25
- let _3: (); // in scope 0 at $DIR/box_expr.rs:8:5: 8:12
- let mut _4: std::boxed::Box<S>; // in scope 0 at $DIR/box_expr.rs:8:10: 8:11
+ let mut _2: usize; // in scope 0 at $DIR/box_expr.rs:7:13: 7:25
+ let mut _3: usize; // in scope 0 at $DIR/box_expr.rs:7:13: 7:25
+ let mut _4: *mut u8; // in scope 0 at $DIR/box_expr.rs:7:13: 7:25
+ let mut _5: std::boxed::Box<S>; // in scope 0 at $DIR/box_expr.rs:7:13: 7:25
+ let _6: (); // in scope 0 at $DIR/box_expr.rs:8:5: 8:12
+ let mut _7: std::boxed::Box<S>; // in scope 0 at $DIR/box_expr.rs:8:10: 8:11
scope 1 {
debug x => _1; // in scope 1 at $DIR/box_expr.rs:7:9: 7:10
}
+ scope 2 {
+ }
bb0: {
StorageLive(_1); // scope 0 at $DIR/box_expr.rs:7:9: 7:10
- StorageLive(_2); // scope 0 at $DIR/box_expr.rs:7:13: 7:25
- _2 = Box(S); // scope 0 at $DIR/box_expr.rs:7:13: 7:25
- (*_2) = S::new() -> [return: bb1, unwind: bb7]; // scope 0 at $DIR/box_expr.rs:7:17: 7:25
+ _2 = SizeOf(S); // scope 2 at $DIR/box_expr.rs:7:13: 7:25
+ _3 = AlignOf(S); // scope 2 at $DIR/box_expr.rs:7:13: 7:25
+ _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/box_expr.rs:7:13: 7:25
// mir::Constant
- // + span: $DIR/box_expr.rs:7:17: 7:23
- // + literal: Const { ty: fn() -> S {S::new}, val: Value(Scalar(<ZST>)) }
+ // + span: $DIR/box_expr.rs:7:13: 7:25
+ // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
}
bb1: {
- _1 = move _2; // scope 0 at $DIR/box_expr.rs:7:13: 7:25
- drop(_2) -> bb2; // scope 0 at $DIR/box_expr.rs:7:24: 7:25
+ StorageLive(_5); // scope 0 at $DIR/box_expr.rs:7:13: 7:25
+ _5 = ShallowInitBox(move _4, S); // scope 0 at $DIR/box_expr.rs:7:13: 7:25
+ (*_5) = S::new() -> [return: bb2, unwind: bb8]; // scope 0 at $DIR/box_expr.rs:7:17: 7:25
+ // mir::Constant
+ // + span: $DIR/box_expr.rs:7:17: 7:23
+ // + literal: Const { ty: fn() -> S {S::new}, val: Value(Scalar(<ZST>)) }
}
bb2: {
- StorageDead(_2); // scope 0 at $DIR/box_expr.rs:7:24: 7:25
- StorageLive(_3); // scope 1 at $DIR/box_expr.rs:8:5: 8:12
- StorageLive(_4); // scope 1 at $DIR/box_expr.rs:8:10: 8:11
- _4 = move _1; // scope 1 at $DIR/box_expr.rs:8:10: 8:11
- _3 = std::mem::drop::<Box<S>>(move _4) -> [return: bb3, unwind: bb5]; // scope 1 at $DIR/box_expr.rs:8:5: 8:12
+ _1 = move _5; // scope 0 at $DIR/box_expr.rs:7:13: 7:25
+ drop(_5) -> bb3; // scope 0 at $DIR/box_expr.rs:7:24: 7:25
+ }
+
+ bb3: {
+ StorageDead(_5); // scope 0 at $DIR/box_expr.rs:7:24: 7:25
+ StorageLive(_6); // scope 1 at $DIR/box_expr.rs:8:5: 8:12
+ StorageLive(_7); // scope 1 at $DIR/box_expr.rs:8:10: 8:11
+ _7 = move _1; // scope 1 at $DIR/box_expr.rs:8:10: 8:11
+ _6 = std::mem::drop::<Box<S>>(move _7) -> [return: bb4, unwind: bb6]; // scope 1 at $DIR/box_expr.rs:8:5: 8:12
// mir::Constant
// + span: $DIR/box_expr.rs:8:5: 8:9
// + literal: Const { ty: fn(std::boxed::Box<S>) {std::mem::drop::<std::boxed::Box<S>>}, val: Value(Scalar(<ZST>)) }
}
- bb3: {
- StorageDead(_4); // scope 1 at $DIR/box_expr.rs:8:11: 8:12
- StorageDead(_3); // scope 1 at $DIR/box_expr.rs:8:12: 8:13
+ bb4: {
+ StorageDead(_7); // scope 1 at $DIR/box_expr.rs:8:11: 8:12
+ StorageDead(_6); // scope 1 at $DIR/box_expr.rs:8:12: 8:13
_0 = const (); // scope 0 at $DIR/box_expr.rs:6:11: 9:2
- drop(_1) -> bb4; // scope 0 at $DIR/box_expr.rs:9:1: 9:2
+ drop(_1) -> bb5; // scope 0 at $DIR/box_expr.rs:9:1: 9:2
}
- bb4: {
+ bb5: {
StorageDead(_1); // scope 0 at $DIR/box_expr.rs:9:1: 9:2
return; // scope 0 at $DIR/box_expr.rs:9:2: 9:2
}
- bb5 (cleanup): {
- drop(_4) -> bb6; // scope 1 at $DIR/box_expr.rs:8:11: 8:12
- }
-
bb6 (cleanup): {
- drop(_1) -> bb8; // scope 0 at $DIR/box_expr.rs:9:1: 9:2
+ drop(_7) -> bb7; // scope 1 at $DIR/box_expr.rs:8:11: 8:12
}
bb7 (cleanup): {
- drop(_2) -> bb8; // scope 0 at $DIR/box_expr.rs:7:24: 7:25
+ drop(_1) -> bb9; // scope 0 at $DIR/box_expr.rs:9:1: 9:2
}
bb8 (cleanup): {
+ drop(_5) -> bb9; // scope 0 at $DIR/box_expr.rs:7:24: 7:25
+ }
+
+ bb9 (cleanup): {
resume; // scope 0 at $DIR/box_expr.rs:6:1: 9:2
}
}
let _1: i32; // in scope 0 at $DIR/boxes.rs:12:9: 12:10
let mut _2: i32; // in scope 0 at $DIR/boxes.rs:12:13: 12:22
let mut _3: std::boxed::Box<i32>; // in scope 0 at $DIR/boxes.rs:12:14: 12:22
- let mut _4: std::boxed::Box<i32>; // in scope 0 at $DIR/boxes.rs:12:14: 12:22
+ let mut _4: usize; // in scope 0 at $DIR/boxes.rs:12:14: 12:22
+ let mut _5: usize; // in scope 0 at $DIR/boxes.rs:12:14: 12:22
+ let mut _6: *mut u8; // in scope 0 at $DIR/boxes.rs:12:14: 12:22
+ let mut _7: std::boxed::Box<i32>; // in scope 0 at $DIR/boxes.rs:12:14: 12:22
scope 1 {
debug x => _1; // in scope 1 at $DIR/boxes.rs:12:9: 12:10
}
+ scope 2 {
+ }
bb0: {
StorageLive(_1); // scope 0 at $DIR/boxes.rs:12:9: 12:10
StorageLive(_2); // scope 0 at $DIR/boxes.rs:12:13: 12:22
StorageLive(_3); // scope 0 at $DIR/boxes.rs:12:14: 12:22
- StorageLive(_4); // scope 0 at $DIR/boxes.rs:12:14: 12:22
- _4 = Box(i32); // scope 0 at $DIR/boxes.rs:12:14: 12:22
- (*_4) = const 42_i32; // scope 0 at $DIR/boxes.rs:12:19: 12:21
- _3 = move _4; // scope 0 at $DIR/boxes.rs:12:14: 12:22
- StorageDead(_4); // scope 0 at $DIR/boxes.rs:12:21: 12:22
+- _4 = SizeOf(i32); // scope 2 at $DIR/boxes.rs:12:14: 12:22
+- _5 = AlignOf(i32); // scope 2 at $DIR/boxes.rs:12:14: 12:22
+- _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:12:14: 12:22
++ _4 = const 4_usize; // scope 2 at $DIR/boxes.rs:12:14: 12:22
++ _5 = const 4_usize; // scope 2 at $DIR/boxes.rs:12:14: 12:22
++ _6 = alloc::alloc::exchange_malloc(const 4_usize, const 4_usize) -> bb1; // scope 2 at $DIR/boxes.rs:12:14: 12:22
+ // mir::Constant
+ // + span: $DIR/boxes.rs:12:14: 12:22
+ // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
+ }
+
+ bb1: {
+ StorageLive(_7); // scope 0 at $DIR/boxes.rs:12:14: 12:22
+ _7 = ShallowInitBox(move _6, i32); // scope 0 at $DIR/boxes.rs:12:14: 12:22
+ (*_7) = const 42_i32; // scope 0 at $DIR/boxes.rs:12:19: 12:21
+ _3 = move _7; // scope 0 at $DIR/boxes.rs:12:14: 12:22
+ StorageDead(_7); // scope 0 at $DIR/boxes.rs:12:21: 12:22
_2 = (*_3); // scope 0 at $DIR/boxes.rs:12:13: 12:22
_1 = Add(move _2, const 0_i32); // scope 0 at $DIR/boxes.rs:12:13: 12:26
StorageDead(_2); // scope 0 at $DIR/boxes.rs:12:25: 12:26
- drop(_3) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/boxes.rs:12:26: 12:27
+ drop(_3) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/boxes.rs:12:26: 12:27
}
- bb1: {
+ bb2: {
StorageDead(_3); // scope 0 at $DIR/boxes.rs:12:26: 12:27
nop; // scope 0 at $DIR/boxes.rs:11:11: 13:2
StorageDead(_1); // scope 0 at $DIR/boxes.rs:13:1: 13:2
return; // scope 0 at $DIR/boxes.rs:13:2: 13:2
}
- bb2 (cleanup): {
+ bb3 (cleanup): {
resume; // scope 0 at $DIR/boxes.rs:11:1: 13:2
}
}
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/inline-into-box-place.rs:7:11: 7:11
let _1: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11
- let mut _2: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
- let mut _3: (); // in scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
-+ let mut _4: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
+ let mut _2: usize; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ let mut _3: usize; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ let mut _4: *mut u8; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ let mut _5: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ let mut _6: (); // in scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
++ let mut _7: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
scope 1 {
debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:8:9: 8:11
}
-+ scope 2 (inlined Vec::<u32>::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43
+ scope 2 {
+ }
++ scope 3 (inlined Vec::<u32>::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43
+ }
bb0: {
StorageLive(_1); // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11
- StorageLive(_2); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
- _2 = Box(std::vec::Vec<u32>); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
-- (*_2) = Vec::<u32>::new() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
-+ StorageLive(_4); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
-+ _4 = &mut (*_2); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
-+ ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: {0x4 as *const u32}, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 2 at $DIR/inline-into-box-place.rs:8:33: 8:43
+ _2 = SizeOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ _3 = AlignOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ // mir::Constant
+ // + span: $DIR/inline-into-box-place.rs:8:29: 8:43
+ // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
+ }
+
+ bb1: {
+ StorageLive(_5); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ _5 = ShallowInitBox(move _4, std::vec::Vec<u32>); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+- (*_5) = Vec::<u32>::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
++ StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
++ _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
++ ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: {0x4 as *const u32}, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43
+ // ty::Const
+ // + ty: alloc::raw_vec::RawVec<u32>
+ // + val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } })
- // + literal: Const { ty: fn() -> std::vec::Vec<u32> {std::vec::Vec::<u32>::new}, val: Value(Scalar(<ZST>)) }
- }
-
-- bb1: {
+- bb2: {
+ // + span: $DIR/inline-into-box-place.rs:8:33: 8:43
+ // + user_ty: UserType(0)
+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
-+ ((*_4).1: usize) = const 0_usize; // scope 2 at $DIR/inline-into-box-place.rs:8:33: 8:43
-+ StorageDead(_4); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
- _1 = move _2; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
- StorageDead(_2); // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
++ ((*_7).1: usize) = const 0_usize; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43
++ StorageDead(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
+ _1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ StorageDead(_5); // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
_0 = const (); // scope 0 at $DIR/inline-into-box-place.rs:7:11: 9:2
-- drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2
-+ drop(_1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2
+- drop(_1) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2
++ drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2
}
-- bb2: {
-+ bb1: {
+- bb3: {
++ bb2: {
StorageDead(_1); // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2
return; // scope 0 at $DIR/inline-into-box-place.rs:9:2: 9:2
}
-- bb3 (cleanup): {
-+ bb2 (cleanup): {
+- bb4 (cleanup): {
++ bb3 (cleanup): {
resume; // scope 0 at $DIR/inline-into-box-place.rs:7:1: 9:2
- }
-
-- bb4 (cleanup): {
-- _3 = alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_2.1: std::alloc::Global)) -> bb3; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
+- bb5 (cleanup): {
+- _6 = alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>(move (_5.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
- // mir::Constant
- // + span: $DIR/inline-into-box-place.rs:8:42: 8:43
- // + literal: Const { ty: unsafe fn(std::ptr::Unique<std::vec::Vec<u32>>, std::alloc::Global) {alloc::alloc::box_free::<std::vec::Vec<u32>, std::alloc::Global>}, val: Value(Scalar(<ZST>)) }
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/inline-into-box-place.rs:7:11: 7:11
let _1: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11
- let mut _2: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
- let mut _3: (); // in scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
-+ let mut _4: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
+ let mut _2: usize; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ let mut _3: usize; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ let mut _4: *mut u8; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ let mut _5: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ let mut _6: (); // in scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
++ let mut _7: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
scope 1 {
debug _x => _1; // in scope 1 at $DIR/inline-into-box-place.rs:8:9: 8:11
}
-+ scope 2 (inlined Vec::<u32>::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43
+ scope 2 {
+ }
++ scope 3 (inlined Vec::<u32>::new) { // at $DIR/inline-into-box-place.rs:8:33: 8:43
+ }
bb0: {
StorageLive(_1); // scope 0 at $DIR/inline-into-box-place.rs:8:9: 8:11
- StorageLive(_2); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
- _2 = Box(std::vec::Vec<u32>); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
-- (*_2) = Vec::<u32>::new() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
-+ StorageLive(_4); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
-+ _4 = &mut (*_2); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
-+ ((*_4).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: {0x4 as *const u32}, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 2 at $DIR/inline-into-box-place.rs:8:33: 8:43
+ _2 = SizeOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ _3 = AlignOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ // mir::Constant
+ // + span: $DIR/inline-into-box-place.rs:8:29: 8:43
+ // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
+ }
+
+ bb1: {
+ StorageLive(_5); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ _5 = ShallowInitBox(move _4, std::vec::Vec<u32>); // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+- (*_5) = Vec::<u32>::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
++ StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
++ _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
++ ((*_7).0: alloc::raw_vec::RawVec<u32>) = const alloc::raw_vec::RawVec::<u32> { ptr: Unique::<u32> { pointer: {0x4 as *const u32}, _marker: PhantomData::<u32> }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43
+ // ty::Const
+ // + ty: alloc::raw_vec::RawVec<u32>
+ // + val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [65535], len: Size { raw: 16 } }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } })
- // + literal: Const { ty: fn() -> std::vec::Vec<u32> {std::vec::Vec::<u32>::new}, val: Value(Scalar(<ZST>)) }
- }
-
-- bb1: {
+- bb2: {
+ // + span: $DIR/inline-into-box-place.rs:8:33: 8:43
+ // + user_ty: UserType(0)
+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [65535], len: Size { raw: 16 } }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) }
-+ ((*_4).1: usize) = const 0_usize; // scope 2 at $DIR/inline-into-box-place.rs:8:33: 8:43
-+ StorageDead(_4); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
- _1 = move _2; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
- StorageDead(_2); // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
++ ((*_7).1: usize) = const 0_usize; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43
++ StorageDead(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43
+ _1 = move _5; // scope 0 at $DIR/inline-into-box-place.rs:8:29: 8:43
+ StorageDead(_5); // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
_0 = const (); // scope 0 at $DIR/inline-into-box-place.rs:7:11: 9:2
-- drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2
-+ drop(_1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2
+- drop(_1) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2
++ drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2
}
-- bb2: {
-+ bb1: {
+- bb3: {
++ bb2: {
StorageDead(_1); // scope 0 at $DIR/inline-into-box-place.rs:9:1: 9:2
return; // scope 0 at $DIR/inline-into-box-place.rs:9:2: 9:2
}
-- bb3 (cleanup): {
-+ bb2 (cleanup): {
+- bb4 (cleanup): {
++ bb3 (cleanup): {
resume; // scope 0 at $DIR/inline-into-box-place.rs:7:1: 9:2
- }
-
-- bb4 (cleanup): {
-- _3 = alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>(move (_2.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_2.1: std::alloc::Global)) -> bb3; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
+- bb5 (cleanup): {
+- _6 = alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>(move (_5.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43
- // mir::Constant
- // + span: $DIR/inline-into-box-place.rs:8:42: 8:43
- // + literal: Const { ty: unsafe fn(std::ptr::Unique<std::vec::Vec<u32>>, std::alloc::Global) {alloc::alloc::box_free::<std::vec::Vec<u32>, std::alloc::Global>}, val: Value(Scalar(<ZST>)) }
fn test() -> Option<Box<u32>> {
let mut _0: std::option::Option<std::boxed::Box<u32>>; // return place in scope 0 at $DIR/issue-62289.rs:8:14: 8:30
let mut _1: std::boxed::Box<u32>; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21
- let mut _2: std::boxed::Box<u32>; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21
- let mut _3: std::ops::ControlFlow<std::option::Option<std::convert::Infallible>, u32>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20
- let mut _4: std::option::Option<u32>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:19
- let mut _5: isize; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
- let _6: std::option::Option<std::convert::Infallible>; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
- let mut _7: !; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
- let mut _8: std::option::Option<std::convert::Infallible>; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
- let _9: u32; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+ let mut _2: usize; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21
+ let mut _3: usize; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21
+ let mut _4: *mut u8; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21
+ let mut _5: std::boxed::Box<u32>; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21
+ let mut _6: std::ops::ControlFlow<std::option::Option<std::convert::Infallible>, u32>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+ let mut _7: std::option::Option<u32>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:19
+ let mut _8: isize; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+ let _9: std::option::Option<std::convert::Infallible>; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+ let mut _10: !; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+ let mut _11: std::option::Option<std::convert::Infallible>; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+ let _12: u32; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20
scope 1 {
- debug residual => _6; // in scope 1 at $DIR/issue-62289.rs:9:19: 9:20
- scope 2 {
+ }
+ scope 2 {
+ debug residual => _9; // in scope 2 at $DIR/issue-62289.rs:9:19: 9:20
+ scope 3 {
}
}
- scope 3 {
- debug val => _9; // in scope 3 at $DIR/issue-62289.rs:9:15: 9:20
- scope 4 {
+ scope 4 {
+ debug val => _12; // in scope 4 at $DIR/issue-62289.rs:9:15: 9:20
+ scope 5 {
}
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/issue-62289.rs:9:10: 9:21
- StorageLive(_2); // scope 0 at $DIR/issue-62289.rs:9:10: 9:21
- _2 = Box(u32); // scope 0 at $DIR/issue-62289.rs:9:10: 9:21
- StorageLive(_3); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
- StorageLive(_4); // scope 0 at $DIR/issue-62289.rs:9:15: 9:19
- _4 = Option::<u32>::None; // scope 0 at $DIR/issue-62289.rs:9:15: 9:19
- _3 = <Option<u32> as Try>::branch(move _4) -> [return: bb1, unwind: bb11]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+ _2 = SizeOf(u32); // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
+ _3 = AlignOf(u32); // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
+ _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 1 at $DIR/issue-62289.rs:9:10: 9:21
// mir::Constant
- // + span: $DIR/issue-62289.rs:9:15: 9:20
- // + literal: Const { ty: fn(std::option::Option<u32>) -> std::ops::ControlFlow<<std::option::Option<u32> as std::ops::Try>::Residual, <std::option::Option<u32> as std::ops::Try>::Output> {<std::option::Option<u32> as std::ops::Try>::branch}, val: Value(Scalar(<ZST>)) }
+ // + span: $DIR/issue-62289.rs:9:10: 9:21
+ // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
}
bb1: {
- StorageDead(_4); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
- _5 = discriminant(_3); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
- switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+ StorageLive(_5); // scope 0 at $DIR/issue-62289.rs:9:10: 9:21
+ _5 = ShallowInitBox(move _4, u32); // scope 0 at $DIR/issue-62289.rs:9:10: 9:21
+ StorageLive(_6); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+ StorageLive(_7); // scope 0 at $DIR/issue-62289.rs:9:15: 9:19
+ _7 = Option::<u32>::None; // scope 0 at $DIR/issue-62289.rs:9:15: 9:19
+ _6 = <Option<u32> as Try>::branch(move _7) -> [return: bb2, unwind: bb12]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+ // mir::Constant
+ // + span: $DIR/issue-62289.rs:9:15: 9:20
+ // + literal: Const { ty: fn(std::option::Option<u32>) -> std::ops::ControlFlow<<std::option::Option<u32> as std::ops::Try>::Residual, <std::option::Option<u32> as std::ops::Try>::Output> {<std::option::Option<u32> as std::ops::Try>::branch}, val: Value(Scalar(<ZST>)) }
}
bb2: {
- StorageLive(_9); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
- _9 = ((_3 as Continue).0: u32); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
- (*_2) = _9; // scope 4 at $DIR/issue-62289.rs:9:15: 9:20
- StorageDead(_9); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
- _1 = move _2; // scope 0 at $DIR/issue-62289.rs:9:10: 9:21
- drop(_2) -> [return: bb6, unwind: bb10]; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
+ StorageDead(_7); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+ _8 = discriminant(_6); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+ switchInt(move _8) -> [0_isize: bb3, 1_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
}
bb3: {
- unreachable; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+ StorageLive(_12); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+ _12 = ((_6 as Continue).0: u32); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+ (*_5) = _12; // scope 5 at $DIR/issue-62289.rs:9:15: 9:20
+ StorageDead(_12); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+ _1 = move _5; // scope 0 at $DIR/issue-62289.rs:9:10: 9:21
+ drop(_5) -> [return: bb7, unwind: bb11]; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
}
bb4: {
- StorageLive(_6); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
- _6 = ((_3 as Break).0: std::option::Option<std::convert::Infallible>); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
- StorageLive(_8); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
- _8 = _6; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
- _0 = <Option<Box<u32>> as FromResidual<Option<Infallible>>>::from_residual(move _8) -> [return: bb5, unwind: bb11]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20
- // mir::Constant
- // + span: $DIR/issue-62289.rs:9:19: 9:20
- // + literal: Const { ty: fn(std::option::Option<std::convert::Infallible>) -> std::option::Option<std::boxed::Box<u32>> {<std::option::Option<std::boxed::Box<u32>> as std::ops::FromResidual<std::option::Option<std::convert::Infallible>>>::from_residual}, val: Value(Scalar(<ZST>)) }
+ unreachable; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
}
bb5: {
- StorageDead(_8); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
- StorageDead(_6); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
- drop(_2) -> bb8; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
+ StorageLive(_9); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+ _9 = ((_6 as Break).0: std::option::Option<std::convert::Infallible>); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+ StorageLive(_11); // scope 3 at $DIR/issue-62289.rs:9:19: 9:20
+ _11 = _9; // scope 3 at $DIR/issue-62289.rs:9:19: 9:20
+ _0 = <Option<Box<u32>> as FromResidual<Option<Infallible>>>::from_residual(move _11) -> [return: bb6, unwind: bb12]; // scope 3 at $DIR/issue-62289.rs:9:15: 9:20
+ // mir::Constant
+ // + span: $DIR/issue-62289.rs:9:19: 9:20
+ // + literal: Const { ty: fn(std::option::Option<std::convert::Infallible>) -> std::option::Option<std::boxed::Box<u32>> {<std::option::Option<std::boxed::Box<u32>> as std::ops::FromResidual<std::option::Option<std::convert::Infallible>>>::from_residual}, val: Value(Scalar(<ZST>)) }
}
bb6: {
- StorageDead(_2); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
- _0 = Option::<Box<u32>>::Some(move _1); // scope 0 at $DIR/issue-62289.rs:9:5: 9:22
- drop(_1) -> bb7; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
+ StorageDead(_11); // scope 3 at $DIR/issue-62289.rs:9:19: 9:20
+ StorageDead(_9); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+ drop(_5) -> bb9; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
}
bb7: {
- StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
- StorageDead(_3); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2
- goto -> bb9; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2
+ StorageDead(_5); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
+ _0 = Option::<Box<u32>>::Some(move _1); // scope 0 at $DIR/issue-62289.rs:9:5: 9:22
+ drop(_1) -> bb8; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
}
bb8: {
- StorageDead(_2); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
- StorageDead(_3); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2
- goto -> bb9; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2
+ StorageDead(_6); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2
+ goto -> bb10; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2
}
bb9: {
- return; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2
+ StorageDead(_5); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
+ StorageDead(_1); // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
+ StorageDead(_6); // scope 0 at $DIR/issue-62289.rs:10:1: 10:2
+ goto -> bb10; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2
}
- bb10 (cleanup): {
- drop(_1) -> bb12; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
+ bb10: {
+ return; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2
}
bb11 (cleanup): {
- drop(_2) -> bb12; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
+ drop(_1) -> bb13; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
}
bb12 (cleanup): {
+ drop(_5) -> bb13; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
+ }
+
+ bb13 (cleanup): {
resume; // scope 0 at $DIR/issue-62289.rs:8:1: 10:2
}
}
let mut _0: (); // return place in scope 0 at $DIR/uniform_array_move_out.rs:10:27: 10:27
let _1: [std::boxed::Box<i32>; 2]; // in scope 0 at $DIR/uniform_array_move_out.rs:11:9: 11:10
let mut _2: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
- let mut _3: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
- let mut _4: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
- let mut _5: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+ let mut _3: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
+ let mut _4: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
+ let mut _5: *mut u8; // in scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
+ let mut _6: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
+ let mut _7: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+ let mut _8: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+ let mut _9: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+ let mut _10: *mut u8; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+ let mut _11: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
scope 1 {
debug a => _1; // in scope 1 at $DIR/uniform_array_move_out.rs:11:9: 11:10
- let _6: [std::boxed::Box<i32>; 2]; // in scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17
- scope 2 {
- debug _y => _6; // in scope 2 at $DIR/uniform_array_move_out.rs:12:10: 12:17
+ let _12: [std::boxed::Box<i32>; 2]; // in scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17
+ scope 4 {
+ debug _y => _12; // in scope 4 at $DIR/uniform_array_move_out.rs:12:10: 12:17
}
}
+ scope 2 {
+ }
+ scope 3 {
+ }
bb0: {
StorageLive(_1); // scope 0 at $DIR/uniform_array_move_out.rs:11:9: 11:10
StorageLive(_2); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
- StorageLive(_3); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
- _3 = Box(i32); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
- (*_3) = const 1_i32; // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19
- _2 = move _3; // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
- drop(_3) -> [return: bb1, unwind: bb9]; // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19
+ _3 = SizeOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
+ _4 = AlignOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
+ _5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb12]; // scope 2 at $DIR/uniform_array_move_out.rs:11:14: 11:19
+ // mir::Constant
+ // + span: $DIR/uniform_array_move_out.rs:11:14: 11:19
+ // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
}
bb1: {
- StorageDead(_3); // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19
- StorageLive(_4); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
- StorageLive(_5); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
- _5 = Box(i32); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
- (*_5) = const 2_i32; // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26
- _4 = move _5; // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
- drop(_5) -> [return: bb2, unwind: bb8]; // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26
+ StorageLive(_6); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
+ _6 = ShallowInitBox(move _5, i32); // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
+ (*_6) = const 1_i32; // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19
+ _2 = move _6; // scope 0 at $DIR/uniform_array_move_out.rs:11:14: 11:19
+ drop(_6) -> [return: bb2, unwind: bb11]; // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19
}
bb2: {
- StorageDead(_5); // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26
- _1 = [move _2, move _4]; // scope 0 at $DIR/uniform_array_move_out.rs:11:13: 11:27
- drop(_4) -> [return: bb3, unwind: bb9]; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27
+ StorageDead(_6); // scope 0 at $DIR/uniform_array_move_out.rs:11:18: 11:19
+ StorageLive(_7); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+ _8 = SizeOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+ _9 = AlignOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+ _10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb11]; // scope 3 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+ // mir::Constant
+ // + span: $DIR/uniform_array_move_out.rs:11:21: 11:26
+ // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
}
bb3: {
- StorageDead(_4); // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27
- drop(_2) -> [return: bb4, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27
+ StorageLive(_11); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+ _11 = ShallowInitBox(move _10, i32); // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+ (*_11) = const 2_i32; // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26
+ _7 = move _11; // scope 0 at $DIR/uniform_array_move_out.rs:11:21: 11:26
+ drop(_11) -> [return: bb4, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26
}
bb4: {
+ StorageDead(_11); // scope 0 at $DIR/uniform_array_move_out.rs:11:25: 11:26
+ _1 = [move _2, move _7]; // scope 0 at $DIR/uniform_array_move_out.rs:11:13: 11:27
+ drop(_7) -> [return: bb5, unwind: bb11]; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27
+ }
+
+ bb5: {
+ StorageDead(_7); // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27
+ drop(_2) -> [return: bb6, unwind: bb12]; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27
+ }
+
+ bb6: {
StorageDead(_2); // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27
FakeRead(ForLet(None), _1); // scope 0 at $DIR/uniform_array_move_out.rs:11:9: 11:10
- StorageLive(_6); // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17
- _6 = move _1[0..2]; // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17
+ StorageLive(_12); // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17
+ _12 = move _1[0..2]; // scope 1 at $DIR/uniform_array_move_out.rs:12:10: 12:17
_0 = const (); // scope 0 at $DIR/uniform_array_move_out.rs:10:27: 13:2
- drop(_6) -> [return: bb5, unwind: bb7]; // scope 1 at $DIR/uniform_array_move_out.rs:13:1: 13:2
+ drop(_12) -> [return: bb7, unwind: bb9]; // scope 1 at $DIR/uniform_array_move_out.rs:13:1: 13:2
}
- bb5: {
- StorageDead(_6); // scope 1 at $DIR/uniform_array_move_out.rs:13:1: 13:2
- drop(_1) -> [return: bb6, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2
+ bb7: {
+ StorageDead(_12); // scope 1 at $DIR/uniform_array_move_out.rs:13:1: 13:2
+ drop(_1) -> [return: bb8, unwind: bb12]; // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2
}
- bb6: {
+ bb8: {
StorageDead(_1); // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2
return; // scope 0 at $DIR/uniform_array_move_out.rs:13:2: 13:2
}
- bb7 (cleanup): {
- drop(_1) -> bb10; // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2
+ bb9 (cleanup): {
+ drop(_1) -> bb12; // scope 0 at $DIR/uniform_array_move_out.rs:13:1: 13:2
}
- bb8 (cleanup): {
- drop(_4) -> bb9; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27
+ bb10 (cleanup): {
+ drop(_7) -> bb11; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27
}
- bb9 (cleanup): {
- drop(_2) -> bb10; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27
+ bb11 (cleanup): {
+ drop(_2) -> bb12; // scope 0 at $DIR/uniform_array_move_out.rs:11:26: 11:27
}
- bb10 (cleanup): {
+ bb12 (cleanup): {
resume; // scope 0 at $DIR/uniform_array_move_out.rs:10:1: 13:2
}
}
let mut _0: (); // return place in scope 0 at $DIR/uniform_array_move_out.rs:4:24: 4:24
let _1: [std::boxed::Box<i32>; 2]; // in scope 0 at $DIR/uniform_array_move_out.rs:5:9: 5:10
let mut _2: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
- let mut _3: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
- let mut _4: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
- let mut _5: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+ let mut _3: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
+ let mut _4: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
+ let mut _5: *mut u8; // in scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
+ let mut _6: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
+ let mut _7: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+ let mut _8: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+ let mut _9: usize; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+ let mut _10: *mut u8; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+ let mut _11: std::boxed::Box<i32>; // in scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
scope 1 {
debug a => _1; // in scope 1 at $DIR/uniform_array_move_out.rs:5:9: 5:10
- let _6: std::boxed::Box<i32>; // in scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16
- scope 2 {
- debug _y => _6; // in scope 2 at $DIR/uniform_array_move_out.rs:6:14: 6:16
+ let _12: std::boxed::Box<i32>; // in scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16
+ scope 4 {
+ debug _y => _12; // in scope 4 at $DIR/uniform_array_move_out.rs:6:14: 6:16
}
}
+ scope 2 {
+ }
+ scope 3 {
+ }
bb0: {
StorageLive(_1); // scope 0 at $DIR/uniform_array_move_out.rs:5:9: 5:10
StorageLive(_2); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
- StorageLive(_3); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
- _3 = Box(i32); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
- (*_3) = const 1_i32; // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19
- _2 = move _3; // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
- drop(_3) -> [return: bb1, unwind: bb9]; // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19
+ _3 = SizeOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
+ _4 = AlignOf(i32); // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
+ _5 = alloc::alloc::exchange_malloc(move _3, move _4) -> [return: bb1, unwind: bb12]; // scope 2 at $DIR/uniform_array_move_out.rs:5:14: 5:19
+ // mir::Constant
+ // + span: $DIR/uniform_array_move_out.rs:5:14: 5:19
+ // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
}
bb1: {
- StorageDead(_3); // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19
- StorageLive(_4); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
- StorageLive(_5); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
- _5 = Box(i32); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
- (*_5) = const 2_i32; // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26
- _4 = move _5; // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
- drop(_5) -> [return: bb2, unwind: bb8]; // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26
+ StorageLive(_6); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
+ _6 = ShallowInitBox(move _5, i32); // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
+ (*_6) = const 1_i32; // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19
+ _2 = move _6; // scope 0 at $DIR/uniform_array_move_out.rs:5:14: 5:19
+ drop(_6) -> [return: bb2, unwind: bb11]; // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19
}
bb2: {
- StorageDead(_5); // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26
- _1 = [move _2, move _4]; // scope 0 at $DIR/uniform_array_move_out.rs:5:13: 5:27
- drop(_4) -> [return: bb3, unwind: bb9]; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27
+ StorageDead(_6); // scope 0 at $DIR/uniform_array_move_out.rs:5:18: 5:19
+ StorageLive(_7); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+ _8 = SizeOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+ _9 = AlignOf(i32); // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+ _10 = alloc::alloc::exchange_malloc(move _8, move _9) -> [return: bb3, unwind: bb11]; // scope 3 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+ // mir::Constant
+ // + span: $DIR/uniform_array_move_out.rs:5:21: 5:26
+ // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(Scalar(<ZST>)) }
}
bb3: {
- StorageDead(_4); // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27
- drop(_2) -> [return: bb4, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27
+ StorageLive(_11); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+ _11 = ShallowInitBox(move _10, i32); // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+ (*_11) = const 2_i32; // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26
+ _7 = move _11; // scope 0 at $DIR/uniform_array_move_out.rs:5:21: 5:26
+ drop(_11) -> [return: bb4, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26
}
bb4: {
+ StorageDead(_11); // scope 0 at $DIR/uniform_array_move_out.rs:5:25: 5:26
+ _1 = [move _2, move _7]; // scope 0 at $DIR/uniform_array_move_out.rs:5:13: 5:27
+ drop(_7) -> [return: bb5, unwind: bb11]; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27
+ }
+
+ bb5: {
+ StorageDead(_7); // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27
+ drop(_2) -> [return: bb6, unwind: bb12]; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27
+ }
+
+ bb6: {
StorageDead(_2); // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27
FakeRead(ForLet(None), _1); // scope 0 at $DIR/uniform_array_move_out.rs:5:9: 5:10
- StorageLive(_6); // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16
- _6 = move _1[1 of 2]; // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16
+ StorageLive(_12); // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16
+ _12 = move _1[1 of 2]; // scope 1 at $DIR/uniform_array_move_out.rs:6:14: 6:16
_0 = const (); // scope 0 at $DIR/uniform_array_move_out.rs:4:24: 7:2
- drop(_6) -> [return: bb5, unwind: bb7]; // scope 1 at $DIR/uniform_array_move_out.rs:7:1: 7:2
+ drop(_12) -> [return: bb7, unwind: bb9]; // scope 1 at $DIR/uniform_array_move_out.rs:7:1: 7:2
}
- bb5: {
- StorageDead(_6); // scope 1 at $DIR/uniform_array_move_out.rs:7:1: 7:2
- drop(_1) -> [return: bb6, unwind: bb10]; // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2
+ bb7: {
+ StorageDead(_12); // scope 1 at $DIR/uniform_array_move_out.rs:7:1: 7:2
+ drop(_1) -> [return: bb8, unwind: bb12]; // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2
}
- bb6: {
+ bb8: {
StorageDead(_1); // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2
return; // scope 0 at $DIR/uniform_array_move_out.rs:7:2: 7:2
}
- bb7 (cleanup): {
- drop(_1) -> bb10; // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2
+ bb9 (cleanup): {
+ drop(_1) -> bb12; // scope 0 at $DIR/uniform_array_move_out.rs:7:1: 7:2
}
- bb8 (cleanup): {
- drop(_4) -> bb9; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27
+ bb10 (cleanup): {
+ drop(_7) -> bb11; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27
}
- bb9 (cleanup): {
- drop(_2) -> bb10; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27
+ bb11 (cleanup): {
+ drop(_2) -> bb12; // scope 0 at $DIR/uniform_array_move_out.rs:5:26: 5:27
}
- bb10 (cleanup): {
+ bb12 (cleanup): {
resume; // scope 0 at $DIR/uniform_array_move_out.rs:4:1: 7:2
}
}
fn main() {
{
- ::std::io::_print(match match () { () => [], } {
- ref args => unsafe {
- ::core::fmt::Arguments::new_v1(&["rust\n"],
- args)
- }
- });
+ ::std::io::_print(::core::fmt::Arguments::new_v1(&["rust\n"],
+ &match () {
+ () => [],
+ }));
};
}
({
let res =
((::alloc::fmt::format as
- for<'r> fn(Arguments<'r>) -> String {format})((match (match (()
- as
- ())
- {
- ()
- =>
- ([]
- as
- [ArgumentV1; 0]),
- }
- as
- [ArgumentV1; 0])
- {
- ref args
- =>
- unsafe
- {
- ((::core::fmt::Arguments::new_v1
- as
- unsafe fn(&[&'static str], &[ArgumentV1]) -> Arguments {Arguments::new_v1})((&([("test"
- as
- &str)]
- as
- [&str; 1])
- as
- &[&str; 1]),
- (args
- as
- &[ArgumentV1; 0]))
- as
- Arguments)
- }
- }
+ for<'r> fn(Arguments<'r>) -> String {format})(((::core::fmt::Arguments::new_v1
+ as
+ fn(&[&'static str], &[ArgumentV1]) -> Arguments {Arguments::new_v1})((&([("test"
+ as
+ &str)]
+ as
+ [&str; 1])
+ as
+ &[&str; 1]),
+ (&(match (()
+ as
+ ())
+ {
+ ()
+ =>
+ ([]
+ as
+ [ArgumentV1; 0]),
+ }
+ as
+ [ArgumentV1; 0])
+ as
+ &[ArgumentV1; 0]))
as
Arguments))
as String);
24| 1| println!("{:?}", Foo(1));
25| 1|
26| 1| assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
- ^0 ^0 ^0 ^0
+ ^0 ^0 ^0
27| 1| assert_ne!(
28| | Foo(0)
29| | ,
30| | Foo(5)
31| | ,
32| 0| "{}"
- 33| | ,
- 34| | if
+ 33| 0| ,
+ 34| 0| if
35| 0| is_true
36| | {
37| 0| "true message"
// aux-build:primitive-doc.rs
// compile-flags: --extern-html-root-url=primitive_doc=../ -Z unstable-options
-// ignore-windows
+// only-linux
#![feature(no_core)]
#![no_core]
--- /dev/null
+// compile-flags: -Z unstable-options --document-hidden-items
+
+// test for trait methods with `doc(hidden)` with `--document-hidden-items` passed.
+#![crate_name = "foo"]
+
+// @has foo/trait.Trait.html
+// @has - '//*[@id="associatedtype.Foo"]' 'type Foo'
+// @has - '//*[@id="associatedtype.Bar"]' 'type Bar'
+// @has - '//*[@id="tymethod.f"]' 'fn f()'
+// @has - '//*[@id="tymethod.g"]' 'fn g()'
+pub trait Trait {
+ #[doc(hidden)]
+ type Foo;
+ type Bar;
+ #[doc(hidden)]
+ fn f();
+ fn g();
+}
+
+// @has foo/struct.S.html
+// @has - '//*[@id="associatedtype.Foo"]' 'type Foo'
+// @has - '//*[@id="associatedtype.Bar"]' 'type Bar'
+// @has - '//*[@id="method.f"]' 'fn f()'
+// @has - '//*[@id="method.g"]' 'fn g()'
+pub struct S;
+impl Trait for S {
+ type Foo = ();
+ type Bar = ();
+ fn f() {}
+ fn g() {}
+}
--- /dev/null
+// test for trait methods with `doc(hidden)`.
+#![crate_name = "foo"]
+
+// @has foo/trait.Trait.html
+// @!has - '//*[@id="associatedtype.Foo"]' 'type Foo'
+// @has - '//*[@id="associatedtype.Bar"]' 'type Bar'
+// @!has - '//*[@id="tymethod.f"]' 'fn f()'
+// @has - '//*[@id="tymethod.g"]' 'fn g()'
+pub trait Trait {
+ #[doc(hidden)]
+ type Foo;
+ type Bar;
+ #[doc(hidden)]
+ fn f();
+ fn g();
+}
+
+// @has foo/struct.S.html
+// @!has - '//*[@id="associatedtype.Foo"]' 'type Foo'
+// @has - '//*[@id="associatedtype.Bar"]' 'type Bar'
+// @!has - '//*[@id="method.f"]' 'fn f()'
+// @has - '//*[@id="method.g"]' 'fn g()'
+pub struct S;
+impl Trait for S {
+ type Foo = ();
+ type Bar = ();
+ fn f() {}
+ fn g() {}
+}
// aux-build:my-core.rs
// build-aux-docs
// ignore-cross-compile
-// ignore-windows
+// only-linux
#![deny(broken_intra_doc_links)]
#![feature(no_core, lang_items)]
+// ignore-test (fails spuriously, see issue #89228)
+
// FIXME: If two macros in the same module have the same name
// (yes, that's a thing), rustdoc lists both of them on the index page,
// but only documents the first one on the page for the macro.
-#![feature(box_syntax, plugin, rustc_private)]
+#![feature(plugin, rustc_private)]
#![crate_type = "dylib"]
extern crate rustc_ast_pretty;
#[no_mangle]
fn __rustc_plugin_registrar(reg: &mut Registry) {
reg.lint_store.register_lints(&[&MISSING_ALLOWED_ATTR]);
- reg.lint_store.register_late_pass(|| box MissingAllowedAttrPass);
+ reg.lint_store.register_late_pass(|| Box::new(MissingAllowedAttrPass));
}
declare_lint! {
// force-host
#![feature(rustc_private)]
-#![feature(box_syntax)]
extern crate rustc_driver;
extern crate rustc_hir;
&CRATE_NOT_GREY,
&CRATE_NOT_GREEN,
]);
- reg.lint_store.register_late_pass(|| box PassOkay);
- reg.lint_store.register_late_pass(|| box PassRedBlue);
- reg.lint_store.register_late_pass(|| box PassGreyGreen);
+ reg.lint_store.register_late_pass(|| Box::new(PassOkay));
+ reg.lint_store.register_late_pass(|| Box::new(PassRedBlue));
+ reg.lint_store.register_late_pass(|| Box::new(PassGreyGreen));
}
// force-host
#![feature(rustc_private)]
-#![feature(box_syntax)]
extern crate rustc_driver;
extern crate rustc_hir;
#[no_mangle]
fn __rustc_plugin_registrar(reg: &mut Registry) {
reg.lint_store.register_lints(&[&CRATE_NOT_OKAY]);
- reg.lint_store.register_late_pass(|| box Pass);
+ reg.lint_store.register_late_pass(|| Box::new(Pass));
}
// force-host
-#![feature(box_syntax, rustc_private)]
+#![feature(rustc_private)]
// Load rustc as a plugin to get macros.
extern crate rustc_driver;
#[no_mangle]
fn __rustc_plugin_registrar(reg: &mut Registry) {
reg.lint_store.register_lints(&[&TEST_LINT, &PLEASE_LINT]);
- reg.lint_store.register_late_pass(|| box Pass);
+ reg.lint_store.register_late_pass(|| Box::new(Pass));
reg.lint_store.register_group(
true,
"lint_me",
// force-host
-#![feature(box_syntax, rustc_private)]
+#![feature(rustc_private)]
extern crate rustc_ast;
#[no_mangle]
fn __rustc_plugin_registrar(reg: &mut Registry) {
reg.lint_store.register_lints(&[&TEST_LINT]);
- reg.lint_store.register_early_pass(|| box Pass);
+ reg.lint_store.register_early_pass(|| Box::new(Pass));
}
-#![feature(box_syntax, rustc_private)]
+#![feature(rustc_private)]
extern crate rustc_ast;
#[no_mangle]
fn __rustc_plugin_registrar(reg: &mut Registry) {
reg.lint_store.register_lints(&[&TEST_RUSTC_TOOL_LINT, &TEST_LINT, &TEST_GROUP]);
- reg.lint_store.register_early_pass(|| box Pass);
+ reg.lint_store.register_early_pass(|| Box::new(Pass));
reg.lint_store.register_group(
true,
"clippy::group",
// force-host
-#![feature(box_syntax, rustc_private)]
+#![feature(rustc_private)]
extern crate rustc_middle;
extern crate rustc_driver;
#[no_mangle]
fn __rustc_plugin_registrar(_: &mut Registry) {
thread_local!(static FOO: RefCell<Option<Box<Any+Send>>> = RefCell::new(None));
- FOO.with(|s| *s.borrow_mut() = Some(box Foo { foo: 10 } as Box<Any+Send>));
+ FOO.with(|s| *s.borrow_mut() = Some(Box::new(Foo { foo: 10 }) as Box<Any+Send>));
}
// run-pass
#![allow(unused_imports)]
-#![feature(box_syntax)]
#![feature(rustc_private)]
extern crate rustc_macros;
#![allow(non_camel_case_types)]
#![allow(dead_code)]
-#![feature(box_syntax)]
-
struct pair<A,B> {
a: A, b: B
}
}
fn f<A:Clone + 'static>(a: A, b: u16) -> Box<dyn Invokable<A>+'static> {
- box Invoker {
+ Box::new(Invoker {
a: a,
b: b,
- } as Box<dyn Invokable<A>+'static>
+ }) as Box<dyn Invokable<A>+'static>
}
pub fn main() {
// run-pass
-#![feature(box_syntax)]
-
pub fn main() {
- // Tests for indexing into box/& [T; n]
+ // Tests for indexing into Box<[T; n]>/& [T; n]
let x: [isize; 3] = [1, 2, 3];
- let mut x: Box<[isize; 3]> = box x;
+ let mut x: Box<[isize; 3]> = x.into();
assert_eq!(x[0], 1);
assert_eq!(x[1], 2);
assert_eq!(x[2], 3);
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
-pub fn main() { let _quux: Box<Vec<usize>> = box Vec::new(); }
+pub fn main() {
+ let _quux: Box<Vec<usize>> = Box::new(Vec::new());
+}
--- /dev/null
+// only-aarch64
+
+#![feature(asm, global_asm)]
+
+fn main() {
+ let mut foo = 0;
+ unsafe {
+ asm!("", options(nomem, readonly));
+ //~^ ERROR the `nomem` and `readonly` options are mutually exclusive
+ asm!("", options(pure, nomem, noreturn));
+ //~^ ERROR the `pure` and `noreturn` options are mutually exclusive
+ //~^^ ERROR asm with the `pure` option must have at least one output
+ asm!("{}", in(reg) foo, options(pure, nomem));
+ //~^ ERROR asm with the `pure` option must have at least one output
+ asm!("{}", out(reg) foo, options(noreturn));
+ //~^ ERROR asm outputs are not allowed with the `noreturn` option
+ }
+
+ unsafe {
+ asm!("", clobber_abi("foo"));
+ //~^ ERROR invalid ABI for `clobber_abi`
+ asm!("{}", out(reg) foo, clobber_abi("C"));
+ //~^ ERROR asm with `clobber_abi` must specify explicit registers for outputs
+ asm!("", out("x0") foo, clobber_abi("C"));
+ }
+}
+
+global_asm!("", options(nomem));
+//~^ ERROR expected one of
+global_asm!("", options(readonly));
+//~^ ERROR expected one of
+global_asm!("", options(noreturn));
+//~^ ERROR expected one of
+global_asm!("", options(pure));
+//~^ ERROR expected one of
+global_asm!("", options(nostack));
+//~^ ERROR expected one of
+global_asm!("", options(preserves_flags));
+//~^ ERROR expected one of
--- /dev/null
+error: the `nomem` and `readonly` options are mutually exclusive
+ --> $DIR/bad-options.rs:8:18
+ |
+LL | asm!("", options(nomem, readonly));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `pure` and `noreturn` options are mutually exclusive
+ --> $DIR/bad-options.rs:10:18
+ |
+LL | asm!("", options(pure, nomem, noreturn));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: asm with the `pure` option must have at least one output
+ --> $DIR/bad-options.rs:10:18
+ |
+LL | asm!("", options(pure, nomem, noreturn));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: asm with the `pure` option must have at least one output
+ --> $DIR/bad-options.rs:13:33
+ |
+LL | asm!("{}", in(reg) foo, options(pure, nomem));
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: asm outputs are not allowed with the `noreturn` option
+ --> $DIR/bad-options.rs:15:20
+ |
+LL | asm!("{}", out(reg) foo, options(noreturn));
+ | ^^^^^^^^^^^^
+
+error: asm with `clobber_abi` must specify explicit registers for outputs
+ --> $DIR/bad-options.rs:22:20
+ |
+LL | asm!("{}", out(reg) foo, clobber_abi("C"));
+ | ^^^^^^^^^^^^ ---------------- clobber_abi
+ | |
+ | generic outputs
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+ --> $DIR/bad-options.rs:28:25
+ |
+LL | global_asm!("", options(nomem));
+ | ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `readonly`
+ --> $DIR/bad-options.rs:30:25
+ |
+LL | global_asm!("", options(readonly));
+ | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn`
+ --> $DIR/bad-options.rs:32:25
+ |
+LL | global_asm!("", options(noreturn));
+ | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `pure`
+ --> $DIR/bad-options.rs:34:25
+ |
+LL | global_asm!("", options(pure));
+ | ^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `nostack`
+ --> $DIR/bad-options.rs:36:25
+ |
+LL | global_asm!("", options(nostack));
+ | ^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags`
+ --> $DIR/bad-options.rs:38:25
+ |
+LL | global_asm!("", options(preserves_flags));
+ | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: invalid ABI for `clobber_abi`
+ --> $DIR/bad-options.rs:20:18
+ |
+LL | asm!("", clobber_abi("foo"));
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`
+
+error: aborting due to 13 previous errors
+
--- /dev/null
+// only-aarch64
+// compile-flags: -C target-feature=+fp
+
+#![feature(asm)]
+
+fn main() {
+ let mut foo = 0;
+ let mut bar = 0;
+ unsafe {
+ // Bad register/register class
+
+ asm!("{}", in(foo) foo);
+ //~^ ERROR invalid register class `foo`: unknown register class
+ asm!("", in("foo") foo);
+ //~^ ERROR invalid register `foo`: unknown register
+ asm!("{:z}", in(reg) foo);
+ //~^ ERROR invalid asm template modifier for this register class
+ asm!("{:r}", in(vreg) foo);
+ //~^ ERROR invalid asm template modifier for this register class
+ asm!("{:r}", in(vreg_low16) foo);
+ //~^ ERROR invalid asm template modifier for this register class
+ asm!("{:a}", const 0);
+ //~^ ERROR asm template modifiers are not allowed for `const` arguments
+ asm!("{:a}", sym main);
+ //~^ ERROR asm template modifiers are not allowed for `sym` arguments
+ asm!("", in("x29") foo);
+ //~^ ERROR invalid register `x29`: the frame pointer cannot be used as an operand
+ asm!("", in("sp") foo);
+ //~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand
+ asm!("", in("xzr") foo);
+ //~^ ERROR invalid register `xzr`: the zero register cannot be used as an operand
+ asm!("", in("x18") foo);
+ //~^ ERROR invalid register `x18`: x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm
+ asm!("", in("x19") foo);
+ //~^ ERROR invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm
+
+ asm!("", in("p0") foo);
+ //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output
+ asm!("", out("p0") _);
+ asm!("{}", in(preg) foo);
+ //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output
+ asm!("{}", out(preg) _);
+ //~^ ERROR register class `preg` can only be used as a clobber, not as an input or output
+
+ // Explicit register conflicts
+ // (except in/lateout which don't conflict)
+
+ asm!("", in("x0") foo, in("w0") bar);
+ //~^ ERROR register `x0` conflicts with register `x0`
+ asm!("", in("x0") foo, out("x0") bar);
+ //~^ ERROR register `x0` conflicts with register `x0`
+ asm!("", in("w0") foo, lateout("w0") bar);
+ asm!("", in("v0") foo, in("q0") bar);
+ //~^ ERROR register `v0` conflicts with register `v0`
+ asm!("", in("v0") foo, out("q0") bar);
+ //~^ ERROR register `v0` conflicts with register `v0`
+ asm!("", in("v0") foo, lateout("q0") bar);
+ }
+}
--- /dev/null
+error: invalid register class `foo`: unknown register class
+ --> $DIR/bad-reg.rs:12:20
+ |
+LL | asm!("{}", in(foo) foo);
+ | ^^^^^^^^^^^
+
+error: invalid register `foo`: unknown register
+ --> $DIR/bad-reg.rs:14:18
+ |
+LL | asm!("", in("foo") foo);
+ | ^^^^^^^^^^^^^
+
+error: invalid asm template modifier for this register class
+ --> $DIR/bad-reg.rs:16:15
+ |
+LL | asm!("{:z}", in(reg) foo);
+ | ^^^^ ----------- argument
+ | |
+ | template modifier
+ |
+ = note: the `reg` register class supports the following template modifiers: `w`, `x`
+
+error: invalid asm template modifier for this register class
+ --> $DIR/bad-reg.rs:18:15
+ |
+LL | asm!("{:r}", in(vreg) foo);
+ | ^^^^ ------------ argument
+ | |
+ | template modifier
+ |
+ = note: the `vreg` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`
+
+error: invalid asm template modifier for this register class
+ --> $DIR/bad-reg.rs:20:15
+ |
+LL | asm!("{:r}", in(vreg_low16) foo);
+ | ^^^^ ------------------ argument
+ | |
+ | template modifier
+ |
+ = note: the `vreg_low16` register class supports the following template modifiers: `b`, `h`, `s`, `d`, `q`, `v`
+
+error: asm template modifiers are not allowed for `const` arguments
+ --> $DIR/bad-reg.rs:22:15
+ |
+LL | asm!("{:a}", const 0);
+ | ^^^^ ------- argument
+ | |
+ | template modifier
+
+error: asm template modifiers are not allowed for `sym` arguments
+ --> $DIR/bad-reg.rs:24:15
+ |
+LL | asm!("{:a}", sym main);
+ | ^^^^ -------- argument
+ | |
+ | template modifier
+
+error: invalid register `x29`: the frame pointer cannot be used as an operand for inline asm
+ --> $DIR/bad-reg.rs:26:18
+ |
+LL | asm!("", in("x29") foo);
+ | ^^^^^^^^^^^^^
+
+error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
+ --> $DIR/bad-reg.rs:28:18
+ |
+LL | asm!("", in("sp") foo);
+ | ^^^^^^^^^^^^
+
+error: invalid register `xzr`: the zero register cannot be used as an operand for inline asm
+ --> $DIR/bad-reg.rs:30:18
+ |
+LL | asm!("", in("xzr") foo);
+ | ^^^^^^^^^^^^^
+
+error: invalid register `x18`: x18 is used as a reserved register on some targets and cannot be used as an operand for inline asm
+ --> $DIR/bad-reg.rs:32:18
+ |
+LL | asm!("", in("x18") foo);
+ | ^^^^^^^^^^^^^
+
+error: invalid register `x19`: x19 is used internally by LLVM and cannot be used as an operand for inline asm
+ --> $DIR/bad-reg.rs:34:18
+ |
+LL | asm!("", in("x19") foo);
+ | ^^^^^^^^^^^^^
+
+error: register class `preg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:37:18
+ |
+LL | asm!("", in("p0") foo);
+ | ^^^^^^^^^^^^
+
+error: register class `preg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:40:20
+ |
+LL | asm!("{}", in(preg) foo);
+ | ^^^^^^^^^^^^
+
+error: register class `preg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:42:20
+ |
+LL | asm!("{}", out(preg) _);
+ | ^^^^^^^^^^^
+
+error: register `x0` conflicts with register `x0`
+ --> $DIR/bad-reg.rs:48:32
+ |
+LL | asm!("", in("x0") foo, in("w0") bar);
+ | ------------ ^^^^^^^^^^^^ register `x0`
+ | |
+ | register `x0`
+
+error: register `x0` conflicts with register `x0`
+ --> $DIR/bad-reg.rs:50:32
+ |
+LL | asm!("", in("x0") foo, out("x0") bar);
+ | ------------ ^^^^^^^^^^^^^ register `x0`
+ | |
+ | register `x0`
+ |
+help: use `lateout` instead of `out` to avoid conflict
+ --> $DIR/bad-reg.rs:50:18
+ |
+LL | asm!("", in("x0") foo, out("x0") bar);
+ | ^^^^^^^^^^^^
+
+error: register `v0` conflicts with register `v0`
+ --> $DIR/bad-reg.rs:53:32
+ |
+LL | asm!("", in("v0") foo, in("q0") bar);
+ | ------------ ^^^^^^^^^^^^ register `v0`
+ | |
+ | register `v0`
+
+error: register `v0` conflicts with register `v0`
+ --> $DIR/bad-reg.rs:55:32
+ |
+LL | asm!("", in("v0") foo, out("q0") bar);
+ | ------------ ^^^^^^^^^^^^^ register `v0`
+ | |
+ | register `v0`
+ |
+help: use `lateout` instead of `out` to avoid conflict
+ --> $DIR/bad-reg.rs:55:18
+ |
+LL | asm!("", in("v0") foo, out("q0") bar);
+ | ^^^^^^^^^^^^
+
+error: aborting due to 19 previous errors
+
--- /dev/null
+// min-llvm-version: 10.0.1
+// only-aarch64
+// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(asm, global_asm)]
+
+fn const_generic<const X: usize>() -> usize {
+ unsafe {
+ let a: usize;
+ asm!("mov {}, {}", out(reg) a, const X);
+ a
+ }
+}
+
+const fn constfn(x: usize) -> usize {
+ x
+}
+
+fn main() {
+ unsafe {
+ let a: usize;
+ asm!("mov {}, {}", out(reg) a, const 5);
+ assert_eq!(a, 5);
+
+ let b: usize;
+ asm!("mov {}, {}", out(reg) b, const constfn(5));
+ assert_eq!(b, 5);
+
+ let c: usize;
+ asm!("mov {}, {}", out(reg) c, const constfn(5) + constfn(5));
+ assert_eq!(c, 10);
+ }
+
+ let d = const_generic::<5>();
+ assert_eq!(d, 5);
+}
+
+global_asm!("mov x0, {}", const 5);
+global_asm!("mov x0, {}", const constfn(5));
+global_asm!("mov x0, {}", const constfn(5) + constfn(5));
--- /dev/null
+// only-aarch64
+// run-rustfix
+
+#![feature(asm, global_asm)]
+
+fn main() {
+ unsafe {
+ asm!("", options(nomem, ));
+ //~^ ERROR the `nomem` option was already provided
+ asm!("", options(preserves_flags, ));
+ //~^ ERROR the `preserves_flags` option was already provided
+ asm!("", options(nostack, preserves_flags), options());
+ //~^ ERROR the `nostack` option was already provided
+ asm!("", options(nostack, ), options(), options());
+ //~^ ERROR the `nostack` option was already provided
+ //~| ERROR the `nostack` option was already provided
+ //~| ERROR the `nostack` option was already provided
+ asm!(
+ "",
+ options(nomem, noreturn),
+ options(preserves_flags, ), //~ ERROR the `noreturn` option was already provided
+ options( nostack), //~ ERROR the `nomem` option was already provided
+ options(), //~ ERROR the `noreturn` option was already provided
+ );
+ }
+}
--- /dev/null
+// only-aarch64
+// run-rustfix
+
+#![feature(asm, global_asm)]
+
+fn main() {
+ unsafe {
+ asm!("", options(nomem, nomem));
+ //~^ ERROR the `nomem` option was already provided
+ asm!("", options(preserves_flags, preserves_flags));
+ //~^ ERROR the `preserves_flags` option was already provided
+ asm!("", options(nostack, preserves_flags), options(nostack));
+ //~^ ERROR the `nostack` option was already provided
+ asm!("", options(nostack, nostack), options(nostack), options(nostack));
+ //~^ ERROR the `nostack` option was already provided
+ //~| ERROR the `nostack` option was already provided
+ //~| ERROR the `nostack` option was already provided
+ asm!(
+ "",
+ options(nomem, noreturn),
+ options(preserves_flags, noreturn), //~ ERROR the `noreturn` option was already provided
+ options(nomem, nostack), //~ ERROR the `nomem` option was already provided
+ options(noreturn), //~ ERROR the `noreturn` option was already provided
+ );
+ }
+}
--- /dev/null
+error: the `nomem` option was already provided
+ --> $DIR/duplicate-options.rs:8:33
+ |
+LL | asm!("", options(nomem, nomem));
+ | ^^^^^ this option was already provided
+
+error: the `preserves_flags` option was already provided
+ --> $DIR/duplicate-options.rs:10:43
+ |
+LL | asm!("", options(preserves_flags, preserves_flags));
+ | ^^^^^^^^^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:12:61
+ |
+LL | asm!("", options(nostack, preserves_flags), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:14:35
+ |
+LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:14:53
+ |
+LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:14:71
+ |
+LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `noreturn` option was already provided
+ --> $DIR/duplicate-options.rs:21:38
+ |
+LL | options(preserves_flags, noreturn),
+ | ^^^^^^^^ this option was already provided
+
+error: the `nomem` option was already provided
+ --> $DIR/duplicate-options.rs:22:21
+ |
+LL | options(nomem, nostack),
+ | ^^^^^ this option was already provided
+
+error: the `noreturn` option was already provided
+ --> $DIR/duplicate-options.rs:23:21
+ |
+LL | options(noreturn),
+ | ^^^^^^^^ this option was already provided
+
+error: aborting due to 9 previous errors
+
--- /dev/null
+// only-aarch64
+
+#![feature(asm)]
+
+macro_rules! m {
+ ($in:ident $out:ident $lateout:ident $inout:ident $inlateout:ident $const:ident $sym:ident
+ $pure:ident $nomem:ident $readonly:ident $preserves_flags:ident
+ $noreturn:ident $nostack:ident $options:ident) => {
+ unsafe {
+ asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x,
+ //~^ ERROR asm outputs are not allowed with the `noreturn` option
+ const x, sym x,
+ $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack));
+ //~^ ERROR the `nomem` and `readonly` options are mutually exclusive
+ //~| ERROR the `pure` and `noreturn` options are mutually exclusive
+ }
+ };
+}
+
+fn main() {
+ m!(in out lateout inout inlateout const sym
+ pure nomem readonly preserves_flags
+ noreturn nostack options);
+}
--- /dev/null
+error: the `nomem` and `readonly` options are mutually exclusive
+ --> $DIR/interpolated-idents.rs:13:13
+ |
+LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | / m!(in out lateout inout inlateout const sym
+LL | | pure nomem readonly preserves_flags
+LL | | noreturn nostack options);
+ | |_________________________________- in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: the `pure` and `noreturn` options are mutually exclusive
+ --> $DIR/interpolated-idents.rs:13:13
+ |
+LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | / m!(in out lateout inout inlateout const sym
+LL | | pure nomem readonly preserves_flags
+LL | | noreturn nostack options);
+ | |_________________________________- in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: asm outputs are not allowed with the `noreturn` option
+ --> $DIR/interpolated-idents.rs:10:32
+ |
+LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x,
+ | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^
+...
+LL | m!(in out lateout inout inlateout const sym
+ | _____-
+ | |_____|
+ | |_____|
+ | |_____|
+ | |
+LL | | pure nomem readonly preserves_flags
+LL | | noreturn nostack options);
+ | | -
+ | |_________________________________|
+ | |_________________________________in this macro invocation
+ | |_________________________________in this macro invocation
+ | |_________________________________in this macro invocation
+ | in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
--- /dev/null
+// only-aarch64
+
+#![feature(asm, global_asm)]
+
+fn main() {
+ let mut foo = 0;
+ let mut bar = 0;
+ unsafe {
+ asm!();
+ //~^ ERROR requires at least a template string argument
+ asm!(foo);
+ //~^ ERROR asm template must be a string literal
+ asm!("{}" foo);
+ //~^ ERROR expected token: `,`
+ asm!("{}", foo);
+ //~^ ERROR expected operand, clobber_abi, options, or additional template string
+ asm!("{}", in foo);
+ //~^ ERROR expected `(`, found `foo`
+ asm!("{}", in(reg foo));
+ //~^ ERROR expected `)`, found `foo`
+ asm!("{}", in(reg));
+ //~^ ERROR expected expression, found end of macro arguments
+ asm!("{}", inout(=) foo => bar);
+ //~^ ERROR expected register class or explicit register
+ asm!("{}", inout(reg) foo =>);
+ //~^ ERROR expected expression, found end of macro arguments
+ asm!("{}", in(reg) foo => bar);
+ //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
+ asm!("{}", sym foo + bar);
+ //~^ ERROR argument to `sym` must be a path expression
+ asm!("", options(foo));
+ //~^ ERROR expected one of
+ asm!("", options(nomem foo));
+ //~^ ERROR expected one of
+ asm!("", options(nomem, foo));
+ //~^ ERROR expected one of
+ asm!("{}", options(), const foo);
+ //~^ ERROR arguments are not allowed after options
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("", clobber_abi(foo));
+ //~^ ERROR expected string literal
+ asm!("", clobber_abi("C" foo));
+ //~^ ERROR expected `)`, found `foo`
+ asm!("", clobber_abi("C", foo));
+ //~^ ERROR expected `)`, found `,`
+ asm!("{}", clobber_abi("C"), const foo);
+ //~^ ERROR arguments are not allowed after clobber_abi
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("", options(), clobber_abi("C"));
+ //~^ ERROR clobber_abi is not allowed after options
+ asm!("{}", options(), clobber_abi("C"), const foo);
+ //~^ ERROR clobber_abi is not allowed after options
+ asm!("", clobber_abi("C"), clobber_abi("C"));
+ //~^ ERROR clobber_abi specified multiple times
+ asm!("{a}", a = const foo, a = const bar);
+ //~^ ERROR duplicate argument named `a`
+ //~^^ ERROR argument never used
+ //~^^^ ERROR attempt to use a non-constant value in a constant
+ //~^^^^ ERROR attempt to use a non-constant value in a constant
+ asm!("", a = in("x0") foo);
+ //~^ ERROR explicit register arguments cannot have names
+ asm!("{a}", in("x0") foo, a = const bar);
+ //~^ ERROR named arguments cannot follow explicit register arguments
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("{a}", in("x0") foo, a = const bar);
+ //~^ ERROR named arguments cannot follow explicit register arguments
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("{1}", in("x0") foo, const bar);
+ //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("", options(), "");
+ //~^ ERROR expected one of
+ asm!("{}", in(reg) foo, "{}", out(reg) foo);
+ //~^ ERROR expected one of
+ asm!(format!("{{{}}}", 0), in(reg) foo);
+ //~^ ERROR asm template must be a string literal
+ asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
+ //~^ ERROR asm template must be a string literal
+ asm!("{}", in(reg) _);
+ //~^ ERROR _ cannot be used for input operands
+ asm!("{}", inout(reg) _);
+ //~^ ERROR _ cannot be used for input operands
+ asm!("{}", inlateout(reg) _);
+ //~^ ERROR _ cannot be used for input operands
+ }
+}
+
+const FOO: i32 = 1;
+const BAR: i32 = 2;
+global_asm!();
+//~^ ERROR requires at least a template string argument
+global_asm!(FOO);
+//~^ ERROR asm template must be a string literal
+global_asm!("{}" FOO);
+//~^ ERROR expected token: `,`
+global_asm!("{}", FOO);
+//~^ ERROR expected operand, options, or additional template string
+global_asm!("{}", const);
+//~^ ERROR expected expression, found end of macro arguments
+global_asm!("{}", const(reg) FOO);
+//~^ ERROR expected one of
+global_asm!("", options(FOO));
+//~^ ERROR expected one of
+global_asm!("", options(nomem FOO));
+//~^ ERROR expected one of
+global_asm!("", options(nomem, FOO));
+//~^ ERROR expected one of
+global_asm!("{}", options(), const FOO);
+//~^ ERROR arguments are not allowed after options
+global_asm!("", clobber_abi(FOO));
+//~^ ERROR expected string literal
+global_asm!("", clobber_abi("C" FOO));
+//~^ ERROR expected `)`, found `FOO`
+global_asm!("", clobber_abi("C", FOO));
+//~^ ERROR expected `)`, found `,`
+global_asm!("{}", clobber_abi("C"), const FOO);
+//~^ ERROR arguments are not allowed after clobber_abi
+//~^^ ERROR `clobber_abi` cannot be used with `global_asm!`
+global_asm!("", options(), clobber_abi("C"));
+//~^ ERROR clobber_abi is not allowed after options
+global_asm!("{}", options(), clobber_abi("C"), const FOO);
+//~^ ERROR clobber_abi is not allowed after options
+global_asm!("", clobber_abi("C"), clobber_abi("C"));
+//~^ ERROR clobber_abi specified multiple times
+global_asm!("{a}", a = const FOO, a = const BAR);
+//~^ ERROR duplicate argument named `a`
+//~^^ ERROR argument never used
+global_asm!("", options(), "");
+//~^ ERROR expected one of
+global_asm!("{}", const FOO, "{}", const FOO);
+//~^ ERROR expected one of
+global_asm!(format!("{{{}}}", 0), const FOO);
+//~^ ERROR asm template must be a string literal
+global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
+//~^ ERROR asm template must be a string literal
--- /dev/null
+error: requires at least a template string argument
+ --> $DIR/parse-error.rs:9:9
+ |
+LL | asm!();
+ | ^^^^^^^
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:11:14
+ |
+LL | asm!(foo);
+ | ^^^
+
+error: expected token: `,`
+ --> $DIR/parse-error.rs:13:19
+ |
+LL | asm!("{}" foo);
+ | ^^^ expected `,`
+
+error: expected operand, clobber_abi, options, or additional template string
+ --> $DIR/parse-error.rs:15:20
+ |
+LL | asm!("{}", foo);
+ | ^^^ expected operand, clobber_abi, options, or additional template string
+
+error: expected `(`, found `foo`
+ --> $DIR/parse-error.rs:17:23
+ |
+LL | asm!("{}", in foo);
+ | ^^^ expected `(`
+
+error: expected `)`, found `foo`
+ --> $DIR/parse-error.rs:19:27
+ |
+LL | asm!("{}", in(reg foo));
+ | ^^^ expected `)`
+
+error: expected expression, found end of macro arguments
+ --> $DIR/parse-error.rs:21:27
+ |
+LL | asm!("{}", in(reg));
+ | ^ expected expression
+
+error: expected register class or explicit register
+ --> $DIR/parse-error.rs:23:26
+ |
+LL | asm!("{}", inout(=) foo => bar);
+ | ^
+
+error: expected expression, found end of macro arguments
+ --> $DIR/parse-error.rs:25:37
+ |
+LL | asm!("{}", inout(reg) foo =>);
+ | ^ expected expression
+
+error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
+ --> $DIR/parse-error.rs:27:32
+ |
+LL | asm!("{}", in(reg) foo => bar);
+ | ^^ expected one of 7 possible tokens
+
+error: argument to `sym` must be a path expression
+ --> $DIR/parse-error.rs:29:24
+ |
+LL | asm!("{}", sym foo + bar);
+ | ^^^^^^^^^
+
+error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
+ --> $DIR/parse-error.rs:31:26
+ |
+LL | asm!("", options(foo));
+ | ^^^ expected one of 9 possible tokens
+
+error: expected one of `)` or `,`, found `foo`
+ --> $DIR/parse-error.rs:33:32
+ |
+LL | asm!("", options(nomem foo));
+ | ^^^ expected one of `)` or `,`
+
+error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
+ --> $DIR/parse-error.rs:35:33
+ |
+LL | asm!("", options(nomem, foo));
+ | ^^^ expected one of 9 possible tokens
+
+error: arguments are not allowed after options
+ --> $DIR/parse-error.rs:37:31
+ |
+LL | asm!("{}", options(), const foo);
+ | --------- ^^^^^^^^^ argument
+ | |
+ | previous options
+
+error: expected string literal
+ --> $DIR/parse-error.rs:40:30
+ |
+LL | asm!("", clobber_abi(foo));
+ | ^^^ not a string literal
+
+error: expected `)`, found `foo`
+ --> $DIR/parse-error.rs:42:34
+ |
+LL | asm!("", clobber_abi("C" foo));
+ | ^^^ expected `)`
+
+error: expected `)`, found `,`
+ --> $DIR/parse-error.rs:44:33
+ |
+LL | asm!("", clobber_abi("C", foo));
+ | ^ expected `)`
+
+error: arguments are not allowed after clobber_abi
+ --> $DIR/parse-error.rs:46:38
+ |
+LL | asm!("{}", clobber_abi("C"), const foo);
+ | ---------------- ^^^^^^^^^ argument
+ | |
+ | clobber_abi
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:49:29
+ |
+LL | asm!("", options(), clobber_abi("C"));
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:51:31
+ |
+LL | asm!("{}", options(), clobber_abi("C"), const foo);
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: clobber_abi specified multiple times
+ --> $DIR/parse-error.rs:53:36
+ |
+LL | asm!("", clobber_abi("C"), clobber_abi("C"));
+ | ---------------- ^^^^^^^^^^^^^^^^
+ | |
+ | clobber_abi previously specified here
+
+error: duplicate argument named `a`
+ --> $DIR/parse-error.rs:55:36
+ |
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ------------- ^^^^^^^^^^^^^ duplicate argument
+ | |
+ | previously here
+
+error: argument never used
+ --> $DIR/parse-error.rs:55:36
+ |
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ^^^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
+
+error: explicit register arguments cannot have names
+ --> $DIR/parse-error.rs:60:18
+ |
+LL | asm!("", a = in("x0") foo);
+ | ^^^^^^^^^^^^^^^^
+
+error: named arguments cannot follow explicit register arguments
+ --> $DIR/parse-error.rs:62:35
+ |
+LL | asm!("{a}", in("x0") foo, a = const bar);
+ | ------------ ^^^^^^^^^^^^^ named argument
+ | |
+ | explicit register argument
+
+error: named arguments cannot follow explicit register arguments
+ --> $DIR/parse-error.rs:65:35
+ |
+LL | asm!("{a}", in("x0") foo, a = const bar);
+ | ------------ ^^^^^^^^^^^^^ named argument
+ | |
+ | explicit register argument
+
+error: positional arguments cannot follow named arguments or explicit register arguments
+ --> $DIR/parse-error.rs:68:35
+ |
+LL | asm!("{1}", in("x0") foo, const bar);
+ | ------------ ^^^^^^^^^ positional argument
+ | |
+ | explicit register argument
+
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""`
+ --> $DIR/parse-error.rs:71:29
+ |
+LL | asm!("", options(), "");
+ | ^^ expected one of 9 possible tokens
+
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
+ --> $DIR/parse-error.rs:73:33
+ |
+LL | asm!("{}", in(reg) foo, "{}", out(reg) foo);
+ | ^^^^ expected one of 9 possible tokens
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:75:14
+ |
+LL | asm!(format!("{{{}}}", 0), in(reg) foo);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:77:21
+ |
+LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:79:28
+ |
+LL | asm!("{}", in(reg) _);
+ | ^
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:81:31
+ |
+LL | asm!("{}", inout(reg) _);
+ | ^
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:83:35
+ |
+LL | asm!("{}", inlateout(reg) _);
+ | ^
+
+error: requires at least a template string argument
+ --> $DIR/parse-error.rs:90:1
+ |
+LL | global_asm!();
+ | ^^^^^^^^^^^^^^
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:92:13
+ |
+LL | global_asm!(FOO);
+ | ^^^
+
+error: expected token: `,`
+ --> $DIR/parse-error.rs:94:18
+ |
+LL | global_asm!("{}" FOO);
+ | ^^^ expected `,`
+
+error: expected operand, options, or additional template string
+ --> $DIR/parse-error.rs:96:19
+ |
+LL | global_asm!("{}", FOO);
+ | ^^^ expected operand, options, or additional template string
+
+error: expected expression, found end of macro arguments
+ --> $DIR/parse-error.rs:98:24
+ |
+LL | global_asm!("{}", const);
+ | ^ expected expression
+
+error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
+ --> $DIR/parse-error.rs:100:30
+ |
+LL | global_asm!("{}", const(reg) FOO);
+ | ^^^ expected one of `,`, `.`, `?`, or an operator
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
+ --> $DIR/parse-error.rs:102:25
+ |
+LL | global_asm!("", options(FOO));
+ | ^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+ --> $DIR/parse-error.rs:104:25
+ |
+LL | global_asm!("", options(nomem FOO));
+ | ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+ --> $DIR/parse-error.rs:106:25
+ |
+LL | global_asm!("", options(nomem, FOO));
+ | ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: arguments are not allowed after options
+ --> $DIR/parse-error.rs:108:30
+ |
+LL | global_asm!("{}", options(), const FOO);
+ | --------- ^^^^^^^^^ argument
+ | |
+ | previous options
+
+error: expected string literal
+ --> $DIR/parse-error.rs:110:29
+ |
+LL | global_asm!("", clobber_abi(FOO));
+ | ^^^ not a string literal
+
+error: expected `)`, found `FOO`
+ --> $DIR/parse-error.rs:112:33
+ |
+LL | global_asm!("", clobber_abi("C" FOO));
+ | ^^^ expected `)`
+
+error: expected `)`, found `,`
+ --> $DIR/parse-error.rs:114:32
+ |
+LL | global_asm!("", clobber_abi("C", FOO));
+ | ^ expected `)`
+
+error: arguments are not allowed after clobber_abi
+ --> $DIR/parse-error.rs:116:37
+ |
+LL | global_asm!("{}", clobber_abi("C"), const FOO);
+ | ---------------- ^^^^^^^^^ argument
+ | |
+ | clobber_abi
+
+error: `clobber_abi` cannot be used with `global_asm!`
+ --> $DIR/parse-error.rs:116:19
+ |
+LL | global_asm!("{}", clobber_abi("C"), const FOO);
+ | ^^^^^^^^^^^^^^^^
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:119:28
+ |
+LL | global_asm!("", options(), clobber_abi("C"));
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:121:30
+ |
+LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: clobber_abi specified multiple times
+ --> $DIR/parse-error.rs:123:35
+ |
+LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
+ | ---------------- ^^^^^^^^^^^^^^^^
+ | |
+ | clobber_abi previously specified here
+
+error: duplicate argument named `a`
+ --> $DIR/parse-error.rs:125:35
+ |
+LL | global_asm!("{a}", a = const FOO, a = const BAR);
+ | ------------- ^^^^^^^^^^^^^ duplicate argument
+ | |
+ | previously here
+
+error: argument never used
+ --> $DIR/parse-error.rs:125:35
+ |
+LL | global_asm!("{a}", a = const FOO, a = const BAR);
+ | ^^^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
+
+error: expected one of `clobber_abi`, `const`, or `options`, found `""`
+ --> $DIR/parse-error.rs:128:28
+ |
+LL | global_asm!("", options(), "");
+ | ^^ expected one of `clobber_abi`, `const`, or `options`
+
+error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"`
+ --> $DIR/parse-error.rs:130:30
+ |
+LL | global_asm!("{}", const FOO, "{}", const FOO);
+ | ^^^^ expected one of `clobber_abi`, `const`, or `options`
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:132:13
+ |
+LL | global_asm!(format!("{{{}}}", 0), const FOO);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:134:20
+ |
+LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:37:37
+ |
+LL | let mut foo = 0;
+ | ---------- help: consider using `const` instead of `let`: `const foo`
+...
+LL | asm!("{}", options(), const foo);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:46:44
+ |
+LL | let mut foo = 0;
+ | ---------- help: consider using `const` instead of `let`: `const foo`
+...
+LL | asm!("{}", clobber_abi("C"), const foo);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:55:31
+ |
+LL | let mut foo = 0;
+ | ---------- help: consider using `const` instead of `let`: `const foo`
+...
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:55:46
+ |
+LL | let mut bar = 0;
+ | ---------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:62:45
+ |
+LL | let mut bar = 0;
+ | ---------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{a}", in("x0") foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:65:45
+ |
+LL | let mut bar = 0;
+ | ---------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{a}", in("x0") foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:68:41
+ |
+LL | let mut bar = 0;
+ | ---------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{1}", in("x0") foo, const bar);
+ | ^^^ non-constant value
+
+error: aborting due to 66 previous errors
+
+For more information about this error, try `rustc --explain E0435`.
--- /dev/null
+// min-llvm-version: 10.0.1
+// only-aarch64
+// build-fail
+// compile-flags: -Ccodegen-units=1
+#![feature(asm)]
+
+// Checks that inline asm errors are mapped to the correct line in the source code.
+
+fn main() {
+ unsafe {
+ asm!("invalid_instruction");
+ //~^ ERROR: unrecognized instruction mnemonic
+
+ asm!("
+ invalid_instruction
+ ");
+ //~^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(r#"
+ invalid_instruction
+ "#);
+ //~^^ ERROR: unrecognized instruction mnemonic
+
+ asm!("
+ mov x0, x0
+ invalid_instruction
+ mov x0, x0
+ ");
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(r#"
+ mov x0, x0
+ invalid_instruction
+ mov x0, x0
+ "#);
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(concat!("invalid", "_", "instruction"));
+ //~^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ "invalid_instruction",
+ );
+ //~^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ "mov x0, x0",
+ "invalid_instruction",
+ "mov x0, x0",
+ );
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ "mov x0, x0\n",
+ "invalid_instruction",
+ "mov x0, x0",
+ );
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ "mov x0, x0",
+ concat!("invalid", "_", "instruction"),
+ "mov x0, x0",
+ );
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ concat!("mov x0", ", ", "x0"),
+ concat!("invalid", "_", "instruction"),
+ concat!("mov x0", ", ", "x0"),
+ );
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ // Make sure template strings get separated
+ asm!(
+ "invalid_instruction1",
+ "invalid_instruction2",
+ );
+ //~^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2",
+ ),
+ );
+ //~^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2",
+ ),
+ concat!(
+ "invalid", "_", "instruction3", "\n",
+ "invalid", "_", "instruction4",
+ ),
+ );
+ //~^^^^^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^^^ ERROR: unrecognized instruction mnemonic
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2", "\n",
+ ),
+ concat!(
+ "invalid", "_", "instruction3", "\n",
+ "invalid", "_", "instruction4", "\n",
+ ),
+ );
+ //~^^^^^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^^ ERROR: unrecognized instruction mnemonic
+ //~^^^^^^^^ ERROR: unrecognized instruction mnemonic
+ }
+}
--- /dev/null
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:11:15
+ |
+LL | asm!("invalid_instruction");
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:15:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:13
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:20:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:13
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:26:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:13
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:33:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:13
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:38:14
+ |
+LL | asm!(concat!("invalid", "_", "instruction"));
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:42:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:48:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:55:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:62:13
+ |
+LL | concat!("invalid", "_", "instruction"),
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:69:13
+ |
+LL | concat!("invalid", "_", "instruction"),
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:76:14
+ |
+LL | "invalid_instruction1",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction1
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:77:14
+ |
+LL | "invalid_instruction2",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction2
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:83:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction1
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:83:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction2
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:92:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction1
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:92:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction2
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:96:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction3
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:96:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:1
+ |
+LL | invalid_instruction4
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:107:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | invalid_instruction1
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:107:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:1
+ |
+LL | invalid_instruction2
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:111:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:1
+ |
+LL | invalid_instruction3
+ | ^
+
+error: unrecognized instruction mnemonic
+ --> $DIR/srcloc.rs:111:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:5:1
+ |
+LL | invalid_instruction4
+ | ^
+
+error: aborting due to 23 previous errors
+
--- /dev/null
+// min-llvm-version: 10.0.1
+// only-aarch64
+// only-linux
+// run-pass
+
+#![feature(asm, thread_local)]
+
+extern "C" fn f1() -> i32 {
+ 111
+}
+
+// The compiler will generate a shim to hide the caller location parameter.
+#[track_caller]
+fn f2() -> i32 {
+ 222
+}
+
+macro_rules! call {
+ ($func:path) => {
+ unsafe {
+ let result: i32;
+ asm!("bl {}", sym $func,
+ out("w0") result,
+ out("x20") _, out("x21") _, out("x22") _,
+ out("x23") _, out("x24") _, out("x25") _,
+ out("x26") _, out("x27") _, out("x28") _,
+ );
+ result
+ }
+ }
+}
+
+macro_rules! static_addr {
+ ($s:expr) => {
+ unsafe {
+ let result: *const u32;
+ asm!(
+ // ADRP gives the address of a 4KB page from a PC-relative address
+ "adrp {out}, {sym}",
+ // We then add the remaining lower 12 bits
+ "add {out}, {out}, #:lo12:{sym}",
+ out = out(reg) result,
+ sym = sym $s);
+ result
+ }
+ }
+}
+macro_rules! static_tls_addr {
+ ($s:expr) => {
+ unsafe {
+ let result: *const u32;
+ asm!(
+ // Load the thread pointer register
+ "mrs {out}, TPIDR_EL0",
+ // Add the top 12 bits of the symbol's offset
+ "add {out}, {out}, :tprel_hi12:{sym}",
+ // And the bottom 12 bits
+ "add {out}, {out}, :tprel_lo12:{sym}",
+ out = out(reg) result,
+ sym = sym $s
+ );
+ result
+ }
+ }
+}
+
+static S1: u32 = 111;
+#[thread_local]
+static S2: u32 = 222;
+
+fn main() {
+ assert_eq!(call!(f1), 111);
+ assert_eq!(call!(f2), 222);
+ assert_eq!(static_addr!(S1), &S1 as *const u32);
+ assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
+ std::thread::spawn(|| {
+ assert_eq!(static_addr!(S1), &S1 as *const u32);
+ assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
+ }).join().unwrap();
+}
--- /dev/null
+// only-aarch64
+
+#![feature(asm, repr_simd, never_type)]
+
+#[repr(simd)]
+#[derive(Clone, Copy)]
+struct SimdType(f32, f32, f32, f32);
+
+#[repr(simd)]
+struct SimdNonCopy(f32, f32, f32, f32);
+
+fn main() {
+ unsafe {
+ // Inputs must be initialized
+
+ let x: u64;
+ asm!("{}", in(reg) x);
+ //~^ ERROR use of possibly-uninitialized variable: `x`
+ let mut y: u64;
+ asm!("{}", inout(reg) y);
+ //~^ ERROR use of possibly-uninitialized variable: `y`
+ let _ = y;
+
+ // Outputs require mutable places
+
+ let v: Vec<u64> = vec![0, 1, 2];
+ asm!("{}", in(reg) v[0]);
+ asm!("{}", out(reg) v[0]);
+ //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+ asm!("{}", inout(reg) v[0]);
+ //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+
+ // Sym operands must point to a function or static
+
+ const C: i32 = 0;
+ static S: i32 = 0;
+ asm!("{}", sym S);
+ asm!("{}", sym main);
+ asm!("{}", sym C);
+ //~^ ERROR asm `sym` operand must point to a fn or static
+ asm!("{}", sym x);
+ //~^ ERROR asm `sym` operand must point to a fn or static
+
+ // Register operands must be Copy
+
+ asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
+ //~^ ERROR arguments for inline assembly must be copyable
+
+ // Register operands must be integers, floats, SIMD vectors, pointers or
+ // function pointers.
+
+ asm!("{}", in(reg) 0i64);
+ asm!("{}", in(reg) 0f64);
+ asm!("{:v}", in(vreg) SimdType(0.0, 0.0, 0.0, 0.0));
+ asm!("{}", in(reg) 0 as *const u8);
+ asm!("{}", in(reg) 0 as *mut u8);
+ asm!("{}", in(reg) main as fn());
+ asm!("{}", in(reg) |x: i32| x);
+ //~^ ERROR cannot use value of type
+ asm!("{}", in(reg) vec![0]);
+ //~^ ERROR cannot use value of type `Vec<i32>` for inline assembly
+ asm!("{}", in(reg) (1, 2, 3));
+ //~^ ERROR cannot use value of type `(i32, i32, i32)` for inline assembly
+ asm!("{}", in(reg) [1, 2, 3]);
+ //~^ ERROR cannot use value of type `[i32; 3]` for inline assembly
+
+ // Register inputs (but not outputs) allow references and function types
+
+ let mut f = main;
+ let mut r = &mut 0;
+ asm!("{}", in(reg) f);
+ asm!("{}", inout(reg) f);
+ //~^ ERROR cannot use value of type `fn() {main}` for inline assembly
+ asm!("{}", in(reg) r);
+ asm!("{}", inout(reg) r);
+ //~^ ERROR cannot use value of type `&mut i32` for inline assembly
+ let _ = (f, r);
+
+ // Type checks ignore never type
+
+ let u: ! = unreachable!();
+ asm!("{}", in(reg) u);
+ }
+}
--- /dev/null
+error: arguments for inline assembly must be copyable
+ --> $DIR/type-check-2.rs:46:31
+ |
+LL | asm!("{:v}", in(vreg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `SimdNonCopy` does not implement the Copy trait
+
+error: cannot use value of type `[closure@$DIR/type-check-2.rs:58:28: 58:38]` for inline assembly
+ --> $DIR/type-check-2.rs:58:28
+ |
+LL | asm!("{}", in(reg) |x: i32| x);
+ | ^^^^^^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `Vec<i32>` for inline assembly
+ --> $DIR/type-check-2.rs:60:28
+ |
+LL | asm!("{}", in(reg) vec![0]);
+ | ^^^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+ = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot use value of type `(i32, i32, i32)` for inline assembly
+ --> $DIR/type-check-2.rs:62:28
+ |
+LL | asm!("{}", in(reg) (1, 2, 3));
+ | ^^^^^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `[i32; 3]` for inline assembly
+ --> $DIR/type-check-2.rs:64:28
+ |
+LL | asm!("{}", in(reg) [1, 2, 3]);
+ | ^^^^^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `fn() {main}` for inline assembly
+ --> $DIR/type-check-2.rs:72:31
+ |
+LL | asm!("{}", inout(reg) f);
+ | ^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `&mut i32` for inline assembly
+ --> $DIR/type-check-2.rs:75:31
+ |
+LL | asm!("{}", inout(reg) r);
+ | ^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: asm `sym` operand must point to a fn or static
+ --> $DIR/type-check-2.rs:39:24
+ |
+LL | asm!("{}", sym C);
+ | ^
+
+error: asm `sym` operand must point to a fn or static
+ --> $DIR/type-check-2.rs:41:24
+ |
+LL | asm!("{}", sym x);
+ | ^
+
+error[E0381]: use of possibly-uninitialized variable: `x`
+ --> $DIR/type-check-2.rs:17:28
+ |
+LL | asm!("{}", in(reg) x);
+ | ^ use of possibly-uninitialized `x`
+
+error[E0381]: use of possibly-uninitialized variable: `y`
+ --> $DIR/type-check-2.rs:20:9
+ |
+LL | asm!("{}", inout(reg) y);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+ --> $DIR/type-check-2.rs:28:29
+ |
+LL | let v: Vec<u64> = vec![0, 1, 2];
+ | - help: consider changing this to be mutable: `mut v`
+LL | asm!("{}", in(reg) v[0]);
+LL | asm!("{}", out(reg) v[0]);
+ | ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+ --> $DIR/type-check-2.rs:30:31
+ |
+LL | let v: Vec<u64> = vec![0, 1, 2];
+ | - help: consider changing this to be mutable: `mut v`
+...
+LL | asm!("{}", inout(reg) v[0]);
+ | ^ cannot borrow as mutable
+
+error: aborting due to 13 previous errors
+
+Some errors have detailed explanations: E0381, E0596.
+For more information about an error, try `rustc --explain E0381`.
--- /dev/null
+// only-aarch64
+// compile-flags: -C target-feature=+neon
+
+#![feature(asm, global_asm, repr_simd, stdsimd)]
+
+use std::arch::aarch64::float64x2_t;
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct Simd256bit(f64, f64,f64, f64);
+
+fn main() {
+ let f64x2: float64x2_t = unsafe { std::mem::transmute(0i128) };
+ let f64x4 = Simd256bit(0.0, 0.0, 0.0, 0.0);
+
+ unsafe {
+ // Types must be listed in the register class.
+
+ // Success cases
+ asm!("{:w}", in(reg) 0u8);
+ asm!("{:w}", in(reg) 0u16);
+ asm!("{:w}", in(reg) 0u32);
+ asm!("{:w}", in(reg) 0f32);
+ asm!("{}", in(reg) 0i64);
+ asm!("{}", in(reg) 0f64);
+
+ asm!("{:b}", in(vreg) 0u8);
+ asm!("{:h}", in(vreg) 0u16);
+ asm!("{:s}", in(vreg) 0u32);
+ asm!("{:s}", in(vreg) 0f32);
+ asm!("{:d}", in(vreg) 0u64);
+ asm!("{:d}", in(vreg) 0f64);
+ asm!("{:q}", in(vreg) f64x2);
+ asm!("{:v}", in(vreg) f64x2);
+
+ // Should be the same as vreg
+ asm!("{:q}", in(vreg_low16) f64x2);
+
+ // Template modifiers of a different size to the argument are fine
+ asm!("{:w}", in(reg) 0u64);
+ asm!("{:x}", in(reg) 0u32);
+ asm!("{:b}", in(vreg) 0u64);
+ asm!("{:d}", in(vreg_low16) f64x2);
+
+
+ // Template modifier suggestions for sub-registers
+
+ asm!("{}", in(reg) 0u8);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(reg) 0u16);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(reg) 0i32);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(reg) 0f32);
+ //~^ WARN formatting may not be suitable for sub-register argument
+
+ asm!("{}", in(vreg) 0i16);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(vreg) 0f32);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(vreg) 0f64);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(vreg_low16) 0f64);
+ //~^ WARN formatting may not be suitable for sub-register argument
+
+ asm!("{0} {0}", in(reg) 0i16);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{0} {0:x}", in(reg) 0i16);
+ //~^ WARN formatting may not be suitable for sub-register argument
+
+ // Invalid registers
+
+ asm!("{}", in(reg) 0i128);
+ //~^ ERROR type `i128` cannot be used with this register class
+ asm!("{}", in(reg) f64x2);
+ //~^ ERROR type `float64x2_t` cannot be used with this register class
+ asm!("{}", in(vreg) f64x4);
+ //~^ ERROR type `Simd256bit` cannot be used with this register class
+
+ // Split inout operands must have compatible types
+
+ let mut val_i16: i16;
+ let mut val_f32: f32;
+ let mut val_u32: u32;
+ let mut val_u64: u64;
+ let mut val_ptr: *mut u8;
+ asm!("{:x}", inout(reg) 0u16 => val_i16);
+ asm!("{:x}", inout(reg) 0u32 => val_f32);
+ //~^ ERROR incompatible types for asm inout argument
+ asm!("{:x}", inout(reg) 0u32 => val_ptr);
+ //~^ ERROR incompatible types for asm inout argument
+ asm!("{:x}", inout(reg) main => val_u32);
+ //~^ ERROR incompatible types for asm inout argument
+ asm!("{:x}", inout(reg) 0u64 => val_ptr);
+ asm!("{:x}", inout(reg) main => val_u64);
+ }
+}
+
+// Constants must be... constant
+
+static S: i32 = 1;
+const fn const_foo(x: i32) -> i32 {
+ x
+}
+const fn const_bar<T>(x: T) -> T {
+ x
+}
+global_asm!("{}", const S);
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_foo(0));
+global_asm!("{}", const const_foo(S));
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_bar(0));
+global_asm!("{}", const const_bar(S));
+//~^ ERROR constants cannot refer to statics
--- /dev/null
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:48:15
+ |
+LL | asm!("{}", in(reg) 0u8);
+ | ^^ --- for this argument
+ |
+ = note: `#[warn(asm_sub_register)]` on by default
+ = help: use the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier to keep the default formatting of `x0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:50:15
+ |
+LL | asm!("{}", in(reg) 0u16);
+ | ^^ ---- for this argument
+ |
+ = help: use the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier to keep the default formatting of `x0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:52:15
+ |
+LL | asm!("{}", in(reg) 0i32);
+ | ^^ ---- for this argument
+ |
+ = help: use the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier to keep the default formatting of `x0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:54:15
+ |
+LL | asm!("{}", in(reg) 0f32);
+ | ^^ ---- for this argument
+ |
+ = help: use the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier to keep the default formatting of `x0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:57:15
+ |
+LL | asm!("{}", in(vreg) 0i16);
+ | ^^ ---- for this argument
+ |
+ = help: use the `h` modifier to have the register formatted as `h0`
+ = help: or use the `v` modifier to keep the default formatting of `v0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:59:15
+ |
+LL | asm!("{}", in(vreg) 0f32);
+ | ^^ ---- for this argument
+ |
+ = help: use the `s` modifier to have the register formatted as `s0`
+ = help: or use the `v` modifier to keep the default formatting of `v0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:61:15
+ |
+LL | asm!("{}", in(vreg) 0f64);
+ | ^^ ---- for this argument
+ |
+ = help: use the `d` modifier to have the register formatted as `d0`
+ = help: or use the `v` modifier to keep the default formatting of `v0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:63:15
+ |
+LL | asm!("{}", in(vreg_low16) 0f64);
+ | ^^ ---- for this argument
+ |
+ = help: use the `d` modifier to have the register formatted as `d0`
+ = help: or use the `v` modifier to keep the default formatting of `v0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:66:15
+ |
+LL | asm!("{0} {0}", in(reg) 0i16);
+ | ^^^ ^^^ ---- for this argument
+ |
+ = help: use the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier to keep the default formatting of `x0`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:68:15
+ |
+LL | asm!("{0} {0:x}", in(reg) 0i16);
+ | ^^^ ---- for this argument
+ |
+ = help: use the `w` modifier to have the register formatted as `w0`
+ = help: or use the `x` modifier to keep the default formatting of `x0`
+
+error: type `i128` cannot be used with this register class
+ --> $DIR/type-check-3.rs:73:28
+ |
+LL | asm!("{}", in(reg) 0i128);
+ | ^^^^^
+ |
+ = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
+
+error: type `float64x2_t` cannot be used with this register class
+ --> $DIR/type-check-3.rs:75:28
+ |
+LL | asm!("{}", in(reg) f64x2);
+ | ^^^^^
+ |
+ = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
+
+error: type `Simd256bit` cannot be used with this register class
+ --> $DIR/type-check-3.rs:77:29
+ |
+LL | asm!("{}", in(vreg) f64x4);
+ | ^^^^^
+ |
+ = note: register class `vreg` supports these types: i8, i16, i32, i64, f32, f64, i8x8, i16x4, i32x2, i64x1, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
+
+error: incompatible types for asm inout argument
+ --> $DIR/type-check-3.rs:88:33
+ |
+LL | asm!("{:x}", inout(reg) 0u32 => val_f32);
+ | ^^^^ ^^^^^^^ type `f32`
+ | |
+ | type `u32`
+ |
+ = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
+
+error: incompatible types for asm inout argument
+ --> $DIR/type-check-3.rs:90:33
+ |
+LL | asm!("{:x}", inout(reg) 0u32 => val_ptr);
+ | ^^^^ ^^^^^^^ type `*mut u8`
+ | |
+ | type `u32`
+ |
+ = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
+
+error: incompatible types for asm inout argument
+ --> $DIR/type-check-3.rs:92:33
+ |
+LL | asm!("{:x}", inout(reg) main => val_u32);
+ | ^^^^ ^^^^^^^ type `u32`
+ | |
+ | type `fn()`
+ |
+ = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
+
+error[E0013]: constants cannot refer to statics
+ --> $DIR/type-check-3.rs:108:25
+ |
+LL | global_asm!("{}", const S);
+ | ^
+ |
+ = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+ --> $DIR/type-check-3.rs:111:35
+ |
+LL | global_asm!("{}", const const_foo(S));
+ | ^
+ |
+ = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+ --> $DIR/type-check-3.rs:114:35
+ |
+LL | global_asm!("{}", const const_bar(S));
+ | ^
+ |
+ = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error: aborting due to 9 previous errors; 10 warnings emitted
+
+For more information about this error, try `rustc --explain E0013`.
+++ /dev/null
-// only-x86_64
-
-#![feature(asm, global_asm)]
-
-fn main() {
- let mut foo = 0;
- unsafe {
- asm!("", options(nomem, readonly));
- //~^ ERROR the `nomem` and `readonly` options are mutually exclusive
- asm!("", options(pure, nomem, noreturn));
- //~^ ERROR the `pure` and `noreturn` options are mutually exclusive
- //~^^ ERROR asm with the `pure` option must have at least one output
- asm!("{}", in(reg) foo, options(pure, nomem));
- //~^ ERROR asm with the `pure` option must have at least one output
- asm!("{}", out(reg) foo, options(noreturn));
- //~^ ERROR asm outputs are not allowed with the `noreturn` option
- }
-
- unsafe {
- asm!("", clobber_abi("foo"));
- //~^ ERROR invalid ABI for `clobber_abi`
- asm!("{}", out(reg) foo, clobber_abi("C"));
- //~^ ERROR asm with `clobber_abi` must specify explicit registers for outputs
- asm!("", out("eax") foo, clobber_abi("C"));
- }
-}
-
-global_asm!("", options(nomem));
-//~^ ERROR expected one of
-global_asm!("", options(readonly));
-//~^ ERROR expected one of
-global_asm!("", options(noreturn));
-//~^ ERROR expected one of
-global_asm!("", options(pure));
-//~^ ERROR expected one of
-global_asm!("", options(nostack));
-//~^ ERROR expected one of
-global_asm!("", options(preserves_flags));
-//~^ ERROR expected one of
+++ /dev/null
-error: the `nomem` and `readonly` options are mutually exclusive
- --> $DIR/bad-options.rs:8:18
- |
-LL | asm!("", options(nomem, readonly));
- | ^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: the `pure` and `noreturn` options are mutually exclusive
- --> $DIR/bad-options.rs:10:18
- |
-LL | asm!("", options(pure, nomem, noreturn));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: asm with the `pure` option must have at least one output
- --> $DIR/bad-options.rs:10:18
- |
-LL | asm!("", options(pure, nomem, noreturn));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: asm with the `pure` option must have at least one output
- --> $DIR/bad-options.rs:13:33
- |
-LL | asm!("{}", in(reg) foo, options(pure, nomem));
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: asm outputs are not allowed with the `noreturn` option
- --> $DIR/bad-options.rs:15:20
- |
-LL | asm!("{}", out(reg) foo, options(noreturn));
- | ^^^^^^^^^^^^
-
-error: asm with `clobber_abi` must specify explicit registers for outputs
- --> $DIR/bad-options.rs:22:20
- |
-LL | asm!("{}", out(reg) foo, clobber_abi("C"));
- | ^^^^^^^^^^^^ ---------------- clobber_abi
- | |
- | generic outputs
-
-error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
- --> $DIR/bad-options.rs:28:25
- |
-LL | global_asm!("", options(nomem));
- | ^^^^^ expected one of `)`, `att_syntax`, or `raw`
-
-error: expected one of `)`, `att_syntax`, or `raw`, found `readonly`
- --> $DIR/bad-options.rs:30:25
- |
-LL | global_asm!("", options(readonly));
- | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
-
-error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn`
- --> $DIR/bad-options.rs:32:25
- |
-LL | global_asm!("", options(noreturn));
- | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
-
-error: expected one of `)`, `att_syntax`, or `raw`, found `pure`
- --> $DIR/bad-options.rs:34:25
- |
-LL | global_asm!("", options(pure));
- | ^^^^ expected one of `)`, `att_syntax`, or `raw`
-
-error: expected one of `)`, `att_syntax`, or `raw`, found `nostack`
- --> $DIR/bad-options.rs:36:25
- |
-LL | global_asm!("", options(nostack));
- | ^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
-
-error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags`
- --> $DIR/bad-options.rs:38:25
- |
-LL | global_asm!("", options(preserves_flags));
- | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
-
-error: invalid ABI for `clobber_abi`
- --> $DIR/bad-options.rs:20:18
- |
-LL | asm!("", clobber_abi("foo"));
- | ^^^^^^^^^^^^^^^^^^
- |
- = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
-
-error: aborting due to 13 previous errors
-
+++ /dev/null
-// only-x86_64
-// compile-flags: -C target-feature=+avx2
-
-#![feature(asm)]
-
-fn main() {
- let mut foo = 0;
- let mut bar = 0;
- unsafe {
- // Bad register/register class
-
- asm!("{}", in(foo) foo);
- //~^ ERROR invalid register class `foo`: unknown register class
- asm!("", in("foo") foo);
- //~^ ERROR invalid register `foo`: unknown register
- asm!("{:z}", in(reg) foo);
- //~^ ERROR invalid asm template modifier for this register class
- asm!("{:r}", in(xmm_reg) foo);
- //~^ ERROR invalid asm template modifier for this register class
- asm!("{:a}", const 0);
- //~^ ERROR asm template modifiers are not allowed for `const` arguments
- asm!("{:a}", sym main);
- //~^ ERROR asm template modifiers are not allowed for `sym` arguments
- asm!("{}", in(zmm_reg) foo);
- //~^ ERROR register class `zmm_reg` requires the `avx512f` target feature
- asm!("", in("zmm0") foo);
- //~^ ERROR register class `zmm_reg` requires the `avx512f` target feature
- asm!("", in("ebp") foo);
- //~^ ERROR invalid register `ebp`: the frame pointer cannot be used as an operand
- asm!("", in("rsp") foo);
- //~^ ERROR invalid register `rsp`: the stack pointer cannot be used as an operand
- asm!("", in("ip") foo);
- //~^ ERROR invalid register `ip`: the instruction pointer cannot be used as an operand
- asm!("", in("k0") foo);
- //~^ ERROR invalid register `k0`: the k0 AVX mask register cannot be used as an operand
- asm!("", in("ah") foo);
- //~^ ERROR invalid register `ah`: high byte registers cannot be used as an operand
-
- asm!("", in("st(2)") foo);
- //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
- asm!("", in("mm0") foo);
- //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
- asm!("", out("st(2)") _);
- asm!("", out("mm0") _);
- asm!("{}", in(x87_reg) foo);
- //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
- asm!("{}", in(mmx_reg) foo);
- //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
- asm!("{}", out(x87_reg) _);
- //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
- asm!("{}", out(mmx_reg) _);
- //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
-
- // Explicit register conflicts
- // (except in/lateout which don't conflict)
-
- asm!("", in("eax") foo, in("al") bar);
- //~^ ERROR register `al` conflicts with register `ax`
- asm!("", in("rax") foo, out("rax") bar);
- //~^ ERROR register `ax` conflicts with register `ax`
- asm!("", in("al") foo, lateout("al") bar);
- asm!("", in("xmm0") foo, in("ymm0") bar);
- //~^ ERROR register `ymm0` conflicts with register `xmm0`
- asm!("", in("xmm0") foo, out("ymm0") bar);
- //~^ ERROR register `ymm0` conflicts with register `xmm0`
- asm!("", in("xmm0") foo, lateout("ymm0") bar);
- }
-}
+++ /dev/null
-error: invalid register class `foo`: unknown register class
- --> $DIR/bad-reg.rs:12:20
- |
-LL | asm!("{}", in(foo) foo);
- | ^^^^^^^^^^^
-
-error: invalid register `foo`: unknown register
- --> $DIR/bad-reg.rs:14:18
- |
-LL | asm!("", in("foo") foo);
- | ^^^^^^^^^^^^^
-
-error: invalid asm template modifier for this register class
- --> $DIR/bad-reg.rs:16:15
- |
-LL | asm!("{:z}", in(reg) foo);
- | ^^^^ ----------- argument
- | |
- | template modifier
- |
- = note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, `r`
-
-error: invalid asm template modifier for this register class
- --> $DIR/bad-reg.rs:18:15
- |
-LL | asm!("{:r}", in(xmm_reg) foo);
- | ^^^^ --------------- argument
- | |
- | template modifier
- |
- = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z`
-
-error: asm template modifiers are not allowed for `const` arguments
- --> $DIR/bad-reg.rs:20:15
- |
-LL | asm!("{:a}", const 0);
- | ^^^^ ------- argument
- | |
- | template modifier
-
-error: asm template modifiers are not allowed for `sym` arguments
- --> $DIR/bad-reg.rs:22:15
- |
-LL | asm!("{:a}", sym main);
- | ^^^^ -------- argument
- | |
- | template modifier
-
-error: register class `zmm_reg` requires the `avx512f` target feature
- --> $DIR/bad-reg.rs:24:20
- |
-LL | asm!("{}", in(zmm_reg) foo);
- | ^^^^^^^^^^^^^^^
-
-error: register class `zmm_reg` requires the `avx512f` target feature
- --> $DIR/bad-reg.rs:26:18
- |
-LL | asm!("", in("zmm0") foo);
- | ^^^^^^^^^^^^^^
-
-error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm
- --> $DIR/bad-reg.rs:28:18
- |
-LL | asm!("", in("ebp") foo);
- | ^^^^^^^^^^^^^
-
-error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm
- --> $DIR/bad-reg.rs:30:18
- |
-LL | asm!("", in("rsp") foo);
- | ^^^^^^^^^^^^^
-
-error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm
- --> $DIR/bad-reg.rs:32:18
- |
-LL | asm!("", in("ip") foo);
- | ^^^^^^^^^^^^
-
-error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm
- --> $DIR/bad-reg.rs:34:18
- |
-LL | asm!("", in("k0") foo);
- | ^^^^^^^^^^^^
-
-error: invalid register `ah`: high byte registers cannot be used as an operand on x86_64
- --> $DIR/bad-reg.rs:36:18
- |
-LL | asm!("", in("ah") foo);
- | ^^^^^^^^^^^^
-
-error: register class `x87_reg` can only be used as a clobber, not as an input or output
- --> $DIR/bad-reg.rs:39:18
- |
-LL | asm!("", in("st(2)") foo);
- | ^^^^^^^^^^^^^^^
-
-error: register class `mmx_reg` can only be used as a clobber, not as an input or output
- --> $DIR/bad-reg.rs:41:18
- |
-LL | asm!("", in("mm0") foo);
- | ^^^^^^^^^^^^^
-
-error: register class `x87_reg` can only be used as a clobber, not as an input or output
- --> $DIR/bad-reg.rs:45:20
- |
-LL | asm!("{}", in(x87_reg) foo);
- | ^^^^^^^^^^^^^^^
-
-error: register class `mmx_reg` can only be used as a clobber, not as an input or output
- --> $DIR/bad-reg.rs:47:20
- |
-LL | asm!("{}", in(mmx_reg) foo);
- | ^^^^^^^^^^^^^^^
-
-error: register class `x87_reg` can only be used as a clobber, not as an input or output
- --> $DIR/bad-reg.rs:49:20
- |
-LL | asm!("{}", out(x87_reg) _);
- | ^^^^^^^^^^^^^^
-
-error: register class `mmx_reg` can only be used as a clobber, not as an input or output
- --> $DIR/bad-reg.rs:51:20
- |
-LL | asm!("{}", out(mmx_reg) _);
- | ^^^^^^^^^^^^^^
-
-error: register `al` conflicts with register `ax`
- --> $DIR/bad-reg.rs:57:33
- |
-LL | asm!("", in("eax") foo, in("al") bar);
- | ------------- ^^^^^^^^^^^^ register `al`
- | |
- | register `ax`
-
-error: register `ax` conflicts with register `ax`
- --> $DIR/bad-reg.rs:59:33
- |
-LL | asm!("", in("rax") foo, out("rax") bar);
- | ------------- ^^^^^^^^^^^^^^ register `ax`
- | |
- | register `ax`
- |
-help: use `lateout` instead of `out` to avoid conflict
- --> $DIR/bad-reg.rs:59:18
- |
-LL | asm!("", in("rax") foo, out("rax") bar);
- | ^^^^^^^^^^^^^
-
-error: register `ymm0` conflicts with register `xmm0`
- --> $DIR/bad-reg.rs:62:34
- |
-LL | asm!("", in("xmm0") foo, in("ymm0") bar);
- | -------------- ^^^^^^^^^^^^^^ register `ymm0`
- | |
- | register `xmm0`
-
-error: register `ymm0` conflicts with register `xmm0`
- --> $DIR/bad-reg.rs:64:34
- |
-LL | asm!("", in("xmm0") foo, out("ymm0") bar);
- | -------------- ^^^^^^^^^^^^^^^ register `ymm0`
- | |
- | register `xmm0`
- |
-help: use `lateout` instead of `out` to avoid conflict
- --> $DIR/bad-reg.rs:64:18
- |
-LL | asm!("", in("xmm0") foo, out("ymm0") bar);
- | ^^^^^^^^^^^^^^
-
-error: aborting due to 23 previous errors
-
--- /dev/null
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:31:15
+ |
+LL | asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:33:15
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:33:21
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:36:15
+ |
+LL | asm!("{a}");
+ | ^^^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:38:15
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^ --------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:41:15
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:41:21
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:48:15
+ |
+LL | asm!("{}", in("x0") foo);
+ | ^^ ------------ explicit register argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: explicit register arguments cannot be used in the asm template
+ --> $DIR/bad-template.rs:48:20
+ |
+LL | asm!("{}", in("x0") foo);
+ | ^^^^^^^^^^^^
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:50:17
+ |
+LL | asm!("{:foo}", in(reg) foo);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:52:18
+ |
+LL | asm!("", in(reg) 0, in(reg) 1);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:58:14
+ |
+LL | global_asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:60:14
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:60:20
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:63:14
+ |
+LL | global_asm!("{a}");
+ | ^^^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:65:14
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^ ------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:65:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:65:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:68:14
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:68:20
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:71:16
+ |
+LL | global_asm!("{:foo}", const FOO);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:73:17
+ |
+LL | global_asm!("", const FOO, const FOO);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: aborting due to 21 previous errors
+
--- /dev/null
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:31:15
+ |
+LL | asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:33:15
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:33:21
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:36:15
+ |
+LL | asm!("{a}");
+ | ^^^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:38:15
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^ --------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:41:15
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:41:21
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:48:15
+ |
+LL | asm!("{}", in("x0") foo);
+ | ^^ ------------ explicit register argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: explicit register arguments cannot be used in the asm template
+ --> $DIR/bad-template.rs:48:20
+ |
+LL | asm!("{}", in("x0") foo);
+ | ^^^^^^^^^^^^
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:50:17
+ |
+LL | asm!("{:foo}", in(reg) foo);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:52:18
+ |
+LL | asm!("", in(reg) 0, in(reg) 1);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:58:14
+ |
+LL | global_asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:60:14
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:60:20
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:63:14
+ |
+LL | global_asm!("{a}");
+ | ^^^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:65:14
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^ ------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:65:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:65:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:68:14
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:68:20
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:71:16
+ |
+LL | global_asm!("{:foo}", const FOO);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:73:17
+ |
+LL | global_asm!("", const FOO, const FOO);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: aborting due to 21 previous errors
+
+++ /dev/null
-error: invalid reference to argument at index 0
- --> $DIR/bad-template.rs:10:15
- |
-LL | asm!("{}");
- | ^^ from here
- |
- = note: no arguments were given
-
-error: invalid reference to argument at index 1
- --> $DIR/bad-template.rs:12:15
- |
-LL | asm!("{1}", in(reg) foo);
- | ^^^ from here
- |
- = note: there is 1 argument
-
-error: argument never used
- --> $DIR/bad-template.rs:12:21
- |
-LL | asm!("{1}", in(reg) foo);
- | ^^^^^^^^^^^ argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
-
-error: there is no argument named `a`
- --> $DIR/bad-template.rs:15:15
- |
-LL | asm!("{a}");
- | ^^^
-
-error: invalid reference to argument at index 0
- --> $DIR/bad-template.rs:17:15
- |
-LL | asm!("{}", a = in(reg) foo);
- | ^^ --------------- named argument
- | |
- | from here
- |
- = note: no positional arguments were given
-note: named arguments cannot be referenced by position
- --> $DIR/bad-template.rs:17:20
- |
-LL | asm!("{}", a = in(reg) foo);
- | ^^^^^^^^^^^^^^^
-
-error: named argument never used
- --> $DIR/bad-template.rs:17:20
- |
-LL | asm!("{}", a = in(reg) foo);
- | ^^^^^^^^^^^^^^^ named argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
-
-error: invalid reference to argument at index 1
- --> $DIR/bad-template.rs:20:15
- |
-LL | asm!("{1}", a = in(reg) foo);
- | ^^^ from here
- |
- = note: no positional arguments were given
-
-error: named argument never used
- --> $DIR/bad-template.rs:20:21
- |
-LL | asm!("{1}", a = in(reg) foo);
- | ^^^^^^^^^^^^^^^ named argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
-
-error: invalid reference to argument at index 0
- --> $DIR/bad-template.rs:23:15
- |
-LL | asm!("{}", in("eax") foo);
- | ^^ ------------- explicit register argument
- | |
- | from here
- |
- = note: no positional arguments were given
-note: explicit register arguments cannot be used in the asm template
- --> $DIR/bad-template.rs:23:20
- |
-LL | asm!("{}", in("eax") foo);
- | ^^^^^^^^^^^^^
-
-error: asm template modifier must be a single character
- --> $DIR/bad-template.rs:25:17
- |
-LL | asm!("{:foo}", in(reg) foo);
- | ^^^
-
-error: multiple unused asm arguments
- --> $DIR/bad-template.rs:27:18
- |
-LL | asm!("", in(reg) 0, in(reg) 1);
- | ^^^^^^^^^ ^^^^^^^^^ argument never used
- | |
- | argument never used
- |
- = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
-
-error: invalid reference to argument at index 0
- --> $DIR/bad-template.rs:33:14
- |
-LL | global_asm!("{}");
- | ^^ from here
- |
- = note: no arguments were given
-
-error: invalid reference to argument at index 1
- --> $DIR/bad-template.rs:35:14
- |
-LL | global_asm!("{1}", const FOO);
- | ^^^ from here
- |
- = note: there is 1 argument
-
-error: argument never used
- --> $DIR/bad-template.rs:35:20
- |
-LL | global_asm!("{1}", const FOO);
- | ^^^^^^^^^ argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
-
-error: there is no argument named `a`
- --> $DIR/bad-template.rs:38:14
- |
-LL | global_asm!("{a}");
- | ^^^
-
-error: invalid reference to argument at index 0
- --> $DIR/bad-template.rs:40:14
- |
-LL | global_asm!("{}", a = const FOO);
- | ^^ ------------- named argument
- | |
- | from here
- |
- = note: no positional arguments were given
-note: named arguments cannot be referenced by position
- --> $DIR/bad-template.rs:40:19
- |
-LL | global_asm!("{}", a = const FOO);
- | ^^^^^^^^^^^^^
-
-error: named argument never used
- --> $DIR/bad-template.rs:40:19
- |
-LL | global_asm!("{}", a = const FOO);
- | ^^^^^^^^^^^^^ named argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
-
-error: invalid reference to argument at index 1
- --> $DIR/bad-template.rs:43:14
- |
-LL | global_asm!("{1}", a = const FOO);
- | ^^^ from here
- |
- = note: no positional arguments were given
-
-error: named argument never used
- --> $DIR/bad-template.rs:43:20
- |
-LL | global_asm!("{1}", a = const FOO);
- | ^^^^^^^^^^^^^ named argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
-
-error: asm template modifier must be a single character
- --> $DIR/bad-template.rs:46:16
- |
-LL | global_asm!("{:foo}", const FOO);
- | ^^^
-
-error: multiple unused asm arguments
- --> $DIR/bad-template.rs:48:17
- |
-LL | global_asm!("", const FOO, const FOO);
- | ^^^^^^^^^ ^^^^^^^^^ argument never used
- | |
- | argument never used
- |
- = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
-
-error: aborting due to 21 previous errors
-
-// only-x86_64
-// revisions: mirunsafeck thirunsafeck
-// [thirunsafeck]compile-flags: -Z thir-unsafeck
+// revisions: x86_64_mirunsafeck aarch64_mirunsafeck x86_64_thirunsafeck aarch64_thirunsafeck
-#![feature(asm, global_asm)]
+// [x86_64_thirunsafeck] compile-flags: -Z thir-unsafeck --target x86_64-unknown-linux-gnu
+// [aarch64_thirunsafeck] compile-flags: -Z thir-unsafeck --target aarch64-unknown-linux-gnu
+// [x86_64_mirunsafeck] compile-flags: --target x86_64-unknown-linux-gnu
+// [aarch64_mirunsafeck] compile-flags: --target aarch64-unknown-linux-gnu
+
+// [x86_64_thirunsafeck] needs-llvm-components: x86
+// [x86_64_mirunsafeck] needs-llvm-components: x86
+// [aarch64_thirunsafeck] needs-llvm-components: aarch64
+// [aarch64_mirunsafeck] needs-llvm-components: aarch64
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! global_asm {
+ () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
fn main() {
let mut foo = 0;
asm!("{1}", a = in(reg) foo);
//~^ ERROR invalid reference to argument at index 1
//~^^ ERROR named argument never used
+ #[cfg(any(x86_64_thirunsafeck, x86_64_mirunsafeck))]
asm!("{}", in("eax") foo);
- //~^ ERROR invalid reference to argument at index 0
+ //[x86_64_thirunsafeck,x86_64_mirunsafeck]~^ ERROR invalid reference to argument at index 0
+ #[cfg(any(aarch64_thirunsafeck, aarch64_mirunsafeck))]
+ asm!("{}", in("x0") foo);
+ //[aarch64_thirunsafeck,aarch64_mirunsafeck]~^ ERROR invalid reference to argument at index 0
asm!("{:foo}", in(reg) foo);
//~^ ERROR asm template modifier must be a single character
asm!("", in(reg) 0, in(reg) 1);
+++ /dev/null
-error: invalid reference to argument at index 0
- --> $DIR/bad-template.rs:10:15
- |
-LL | asm!("{}");
- | ^^ from here
- |
- = note: no arguments were given
-
-error: invalid reference to argument at index 1
- --> $DIR/bad-template.rs:12:15
- |
-LL | asm!("{1}", in(reg) foo);
- | ^^^ from here
- |
- = note: there is 1 argument
-
-error: argument never used
- --> $DIR/bad-template.rs:12:21
- |
-LL | asm!("{1}", in(reg) foo);
- | ^^^^^^^^^^^ argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
-
-error: there is no argument named `a`
- --> $DIR/bad-template.rs:15:15
- |
-LL | asm!("{a}");
- | ^^^
-
-error: invalid reference to argument at index 0
- --> $DIR/bad-template.rs:17:15
- |
-LL | asm!("{}", a = in(reg) foo);
- | ^^ --------------- named argument
- | |
- | from here
- |
- = note: no positional arguments were given
-note: named arguments cannot be referenced by position
- --> $DIR/bad-template.rs:17:20
- |
-LL | asm!("{}", a = in(reg) foo);
- | ^^^^^^^^^^^^^^^
-
-error: named argument never used
- --> $DIR/bad-template.rs:17:20
- |
-LL | asm!("{}", a = in(reg) foo);
- | ^^^^^^^^^^^^^^^ named argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
-
-error: invalid reference to argument at index 1
- --> $DIR/bad-template.rs:20:15
- |
-LL | asm!("{1}", a = in(reg) foo);
- | ^^^ from here
- |
- = note: no positional arguments were given
-
-error: named argument never used
- --> $DIR/bad-template.rs:20:21
- |
-LL | asm!("{1}", a = in(reg) foo);
- | ^^^^^^^^^^^^^^^ named argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
-
-error: invalid reference to argument at index 0
- --> $DIR/bad-template.rs:23:15
- |
-LL | asm!("{}", in("eax") foo);
- | ^^ ------------- explicit register argument
- | |
- | from here
- |
- = note: no positional arguments were given
-note: explicit register arguments cannot be used in the asm template
- --> $DIR/bad-template.rs:23:20
- |
-LL | asm!("{}", in("eax") foo);
- | ^^^^^^^^^^^^^
-
-error: asm template modifier must be a single character
- --> $DIR/bad-template.rs:25:17
- |
-LL | asm!("{:foo}", in(reg) foo);
- | ^^^
-
-error: multiple unused asm arguments
- --> $DIR/bad-template.rs:27:18
- |
-LL | asm!("", in(reg) 0, in(reg) 1);
- | ^^^^^^^^^ ^^^^^^^^^ argument never used
- | |
- | argument never used
- |
- = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
-
-error: invalid reference to argument at index 0
- --> $DIR/bad-template.rs:33:14
- |
-LL | global_asm!("{}");
- | ^^ from here
- |
- = note: no arguments were given
-
-error: invalid reference to argument at index 1
- --> $DIR/bad-template.rs:35:14
- |
-LL | global_asm!("{1}", const FOO);
- | ^^^ from here
- |
- = note: there is 1 argument
-
-error: argument never used
- --> $DIR/bad-template.rs:35:20
- |
-LL | global_asm!("{1}", const FOO);
- | ^^^^^^^^^ argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
-
-error: there is no argument named `a`
- --> $DIR/bad-template.rs:38:14
- |
-LL | global_asm!("{a}");
- | ^^^
-
-error: invalid reference to argument at index 0
- --> $DIR/bad-template.rs:40:14
- |
-LL | global_asm!("{}", a = const FOO);
- | ^^ ------------- named argument
- | |
- | from here
- |
- = note: no positional arguments were given
-note: named arguments cannot be referenced by position
- --> $DIR/bad-template.rs:40:19
- |
-LL | global_asm!("{}", a = const FOO);
- | ^^^^^^^^^^^^^
-
-error: named argument never used
- --> $DIR/bad-template.rs:40:19
- |
-LL | global_asm!("{}", a = const FOO);
- | ^^^^^^^^^^^^^ named argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
-
-error: invalid reference to argument at index 1
- --> $DIR/bad-template.rs:43:14
- |
-LL | global_asm!("{1}", a = const FOO);
- | ^^^ from here
- |
- = note: no positional arguments were given
-
-error: named argument never used
- --> $DIR/bad-template.rs:43:20
- |
-LL | global_asm!("{1}", a = const FOO);
- | ^^^^^^^^^^^^^ named argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
-
-error: asm template modifier must be a single character
- --> $DIR/bad-template.rs:46:16
- |
-LL | global_asm!("{:foo}", const FOO);
- | ^^^
-
-error: multiple unused asm arguments
- --> $DIR/bad-template.rs:48:17
- |
-LL | global_asm!("", const FOO, const FOO);
- | ^^^^^^^^^ ^^^^^^^^^ argument never used
- | |
- | argument never used
- |
- = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
-
-error: aborting due to 21 previous errors
-
--- /dev/null
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:31:15
+ |
+LL | asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:33:15
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:33:21
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:36:15
+ |
+LL | asm!("{a}");
+ | ^^^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:38:15
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^ --------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:41:15
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:41:21
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:45:15
+ |
+LL | asm!("{}", in("eax") foo);
+ | ^^ ------------- explicit register argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: explicit register arguments cannot be used in the asm template
+ --> $DIR/bad-template.rs:45:20
+ |
+LL | asm!("{}", in("eax") foo);
+ | ^^^^^^^^^^^^^
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:50:17
+ |
+LL | asm!("{:foo}", in(reg) foo);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:52:18
+ |
+LL | asm!("", in(reg) 0, in(reg) 1);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:58:14
+ |
+LL | global_asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:60:14
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:60:20
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:63:14
+ |
+LL | global_asm!("{a}");
+ | ^^^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:65:14
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^ ------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:65:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:65:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:68:14
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:68:20
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:71:16
+ |
+LL | global_asm!("{:foo}", const FOO);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:73:17
+ |
+LL | global_asm!("", const FOO, const FOO);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: aborting due to 21 previous errors
+
--- /dev/null
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:31:15
+ |
+LL | asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:33:15
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:33:21
+ |
+LL | asm!("{1}", in(reg) foo);
+ | ^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:36:15
+ |
+LL | asm!("{a}");
+ | ^^^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:38:15
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^ --------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:38:20
+ |
+LL | asm!("{}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:41:15
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:41:21
+ |
+LL | asm!("{1}", a = in(reg) foo);
+ | ^^^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:45:15
+ |
+LL | asm!("{}", in("eax") foo);
+ | ^^ ------------- explicit register argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: explicit register arguments cannot be used in the asm template
+ --> $DIR/bad-template.rs:45:20
+ |
+LL | asm!("{}", in("eax") foo);
+ | ^^^^^^^^^^^^^
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:50:17
+ |
+LL | asm!("{:foo}", in(reg) foo);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:52:18
+ |
+LL | asm!("", in(reg) 0, in(reg) 1);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:58:14
+ |
+LL | global_asm!("{}");
+ | ^^ from here
+ |
+ = note: no arguments were given
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:60:14
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^ from here
+ |
+ = note: there is 1 argument
+
+error: argument never used
+ --> $DIR/bad-template.rs:60:20
+ |
+LL | global_asm!("{1}", const FOO);
+ | ^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
+
+error: there is no argument named `a`
+ --> $DIR/bad-template.rs:63:14
+ |
+LL | global_asm!("{a}");
+ | ^^^
+
+error: invalid reference to argument at index 0
+ --> $DIR/bad-template.rs:65:14
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^ ------------- named argument
+ | |
+ | from here
+ |
+ = note: no positional arguments were given
+note: named arguments cannot be referenced by position
+ --> $DIR/bad-template.rs:65:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/bad-template.rs:65:19
+ |
+LL | global_asm!("{}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: invalid reference to argument at index 1
+ --> $DIR/bad-template.rs:68:14
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^ from here
+ |
+ = note: no positional arguments were given
+
+error: named argument never used
+ --> $DIR/bad-template.rs:68:20
+ |
+LL | global_asm!("{1}", a = const FOO);
+ | ^^^^^^^^^^^^^ named argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
+
+error: asm template modifier must be a single character
+ --> $DIR/bad-template.rs:71:16
+ |
+LL | global_asm!("{:foo}", const FOO);
+ | ^^^
+
+error: multiple unused asm arguments
+ --> $DIR/bad-template.rs:73:17
+ |
+LL | global_asm!("", const FOO, const FOO);
+ | ^^^^^^^^^ ^^^^^^^^^ argument never used
+ | |
+ | argument never used
+ |
+ = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: aborting due to 21 previous errors
+
+++ /dev/null
-// min-llvm-version: 10.0.1
-// only-x86_64
-// run-pass
-// revisions: mirunsafeck thirunsafeck
-// [thirunsafeck]compile-flags: -Z thir-unsafeck
-
-#![feature(asm, global_asm)]
-
-fn const_generic<const X: usize>() -> usize {
- unsafe {
- let a: usize;
- asm!("mov {}, {}", out(reg) a, const X);
- a
- }
-}
-
-const fn constfn(x: usize) -> usize {
- x
-}
-
-fn main() {
- unsafe {
- let a: usize;
- asm!("mov {}, {}", out(reg) a, const 5);
- assert_eq!(a, 5);
-
- let b: usize;
- asm!("mov {}, {}", out(reg) b, const constfn(5));
- assert_eq!(b, 5);
-
- let c: usize;
- asm!("mov {}, {}", out(reg) c, const constfn(5) + constfn(5));
- assert_eq!(c, 10);
- }
-
- let d = const_generic::<5>();
- assert_eq!(d, 5);
-}
-
-global_asm!("mov eax, {}", const 5);
-global_asm!("mov eax, {}", const constfn(5));
-global_asm!("mov eax, {}", const constfn(5) + constfn(5));
+++ /dev/null
-// only-x86_64
-// run-rustfix
-
-#![feature(asm, global_asm)]
-
-fn main() {
- unsafe {
- asm!("", options(nomem, ));
- //~^ ERROR the `nomem` option was already provided
- asm!("", options(att_syntax, ));
- //~^ ERROR the `att_syntax` option was already provided
- asm!("", options(nostack, att_syntax), options());
- //~^ ERROR the `nostack` option was already provided
- asm!("", options(nostack, ), options(), options());
- //~^ ERROR the `nostack` option was already provided
- //~| ERROR the `nostack` option was already provided
- //~| ERROR the `nostack` option was already provided
- asm!(
- "",
- options(nomem, noreturn),
- options(att_syntax, ), //~ ERROR the `noreturn` option was already provided
- options( nostack), //~ ERROR the `nomem` option was already provided
- options(), //~ ERROR the `noreturn` option was already provided
- );
- }
-}
-
-global_asm!("", options(att_syntax, ));
-//~^ ERROR the `att_syntax` option was already provided
+++ /dev/null
-// only-x86_64
-// run-rustfix
-
-#![feature(asm, global_asm)]
-
-fn main() {
- unsafe {
- asm!("", options(nomem, nomem));
- //~^ ERROR the `nomem` option was already provided
- asm!("", options(att_syntax, att_syntax));
- //~^ ERROR the `att_syntax` option was already provided
- asm!("", options(nostack, att_syntax), options(nostack));
- //~^ ERROR the `nostack` option was already provided
- asm!("", options(nostack, nostack), options(nostack), options(nostack));
- //~^ ERROR the `nostack` option was already provided
- //~| ERROR the `nostack` option was already provided
- //~| ERROR the `nostack` option was already provided
- asm!(
- "",
- options(nomem, noreturn),
- options(att_syntax, noreturn), //~ ERROR the `noreturn` option was already provided
- options(nomem, nostack), //~ ERROR the `nomem` option was already provided
- options(noreturn), //~ ERROR the `noreturn` option was already provided
- );
- }
-}
-
-global_asm!("", options(att_syntax, att_syntax));
-//~^ ERROR the `att_syntax` option was already provided
+++ /dev/null
-error: the `nomem` option was already provided
- --> $DIR/duplicate-options.rs:8:33
- |
-LL | asm!("", options(nomem, nomem));
- | ^^^^^ this option was already provided
-
-error: the `att_syntax` option was already provided
- --> $DIR/duplicate-options.rs:10:38
- |
-LL | asm!("", options(att_syntax, att_syntax));
- | ^^^^^^^^^^ this option was already provided
-
-error: the `nostack` option was already provided
- --> $DIR/duplicate-options.rs:12:56
- |
-LL | asm!("", options(nostack, att_syntax), options(nostack));
- | ^^^^^^^ this option was already provided
-
-error: the `nostack` option was already provided
- --> $DIR/duplicate-options.rs:14:35
- |
-LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
- | ^^^^^^^ this option was already provided
-
-error: the `nostack` option was already provided
- --> $DIR/duplicate-options.rs:14:53
- |
-LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
- | ^^^^^^^ this option was already provided
-
-error: the `nostack` option was already provided
- --> $DIR/duplicate-options.rs:14:71
- |
-LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
- | ^^^^^^^ this option was already provided
-
-error: the `noreturn` option was already provided
- --> $DIR/duplicate-options.rs:21:33
- |
-LL | options(att_syntax, noreturn),
- | ^^^^^^^^ this option was already provided
-
-error: the `nomem` option was already provided
- --> $DIR/duplicate-options.rs:22:21
- |
-LL | options(nomem, nostack),
- | ^^^^^ this option was already provided
-
-error: the `noreturn` option was already provided
- --> $DIR/duplicate-options.rs:23:21
- |
-LL | options(noreturn),
- | ^^^^^^^^ this option was already provided
-
-error: the `att_syntax` option was already provided
- --> $DIR/duplicate-options.rs:28:37
- |
-LL | global_asm!("", options(att_syntax, att_syntax));
- | ^^^^^^^^^^ this option was already provided
-
-error: aborting due to 10 previous errors
-
+++ /dev/null
-// only-x86_64
-
-#![feature(asm)]
-
-macro_rules! m {
- ($in:ident $out:ident $lateout:ident $inout:ident $inlateout:ident $const:ident $sym:ident
- $pure:ident $nomem:ident $readonly:ident $preserves_flags:ident
- $noreturn:ident $nostack:ident $att_syntax:ident $options:ident) => {
- unsafe {
- asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x,
- //~^ ERROR asm outputs are not allowed with the `noreturn` option
- const x, sym x,
- $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax));
- //~^ ERROR the `nomem` and `readonly` options are mutually exclusive
- //~| ERROR the `pure` and `noreturn` options are mutually exclusive
- }
- };
-}
-
-fn main() {
- m!(in out lateout inout inlateout const sym
- pure nomem readonly preserves_flags
- noreturn nostack att_syntax options);
-}
+++ /dev/null
-error: the `nomem` and `readonly` options are mutually exclusive
- --> $DIR/interpolated-idents.rs:13:13
- |
-LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL | / m!(in out lateout inout inlateout const sym
-LL | | pure nomem readonly preserves_flags
-LL | | noreturn nostack att_syntax options);
- | |____________________________________________- in this macro invocation
- |
- = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: the `pure` and `noreturn` options are mutually exclusive
- --> $DIR/interpolated-idents.rs:13:13
- |
-LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-...
-LL | / m!(in out lateout inout inlateout const sym
-LL | | pure nomem readonly preserves_flags
-LL | | noreturn nostack att_syntax options);
- | |____________________________________________- in this macro invocation
- |
- = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: asm outputs are not allowed with the `noreturn` option
- --> $DIR/interpolated-idents.rs:10:32
- |
-LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x,
- | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^
-...
-LL | m!(in out lateout inout inlateout const sym
- | _____-
- | |_____|
- | |_____|
- | |_____|
- | |
-LL | | pure nomem readonly preserves_flags
-LL | | noreturn nostack att_syntax options);
- | | -
- | |____________________________________________|
- | |____________________________________________in this macro invocation
- | |____________________________________________in this macro invocation
- | |____________________________________________in this macro invocation
- | in this macro invocation
- |
- = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 3 previous errors
-
// compile-flags: -Zsave-analysis
-// only-x86_64
+// needs-asm-support
// Also test for #72960
#![feature(asm)]
+++ /dev/null
-// only-x86_64
-// Make sure rustc doesn't ICE on asm! for a foreign architecture.
-
-#![feature(asm)]
-#![crate_type = "rlib"]
-
-pub unsafe fn aarch64(a: f64, b: f64) -> f64 {
- let c;
- asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
- || {};
- b
- });
- //~^^^^ invalid register class
- //~^^^^^ invalid register class
- //~^^^^^^ invalid register
- c
-}
-
-pub unsafe fn x86(a: f64, b: f64) -> f64 {
- let c;
- asm!("addsd {}, {}, xmm0", out(xmm_reg) c, in(xmm_reg) a, in("xmm0") b);
- c
-}
+++ /dev/null
-error: invalid register class `vreg`: unknown register class
- --> $DIR/issue-82869.rs:9:32
- |
-LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
- | ^^^^^^^^^^^
-
-error: invalid register class `vreg`: unknown register class
- --> $DIR/issue-82869.rs:9:45
- |
-LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
- | ^^^^^^^^^^
-
-error: invalid register `d0`: unknown register
- --> $DIR/issue-82869.rs:9:57
- |
-LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
- | _________________________________________________________^
-LL | | || {};
-LL | | b
-LL | | });
- | |_____^
-
-error: aborting due to 3 previous errors
-
-// only-x86_64
+// needs-asm-support
+// ignore-nvptx64
+// ignore-spirv
+// ignore-wasm32
// Make sure rustc doesn't ICE on asm! when output type is !.
#![feature(asm)]
error: cannot use value of type `!` for inline assembly
- --> $DIR/issue-87802.rs:9:36
+ --> $DIR/issue-87802.rs:12:36
|
LL | asm!("/* {0} */", out(reg) x);
| ^
// check-pass
-// only-x86_64
+// needs-asm-support
#![feature(asm)]
#![feature(naked_functions)]
#![crate_type = "lib"]
--- /dev/null
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:15:32
+ |
+LL | pub extern "C" fn function(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+ |
+note: the lint level is defined here
+ --> $DIR/naked-functions-unused.rs:4:9
+ |
+LL | #![deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:15:42
+ |
+LL | pub extern "C" fn function(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:24:38
+ |
+LL | pub extern "C" fn associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:24:48
+ |
+LL | pub extern "C" fn associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:30:41
+ |
+LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:30:51
+ |
+LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:38:40
+ |
+LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:38:50
+ |
+LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:44:43
+ |
+LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:44:53
+ |
+LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: aborting due to 10 previous errors
+
-// only-x86_64
+// revisions: x86_64 aarch64
+//[x86_64] only-x86_64
+//[aarch64] only-aarch64
#![deny(unused)]
#![feature(asm)]
#![feature(naked_functions)]
#![crate_type = "lib"]
pub trait Trait {
- extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize;
- extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize;
+ extern "C" fn trait_associated(a: usize, b: usize) -> usize;
+ extern "C" fn trait_method(&self, a: usize, b: usize) -> usize;
}
pub mod normal {
- pub extern "sysv64" fn function(a: usize, b: usize) -> usize {
+ pub extern "C" fn function(a: usize, b: usize) -> usize {
//~^ ERROR unused variable: `a`
//~| ERROR unused variable: `b`
unsafe { asm!("", options(noreturn)); }
pub struct Normal;
impl Normal {
- pub extern "sysv64" fn associated(a: usize, b: usize) -> usize {
+ pub extern "C" fn associated(a: usize, b: usize) -> usize {
//~^ ERROR unused variable: `a`
//~| ERROR unused variable: `b`
unsafe { asm!("", options(noreturn)); }
}
- pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize {
+ pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
//~^ ERROR unused variable: `a`
//~| ERROR unused variable: `b`
unsafe { asm!("", options(noreturn)); }
}
impl super::Trait for Normal {
- extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize {
+ extern "C" fn trait_associated(a: usize, b: usize) -> usize {
//~^ ERROR unused variable: `a`
//~| ERROR unused variable: `b`
unsafe { asm!("", options(noreturn)); }
}
- extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize {
+ extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
//~^ ERROR unused variable: `a`
//~| ERROR unused variable: `b`
unsafe { asm!("", options(noreturn)); }
pub mod naked {
#[naked]
- pub extern "sysv64" fn function(a: usize, b: usize) -> usize {
+ pub extern "C" fn function(a: usize, b: usize) -> usize {
unsafe { asm!("", options(noreturn)); }
}
impl Naked {
#[naked]
- pub extern "sysv64" fn associated(a: usize, b: usize) -> usize {
+ pub extern "C" fn associated(a: usize, b: usize) -> usize {
unsafe { asm!("", options(noreturn)); }
}
#[naked]
- pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize {
+ pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
unsafe { asm!("", options(noreturn)); }
}
}
impl super::Trait for Naked {
#[naked]
- extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize {
+ extern "C" fn trait_associated(a: usize, b: usize) -> usize {
unsafe { asm!("", options(noreturn)); }
}
#[naked]
- extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize {
+ extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
unsafe { asm!("", options(noreturn)); }
}
}
+++ /dev/null
-error: unused variable: `a`
- --> $DIR/naked-functions-unused.rs:13:37
- |
-LL | pub extern "sysv64" fn function(a: usize, b: usize) -> usize {
- | ^ help: if this is intentional, prefix it with an underscore: `_a`
- |
-note: the lint level is defined here
- --> $DIR/naked-functions-unused.rs:2:9
- |
-LL | #![deny(unused)]
- | ^^^^^^
- = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]`
-
-error: unused variable: `b`
- --> $DIR/naked-functions-unused.rs:13:47
- |
-LL | pub extern "sysv64" fn function(a: usize, b: usize) -> usize {
- | ^ help: if this is intentional, prefix it with an underscore: `_b`
-
-error: unused variable: `a`
- --> $DIR/naked-functions-unused.rs:22:43
- |
-LL | pub extern "sysv64" fn associated(a: usize, b: usize) -> usize {
- | ^ help: if this is intentional, prefix it with an underscore: `_a`
-
-error: unused variable: `b`
- --> $DIR/naked-functions-unused.rs:22:53
- |
-LL | pub extern "sysv64" fn associated(a: usize, b: usize) -> usize {
- | ^ help: if this is intentional, prefix it with an underscore: `_b`
-
-error: unused variable: `a`
- --> $DIR/naked-functions-unused.rs:28:46
- |
-LL | pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize {
- | ^ help: if this is intentional, prefix it with an underscore: `_a`
-
-error: unused variable: `b`
- --> $DIR/naked-functions-unused.rs:28:56
- |
-LL | pub extern "sysv64" fn method(&self, a: usize, b: usize) -> usize {
- | ^ help: if this is intentional, prefix it with an underscore: `_b`
-
-error: unused variable: `a`
- --> $DIR/naked-functions-unused.rs:36:45
- |
-LL | extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize {
- | ^ help: if this is intentional, prefix it with an underscore: `_a`
-
-error: unused variable: `b`
- --> $DIR/naked-functions-unused.rs:36:55
- |
-LL | extern "sysv64" fn trait_associated(a: usize, b: usize) -> usize {
- | ^ help: if this is intentional, prefix it with an underscore: `_b`
-
-error: unused variable: `a`
- --> $DIR/naked-functions-unused.rs:42:48
- |
-LL | extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize {
- | ^ help: if this is intentional, prefix it with an underscore: `_a`
-
-error: unused variable: `b`
- --> $DIR/naked-functions-unused.rs:42:58
- |
-LL | extern "sysv64" fn trait_method(&self, a: usize, b: usize) -> usize {
- | ^ help: if this is intentional, prefix it with an underscore: `_b`
-
-error: aborting due to 10 previous errors
-
--- /dev/null
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:15:32
+ |
+LL | pub extern "C" fn function(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+ |
+note: the lint level is defined here
+ --> $DIR/naked-functions-unused.rs:4:9
+ |
+LL | #![deny(unused)]
+ | ^^^^^^
+ = note: `#[deny(unused_variables)]` implied by `#[deny(unused)]`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:15:42
+ |
+LL | pub extern "C" fn function(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:24:38
+ |
+LL | pub extern "C" fn associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:24:48
+ |
+LL | pub extern "C" fn associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:30:41
+ |
+LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:30:51
+ |
+LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:38:40
+ |
+LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:38:50
+ |
+LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: unused variable: `a`
+ --> $DIR/naked-functions-unused.rs:44:43
+ |
+LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_a`
+
+error: unused variable: `b`
+ --> $DIR/naked-functions-unused.rs:44:53
+ |
+LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
+ | ^ help: if this is intentional, prefix it with an underscore: `_b`
+
+error: aborting due to 10 previous errors
+
-// only-x86_64
+// needs-asm-support
+// ignore-nvptx64
+// ignore-spirv
+// ignore-wasm32
+
#![feature(asm)]
#![feature(llvm_asm)]
#![feature(naked_functions)]
error: asm with the `pure` option must have at least one output
- --> $DIR/naked-functions.rs:127:14
+ --> $DIR/naked-functions.rs:131:14
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
error: patterns not allowed in naked function parameters
- --> $DIR/naked-functions.rs:14:5
+ --> $DIR/naked-functions.rs:18:5
|
LL | mut a: u32,
| ^^^^^
error: patterns not allowed in naked function parameters
- --> $DIR/naked-functions.rs:16:5
+ --> $DIR/naked-functions.rs:20:5
|
LL | &b: &i32,
| ^^
error: patterns not allowed in naked function parameters
- --> $DIR/naked-functions.rs:18:6
+ --> $DIR/naked-functions.rs:22:6
|
LL | (None | Some(_)): Option<std::ptr::NonNull<u8>>,
| ^^^^^^^^^^^^^^
error: patterns not allowed in naked function parameters
- --> $DIR/naked-functions.rs:20:5
+ --> $DIR/naked-functions.rs:24:5
|
LL | P { x, y }: P,
| ^^^^^^^^^^
error: referencing function parameters is not allowed in naked functions
- --> $DIR/naked-functions.rs:30:5
+ --> $DIR/naked-functions.rs:34:5
|
LL | a + 1
| ^
= help: follow the calling convention in asm block to use parameters
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:27:1
+ --> $DIR/naked-functions.rs:31:1
|
LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
error: referencing function parameters is not allowed in naked functions
- --> $DIR/naked-functions.rs:36:31
+ --> $DIR/naked-functions.rs:40:31
|
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
| ^
= help: follow the calling convention in asm block to use parameters
warning: only `const` and `sym` operands are supported in naked functions
- --> $DIR/naked-functions.rs:36:23
+ --> $DIR/naked-functions.rs:40:23
|
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
| ^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:43:1
+ --> $DIR/naked-functions.rs:47:1
|
LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: only `const` and `sym` operands are supported in naked functions
- --> $DIR/naked-functions.rs:63:10
+ --> $DIR/naked-functions.rs:67:10
|
LL | in(reg) a,
| ^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
- --> $DIR/naked-functions.rs:60:5
+ --> $DIR/naked-functions.rs:64:5
|
LL | / asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:50:1
+ --> $DIR/naked-functions.rs:54:1
|
LL | / pub unsafe extern "C" fn unsupported_operands() {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:76:1
+ --> $DIR/naked-functions.rs:80:1
|
LL | / pub extern "C" fn missing_assembly() {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
- --> $DIR/naked-functions.rs:85:5
+ --> $DIR/naked-functions.rs:89:5
|
LL | asm!("");
| ^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
- --> $DIR/naked-functions.rs:88:5
+ --> $DIR/naked-functions.rs:92:5
|
LL | asm!("");
| ^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
- --> $DIR/naked-functions.rs:91:5
+ --> $DIR/naked-functions.rs:95:5
|
LL | asm!("");
| ^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:82:1
+ --> $DIR/naked-functions.rs:86:1
|
LL | / pub extern "C" fn too_many_asm_blocks() {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
error: referencing function parameters is not allowed in naked functions
- --> $DIR/naked-functions.rs:102:11
+ --> $DIR/naked-functions.rs:106:11
|
LL | *&y
| ^
= help: follow the calling convention in asm block to use parameters
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:99:5
+ --> $DIR/naked-functions.rs:103:5
|
LL | / pub extern "C" fn inner(y: usize) -> usize {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: the LLVM-style inline assembly is unsupported in naked functions
- --> $DIR/naked-functions.rs:112:5
+ --> $DIR/naked-functions.rs:116:5
|
LL | llvm_asm!("");
| ^^^^^^^^^^^^^^
= note: this warning originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:109:1
+ --> $DIR/naked-functions.rs:113:1
|
LL | / unsafe extern "C" fn llvm() -> ! {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm options unsupported in naked functions: `nomem`, `preserves_flags`
- --> $DIR/naked-functions.rs:120:5
+ --> $DIR/naked-functions.rs:124:5
|
LL | asm!("", options(nomem, preserves_flags, noreturn));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
- --> $DIR/naked-functions.rs:127:5
+ --> $DIR/naked-functions.rs:131:5
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
- --> $DIR/naked-functions.rs:127:5
+ --> $DIR/naked-functions.rs:131:5
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: Rust ABI is unsupported in naked functions
- --> $DIR/naked-functions.rs:136:15
+ --> $DIR/naked-functions.rs:140:15
|
LL | pub unsafe fn default_abi() {
| ^^^^^^^^^^^
= note: `#[warn(undefined_naked_function_abi)]` on by default
warning: Rust ABI is unsupported in naked functions
- --> $DIR/naked-functions.rs:142:29
+ --> $DIR/naked-functions.rs:146:29
|
LL | pub unsafe extern "Rust" fn rust_abi() {
| ^^^^^^^^
warning: naked functions cannot be inlined
- --> $DIR/naked-functions.rs:176:1
+ --> $DIR/naked-functions.rs:180:1
|
LL | #[inline]
| ^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
- --> $DIR/naked-functions.rs:184:1
+ --> $DIR/naked-functions.rs:188:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
- --> $DIR/naked-functions.rs:192:1
+ --> $DIR/naked-functions.rs:196:1
|
LL | #[inline(never)]
| ^^^^^^^^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
- --> $DIR/naked-functions.rs:200:1
+ --> $DIR/naked-functions.rs:204:1
|
LL | #[inline]
| ^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
- --> $DIR/naked-functions.rs:203:1
+ --> $DIR/naked-functions.rs:207:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
- --> $DIR/naked-functions.rs:206:1
+ --> $DIR/naked-functions.rs:210:1
|
LL | #[inline(never)]
| ^^^^^^^^^^^^^^^^
-// only-x86_64
+// needs-asm-support
+// ignore-nvptx64
+// ignore-spirv
+// ignore-wasm32
// Tests that the use of named labels in the `asm!` macro are linted against
// except for in `#[naked]` fns.
asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70"); //~ ERROR avoid using named labels
// Non-label colons - should pass
- // (most of these are stolen from other places)
- asm!("{:l}", in(reg) 0i64);
- asm!("{:e}", in(reg) 0f32);
asm!("mov rax, qword ptr fs:[0]");
// Comments
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:19:15
+ --> $DIR/named-asm-labels.rs:22:15
|
LL | asm!("bar: nop");
| ^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:22:15
+ --> $DIR/named-asm-labels.rs:25:15
|
LL | asm!("abcd:");
| ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:25:15
+ --> $DIR/named-asm-labels.rs:28:15
|
LL | asm!("foo: bar1: nop");
| ^^^ ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:29:15
+ --> $DIR/named-asm-labels.rs:32:15
|
LL | asm!("foo1: nop", "nop");
| ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:30:15
+ --> $DIR/named-asm-labels.rs:33:15
|
LL | asm!("foo2: foo3: nop", "nop");
| ^^^^ ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:32:22
+ --> $DIR/named-asm-labels.rs:35:22
|
LL | asm!("nop", "foo4: nop");
| ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:33:15
+ --> $DIR/named-asm-labels.rs:36:15
|
LL | asm!("foo5: nop", "foo6: nop");
| ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:33:28
+ --> $DIR/named-asm-labels.rs:36:28
|
LL | asm!("foo5: nop", "foo6: nop");
| ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:38:15
+ --> $DIR/named-asm-labels.rs:41:15
|
LL | asm!("foo7: nop; foo8: nop");
| ^^^^ ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:40:15
+ --> $DIR/named-asm-labels.rs:43:15
|
LL | asm!("foo9: nop; nop");
| ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:41:20
+ --> $DIR/named-asm-labels.rs:44:20
|
LL | asm!("nop; foo10: nop");
| ^^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:44:15
+ --> $DIR/named-asm-labels.rs:47:15
|
LL | asm!("bar2: nop\n bar3: nop");
| ^^^^ ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:46:15
+ --> $DIR/named-asm-labels.rs:49:15
|
LL | asm!("bar4: nop\n nop");
| ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:47:21
+ --> $DIR/named-asm-labels.rs:50:21
|
LL | asm!("nop\n bar5: nop");
| ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:48:21
+ --> $DIR/named-asm-labels.rs:51:21
|
LL | asm!("nop\n bar6: bar7: nop");
| ^^^^ ^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:54:13
+ --> $DIR/named-asm-labels.rs:57:13
|
LL | blah2: nop
| ^^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:63:19
+ --> $DIR/named-asm-labels.rs:66:19
|
LL | nop ; blah4: nop
| ^^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:77:15
+ --> $DIR/named-asm-labels.rs:80:15
|
LL | asm!("blah1: 2bar: nop");
| ^^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:80:15
+ --> $DIR/named-asm-labels.rs:83:15
|
LL | asm!("def: def: nop");
| ^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:81:15
+ --> $DIR/named-asm-labels.rs:84:15
|
LL | asm!("def: nop\ndef: nop");
| ^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:82:15
+ --> $DIR/named-asm-labels.rs:85:15
|
LL | asm!("def: nop; def: nop");
| ^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:90:15
+ --> $DIR/named-asm-labels.rs:93:15
|
LL | asm!("fooo\u{003A} nop");
| ^^^^^^^^^^^^^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:91:15
+ --> $DIR/named-asm-labels.rs:94:15
|
LL | asm!("foooo\x3A nop");
| ^^^^^^^^^^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:94:15
+ --> $DIR/named-asm-labels.rs:97:15
|
LL | asm!("fooooo:\u{000A} nop");
| ^^^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:95:15
+ --> $DIR/named-asm-labels.rs:98:15
|
LL | asm!("foooooo:\x0A nop");
| ^^^^^^^
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
- --> $DIR/named-asm-labels.rs:99:14
+ --> $DIR/named-asm-labels.rs:102:14
|
LL | asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-// only-x86_64
+// needs-asm-support
// check-pass
#![feature(asm, never_type)]
+++ /dev/null
-// only-x86_64
-
-#![feature(asm, global_asm)]
-
-fn main() {
- let mut foo = 0;
- let mut bar = 0;
- unsafe {
- asm!();
- //~^ ERROR requires at least a template string argument
- asm!(foo);
- //~^ ERROR asm template must be a string literal
- asm!("{}" foo);
- //~^ ERROR expected token: `,`
- asm!("{}", foo);
- //~^ ERROR expected operand, clobber_abi, options, or additional template string
- asm!("{}", in foo);
- //~^ ERROR expected `(`, found `foo`
- asm!("{}", in(reg foo));
- //~^ ERROR expected `)`, found `foo`
- asm!("{}", in(reg));
- //~^ ERROR expected expression, found end of macro arguments
- asm!("{}", inout(=) foo => bar);
- //~^ ERROR expected register class or explicit register
- asm!("{}", inout(reg) foo =>);
- //~^ ERROR expected expression, found end of macro arguments
- asm!("{}", in(reg) foo => bar);
- //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
- asm!("{}", sym foo + bar);
- //~^ ERROR argument to `sym` must be a path expression
- asm!("", options(foo));
- //~^ ERROR expected one of
- asm!("", options(nomem foo));
- //~^ ERROR expected one of
- asm!("", options(nomem, foo));
- //~^ ERROR expected one of
- asm!("{}", options(), const foo);
- //~^ ERROR arguments are not allowed after options
- //~^^ ERROR attempt to use a non-constant value in a constant
- asm!("", clobber_abi(foo));
- //~^ ERROR expected string literal
- asm!("", clobber_abi("C" foo));
- //~^ ERROR expected `)`, found `foo`
- asm!("", clobber_abi("C", foo));
- //~^ ERROR expected `)`, found `,`
- asm!("{}", clobber_abi("C"), const foo);
- //~^ ERROR arguments are not allowed after clobber_abi
- //~^^ ERROR attempt to use a non-constant value in a constant
- asm!("", options(), clobber_abi("C"));
- //~^ ERROR clobber_abi is not allowed after options
- asm!("{}", options(), clobber_abi("C"), const foo);
- //~^ ERROR clobber_abi is not allowed after options
- asm!("", clobber_abi("C"), clobber_abi("C"));
- //~^ ERROR clobber_abi specified multiple times
- asm!("{a}", a = const foo, a = const bar);
- //~^ ERROR duplicate argument named `a`
- //~^^ ERROR argument never used
- //~^^^ ERROR attempt to use a non-constant value in a constant
- //~^^^^ ERROR attempt to use a non-constant value in a constant
- asm!("", a = in("eax") foo);
- //~^ ERROR explicit register arguments cannot have names
- asm!("{a}", in("eax") foo, a = const bar);
- //~^ ERROR named arguments cannot follow explicit register arguments
- //~^^ ERROR attempt to use a non-constant value in a constant
- asm!("{a}", in("eax") foo, a = const bar);
- //~^ ERROR named arguments cannot follow explicit register arguments
- //~^^ ERROR attempt to use a non-constant value in a constant
- asm!("{1}", in("eax") foo, const bar);
- //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments
- //~^^ ERROR attempt to use a non-constant value in a constant
- asm!("", options(), "");
- //~^ ERROR expected one of
- asm!("{}", in(reg) foo, "{}", out(reg) foo);
- //~^ ERROR expected one of
- asm!(format!("{{{}}}", 0), in(reg) foo);
- //~^ ERROR asm template must be a string literal
- asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
- //~^ ERROR asm template must be a string literal
- asm!("{}", in(reg) _);
- //~^ ERROR _ cannot be used for input operands
- asm!("{}", inout(reg) _);
- //~^ ERROR _ cannot be used for input operands
- asm!("{}", inlateout(reg) _);
- //~^ ERROR _ cannot be used for input operands
- }
-}
-
-const FOO: i32 = 1;
-const BAR: i32 = 2;
-global_asm!();
-//~^ ERROR requires at least a template string argument
-global_asm!(FOO);
-//~^ ERROR asm template must be a string literal
-global_asm!("{}" FOO);
-//~^ ERROR expected token: `,`
-global_asm!("{}", FOO);
-//~^ ERROR expected operand, options, or additional template string
-global_asm!("{}", const);
-//~^ ERROR expected expression, found end of macro arguments
-global_asm!("{}", const(reg) FOO);
-//~^ ERROR expected one of
-global_asm!("", options(FOO));
-//~^ ERROR expected one of
-global_asm!("", options(nomem FOO));
-//~^ ERROR expected one of
-global_asm!("", options(nomem, FOO));
-//~^ ERROR expected one of
-global_asm!("{}", options(), const FOO);
-//~^ ERROR arguments are not allowed after options
-global_asm!("", clobber_abi(FOO));
-//~^ ERROR expected string literal
-global_asm!("", clobber_abi("C" FOO));
-//~^ ERROR expected `)`, found `FOO`
-global_asm!("", clobber_abi("C", FOO));
-//~^ ERROR expected `)`, found `,`
-global_asm!("{}", clobber_abi("C"), const FOO);
-//~^ ERROR arguments are not allowed after clobber_abi
-//~^^ ERROR `clobber_abi` cannot be used with `global_asm!`
-global_asm!("", options(), clobber_abi("C"));
-//~^ ERROR clobber_abi is not allowed after options
-global_asm!("{}", options(), clobber_abi("C"), const FOO);
-//~^ ERROR clobber_abi is not allowed after options
-global_asm!("", clobber_abi("C"), clobber_abi("C"));
-//~^ ERROR clobber_abi specified multiple times
-global_asm!("{a}", a = const FOO, a = const BAR);
-//~^ ERROR duplicate argument named `a`
-//~^^ ERROR argument never used
-global_asm!("", options(), "");
-//~^ ERROR expected one of
-global_asm!("{}", const FOO, "{}", const FOO);
-//~^ ERROR expected one of
-global_asm!(format!("{{{}}}", 0), const FOO);
-//~^ ERROR asm template must be a string literal
-global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
-//~^ ERROR asm template must be a string literal
+++ /dev/null
-error: requires at least a template string argument
- --> $DIR/parse-error.rs:9:9
- |
-LL | asm!();
- | ^^^^^^^
-
-error: asm template must be a string literal
- --> $DIR/parse-error.rs:11:14
- |
-LL | asm!(foo);
- | ^^^
-
-error: expected token: `,`
- --> $DIR/parse-error.rs:13:19
- |
-LL | asm!("{}" foo);
- | ^^^ expected `,`
-
-error: expected operand, clobber_abi, options, or additional template string
- --> $DIR/parse-error.rs:15:20
- |
-LL | asm!("{}", foo);
- | ^^^ expected operand, clobber_abi, options, or additional template string
-
-error: expected `(`, found `foo`
- --> $DIR/parse-error.rs:17:23
- |
-LL | asm!("{}", in foo);
- | ^^^ expected `(`
-
-error: expected `)`, found `foo`
- --> $DIR/parse-error.rs:19:27
- |
-LL | asm!("{}", in(reg foo));
- | ^^^ expected `)`
-
-error: expected expression, found end of macro arguments
- --> $DIR/parse-error.rs:21:27
- |
-LL | asm!("{}", in(reg));
- | ^ expected expression
-
-error: expected register class or explicit register
- --> $DIR/parse-error.rs:23:26
- |
-LL | asm!("{}", inout(=) foo => bar);
- | ^
-
-error: expected expression, found end of macro arguments
- --> $DIR/parse-error.rs:25:37
- |
-LL | asm!("{}", inout(reg) foo =>);
- | ^ expected expression
-
-error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
- --> $DIR/parse-error.rs:27:32
- |
-LL | asm!("{}", in(reg) foo => bar);
- | ^^ expected one of 7 possible tokens
-
-error: argument to `sym` must be a path expression
- --> $DIR/parse-error.rs:29:24
- |
-LL | asm!("{}", sym foo + bar);
- | ^^^^^^^^^
-
-error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
- --> $DIR/parse-error.rs:31:26
- |
-LL | asm!("", options(foo));
- | ^^^ expected one of 9 possible tokens
-
-error: expected one of `)` or `,`, found `foo`
- --> $DIR/parse-error.rs:33:32
- |
-LL | asm!("", options(nomem foo));
- | ^^^ expected one of `)` or `,`
-
-error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
- --> $DIR/parse-error.rs:35:33
- |
-LL | asm!("", options(nomem, foo));
- | ^^^ expected one of 9 possible tokens
-
-error: arguments are not allowed after options
- --> $DIR/parse-error.rs:37:31
- |
-LL | asm!("{}", options(), const foo);
- | --------- ^^^^^^^^^ argument
- | |
- | previous options
-
-error: expected string literal
- --> $DIR/parse-error.rs:40:30
- |
-LL | asm!("", clobber_abi(foo));
- | ^^^ not a string literal
-
-error: expected `)`, found `foo`
- --> $DIR/parse-error.rs:42:34
- |
-LL | asm!("", clobber_abi("C" foo));
- | ^^^ expected `)`
-
-error: expected `)`, found `,`
- --> $DIR/parse-error.rs:44:33
- |
-LL | asm!("", clobber_abi("C", foo));
- | ^ expected `)`
-
-error: arguments are not allowed after clobber_abi
- --> $DIR/parse-error.rs:46:38
- |
-LL | asm!("{}", clobber_abi("C"), const foo);
- | ---------------- ^^^^^^^^^ argument
- | |
- | clobber_abi
-
-error: clobber_abi is not allowed after options
- --> $DIR/parse-error.rs:49:29
- |
-LL | asm!("", options(), clobber_abi("C"));
- | --------- ^^^^^^^^^^^^^^^^
- | |
- | options
-
-error: clobber_abi is not allowed after options
- --> $DIR/parse-error.rs:51:31
- |
-LL | asm!("{}", options(), clobber_abi("C"), const foo);
- | --------- ^^^^^^^^^^^^^^^^
- | |
- | options
-
-error: clobber_abi specified multiple times
- --> $DIR/parse-error.rs:53:36
- |
-LL | asm!("", clobber_abi("C"), clobber_abi("C"));
- | ---------------- ^^^^^^^^^^^^^^^^
- | |
- | clobber_abi previously specified here
-
-error: duplicate argument named `a`
- --> $DIR/parse-error.rs:55:36
- |
-LL | asm!("{a}", a = const foo, a = const bar);
- | ------------- ^^^^^^^^^^^^^ duplicate argument
- | |
- | previously here
-
-error: argument never used
- --> $DIR/parse-error.rs:55:36
- |
-LL | asm!("{a}", a = const foo, a = const bar);
- | ^^^^^^^^^^^^^ argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
-
-error: explicit register arguments cannot have names
- --> $DIR/parse-error.rs:60:18
- |
-LL | asm!("", a = in("eax") foo);
- | ^^^^^^^^^^^^^^^^^
-
-error: named arguments cannot follow explicit register arguments
- --> $DIR/parse-error.rs:62:36
- |
-LL | asm!("{a}", in("eax") foo, a = const bar);
- | ------------- ^^^^^^^^^^^^^ named argument
- | |
- | explicit register argument
-
-error: named arguments cannot follow explicit register arguments
- --> $DIR/parse-error.rs:65:36
- |
-LL | asm!("{a}", in("eax") foo, a = const bar);
- | ------------- ^^^^^^^^^^^^^ named argument
- | |
- | explicit register argument
-
-error: positional arguments cannot follow named arguments or explicit register arguments
- --> $DIR/parse-error.rs:68:36
- |
-LL | asm!("{1}", in("eax") foo, const bar);
- | ------------- ^^^^^^^^^ positional argument
- | |
- | explicit register argument
-
-error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""`
- --> $DIR/parse-error.rs:71:29
- |
-LL | asm!("", options(), "");
- | ^^ expected one of 9 possible tokens
-
-error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
- --> $DIR/parse-error.rs:73:33
- |
-LL | asm!("{}", in(reg) foo, "{}", out(reg) foo);
- | ^^^^ expected one of 9 possible tokens
-
-error: asm template must be a string literal
- --> $DIR/parse-error.rs:75:14
- |
-LL | asm!(format!("{{{}}}", 0), in(reg) foo);
- | ^^^^^^^^^^^^^^^^^^^^
- |
- = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: asm template must be a string literal
- --> $DIR/parse-error.rs:77:21
- |
-LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
- | ^^^^^^^^^^^^^^^^^^^^
- |
- = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: _ cannot be used for input operands
- --> $DIR/parse-error.rs:79:28
- |
-LL | asm!("{}", in(reg) _);
- | ^
-
-error: _ cannot be used for input operands
- --> $DIR/parse-error.rs:81:31
- |
-LL | asm!("{}", inout(reg) _);
- | ^
-
-error: _ cannot be used for input operands
- --> $DIR/parse-error.rs:83:35
- |
-LL | asm!("{}", inlateout(reg) _);
- | ^
-
-error: requires at least a template string argument
- --> $DIR/parse-error.rs:90:1
- |
-LL | global_asm!();
- | ^^^^^^^^^^^^^^
-
-error: asm template must be a string literal
- --> $DIR/parse-error.rs:92:13
- |
-LL | global_asm!(FOO);
- | ^^^
-
-error: expected token: `,`
- --> $DIR/parse-error.rs:94:18
- |
-LL | global_asm!("{}" FOO);
- | ^^^ expected `,`
-
-error: expected operand, options, or additional template string
- --> $DIR/parse-error.rs:96:19
- |
-LL | global_asm!("{}", FOO);
- | ^^^ expected operand, options, or additional template string
-
-error: expected expression, found end of macro arguments
- --> $DIR/parse-error.rs:98:24
- |
-LL | global_asm!("{}", const);
- | ^ expected expression
-
-error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
- --> $DIR/parse-error.rs:100:30
- |
-LL | global_asm!("{}", const(reg) FOO);
- | ^^^ expected one of `,`, `.`, `?`, or an operator
-
-error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
- --> $DIR/parse-error.rs:102:25
- |
-LL | global_asm!("", options(FOO));
- | ^^^ expected one of `)`, `att_syntax`, or `raw`
-
-error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
- --> $DIR/parse-error.rs:104:25
- |
-LL | global_asm!("", options(nomem FOO));
- | ^^^^^ expected one of `)`, `att_syntax`, or `raw`
-
-error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
- --> $DIR/parse-error.rs:106:25
- |
-LL | global_asm!("", options(nomem, FOO));
- | ^^^^^ expected one of `)`, `att_syntax`, or `raw`
-
-error: arguments are not allowed after options
- --> $DIR/parse-error.rs:108:30
- |
-LL | global_asm!("{}", options(), const FOO);
- | --------- ^^^^^^^^^ argument
- | |
- | previous options
-
-error: expected string literal
- --> $DIR/parse-error.rs:110:29
- |
-LL | global_asm!("", clobber_abi(FOO));
- | ^^^ not a string literal
-
-error: expected `)`, found `FOO`
- --> $DIR/parse-error.rs:112:33
- |
-LL | global_asm!("", clobber_abi("C" FOO));
- | ^^^ expected `)`
-
-error: expected `)`, found `,`
- --> $DIR/parse-error.rs:114:32
- |
-LL | global_asm!("", clobber_abi("C", FOO));
- | ^ expected `)`
-
-error: arguments are not allowed after clobber_abi
- --> $DIR/parse-error.rs:116:37
- |
-LL | global_asm!("{}", clobber_abi("C"), const FOO);
- | ---------------- ^^^^^^^^^ argument
- | |
- | clobber_abi
-
-error: `clobber_abi` cannot be used with `global_asm!`
- --> $DIR/parse-error.rs:116:19
- |
-LL | global_asm!("{}", clobber_abi("C"), const FOO);
- | ^^^^^^^^^^^^^^^^
-
-error: clobber_abi is not allowed after options
- --> $DIR/parse-error.rs:119:28
- |
-LL | global_asm!("", options(), clobber_abi("C"));
- | --------- ^^^^^^^^^^^^^^^^
- | |
- | options
-
-error: clobber_abi is not allowed after options
- --> $DIR/parse-error.rs:121:30
- |
-LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
- | --------- ^^^^^^^^^^^^^^^^
- | |
- | options
-
-error: clobber_abi specified multiple times
- --> $DIR/parse-error.rs:123:35
- |
-LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
- | ---------------- ^^^^^^^^^^^^^^^^
- | |
- | clobber_abi previously specified here
-
-error: duplicate argument named `a`
- --> $DIR/parse-error.rs:125:35
- |
-LL | global_asm!("{a}", a = const FOO, a = const BAR);
- | ------------- ^^^^^^^^^^^^^ duplicate argument
- | |
- | previously here
-
-error: argument never used
- --> $DIR/parse-error.rs:125:35
- |
-LL | global_asm!("{a}", a = const FOO, a = const BAR);
- | ^^^^^^^^^^^^^ argument never used
- |
- = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
-
-error: expected one of `clobber_abi`, `const`, or `options`, found `""`
- --> $DIR/parse-error.rs:128:28
- |
-LL | global_asm!("", options(), "");
- | ^^ expected one of `clobber_abi`, `const`, or `options`
-
-error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"`
- --> $DIR/parse-error.rs:130:30
- |
-LL | global_asm!("{}", const FOO, "{}", const FOO);
- | ^^^^ expected one of `clobber_abi`, `const`, or `options`
-
-error: asm template must be a string literal
- --> $DIR/parse-error.rs:132:13
- |
-LL | global_asm!(format!("{{{}}}", 0), const FOO);
- | ^^^^^^^^^^^^^^^^^^^^
- |
- = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: asm template must be a string literal
- --> $DIR/parse-error.rs:134:20
- |
-LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
- | ^^^^^^^^^^^^^^^^^^^^
- |
- = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/parse-error.rs:37:37
- |
-LL | let mut foo = 0;
- | ---------- help: consider using `const` instead of `let`: `const foo`
-...
-LL | asm!("{}", options(), const foo);
- | ^^^ non-constant value
-
-error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/parse-error.rs:46:44
- |
-LL | let mut foo = 0;
- | ---------- help: consider using `const` instead of `let`: `const foo`
-...
-LL | asm!("{}", clobber_abi("C"), const foo);
- | ^^^ non-constant value
-
-error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/parse-error.rs:55:31
- |
-LL | let mut foo = 0;
- | ---------- help: consider using `const` instead of `let`: `const foo`
-...
-LL | asm!("{a}", a = const foo, a = const bar);
- | ^^^ non-constant value
-
-error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/parse-error.rs:55:46
- |
-LL | let mut bar = 0;
- | ---------- help: consider using `const` instead of `let`: `const bar`
-...
-LL | asm!("{a}", a = const foo, a = const bar);
- | ^^^ non-constant value
-
-error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/parse-error.rs:62:46
- |
-LL | let mut bar = 0;
- | ---------- help: consider using `const` instead of `let`: `const bar`
-...
-LL | asm!("{a}", in("eax") foo, a = const bar);
- | ^^^ non-constant value
-
-error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/parse-error.rs:65:46
- |
-LL | let mut bar = 0;
- | ---------- help: consider using `const` instead of `let`: `const bar`
-...
-LL | asm!("{a}", in("eax") foo, a = const bar);
- | ^^^ non-constant value
-
-error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/parse-error.rs:68:42
- |
-LL | let mut bar = 0;
- | ---------- help: consider using `const` instead of `let`: `const bar`
-...
-LL | asm!("{1}", in("eax") foo, const bar);
- | ^^^ non-constant value
-
-error: aborting due to 66 previous errors
-
-For more information about this error, try `rustc --explain E0435`.
// run-rustfix
-// only-x86_64
+// needs-asm-support
#![feature(asm, llvm_asm)]
#![allow(deprecated)] // llvm_asm!
// run-rustfix
-// only-x86_64
+// needs-asm-support
#![feature(asm, llvm_asm)]
#![allow(deprecated)] // llvm_asm!
+++ /dev/null
-// min-llvm-version: 10.0.1
-// only-x86_64
-// build-fail
-// compile-flags: -Ccodegen-units=1
-#![feature(asm)]
-
-// Checks that inline asm errors are mapped to the correct line in the source code.
-
-fn main() {
- unsafe {
- asm!("invalid_instruction");
- //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'
-
- asm!("
- invalid_instruction
- ");
- //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
-
- asm!(r#"
- invalid_instruction
- "#);
- //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
-
- asm!("
- mov eax, eax
- invalid_instruction
- mov eax, eax
- ");
- //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
-
- asm!(r#"
- mov eax, eax
- invalid_instruction
- mov eax, eax
- "#);
- //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
-
- asm!(concat!("invalid", "_", "instruction"));
- //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'
-
- asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
- //~^ WARN: scale factor without index register is ignored
-
- asm!(
- "invalid_instruction",
- );
- //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
-
- asm!(
- "mov eax, eax",
- "invalid_instruction",
- "mov eax, eax",
- );
- //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
-
- asm!(
- "mov eax, eax\n",
- "invalid_instruction",
- "mov eax, eax",
- );
- //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
-
- asm!(
- "mov eax, eax",
- concat!("invalid", "_", "instruction"),
- "mov eax, eax",
- );
- //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
-
- asm!(
- concat!("mov eax", ", ", "eax"),
- concat!("invalid", "_", "instruction"),
- concat!("mov eax", ", ", "eax"),
- );
- //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
-
- // Make sure template strings get separated
- asm!(
- "invalid_instruction1",
- "invalid_instruction2",
- );
- //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
- //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
-
- asm!(
- concat!(
- "invalid", "_", "instruction1", "\n",
- "invalid", "_", "instruction2",
- ),
- );
- //~^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
- //~^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
-
- asm!(
- concat!(
- "invalid", "_", "instruction1", "\n",
- "invalid", "_", "instruction2",
- ),
- concat!(
- "invalid", "_", "instruction3", "\n",
- "invalid", "_", "instruction4",
- ),
- );
- //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
- //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
- //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3'
- //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4'
-
- asm!(
- concat!(
- "invalid", "_", "instruction1", "\n",
- "invalid", "_", "instruction2", "\n",
- ),
- concat!(
- "invalid", "_", "instruction3", "\n",
- "invalid", "_", "instruction4", "\n",
- ),
- );
- //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
- //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
- //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3'
- //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4'
- }
-}
+++ /dev/null
-error: invalid instruction mnemonic 'invalid_instruction'
- --> $DIR/srcloc.rs:11:15
- |
-LL | asm!("invalid_instruction");
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:2:2
- |
-LL | invalid_instruction
- | ^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction'
- --> $DIR/srcloc.rs:15:13
- |
-LL | invalid_instruction
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:3:13
- |
-LL | invalid_instruction
- | ^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction'
- --> $DIR/srcloc.rs:20:13
- |
-LL | invalid_instruction
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:3:13
- |
-LL | invalid_instruction
- | ^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction'
- --> $DIR/srcloc.rs:26:13
- |
-LL | invalid_instruction
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:4:13
- |
-LL | invalid_instruction
- | ^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction'
- --> $DIR/srcloc.rs:33:13
- |
-LL | invalid_instruction
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:4:13
- |
-LL | invalid_instruction
- | ^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction'
- --> $DIR/srcloc.rs:38:14
- |
-LL | asm!(concat!("invalid", "_", "instruction"));
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:2:2
- |
-LL | invalid_instruction
- | ^^^^^^^^^^^^^^^^^^^
-
-warning: scale factor without index register is ignored
- --> $DIR/srcloc.rs:41:15
- |
-LL | asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:1:23
- |
-LL | movaps %xmm3, (%esi, 2)
- | ^
-
-error: invalid instruction mnemonic 'invalid_instruction'
- --> $DIR/srcloc.rs:45:14
- |
-LL | "invalid_instruction",
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:2:2
- |
-LL | invalid_instruction
- | ^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction'
- --> $DIR/srcloc.rs:51:14
- |
-LL | "invalid_instruction",
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:3:1
- |
-LL | invalid_instruction
- | ^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction'
- --> $DIR/srcloc.rs:58:14
- |
-LL | "invalid_instruction",
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:4:1
- |
-LL | invalid_instruction
- | ^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction'
- --> $DIR/srcloc.rs:65:13
- |
-LL | concat!("invalid", "_", "instruction"),
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:3:1
- |
-LL | invalid_instruction
- | ^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction'
- --> $DIR/srcloc.rs:72:13
- |
-LL | concat!("invalid", "_", "instruction"),
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:3:1
- |
-LL | invalid_instruction
- | ^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction1'
- --> $DIR/srcloc.rs:79:14
- |
-LL | "invalid_instruction1",
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:2:2
- |
-LL | invalid_instruction1
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction2'
- --> $DIR/srcloc.rs:80:14
- |
-LL | "invalid_instruction2",
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:3:1
- |
-LL | invalid_instruction2
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction1'
- --> $DIR/srcloc.rs:86:13
- |
-LL | concat!(
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:2:2
- |
-LL | invalid_instruction1
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction2'
- --> $DIR/srcloc.rs:86:13
- |
-LL | concat!(
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:3:1
- |
-LL | invalid_instruction2
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction1'
- --> $DIR/srcloc.rs:95:13
- |
-LL | concat!(
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:2:2
- |
-LL | invalid_instruction1
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction2'
- --> $DIR/srcloc.rs:95:13
- |
-LL | concat!(
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:3:1
- |
-LL | invalid_instruction2
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction3'
- --> $DIR/srcloc.rs:99:13
- |
-LL | concat!(
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:4:1
- |
-LL | invalid_instruction3
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction4'
- --> $DIR/srcloc.rs:99:13
- |
-LL | concat!(
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:5:1
- |
-LL | invalid_instruction4
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction1'
- --> $DIR/srcloc.rs:110:13
- |
-LL | concat!(
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:2:2
- |
-LL | invalid_instruction1
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction2'
- --> $DIR/srcloc.rs:110:13
- |
-LL | concat!(
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:3:1
- |
-LL | invalid_instruction2
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction3'
- --> $DIR/srcloc.rs:114:13
- |
-LL | concat!(
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:5:1
- |
-LL | invalid_instruction3
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: invalid instruction mnemonic 'invalid_instruction4'
- --> $DIR/srcloc.rs:114:13
- |
-LL | concat!(
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:6:1
- |
-LL | invalid_instruction4
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 23 previous errors; 1 warning emitted
-
+++ /dev/null
-// min-llvm-version: 10.0.1
-// only-x86_64
-// only-linux
-// run-pass
-
-#![feature(asm, thread_local)]
-
-extern "C" fn f1() -> i32 {
- 111
-}
-
-// The compiler will generate a shim to hide the caller location parameter.
-#[track_caller]
-fn f2() -> i32 {
- 222
-}
-
-macro_rules! call {
- ($func:path) => {
- unsafe {
- let result: i32;
- asm!("call {}", sym $func,
- out("rax") result,
- out("rcx") _, out("rdx") _, out("rdi") _, out("rsi") _,
- out("r8") _, out("r9") _, out("r10") _, out("r11") _,
- out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _,
- out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _,
- out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,
- out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,
- );
- result
- }
- }
-}
-
-macro_rules! static_addr {
- ($s:expr) => {
- unsafe {
- let result: *const u32;
- // LEA performs a RIP-relative address calculation and returns the address
- asm!("lea {}, [rip + {}]", out(reg) result, sym $s);
- result
- }
- }
-}
-macro_rules! static_tls_addr {
- ($s:expr) => {
- unsafe {
- let result: *const u32;
- asm!(
- "
- # Load TLS base address
- mov {out}, qword ptr fs:[0]
- # Calculate the address of sym in the TLS block. The @tpoff
- # relocation gives the offset of the symbol from the start
- # of the TLS block.
- lea {out}, [{out} + {sym}@tpoff]
- ",
- out = out(reg) result,
- sym = sym $s
- );
- result
- }
- }
-}
-
-static S1: u32 = 111;
-#[thread_local]
-static S2: u32 = 222;
-
-fn main() {
- assert_eq!(call!(f1), 111);
- assert_eq!(call!(f2), 222);
- assert_eq!(static_addr!(S1), &S1 as *const u32);
- assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
- std::thread::spawn(|| {
- assert_eq!(static_addr!(S1), &S1 as *const u32);
- assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
- }).join().unwrap();
-}
-// only-x86_64
+// needs-asm-support
+// ignore-nvptx64
+// ignore-spirv
+// ignore-wasm32
#![feature(asm, global_asm)]
//~^ ERROR mismatched types
asm!("{}", const 0 as *mut u8);
//~^ ERROR mismatched types
+ asm!("{}", const &0);
+ //~^ ERROR mismatched types
}
}
error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/type-check-1.rs:34:26
+ --> $DIR/type-check-1.rs:37:26
|
LL | let x = 0;
| ----- help: consider using `const` instead of `let`: `const x`
| ^ non-constant value
error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/type-check-1.rs:37:36
+ --> $DIR/type-check-1.rs:40:36
|
LL | let x = 0;
| ----- help: consider using `const` instead of `let`: `const x`
| ^ non-constant value
error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/type-check-1.rs:40:36
+ --> $DIR/type-check-1.rs:43:36
|
LL | let x = 0;
| ----- help: consider using `const` instead of `let`: `const x`
| ^ non-constant value
error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:48:26
+ --> $DIR/type-check-1.rs:51:26
|
LL | asm!("{}", const 0f32);
| ^^^^ expected integer, found `f32`
error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:50:26
+ --> $DIR/type-check-1.rs:53:26
|
LL | asm!("{}", const 0 as *mut u8);
| ^^^^^^^^^^^^ expected integer, found *-ptr
= note: expected type `{integer}`
found raw pointer `*mut u8`
+error[E0308]: mismatched types
+ --> $DIR/type-check-1.rs:55:26
+ |
+LL | asm!("{}", const &0);
+ | ^^ expected integer, found `&{integer}`
+ |
+help: consider removing the borrow
+ |
+LL - asm!("{}", const &0);
+LL + asm!("{}", const 0);
+ |
+
error: invalid asm output
- --> $DIR/type-check-1.rs:10:29
+ --> $DIR/type-check-1.rs:13:29
|
LL | asm!("{}", out(reg) 1 + 2);
| ^^^^^ cannot assign to this expression
error: invalid asm output
- --> $DIR/type-check-1.rs:12:31
+ --> $DIR/type-check-1.rs:15:31
|
LL | asm!("{}", inout(reg) 1 + 2);
| ^^^^^ cannot assign to this expression
error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
- --> $DIR/type-check-1.rs:18:28
+ --> $DIR/type-check-1.rs:21:28
|
LL | asm!("{}", in(reg) v[..]);
| ^^^^^ doesn't have a size known at compile-time
= note: all inline asm arguments must have a statically known size
error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
- --> $DIR/type-check-1.rs:20:29
+ --> $DIR/type-check-1.rs:23:29
|
LL | asm!("{}", out(reg) v[..]);
| ^^^^^ doesn't have a size known at compile-time
= note: all inline asm arguments must have a statically known size
error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
- --> $DIR/type-check-1.rs:22:31
+ --> $DIR/type-check-1.rs:25:31
|
LL | asm!("{}", inout(reg) v[..]);
| ^^^^^ doesn't have a size known at compile-time
= note: all inline asm arguments must have a statically known size
error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:60:25
+ --> $DIR/type-check-1.rs:65:25
|
LL | global_asm!("{}", const 0f32);
| ^^^^ expected integer, found `f32`
error[E0308]: mismatched types
- --> $DIR/type-check-1.rs:62:25
+ --> $DIR/type-check-1.rs:67:25
|
LL | global_asm!("{}", const 0 as *mut u8);
| ^^^^^^^^^^^^ expected integer, found *-ptr
= note: expected type `{integer}`
found raw pointer `*mut u8`
-error: aborting due to 12 previous errors
+error: aborting due to 13 previous errors
Some errors have detailed explanations: E0277, E0308, E0435.
For more information about an error, try `rustc --explain E0277`.
+++ /dev/null
-// only-x86_64
-
-#![feature(asm, repr_simd, never_type)]
-
-#[repr(simd)]
-struct SimdNonCopy(f32, f32, f32, f32);
-
-fn main() {
- unsafe {
- // Inputs must be initialized
-
- let x: u64;
- asm!("{}", in(reg) x);
- //~^ ERROR use of possibly-uninitialized variable: `x`
- let mut y: u64;
- asm!("{}", inout(reg) y);
- //~^ ERROR use of possibly-uninitialized variable: `y`
- let _ = y;
-
- // Outputs require mutable places
-
- let v: Vec<u64> = vec![0, 1, 2];
- asm!("{}", in(reg) v[0]);
- asm!("{}", out(reg) v[0]);
- //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
- asm!("{}", inout(reg) v[0]);
- //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
-
- // This currently causes an ICE: https://github.com/rust-lang/rust/issues/81857
- // asm!("{}", const &0);
- // ERROR asm `const` arguments must be integer or floating-point values
-
- // Sym operands must point to a function or static
-
- const C: i32 = 0;
- static S: i32 = 0;
- asm!("{}", sym S);
- asm!("{}", sym main);
- asm!("{}", sym C);
- //~^ ERROR asm `sym` operand must point to a fn or static
- asm!("{}", sym x);
- //~^ ERROR asm `sym` operand must point to a fn or static
-
- // Register operands must be Copy
-
- asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
- //~^ ERROR arguments for inline assembly must be copyable
-
- // Register operands must be integers, floats, SIMD vectors, pointers or
- // function pointers.
-
- asm!("{}", in(reg) 0i64);
- asm!("{}", in(reg) 0f64);
- asm!("{}", in(xmm_reg) std::arch::x86_64::_mm_setzero_ps());
- asm!("{}", in(reg) 0 as *const u8);
- asm!("{}", in(reg) 0 as *mut u8);
- asm!("{}", in(reg) main as fn());
- asm!("{}", in(reg) |x: i32| x);
- //~^ ERROR cannot use value of type
- asm!("{}", in(reg) vec![0]);
- //~^ ERROR cannot use value of type `Vec<i32>` for inline assembly
- asm!("{}", in(reg) (1, 2, 3));
- //~^ ERROR cannot use value of type `(i32, i32, i32)` for inline assembly
- asm!("{}", in(reg) [1, 2, 3]);
- //~^ ERROR cannot use value of type `[i32; 3]` for inline assembly
-
- // Register inputs (but not outputs) allow references and function types
-
- let mut f = main;
- let mut r = &mut 0;
- asm!("{}", in(reg) f);
- asm!("{}", inout(reg) f);
- //~^ ERROR cannot use value of type `fn() {main}` for inline assembly
- asm!("{}", in(reg) r);
- asm!("{}", inout(reg) r);
- //~^ ERROR cannot use value of type `&mut i32` for inline assembly
- let _ = (f, r);
-
- // Type checks ignore never type
-
- let u: ! = unreachable!();
- asm!("{}", in(reg) u);
- }
-}
+++ /dev/null
-error: arguments for inline assembly must be copyable
- --> $DIR/type-check-2.rs:46:32
- |
-LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: `SimdNonCopy` does not implement the Copy trait
-
-error: cannot use value of type `[closure@$DIR/type-check-2.rs:58:28: 58:38]` for inline assembly
- --> $DIR/type-check-2.rs:58:28
- |
-LL | asm!("{}", in(reg) |x: i32| x);
- | ^^^^^^^^^^
- |
- = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
-
-error: cannot use value of type `Vec<i32>` for inline assembly
- --> $DIR/type-check-2.rs:60:28
- |
-LL | asm!("{}", in(reg) vec![0]);
- | ^^^^^^^
- |
- = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
- = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: cannot use value of type `(i32, i32, i32)` for inline assembly
- --> $DIR/type-check-2.rs:62:28
- |
-LL | asm!("{}", in(reg) (1, 2, 3));
- | ^^^^^^^^^
- |
- = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
-
-error: cannot use value of type `[i32; 3]` for inline assembly
- --> $DIR/type-check-2.rs:64:28
- |
-LL | asm!("{}", in(reg) [1, 2, 3]);
- | ^^^^^^^^^
- |
- = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
-
-error: cannot use value of type `fn() {main}` for inline assembly
- --> $DIR/type-check-2.rs:72:31
- |
-LL | asm!("{}", inout(reg) f);
- | ^
- |
- = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
-
-error: cannot use value of type `&mut i32` for inline assembly
- --> $DIR/type-check-2.rs:75:31
- |
-LL | asm!("{}", inout(reg) r);
- | ^
- |
- = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
-
-error: asm `sym` operand must point to a fn or static
- --> $DIR/type-check-2.rs:39:24
- |
-LL | asm!("{}", sym C);
- | ^
-
-error: asm `sym` operand must point to a fn or static
- --> $DIR/type-check-2.rs:41:24
- |
-LL | asm!("{}", sym x);
- | ^
-
-error[E0381]: use of possibly-uninitialized variable: `x`
- --> $DIR/type-check-2.rs:13:28
- |
-LL | asm!("{}", in(reg) x);
- | ^ use of possibly-uninitialized `x`
-
-error[E0381]: use of possibly-uninitialized variable: `y`
- --> $DIR/type-check-2.rs:16:9
- |
-LL | asm!("{}", inout(reg) y);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
-
-error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
- --> $DIR/type-check-2.rs:24:29
- |
-LL | let v: Vec<u64> = vec![0, 1, 2];
- | - help: consider changing this to be mutable: `mut v`
-LL | asm!("{}", in(reg) v[0]);
-LL | asm!("{}", out(reg) v[0]);
- | ^ cannot borrow as mutable
-
-error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
- --> $DIR/type-check-2.rs:26:31
- |
-LL | let v: Vec<u64> = vec![0, 1, 2];
- | - help: consider changing this to be mutable: `mut v`
-...
-LL | asm!("{}", inout(reg) v[0]);
- | ^ cannot borrow as mutable
-
-error: aborting due to 13 previous errors
-
-Some errors have detailed explanations: E0381, E0596.
-For more information about an error, try `rustc --explain E0381`.
+++ /dev/null
-// only-x86_64
-// compile-flags: -C target-feature=+avx512f
-
-#![feature(asm, global_asm)]
-
-use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
-
-fn main() {
- unsafe {
- // Types must be listed in the register class.
-
- asm!("{}", in(reg) 0i128);
- //~^ ERROR type `i128` cannot be used with this register class
- asm!("{}", in(reg) _mm_setzero_ps());
- //~^ ERROR type `__m128` cannot be used with this register class
- asm!("{}", in(reg) _mm256_setzero_ps());
- //~^ ERROR type `__m256` cannot be used with this register class
- asm!("{}", in(xmm_reg) 0u8);
- //~^ ERROR type `u8` cannot be used with this register class
- asm!("{:e}", in(reg) 0i32);
- asm!("{}", in(xmm_reg) 0i32);
- asm!("{:e}", in(reg) 0f32);
- asm!("{}", in(xmm_reg) 0f32);
- asm!("{}", in(xmm_reg) _mm_setzero_ps());
- asm!("{:x}", in(ymm_reg) _mm_setzero_ps());
- asm!("{}", in(kreg) 0u16);
- asm!("{}", in(kreg) 0u64);
- //~^ ERROR `avx512bw` target feature is not enabled
-
- // Template modifier suggestions for sub-registers
-
- asm!("{0} {0}", in(reg) 0i16);
- //~^ WARN formatting may not be suitable for sub-register argument
- asm!("{0} {0:x}", in(reg) 0i16);
- //~^ WARN formatting may not be suitable for sub-register argument
- asm!("{}", in(reg) 0i32);
- //~^ WARN formatting may not be suitable for sub-register argument
- asm!("{}", in(reg) 0i64);
- asm!("{}", in(ymm_reg) 0i64);
- //~^ WARN formatting may not be suitable for sub-register argument
- asm!("{}", in(ymm_reg) _mm256_setzero_ps());
- asm!("{:l}", in(reg) 0i16);
- asm!("{:l}", in(reg) 0i32);
- asm!("{:l}", in(reg) 0i64);
- asm!("{:x}", in(ymm_reg) 0i64);
- asm!("{:x}", in(ymm_reg) _mm256_setzero_ps());
-
- // Suggest different register class for type
-
- asm!("{}", in(reg) 0i8);
- //~^ ERROR type `i8` cannot be used with this register class
- asm!("{}", in(reg_byte) 0i8);
-
- // Split inout operands must have compatible types
-
- let mut val_i16: i16;
- let mut val_f32: f32;
- let mut val_u32: u32;
- let mut val_u64: u64;
- let mut val_ptr: *mut u8;
- asm!("{:r}", inout(reg) 0u16 => val_i16);
- asm!("{:r}", inout(reg) 0u32 => val_f32);
- //~^ ERROR incompatible types for asm inout argument
- asm!("{:r}", inout(reg) 0u32 => val_ptr);
- //~^ ERROR incompatible types for asm inout argument
- asm!("{:r}", inout(reg) main => val_u32);
- //~^ ERROR incompatible types for asm inout argument
- asm!("{:r}", inout(reg) 0u64 => val_ptr);
- asm!("{:r}", inout(reg) main => val_u64);
- }
-}
-
-// Constants must be... constant
-
-static S: i32 = 1;
-const fn const_foo(x: i32) -> i32 {
- x
-}
-const fn const_bar<T>(x: T) -> T {
- x
-}
-global_asm!("{}", const S);
-//~^ ERROR constants cannot refer to statics
-global_asm!("{}", const const_foo(0));
-global_asm!("{}", const const_foo(S));
-//~^ ERROR constants cannot refer to statics
-global_asm!("{}", const const_bar(0));
-global_asm!("{}", const const_bar(S));
-//~^ ERROR constants cannot refer to statics
+++ /dev/null
-error: type `i128` cannot be used with this register class
- --> $DIR/type-check-3.rs:12:28
- |
-LL | asm!("{}", in(reg) 0i128);
- | ^^^^^
- |
- = note: register class `reg` supports these types: i16, i32, i64, f32, f64
-
-error: type `__m128` cannot be used with this register class
- --> $DIR/type-check-3.rs:14:28
- |
-LL | asm!("{}", in(reg) _mm_setzero_ps());
- | ^^^^^^^^^^^^^^^^
- |
- = note: register class `reg` supports these types: i16, i32, i64, f32, f64
-
-error: type `__m256` cannot be used with this register class
- --> $DIR/type-check-3.rs:16:28
- |
-LL | asm!("{}", in(reg) _mm256_setzero_ps());
- | ^^^^^^^^^^^^^^^^^^^
- |
- = note: register class `reg` supports these types: i16, i32, i64, f32, f64
-
-error: type `u8` cannot be used with this register class
- --> $DIR/type-check-3.rs:18:32
- |
-LL | asm!("{}", in(xmm_reg) 0u8);
- | ^^^
- |
- = note: register class `xmm_reg` supports these types: i32, i64, f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
-
-error: `avx512bw` target feature is not enabled
- --> $DIR/type-check-3.rs:27:29
- |
-LL | asm!("{}", in(kreg) 0u64);
- | ^^^^
- |
- = note: this is required to use type `u64` with register class `kreg`
-
-warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:32:15
- |
-LL | asm!("{0} {0}", in(reg) 0i16);
- | ^^^ ^^^ ---- for this argument
- |
- = note: `#[warn(asm_sub_register)]` on by default
- = help: use the `x` modifier to have the register formatted as `ax`
- = help: or use the `r` modifier to keep the default formatting of `rax`
-
-warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:34:15
- |
-LL | asm!("{0} {0:x}", in(reg) 0i16);
- | ^^^ ---- for this argument
- |
- = help: use the `x` modifier to have the register formatted as `ax`
- = help: or use the `r` modifier to keep the default formatting of `rax`
-
-warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:36:15
- |
-LL | asm!("{}", in(reg) 0i32);
- | ^^ ---- for this argument
- |
- = help: use the `e` modifier to have the register formatted as `eax`
- = help: or use the `r` modifier to keep the default formatting of `rax`
-
-warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:39:15
- |
-LL | asm!("{}", in(ymm_reg) 0i64);
- | ^^ ---- for this argument
- |
- = help: use the `x` modifier to have the register formatted as `xmm0`
- = help: or use the `y` modifier to keep the default formatting of `ymm0`
-
-error: type `i8` cannot be used with this register class
- --> $DIR/type-check-3.rs:50:28
- |
-LL | asm!("{}", in(reg) 0i8);
- | ^^^
- |
- = note: register class `reg` supports these types: i16, i32, i64, f32, f64
- = help: consider using the `reg_byte` register class instead
-
-error: incompatible types for asm inout argument
- --> $DIR/type-check-3.rs:62:33
- |
-LL | asm!("{:r}", inout(reg) 0u32 => val_f32);
- | ^^^^ ^^^^^^^ type `f32`
- | |
- | type `u32`
- |
- = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
-
-error: incompatible types for asm inout argument
- --> $DIR/type-check-3.rs:64:33
- |
-LL | asm!("{:r}", inout(reg) 0u32 => val_ptr);
- | ^^^^ ^^^^^^^ type `*mut u8`
- | |
- | type `u32`
- |
- = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
-
-error: incompatible types for asm inout argument
- --> $DIR/type-check-3.rs:66:33
- |
-LL | asm!("{:r}", inout(reg) main => val_u32);
- | ^^^^ ^^^^^^^ type `u32`
- | |
- | type `fn()`
- |
- = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
-
-error[E0013]: constants cannot refer to statics
- --> $DIR/type-check-3.rs:82:25
- |
-LL | global_asm!("{}", const S);
- | ^
- |
- = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error[E0013]: constants cannot refer to statics
- --> $DIR/type-check-3.rs:85:35
- |
-LL | global_asm!("{}", const const_foo(S));
- | ^
- |
- = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error[E0013]: constants cannot refer to statics
- --> $DIR/type-check-3.rs:88:35
- |
-LL | global_asm!("{}", const const_bar(S));
- | ^
- |
- = help: consider extracting the value of the `static` to a `const`, and referring to that
-
-error: aborting due to 12 previous errors; 4 warnings emitted
-
-For more information about this error, try `rustc --explain E0013`.
-// only-x86_64
+// needs-asm-support
+// ignore-nvptx64
+// ignore-spirv
+// ignore-wasm32
#![feature(asm)]
error[E0506]: cannot assign to `a` because it is borrowed
- --> $DIR/type-check-4.rs:11:9
+ --> $DIR/type-check-4.rs:14:9
|
LL | let p = &a;
| -- borrow of `a` occurs here
| - borrow later used here
error[E0503]: cannot use `a` because it was mutably borrowed
- --> $DIR/type-check-4.rs:19:28
+ --> $DIR/type-check-4.rs:22:28
|
LL | let p = &mut a;
| ------ borrow of `a` occurs here
--- /dev/null
+// only-x86_64
+
+#![feature(asm, global_asm)]
+
+fn main() {
+ let mut foo = 0;
+ unsafe {
+ asm!("", options(nomem, readonly));
+ //~^ ERROR the `nomem` and `readonly` options are mutually exclusive
+ asm!("", options(pure, nomem, noreturn));
+ //~^ ERROR the `pure` and `noreturn` options are mutually exclusive
+ //~^^ ERROR asm with the `pure` option must have at least one output
+ asm!("{}", in(reg) foo, options(pure, nomem));
+ //~^ ERROR asm with the `pure` option must have at least one output
+ asm!("{}", out(reg) foo, options(noreturn));
+ //~^ ERROR asm outputs are not allowed with the `noreturn` option
+ }
+
+ unsafe {
+ asm!("", clobber_abi("foo"));
+ //~^ ERROR invalid ABI for `clobber_abi`
+ asm!("{}", out(reg) foo, clobber_abi("C"));
+ //~^ ERROR asm with `clobber_abi` must specify explicit registers for outputs
+ asm!("", out("eax") foo, clobber_abi("C"));
+ }
+}
+
+global_asm!("", options(nomem));
+//~^ ERROR expected one of
+global_asm!("", options(readonly));
+//~^ ERROR expected one of
+global_asm!("", options(noreturn));
+//~^ ERROR expected one of
+global_asm!("", options(pure));
+//~^ ERROR expected one of
+global_asm!("", options(nostack));
+//~^ ERROR expected one of
+global_asm!("", options(preserves_flags));
+//~^ ERROR expected one of
--- /dev/null
+error: the `nomem` and `readonly` options are mutually exclusive
+ --> $DIR/bad-options.rs:8:18
+ |
+LL | asm!("", options(nomem, readonly));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the `pure` and `noreturn` options are mutually exclusive
+ --> $DIR/bad-options.rs:10:18
+ |
+LL | asm!("", options(pure, nomem, noreturn));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: asm with the `pure` option must have at least one output
+ --> $DIR/bad-options.rs:10:18
+ |
+LL | asm!("", options(pure, nomem, noreturn));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: asm with the `pure` option must have at least one output
+ --> $DIR/bad-options.rs:13:33
+ |
+LL | asm!("{}", in(reg) foo, options(pure, nomem));
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: asm outputs are not allowed with the `noreturn` option
+ --> $DIR/bad-options.rs:15:20
+ |
+LL | asm!("{}", out(reg) foo, options(noreturn));
+ | ^^^^^^^^^^^^
+
+error: asm with `clobber_abi` must specify explicit registers for outputs
+ --> $DIR/bad-options.rs:22:20
+ |
+LL | asm!("{}", out(reg) foo, clobber_abi("C"));
+ | ^^^^^^^^^^^^ ---------------- clobber_abi
+ | |
+ | generic outputs
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+ --> $DIR/bad-options.rs:28:25
+ |
+LL | global_asm!("", options(nomem));
+ | ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `readonly`
+ --> $DIR/bad-options.rs:30:25
+ |
+LL | global_asm!("", options(readonly));
+ | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `noreturn`
+ --> $DIR/bad-options.rs:32:25
+ |
+LL | global_asm!("", options(noreturn));
+ | ^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `pure`
+ --> $DIR/bad-options.rs:34:25
+ |
+LL | global_asm!("", options(pure));
+ | ^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `nostack`
+ --> $DIR/bad-options.rs:36:25
+ |
+LL | global_asm!("", options(nostack));
+ | ^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `preserves_flags`
+ --> $DIR/bad-options.rs:38:25
+ |
+LL | global_asm!("", options(preserves_flags));
+ | ^^^^^^^^^^^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: invalid ABI for `clobber_abi`
+ --> $DIR/bad-options.rs:20:18
+ |
+LL | asm!("", clobber_abi("foo"));
+ | ^^^^^^^^^^^^^^^^^^
+ |
+ = note: the following ABIs are supported on this target: `C`, `system`, `efiapi`, `win64`, `sysv64`
+
+error: aborting due to 13 previous errors
+
--- /dev/null
+// only-x86_64
+// compile-flags: -C target-feature=+avx2
+
+#![feature(asm)]
+
+fn main() {
+ let mut foo = 0;
+ let mut bar = 0;
+ unsafe {
+ // Bad register/register class
+
+ asm!("{}", in(foo) foo);
+ //~^ ERROR invalid register class `foo`: unknown register class
+ asm!("", in("foo") foo);
+ //~^ ERROR invalid register `foo`: unknown register
+ asm!("{:z}", in(reg) foo);
+ //~^ ERROR invalid asm template modifier for this register class
+ asm!("{:r}", in(xmm_reg) foo);
+ //~^ ERROR invalid asm template modifier for this register class
+ asm!("{:a}", const 0);
+ //~^ ERROR asm template modifiers are not allowed for `const` arguments
+ asm!("{:a}", sym main);
+ //~^ ERROR asm template modifiers are not allowed for `sym` arguments
+ asm!("{}", in(zmm_reg) foo);
+ //~^ ERROR register class `zmm_reg` requires the `avx512f` target feature
+ asm!("", in("zmm0") foo);
+ //~^ ERROR register class `zmm_reg` requires the `avx512f` target feature
+ asm!("", in("ebp") foo);
+ //~^ ERROR invalid register `ebp`: the frame pointer cannot be used as an operand
+ asm!("", in("rsp") foo);
+ //~^ ERROR invalid register `rsp`: the stack pointer cannot be used as an operand
+ asm!("", in("ip") foo);
+ //~^ ERROR invalid register `ip`: the instruction pointer cannot be used as an operand
+ asm!("", in("k0") foo);
+ //~^ ERROR invalid register `k0`: the k0 AVX mask register cannot be used as an operand
+ asm!("", in("ah") foo);
+ //~^ ERROR invalid register `ah`: high byte registers cannot be used as an operand
+
+ asm!("", in("st(2)") foo);
+ //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+ asm!("", in("mm0") foo);
+ //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+ asm!("", out("st(2)") _);
+ asm!("", out("mm0") _);
+ asm!("{}", in(x87_reg) foo);
+ //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+ asm!("{}", in(mmx_reg) foo);
+ //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+ asm!("{}", out(x87_reg) _);
+ //~^ ERROR register class `x87_reg` can only be used as a clobber, not as an input or output
+ asm!("{}", out(mmx_reg) _);
+ //~^ ERROR register class `mmx_reg` can only be used as a clobber, not as an input or output
+
+ // Explicit register conflicts
+ // (except in/lateout which don't conflict)
+
+ asm!("", in("eax") foo, in("al") bar);
+ //~^ ERROR register `al` conflicts with register `ax`
+ asm!("", in("rax") foo, out("rax") bar);
+ //~^ ERROR register `ax` conflicts with register `ax`
+ asm!("", in("al") foo, lateout("al") bar);
+ asm!("", in("xmm0") foo, in("ymm0") bar);
+ //~^ ERROR register `ymm0` conflicts with register `xmm0`
+ asm!("", in("xmm0") foo, out("ymm0") bar);
+ //~^ ERROR register `ymm0` conflicts with register `xmm0`
+ asm!("", in("xmm0") foo, lateout("ymm0") bar);
+ }
+}
--- /dev/null
+error: invalid register class `foo`: unknown register class
+ --> $DIR/bad-reg.rs:12:20
+ |
+LL | asm!("{}", in(foo) foo);
+ | ^^^^^^^^^^^
+
+error: invalid register `foo`: unknown register
+ --> $DIR/bad-reg.rs:14:18
+ |
+LL | asm!("", in("foo") foo);
+ | ^^^^^^^^^^^^^
+
+error: invalid asm template modifier for this register class
+ --> $DIR/bad-reg.rs:16:15
+ |
+LL | asm!("{:z}", in(reg) foo);
+ | ^^^^ ----------- argument
+ | |
+ | template modifier
+ |
+ = note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, `r`
+
+error: invalid asm template modifier for this register class
+ --> $DIR/bad-reg.rs:18:15
+ |
+LL | asm!("{:r}", in(xmm_reg) foo);
+ | ^^^^ --------------- argument
+ | |
+ | template modifier
+ |
+ = note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z`
+
+error: asm template modifiers are not allowed for `const` arguments
+ --> $DIR/bad-reg.rs:20:15
+ |
+LL | asm!("{:a}", const 0);
+ | ^^^^ ------- argument
+ | |
+ | template modifier
+
+error: asm template modifiers are not allowed for `sym` arguments
+ --> $DIR/bad-reg.rs:22:15
+ |
+LL | asm!("{:a}", sym main);
+ | ^^^^ -------- argument
+ | |
+ | template modifier
+
+error: register class `zmm_reg` requires the `avx512f` target feature
+ --> $DIR/bad-reg.rs:24:20
+ |
+LL | asm!("{}", in(zmm_reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: register class `zmm_reg` requires the `avx512f` target feature
+ --> $DIR/bad-reg.rs:26:18
+ |
+LL | asm!("", in("zmm0") foo);
+ | ^^^^^^^^^^^^^^
+
+error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm
+ --> $DIR/bad-reg.rs:28:18
+ |
+LL | asm!("", in("ebp") foo);
+ | ^^^^^^^^^^^^^
+
+error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm
+ --> $DIR/bad-reg.rs:30:18
+ |
+LL | asm!("", in("rsp") foo);
+ | ^^^^^^^^^^^^^
+
+error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm
+ --> $DIR/bad-reg.rs:32:18
+ |
+LL | asm!("", in("ip") foo);
+ | ^^^^^^^^^^^^
+
+error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm
+ --> $DIR/bad-reg.rs:34:18
+ |
+LL | asm!("", in("k0") foo);
+ | ^^^^^^^^^^^^
+
+error: invalid register `ah`: high byte registers cannot be used as an operand on x86_64
+ --> $DIR/bad-reg.rs:36:18
+ |
+LL | asm!("", in("ah") foo);
+ | ^^^^^^^^^^^^
+
+error: register class `x87_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:39:18
+ |
+LL | asm!("", in("st(2)") foo);
+ | ^^^^^^^^^^^^^^^
+
+error: register class `mmx_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:41:18
+ |
+LL | asm!("", in("mm0") foo);
+ | ^^^^^^^^^^^^^
+
+error: register class `x87_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:45:20
+ |
+LL | asm!("{}", in(x87_reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: register class `mmx_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:47:20
+ |
+LL | asm!("{}", in(mmx_reg) foo);
+ | ^^^^^^^^^^^^^^^
+
+error: register class `x87_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:49:20
+ |
+LL | asm!("{}", out(x87_reg) _);
+ | ^^^^^^^^^^^^^^
+
+error: register class `mmx_reg` can only be used as a clobber, not as an input or output
+ --> $DIR/bad-reg.rs:51:20
+ |
+LL | asm!("{}", out(mmx_reg) _);
+ | ^^^^^^^^^^^^^^
+
+error: register `al` conflicts with register `ax`
+ --> $DIR/bad-reg.rs:57:33
+ |
+LL | asm!("", in("eax") foo, in("al") bar);
+ | ------------- ^^^^^^^^^^^^ register `al`
+ | |
+ | register `ax`
+
+error: register `ax` conflicts with register `ax`
+ --> $DIR/bad-reg.rs:59:33
+ |
+LL | asm!("", in("rax") foo, out("rax") bar);
+ | ------------- ^^^^^^^^^^^^^^ register `ax`
+ | |
+ | register `ax`
+ |
+help: use `lateout` instead of `out` to avoid conflict
+ --> $DIR/bad-reg.rs:59:18
+ |
+LL | asm!("", in("rax") foo, out("rax") bar);
+ | ^^^^^^^^^^^^^
+
+error: register `ymm0` conflicts with register `xmm0`
+ --> $DIR/bad-reg.rs:62:34
+ |
+LL | asm!("", in("xmm0") foo, in("ymm0") bar);
+ | -------------- ^^^^^^^^^^^^^^ register `ymm0`
+ | |
+ | register `xmm0`
+
+error: register `ymm0` conflicts with register `xmm0`
+ --> $DIR/bad-reg.rs:64:34
+ |
+LL | asm!("", in("xmm0") foo, out("ymm0") bar);
+ | -------------- ^^^^^^^^^^^^^^^ register `ymm0`
+ | |
+ | register `xmm0`
+ |
+help: use `lateout` instead of `out` to avoid conflict
+ --> $DIR/bad-reg.rs:64:18
+ |
+LL | asm!("", in("xmm0") foo, out("ymm0") bar);
+ | ^^^^^^^^^^^^^^
+
+error: aborting due to 23 previous errors
+
--- /dev/null
+// min-llvm-version: 10.0.1
+// only-x86_64
+// run-pass
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(asm, global_asm)]
+
+fn const_generic<const X: usize>() -> usize {
+ unsafe {
+ let a: usize;
+ asm!("mov {}, {}", out(reg) a, const X);
+ a
+ }
+}
+
+const fn constfn(x: usize) -> usize {
+ x
+}
+
+fn main() {
+ unsafe {
+ let a: usize;
+ asm!("mov {}, {}", out(reg) a, const 5);
+ assert_eq!(a, 5);
+
+ let b: usize;
+ asm!("mov {}, {}", out(reg) b, const constfn(5));
+ assert_eq!(b, 5);
+
+ let c: usize;
+ asm!("mov {}, {}", out(reg) c, const constfn(5) + constfn(5));
+ assert_eq!(c, 10);
+ }
+
+ let d = const_generic::<5>();
+ assert_eq!(d, 5);
+}
+
+global_asm!("mov eax, {}", const 5);
+global_asm!("mov eax, {}", const constfn(5));
+global_asm!("mov eax, {}", const constfn(5) + constfn(5));
--- /dev/null
+// only-x86_64
+// run-rustfix
+
+#![feature(asm, global_asm)]
+
+fn main() {
+ unsafe {
+ asm!("", options(nomem, ));
+ //~^ ERROR the `nomem` option was already provided
+ asm!("", options(att_syntax, ));
+ //~^ ERROR the `att_syntax` option was already provided
+ asm!("", options(nostack, att_syntax), options());
+ //~^ ERROR the `nostack` option was already provided
+ asm!("", options(nostack, ), options(), options());
+ //~^ ERROR the `nostack` option was already provided
+ //~| ERROR the `nostack` option was already provided
+ //~| ERROR the `nostack` option was already provided
+ asm!(
+ "",
+ options(nomem, noreturn),
+ options(att_syntax, ), //~ ERROR the `noreturn` option was already provided
+ options( nostack), //~ ERROR the `nomem` option was already provided
+ options(), //~ ERROR the `noreturn` option was already provided
+ );
+ }
+}
+
+global_asm!("", options(att_syntax, ));
+//~^ ERROR the `att_syntax` option was already provided
--- /dev/null
+// only-x86_64
+// run-rustfix
+
+#![feature(asm, global_asm)]
+
+fn main() {
+ unsafe {
+ asm!("", options(nomem, nomem));
+ //~^ ERROR the `nomem` option was already provided
+ asm!("", options(att_syntax, att_syntax));
+ //~^ ERROR the `att_syntax` option was already provided
+ asm!("", options(nostack, att_syntax), options(nostack));
+ //~^ ERROR the `nostack` option was already provided
+ asm!("", options(nostack, nostack), options(nostack), options(nostack));
+ //~^ ERROR the `nostack` option was already provided
+ //~| ERROR the `nostack` option was already provided
+ //~| ERROR the `nostack` option was already provided
+ asm!(
+ "",
+ options(nomem, noreturn),
+ options(att_syntax, noreturn), //~ ERROR the `noreturn` option was already provided
+ options(nomem, nostack), //~ ERROR the `nomem` option was already provided
+ options(noreturn), //~ ERROR the `noreturn` option was already provided
+ );
+ }
+}
+
+global_asm!("", options(att_syntax, att_syntax));
+//~^ ERROR the `att_syntax` option was already provided
--- /dev/null
+error: the `nomem` option was already provided
+ --> $DIR/duplicate-options.rs:8:33
+ |
+LL | asm!("", options(nomem, nomem));
+ | ^^^^^ this option was already provided
+
+error: the `att_syntax` option was already provided
+ --> $DIR/duplicate-options.rs:10:38
+ |
+LL | asm!("", options(att_syntax, att_syntax));
+ | ^^^^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:12:56
+ |
+LL | asm!("", options(nostack, att_syntax), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:14:35
+ |
+LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:14:53
+ |
+LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `nostack` option was already provided
+ --> $DIR/duplicate-options.rs:14:71
+ |
+LL | asm!("", options(nostack, nostack), options(nostack), options(nostack));
+ | ^^^^^^^ this option was already provided
+
+error: the `noreturn` option was already provided
+ --> $DIR/duplicate-options.rs:21:33
+ |
+LL | options(att_syntax, noreturn),
+ | ^^^^^^^^ this option was already provided
+
+error: the `nomem` option was already provided
+ --> $DIR/duplicate-options.rs:22:21
+ |
+LL | options(nomem, nostack),
+ | ^^^^^ this option was already provided
+
+error: the `noreturn` option was already provided
+ --> $DIR/duplicate-options.rs:23:21
+ |
+LL | options(noreturn),
+ | ^^^^^^^^ this option was already provided
+
+error: the `att_syntax` option was already provided
+ --> $DIR/duplicate-options.rs:28:37
+ |
+LL | global_asm!("", options(att_syntax, att_syntax));
+ | ^^^^^^^^^^ this option was already provided
+
+error: aborting due to 10 previous errors
+
--- /dev/null
+// only-x86_64
+
+#![feature(asm)]
+
+macro_rules! m {
+ ($in:ident $out:ident $lateout:ident $inout:ident $inlateout:ident $const:ident $sym:ident
+ $pure:ident $nomem:ident $readonly:ident $preserves_flags:ident
+ $noreturn:ident $nostack:ident $att_syntax:ident $options:ident) => {
+ unsafe {
+ asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x,
+ //~^ ERROR asm outputs are not allowed with the `noreturn` option
+ const x, sym x,
+ $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax));
+ //~^ ERROR the `nomem` and `readonly` options are mutually exclusive
+ //~| ERROR the `pure` and `noreturn` options are mutually exclusive
+ }
+ };
+}
+
+fn main() {
+ m!(in out lateout inout inlateout const sym
+ pure nomem readonly preserves_flags
+ noreturn nostack att_syntax options);
+}
--- /dev/null
+error: the `nomem` and `readonly` options are mutually exclusive
+ --> $DIR/interpolated-idents.rs:13:13
+ |
+LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | / m!(in out lateout inout inlateout const sym
+LL | | pure nomem readonly preserves_flags
+LL | | noreturn nostack att_syntax options);
+ | |____________________________________________- in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: the `pure` and `noreturn` options are mutually exclusive
+ --> $DIR/interpolated-idents.rs:13:13
+ |
+LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | / m!(in out lateout inout inlateout const sym
+LL | | pure nomem readonly preserves_flags
+LL | | noreturn nostack att_syntax options);
+ | |____________________________________________- in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: asm outputs are not allowed with the `noreturn` option
+ --> $DIR/interpolated-idents.rs:10:32
+ |
+LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x,
+ | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^
+...
+LL | m!(in out lateout inout inlateout const sym
+ | _____-
+ | |_____|
+ | |_____|
+ | |_____|
+ | |
+LL | | pure nomem readonly preserves_flags
+LL | | noreturn nostack att_syntax options);
+ | | -
+ | |____________________________________________|
+ | |____________________________________________in this macro invocation
+ | |____________________________________________in this macro invocation
+ | |____________________________________________in this macro invocation
+ | in this macro invocation
+ |
+ = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
--- /dev/null
+// only-x86_64
+// Make sure rustc doesn't ICE on asm! for a foreign architecture.
+
+#![feature(asm)]
+#![crate_type = "rlib"]
+
+pub unsafe fn aarch64(a: f64, b: f64) -> f64 {
+ let c;
+ asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+ || {};
+ b
+ });
+ //~^^^^ invalid register class
+ //~^^^^^ invalid register class
+ //~^^^^^^ invalid register
+ c
+}
+
+pub unsafe fn x86(a: f64, b: f64) -> f64 {
+ let c;
+ asm!("addsd {}, {}, xmm0", out(xmm_reg) c, in(xmm_reg) a, in("xmm0") b);
+ c
+}
--- /dev/null
+error: invalid register class `vreg`: unknown register class
+ --> $DIR/issue-82869.rs:9:32
+ |
+LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+ | ^^^^^^^^^^^
+
+error: invalid register class `vreg`: unknown register class
+ --> $DIR/issue-82869.rs:9:45
+ |
+LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+ | ^^^^^^^^^^
+
+error: invalid register `d0`: unknown register
+ --> $DIR/issue-82869.rs:9:57
+ |
+LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
+ | _________________________________________________________^
+LL | | || {};
+LL | | b
+LL | | });
+ | |_____^
+
+error: aborting due to 3 previous errors
+
--- /dev/null
+// only-x86_64
+
+#![feature(asm, global_asm)]
+
+fn main() {
+ let mut foo = 0;
+ let mut bar = 0;
+ unsafe {
+ asm!();
+ //~^ ERROR requires at least a template string argument
+ asm!(foo);
+ //~^ ERROR asm template must be a string literal
+ asm!("{}" foo);
+ //~^ ERROR expected token: `,`
+ asm!("{}", foo);
+ //~^ ERROR expected operand, clobber_abi, options, or additional template string
+ asm!("{}", in foo);
+ //~^ ERROR expected `(`, found `foo`
+ asm!("{}", in(reg foo));
+ //~^ ERROR expected `)`, found `foo`
+ asm!("{}", in(reg));
+ //~^ ERROR expected expression, found end of macro arguments
+ asm!("{}", inout(=) foo => bar);
+ //~^ ERROR expected register class or explicit register
+ asm!("{}", inout(reg) foo =>);
+ //~^ ERROR expected expression, found end of macro arguments
+ asm!("{}", in(reg) foo => bar);
+ //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
+ asm!("{}", sym foo + bar);
+ //~^ ERROR argument to `sym` must be a path expression
+ asm!("", options(foo));
+ //~^ ERROR expected one of
+ asm!("", options(nomem foo));
+ //~^ ERROR expected one of
+ asm!("", options(nomem, foo));
+ //~^ ERROR expected one of
+ asm!("{}", options(), const foo);
+ //~^ ERROR arguments are not allowed after options
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("", clobber_abi(foo));
+ //~^ ERROR expected string literal
+ asm!("", clobber_abi("C" foo));
+ //~^ ERROR expected `)`, found `foo`
+ asm!("", clobber_abi("C", foo));
+ //~^ ERROR expected `)`, found `,`
+ asm!("{}", clobber_abi("C"), const foo);
+ //~^ ERROR arguments are not allowed after clobber_abi
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("", options(), clobber_abi("C"));
+ //~^ ERROR clobber_abi is not allowed after options
+ asm!("{}", options(), clobber_abi("C"), const foo);
+ //~^ ERROR clobber_abi is not allowed after options
+ asm!("", clobber_abi("C"), clobber_abi("C"));
+ //~^ ERROR clobber_abi specified multiple times
+ asm!("{a}", a = const foo, a = const bar);
+ //~^ ERROR duplicate argument named `a`
+ //~^^ ERROR argument never used
+ //~^^^ ERROR attempt to use a non-constant value in a constant
+ //~^^^^ ERROR attempt to use a non-constant value in a constant
+ asm!("", a = in("eax") foo);
+ //~^ ERROR explicit register arguments cannot have names
+ asm!("{a}", in("eax") foo, a = const bar);
+ //~^ ERROR named arguments cannot follow explicit register arguments
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("{a}", in("eax") foo, a = const bar);
+ //~^ ERROR named arguments cannot follow explicit register arguments
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("{1}", in("eax") foo, const bar);
+ //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments
+ //~^^ ERROR attempt to use a non-constant value in a constant
+ asm!("", options(), "");
+ //~^ ERROR expected one of
+ asm!("{}", in(reg) foo, "{}", out(reg) foo);
+ //~^ ERROR expected one of
+ asm!(format!("{{{}}}", 0), in(reg) foo);
+ //~^ ERROR asm template must be a string literal
+ asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
+ //~^ ERROR asm template must be a string literal
+ asm!("{}", in(reg) _);
+ //~^ ERROR _ cannot be used for input operands
+ asm!("{}", inout(reg) _);
+ //~^ ERROR _ cannot be used for input operands
+ asm!("{}", inlateout(reg) _);
+ //~^ ERROR _ cannot be used for input operands
+ }
+}
+
+const FOO: i32 = 1;
+const BAR: i32 = 2;
+global_asm!();
+//~^ ERROR requires at least a template string argument
+global_asm!(FOO);
+//~^ ERROR asm template must be a string literal
+global_asm!("{}" FOO);
+//~^ ERROR expected token: `,`
+global_asm!("{}", FOO);
+//~^ ERROR expected operand, options, or additional template string
+global_asm!("{}", const);
+//~^ ERROR expected expression, found end of macro arguments
+global_asm!("{}", const(reg) FOO);
+//~^ ERROR expected one of
+global_asm!("", options(FOO));
+//~^ ERROR expected one of
+global_asm!("", options(nomem FOO));
+//~^ ERROR expected one of
+global_asm!("", options(nomem, FOO));
+//~^ ERROR expected one of
+global_asm!("{}", options(), const FOO);
+//~^ ERROR arguments are not allowed after options
+global_asm!("", clobber_abi(FOO));
+//~^ ERROR expected string literal
+global_asm!("", clobber_abi("C" FOO));
+//~^ ERROR expected `)`, found `FOO`
+global_asm!("", clobber_abi("C", FOO));
+//~^ ERROR expected `)`, found `,`
+global_asm!("{}", clobber_abi("C"), const FOO);
+//~^ ERROR arguments are not allowed after clobber_abi
+//~^^ ERROR `clobber_abi` cannot be used with `global_asm!`
+global_asm!("", options(), clobber_abi("C"));
+//~^ ERROR clobber_abi is not allowed after options
+global_asm!("{}", options(), clobber_abi("C"), const FOO);
+//~^ ERROR clobber_abi is not allowed after options
+global_asm!("", clobber_abi("C"), clobber_abi("C"));
+//~^ ERROR clobber_abi specified multiple times
+global_asm!("{a}", a = const FOO, a = const BAR);
+//~^ ERROR duplicate argument named `a`
+//~^^ ERROR argument never used
+global_asm!("", options(), "");
+//~^ ERROR expected one of
+global_asm!("{}", const FOO, "{}", const FOO);
+//~^ ERROR expected one of
+global_asm!(format!("{{{}}}", 0), const FOO);
+//~^ ERROR asm template must be a string literal
+global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
+//~^ ERROR asm template must be a string literal
--- /dev/null
+error: requires at least a template string argument
+ --> $DIR/parse-error.rs:9:9
+ |
+LL | asm!();
+ | ^^^^^^^
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:11:14
+ |
+LL | asm!(foo);
+ | ^^^
+
+error: expected token: `,`
+ --> $DIR/parse-error.rs:13:19
+ |
+LL | asm!("{}" foo);
+ | ^^^ expected `,`
+
+error: expected operand, clobber_abi, options, or additional template string
+ --> $DIR/parse-error.rs:15:20
+ |
+LL | asm!("{}", foo);
+ | ^^^ expected operand, clobber_abi, options, or additional template string
+
+error: expected `(`, found `foo`
+ --> $DIR/parse-error.rs:17:23
+ |
+LL | asm!("{}", in foo);
+ | ^^^ expected `(`
+
+error: expected `)`, found `foo`
+ --> $DIR/parse-error.rs:19:27
+ |
+LL | asm!("{}", in(reg foo));
+ | ^^^ expected `)`
+
+error: expected expression, found end of macro arguments
+ --> $DIR/parse-error.rs:21:27
+ |
+LL | asm!("{}", in(reg));
+ | ^ expected expression
+
+error: expected register class or explicit register
+ --> $DIR/parse-error.rs:23:26
+ |
+LL | asm!("{}", inout(=) foo => bar);
+ | ^
+
+error: expected expression, found end of macro arguments
+ --> $DIR/parse-error.rs:25:37
+ |
+LL | asm!("{}", inout(reg) foo =>);
+ | ^ expected expression
+
+error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
+ --> $DIR/parse-error.rs:27:32
+ |
+LL | asm!("{}", in(reg) foo => bar);
+ | ^^ expected one of 7 possible tokens
+
+error: argument to `sym` must be a path expression
+ --> $DIR/parse-error.rs:29:24
+ |
+LL | asm!("{}", sym foo + bar);
+ | ^^^^^^^^^
+
+error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
+ --> $DIR/parse-error.rs:31:26
+ |
+LL | asm!("", options(foo));
+ | ^^^ expected one of 9 possible tokens
+
+error: expected one of `)` or `,`, found `foo`
+ --> $DIR/parse-error.rs:33:32
+ |
+LL | asm!("", options(nomem foo));
+ | ^^^ expected one of `)` or `,`
+
+error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
+ --> $DIR/parse-error.rs:35:33
+ |
+LL | asm!("", options(nomem, foo));
+ | ^^^ expected one of 9 possible tokens
+
+error: arguments are not allowed after options
+ --> $DIR/parse-error.rs:37:31
+ |
+LL | asm!("{}", options(), const foo);
+ | --------- ^^^^^^^^^ argument
+ | |
+ | previous options
+
+error: expected string literal
+ --> $DIR/parse-error.rs:40:30
+ |
+LL | asm!("", clobber_abi(foo));
+ | ^^^ not a string literal
+
+error: expected `)`, found `foo`
+ --> $DIR/parse-error.rs:42:34
+ |
+LL | asm!("", clobber_abi("C" foo));
+ | ^^^ expected `)`
+
+error: expected `)`, found `,`
+ --> $DIR/parse-error.rs:44:33
+ |
+LL | asm!("", clobber_abi("C", foo));
+ | ^ expected `)`
+
+error: arguments are not allowed after clobber_abi
+ --> $DIR/parse-error.rs:46:38
+ |
+LL | asm!("{}", clobber_abi("C"), const foo);
+ | ---------------- ^^^^^^^^^ argument
+ | |
+ | clobber_abi
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:49:29
+ |
+LL | asm!("", options(), clobber_abi("C"));
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:51:31
+ |
+LL | asm!("{}", options(), clobber_abi("C"), const foo);
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: clobber_abi specified multiple times
+ --> $DIR/parse-error.rs:53:36
+ |
+LL | asm!("", clobber_abi("C"), clobber_abi("C"));
+ | ---------------- ^^^^^^^^^^^^^^^^
+ | |
+ | clobber_abi previously specified here
+
+error: duplicate argument named `a`
+ --> $DIR/parse-error.rs:55:36
+ |
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ------------- ^^^^^^^^^^^^^ duplicate argument
+ | |
+ | previously here
+
+error: argument never used
+ --> $DIR/parse-error.rs:55:36
+ |
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ^^^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
+
+error: explicit register arguments cannot have names
+ --> $DIR/parse-error.rs:60:18
+ |
+LL | asm!("", a = in("eax") foo);
+ | ^^^^^^^^^^^^^^^^^
+
+error: named arguments cannot follow explicit register arguments
+ --> $DIR/parse-error.rs:62:36
+ |
+LL | asm!("{a}", in("eax") foo, a = const bar);
+ | ------------- ^^^^^^^^^^^^^ named argument
+ | |
+ | explicit register argument
+
+error: named arguments cannot follow explicit register arguments
+ --> $DIR/parse-error.rs:65:36
+ |
+LL | asm!("{a}", in("eax") foo, a = const bar);
+ | ------------- ^^^^^^^^^^^^^ named argument
+ | |
+ | explicit register argument
+
+error: positional arguments cannot follow named arguments or explicit register arguments
+ --> $DIR/parse-error.rs:68:36
+ |
+LL | asm!("{1}", in("eax") foo, const bar);
+ | ------------- ^^^^^^^^^ positional argument
+ | |
+ | explicit register argument
+
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""`
+ --> $DIR/parse-error.rs:71:29
+ |
+LL | asm!("", options(), "");
+ | ^^ expected one of 9 possible tokens
+
+error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
+ --> $DIR/parse-error.rs:73:33
+ |
+LL | asm!("{}", in(reg) foo, "{}", out(reg) foo);
+ | ^^^^ expected one of 9 possible tokens
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:75:14
+ |
+LL | asm!(format!("{{{}}}", 0), in(reg) foo);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:77:21
+ |
+LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:79:28
+ |
+LL | asm!("{}", in(reg) _);
+ | ^
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:81:31
+ |
+LL | asm!("{}", inout(reg) _);
+ | ^
+
+error: _ cannot be used for input operands
+ --> $DIR/parse-error.rs:83:35
+ |
+LL | asm!("{}", inlateout(reg) _);
+ | ^
+
+error: requires at least a template string argument
+ --> $DIR/parse-error.rs:90:1
+ |
+LL | global_asm!();
+ | ^^^^^^^^^^^^^^
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:92:13
+ |
+LL | global_asm!(FOO);
+ | ^^^
+
+error: expected token: `,`
+ --> $DIR/parse-error.rs:94:18
+ |
+LL | global_asm!("{}" FOO);
+ | ^^^ expected `,`
+
+error: expected operand, options, or additional template string
+ --> $DIR/parse-error.rs:96:19
+ |
+LL | global_asm!("{}", FOO);
+ | ^^^ expected operand, options, or additional template string
+
+error: expected expression, found end of macro arguments
+ --> $DIR/parse-error.rs:98:24
+ |
+LL | global_asm!("{}", const);
+ | ^ expected expression
+
+error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
+ --> $DIR/parse-error.rs:100:30
+ |
+LL | global_asm!("{}", const(reg) FOO);
+ | ^^^ expected one of `,`, `.`, `?`, or an operator
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
+ --> $DIR/parse-error.rs:102:25
+ |
+LL | global_asm!("", options(FOO));
+ | ^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+ --> $DIR/parse-error.rs:104:25
+ |
+LL | global_asm!("", options(nomem FOO));
+ | ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
+ --> $DIR/parse-error.rs:106:25
+ |
+LL | global_asm!("", options(nomem, FOO));
+ | ^^^^^ expected one of `)`, `att_syntax`, or `raw`
+
+error: arguments are not allowed after options
+ --> $DIR/parse-error.rs:108:30
+ |
+LL | global_asm!("{}", options(), const FOO);
+ | --------- ^^^^^^^^^ argument
+ | |
+ | previous options
+
+error: expected string literal
+ --> $DIR/parse-error.rs:110:29
+ |
+LL | global_asm!("", clobber_abi(FOO));
+ | ^^^ not a string literal
+
+error: expected `)`, found `FOO`
+ --> $DIR/parse-error.rs:112:33
+ |
+LL | global_asm!("", clobber_abi("C" FOO));
+ | ^^^ expected `)`
+
+error: expected `)`, found `,`
+ --> $DIR/parse-error.rs:114:32
+ |
+LL | global_asm!("", clobber_abi("C", FOO));
+ | ^ expected `)`
+
+error: arguments are not allowed after clobber_abi
+ --> $DIR/parse-error.rs:116:37
+ |
+LL | global_asm!("{}", clobber_abi("C"), const FOO);
+ | ---------------- ^^^^^^^^^ argument
+ | |
+ | clobber_abi
+
+error: `clobber_abi` cannot be used with `global_asm!`
+ --> $DIR/parse-error.rs:116:19
+ |
+LL | global_asm!("{}", clobber_abi("C"), const FOO);
+ | ^^^^^^^^^^^^^^^^
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:119:28
+ |
+LL | global_asm!("", options(), clobber_abi("C"));
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: clobber_abi is not allowed after options
+ --> $DIR/parse-error.rs:121:30
+ |
+LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
+ | --------- ^^^^^^^^^^^^^^^^
+ | |
+ | options
+
+error: clobber_abi specified multiple times
+ --> $DIR/parse-error.rs:123:35
+ |
+LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
+ | ---------------- ^^^^^^^^^^^^^^^^
+ | |
+ | clobber_abi previously specified here
+
+error: duplicate argument named `a`
+ --> $DIR/parse-error.rs:125:35
+ |
+LL | global_asm!("{a}", a = const FOO, a = const BAR);
+ | ------------- ^^^^^^^^^^^^^ duplicate argument
+ | |
+ | previously here
+
+error: argument never used
+ --> $DIR/parse-error.rs:125:35
+ |
+LL | global_asm!("{a}", a = const FOO, a = const BAR);
+ | ^^^^^^^^^^^^^ argument never used
+ |
+ = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
+
+error: expected one of `clobber_abi`, `const`, or `options`, found `""`
+ --> $DIR/parse-error.rs:128:28
+ |
+LL | global_asm!("", options(), "");
+ | ^^ expected one of `clobber_abi`, `const`, or `options`
+
+error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"`
+ --> $DIR/parse-error.rs:130:30
+ |
+LL | global_asm!("{}", const FOO, "{}", const FOO);
+ | ^^^^ expected one of `clobber_abi`, `const`, or `options`
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:132:13
+ |
+LL | global_asm!(format!("{{{}}}", 0), const FOO);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: asm template must be a string literal
+ --> $DIR/parse-error.rs:134:20
+ |
+LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:37:37
+ |
+LL | let mut foo = 0;
+ | ---------- help: consider using `const` instead of `let`: `const foo`
+...
+LL | asm!("{}", options(), const foo);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:46:44
+ |
+LL | let mut foo = 0;
+ | ---------- help: consider using `const` instead of `let`: `const foo`
+...
+LL | asm!("{}", clobber_abi("C"), const foo);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:55:31
+ |
+LL | let mut foo = 0;
+ | ---------- help: consider using `const` instead of `let`: `const foo`
+...
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:55:46
+ |
+LL | let mut bar = 0;
+ | ---------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{a}", a = const foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:62:46
+ |
+LL | let mut bar = 0;
+ | ---------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{a}", in("eax") foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:65:46
+ |
+LL | let mut bar = 0;
+ | ---------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{a}", in("eax") foo, a = const bar);
+ | ^^^ non-constant value
+
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/parse-error.rs:68:42
+ |
+LL | let mut bar = 0;
+ | ---------- help: consider using `const` instead of `let`: `const bar`
+...
+LL | asm!("{1}", in("eax") foo, const bar);
+ | ^^^ non-constant value
+
+error: aborting due to 66 previous errors
+
+For more information about this error, try `rustc --explain E0435`.
--- /dev/null
+// min-llvm-version: 10.0.1
+// only-x86_64
+// build-fail
+// compile-flags: -Ccodegen-units=1
+#![feature(asm)]
+
+// Checks that inline asm errors are mapped to the correct line in the source code.
+
+fn main() {
+ unsafe {
+ asm!("invalid_instruction");
+ //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!("
+ invalid_instruction
+ ");
+ //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(r#"
+ invalid_instruction
+ "#);
+ //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!("
+ mov eax, eax
+ invalid_instruction
+ mov eax, eax
+ ");
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(r#"
+ mov eax, eax
+ invalid_instruction
+ mov eax, eax
+ "#);
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(concat!("invalid", "_", "instruction"));
+ //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
+ //~^ WARN: scale factor without index register is ignored
+
+ asm!(
+ "invalid_instruction",
+ );
+ //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(
+ "mov eax, eax",
+ "invalid_instruction",
+ "mov eax, eax",
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(
+ "mov eax, eax\n",
+ "invalid_instruction",
+ "mov eax, eax",
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(
+ "mov eax, eax",
+ concat!("invalid", "_", "instruction"),
+ "mov eax, eax",
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ asm!(
+ concat!("mov eax", ", ", "eax"),
+ concat!("invalid", "_", "instruction"),
+ concat!("mov eax", ", ", "eax"),
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+ // Make sure template strings get separated
+ asm!(
+ "invalid_instruction1",
+ "invalid_instruction2",
+ );
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
+ //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2",
+ ),
+ );
+ //~^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
+ //~^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2",
+ ),
+ concat!(
+ "invalid", "_", "instruction3", "\n",
+ "invalid", "_", "instruction4",
+ ),
+ );
+ //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
+ //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
+ //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3'
+ //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4'
+
+ asm!(
+ concat!(
+ "invalid", "_", "instruction1", "\n",
+ "invalid", "_", "instruction2", "\n",
+ ),
+ concat!(
+ "invalid", "_", "instruction3", "\n",
+ "invalid", "_", "instruction4", "\n",
+ ),
+ );
+ //~^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction1'
+ //~^^^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction2'
+ //~^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction3'
+ //~^^^^^^^^ ERROR: invalid instruction mnemonic 'invalid_instruction4'
+ }
+}
--- /dev/null
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:11:15
+ |
+LL | asm!("invalid_instruction");
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:15:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:13
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:20:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:13
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:26:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:13
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:33:13
+ |
+LL | invalid_instruction
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:13
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:38:14
+ |
+LL | asm!(concat!("invalid", "_", "instruction"));
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+warning: scale factor without index register is ignored
+ --> $DIR/srcloc.rs:41:15
+ |
+LL | asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:23
+ |
+LL | movaps %xmm3, (%esi, 2)
+ | ^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:45:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:51:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:58:14
+ |
+LL | "invalid_instruction",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:65:13
+ |
+LL | concat!("invalid", "_", "instruction"),
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+ --> $DIR/srcloc.rs:72:13
+ |
+LL | concat!("invalid", "_", "instruction"),
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+ --> $DIR/srcloc.rs:79:14
+ |
+LL | "invalid_instruction1",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction1
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+ --> $DIR/srcloc.rs:80:14
+ |
+LL | "invalid_instruction2",
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction2
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+ --> $DIR/srcloc.rs:86:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction1
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+ --> $DIR/srcloc.rs:86:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction2
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+ --> $DIR/srcloc.rs:95:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction1
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+ --> $DIR/srcloc.rs:95:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction2
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction3'
+ --> $DIR/srcloc.rs:99:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:4:1
+ |
+LL | invalid_instruction3
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction4'
+ --> $DIR/srcloc.rs:99:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:5:1
+ |
+LL | invalid_instruction4
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction1'
+ --> $DIR/srcloc.rs:110:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:2:2
+ |
+LL | invalid_instruction1
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction2'
+ --> $DIR/srcloc.rs:110:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:3:1
+ |
+LL | invalid_instruction2
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction3'
+ --> $DIR/srcloc.rs:114:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:5:1
+ |
+LL | invalid_instruction3
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction4'
+ --> $DIR/srcloc.rs:114:13
+ |
+LL | concat!(
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:6:1
+ |
+LL | invalid_instruction4
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 23 previous errors; 1 warning emitted
+
--- /dev/null
+// min-llvm-version: 10.0.1
+// only-x86_64
+// only-linux
+// run-pass
+
+#![feature(asm, thread_local)]
+
+extern "C" fn f1() -> i32 {
+ 111
+}
+
+// The compiler will generate a shim to hide the caller location parameter.
+#[track_caller]
+fn f2() -> i32 {
+ 222
+}
+
+macro_rules! call {
+ ($func:path) => {
+ unsafe {
+ let result: i32;
+ asm!("call {}", sym $func,
+ out("rax") result,
+ out("rcx") _, out("rdx") _, out("rdi") _, out("rsi") _,
+ out("r8") _, out("r9") _, out("r10") _, out("r11") _,
+ out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _,
+ out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _,
+ out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,
+ out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,
+ );
+ result
+ }
+ }
+}
+
+macro_rules! static_addr {
+ ($s:expr) => {
+ unsafe {
+ let result: *const u32;
+ // LEA performs a RIP-relative address calculation and returns the address
+ asm!("lea {}, [rip + {}]", out(reg) result, sym $s);
+ result
+ }
+ }
+}
+macro_rules! static_tls_addr {
+ ($s:expr) => {
+ unsafe {
+ let result: *const u32;
+ asm!(
+ "
+ # Load TLS base address
+ mov {out}, qword ptr fs:[0]
+ # Calculate the address of sym in the TLS block. The @tpoff
+ # relocation gives the offset of the symbol from the start
+ # of the TLS block.
+ lea {out}, [{out} + {sym}@tpoff]
+ ",
+ out = out(reg) result,
+ sym = sym $s
+ );
+ result
+ }
+ }
+}
+
+static S1: u32 = 111;
+#[thread_local]
+static S2: u32 = 222;
+
+fn main() {
+ assert_eq!(call!(f1), 111);
+ assert_eq!(call!(f2), 222);
+ assert_eq!(static_addr!(S1), &S1 as *const u32);
+ assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
+ std::thread::spawn(|| {
+ assert_eq!(static_addr!(S1), &S1 as *const u32);
+ assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
+ }).join().unwrap();
+}
--- /dev/null
+// only-x86_64
+
+#![feature(asm, repr_simd, never_type)]
+
+#[repr(simd)]
+struct SimdNonCopy(f32, f32, f32, f32);
+
+fn main() {
+ unsafe {
+ // Inputs must be initialized
+
+ let x: u64;
+ asm!("{}", in(reg) x);
+ //~^ ERROR use of possibly-uninitialized variable: `x`
+ let mut y: u64;
+ asm!("{}", inout(reg) y);
+ //~^ ERROR use of possibly-uninitialized variable: `y`
+ let _ = y;
+
+ // Outputs require mutable places
+
+ let v: Vec<u64> = vec![0, 1, 2];
+ asm!("{}", in(reg) v[0]);
+ asm!("{}", out(reg) v[0]);
+ //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+ asm!("{}", inout(reg) v[0]);
+ //~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
+
+ // Sym operands must point to a function or static
+
+ const C: i32 = 0;
+ static S: i32 = 0;
+ asm!("{}", sym S);
+ asm!("{}", sym main);
+ asm!("{}", sym C);
+ //~^ ERROR asm `sym` operand must point to a fn or static
+ asm!("{}", sym x);
+ //~^ ERROR asm `sym` operand must point to a fn or static
+
+ // Register operands must be Copy
+
+ asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
+ //~^ ERROR arguments for inline assembly must be copyable
+
+ // Register operands must be integers, floats, SIMD vectors, pointers or
+ // function pointers.
+
+ asm!("{}", in(reg) 0i64);
+ asm!("{}", in(reg) 0f64);
+ asm!("{}", in(xmm_reg) std::arch::x86_64::_mm_setzero_ps());
+ asm!("{}", in(reg) 0 as *const u8);
+ asm!("{}", in(reg) 0 as *mut u8);
+ asm!("{}", in(reg) main as fn());
+ asm!("{}", in(reg) |x: i32| x);
+ //~^ ERROR cannot use value of type
+ asm!("{}", in(reg) vec![0]);
+ //~^ ERROR cannot use value of type `Vec<i32>` for inline assembly
+ asm!("{}", in(reg) (1, 2, 3));
+ //~^ ERROR cannot use value of type `(i32, i32, i32)` for inline assembly
+ asm!("{}", in(reg) [1, 2, 3]);
+ //~^ ERROR cannot use value of type `[i32; 3]` for inline assembly
+
+ // Register inputs (but not outputs) allow references and function types
+
+ let mut f = main;
+ let mut r = &mut 0;
+ asm!("{}", in(reg) f);
+ asm!("{}", inout(reg) f);
+ //~^ ERROR cannot use value of type `fn() {main}` for inline assembly
+ asm!("{}", in(reg) r);
+ asm!("{}", inout(reg) r);
+ //~^ ERROR cannot use value of type `&mut i32` for inline assembly
+ let _ = (f, r);
+
+ // Type checks ignore never type
+
+ let u: ! = unreachable!();
+ asm!("{}", in(reg) u);
+ }
+}
--- /dev/null
+error: arguments for inline assembly must be copyable
+ --> $DIR/type-check-2.rs:42:32
+ |
+LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `SimdNonCopy` does not implement the Copy trait
+
+error: cannot use value of type `[closure@$DIR/type-check-2.rs:54:28: 54:38]` for inline assembly
+ --> $DIR/type-check-2.rs:54:28
+ |
+LL | asm!("{}", in(reg) |x: i32| x);
+ | ^^^^^^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `Vec<i32>` for inline assembly
+ --> $DIR/type-check-2.rs:56:28
+ |
+LL | asm!("{}", in(reg) vec![0]);
+ | ^^^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+ = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: cannot use value of type `(i32, i32, i32)` for inline assembly
+ --> $DIR/type-check-2.rs:58:28
+ |
+LL | asm!("{}", in(reg) (1, 2, 3));
+ | ^^^^^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `[i32; 3]` for inline assembly
+ --> $DIR/type-check-2.rs:60:28
+ |
+LL | asm!("{}", in(reg) [1, 2, 3]);
+ | ^^^^^^^^^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `fn() {main}` for inline assembly
+ --> $DIR/type-check-2.rs:68:31
+ |
+LL | asm!("{}", inout(reg) f);
+ | ^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: cannot use value of type `&mut i32` for inline assembly
+ --> $DIR/type-check-2.rs:71:31
+ |
+LL | asm!("{}", inout(reg) r);
+ | ^
+ |
+ = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
+
+error: asm `sym` operand must point to a fn or static
+ --> $DIR/type-check-2.rs:35:24
+ |
+LL | asm!("{}", sym C);
+ | ^
+
+error: asm `sym` operand must point to a fn or static
+ --> $DIR/type-check-2.rs:37:24
+ |
+LL | asm!("{}", sym x);
+ | ^
+
+error[E0381]: use of possibly-uninitialized variable: `x`
+ --> $DIR/type-check-2.rs:13:28
+ |
+LL | asm!("{}", in(reg) x);
+ | ^ use of possibly-uninitialized `x`
+
+error[E0381]: use of possibly-uninitialized variable: `y`
+ --> $DIR/type-check-2.rs:16:9
+ |
+LL | asm!("{}", inout(reg) y);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+ --> $DIR/type-check-2.rs:24:29
+ |
+LL | let v: Vec<u64> = vec![0, 1, 2];
+ | - help: consider changing this to be mutable: `mut v`
+LL | asm!("{}", in(reg) v[0]);
+LL | asm!("{}", out(reg) v[0]);
+ | ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
+ --> $DIR/type-check-2.rs:26:31
+ |
+LL | let v: Vec<u64> = vec![0, 1, 2];
+ | - help: consider changing this to be mutable: `mut v`
+...
+LL | asm!("{}", inout(reg) v[0]);
+ | ^ cannot borrow as mutable
+
+error: aborting due to 13 previous errors
+
+Some errors have detailed explanations: E0381, E0596.
+For more information about an error, try `rustc --explain E0381`.
--- /dev/null
+// only-x86_64
+// compile-flags: -C target-feature=+avx512f
+
+#![feature(asm, global_asm)]
+
+use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
+
+fn main() {
+ unsafe {
+ // Types must be listed in the register class.
+
+ asm!("{}", in(reg) 0i128);
+ //~^ ERROR type `i128` cannot be used with this register class
+ asm!("{}", in(reg) _mm_setzero_ps());
+ //~^ ERROR type `__m128` cannot be used with this register class
+ asm!("{}", in(reg) _mm256_setzero_ps());
+ //~^ ERROR type `__m256` cannot be used with this register class
+ asm!("{}", in(xmm_reg) 0u8);
+ //~^ ERROR type `u8` cannot be used with this register class
+ asm!("{:e}", in(reg) 0i32);
+ asm!("{}", in(xmm_reg) 0i32);
+ asm!("{:e}", in(reg) 0f32);
+ asm!("{}", in(xmm_reg) 0f32);
+ asm!("{}", in(xmm_reg) _mm_setzero_ps());
+ asm!("{:x}", in(ymm_reg) _mm_setzero_ps());
+ asm!("{}", in(kreg) 0u16);
+ asm!("{}", in(kreg) 0u64);
+ //~^ ERROR `avx512bw` target feature is not enabled
+
+ // Template modifier suggestions for sub-registers
+
+ asm!("{0} {0}", in(reg) 0i16);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{0} {0:x}", in(reg) 0i16);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(reg) 0i32);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(reg) 0i64);
+ asm!("{}", in(ymm_reg) 0i64);
+ //~^ WARN formatting may not be suitable for sub-register argument
+ asm!("{}", in(ymm_reg) _mm256_setzero_ps());
+ asm!("{:l}", in(reg) 0i16);
+ asm!("{:l}", in(reg) 0i32);
+ asm!("{:l}", in(reg) 0i64);
+ asm!("{:x}", in(ymm_reg) 0i64);
+ asm!("{:x}", in(ymm_reg) _mm256_setzero_ps());
+
+ // Suggest different register class for type
+
+ asm!("{}", in(reg) 0i8);
+ //~^ ERROR type `i8` cannot be used with this register class
+ asm!("{}", in(reg_byte) 0i8);
+
+ // Split inout operands must have compatible types
+
+ let mut val_i16: i16;
+ let mut val_f32: f32;
+ let mut val_u32: u32;
+ let mut val_u64: u64;
+ let mut val_ptr: *mut u8;
+ asm!("{:r}", inout(reg) 0u16 => val_i16);
+ asm!("{:r}", inout(reg) 0u32 => val_f32);
+ //~^ ERROR incompatible types for asm inout argument
+ asm!("{:r}", inout(reg) 0u32 => val_ptr);
+ //~^ ERROR incompatible types for asm inout argument
+ asm!("{:r}", inout(reg) main => val_u32);
+ //~^ ERROR incompatible types for asm inout argument
+ asm!("{:r}", inout(reg) 0u64 => val_ptr);
+ asm!("{:r}", inout(reg) main => val_u64);
+ }
+}
+
+// Constants must be... constant
+
+static S: i32 = 1;
+const fn const_foo(x: i32) -> i32 {
+ x
+}
+const fn const_bar<T>(x: T) -> T {
+ x
+}
+global_asm!("{}", const S);
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_foo(0));
+global_asm!("{}", const const_foo(S));
+//~^ ERROR constants cannot refer to statics
+global_asm!("{}", const const_bar(0));
+global_asm!("{}", const const_bar(S));
+//~^ ERROR constants cannot refer to statics
--- /dev/null
+error: type `i128` cannot be used with this register class
+ --> $DIR/type-check-3.rs:12:28
+ |
+LL | asm!("{}", in(reg) 0i128);
+ | ^^^^^
+ |
+ = note: register class `reg` supports these types: i16, i32, i64, f32, f64
+
+error: type `__m128` cannot be used with this register class
+ --> $DIR/type-check-3.rs:14:28
+ |
+LL | asm!("{}", in(reg) _mm_setzero_ps());
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: register class `reg` supports these types: i16, i32, i64, f32, f64
+
+error: type `__m256` cannot be used with this register class
+ --> $DIR/type-check-3.rs:16:28
+ |
+LL | asm!("{}", in(reg) _mm256_setzero_ps());
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: register class `reg` supports these types: i16, i32, i64, f32, f64
+
+error: type `u8` cannot be used with this register class
+ --> $DIR/type-check-3.rs:18:32
+ |
+LL | asm!("{}", in(xmm_reg) 0u8);
+ | ^^^
+ |
+ = note: register class `xmm_reg` supports these types: i32, i64, f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
+
+error: `avx512bw` target feature is not enabled
+ --> $DIR/type-check-3.rs:27:29
+ |
+LL | asm!("{}", in(kreg) 0u64);
+ | ^^^^
+ |
+ = note: this is required to use type `u64` with register class `kreg`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:32:15
+ |
+LL | asm!("{0} {0}", in(reg) 0i16);
+ | ^^^ ^^^ ---- for this argument
+ |
+ = note: `#[warn(asm_sub_register)]` on by default
+ = help: use the `x` modifier to have the register formatted as `ax`
+ = help: or use the `r` modifier to keep the default formatting of `rax`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:34:15
+ |
+LL | asm!("{0} {0:x}", in(reg) 0i16);
+ | ^^^ ---- for this argument
+ |
+ = help: use the `x` modifier to have the register formatted as `ax`
+ = help: or use the `r` modifier to keep the default formatting of `rax`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:36:15
+ |
+LL | asm!("{}", in(reg) 0i32);
+ | ^^ ---- for this argument
+ |
+ = help: use the `e` modifier to have the register formatted as `eax`
+ = help: or use the `r` modifier to keep the default formatting of `rax`
+
+warning: formatting may not be suitable for sub-register argument
+ --> $DIR/type-check-3.rs:39:15
+ |
+LL | asm!("{}", in(ymm_reg) 0i64);
+ | ^^ ---- for this argument
+ |
+ = help: use the `x` modifier to have the register formatted as `xmm0`
+ = help: or use the `y` modifier to keep the default formatting of `ymm0`
+
+error: type `i8` cannot be used with this register class
+ --> $DIR/type-check-3.rs:50:28
+ |
+LL | asm!("{}", in(reg) 0i8);
+ | ^^^
+ |
+ = note: register class `reg` supports these types: i16, i32, i64, f32, f64
+ = help: consider using the `reg_byte` register class instead
+
+error: incompatible types for asm inout argument
+ --> $DIR/type-check-3.rs:62:33
+ |
+LL | asm!("{:r}", inout(reg) 0u32 => val_f32);
+ | ^^^^ ^^^^^^^ type `f32`
+ | |
+ | type `u32`
+ |
+ = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
+
+error: incompatible types for asm inout argument
+ --> $DIR/type-check-3.rs:64:33
+ |
+LL | asm!("{:r}", inout(reg) 0u32 => val_ptr);
+ | ^^^^ ^^^^^^^ type `*mut u8`
+ | |
+ | type `u32`
+ |
+ = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
+
+error: incompatible types for asm inout argument
+ --> $DIR/type-check-3.rs:66:33
+ |
+LL | asm!("{:r}", inout(reg) main => val_u32);
+ | ^^^^ ^^^^^^^ type `u32`
+ | |
+ | type `fn()`
+ |
+ = note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
+
+error[E0013]: constants cannot refer to statics
+ --> $DIR/type-check-3.rs:82:25
+ |
+LL | global_asm!("{}", const S);
+ | ^
+ |
+ = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+ --> $DIR/type-check-3.rs:85:35
+ |
+LL | global_asm!("{}", const const_foo(S));
+ | ^
+ |
+ = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0013]: constants cannot refer to statics
+ --> $DIR/type-check-3.rs:88:35
+ |
+LL | global_asm!("{}", const const_bar(S));
+ | ^
+ |
+ = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error: aborting due to 12 previous errors; 4 warnings emitted
+
+For more information about this error, try `rustc --explain E0013`.
// check-pass
-// compile-flags:-Cincremental=tmp/traits-assoc-type-macros
+// incremental
// This test case makes sure that we can compile with incremental compilation
// enabled when there are macros, traits, inheritance and associated types involved.
// run-pass
-#![feature(box_syntax)]
fn pairwise_sub(mut t: Box<dyn DoubleEndedIterator<Item=isize>>) -> isize {
let mut result = 0;
// edition:2018
-// compile-flags:-Cincremental=tmp/issue-72442
+// incremental
use std::fs::File;
use std::future::Future;
// check-pass
-// compile-flags: -Z query-dep-graph -C incremental=tmp/issue-64964
+// incremental
+// compile-flags: -Z query-dep-graph
// edition:2018
// Regression test for ICE related to `await`ing in a method + incr. comp. (#64964)
//~^ ERROR this enum takes 2 generic arguments
{
Ok(())
- //~^ ERROR type annotations needed
}
fn main() { }
LL | async fn copy() -> Result<(), E>
| +++
-error[E0282]: type annotations needed
- --> $DIR/issue-65159.rs:8:5
- |
-LL | Ok(())
- | ^^ cannot infer type for type parameter `E` declared on the enum `Result`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
-Some errors have detailed explanations: E0107, E0282.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
--- /dev/null
+// normalize-stderr-test: "couldn't read.*" -> "couldn't read the file"
+
+#![feature(extended_key_value_attributes)]
+#![doc = include_str!("../not_existing_file.md")]
+struct Documented {}
+//~^^ ERROR couldn't read
+
+fn main() {}
--- /dev/null
+error: couldn't read the file
+ --> $DIR/extented-attribute-macro-error.rs:4:10
+ |
+LL | #![doc = include_str!("../not_existing_file.md")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
error: unexpected token: `{
let res =
- ::alloc::fmt::format(match match (&"u8",) {
- (arg0,) =>
- [::core::fmt::ArgumentV1::new(arg0,
- ::core::fmt::Display::fmt)],
- } {
- ref args => unsafe {
- ::core::fmt::Arguments::new_v1(&[""],
- args)
- }
- });
+ ::alloc::fmt::format(::core::fmt::Arguments::new_v1(&[""],
+ &match (&"u8",) {
+ (arg0,) =>
+ [::core::fmt::ArgumentV1::new(arg0,
+ ::core::fmt::Display::fmt)],
+ }));
res
}.as_str()`
--> $DIR/key-value-expansion.rs:48:23
--> $DIR/register-attr-tool-fail.rs:4:1
|
LL | #![register_attr]
- | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[register_attr(attr1, attr2, ...)]`
+ | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#![register_attr(attr1, attr2, ...)]`
error: malformed `register_tool` attribute input
--> $DIR/register-attr-tool-fail.rs:5:1
|
LL | #![register_tool]
- | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[register_tool(tool1, tool2, ...)]`
+ | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#![register_tool(tool1, tool2, ...)]`
error: aborting due to 6 previous errors
-#![feature(box_syntax)]
-
struct Clam {
x: Box<isize>,
y: Box<isize>,
}
+
+
struct Fish {
a: Box<isize>,
}
fn main() {
- let a: Clam = Clam{x: box 1, y: box 2};
- let b: Clam = Clam{x: box 10, y: box 20};
+ let a: Clam = Clam{ x: Box::new(1), y: Box::new(2) };
+ let b: Clam = Clam{ x: Box::new(10), y: Box::new(20) };
let z: isize = a.x + b.y;
//~^ ERROR cannot add `Box<isize>` to `Box<isize>`
println!("{}", z);
assert_eq!(z, 21);
- let forty: Fish = Fish{a: box 40};
- let two: Fish = Fish{a: box 2};
+ let forty: Fish = Fish{ a: Box::new(40) };
+ let two: Fish = Fish{ a: Box::new(2) };
let answer: isize = forty.a + two.a;
//~^ ERROR cannot add `Box<isize>` to `Box<isize>`
println!("{}", answer);
// run-pass
#![allow(non_camel_case_types)]
-#![feature(box_syntax)]
trait double {
fn double(self: Box<Self>) -> usize;
}
pub fn main() {
- let x: Box<_> = box (box 3usize as Box<dyn double>);
+ let x: Box<_> = Box::new(Box::new(3usize) as Box<dyn double>);
assert_eq!(x.double(), 6);
}
// run-pass
#![allow(non_camel_case_types)]
-#![feature(box_syntax)]
trait double {
fn double(self) -> usize;
}
pub fn main() {
- let x: Box<_> = box 3;
+ let x: Box<_> = Box::new(3);
assert_eq!(x.double(), 6);
}
// run-pass
#![allow(non_camel_case_types)]
-#![feature(box_syntax)]
trait double {
fn double(self: Box<Self>) -> usize;
}
pub fn main() {
- let x: Box<Box<Box<Box<Box<_>>>>> = box box box box box 3;
+ let x: Box<Box<Box<Box<Box<_>>>>> = Box::new(Box::new(Box::new(Box::new(Box::new(3)))));
assert_eq!(x.double(), 6);
}
// run-pass
#![allow(non_camel_case_types)]
-#![feature(box_syntax)]
trait double {
fn double(self: Box<Self>) -> usize;
}
pub fn main() {
- let x: Box<Box<_>> = box box 3;
+ let x: Box<Box<_>> = Box::new(Box::new(3));
assert_eq!(x.double(), 6);
}
// run-pass
#![allow(non_camel_case_types)]
-#![feature(box_syntax)]
trait double {
fn double(self: Box<Self>) -> usize;
}
pub fn main() {
- let x: Box<_> = box 3;
+ let x: Box<_> = Box::new(3);
assert_eq!(x.double(), 6);
}
// run-pass
-#![feature(box_syntax)]
trait Foo {
fn foo(&self) -> String;
}
pub fn main() {
- let x: Box<_> = box 3;
+ let x: Box<_> = Box::new(3);
assert_eq!(x.foo(), "box 3".to_string());
}
// run-pass
-#![feature(box_syntax)]
fn test_generic<T: Clone, F>(expected: Box<T>, eq: F) where F: FnOnce(Box<T>, Box<T>) -> bool {
let actual: Box<T> = match true {
fn compare_box(b1: Box<bool>, b2: Box<bool>) -> bool {
return *b1 == *b2;
}
- test_generic::<bool, _>(box true, compare_box);
+ test_generic::<bool, _>(Box::new(true), compare_box);
}
pub fn main() { test_box(); }
// run-pass
-#![feature(box_syntax)]
fn test_generic<T: Clone, F>(expected: T, eq: F) where F: FnOnce(T, T) -> bool {
let actual: T = match true {
fn test_vec() {
fn compare_box(v1: Box<isize>, v2: Box<isize>) -> bool { return v1 == v2; }
- test_generic::<Box<isize>, _>(box 1, compare_box);
+ test_generic::<Box<isize>, _>(Box::new(1), compare_box);
}
pub fn main() { test_vec(); }
// run-pass
-#![feature(box_syntax)]
// Tests for match as expressions resulting in boxed types
fn test_box() {
- let res: Box<_> = match true { true => { box 100 }, _ => panic!() };
+ let res: Box<_> = match true { true => { Box::new(100) }, _ => panic!() };
assert_eq!(*res, 100);
}
// Test that we do not leak when the arg pattern must drop part of the
// argument (in this case, the `y` field).
-#![feature(box_syntax)]
-
struct Foo {
x: Box<usize>,
y: Box<usize>,
}
pub fn main() {
- let obj: Box<_> = box 1;
+ let obj: Box<_> = Box::new(1);
let objptr: *const usize = &*obj;
- let f = Foo {x: obj, y: box 2};
+ let f = Foo { x: obj, y: Box::new(2) };
let xptr = foo(f);
assert_eq!(objptr, xptr);
}
// pattern.
#![feature(box_patterns)]
-#![feature(box_syntax)]
fn getaddr(box ref x: Box<usize>) -> *const usize {
let addr: *const usize = &*x;
}
pub fn main() {
- let obj: Box<_> = box 1;
+ let obj: Box<_> = Box::new(1);
let objptr: *const usize = &*obj;
let xptr = getaddr(obj);
assert_eq!(objptr, xptr);
- let obj = box 22;
+ let obj = Box::new(22);
assert_eq!(checkval(obj), 22);
}
// run-pass
-#![feature(box_syntax)]
fn f() {
- let a: Box<_> = box 1;
+ let a: Box<_> = Box::new(1);
let b: &isize = &*a;
println!("{}", b);
}
// run-pass
#![allow(non_shorthand_field_patterns)]
-#![feature(box_syntax)]
struct Pair { a: Box<isize>, b: Box<isize> }
pub fn main() {
- let mut x: Box<_> = box Pair {a: box 10, b: box 20};
+ let mut x: Box<_> = Box::new(Pair { a: Box::new(10), b: Box::new(20) });
let x_internal = &mut *x;
match *x_internal {
Pair {a: ref mut a, b: ref mut _b} => {
assert_eq!(**a, 10);
- *a = box 30;
+ *a = Box::new(30);
assert_eq!(**a, 30);
}
}
// run-pass
#![feature(box_patterns)]
-#![feature(box_syntax)]
pub fn main() {
- match box 100 {
+ match Box::new(100) {
box x => {
println!("{}", x);
assert_eq!(x, 100);
// run-pass
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
fn foo(x: Option<Box<isize>>, b: bool) -> isize {
match x {
None => { 1 }
}
pub fn main() {
- foo(Some(box 22), true);
- foo(Some(box 22), false);
+ foo(Some(Box::new(22)), true);
+ foo(Some(Box::new(22)), false);
foo(None, true);
foo(None, false);
}
-#![feature(box_syntax)]
+struct Foo(Box<isize>, isize);
+
+struct Bar(isize, isize);
-struct Foo(Box<isize>, isize);
-struct Bar(isize, isize);
fn main() {
- let x: (Box<_>, _) = (box 1, 2);
+ let x: (Box<_>, _) = (Box::new(1), 2);
let r = &x.0;
let y = x; //~ ERROR cannot move out of `x` because it is borrowed
let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable more than once at a time
a.use_ref();
- let x = Foo(box 1, 2);
+ let x = Foo(Box::new(1), 2);
let r = &x.0;
let y = x; //~ ERROR cannot move out of `x` because it is borrowed
r.use_ref();
// Test that we detect nested calls that could free pointers evaluated
// for earlier arguments.
-#![feature(box_syntax)]
+
fn rewrite(v: &mut Box<usize>) -> usize {
- *v = box 22;
+ *v = Box::new(22);
**v
}
}
fn implicit() {
- let mut a: Box<_> = box 1;
+ let mut a: Box<_> = Box::new(1);
// Note the danger here:
//
}
fn explicit() {
- let mut a: Box<_> = box 1;
+ let mut a: Box<_> = Box::new(1);
add(
&*a,
rewrite(&mut a)); //~ ERROR cannot borrow
// Test that we detect nested calls that could free pointers evaluated
// for earlier arguments.
-#![feature(box_syntax)]
+
fn rewrite(v: &mut Box<usize>) -> usize {
- *v = box 22;
+ *v = Box::new(22);
**v
}
}
fn implicit() {
- let mut a: Box<_> = box 1;
+ let mut a: Box<_> = Box::new(1);
// Note the danger here:
//
}
fn explicit() {
- let mut a: Box<_> = box 1;
+ let mut a: Box<_> = Box::new(1);
add(
&*a,
a); //~ ERROR cannot move
// run-pass
-#![feature(box_syntax)]
fn borrow<F>(x: &isize, f: F) where F: FnOnce(&isize) {
f(x)
}
pub fn main() {
- test1(&box 22);
+ test1(&Box::new(22));
}
-#![feature(box_syntax)]
-
struct A;
impl A {
}
}
+
+
pub fn main() {
- let a: Box<_> = box A;
+ let a: Box<_> = Box::new(A);
a.foo();
//~^ ERROR cannot borrow `*a` as mutable, as `a` is not declared as mutable [E0596]
}
error[E0596]: cannot borrow `*a` as mutable, as `a` is not declared as mutable
--> $DIR/borrowck-borrow-immut-deref-of-box-as-mut.rs:12:5
|
-LL | let a: Box<_> = box A;
+LL | let a: Box<_> = Box::new(A);
| - help: consider changing this to be mutable: `mut a`
LL | a.foo();
| ^ cannot borrow as mutable
-//buggy.rs
+use std::collections::HashMap;
+
+
-#![feature(box_syntax)]
-use std::collections::HashMap;
fn main() {
let tmp: Box<_>;
buggy_map.insert(42, &*Box::new(1)); //~ ERROR temporary value dropped while borrowed
// but it is ok if we use a temporary
- tmp = box 2;
+ tmp = Box::new(2);
buggy_map.insert(43, &*tmp);
}
// run-pass
-#![feature(box_syntax)]
-
struct A {
x: Box<isize>,
y: isize,
}
fn copy_after_move() {
- let a: Box<_> = box A { x: box 0, y: 1 };
+ let a: Box<_> = Box::new(A { x: Box::new(0), y: 1 });
let _x = a.x;
let _y = a.y;
}
fn move_after_move() {
- let a: Box<_> = box B { x: box 0, y: box 1 };
+ let a: Box<_> = Box::new(B { x: Box::new(0), y: Box::new(1) });
let _x = a.x;
let _y = a.y;
}
fn borrow_after_move() {
- let a: Box<_> = box A { x: box 0, y: 1 };
+ let a: Box<_> = Box::new(A { x: Box::new(0), y: 1 });
let _x = a.x;
let _y = &a.y;
}
fn move_after_borrow() {
- let a: Box<_> = box B { x: box 0, y: box 1 };
+ let a: Box<_> = Box::new(B { x: Box::new(0), y: Box::new(1) });
let _x = &a.x;
let _y = a.y;
use_imm(_x);
}
fn copy_after_mut_borrow() {
- let mut a: Box<_> = box A { x: box 0, y: 1 };
+ let mut a: Box<_> = Box::new(A { x: Box::new(0), y: 1 });
let _x = &mut a.x;
let _y = a.y;
use_mut(_x);
}
fn move_after_mut_borrow() {
- let mut a: Box<_> = box B { x: box 0, y: box 1 };
+ let mut a: Box<_> = Box::new(B { x: Box::new(0), y: Box::new(1) });
let _x = &mut a.x;
let _y = a.y;
use_mut(_x);
}
fn borrow_after_mut_borrow() {
- let mut a: Box<_> = box A { x: box 0, y: 1 };
+ let mut a: Box<_> = Box::new(A { x: Box::new(0), y: 1 });
let _x = &mut a.x;
let _y = &a.y;
use_mut(_x);
}
fn mut_borrow_after_borrow() {
- let mut a: Box<_> = box A { x: box 0, y: 1 };
+ let mut a: Box<_> = Box::new(A { x: Box::new(0), y: 1 });
let _x = &a.x;
let _y = &mut a.y;
use_imm(_x);
}
fn copy_after_move_nested() {
- let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
+ let a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 });
let _x = a.x.x;
let _y = a.y;
}
fn move_after_move_nested() {
- let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
+ let a: Box<_> = Box::new(D { x: Box::new(A { x: Box::new(0), y: 1 }), y: Box::new(2) });
let _x = a.x.x;
let _y = a.y;
}
fn borrow_after_move_nested() {
- let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
+ let a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 });
let _x = a.x.x;
let _y = &a.y;
}
fn move_after_borrow_nested() {
- let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
+ let a: Box<_> = Box::new(D { x: Box::new(A { x: Box::new(0), y: 1 }), y: Box::new(2) });
let _x = &a.x.x;
let _y = a.y;
use_imm(_x);
}
fn copy_after_mut_borrow_nested() {
- let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
+ let mut a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 });
let _x = &mut a.x.x;
let _y = a.y;
use_mut(_x);
}
fn move_after_mut_borrow_nested() {
- let mut a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
+ let mut a: Box<_> = Box::new(D { x: Box::new(A { x: Box::new(0), y: 1 }), y: Box::new(2) });
let _x = &mut a.x.x;
let _y = a.y;
use_mut(_x);
}
fn borrow_after_mut_borrow_nested() {
- let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
+ let mut a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 });
let _x = &mut a.x.x;
let _y = &a.y;
use_mut(_x);
}
fn mut_borrow_after_borrow_nested() {
- let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
+ let mut a: Box<_> = Box::new(C { x: Box::new(A { x: Box::new(0), y: 1 }), y: 2 });
let _x = &a.x.x;
let _y = &mut a.y;
use_imm(_x);
// Tests that two closures cannot simultaneously have mutable
// and immutable access to the variable. Issue #6801.
-#![feature(box_syntax)]
-
fn get(x: &isize) -> isize {
*x
}
*x = 4;
}
+
+
fn a() {
let mut x = 3;
let c1 = || x = 4;
}
fn f() {
- let mut x: Box<_> = box 3;
+ let mut x: Box<_> = Box::new(3);
let c1 = || get(&*x);
*x = 5;
//~^ ERROR cannot assign to `*x` because it is borrowed
f: Box<isize>
}
- let mut x: Box<_> = box Foo { f: box 3 };
+ let mut x: Box<_> = Box::new(Foo { f: Box::new(3) });
let c1 = || get(&*x.f);
*x.f = 5;
//~^ ERROR cannot assign to `*x.f` because it is borrowed
f: Box<isize>
}
- let mut x: Box<_> = box Foo { f: box 3 };
+ let mut x: Box<_> = Box::new(Foo { f: Box::new(3) });
let c1 = || get(&*x.f);
let c2 = || *x.f = 5;
//~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
// access to the variable, whether that mutable access be used
// for direct assignment or for taking mutable ref. Issue #6801.
-#![feature(box_syntax)]
+
f: Box<isize>
}
- let mut x: Box<_> = box Foo { f: box 3 };
+ let mut x: Box<_> = Box::new(Foo { f: Box::new(3) });
let c1 = to_fn_mut(|| set(&mut *x.f));
let c2 = to_fn_mut(|| set(&mut *x.f));
//~^ ERROR cannot borrow `x` as mutable more than once
// access to the variable, whether that mutable access be used
// for direct assignment or for taking mutable ref. Issue #6801.
-#![feature(box_syntax)]
+
fn to_fn_mut<F: FnMut()>(f: F) -> F { f }
f: Box<isize>
}
- let mut x: Box<_> = box Foo { f: box 3 };
+ let mut x: Box<_> = Box::new(Foo { f: Box::new(3) });
let c1 = to_fn_mut(|| set(&mut *x.f));
let c2 = to_fn_mut(|| set(&mut *x.f));
//~^ ERROR cannot borrow `x` as mutable more than once
// cannot also be supplied a borrowed version of that
// variable's contents. Issue #11192.
-#![feature(box_syntax)]
-
struct Foo {
x: isize
}
}
}
+
+
fn main() {
- let mut ptr: Box<_> = box Foo { x: 0 };
+ let mut ptr: Box<_> = Box::new(Foo { x: 0 });
let mut test = |foo: &Foo| {
- ptr = box Foo { x: ptr.x + 1 };
+ ptr = Box::new(Foo { x: ptr.x + 1 });
};
test(&*ptr); //~ ERROR cannot borrow `*ptr`
}
|
LL | let mut test = |foo: &Foo| {
| ----------- mutable borrow occurs here
-LL | ptr = box Foo { x: ptr.x + 1 };
+LL | ptr = Box::new(Foo { x: ptr.x + 1 });
| --- first borrow occurs due to use of `ptr` in closure
LL | };
LL | test(&*ptr);
#![allow(unused_variables)]
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
struct A { a: isize, b: Box<isize> }
struct B { a: Box<isize>, b: Box<isize> }
fn move_after_copy() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
drop(x.a);
drop(x.b);
}
fn move_after_fu_copy() {
- let x = A { a: 1, b: box 2 };
- let _y = A { b: box 3, .. x };
+ let x = A { a: 1, b: Box::new(2) };
+ let _y = A { b: Box::new(3), .. x };
drop(x.b);
}
fn fu_move_after_copy() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
drop(x.a);
let _y = A { a: 3, .. x };
}
fn fu_move_after_fu_copy() {
- let x = A { a: 1, b: box 2 };
- let _y = A { b: box 3, .. x };
+ let x = A { a: 1, b: Box::new(2) };
+ let _y = A { b: Box::new(3), .. x };
let _z = A { a: 4, .. x };
}
fn copy_after_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
drop(x.b);
drop(x.a);
}
fn copy_after_fu_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
let y = A { a: 3, .. x };
drop(x.a);
}
fn fu_copy_after_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
drop(x.b);
- let _y = A { b: box 3, .. x };
+ let _y = A { b: Box::new(3), .. x };
}
fn fu_copy_after_fu_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
let _y = A { a: 3, .. x };
- let _z = A { b: box 3, .. x };
+ let _z = A { b: Box::new(3), .. x };
}
fn borrow_after_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
drop(x.b);
let p = &x.a;
drop(*p);
}
fn borrow_after_fu_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
let _y = A { a: 3, .. x };
let p = &x.a;
drop(*p);
}
fn move_after_borrow() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
let p = &x.a;
drop(x.b);
drop(*p);
}
fn fu_move_after_borrow() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
let p = &x.a;
let _y = A { a: 3, .. x };
drop(*p);
}
fn mut_borrow_after_mut_borrow() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let p = &mut x.a;
let q = &mut x.b;
drop(*p);
}
fn move_after_move() {
- let x = B { a: box 1, b: box 2 };
+ let x = B { a: Box::new(1), b: Box::new(2) };
drop(x.a);
drop(x.b);
}
fn move_after_fu_move() {
- let x = B { a: box 1, b: box 2 };
- let y = B { a: box 3, .. x };
+ let x = B { a: Box::new(1), b: Box::new(2) };
+ let y = B { a: Box::new(3), .. x };
drop(x.a);
}
fn fu_move_after_move() {
- let x = B { a: box 1, b: box 2 };
+ let x = B { a: Box::new(1), b: Box::new(2) };
drop(x.a);
- let z = B { a: box 3, .. x };
+ let z = B { a: Box::new(3), .. x };
drop(z.b);
}
fn fu_move_after_fu_move() {
- let x = B { a: box 1, b: box 2 };
- let _y = B { b: box 3, .. x };
- let _z = B { a: box 4, .. x };
+ let x = B { a: Box::new(1), b: Box::new(2) };
+ let _y = B { b: Box::new(3), .. x };
+ let _z = B { a: Box::new(4), .. x };
}
fn copy_after_assign_after_move() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
drop(x.b);
- x = A { a: 3, b: box 4 };
+ x = A { a: 3, b: Box::new(4) };
drop(*x.b);
}
fn copy_after_assign_after_fu_move() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let _y = A { a: 3, .. x };
- x = A { a: 3, b: box 4 };
+ x = A { a: 3, b: Box::new(4) };
drop(*x.b);
}
fn copy_after_field_assign_after_move() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
drop(x.b);
- x.b = box 3;
+ x.b = Box::new(3);
drop(*x.b);
}
fn copy_after_field_assign_after_fu_move() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let _y = A { a: 3, .. x };
- x.b = box 3;
+ x.b = Box::new(3);
drop(*x.b);
}
fn borrow_after_assign_after_move() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
drop(x.b);
- x = A { a: 3, b: box 4 };
+ x = A { a: 3, b: Box::new(4) };
let p = &x.b;
drop(**p);
}
fn borrow_after_assign_after_fu_move() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let _y = A { a: 3, .. x };
- x = A { a: 3, b: box 4 };
+ x = A { a: 3, b: Box::new(4) };
let p = &x.b;
drop(**p);
}
fn borrow_after_field_assign_after_move() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
drop(x.b);
- x.b = box 3;
+ x.b = Box::new(3);
let p = &x.b;
drop(**p);
}
fn borrow_after_field_assign_after_fu_move() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let _y = A { a: 3, .. x };
- x.b = box 3;
+ x.b = Box::new(3);
let p = &x.b;
drop(**p);
}
fn move_after_assign_after_move() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let _y = x.b;
- x = A { a: 3, b: box 4 };
+ x = A { a: 3, b: Box::new(4) };
drop(x.b);
}
fn move_after_assign_after_fu_move() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let _y = A { a: 3, .. x };
- x = A { a: 3, b: box 4 };
+ x = A { a: 3, b: Box::new(4) };
drop(x.b);
}
fn move_after_field_assign_after_move() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
drop(x.b);
- x.b = box 3;
+ x.b = Box::new(3);
drop(x.b);
}
fn move_after_field_assign_after_fu_move() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let _y = A { a: 3, .. x };
- x.b = box 3;
+ x.b = Box::new(3);
drop(x.b);
}
fn copy_after_assign_after_uninit() {
let mut x: A;
- x = A { a: 1, b: box 2 };
+ x = A { a: 1, b: Box::new(2) };
drop(x.a);
}
fn borrow_after_assign_after_uninit() {
let mut x: A;
- x = A { a: 1, b: box 2 };
+ x = A { a: 1, b: Box::new(2) };
let p = &x.a;
drop(*p);
}
fn move_after_assign_after_uninit() {
let mut x: A;
- x = A { a: 1, b: box 2 };
+ x = A { a: 1, b: Box::new(2) };
drop(x.b);
}
-#![feature(box_syntax)]
-
struct A { a: isize, b: Box<isize> }
+
+
fn deref_after_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
drop(x.b);
drop(*x.b); //~ ERROR use of moved value: `x.b`
}
fn deref_after_fu_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
let y = A { a: 3, .. x };
drop(*x.b); //~ ERROR use of moved value: `x.b`
}
fn borrow_after_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
drop(x.b);
let p = &x.b; //~ ERROR borrow of moved value: `x.b`
drop(**p);
}
fn borrow_after_fu_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
let _y = A { a: 3, .. x };
let p = &x.b; //~ ERROR borrow of moved value: `x.b`
drop(**p);
}
fn move_after_borrow() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
let p = &x.b;
drop(x.b); //~ ERROR cannot move out of `x.b` because it is borrowed
drop(**p);
}
fn fu_move_after_borrow() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
let p = &x.b;
let _y = A { a: 3, .. x }; //~ ERROR cannot move out of `x.b` because it is borrowed
drop(**p);
}
fn mut_borrow_after_mut_borrow() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let p = &mut x.a;
let q = &mut x.a; //~ ERROR cannot borrow `x.a` as mutable more than once at a time
drop(*p);
}
fn move_after_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
drop(x.b);
drop(x.b); //~ ERROR use of moved value: `x.b`
}
fn move_after_fu_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
let _y = A { a: 3, .. x };
drop(x.b); //~ ERROR use of moved value: `x.b`
}
fn fu_move_after_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
drop(x.b);
let _z = A { a: 3, .. x }; //~ ERROR use of moved value: `x.b`
}
fn fu_move_after_fu_move() {
- let x = A { a: 1, b: box 2 };
+ let x = A { a: 1, b: Box::new(2) };
let _y = A { a: 3, .. x };
let _z = A { a: 4, .. x }; //~ ERROR use of moved value: `x.b`
}
fn move_after_field_assign_after_uninit() {
let mut x: A;
- x.b = box 1; //~ ERROR assign to part of possibly-uninitialized variable: `x`
+ x.b = Box::new(1); //~ ERROR assign to part of possibly-uninitialized variable: `x`
drop(x.b);
}
error[E0381]: assign to part of possibly-uninitialized variable: `x`
--> $DIR/borrowck-field-sensitivity.rs:94:5
|
-LL | x.b = box 1;
+LL | x.b = Box::new(1);
| ^^^ use of possibly-uninitialized `x`
error: aborting due to 14 previous errors
// Issue #16205.
-#![feature(box_syntax)]
+
struct Foo {
a: [Box<isize>; 3],
}
let f = Foo {
- a: [box 3, box 4, box 5],
+ a: [Box::new(3), Box::new(4), Box::new(5)],
};
for &a in &f.a { //~ ERROR cannot move out
}
- let x: Option<Box<_>> = Some(box 1);
+ let x: Option<Box<_>> = Some(Box::new(1));
for &a in x.iter() { //~ ERROR cannot move out
}
}
// Also includes tests of the errors reported when the Box in question
// is immutable (#14270).
-#![feature(box_syntax)]
+
struct A { a: isize }
struct B<'a> { a: Box<&'a mut isize> }
fn indirect_write_to_imm_box() {
let mut x: isize = 1;
- let y: Box<_> = box &mut x;
+ let y: Box<_> = Box::new(&mut x);
let p = &y;
***p = 2; //~ ERROR cannot assign to `***p`
drop(p);
fn borrow_in_var_from_var() {
let mut x: isize = 1;
- let mut y: Box<_> = box &mut x;
+ let mut y: Box<_> = Box::new(&mut x);
let p = &y;
let q = &***p;
**y = 2; //~ ERROR cannot assign to `**y` because it is borrowed
fn borrow_in_var_from_var_via_imm_box() {
let mut x: isize = 1;
- let y: Box<_> = box &mut x;
+ let y: Box<_> = Box::new(&mut x);
let p = &y;
let q = &***p;
**y = 2; //~ ERROR cannot assign to `**y` because it is borrowed
fn borrow_in_var_from_field() {
let mut x = A { a: 1 };
- let mut y: Box<_> = box &mut x.a;
+ let mut y: Box<_> = Box::new(&mut x.a);
let p = &y;
let q = &***p;
**y = 2; //~ ERROR cannot assign to `**y` because it is borrowed
fn borrow_in_var_from_field_via_imm_box() {
let mut x = A { a: 1 };
- let y: Box<_> = box &mut x.a;
+ let y: Box<_> = Box::new(&mut x.a);
let p = &y;
let q = &***p;
**y = 2; //~ ERROR cannot assign to `**y` because it is borrowed
fn borrow_in_field_from_var() {
let mut x: isize = 1;
- let mut y = B { a: box &mut x };
+ let mut y = B { a: Box::new(&mut x) };
let p = &y.a;
let q = &***p;
**y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed
fn borrow_in_field_from_var_via_imm_box() {
let mut x: isize = 1;
- let y = B { a: box &mut x };
+ let y = B { a: Box::new(&mut x) };
let p = &y.a;
let q = &***p;
**y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed
fn borrow_in_field_from_field() {
let mut x = A { a: 1 };
- let mut y = B { a: box &mut x.a };
+ let mut y = B { a: Box::new(&mut x.a) };
let p = &y.a;
let q = &***p;
**y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed
fn borrow_in_field_from_field_via_imm_box() {
let mut x = A { a: 1 };
- let y = B { a: box &mut x.a };
+ let y = B { a: Box::new(&mut x.a) };
let p = &y.a;
let q = &***p;
**y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed
-#![feature(box_syntax)]
-
+trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } }
+impl<T> Fake for T { }
fn main() {
- let x: Option<Box<_>> = Some(box 1);
+ let x: Option<Box<_>> = Some(Box::new(1));
match x {
Some(ref _y) => {
let _a = x; //~ ERROR cannot move
_ => {}
}
}
-
-trait Fake { fn use_mut(&mut self) { } fn use_ref(&self) { } }
-impl<T> Fake for T { }
-#![feature(box_syntax)]
-
fn main() {
- let x: Option<Box<_>> = Some(box 1);
+
+ let x: Option<Box<_>> = Some(Box::new(1));
+
match x {
Some(ref y) => {
let _b = *y; //~ ERROR cannot move out
// either genuine or would require more advanced changes. The latter
// cases are noted.
-#![feature(box_syntax)]
+
fn borrow(_v: &isize) {}
fn borrow_mut(_v: &mut isize) {}
fn produce<T>() -> T { panic!(); }
fn inc(v: &mut Box<isize>) {
- *v = box (**v + 1);
+ *v = Box::new(**v + 1);
}
fn pre_freeze_cond() {
// In this instance, the freeze is conditional and starts before
// the mut borrow.
- let u = box 0;
- let mut v: Box<_> = box 3;
+ let u = Box::new(0);
+ let mut v: Box<_> = Box::new(3);
let mut _w = &u;
if cond() {
_w = &v;
// In this instance, the freeze and mut borrow are on separate sides
// of the if.
- let u = box 0;
- let mut v: Box<_> = box 3;
+ let u = Box::new(0);
+ let mut v: Box<_> = Box::new(3);
let mut _w = &u;
if cond() {
_w = &v;
-#![feature(box_syntax)]
-
fn borrow(_v: &isize) {}
fn borrow_mut(_v: &mut isize) {}
fn cond() -> bool { panic!() }
fn produce<T>() -> T { panic!(); }
+
fn inc(v: &mut Box<isize>) {
- *v = box (**v + 1);
+ *v = Box::new(**v + 1);
}
+
fn loop_overarching_alias_mut() {
// In this instance, the borrow ends on the line before the loop
- let mut v: Box<_> = box 3;
+ let mut v: Box<_> = Box::new(3);
let mut x = &mut v;
**x += 1;
loop {
fn block_overarching_alias_mut() {
// In this instance, the borrow encompasses the entire closure call.
- let mut v: Box<_> = box 3;
+ let mut v: Box<_> = Box::new(3);
let mut x = &mut v;
for _ in 0..3 {
borrow(&*v); //~ ERROR cannot borrow
}
- *x = box 5;
+ *x = Box::new(5);
}
fn loop_aliased_mut() {
// In this instance, the borrow ends right after each assignment to _x
- let mut v: Box<_> = box 3;
- let mut w: Box<_> = box 4;
+ let mut v: Box<_> = Box::new(3);
+ let mut w: Box<_> = Box::new(4);
let mut _x = &w;
loop {
borrow_mut(&mut *v); // OK
fn while_aliased_mut() {
// In this instance, the borrow ends right after each assignment to _x
- let mut v: Box<_> = box 3;
- let mut w: Box<_> = box 4;
+ let mut v: Box<_> = Box::new(3);
+ let mut w: Box<_> = Box::new(4);
let mut _x = &w;
while cond() {
borrow_mut(&mut *v); // OK
fn loop_aliased_mut_break() {
// In this instance, the borrow ends right after each assignment to _x
- let mut v: Box<_> = box 3;
- let mut w: Box<_> = box 4;
+ let mut v: Box<_> = Box::new(3);
+ let mut w: Box<_> = Box::new(4);
let mut _x = &w;
loop {
borrow_mut(&mut *v);
fn while_aliased_mut_break() {
// In this instance, the borrow ends right after each assignment to _x
- let mut v: Box<_> = box 3;
- let mut w: Box<_> = box 4;
+ let mut v: Box<_> = Box::new(3);
+ let mut w: Box<_> = Box::new(4);
let mut _x = &w;
while cond() {
borrow_mut(&mut *v);
}
fn while_aliased_mut_cond(cond: bool, cond2: bool) {
- let mut v: Box<_> = box 3;
- let mut w: Box<_> = box 4;
+ let mut v: Box<_> = Box::new(3);
+ let mut w: Box<_> = Box::new(4);
let mut x = &mut w;
while cond {
**x += 1;
LL | borrow(&*v);
| ^^^ immutable borrow occurs here
LL | }
-LL | *x = box 5;
+LL | *x = Box::new(5);
| -- mutable borrow later used here
error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable
// either genuine or would require more advanced changes. The latter
// cases are noted.
-#![feature(box_syntax)]
+
fn borrow(_v: &isize) {}
fn borrow_mut(_v: &mut isize) {}
fn produce<T>() -> T { panic!(); }
fn inc(v: &mut Box<isize>) {
- *v = box (**v + 1);
+ *v = Box::new(**v + 1);
}
fn pre_freeze() {
// In this instance, the freeze starts before the mut borrow.
- let mut v: Box<_> = box 3;
+ let mut v: Box<_> = Box::new(3);
let _w = &v;
borrow_mut(&mut *v); //~ ERROR cannot borrow
_w.use_ref();
fn post_freeze() {
// In this instance, the const alias starts after the borrow.
- let mut v: Box<_> = box 3;
+ let mut v: Box<_> = Box::new(3);
borrow_mut(&mut *v);
let _w = &v;
}
-#![feature(box_syntax)]
-
use std::thread;
f(v);
}
+
+
fn box_imm() {
- let v: Box<_> = box 3;
+ let v: Box<_> = Box::new(3);
let w = &v;
thread::spawn(move|| {
//~^ ERROR cannot move out of `v` because it is borrowed
}
fn box_imm_explicit() {
- let v: Box<_> = box 3;
+ let v: Box<_> = Box::new(3);
let w = &v;
thread::spawn(move|| {
//~^ ERROR cannot move
-#![feature(box_syntax)]
+fn take(_v: Box<isize>) {
+}
+
-fn take(_v: Box<isize>) {
-}
fn box_imm() {
- let v = box 3;
+ let v = Box::new(3);
let w = &v;
take(v); //~ ERROR cannot move out of `v` because it is borrowed
w.use_ref();
-#![feature(box_syntax)]
-
fn borrow<F>(v: &isize, f: F) where F: FnOnce(&isize) {
f(v);
}
+
+
fn box_imm() {
- let mut v: Box<_> = box 3;
+ let mut v: Box<_> = Box::new(3);
borrow(&*v,
|w| { //~ ERROR cannot borrow `v` as mutable
- v = box 4;
+ v = Box::new(4);
assert_eq!(*v, 3);
assert_eq!(*w, 4);
})
| immutable borrow later used by call
LL | |w| {
| ^^^ mutable borrow occurs here
-LL | v = box 4;
+LL | v = Box::new(4);
| - second borrow occurs due to use of `v` in closure
error: aborting due to previous error
#![feature(box_patterns)]
-#![feature(box_syntax)]
+
use std::ops::Add;
fn add(self, f: Foo) -> Foo {
let Foo(box i) = self;
let Foo(box j) = f;
- Foo(box (i + j))
+ Foo(Box::new(i + j))
}
}
fn main() {
- let x = Foo(box 3);
+ let x = Foo(Box::new(3));
let _y = {x} + x.clone(); // the `{x}` forces a move to occur
//~^ ERROR borrow of moved value: `x`
}
error[E0382]: borrow of moved value: `x`
--> $DIR/borrowck-loan-in-overloaded-op.rs:21:20
|
-LL | let x = Foo(box 3);
+LL | let x = Foo(Box::new(3));
| - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait
LL | let _y = {x} + x.clone(); // the `{x}` forces a move to occur
| - ^ value borrowed here after move
// Check that we do not ICE when compiling this
// macro, which reuses the expression `$id`
-
#![feature(box_patterns)]
-#![feature(box_syntax)]
struct Foo {
a: isize
macro_rules! declare {
($id:expr, $rest:expr) => ({
self.check_id($id);
- box Bar::Bar2($id, $rest)
+ Box::new(Bar::Bar2($id, $rest))
})
}
match s {
// run-pass
-#![feature(box_syntax)]
pub fn main() {
- let bar: Box<_> = box 3;
+ let bar: Box<_> = Box::new(3);
let h = || -> isize { *bar };
assert_eq!(h(), 3);
}
-#![feature(box_syntax,unboxed_closures)]
+#![feature(unboxed_closures)]
fn to_fn_mut<A,F:FnMut<A>>(f: F) -> F { f }
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
pub fn main() {
- let bar: Box<_> = box 3;
+ let bar: Box<_> = Box::new(3);
let _g = to_fn_mut(|| {
let _h = to_fn_once(move || -> isize { *bar }); //~ ERROR cannot move out of
});
error[E0507]: cannot move out of `bar`, a captured variable in an `FnMut` closure
--> $DIR/borrowck-move-by-capture.rs:9:29
|
-LL | let bar: Box<_> = box 3;
+LL | let bar: Box<_> = Box::new(3);
| --- captured outer variable
LL | let _g = to_fn_mut(|| {
| ________________________-
-#![feature(box_syntax)]
-
enum Foo {
Foo1(Box<u32>, Box<u32>),
Foo2(Box<u32>),
Foo3,
}
+
+
fn blah() {
- let f = &Foo::Foo1(box 1, box 2);
- match *f { //~ ERROR cannot move out of
+ let f = &Foo::Foo1(Box::new(1), Box::new(2));
+ match *f { //~ ERROR cannot move out of
Foo::Foo1(num1,
num2) => (),
Foo::Foo2(num) => (),
fn free<T>(_: T) {}
fn blah2() {
- let a = &A { a: box 1 };
- match a.a { //~ ERROR cannot move out of
+ let a = &A { a: Box::new(1) };
+ match a.a { //~ ERROR cannot move out of
n => {
free(n)
}
-#![feature(box_syntax)]
+
fn main() {
- let a: Box<Box<_>> = box box 2;
+ let a: Box<Box<_>> = Box::new(Box::new(2));
let b = &a;
let z = *a; //~ ERROR: cannot move out of `*a` because it is borrowed
-#![feature(box_syntax)]
-
fn call_f<F:FnOnce() -> isize>(f: F) -> isize {
f()
}
+
+
fn main() {
- let t: Box<_> = box 3;
+ let t: Box<_> = Box::new(3);
call_f(move|| { *t + 1 });
call_f(move|| { *t + 1 }); //~ ERROR use of moved value
error[E0382]: use of moved value: `t`
--> $DIR/borrowck-move-moved-value-into-closure.rs:11:12
|
-LL | let t: Box<_> = box 3;
+LL | let t: Box<_> = Box::new(3);
| - move occurs because `t` has type `Box<isize>`, which does not implement the `Copy` trait
LL |
LL | call_f(move|| { *t + 1 });
// Tests that the borrow checker checks all components of a path when moving
// out.
-#![feature(box_syntax)]
+
struct S {
x : Box<isize>
fn f<T>(_: T) {}
fn main() {
- let a : S = S { x : box 1 };
+ let a : S = S { x : Box::new(1) };
let pb = &a;
let S { x: ax } = a; //~ ERROR cannot move out
f(pb);
-#![feature(box_syntax)]
-
use std::thread;
+
fn borrow<T>(_: &T) { }
+
fn different_vars_after_borrows() {
- let x1: Box<_> = box 1;
+ let x1: Box<_> = Box::new(1);
let p1 = &x1;
- let x2: Box<_> = box 2;
+ let x2: Box<_> = Box::new(2);
let p2 = &x2;
thread::spawn(move|| {
//~^ ERROR cannot move out of `x1` because it is borrowed
}
fn different_vars_after_moves() {
- let x1: Box<_> = box 1;
+ let x1: Box<_> = Box::new(1);
drop(x1);
- let x2: Box<_> = box 2;
+ let x2: Box<_> = Box::new(2);
drop(x2);
thread::spawn(move|| {
//~^ ERROR use of moved value: `x1`
}
fn same_var_after_borrow() {
- let x: Box<_> = box 1;
+ let x: Box<_> = Box::new(1);
let p = &x;
thread::spawn(move|| {
//~^ ERROR cannot move out of `x` because it is borrowed
}
fn same_var_after_move() {
- let x: Box<_> = box 1;
+ let x: Box<_> = Box::new(1);
drop(x);
thread::spawn(move|| {
//~^ ERROR use of moved value: `x`
error[E0382]: use of moved value: `x1`
--> $DIR/borrowck-multiple-captures.rs:27:19
|
-LL | let x1: Box<_> = box 1;
+LL | let x1: Box<_> = Box::new(1);
| -- move occurs because `x1` has type `Box<i32>`, which does not implement the `Copy` trait
LL | drop(x1);
| -- value moved here
error[E0382]: use of moved value: `x2`
--> $DIR/borrowck-multiple-captures.rs:27:19
|
-LL | let x2: Box<_> = box 2;
+LL | let x2: Box<_> = Box::new(2);
| -- move occurs because `x2` has type `Box<i32>`, which does not implement the `Copy` trait
LL | drop(x2);
| -- value moved here
error[E0382]: use of moved value: `x`
--> $DIR/borrowck-multiple-captures.rs:49:19
|
-LL | let x: Box<_> = box 1;
+LL | let x: Box<_> = Box::new(1);
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
LL | drop(x);
| - value moved here
// run-pass
-#![feature(box_syntax)]
use std::mem::swap;
}
pub fn main() {
- let mut ints: Box<_> = box Ints {sum: box 0, values: Vec::new()};
+ let mut ints: Box<_> = Box::new(Ints {sum: Box::new(0), values: Vec::new()});
add_int(&mut *ints, 22);
add_int(&mut *ints, 44);
-#![feature(box_syntax)]
-
struct Node_ {
a: Box<Cycle>
}
Node(Node_),
Empty,
}
+
fn main() {
- let mut x: Box<_> = box Cycle::Node(Node_ {a: box Cycle::Empty});
+ let mut x: Box<_> = Box::new(Cycle::Node(Node_ {a: Box::new(Cycle::Empty)}));
+
// Create a cycle!
match *x {
Cycle::Node(ref mut y) => {
-#![feature(box_syntax)]
-
use std::ops::Index;
struct MyVec<T> {
}
}
+
+
fn main() {
- let v = MyVec::<Box<_>> { data: vec![box 1, box 2, box 3] };
+ let v = MyVec::<Box<_>> { data: vec![Box::new(1), Box::new(2), Box::new(3)] };
let good = &v[0]; // Shouldn't fail here
let bad = v[0];
//~^ ERROR cannot move out of index of `MyVec<Box<i32>>`
-#![feature(box_syntax)]
+fn borrow(_v: &isize) {}
+
-fn borrow(_v: &isize) {}
fn local() {
- let mut v: Box<_> = box 3;
+ let mut v: Box<_> = Box::new(3);
borrow(&*v);
}
fn local_rec() {
struct F { f: Box<isize> }
- let mut v = F {f: box 3};
+ let mut v = F {f: Box::new(3)};
borrow(&*v.f);
}
struct F { f: G }
struct G { g: H }
struct H { h: Box<isize> }
- let mut v = F {f: G {g: H {h: box 3}}};
+ let mut v = F {f: G {g: H {h: Box::new(3)}}};
borrow(&*v.f.g.h);
}
fn aliased_imm() {
- let mut v: Box<_> = box 3;
+ let mut v: Box<_> = Box::new(3);
let w = &v;
borrow(&*v);
w.use_ref();
}
fn aliased_mut() {
- let mut v: Box<_> = box 3;
+ let mut v: Box<_> = Box::new(3);
let w = &mut v;
borrow(&*v); //~ ERROR cannot borrow `*v`
w.use_mut();
}
fn aliased_other() {
- let mut v: Box<_> = box 3;
- let mut w: Box<_> = box 4;
+ let mut v: Box<_> = Box::new(3);
+ let mut w: Box<_> = Box::new(4);
let x = &mut w;
borrow(&*v);
x.use_mut();
}
fn aliased_other_reassign() {
- let mut v: Box<_> = box 3;
- let mut w: Box<_> = box 4;
+ let mut v: Box<_> = Box::new(3);
+ let mut w: Box<_> = Box::new(4);
let mut x = &mut w;
x = &mut v;
borrow(&*v); //~ ERROR cannot borrow `*v`
// run-pass
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
struct A { a: isize, b: Box<isize> }
fn field_copy_after_field_borrow() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let p = &mut x.b;
drop(x.a);
**p = 3;
}
fn fu_field_copy_after_field_borrow() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let p = &mut x.b;
- let y = A { b: box 3, .. x };
+ let y = A { b: Box::new(3), .. x };
drop(y);
**p = 4;
}
fn field_deref_after_field_borrow() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let p = &mut x.a;
drop(*x.b);
*p = 3;
}
fn field_move_after_field_borrow() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let p = &mut x.a;
drop(x.b);
*p = 3;
}
fn fu_field_move_after_field_borrow() {
- let mut x = A { a: 1, b: box 2 };
+ let mut x = A { a: 1, b: Box::new(2) };
let p = &mut x.a;
let y = A { a: 3, .. x };
drop(y);
-#![feature(box_syntax)]
-
#[derive(Copy, Clone)]
struct A { a: isize, b: isize }
struct B { a: isize, b: Box<isize> }
+
+
fn var_copy_after_var_borrow() {
let mut x: isize = 1;
let p = &mut x;
}
fn var_deref_after_var_borrow() {
- let mut x: Box<isize> = box 1;
+ let mut x: Box<isize> = Box::new(1);
let p = &mut x;
drop(*x); //~ ERROR cannot use `*x` because it was mutably borrowed
**p = 2;
}
fn field_deref_after_var_borrow() {
- let mut x = B { a: 1, b: box 2 };
+ let mut x = B { a: 1, b: Box::new(2) };
let p = &mut x;
drop(*x.b); //~ ERROR cannot use `*x.b` because it was mutably borrowed
p.a = 3;
}
fn field_deref_after_field_borrow() {
- let mut x = B { a: 1, b: box 2 };
+ let mut x = B { a: 1, b: Box::new(2) };
let p = &mut x.b;
drop(*x.b); //~ ERROR cannot use `*x.b` because it was mutably borrowed
**p = 3;
#![feature(box_patterns)]
-#![feature(box_syntax)]
+
fn a() {
- let mut vec = [box 1, box 2, box 3];
+ let mut vec = [Box::new(1), Box::new(2), Box::new(3)];
match vec {
[box ref _a, _, _] => {
//~^ NOTE borrow of `vec[_]` occurs here
- vec[0] = box 4; //~ ERROR cannot assign
+ vec[0] = Box::new(4); //~ ERROR cannot assign
//~^ NOTE assignment to borrowed `vec[_]` occurs here
_a.use_ref();
//~^ NOTE borrow later used here
}
fn b() {
- let mut vec = vec![box 1, box 2, box 3];
+ let mut vec = vec![Box::new(1), Box::new(2), Box::new(3)];
let vec: &mut [Box<isize>] = &mut vec;
match vec {
&mut [ref _b @ ..] => {
//~^ borrow of `vec[_]` occurs here
- vec[0] = box 4; //~ ERROR cannot assign
+ vec[0] = Box::new(4); //~ ERROR cannot assign
//~^ NOTE assignment to borrowed `vec[_]` occurs here
_b.use_ref();
//~^ NOTE borrow later used here
}
fn c() {
- let mut vec = vec![box 1, box 2, box 3];
+ let mut vec = vec![Box::new(1), Box::new(2), Box::new(3)];
let vec: &mut [Box<isize>] = &mut vec;
match vec {
//~^ ERROR cannot move out
}
fn d() {
- let mut vec = vec![box 1, box 2, box 3];
+ let mut vec = vec![Box::new(1), Box::new(2), Box::new(3)];
let vec: &mut [Box<isize>] = &mut vec;
match vec {
//~^ ERROR cannot move out
}
fn e() {
- let mut vec = vec![box 1, box 2, box 3];
+ let mut vec = vec![Box::new(1), Box::new(2), Box::new(3)];
let vec: &mut [Box<isize>] = &mut vec;
match vec {
//~^ ERROR cannot move out
LL | [box ref _a, _, _] => {
| ------ borrow of `vec[_]` occurs here
LL |
-LL | vec[0] = box 4;
+LL | vec[0] = Box::new(4);
| ^^^^^^ assignment to borrowed `vec[_]` occurs here
LL |
LL | _a.use_ref();
LL | &mut [ref _b @ ..] => {
| ----------- borrow of `vec[_]` occurs here
LL |
-LL | vec[0] = box 4;
+LL | vec[0] = Box::new(4);
| ^^^^^^ assignment to borrowed `vec[_]` occurs here
LL |
LL | _b.use_ref();
// Issue 4691: Ensure that functional-struct-updates operates
// correctly and moves rather than copy when appropriate.
-#![feature(box_syntax, core)]
+#![feature(core)]
struct ncint { v: isize }
fn ncint(v: isize) -> ncint { ncint { v: v } }
struct MoveFoo { copied: isize, moved: Box<isize>, }
impl MoveFoo {
- fn new(x:isize,y:isize) -> MoveFoo { MoveFoo { copied: x, moved: box y } }
+ fn new(x:isize,y:isize) -> MoveFoo { MoveFoo { copied: x, moved: Box::new(y) } }
}
struct DropNoFoo { inner: NoFoo }
// Case 2: Owned
let f = DropMoveFoo::new(5, 6);
- let b = DropMoveFoo { inner: MoveFoo { moved: box 7, ..f.inner }};
- let c = DropMoveFoo { inner: MoveFoo { moved: box 8, ..f.inner }};
+ let b = DropMoveFoo { inner: MoveFoo { moved: Box::new(7), ..f.inner }};
+ let c = DropMoveFoo { inner: MoveFoo { moved: Box::new(8), ..f.inner }};
assert_eq!(f.inner.copied, 5);
assert_eq!(*f.inner.moved, 6);
// copying move-by-default fields from `f`, so it moves:
let f = MoveFoo::new(11, 12);
- let b = MoveFoo {moved: box 13, ..f};
+ let b = MoveFoo {moved: Box::new(13), ..f};
let c = MoveFoo {copied: 14, ..f};
assert_eq!(b.copied, 11);
assert_eq!(*b.moved, 13);
// check-pass
-#![feature(box_syntax)]
-
struct Foo { a: isize, b: isize }
fn main() {
- let mut x: Box<_> = box Foo { a: 1, b: 2 };
+ let mut x: Box<_> = Box::new(Foo { a: 1, b: 2 });
let (a, b) = (&mut x.a, &mut x.b);
- let mut foo: Box<_> = box Foo { a: 1, b: 2 };
+ let mut foo: Box<_> = Box::new(Foo { a: 1, b: 2 });
let (c, d) = (&mut foo.a, &foo.b);
// We explicitly use the references created above to illustrate that the
//~^ ERROR this struct takes 0 lifetime arguments but 1 lifetime argument was supplied
//~^^ ERROR this struct takes 1 generic argument but 0 generic arguments were supplied
LockedMarket(generator.lock().unwrap().buy())
- //~^ ERROR cannot return value referencing temporary value
}
struct LockedMarket<T>(T);
| expected 0 lifetime arguments
|
note: struct defined here, with 0 lifetime parameters
- --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8
+ --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8
|
LL | struct LockedMarket<T>(T);
| ^^^^^^^^^^^^
| ^^^^^^^^^^^^ expected 1 generic argument
|
note: struct defined here, with 1 generic parameter: `T`
- --> $DIR/issue-82126-mismatched-subst-and-hir.rs:23:8
+ --> $DIR/issue-82126-mismatched-subst-and-hir.rs:22:8
|
LL | struct LockedMarket<T>(T);
| ^^^^^^^^^^^^ -
LL | async fn buy_lock(generator: &Mutex<MarketMultiplier>) -> LockedMarket<'_, T> {
| +++
-error[E0515]: cannot return value referencing temporary value
- --> $DIR/issue-82126-mismatched-subst-and-hir.rs:19:5
- |
-LL | LockedMarket(generator.lock().unwrap().buy())
- | ^^^^^^^^^^^^^-------------------------^^^^^^^
- | | |
- | | temporary value created here
- | returns a value referencing data owned by the current function
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0107, E0515.
-For more information about an error, try `rustc --explain E0107`.
+For more information about this error, try `rustc --explain E0107`.
// run-pass
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
fn foo(x: &mut Box<u8>) {
- *x = box 5;
+ *x = Box::new(5);
}
pub fn main() {
- foo(&mut box 4);
+ foo(&mut Box::new(4));
}
-#![feature(box_syntax)]
-
trait Noisy {
fn speak(&self);
}
}
}
+
+
fn main() {
- let nyan: Box<dyn Noisy> = box cat(0, 2, "nyan".to_string()) as Box<dyn Noisy>;
+ let nyan: Box<dyn Noisy> = Box::new(cat(0, 2, "nyan".to_string())) as Box<dyn Noisy>;
nyan.eat(); //~ ERROR no method named `eat` found
}
// pretty-expanded FIXME #23616
-#![feature(box_syntax, os)]
+#![feature(os)]
use std::os;
impl Test {
fn get_x(&self) -> Option<Box<isize>> {
- Some(box self.x)
+ Some(Box::new(self.x))
}
}
// lifetime rules.
#![feature(box_patterns)]
-#![feature(box_syntax)]
use std::ops::Drop;
end_of_block!(AddFlags { bits: ref _x }, AddFlags(1));
end_of_block!(&AddFlags { bits }, &AddFlags(1));
end_of_block!((_, ref _y), (AddFlags(1), 22));
- end_of_block!(box ref _x, box AddFlags(1));
- end_of_block!(box _x, box AddFlags(1));
+ end_of_block!(box ref _x, std::boxed::Box::new(AddFlags(1)));
+ end_of_block!(box _x, std::boxed::Box::new(AddFlags(1)));
end_of_block!(_, { { check_flags(0); &AddFlags(1) } });
end_of_block!(_, &((Box { f: AddFlags(1) }).f));
end_of_block!(_, &(([AddFlags(1)])[0]));
// ignore-emscripten no threads support
-#![feature(box_syntax)]
-
use std::thread;
enum Conzabble {
pub fn fails() {
let x = 2;
let mut y: Vec<Box<_>> = Vec::new();
- y.push(box Conzabble::Bickwick(do_it(&get_bar(x))));
+ y.push(Box::new(Conzabble::Bickwick(do_it(&get_bar(x)))));
}
pub fn main() {
#![allow(unused_must_use)]
// ignore-emscripten no threads support
-#![feature(box_syntax)]
-
use std::thread;
struct Pair {
}
pub fn main() {
- let z: Box<_> = box Pair { a : 10, b : 12};
+ let z: Box<_> = Box::new(Pair { a : 10, b : 12});
thread::spawn(move|| {
assert_eq!(z.a, 10);
// storing closure data (as we used to do), the u64 would
// overwrite the u16.
-#![feature(box_syntax)]
-
struct Pair<A,B> {
a: A, b: B
}
}
fn f<A:Clone + 'static>(a: A, b: u16) -> Box<dyn Invokable<A>+'static> {
- box Invoker {
+ Box::new(Invoker {
a: a,
b: b,
- } as Box<dyn Invokable<A>+'static>
+ }) as Box<dyn Invokable<A>+'static>
}
pub fn main() {
// edition:2021
+
+
// Tests that two closures cannot simultaneously have mutable
// and immutable access to the variable. Issue #6801.
-#![feature(box_syntax)]
-
#[derive(Debug)]
struct Point {
x: i32,
--- /dev/null
+// edition:2021
+
+// Tests that in cases where we individually capture all the fields of a type,
+// we still drop them in the order they would have been dropped in the 2018 edition.
+
+// NOTE: It is *critical* that the order of the min capture NOTES in the stderr output
+// does *not* change!
+
+#![feature(rustc_attrs)]
+
+#[derive(Debug)]
+struct HasDrop;
+impl Drop for HasDrop {
+ fn drop(&mut self) {
+ println!("dropped");
+ }
+}
+
+fn test_one() {
+ let a = (HasDrop, HasDrop);
+ let b = (HasDrop, HasDrop);
+
+ let c = #[rustc_capture_analysis]
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ || {
+ //~^ ERROR: Min Capture analysis includes:
+ //~| ERROR
+ println!("{:?}", a.0);
+ //~^ NOTE: Min Capture a[(0, 0)] -> ImmBorrow
+ //~| NOTE
+ println!("{:?}", a.1);
+ //~^ NOTE: Min Capture a[(1, 0)] -> ImmBorrow
+ //~| NOTE
+
+ println!("{:?}", b.0);
+ //~^ NOTE: Min Capture b[(0, 0)] -> ImmBorrow
+ //~| NOTE
+ println!("{:?}", b.1);
+ //~^ NOTE: Min Capture b[(1, 0)] -> ImmBorrow
+ //~| NOTE
+ };
+}
+
+fn test_two() {
+ let a = (HasDrop, HasDrop);
+ let b = (HasDrop, HasDrop);
+
+ let c = #[rustc_capture_analysis]
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ || {
+ //~^ ERROR: Min Capture analysis includes:
+ //~| ERROR
+ println!("{:?}", a.1);
+ //~^ NOTE: Min Capture a[(1, 0)] -> ImmBorrow
+ //~| NOTE
+ println!("{:?}", a.0);
+ //~^ NOTE: Min Capture a[(0, 0)] -> ImmBorrow
+ //~| NOTE
+
+ println!("{:?}", b.1);
+ //~^ NOTE: Min Capture b[(1, 0)] -> ImmBorrow
+ //~| NOTE
+ println!("{:?}", b.0);
+ //~^ NOTE: Min Capture b[(0, 0)] -> ImmBorrow
+ //~| NOTE
+ };
+}
+
+fn test_three() {
+ let a = (HasDrop, HasDrop);
+ let b = (HasDrop, HasDrop);
+
+ let c = #[rustc_capture_analysis]
+ //~^ ERROR: attributes on expressions are experimental
+ //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
+ || {
+ //~^ ERROR: Min Capture analysis includes:
+ //~| ERROR
+ println!("{:?}", b.1);
+ //~^ NOTE: Min Capture b[(1, 0)] -> ImmBorrow
+ //~| NOTE
+ println!("{:?}", a.1);
+ //~^ NOTE: Min Capture a[(1, 0)] -> ImmBorrow
+ //~| NOTE
+ println!("{:?}", a.0);
+ //~^ NOTE: Min Capture a[(0, 0)] -> ImmBorrow
+ //~| NOTE
+
+ println!("{:?}", b.0);
+ //~^ NOTE: Min Capture b[(0, 0)] -> ImmBorrow
+ //~| NOTE
+ };
+}
+
+fn main() {
+ test_one();
+ test_two();
+ test_three();
+}
--- /dev/null
+error[E0658]: attributes on expressions are experimental
+ --> $DIR/preserve_field_drop_order.rs:23:13
+ |
+LL | let c = #[rustc_capture_analysis]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+ = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+ --> $DIR/preserve_field_drop_order.rs:49:13
+ |
+LL | let c = #[rustc_capture_analysis]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+ = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error[E0658]: attributes on expressions are experimental
+ --> $DIR/preserve_field_drop_order.rs:75:13
+ |
+LL | let c = #[rustc_capture_analysis]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
+ = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
+
+error: First Pass analysis includes:
+ --> $DIR/preserve_field_drop_order.rs:26:5
+ |
+LL | / || {
+LL | |
+LL | |
+LL | | println!("{:?}", a.0);
+... |
+LL | |
+LL | | };
+ | |_____^
+ |
+note: Capturing a[(0, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:29:26
+ |
+LL | println!("{:?}", a.0);
+ | ^^^
+note: Capturing a[(1, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:32:26
+ |
+LL | println!("{:?}", a.1);
+ | ^^^
+note: Capturing b[(0, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:36:26
+ |
+LL | println!("{:?}", b.0);
+ | ^^^
+note: Capturing b[(1, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:39:26
+ |
+LL | println!("{:?}", b.1);
+ | ^^^
+
+error: Min Capture analysis includes:
+ --> $DIR/preserve_field_drop_order.rs:26:5
+ |
+LL | / || {
+LL | |
+LL | |
+LL | | println!("{:?}", a.0);
+... |
+LL | |
+LL | | };
+ | |_____^
+ |
+note: Min Capture a[(0, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:29:26
+ |
+LL | println!("{:?}", a.0);
+ | ^^^
+note: Min Capture a[(1, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:32:26
+ |
+LL | println!("{:?}", a.1);
+ | ^^^
+note: Min Capture b[(0, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:36:26
+ |
+LL | println!("{:?}", b.0);
+ | ^^^
+note: Min Capture b[(1, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:39:26
+ |
+LL | println!("{:?}", b.1);
+ | ^^^
+
+error: First Pass analysis includes:
+ --> $DIR/preserve_field_drop_order.rs:52:5
+ |
+LL | / || {
+LL | |
+LL | |
+LL | | println!("{:?}", a.1);
+... |
+LL | |
+LL | | };
+ | |_____^
+ |
+note: Capturing a[(1, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:55:26
+ |
+LL | println!("{:?}", a.1);
+ | ^^^
+note: Capturing a[(0, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:58:26
+ |
+LL | println!("{:?}", a.0);
+ | ^^^
+note: Capturing b[(1, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:62:26
+ |
+LL | println!("{:?}", b.1);
+ | ^^^
+note: Capturing b[(0, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:65:26
+ |
+LL | println!("{:?}", b.0);
+ | ^^^
+
+error: Min Capture analysis includes:
+ --> $DIR/preserve_field_drop_order.rs:52:5
+ |
+LL | / || {
+LL | |
+LL | |
+LL | | println!("{:?}", a.1);
+... |
+LL | |
+LL | | };
+ | |_____^
+ |
+note: Min Capture a[(0, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:58:26
+ |
+LL | println!("{:?}", a.0);
+ | ^^^
+note: Min Capture a[(1, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:55:26
+ |
+LL | println!("{:?}", a.1);
+ | ^^^
+note: Min Capture b[(0, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:65:26
+ |
+LL | println!("{:?}", b.0);
+ | ^^^
+note: Min Capture b[(1, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:62:26
+ |
+LL | println!("{:?}", b.1);
+ | ^^^
+
+error: First Pass analysis includes:
+ --> $DIR/preserve_field_drop_order.rs:78:5
+ |
+LL | / || {
+LL | |
+LL | |
+LL | | println!("{:?}", b.1);
+... |
+LL | |
+LL | | };
+ | |_____^
+ |
+note: Capturing b[(1, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:81:26
+ |
+LL | println!("{:?}", b.1);
+ | ^^^
+note: Capturing a[(1, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:84:26
+ |
+LL | println!("{:?}", a.1);
+ | ^^^
+note: Capturing a[(0, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:87:26
+ |
+LL | println!("{:?}", a.0);
+ | ^^^
+note: Capturing b[(0, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:91:26
+ |
+LL | println!("{:?}", b.0);
+ | ^^^
+
+error: Min Capture analysis includes:
+ --> $DIR/preserve_field_drop_order.rs:78:5
+ |
+LL | / || {
+LL | |
+LL | |
+LL | | println!("{:?}", b.1);
+... |
+LL | |
+LL | | };
+ | |_____^
+ |
+note: Min Capture b[(0, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:91:26
+ |
+LL | println!("{:?}", b.0);
+ | ^^^
+note: Min Capture b[(1, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:81:26
+ |
+LL | println!("{:?}", b.1);
+ | ^^^
+note: Min Capture a[(0, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:87:26
+ |
+LL | println!("{:?}", a.0);
+ | ^^^
+note: Min Capture a[(1, 0)] -> ImmBorrow
+ --> $DIR/preserve_field_drop_order.rs:84:26
+ |
+LL | println!("{:?}", a.1);
+ | ^^^
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// run-pass
+// check-run-results
+// revisions: twenty_eighteen twenty_twentyone
+// [twenty_eighteen]compile-flags: --edition 2018
+// [twenty_twentyone]compile-flags: --edition 2021
+
+#[derive(Debug)]
+struct Dropable(&'static str);
+
+impl Drop for Dropable {
+ fn drop(&mut self) {
+ println!("Dropping {}", self.0)
+ }
+}
+
+#[derive(Debug)]
+struct A {
+ x: Dropable,
+ y: Dropable,
+}
+
+#[derive(Debug)]
+struct B {
+ c: A,
+ d: A,
+}
+
+#[derive(Debug)]
+struct R<'a> {
+ c: &'a A,
+ d: &'a A,
+}
+
+fn main() {
+ let a = A { x: Dropable("x"), y: Dropable("y") };
+
+ let c = move || println!("{:?} {:?}", a.y, a.x);
+
+ c();
+
+ let b = B {
+ c: A { x: Dropable("b.c.x"), y: Dropable("b.c.y") },
+ d: A { x: Dropable("b.d.x"), y: Dropable("b.d.y") },
+ };
+
+ let d = move || println!("{:?} {:?} {:?} {:?}", b.d.y, b.d.x, b.c.y, b.c.x);
+
+ d();
+
+ let r = R {
+ c: &A { x: Dropable("r.c.x"), y: Dropable("r.c.y") },
+ d: &A { x: Dropable("r.d.x"), y: Dropable("r.d.y") },
+ };
+
+ let e = move || println!("{:?} {:?} {:?} {:?}", r.d.y, r.d.x, r.c.y, r.c.x);
+
+ e();
+}
--- /dev/null
+Dropable("y") Dropable("x")
+Dropable("b.d.y") Dropable("b.d.x") Dropable("b.c.y") Dropable("b.c.x")
+Dropable("r.d.y") Dropable("r.d.x") Dropable("r.c.y") Dropable("r.c.x")
+Dropping r.d.x
+Dropping r.d.y
+Dropping r.c.x
+Dropping r.c.y
+Dropping b.c.x
+Dropping b.c.y
+Dropping b.d.x
+Dropping b.d.y
+Dropping x
+Dropping y
--- /dev/null
+Dropable("y") Dropable("x")
+Dropable("b.d.y") Dropable("b.d.x") Dropable("b.c.y") Dropable("b.c.x")
+Dropable("r.d.y") Dropable("r.d.x") Dropable("r.c.y") Dropable("r.c.x")
+Dropping r.d.x
+Dropping r.d.y
+Dropping r.c.x
+Dropping r.c.y
+Dropping b.c.x
+Dropping b.c.y
+Dropping b.d.x
+Dropping b.d.y
+Dropping x
+Dropping y
// run-pass
#![allow(unused_braces)]
-#![feature(box_syntax)]
use std::cell::RefCell;
use std::fmt::Debug;
--- /dev/null
+error[E0277]: the trait bound `(): std::error::Error` is not satisfied
+ --> $DIR/coerce-issue-49593-box-never.rs:17:53
+ |
+LL | /* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
+ |
+ = note: required for the cast to the object type `dyn std::error::Error`
+
+error[E0277]: the trait bound `(): std::error::Error` is not satisfied
+ --> $DIR/coerce-issue-49593-box-never.rs:22:49
+ |
+LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()`
+ |
+ = note: required for the cast to the object type `(dyn std::error::Error + 'static)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
-// check-pass
-#![feature(never_type, never_type_fallback)]
+// revisions: nofallback fallback
+//[fallback] check-pass
+//[nofallback] check-fail
+
+#![feature(never_type)]
+#![cfg_attr(fallback, feature(never_type_fallback))]
#![allow(unreachable_code)]
use std::error::Error;
fn foo(x: !) -> Box<dyn Error> {
/* *mut $0 is coerced to Box<dyn Error> here */ Box::<_ /* ! */>::new(x)
+ //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied
}
fn foo_raw_ptr(x: !) -> *mut dyn Error {
/* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x)
+ //[nofallback]~^ ERROR trait bound `(): std::error::Error` is not satisfied
}
fn no_coercion(d: *mut dyn Error) -> *mut dyn Error {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
|
= note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
+ = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
error: aborting due to previous error
--- /dev/null
+// Regression test for the ICE described in #89088.
+
+// check-pass
+
+#![allow(indirect_structural_match)]
+use std::borrow::Cow;
+
+const FOO: &A = &A::Field(Cow::Borrowed("foo"));
+
+#[derive(PartialEq, Eq)]
+enum A {
+ Field(Cow<'static, str>)
+}
+
+fn main() {
+ let var = A::Field(Cow::Borrowed("bar"));
+
+ match &var {
+ FOO => todo!(),
+ _ => todo!()
+ }
+}
static TEST_BAD: &mut i32 = {
&mut *(box 0)
//~^ ERROR could not evaluate static initializer
- //~| NOTE heap allocations
+ //~| NOTE calling non-const function `alloc::alloc::exchange_malloc`
};
--> $DIR/box.rs:10:11
|
LL | &mut *(box 0)
- | ^^^^^^^ "heap allocations via `box` keyword" needs an rfc before being allowed inside constants
+ | ^^^^^^^ calling non-const function `alloc::alloc::exchange_malloc`
warning: skipping const checks
|
--- /dev/null
+// check-pass
+
+#![feature(fn_traits)]
+#![feature(adt_const_params)]
+//~^ WARNING the feature `adt_const_params` is incomplete
+
+#[derive(PartialEq, Eq)]
+struct CompileTimeSettings{
+ hooks: &'static[fn()],
+}
+
+struct Foo<const T: CompileTimeSettings>;
+
+impl<const T: CompileTimeSettings> Foo<T> {
+ fn call_hooks(){
+ }
+}
+
+fn main(){
+ const SETTINGS: CompileTimeSettings = CompileTimeSettings{
+ hooks: &[],
+ };
+
+ Foo::<SETTINGS>::call_hooks();
+}
--- /dev/null
+warning: the feature `adt_const_params` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/refs_check_const_eq-issue-88384.rs:4:12
+ |
+LL | #![feature(adt_const_params)]
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
+
+warning: 1 warning emitted
+
--- /dev/null
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(adt_const_params)]
+
+struct FooConst<const ARRAY: &'static [&'static str]> {}
+
+const FOO_ARR: &[&'static str; 2] = &["Hello", "Friend"];
+
+fn main() {
+ let _ = FooConst::<FOO_ARR> {};
+}
// run-pass
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
// This is a regression test that the metadata for the
// name_pool::methods impl in the other crate is reachable from this
// crate.
pub fn main() {
use crate_method_reexport_grrrrrrr2::rust::add;
use crate_method_reexport_grrrrrrr2::rust::cx;
- let x: Box<_> = box ();
+ let x: Box<_> = Box::new(());
x.cx();
let y = ();
y.add("hi".to_string());
-#![feature(box_syntax)]
-
use std::cell::RefCell;
pub struct Entry<A,B> {
fn eq_int(a: isize, b: isize) -> bool { a == b }
return alist {
eq_fn: eq_int,
- data: box RefCell::new(Vec::new()),
+ data: Box::new(RefCell::new(Vec::new())),
};
}
fn eq_int(a: isize, b: isize) -> bool { a == b }
return alist {
eq_fn: eq_int,
- data: box RefCell::new(Vec::new()),
+ data: Box::new(RefCell::new(Vec::new())),
};
}
// run-pass
// aux-build:cci_borrow_lib.rs
-#![feature(box_syntax)]
-
extern crate cci_borrow_lib;
use cci_borrow_lib::foo;
pub fn main() {
- let p: Box<_> = box 22;
+ let p: Box<_> = Box::new(22);
let r = foo(&*p);
println!("r={}", r);
assert_eq!(r, 22);
// Test that when a trait impl changes, fns whose body uses that trait
// must also be recompiled.
-// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-assoc-type-codegen
+// incremental
+// compile-flags: -Z query-dep-graph
#![feature(rustc_attrs)]
#![allow(warnings)]
error: OK
- --> $DIR/dep-graph-assoc-type-codegen.rs:28:5
+ --> $DIR/dep-graph-assoc-type-codegen.rs:29:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Test that immediate callers have to change when callee changes, but
// not callers' callers.
-// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-caller-callee
+// incremental
+// compile-flags: -Z query-dep-graph
#![feature(rustc_attrs)]
#![allow(dead_code)]
error: OK
- --> $DIR/dep-graph-caller-callee.rs:20:5
+ --> $DIR/dep-graph-caller-callee.rs:21:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `x` to `typeck`
- --> $DIR/dep-graph-caller-callee.rs:31:5
+ --> $DIR/dep-graph-caller-callee.rs:32:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Test cases where a changing struct appears in the signature of fns
// and methods.
-// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-struct-signature
+// incremental
+// compile-flags: -Z query-dep-graph
#![feature(rustc_attrs)]
#![allow(dead_code)]
error: no path from `WillChange` to `type_of`
- --> $DIR/dep-graph-struct-signature.rs:27:5
+ --> $DIR/dep-graph-struct-signature.rs:28:5
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `WillChange` to `associated_item`
- --> $DIR/dep-graph-struct-signature.rs:28:5
+ --> $DIR/dep-graph-struct-signature.rs:29:5
|
LL | #[rustc_then_this_would_need(associated_item)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `WillChange` to `trait_def`
- --> $DIR/dep-graph-struct-signature.rs:29:5
+ --> $DIR/dep-graph-struct-signature.rs:30:5
|
LL | #[rustc_then_this_would_need(trait_def)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:31:9
+ --> $DIR/dep-graph-struct-signature.rs:32:9
|
LL | #[rustc_then_this_would_need(fn_sig)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:35:5
+ --> $DIR/dep-graph-struct-signature.rs:36:5
|
LL | #[rustc_then_this_would_need(fn_sig)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:36:5
+ --> $DIR/dep-graph-struct-signature.rs:37:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:39:5
+ --> $DIR/dep-graph-struct-signature.rs:40:5
|
LL | #[rustc_then_this_would_need(fn_sig)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:40:5
+ --> $DIR/dep-graph-struct-signature.rs:41:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:45:5
+ --> $DIR/dep-graph-struct-signature.rs:46:5
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:47:9
+ --> $DIR/dep-graph-struct-signature.rs:48:9
|
LL | #[rustc_then_this_would_need(fn_sig)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:48:9
+ --> $DIR/dep-graph-struct-signature.rs:49:9
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:52:5
+ --> $DIR/dep-graph-struct-signature.rs:53:5
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:54:9
+ --> $DIR/dep-graph-struct-signature.rs:55:9
|
LL | #[rustc_then_this_would_need(fn_sig)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:55:9
+ --> $DIR/dep-graph-struct-signature.rs:56:9
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:60:9
+ --> $DIR/dep-graph-struct-signature.rs:61:9
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-struct-signature.rs:62:9
+ --> $DIR/dep-graph-struct-signature.rs:63:9
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `WillChange` to `type_of`
- --> $DIR/dep-graph-struct-signature.rs:67:5
+ --> $DIR/dep-graph-struct-signature.rs:68:5
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `WillChange` to `type_of`
- --> $DIR/dep-graph-struct-signature.rs:74:5
+ --> $DIR/dep-graph-struct-signature.rs:75:5
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `WillChange` to `fn_sig`
- --> $DIR/dep-graph-struct-signature.rs:76:9
+ --> $DIR/dep-graph-struct-signature.rs:77:9
|
LL | #[rustc_then_this_would_need(fn_sig)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `WillChange` to `fn_sig`
- --> $DIR/dep-graph-struct-signature.rs:80:5
+ --> $DIR/dep-graph-struct-signature.rs:81:5
|
LL | #[rustc_then_this_would_need(fn_sig)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `WillChange` to `fn_sig`
- --> $DIR/dep-graph-struct-signature.rs:83:5
+ --> $DIR/dep-graph-struct-signature.rs:84:5
|
LL | #[rustc_then_this_would_need(fn_sig)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `WillChange` to `typeck`
- --> $DIR/dep-graph-struct-signature.rs:84:5
+ --> $DIR/dep-graph-struct-signature.rs:85:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Test that adding an impl to a trait `Foo` DOES affect functions
// that only use `Bar` if they have methods in common.
-// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-trait-impl-two-traits-same-method
+// incremental
+// compile-flags: -Z query-dep-graph
#![feature(rustc_attrs)]
#![allow(dead_code)]
error: OK
- --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:32:5
+ --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:33:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `x::<impl Foo for u32>` to `typeck`
- --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:41:5
+ --> $DIR/dep-graph-trait-impl-two-traits-same-method.rs:42:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Test that adding an impl to a trait `Foo` does not affect functions
// that only use `Bar`, so long as they do not have methods in common.
-// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-trait-impl-two-traits
+// incremental
+// compile-flags: -Z query-dep-graph
#![feature(rustc_attrs)]
#![allow(warnings)]
error: no path from `x::<impl Foo for char>` to `typeck`
- --> $DIR/dep-graph-trait-impl-two-traits.rs:31:5
+ --> $DIR/dep-graph-trait-impl-two-traits.rs:32:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `x::<impl Foo for char>` to `typeck`
- --> $DIR/dep-graph-trait-impl-two-traits.rs:40:5
+ --> $DIR/dep-graph-trait-impl-two-traits.rs:41:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Test that when a trait impl changes, fns whose body uses that trait
// must also be recompiled.
-// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-trait-impl
+// incremental
+// compile-flags: -Z query-dep-graph
#![feature(rustc_attrs)]
#![allow(warnings)]
error: OK
- --> $DIR/dep-graph-trait-impl.rs:27:5
+ --> $DIR/dep-graph-trait-impl.rs:28:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-trait-impl.rs:32:5
+ --> $DIR/dep-graph-trait-impl.rs:33:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-trait-impl.rs:37:5
+ --> $DIR/dep-graph-trait-impl.rs:38:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-trait-impl.rs:42:5
+ --> $DIR/dep-graph-trait-impl.rs:43:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `x::<impl Foo for char>` to `typeck`
- --> $DIR/dep-graph-trait-impl.rs:55:5
+ --> $DIR/dep-graph-trait-impl.rs:56:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Test that changing what a `type` points to does not go unnoticed.
-// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-type-alias
+// incremental
+// compile-flags: -Z query-dep-graph
#![feature(rustc_attrs)]
#![allow(dead_code)]
error: no path from `TypeAlias` to `type_of`
- --> $DIR/dep-graph-type-alias.rs:17:1
+ --> $DIR/dep-graph-type-alias.rs:18:1
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-type-alias.rs:19:5
+ --> $DIR/dep-graph-type-alias.rs:20:5
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `TypeAlias` to `type_of`
- --> $DIR/dep-graph-type-alias.rs:24:1
+ --> $DIR/dep-graph-type-alias.rs:25:1
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-type-alias.rs:27:9
+ --> $DIR/dep-graph-type-alias.rs:28:9
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `TypeAlias` to `type_of`
- --> $DIR/dep-graph-type-alias.rs:33:1
+ --> $DIR/dep-graph-type-alias.rs:34:1
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-type-alias.rs:35:5
+ --> $DIR/dep-graph-type-alias.rs:36:5
|
LL | #[rustc_then_this_would_need(fn_sig)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: no path from `TypeAlias` to `type_of`
- --> $DIR/dep-graph-type-alias.rs:41:1
+ --> $DIR/dep-graph-type-alias.rs:42:1
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-type-alias.rs:43:5
+ --> $DIR/dep-graph-type-alias.rs:44:5
|
LL | #[rustc_then_this_would_need(fn_sig)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-type-alias.rs:44:5
+ --> $DIR/dep-graph-type-alias.rs:45:5
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-type-alias.rs:48:1
+ --> $DIR/dep-graph-type-alias.rs:49:1
|
LL | #[rustc_then_this_would_need(type_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-type-alias.rs:51:1
+ --> $DIR/dep-graph-type-alias.rs:52:1
|
LL | #[rustc_then_this_would_need(fn_sig)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: OK
- --> $DIR/dep-graph-type-alias.rs:52:1
+ --> $DIR/dep-graph-type-alias.rs:53:1
|
LL | #[rustc_then_this_would_need(typeck)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Test that changing what a `type` points to does not go unnoticed
// by the variance analysis.
-// compile-flags: -Z query-dep-graph -C incremental=tmp/dep-graph-variance-alias
+// incremental
+// compile-flags: -Z query-dep-graph
#![feature(rustc_attrs)]
#![allow(dead_code)]
error: OK
- --> $DIR/dep-graph-variance-alias.rs:18:1
+ --> $DIR/dep-graph-variance-alias.rs:19:1
|
LL | #[rustc_then_this_would_need(variances_of)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// run-pass
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
pub fn main() {
- let x: Box<isize> = box 10;
+ let x: Box<isize> = Box::new(10);
let _y: isize = *x;
}
// run-pass
-#![feature(box_syntax)]
-
use std::default::Default;
#[derive(Default)]
// reference work properly.
#![feature(box_patterns)]
-#![feature(box_syntax)]
trait T { fn foo(&self) {} }
impl T for isize {}
+
fn main() {
// For an expression of the form:
//
// n == m
let &x = &1isize as &dyn T; //~ ERROR type `&dyn T` cannot be dereferenced
let &&x = &(&1isize as &dyn T); //~ ERROR type `&dyn T` cannot be dereferenced
- let box x = box 1isize as Box<dyn T>;
+ let box x = Box::new(1isize) as Box<dyn T>;
//~^ ERROR type `Box<dyn T>` cannot be dereferenced
// n > m
//~^ ERROR mismatched types
//~| expected trait object `dyn T`
//~| found reference `&_`
- let box box x = box 1isize as Box<dyn T>;
+ let box box x = Box::new(1isize) as Box<dyn T>;
//~^ ERROR mismatched types
//~| expected trait object `dyn T`
//~| found struct `Box<_>`
error[E0033]: type `Box<dyn T>` cannot be dereferenced
--> $DIR/destructure-trait-ref.rs:28:9
|
-LL | let box x = box 1isize as Box<dyn T>;
+LL | let box x = Box::new(1isize) as Box<dyn T>;
| ^^^^^ type `Box<dyn T>` cannot be dereferenced
error[E0308]: mismatched types
error[E0308]: mismatched types
--> $DIR/destructure-trait-ref.rs:40:13
|
-LL | let box box x = box 1isize as Box<dyn T>;
- | ^^^^^ ------------------------ this expression has type `Box<dyn T>`
+LL | let box box x = Box::new(1isize) as Box<dyn T>;
+ | ^^^^^ ------------------------------ this expression has type `Box<dyn T>`
| |
| expected trait object `dyn T`, found struct `Box`
|
// pretty-expanded FIXME #23616
#![allow(non_camel_case_types)]
-#![feature(box_syntax)]
-
enum t { foo(Box<isize>), }
pub fn main() {
- let tt = t::foo(box 10);
+ let tt = t::foo(Box::new(10));
match tt { t::foo(_z) => { } }
}
// Test that destructor on a struct runs successfully after the struct
// is boxed and converted to an object.
-#![feature(box_syntax)]
-
static mut value: usize = 0;
struct Cat {
pub fn main() {
{
- let x = box Cat {name: 22};
+ let x = Box::new(Cat {name: 22});
let nyan: Box<dyn Dummy> = x as Box<dyn Dummy>;
}
unsafe {
#![allow(unused_variables)]
// ignore-emscripten no threads support
-#![feature(box_syntax)]
-
use std::thread;
use std::sync::mpsc::{channel, Sender};
let (sender, receiver) = channel();
{
- let v = Foo::NestedVariant(box 42, SendOnDrop { sender: sender.clone() }, sender);
+ let v = Foo::NestedVariant(Box::new(42), SendOnDrop { sender: sender.clone() }, sender);
}
assert_eq!(receiver.recv().unwrap(), Message::DestructorRan);
assert_eq!(receiver.recv().unwrap(), Message::Dropped);
let (sender, receiver) = channel();
let t = {
thread::spawn(move|| {
- let mut v = Foo::NestedVariant(box 42, SendOnDrop {
+ let mut v = Foo::NestedVariant(Box::new(42), SendOnDrop {
sender: sender.clone()
}, sender.clone());
- v = Foo::NestedVariant(box 42,
+ v = Foo::NestedVariant(Box::new(42),
SendOnDrop { sender: sender.clone() },
sender.clone());
v = Foo::SimpleVariant(sender.clone());
#![allow(type_alias_bounds)]
#![allow(unused_features)]
-#![feature(box_syntax)]
#![feature(unsized_tuple_coercion)]
type Fat<T: ?Sized> = (isize, &'static str, T);
// run-pass
#![allow(type_alias_bounds)]
-#![feature(box_syntax)]
#![feature(unsized_tuple_coercion)]
type Fat<T: ?Sized> = (isize, &'static str, T);
assert_eq!((*f2)[1], 2);
// Nested Box.
- let f1 : Box<Fat<[isize; 3]>> = box (5, "some str", [1, 2, 3]);
+ let f1 : Box<Fat<[isize; 3]>> = Box::new((5, "some str", [1, 2, 3]));
foo(&*f1);
let f2 : Box<Fat<[isize]>> = f1;
foo(&*f2);
// run-pass
#![allow(unused_braces)]
-#![feature(box_syntax)]
fn test_generic<T, F>(expected: Box<T>, eq: F) where T: Clone, F: FnOnce(Box<T>, Box<T>) -> bool {
let actual: Box<T> = { expected.clone() };
println!("{}", *b2);
return *b1 == *b2;
}
- test_generic::<bool, _>(box true, compare_box);
+ test_generic::<bool, _>(Box::new(true), compare_box);
}
pub fn main() { test_box(); }
// run-pass
#![allow(unused_braces)]
-#![feature(box_syntax)]
fn test_generic<T, F>(expected: T, eq: F) where T: Clone, F: FnOnce(T, T) -> bool {
let actual: T = { expected.clone() };
fn test_vec() {
fn compare_vec(v1: Box<isize>, v2: Box<isize>) -> bool { return v1 == v2; }
- test_generic::<Box<isize>, _>(box 1, compare_vec);
+ test_generic::<Box<isize>, _>(Box::new(1), compare_vec);
}
pub fn main() { test_vec(); }
// run-pass
#![allow(unused_braces)]
-#![feature(box_syntax)]
-pub fn main() { let x: Box<_> = { box 100 }; assert_eq!(*x, 100); }
+pub fn main() { let x: Box<_> = { Box::new(100) }; assert_eq!(*x, 100); }
// run-pass
-#![feature(box_syntax)]
-
// Tests for if as expressions returning boxed types
fn test_box() {
- let rs: Box<_> = if true { box 100 } else { box 101 };
+ let rs: Box<_> = if true { Box::new(100) } else { Box::new(101) };
assert_eq!(*rs, 100);
}
--- /dev/null
+#![feature(stmt_expr_attributes)]
+#![feature(generators)]
+
+fn main() {
+ let _closure = #[track_caller] || {}; //~ `#[track_caller]` on closures
+ let _generator = #[track_caller] || { yield; }; //~ `#[track_caller]` on closures
+}
--- /dev/null
+error[E0658]: `#[track_caller]` on closures is currently unstable
+ --> $DIR/feature-gate-closure_track_caller.rs:5:20
+ |
+LL | let _closure = #[track_caller] || {};
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+ = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+error[E0658]: `#[track_caller]` on closures is currently unstable
+ --> $DIR/feature-gate-closure_track_caller.rs:6:22
+ |
+LL | let _generator = #[track_caller] || { yield; };
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
+ = help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
-#![feature(box_syntax)]
-
fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
+
+
fn main() {
- let _: () = (box |_: isize| {}) as Box<dyn FnOnce(isize)>;
+ let _: () = Box::new(|_: isize| {}) as Box<dyn FnOnce(isize)>;
//~^ ERROR mismatched types
//~| expected unit type `()`
//~| found struct `Box<dyn FnOnce(isize)>`
- let _: () = (box |_: isize, isize| {}) as Box<dyn Fn(isize, isize)>;
+ let _: () = Box::new(|_: isize, isize| {}) as Box<dyn Fn(isize, isize)>;
//~^ ERROR mismatched types
//~| expected unit type `()`
//~| found struct `Box<dyn Fn(isize, isize)>`
- let _: () = (box || -> isize { unimplemented!() }) as Box<dyn FnMut() -> isize>;
+ let _: () = Box::new(|| -> isize { unimplemented!() }) as Box<dyn FnMut() -> isize>;
//~^ ERROR mismatched types
//~| expected unit type `()`
//~| found struct `Box<dyn FnMut() -> isize>`
error[E0308]: mismatched types
--> $DIR/fn-trait-formatting.rs:6:17
|
-LL | let _: () = (box |_: isize| {}) as Box<dyn FnOnce(isize)>;
- | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
+LL | let _: () = Box::new(|_: isize| {}) as Box<dyn FnOnce(isize)>;
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
| |
| expected due to this
|
error[E0308]: mismatched types
--> $DIR/fn-trait-formatting.rs:10:17
|
-LL | let _: () = (box |_: isize, isize| {}) as Box<dyn Fn(isize, isize)>;
- | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
+LL | let _: () = Box::new(|_: isize, isize| {}) as Box<dyn Fn(isize, isize)>;
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
| |
| expected due to this
|
error[E0308]: mismatched types
--> $DIR/fn-trait-formatting.rs:14:17
|
-LL | let _: () = (box || -> isize { unimplemented!() }) as Box<dyn FnMut() -> isize>;
- | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
+LL | let _: () = Box::new(|| -> isize { unimplemented!() }) as Box<dyn FnMut() -> isize>;
+ | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found struct `Box`
| |
| expected due to this
|
|
= help: the trait `Fn<(isize,)>` is not implemented for `{integer}`
note: required by a bound in `needs_fn`
- --> $DIR/fn-trait-formatting.rs:3:31
+ --> $DIR/fn-trait-formatting.rs:1:31
|
LL | fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
| ^^^^^^^^^^^^^^^^^^ required by this bound in `needs_fn`
// This test verifies that temporaries created for `while`'s and `if`
// conditions are dropped after the condition is evaluated.
-#![feature(box_syntax)]
-
struct Temporary;
static mut DROPPED: isize = 0;
fn do_stuff(&self) -> bool {true}
}
-fn borrow() -> Box<Temporary> { box Temporary }
+fn borrow() -> Box<Temporary> { Box::new(Temporary) }
pub fn main() {
--> $DIR/gated-bad-feature.rs:5:1
|
LL | #![feature]
- | ^^^^^^^^^^^ help: must be of the form: `#[feature(name1, name1, ...)]`
+ | ^^^^^^^^^^^ help: must be of the form: `#![feature(name1, name1, ...)]`
error: malformed `feature` attribute input
--> $DIR/gated-bad-feature.rs:6:1
|
LL | #![feature = "foo"]
- | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[feature(name1, name1, ...)]`
+ | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![feature(name1, name1, ...)]`
error: aborting due to 5 previous errors
--- /dev/null
+#![feature(generic_associated_types)]
+
+trait GatTrait {
+ type Gat<'a>;
+
+ fn test(&self) -> Self::Gat<'_>;
+}
+
+trait SuperTrait<T>
+where
+ for<'a> Self: GatTrait<Gat<'a> = &'a T>,
+{
+ fn copy(&self) -> Self::Gat<'_> where T: Copy {
+ *self.test()
+ //~^ mismatched types
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-88360.rs:14:9
+ |
+LL | trait SuperTrait<T>
+ | - this type parameter
+...
+LL | fn copy(&self) -> Self::Gat<'_> where T: Copy {
+ | ------------- expected `&T` because of return type
+LL | *self.test()
+ | ^^^^^^^^^^^^
+ | |
+ | expected `&T`, found type parameter `T`
+ | help: consider borrowing here: `&*self.test()`
+ |
+ = note: expected reference `&T`
+ found type parameter `T`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
// run-pass
-#![feature(box_syntax)]
fn id<T:Send>(t: T) -> T { return t; }
pub fn main() {
- let expected: Box<_> = box 100;
+ let expected: Box<_> = Box::new(100);
let actual = id::<Box<isize>>(expected.clone());
println!("{}", *actual);
assert_eq!(*expected, *actual);
// run-pass
-#![feature(box_syntax)]
struct Recbox<T> {x: Box<T>}
-fn reclift<T>(t: T) -> Recbox<T> { return Recbox {x: box t}; }
+fn reclift<T>(t: T) -> Recbox<T> { return Recbox { x: Box::new(t) }; }
pub fn main() {
let foo: isize = 17;
// run-pass
-#![feature(box_syntax)]
fn f<T>(x: Box<T>) -> Box<T> { return x; }
-pub fn main() { let x = f(box 3); println!("{}", *x); }
+pub fn main() {
+ let x = f(Box::new(3));
+ println!("{}", *x);
+}
// run-pass
-#![feature(box_syntax)]
trait Foo<T> {
fn get(&self) -> T;
}
pub fn main() {
- let x = box S { x: 1 };
+ let x = Box::new(S { x: 1 });
let y = x as Box<dyn Foo<isize>>;
assert_eq!(y.get(), 1);
}
// run-pass
#![allow(non_camel_case_types)]
-#![feature(box_syntax)]
enum list<T> { cons(Box<T>, Box<list<T>>), nil, }
pub fn main() {
let _a: list<isize> =
- list::cons::<isize>(box 10,
- box list::cons::<isize>(box 12,
- box list::cons::<isize>(box 13,
- box list::nil::<isize>)));
+ list::cons::<isize>(Box::new(10),
+ Box::new(list::cons::<isize>(Box::new(12),
+ Box::new(list::cons::<isize>(Box::new(13),
+ Box::new(list::nil::<isize>))))));
}
// pretty-expanded FIXME #23616
#![allow(unused_variables)]
-#![feature(box_syntax)]
enum option<T> { some(Box<T>), none, }
pub fn main() {
- let mut a: option<isize> = option::some::<isize>(box 10);
+ let mut a: option<isize> = option::some::<isize>(Box::new(10));
a = option::none::<isize>;
}
// run-pass
#![allow(dead_code)]
-#![feature(box_syntax)]
struct Triple<T> { x: T, y: T, z: T }
-fn box_it<T>(x: Triple<T>) -> Box<Triple<T>> { return box x; }
+fn box_it<T>(x: Triple<T>) -> Box<Triple<T>> { return Box::new(x); }
pub fn main() {
let x: Box<Triple<isize>> = box_it::<isize>(Triple{x: 1, y: 2, z: 3});
|
LL | send(cycle2().clone());
| ^^^^
- = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+ = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
note: ...which requires computing type of `cycle2::{opaque#0}`...
--> $DIR/auto-trait-leak.rs:19:16
|
|
LL | send(cycle1().clone());
| ^^^^
- = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
+ = note: ...which requires evaluating trait selection obligation `impl core::clone::Clone: core::marker::Send`...
= note: ...which again requires computing type of `cycle1::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> $DIR/auto-trait-leak.rs:1:1
// error-pattern: reached the recursion limit while auto-dereferencing
-#![feature(box_syntax)]
+
use std::ops::Deref;
pub fn main() {
let mut x;
loop {
- x = box x;
+ x = Box::new(x);
x.foo;
x.bar();
}
error[E0308]: mismatched types
--> $DIR/infinite-autoderef.rs:20:13
|
-LL | x = box x;
- | ^^^^^ cyclic type of infinite size
- |
-help: try using a conversion method
- |
-LL | x = (box x).to_string();
- | + +++++++++++++
+LL | x = Box::new(x);
+ | ^^^^^^^^^^^- help: try using a conversion method: `.to_string()`
+ | |
+ | cyclic type of infinite size
error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
--> $DIR/infinite-autoderef.rs:25:5
#![allow(non_camel_case_types)]
#![allow(dead_code)]
-#![feature(box_syntax)]
use std::cell::Cell;
fn test_unique() {
let i = &Cell::new(0);
{
- let _a: Box<_> = box r(i);
+ let _a: Box<_> = Box::new(r(i));
}
assert_eq!(i.get(), 1);
}
fn test_unique_rec() {
let i = &Cell::new(0);
{
- let _a: Box<_> = box BoxR {
+ let _a: Box<_> = Box::new(BoxR {
x: r(i)
- };
+ });
}
assert_eq!(i.get(), 1);
}
// run-pass
-#![feature(box_syntax)]
#![feature(intrinsics)]
mod rusti {
pub fn main() {
unsafe {
- let mut x: Box<_> = box 1;
+ let mut x: Box<_> = Box::new(1);
assert_eq!(rusti::atomic_load(&*x), 1);
*x = 5;
// ignore-wasm32-bare compiled with panic=abort by default
// revisions: mir thir
// [thir]compile-flags: -Zthir-unsafeck
+// ignore-tidy-linelength
// This test checks panic emitted from `mem::{uninitialized,zeroed}`.
test_panic_msg(
|| mem::uninitialized::<*const dyn Send>(),
- "attempted to leave type `*const dyn std::marker::Send` uninitialized, which is invalid"
+ "attempted to leave type `*const dyn core::marker::Send` uninitialized, which is invalid"
);
test_panic_msg(
|| mem::zeroed::<*const dyn Send>(),
- "attempted to zero-initialize type `*const dyn std::marker::Send`, which is invalid"
+ "attempted to zero-initialize type `*const dyn core::marker::Send`, which is invalid"
);
/* FIXME(#66151) we conservatively do not error here yet.
test_panic_msg(
|| mem::uninitialized::<(NonNull<u32>, u32, u32)>(),
- "attempted to leave type `(std::ptr::NonNull<u32>, u32, u32)` uninitialized, \
+ "attempted to leave type `(core::ptr::non_null::NonNull<u32>, u32, u32)` uninitialized, \
which is invalid"
);
test_panic_msg(
|| mem::zeroed::<(NonNull<u32>, u32, u32)>(),
- "attempted to zero-initialize type `(std::ptr::NonNull<u32>, u32, u32)`, \
+ "attempted to zero-initialize type `(core::ptr::non_null::NonNull<u32>, u32, u32)`, \
which is invalid"
);
);
test_panic_msg(
|| mem::uninitialized::<ManuallyDrop<LR>>(),
- "attempted to leave type `std::mem::ManuallyDrop<LR>` uninitialized, which is invalid"
+ "attempted to leave type `core::mem::manually_drop::ManuallyDrop<LR>` uninitialized, which is invalid"
);
// Some things that should work.
--- /dev/null
+#![crate_type = foo!()] //~ ERROR malformed `crate_type` attribute
+
+macro_rules! foo {
+ () => {"rlib"};
+}
+
+fn main() {}
--- /dev/null
+error: malformed `crate_type` attribute input
+ --> $DIR/invalid-crate-type-macro.rs:1:1
+ |
+LL | #![crate_type = foo!()]
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]`
+
+error: aborting due to previous error
+
--> $DIR/invalid_crate_type_syntax.rs:2:1
|
LL | #![crate_type(lib)]
- | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[crate_type = "bin|lib|..."]`
+ | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]`
error: aborting due to previous error
-#![feature(box_syntax)]
-
trait Foo {
}
+
+
impl<T:Copy> Foo for T {
}
fn take_param<T:Foo>(foo: &T) { }
fn main() {
- let x: Box<_> = box 3;
+ let x: Box<_> = Box::new(3);
take_param(&x);
//~^ ERROR the trait bound `Box<{integer}>: Foo` is not satisfied
}
// Issue #14061: tests the interaction between generic implementation
// parameter bounds and trait objects.
-#![feature(box_syntax)]
+
use std::marker;
}
fn foo2<'a>() {
- let t: Box<S<String>> = box S(marker::PhantomData);
+ let t: Box<S<String>> = Box::new(S(marker::PhantomData));
let a = t as Box<dyn Gettable<String>>;
//~^ ERROR : Copy` is not satisfied
}
fn foo3<'a>() {
struct Foo; // does not impl Copy
- let t: Box<S<Foo>> = box S(marker::PhantomData);
+ let t: Box<S<Foo>> = Box::new(S(marker::PhantomData));
let a: Box<dyn Gettable<Foo>> = t;
//~^ ERROR : Copy` is not satisfied
}
// revisions: curr object_safe_for_dispatch
#![cfg_attr(object_safe_for_dispatch, feature(object_safe_for_dispatch))]
-#![feature(box_syntax)]
+
use std::any::Any;
fn take_param<T:Foo>(foo: &T) { }
fn a() {
- let x: Box<_> = box 3;
+ let x: Box<_> = Box::new(3);
take_param(&x); //[curr]~ ERROR E0277
//[object_safe_for_dispatch]~^ ERROR E0277
}
fn b() {
- let x: Box<_> = box 3;
+ let x: Box<_> = Box::new(3);
let y = &x;
let z = &x as &dyn Foo;
//[curr]~^ ERROR E0038
--- /dev/null
+// Make sure that an error is reported if the `call` function of the
+// `fn`/`fn_mut` lang item is grossly ill-formed.
+
+#![feature(lang_items)]
+#![feature(no_core)]
+#![no_core]
+
+#[lang = "fn"]
+trait MyFn<T> {
+ const call: i32 = 42;
+ //~^ ERROR: `call` trait item in `fn` lang item must be a function
+}
+
+#[lang = "fn_mut"]
+trait MyFnMut<T> {
+ fn call(i: i32, j: i32) -> i32 { i + j }
+ //~^ ERROR: first argument of `call` in `fn_mut` lang item must be a reference
+}
+
+fn main() {
+ let a = || 42;
+ a();
+
+ let mut i = 0;
+ let mut b = || { i += 1; };
+ b();
+}
--- /dev/null
+error: `call` trait item in `fn` lang item must be a function
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:10:5
+ |
+LL | const call: i32 = 42;
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: first argument of `call` in `fn_mut` lang item must be a reference
+ --> $DIR/fn-fn_mut-call-ill-formed.rs:16:16
+ |
+LL | fn call(i: i32, j: i32) -> i32 { i + j }
+ | ^^^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// Regression test for the ICE reported in issue #83471.
+
+#![crate_type="lib"]
+#![feature(no_core)]
+#![no_core]
+
+#[lang = "sized"]
+//~^ ERROR: language items are subject to change [E0658]
+trait Sized {}
+
+#[lang = "fn"]
+//~^ ERROR: language items are subject to change [E0658]
+//~| ERROR: `fn` language item must be applied to a trait with 1 generic argument
+trait Fn {
+ fn call(export_name);
+ //~^ ERROR: expected type
+ //~| WARNING: anonymous parameters are deprecated
+ //~| WARNING: this is accepted in the current edition
+}
+fn call_through_fn_trait() {
+ a()
+ //~^ ERROR: cannot find function
+}
--- /dev/null
+error[E0573]: expected type, found built-in attribute `export_name`
+ --> $DIR/issue-83471.rs:15:13
+ |
+LL | fn call(export_name);
+ | ^^^^^^^^^^^ not a type
+
+error[E0425]: cannot find function `a` in this scope
+ --> $DIR/issue-83471.rs:21:5
+ |
+LL | a()
+ | ^ not found in this scope
+
+error[E0658]: language items are subject to change
+ --> $DIR/issue-83471.rs:7:1
+ |
+LL | #[lang = "sized"]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = help: add `#![feature(lang_items)]` to the crate attributes to enable
+
+error[E0658]: language items are subject to change
+ --> $DIR/issue-83471.rs:11:1
+ |
+LL | #[lang = "fn"]
+ | ^^^^^^^^^^^^^^
+ |
+ = help: add `#![feature(lang_items)]` to the crate attributes to enable
+
+warning: anonymous parameters are deprecated and will be removed in the next edition.
+ --> $DIR/issue-83471.rs:15:13
+ |
+LL | fn call(export_name);
+ | ^^^^^^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: export_name`
+ |
+ = note: `#[warn(anonymous_parameters)]` on by default
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+
+error[E0718]: `fn` language item must be applied to a trait with 1 generic argument
+ --> $DIR/issue-83471.rs:11:1
+ |
+LL | #[lang = "fn"]
+ | ^^^^^^^^^^^^^^
+...
+LL | trait Fn {
+ | - this trait has 0 generic arguments
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0425, E0573, E0658, E0718.
+For more information about an error, try `rustc --explain E0425`.
#![allow(dead_code)]
// Make sure #1399 stays fixed
-#![feature(box_syntax)]
-
struct A { a: Box<isize> }
pub fn main() {
fn invoke<F>(f: F) where F: FnOnce() { f(); }
- let k: Box<_> = box 22;
+ let k: Box<_> = 22.into();
let _u = A {a: k.clone()};
invoke(|| println!("{}", k.clone()) )
}
// run-pass
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
fn leaky<T>(_t: T) { }
-pub fn main() { let x = box 10; leaky::<Box<isize>>(x); }
+pub fn main() {
+ let x = Box::new(10);
+ leaky::<Box<isize>>(x);
+}
--- /dev/null
+// Regression test for the ICE described in #79546.
+
+// compile-flags: --cap-lints=allow -Zfuel=issue79546=0
+// check-pass
+#![crate_name="issue79546"]
+
+struct S;
+fn main() {}
--> $DIR/lint-malformed.rs:1:1
|
LL | #![deny = "foo"]
- | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[deny(lint1, lint2, ..., /*opt*/ reason = "...")]`
+ | ^^^^^^^^^^^^^^^^ help: must be of the form: `#![deny(lint1, lint2, ..., /*opt*/ reason = "...")]`
error[E0452]: malformed lint attribute input
--> $DIR/lint-malformed.rs:2:10
#![allow(dead_code)]
#![forbid(box_pointers)]
-#![feature(box_syntax)]
+
struct Foo {
x: Box<isize> //~ ERROR type uses owned
}
fn main() {
- let _x : Foo = Foo {x : box 10};
+ let _x: Foo = Foo { x : Box::new(10) };
//~^ ERROR type uses owned
}
error: type uses owned (Box type) pointers: Box<isize>
--> $DIR/lint-owned-heap-memory.rs:10:29
|
-LL | let _x : Foo = Foo {x : box 10};
- | ^^^^^^
+LL | let _x: Foo = Foo { x : Box::new(10) };
+ | ^^^^^^^^^^^^
error: aborting due to 2 previous errors
--- /dev/null
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"]
+struct Umm {
+ i: i64
+}
+
+
+fn bar() -> Box<Umm> {
+ Box::new(Umm {
+ i: 1
+ })
+}
+
+async fn other() {}
+
+pub async fn uhoh() {
+ let _guard = bar(); //~ ERROR boxed `Umm` held across
+ other().await;
+}
+
+fn main() {
+}
--- /dev/null
+error: boxed `Umm` held across a suspend point, but should not be
+ --> $DIR/boxed.rs:20:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+LL | other().await;
+ | ------------- the value is held across this suspend point
+ |
+note: the lint level is defined here
+ --> $DIR/boxed.rs:3:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+note: You gotta use Umm's, ya know?
+ --> $DIR/boxed.rs:20:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/boxed.rs:20:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend]
+struct No {}
+
+async fn shushspend() {}
+
+async fn wheeee<T>(t: T) {
+ shushspend().await;
+ drop(t);
+}
+
+async fn yes() {
+ wheeee(No {}).await; //~ ERROR `No` held across
+}
+
+fn main() {
+}
--- /dev/null
+error: `No` held across a suspend point, but should not be
+ --> $DIR/dedup.rs:16:12
+ |
+LL | wheeee(No {}).await;
+ | -------^^^^^------- the value is held across this suspend point
+ |
+note: the lint level is defined here
+ --> $DIR/dedup.rs:3:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/dedup.rs:16:12
+ |
+LL | wheeee(No {}).await;
+ | ^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// edition:2018
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"] //~ ERROR the `#[must_not_suspend]`
+struct Umm {
+ _i: i64
+}
+
+fn main() {
+}
--- /dev/null
+error[E0658]: the `#[must_not_suspend]` attribute is an experimental feature
+ --> $DIR/feature-gate-must_not_suspend.rs:3:1
+ |
+LL | #[must_not_suspend = "You gotta use Umm's, ya know?"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
+ = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// edition:2018
+// run-pass
+//
+// this test shows a case where the lint doesn't fire in generic code
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend]
+struct No {}
+
+async fn shushspend() {}
+
+async fn wheeee<T>(t: T) {
+ shushspend().await;
+ drop(t);
+}
+
+fn main() {
+ let _fut = wheeee(No {});
+}
--- /dev/null
+// edition:2018
+// run-pass
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"]
+struct Umm {
+ _i: i64
+}
+
+
+fn bar() -> Umm {
+ Umm {
+ _i: 1
+ }
+}
+
+async fn other() {}
+
+pub async fn uhoh() {
+ {
+ let _guard = bar();
+ }
+ other().await;
+}
+
+fn main() {
+}
--- /dev/null
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend] //~ ERROR attribute should be
+mod inner {}
+
+fn main() {}
--- /dev/null
+error: `must_not_suspend` attribute should be applied to a struct, enum, or trait
+ --> $DIR/other_items.rs:5:1
+ |
+LL | #[must_not_suspend]
+ | ^^^^^^^^^^^^^^^^^^^
+LL | mod inner {}
+ | ------------ is not a struct, enum, or trait
+
+error: aborting due to previous error
+
--- /dev/null
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"]
+struct Umm {
+ i: i64
+}
+
+struct Bar {
+ u: Umm,
+}
+
+async fn other() {}
+
+impl Bar {
+ async fn uhoh(&mut self) {
+ let guard = &mut self.u; //~ ERROR `Umm` held across
+
+ other().await;
+
+ *guard = Umm {
+ i: 2
+ }
+ }
+}
+
+fn main() {
+}
--- /dev/null
+error: `Umm` held across a suspend point, but should not be
+ --> $DIR/ref.rs:18:26
+ |
+LL | let guard = &mut self.u;
+ | ^^^^^^
+LL |
+LL | other().await;
+ | ------------- the value is held across this suspend point
+ |
+note: the lint level is defined here
+ --> $DIR/ref.rs:3:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+note: You gotta use Umm's, ya know?
+ --> $DIR/ref.rs:18:26
+ |
+LL | let guard = &mut self.u;
+ | ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/ref.rs:18:26
+ |
+LL | let guard = &mut self.u;
+ | ^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend] //~ ERROR attribute should be
+fn foo() -> i32 {
+ 0
+}
+fn main() {}
--- /dev/null
+error: `must_not_suspend` attribute should be applied to a struct, enum, or trait
+ --> $DIR/return.rs:5:1
+ |
+LL | #[must_not_suspend]
+ | ^^^^^^^^^^^^^^^^^^^
+LL | / fn foo() -> i32 {
+LL | | 0
+LL | | }
+ | |_- is not a struct, enum, or trait
+
+error: aborting due to previous error
+
--- /dev/null
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend]
+trait Wow {}
+
+impl Wow for i32 {}
+
+fn r#impl() -> impl Wow {
+ 1
+}
+
+fn r#dyn() -> Box<dyn Wow> {
+ Box::new(1)
+}
+
+async fn other() {}
+
+pub async fn uhoh() {
+ let _guard1 = r#impl(); //~ ERROR implementer of `Wow` held across
+ let _guard2 = r#dyn(); //~ ERROR boxed `Wow` trait object held across
+
+ other().await;
+}
+
+fn main() {
+}
--- /dev/null
+error: implementer of `Wow` held across a suspend point, but should not be
+ --> $DIR/trait.rs:21:9
+ |
+LL | let _guard1 = r#impl();
+ | ^^^^^^^
+...
+LL | other().await;
+ | ------------- the value is held across this suspend point
+ |
+note: the lint level is defined here
+ --> $DIR/trait.rs:3:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/trait.rs:21:9
+ |
+LL | let _guard1 = r#impl();
+ | ^^^^^^^
+
+error: boxed `Wow` trait object held across a suspend point, but should not be
+ --> $DIR/trait.rs:22:9
+ |
+LL | let _guard2 = r#dyn();
+ | ^^^^^^^
+LL |
+LL | other().await;
+ | ------------- the value is held across this suspend point
+ |
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/trait.rs:22:9
+ |
+LL | let _guard2 = r#dyn();
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// edition:2018
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"]
+struct Umm {
+ i: i64
+}
+
+
+fn bar() -> Umm {
+ Umm {
+ i: 1
+ }
+}
+
+async fn other() {}
+
+pub async fn uhoh() {
+ let _guard = bar(); //~ ERROR `Umm` held across
+ other().await;
+}
+
+fn main() {
+}
--- /dev/null
+error: `Umm` held across a suspend point, but should not be
+ --> $DIR/unit.rs:20:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+LL | other().await;
+ | ------------- the value is held across this suspend point
+ |
+note: the lint level is defined here
+ --> $DIR/unit.rs:3:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+note: You gotta use Umm's, ya know?
+ --> $DIR/unit.rs:20:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/unit.rs:20:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// edition:2018
+// run-pass
+#![feature(must_not_suspend)]
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"]
+struct Umm {
+ _i: i64
+}
+
+
+fn bar() -> Umm {
+ Umm {
+ _i: 1
+ }
+}
+
+async fn other() {}
+
+pub async fn uhoh() {
+ let _guard = bar(); //~ WARNING `Umm` held across
+ other().await;
+}
+
+fn main() {
+}
--- /dev/null
+warning: `Umm` held across a suspend point, but should not be
+ --> $DIR/warn.rs:20:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+LL | other().await;
+ | ------------- the value is held across this suspend point
+ |
+ = note: `#[warn(must_not_suspend)]` on by default
+note: You gotta use Umm's, ya know?
+ --> $DIR/warn.rs:20:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/warn.rs:20:9
+ |
+LL | let _guard = bar();
+ | ^^^^^^
+
+warning: 1 warning emitted
+
// check-pass
-#![feature(box_syntax)]
#![feature(box_patterns)]
+
#![warn(unused)] // UI tests pass `-A unused` (#43896)
struct SoulHistory {
};
// Boxed struct
- match box bag {
+ match Box::new(bag) {
box Large::Suit { case } => {} //~ WARNING unused variable: `case`
};
#![allow(non_camel_case_types)]
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
enum list { cons(isize, Box<list>), nil, }
-pub fn main() { list::cons(10, box list::cons(11, box list::cons(12, box list::nil))); }
+pub fn main() {
+ list::cons(10, Box::new(list::cons(11, Box::new(list::cons(12, Box::new(list::nil))))));
+}
-#![feature(box_syntax)]
-
fn take(_x: Box<isize>) {}
+
fn main() {
- let x: Box<isize> = box 25;
+ let x: Box<isize> = Box::new(25);
+
loop {
take(x); //~ ERROR use of moved value: `x`
}
error[E0382]: use of moved value: `x`
--> $DIR/liveness-move-call-arg.rs:9:14
|
-LL | let x: Box<isize> = box 25;
+LL | let x: Box<isize> = Box::new(25);
| - move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
-LL | loop {
+...
LL | take(x);
| ^ value moved here, in previous iteration of loop
-#![feature(box_syntax)]
-
fn main() {
- let y: Box<isize> = box 42;
+
+ let y: Box<isize> = 42.into();
let mut x: Box<isize>;
+
loop {
println!("{}", y);
loop {
error[E0382]: use of moved value: `y`
--> $DIR/liveness-move-in-loop.rs:11:25
|
-LL | let y: Box<isize> = box 42;
+LL | let y: Box<isize> = 42.into();
| - move occurs because `y` has type `Box<isize>`, which does not implement the `Copy` trait
...
LL | x = y;
-#![feature(box_syntax)]
-
fn main() {
- let y: Box<isize> = box 42;
+
+ let y: Box<isize> = 42.into();
let mut x: Box<isize>;
+
loop {
println!("{}", y); //~ ERROR borrow of moved value: `y`
while true { while true { while true { x = y; x.clone(); } } }
error[E0382]: borrow of moved value: `y`
--> $DIR/liveness-move-in-while.rs:7:24
|
-LL | let y: Box<isize> = box 42;
+LL | let y: Box<isize> = 42.into();
| - move occurs because `y` has type `Box<isize>`, which does not implement the `Copy` trait
...
LL | println!("{}", y);
-#![feature(box_syntax)]
-
fn main() {
- let x: Box<_> = box 5;
+
+ let x: Box<_> = 5.into();
let y = x;
+
println!("{}", *x); //~ ERROR borrow of moved value: `x`
y.clone();
}
error[E0382]: borrow of moved value: `x`
--> $DIR/liveness-use-after-move.rs:6:20
|
-LL | let x: Box<_> = box 5;
+LL | let x: Box<_> = 5.into();
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
LL | let y = x;
| - value moved here
+LL |
LL | println!("{}", *x);
| ^^ value borrowed here after move
--- /dev/null
+// run-rustfix
+#[allow(unused_macros)]
+
+macro_rules! foo { //~ ERROR macro names aren't followed by a `!`
+ () => {};
+}
+
+fn main() {}
--- /dev/null
+// run-rustfix
+#[allow(unused_macros)]
+
+macro_rules! foo! { //~ ERROR macro names aren't followed by a `!`
+ () => {};
+}
+
+fn main() {}
--- /dev/null
+error: macro names aren't followed by a `!`
+ --> $DIR/bang-after-name.rs:4:17
+ |
+LL | macro_rules! foo! {
+ | ^ help: remove the `!`
+
+error: aborting due to previous error
+
--> $DIR/malformed-plugin-1.rs:2:1
|
LL | #![plugin]
- | ^^^^^^^^^^ help: must be of the form: `#[plugin(name)]`
+ | ^^^^^^^^^^ help: must be of the form: `#![plugin(name)]`
warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
--> $DIR/malformed-plugin-1.rs:2:1
--> $DIR/malformed-plugin-2.rs:2:1
|
LL | #![plugin="bleh"]
- | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[plugin(name)]`
+ | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#![plugin(name)]`
warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
--> $DIR/malformed-plugin-2.rs:2:1
-#![feature(box_syntax)]
-
use std::collections::HashMap;
+
+
trait Map<K, V>
{
fn get(&self, k: K) -> V { panic!() }
// Test that trait types printed in error msgs include the type arguments.
fn main() {
- let x: Box<HashMap<isize, isize>> = box HashMap::new();
+ let x: Box<HashMap<isize, isize>> = HashMap::new().into();
let x: Box<dyn Map<isize, isize>> = x;
let y: Box<dyn Map<usize, isize>> = Box::new(x);
//~^ ERROR `Box<dyn Map<isize, isize>>: Map<usize, isize>` is not satisfied
#![crate_type = "lib"]
-#![feature(box_syntax)]
-
static mut COUNT: u64 = 1;
pub fn get_count() -> u64 { unsafe { COUNT } }
Foo::baz(self);
Foo::baz(*x);
- Foo::qux(box self);
- Foo::qux(box *x);
+ Foo::qux(Box::new(self));
+ Foo::qux(Box::new(*x));
}
pub fn bar(&self) {
#![crate_type = "lib"]
-#![feature(box_syntax)]
-
static mut COUNT: u64 = 1;
pub fn get_count() -> u64 { unsafe { COUNT } }
// Test internal call.
Bar::foo1(&self);
Bar::foo2(self);
- Bar::foo3(box self);
+ Bar::foo3(Box::new(self));
Bar::bar1(&self);
Bar::bar2(self);
- Bar::bar3(box self);
+ Bar::bar3(Box::new(self));
}
}
// run-pass
// Test method calls with self as an argument (cross-crate)
-#![feature(box_syntax)]
-
// aux-build:method_self_arg1.rs
extern crate method_self_arg1;
use method_self_arg1::Foo;
// Test external call.
Foo::bar(&x);
Foo::baz(x);
- Foo::qux(box x);
+ Foo::qux(Box::new(x));
x.foo(&x);
// run-pass
// Test method calls with self as an argument (cross-crate)
-#![feature(box_syntax)]
-
// aux-build:method_self_arg2.rs
extern crate method_self_arg2;
use method_self_arg2::{Foo, Bar};
// Test external call.
Bar::foo1(&x);
Bar::foo2(x);
- Bar::foo3(box x);
+ Bar::foo3(Box::new(x));
Bar::bar1(&x);
Bar::bar2(x);
- Bar::bar3(box x);
+ Bar::bar3(Box::new(x));
x.run_trait();
// run-pass
// Test method calls with self as an argument
-#![feature(box_syntax)]
-
static mut COUNT: u64 = 1;
#[derive(Copy, Clone)]
// Test internal call.
Bar::foo1(&self);
Bar::foo2(self);
- Bar::foo3(box self);
+ Bar::foo3(Box::new(self));
Bar::bar1(&self);
Bar::bar2(self);
- Bar::bar3(box self);
+ Bar::bar3(Box::new(self));
}
}
// Test external call.
Bar::foo1(&x);
Bar::foo2(x);
- Bar::foo3(box x);
+ Bar::foo3(Box::new(x));
Bar::bar1(&x);
Bar::bar2(x);
- Bar::bar3(box x);
+ Bar::bar3(Box::new(x));
x.baz();
// run-pass
// Test method calls with self as an argument
-#![feature(box_syntax)]
-
static mut COUNT: usize = 1;
#[derive(Copy, Clone)]
Foo::baz(self);
Foo::baz(*x);
- Foo::qux(box self);
- Foo::qux(box *x);
+ Foo::qux(Box::new(self));
+ Foo::qux(Box::new(*x));
}
fn bar(&self) {
// Test external call.
Foo::bar(&x);
Foo::baz(x);
- Foo::qux(box x);
+ Foo::qux(Box::new(x));
x.foo(&x);
// codegen the call as `Foo::foo(&x)` and let the specific impl get
// chosen later.
-#![feature(box_syntax)]
-
trait Foo {
fn foo(&self) -> isize;
}
fn call_foo_other() -> isize {
let mut x: Vec<_> = Vec::new();
let y = x.foo();
- let z: Box<i32> = box 0;
+ let z: Box<i32> = Box::new(0);
x.push(z);
y
}
--- /dev/null
+#[path = 123] //~ ERROR malformed `path` attribute
+mod foo;
+
+fn main() {}
--- /dev/null
+error: malformed `path` attribute input
+ --> $DIR/path-invalid-form.rs:1:1
+ |
+LL | #[path = 123]
+ | ^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]`
+
+error: aborting due to previous error
+
--- /dev/null
+macro_rules! foo {
+ () => {"bar.rs"};
+}
+
+#[path = foo!()] //~ ERROR malformed `path` attribute
+mod abc;
+
+fn main() {}
--- /dev/null
+error: malformed `path` attribute input
+ --> $DIR/path-macro.rs:5:1
+ |
+LL | #[path = foo!()]
+ | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]`
+
+error: aborting due to previous error
+
// run-pass
#![allow(unused_mut)]
#![allow(dead_code)]
-#![feature(box_syntax)]
#[derive(Clone)]
struct Triple {
fn test(x: bool, foo: Box<Triple>) -> isize {
let bar = foo;
let mut y: Box<Triple>;
- if x { y = bar; } else { y = box Triple{x: 4, y: 5, z: 6}; }
+ if x { y = bar; } else { y = Box::new(Triple{x: 4, y: 5, z: 6}); }
return y.y;
}
pub fn main() {
- let x: Box<_> = box Triple{x: 1, y: 2, z: 3};
+ let x: Box<_> = Box::new(Triple{x: 1, y: 2, z: 3});
assert_eq!(test(true, x.clone()), 2);
assert_eq!(test(true, x.clone()), 2);
assert_eq!(test(true, x.clone()), 2);
// run-pass
#![allow(dead_code)]
-#![feature(box_syntax)]
struct X { x: isize, y: isize, z: isize }
pub fn main() {
- let x: Box<_> = box X{x: 1, y: 2, z: 3};
+ let x: Box<_> = Box::new(X {x: 1, y: 2, z: 3});
let y = x;
assert_eq!(y.y, 2);
}
// run-pass
#![allow(dead_code)]
-#![feature(box_syntax)]
struct X { x: isize, y: isize, z: isize }
-pub fn main() { let x: Box<_> = box X {x: 1, y: 2, z: 3}; let y = x; assert_eq!(y.y, 2); }
+pub fn main() { let x: Box<_> = Box::new(X {x: 1, y: 2, z: 3}); let y = x; assert_eq!(y.y, 2); }
// run-pass
#![allow(unused_mut)]
#![allow(dead_code)]
-#![feature(box_syntax)]
#[derive(Clone)]
struct Triple {
fn test(x: bool, foo: Box<Triple>) -> isize {
let bar = foo;
let mut y: Box<Triple>;
- if x { y = bar; } else { y = box Triple {x: 4, y: 5, z: 6}; }
+ if x { y = bar; } else { y = Box::new(Triple {x: 4, y: 5, z: 6}); }
return y.y;
}
pub fn main() {
- let x: Box<_> = box Triple{x: 1, y: 2, z: 3};
+ let x: Box<_> = Box::new(Triple{x: 1, y: 2, z: 3});
for _ in 0_usize..10000_usize {
assert_eq!(test(true, x.clone()), 2);
}
// run-pass
#![allow(dead_code)]
-#![feature(box_syntax)]
struct Triple {a: isize, b: isize, c: isize}
}
pub fn main() {
- let x = box Triple{a: 1, b: 2, c: 3};
+ let x = Box::new(Triple{a: 1, b: 2, c: 3});
let y = test(x);
assert_eq!(y.c, 3);
}
// run-pass
#![allow(dead_code)]
-#![feature(box_syntax)]
struct Triple { a: isize, b: isize, c: isize }
}
pub fn main() {
- let x = box Triple{a: 1, b: 2, c: 3};
+ let x = Box::new(Triple{ a: 1, b: 2, c: 3 });
let y = test(x);
assert_eq!(y.c, 3);
}
// run-pass
-#![feature(box_syntax)]
fn test(foo: Box<Vec<isize>> ) { assert_eq!((*foo)[0], 10); }
pub fn main() {
- let x = box vec![10];
+ let x = Box::new(vec![10]);
// Test forgetting a local by move-in
test(x);
// Test forgetting a temporary by move-in.
- test(box vec![10]);
+ test(Box::new(vec![10]));
}
// run-pass
-#![feature(box_syntax)]
fn test(foo: Box<Vec<isize>>) { assert_eq!((*foo)[0], 10); }
pub fn main() {
- let x = box vec![10];
+ let x = Box::new(vec![10]);
// Test forgetting a local by move-in
test(x);
// Test forgetting a temporary by move-in.
- test(box vec![10]);
+ test(Box::new(vec![10]));
}
// that assumption did not hold, at least not in the long run (namely,
// overlapping patterns were turned into warnings rather than errors).
-#![feature(box_syntax)]
+
fn main() {
- let x: Box<_> = box 1;
+ let x: Box<_> = Box::new(1);
let v = (1, 2);
error[E0382]: use of moved value: `x`
--> $DIR/move-guard-same-consts.rs:20:24
|
-LL | let x: Box<_> = box 1;
+LL | let x: Box<_> = Box::new(1);
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
...
LL | (1, 2) if take(x) => (),
-#![feature(box_syntax)]
-
pub fn main() {
- let x: Box<_> = box 1;
+
+
+ let x: Box<_> = Box::new(1);
let v = (1, 2);
error[E0382]: use of moved value: `x`
--> $DIR/move-in-guard-1.rs:10:24
|
-LL | let x: Box<_> = box 1;
+LL | let x: Box<_> = Box::new(1);
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
...
LL | (1, _) if take(x) => (),
-#![feature(box_syntax)]
-
pub fn main() {
- let x: Box<_> = box 1;
+ let x: Box<_> = Box::new(1);
let v = (1, 2);
error[E0382]: use of moved value: `x`
- --> $DIR/move-in-guard-2.rs:10:24
+ --> $DIR/move-in-guard-2.rs:8:24
|
-LL | let x: Box<_> = box 1;
+LL | let x: Box<_> = Box::new(1);
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
...
LL | (_, 2) if take(x) => (),
-#![feature(box_syntax)]
-
struct Foo(Box<isize>);
+
+
fn main() {
- let x: (Box<_>,) = (box 1,);
+ let x: (Box<_>,) = (Box::new(1),);
let y = x.0;
let z = x.0; //~ ERROR use of moved value: `x.0`
- let x = Foo(box 1);
+ let x = Foo(Box::new(1));
let y = x.0;
let z = x.0; //~ ERROR use of moved value: `x.0`
}
#![feature(box_patterns)]
-#![feature(box_syntax)]
+
struct S {
x: Box<E>
}
fn main() {
- let s = S { x: box E::Bar(box 42) };
+ let s = S { x: Box::new(E::Bar(Box::new(42))) };
loop {
f(&s, |hellothere| {
match hellothere.x { //~ ERROR cannot move out
-#![feature(box_syntax, unboxed_closures)]
+#![feature(unboxed_closures)]
fn to_fn<A,F:Fn<A>>(f: F) -> F { f }
fn test(_x: Box<usize>) {}
fn main() {
- let i = box 3;
+ let i = Box::new(3);
let _f = to_fn(|| test(i)); //~ ERROR cannot move out
}
error[E0507]: cannot move out of `i`, a captured variable in an `Fn` closure
--> $DIR/moves-based-on-type-move-out-of-closure-env-issue-1965.rs:9:28
|
-LL | let i = box 3;
+LL | let i = Box::new(3);
| - captured outer variable
LL | let _f = to_fn(|| test(i));
| --------^-
-#![feature(box_syntax)]
-
fn dup(x: Box<isize>) -> Box<(Box<isize>,Box<isize>)> {
- box (x, x)
+
+
+ Box::new((x, x))
//~^ use of moved value: `x` [E0382]
}
fn main() {
- dup(box 3);
+ dup(Box::new(3));
}
error[E0382]: use of moved value: `x`
- --> $DIR/moves-based-on-type-tuple.rs:4:13
+ --> $DIR/moves-based-on-type-tuple.rs:4:18
|
LL | fn dup(x: Box<isize>) -> Box<(Box<isize>,Box<isize>)> {
| - move occurs because `x` has type `Box<isize>`, which does not implement the `Copy` trait
-LL | box (x, x)
- | - ^ value used here after move
- | |
- | value moved here
+...
+LL | Box::new((x, x))
+ | - ^ value used here after move
+ | |
+ | value moved here
error: aborting due to previous error
-#![feature(box_syntax)]
-
type Noncopyable = Box<isize>;
+
+
struct Foo {
copied: isize,
moved: Box<isize>,
fn test0(f: Foo, g: Noncopyable, h: Noncopyable) {
// just copy implicitly copyable fields from `f`, no moves:
- let _b = Foo {moved: box 1, noncopyable: g, ..f};
- let _c = Foo {moved: box 2, noncopyable: h, ..f};
+ let _b = Foo {moved: Box::new(1), noncopyable: g, ..f};
+ let _c = Foo {moved: Box::new(2), noncopyable: h, ..f};
}
fn test1(f: Foo, g: Noncopyable, h: Noncopyable) {
// run-pass
-#![feature(box_syntax)]
-
fn f(mut y: Box<isize>) {
*y = 5;
assert_eq!(*y, 5);
fn g() {
let frob = |mut q: Box<isize>| { *q = 2; assert_eq!(*q, 2); };
- let w = box 37;
+ let w = Box::new(37);
frob(w);
}
pub fn main() {
- let z = box 17;
+ let z = Box::new(17);
f(z);
g();
}
-#![feature(box_syntax)]
-
fn f(_: &mut isize) {}
fn main() {
- let mut x: Box<_> = box 3;
+
+ let mut x: Box<_> = Box::new(3);
+
f(x) //~ ERROR mismatched types
}
--- /dev/null
+error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied
+ --> $DIR/defaulted-never-note.rs:30:5
+ |
+LL | foo(_x);
+ | ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!`
+ |
+ = note: this trait is implemented for `()`.
+ = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information).
+ = help: did you intend to use the type `()` here instead?
+note: required by a bound in `foo`
+ --> $DIR/defaulted-never-note.rs:25:11
+ |
+LL | fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
+// revisions: nofallback fallback
+//[nofallback] run-pass
+//[fallback] check-fail
+
// We need to opt into the `never_type_fallback` feature
// to trigger the requirement that this is testing.
-#![feature(never_type, never_type_fallback)]
+#![cfg_attr(fallback, feature(never_type, never_type_fallback))]
#![allow(unused)]
impl ImplementedForUnitButNotNever for () {}
fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
-//~^ NOTE required by this bound in `foo`
-//~| NOTE required by a bound in `foo`
+//[fallback]~^ NOTE required by this bound in `foo`
+//[fallback]~| NOTE required by a bound in `foo`
fn smeg() {
let _x = return;
foo(_x);
- //~^ ERROR the trait bound
- //~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented
- //~| NOTE this trait is implemented for `()`
- //~| NOTE this error might have been caused
- //~| HELP did you intend
+ //[fallback]~^ ERROR the trait bound
+ //[fallback]~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented
+ //[fallback]~| NOTE this trait is implemented for `()`
+ //[fallback]~| NOTE this error might have been caused
+ //[fallback]~| HELP did you intend
}
fn main() {
+++ /dev/null
-error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied
- --> $DIR/defaulted-never-note.rs:26:5
- |
-LL | foo(_x);
- | ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!`
- |
- = note: this trait is implemented for `()`.
- = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information).
- = help: did you intend to use the type `()` here instead?
-note: required by a bound in `foo`
- --> $DIR/defaulted-never-note.rs:21:11
- |
-LL | fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
+// revisions: nofallback fallback
// run-pass
#![allow(dead_code)]
#![allow(unused_assignments)]
#![allow(unused_variables)]
#![allow(unreachable_code)]
-
// Test various cases where we permit an unconstrained variable
-// to fallback based on control-flow.
-//
-// These represent current behavior, but are pretty dubious. I would
-// like to revisit these and potentially change them. --nmatsakis
-
-#![feature(never_type, never_type_fallback)]
+// to fallback based on control-flow. In all of these cases,
+// the type variable winds up being the target of both a `!` coercion
+// and a coercion from a non-`!` variable, and hence falls back to `()`.
+#![cfg_attr(fallback, feature(never_type, never_type_fallback))]
-trait BadDefault {
+trait UnitDefault {
fn default() -> Self;
}
-impl BadDefault for u32 {
+impl UnitDefault for u32 {
fn default() -> Self {
0
}
}
-impl BadDefault for ! {
- fn default() -> ! {
+impl UnitDefault for () {
+ fn default() -> () {
panic!()
}
}
let x;
if true {
- x = BadDefault::default();
+ x = UnitDefault::default();
} else {
x = return;
}
if true {
x = return;
} else {
- x = BadDefault::default();
+ x = UnitDefault::default();
}
}
fn if_then_else() {
let _x = if true {
- BadDefault::default()
+ UnitDefault::default()
} else {
return;
};
let _x = if true {
return;
} else {
- BadDefault::default()
+ UnitDefault::default()
};
}
fn match_arm() {
- let _x = match Ok(BadDefault::default()) {
+ let _x = match Ok(UnitDefault::default()) {
Ok(v) => v,
Err(()) => return,
};
}
fn match_arm_rev() {
- let _x = match Ok(BadDefault::default()) {
+ let _x = match Ok(UnitDefault::default()) {
Err(()) => return,
Ok(v) => v,
};
if false {
break return;
} else {
- break BadDefault::default();
+ break UnitDefault::default();
}
};
}
if false {
break return;
} else {
- break BadDefault::default();
+ break UnitDefault::default();
}
};
}
-fn main() { }
+fn main() {}
--- /dev/null
+error[E0277]: the trait bound `!: Test` is not satisfied
+ --> $DIR/diverging-fallback-no-leak.rs:17:5
+ |
+LL | unconstrained_arg(return);
+ | ^^^^^^^^^^^^^^^^^ the trait `Test` is not implemented for `!`
+ |
+ = note: this trait is implemented for `()`.
+ = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information).
+ = help: did you intend to use the type `()` here instead?
+note: required by a bound in `unconstrained_arg`
+ --> $DIR/diverging-fallback-no-leak.rs:12:25
+ |
+LL | fn unconstrained_arg<T: Test>(_: T) {}
+ | ^^^^ required by this bound in `unconstrained_arg`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+// revisions: nofallback fallback
+//[nofallback] check-pass
+
+#![cfg_attr(fallback, feature(never_type, never_type_fallback))]
+
+fn make_unit() {}
+
+trait Test {}
+impl Test for i32 {}
+impl Test for () {}
+
+fn unconstrained_arg<T: Test>(_: T) {}
+
+fn main() {
+ // Here the type variable falls back to `!`,
+ // and hence we get a type error.
+ unconstrained_arg(return);
+ //[fallback]~^ ERROR trait bound `!: Test` is not satisfied
+}
--- /dev/null
+// Variant of diverging-falllback-control-flow that tests
+// the specific case of a free function with an unconstrained
+// return type. This captures the pattern we saw in the wild
+// in the objc crate, where changing the fallback from `!` to `()`
+// resulted in unsoundness.
+//
+// check-pass
+
+// revisions: nofallback fallback
+
+#![cfg_attr(fallback, feature(never_type, never_type_fallback))]
+
+
+fn make_unit() {}
+
+trait UnitReturn {}
+impl UnitReturn for i32 {}
+impl UnitReturn for () {}
+
+fn unconstrained_return<T: UnitReturn>() -> T {
+ unsafe {
+ let make_unit_fn: fn() = make_unit;
+ let ffi: fn() -> T = std::mem::transmute(make_unit_fn);
+ ffi()
+ }
+}
+
+fn main() {
+ // In Ye Olde Days, the `T` parameter of `unconstrained_return`
+ // winds up "entangled" with the `!` type that results from
+ // `panic!`, and hence falls back to `()`. This is kind of unfortunate
+ // and unexpected. When we introduced the `!` type, the original
+ // idea was to change that fallback to `!`, but that would have resulted
+ // in this code no longer compiling (or worse, in some cases it injected
+ // unsound results).
+ let _ = if true { unconstrained_return() } else { panic!() };
+}
--- /dev/null
+// This test verifies that never type fallback preserves the following code in a
+// compiling state. This pattern is fairly common in the wild, notably seen in
+// wasmtime v0.16. Typically this is some closure wrapper that expects a
+// collection of 'known' signatures, and -> ! is not included in that set.
+//
+// This test is specifically targeted by the unit type fallback when
+// encountering a set of obligations like `?T: Foo` and `Trait::Projection =
+// ?T`. In the code below, these are `R: Bar` and `Fn::Output = R`.
+//
+// revisions: nofallback fallback
+// check-pass
+
+#![cfg_attr(fallback, feature(never_type_fallback))]
+
+trait Bar { }
+impl Bar for () { }
+impl Bar for u32 { }
+
+fn foo<R: Bar>(_: impl Fn() -> R) {}
+
+fn main() {
+ foo(|| panic!());
+}
--- /dev/null
+error[E0271]: type mismatch resolving `<[closure@$DIR/fallback-closure-wrap.rs:18:40: 21:6] as FnOnce<()>>::Output == ()`
+ --> $DIR/fallback-closure-wrap.rs:18:31
+ |
+LL | let error = Closure::wrap(Box::new(move || {
+ | _______________________________^
+LL | |
+LL | | panic!("Can't connect to server.");
+LL | | }) as Box<dyn FnMut()>);
+ | |______^ expected `()`, found `!`
+ |
+ = note: expected unit type `()`
+ found type `!`
+ = note: required for the cast to the object type `dyn FnMut()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
--- /dev/null
+// This is a minified example from Crater breakage observed when attempting to
+// stabilize never type, nstoddard/webgl-gui @ 22f0169f.
+//
+// This particular test case currently fails as the inference to `()` rather
+// than `!` happens as a result of an `as` cast, which is not currently tracked.
+// Crater did not find many cases of this occuring, but it is included for
+// awareness.
+//
+// revisions: nofallback fallback
+//[nofallback] check-pass
+//[fallback] check-fail
+
+#![cfg_attr(fallback, feature(never_type_fallback))]
+
+use std::marker::PhantomData;
+
+fn main() {
+ let error = Closure::wrap(Box::new(move || {
+ //[fallback]~^ ERROR type mismatch resolving
+ panic!("Can't connect to server.");
+ }) as Box<dyn FnMut()>);
+}
+
+struct Closure<T: ?Sized>(PhantomData<T>);
+
+impl<T: ?Sized> Closure<T> {
+ fn wrap(data: Box<T>) -> Closure<T> {
+ todo!()
+ }
+}
--- /dev/null
+error[E0277]: the trait bound `E: From<()>` is not satisfied
+ --> $DIR/never-value-fallback-issue-66757.rs:27:5
+ |
+LL | <E as From<_>>::from(never);
+ | ^^^^^^^^^^^^^^^^^^^^ the trait `From<()>` is not implemented for `E`
+ |
+ = help: the following implementations were found:
+ <E as From<!>>
+note: required by `from`
+ --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
+ |
+LL | fn from(_: T) -> Self;
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
// never) and an uninferred variable (here the argument to `From`) it
// doesn't fallback to `()` but rather `!`.
//
-// run-pass
+// revisions: nofallback fallback
+//[fallback] run-pass
+//[nofallback] check-fail
#![feature(never_type)]
-// FIXME(#67225) -- this should be true even without the fallback gate.
-#![feature(never_type_fallback)]
+#![cfg_attr(fallback, feature(never_type_fallback))]
struct E;
#[allow(dead_code)]
fn foo(never: !) {
<E as From<!>>::from(never); // Ok
- <E as From<_>>::from(never); // Inference fails here
+ <E as From<_>>::from(never); //[nofallback]~ ERROR trait bound `E: From<()>` is not satisfied
}
fn main() { }
* http://creativecommons.org/publicdomain/zero/1.0/ */
#![allow(dead_code, unused_variables)]
-#![feature(box_syntax)]
// Tests that the new `box` syntax works with unique pointers.
}
pub fn main() {
- let y: Box<isize> = box 2;
- let b: Box<isize> = box (1 + 2);
- let c = box (3 + 4);
+ let y: Box<isize> = Box::new(2);
+ let b: Box<isize> = Box::new(1 + 2);
+ let c = Box::new(3 + 4);
- let s: Box<Structure> = box Structure {
+ let s: Box<Structure> = Box::new(Structure {
x: 3,
y: 4,
- };
+ });
}
// run-pass
-#![feature(box_syntax)]
-
fn f(x: Box<isize>) {
let y: &isize = &*x;
println!("{}", *x);
}
fn main() {
- f(box 1234);
- g(box Struct as Box<dyn Trait>);
+ f(Box::new(1234));
+ g(Box::new(Struct) as Box<dyn Trait>);
}
-#![feature(box_syntax)]
-
trait Foo { fn get(&self); }
impl<A> Foo for A {
fn get(&self) { }
}
+
+
fn main() {
let _ = {
let tmp0 = 3;
let tmp1 = &tmp0;
- box tmp1 as Box<dyn Foo + '_>
+ Box::new(tmp1) as Box<dyn Foo + '_>
};
//~^^^ ERROR `tmp0` does not live long enough
}
|
LL | let tmp1 = &tmp0;
| ^^^^^ borrowed value does not live long enough
-LL | box tmp1 as Box<dyn Foo + '_>
- | ----------------------------- borrow later captured here by trait object
+LL | Box::new(tmp1) as Box<dyn Foo + '_>
+ | ----------------------------------- borrow later captured here by trait object
LL | };
| - `tmp0` dropped here while still borrowed
--> $DIR/no_crate_type.rs:2:1
|
LL | #![crate_type]
- | ^^^^^^^^^^^^^^ help: must be of the form: `#[crate_type = "bin|lib|..."]`
+ | ^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]`
error: aborting due to previous error
// run-pass
-#![feature(box_syntax)]
-
// Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions,
// which "says that a destructor applied to an object built from a constructor
// behaves as expected". -- https://coq.inria.fr/doc/language/core/conversion.html#iota-reduction
pub fn main() {
check_type!(&17, &isize);
- check_type!(box 18, Box<isize>);
+ check_type!(Box::new(18), Box<isize>);
check_type!("foo".to_string(), String);
check_type!(vec![20, 22], Vec<isize>);
check_type!(main, fn(), |pthing| {
// closed over do not contain managed values, and thus the boxes do
// not have headers.
-#![feature(box_syntax)]
-
-
trait FooTrait {
fn foo(&self) -> usize;
}
pub fn main() {
let foos: Vec<Box<dyn FooTrait>> = vec![
- box BarStruct{ x: 0 } as Box<dyn FooTrait>,
- box BarStruct{ x: 1 } as Box<dyn FooTrait>,
- box BarStruct{ x: 2 } as Box<dyn FooTrait>
+ Box::new(BarStruct{ x: 0 }) as Box<dyn FooTrait>,
+ Box::new(BarStruct{ x: 1 }) as Box<dyn FooTrait>,
+ Box::new(BarStruct{ x: 2 }) as Box<dyn FooTrait>,
];
for i in 0..foos.len() {
// closed over contain managed values. This implies that the boxes
// will have headers that must be skipped over.
-#![feature(box_syntax)]
-
trait FooTrait {
fn foo(self: Box<Self>) -> usize;
}
}
pub fn main() {
- let foo = box BarStruct{ x: 22 } as Box<dyn FooTrait>;
+ let foo = Box::new(BarStruct{ x: 22 }) as Box<dyn FooTrait>;
assert_eq!(22, foo.foo());
}
-#![feature(box_syntax)]
-
fn main() {
+
let f;
let g;
+
g = f;
- f = box g;
+ f = Box::new(g);
//~^ ERROR mismatched types
//~| cyclic type of infinite size
}
error[E0308]: mismatched types
--> $DIR/occurs-check-2.rs:7:9
|
-LL | f = box g;
- | ^^^^^ cyclic type of infinite size
- |
-help: try using a conversion method
- |
-LL | f = (box g).to_string();
- | + +++++++++++++
+LL | f = Box::new(g);
+ | ^^^^^^^^^^^- help: try using a conversion method: `.to_string()`
+ | |
+ | cyclic type of infinite size
error: aborting due to previous error
-#![feature(box_syntax)]
-
fn main() {
+
let f;
- f = box f;
+
+ f = Box::new(f);
//~^ ERROR mismatched types
//~| cyclic type of infinite size
}
error[E0308]: mismatched types
--> $DIR/occurs-check.rs:5:9
|
-LL | f = box f;
- | ^^^^^ cyclic type of infinite size
- |
-help: try using a conversion method
- |
-LL | f = (box f).to_string();
- | + +++++++++++++
+LL | f = Box::new(f);
+ | ^^^^^^^^^^^- help: try using a conversion method: `.to_string()`
+ | |
+ | cyclic type of infinite size
error: aborting due to previous error
#![allow(dead_assignment)]
#![allow(unused_variables)]
-#![feature(box_syntax)]
struct A { a: isize, b: isize }
struct Abox { a: Box<isize>, b: Box<isize> }
fn ret_int_i() -> isize { 10 }
-fn ret_ext_i() -> Box<isize> { box 10 }
+fn ret_ext_i() -> Box<isize> { Box::new(10) }
fn ret_int_rec() -> A { A {a: 10, b: 10} }
-fn ret_ext_rec() -> Box<A> { box A {a: 10, b: 10} }
+fn ret_ext_rec() -> Box<A> { Box::new(A {a: 10, b: 10}) }
-fn ret_ext_mem() -> Abox { Abox {a: box 10, b: box 10} }
+fn ret_ext_mem() -> Abox { Abox {a: Box::new(10), b: Box::new(10) } }
-fn ret_ext_ext_mem() -> Box<Abox> { box Abox{a: box 10, b: box 10} }
+fn ret_ext_ext_mem() -> Box<Abox> { Box::new(Abox{a: Box::new(10), b: Box::new(10) }) }
pub fn main() {
let mut int_i: isize;
#![allow(unused_variables)]
#![allow(stable_features)]
-#![feature(box_syntax, core)]
-
use std::cell::RefCell;
use std::rc::Rc;
}
pub fn main() {
- let box_5: Box<_> = box 5_usize;
+ let box_5: Box<_> = Box::new(5_usize);
let point = Rc::new(Point {x: 2, y: 4});
assert_eq!(point.x, 2);
assert_eq!(point.y, 4);
// Test overloaded indexing combined with autoderef.
-#![feature(box_syntax, core)]
-
use std::ops::{Index, IndexMut};
struct Foo {
}
fn main() {
- let mut f: Box<_> = box Foo {
+ let mut f: Box<_> = Box::new(Foo {
x: 1,
y: 2,
- };
+ });
assert_eq!(f[1], 2);
// error-pattern:meep
// ignore-emscripten no processes
-#![feature(box_syntax)]
-
fn f(_a: isize, _b: isize, _c: Box<isize>) {
panic!("moop");
}
fn main() {
- f(1, panic!("meep"), box 42);
+ f(1, panic!("meep"), Box::new(42));
}
// error-pattern:panicked at 'Box<dyn Any>'
// ignore-emscripten no processes
-#![feature(box_syntax)]
#![allow(non_fmt_panics)]
fn main() {
- panic!(box 413 as Box<dyn std::any::Any + Send>);
+ panic!(Box::new(413) as Box<dyn std::any::Any + Send>);
}
help: if `bar` is a function, use the arguments directly
|
LL - bar(baz: $rest)
-LL + bar(true);
+LL + bar(: $rest)
|
error: aborting due to 2 previous errors
--- /dev/null
+// Regression test for the ICE described in #88770.
+
+// error-pattern:this file contains an unclosed delimiter
+// error-pattern:expected one of
+// error-pattern:missing `in` in `for` loop
+// error-pattern:expected `;`, found `e`
+
+fn m(){print!("",(c for&g
+u
+e
+e
--- /dev/null
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-88770.rs:11:3
+ |
+LL | fn m(){print!("",(c for&g
+ | - - - unclosed delimiter
+ | | |
+ | | unclosed delimiter
+ | unclosed delimiter
+...
+LL | e
+ | ^
+
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-88770.rs:11:3
+ |
+LL | fn m(){print!("",(c for&g
+ | - - - unclosed delimiter
+ | | |
+ | | unclosed delimiter
+ | unclosed delimiter
+...
+LL | e
+ | ^
+
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-88770.rs:11:3
+ |
+LL | fn m(){print!("",(c for&g
+ | - - - unclosed delimiter
+ | | |
+ | | unclosed delimiter
+ | unclosed delimiter
+...
+LL | e
+ | ^
+
+error: missing `in` in `for` loop
+ --> $DIR/issue-88770.rs:8:26
+ |
+LL | fn m(){print!("",(c for&g
+ | __________________________^
+LL | | u
+ | |_ help: try adding `in` here
+
+error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found keyword `for`
+ --> $DIR/issue-88770.rs:8:21
+ |
+LL | fn m(){print!("",(c for&g
+ | ^^^ expected one of 8 possible tokens
+
+error: expected `;`, found `e`
+ --> $DIR/issue-88770.rs:10:2
+ |
+LL | e
+ | ^ help: add `;` here
+LL | e
+ | - unexpected token
+
+error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `)`
+ --> $DIR/issue-88770.rs:11:3
+ |
+LL | e
+ | ^ expected one of 7 possible tokens
+
+error: aborting due to 7 previous errors
+
// build-pass (FIXME(62277): could be check-pass?)
-#![feature(box_syntax)]
#![allow(bare_trait_objects)]
use std::fmt::Debug;
fn main() {
- let x: Box<Debug+> = box 3 as Box<Debug+>; // Trailing `+` is OK
+ let x: Box<Debug+> = Box::new(3) as Box<Debug+>; // Trailing `+` is OK
}
--- /dev/null
+// Regression test for #88684: Improve diagnostics for combining marks
+// in character literals.
+
+// run-rustfix
+
+fn main() {
+ let _spade = "♠️";
+ //~^ ERROR: character literal may only contain one codepoint
+ //~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}`
+ //~| HELP: if you meant to write a `str` literal, use double quotes
+
+ let _s = "ṩ̂̊";
+ //~^ ERROR: character literal may only contain one codepoint
+ //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
+ //~| HELP: if you meant to write a `str` literal, use double quotes
+
+ let _a = 'Å';
+ //~^ ERROR: character literal may only contain one codepoint
+ //~| NOTE: this `A` is followed by the combining mark `\u{30a}`
+ //~| HELP: consider using the normalized form `\u{c5}` of this character
+}
--- /dev/null
+// Regression test for #88684: Improve diagnostics for combining marks
+// in character literals.
+
+// run-rustfix
+
+fn main() {
+ let _spade = '♠️';
+ //~^ ERROR: character literal may only contain one codepoint
+ //~| NOTE: this `♠` is followed by the combining mark `\u{fe0f}`
+ //~| HELP: if you meant to write a `str` literal, use double quotes
+
+ let _s = 'ṩ̂̊';
+ //~^ ERROR: character literal may only contain one codepoint
+ //~| NOTE: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
+ //~| HELP: if you meant to write a `str` literal, use double quotes
+
+ let _a = 'Å';
+ //~^ ERROR: character literal may only contain one codepoint
+ //~| NOTE: this `A` is followed by the combining mark `\u{30a}`
+ //~| HELP: consider using the normalized form `\u{c5}` of this character
+}
--- /dev/null
+error: character literal may only contain one codepoint
+ --> $DIR/unicode-character-literal.rs:7:18
+ |
+LL | let _spade = '♠️';
+ | ^^^
+ |
+note: this `♠` is followed by the combining mark `\u{fe0f}`
+ --> $DIR/unicode-character-literal.rs:7:19
+ |
+LL | let _spade = '♠️';
+ | ^
+help: if you meant to write a `str` literal, use double quotes
+ |
+LL | let _spade = "♠️";
+ | ~~~
+
+error: character literal may only contain one codepoint
+ --> $DIR/unicode-character-literal.rs:12:14
+ |
+LL | let _s = 'ṩ̂̊';
+ | ^^^
+ |
+note: this `s` is followed by the combining marks `\u{323}\u{307}\u{302}\u{30a}`
+ --> $DIR/unicode-character-literal.rs:12:15
+ |
+LL | let _s = 'ṩ̂̊';
+ | ^
+help: if you meant to write a `str` literal, use double quotes
+ |
+LL | let _s = "ṩ̂̊";
+ | ~~~
+
+error: character literal may only contain one codepoint
+ --> $DIR/unicode-character-literal.rs:17:14
+ |
+LL | let _a = 'Å';
+ | ^-^
+ | |
+ | help: consider using the normalized form `\u{c5}` of this character: `Å`
+ |
+note: this `A` is followed by the combining mark `\u{30a}`
+ --> $DIR/unicode-character-literal.rs:17:15
+ |
+LL | let _a = 'Å';
+ | ^
+
+error: aborting due to 3 previous errors
+
#![feature(box_patterns)]
-#![feature(box_syntax)]
#![allow(dead_code)]
#![allow(unused_variables)]
#![deny(unreachable_patterns)]
+
enum IntList {
Cons(isize, Box<IntList>),
Nil
fn tail(source_list: &IntList) -> IntList {
match source_list {
&IntList::Cons(val, box ref next_list) => tail(next_list),
- &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, box IntList::Nil),
-//~^ ERROR unreachable pattern
- _ => panic!()
+ &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)),
+ //~^ ERROR unreachable pattern
+ _ => panic!(),
}
}
error: unreachable pattern
--> $DIR/issue-12116.rs:15:9
|
-LL | &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, box IntList::Nil),
+LL | &IntList::Cons(val, box IntList::Nil) => IntList::Cons(val, Box::new(IntList::Nil)),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/issue-12116.rs:5:9
+ --> $DIR/issue-12116.rs:4:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
#![feature(box_patterns)]
-#![feature(box_syntax)]
struct HTMLImageData {
image: Option<String>
fn main() {
let mut id = HTMLImageData { image: None };
- let ed = ElementData { kind: box ElementKind::HTMLImageElement(id) };
- let n = NodeData {kind : box NodeKind::Element(ed)};
+ let ed = ElementData { kind: Box::new(ElementKind::HTMLImageElement(id)) };
+ let n = NodeData { kind: Box::new(NodeKind::Element(ed)) };
+
// n.b. span could be better
match n.kind {
box NodeKind::Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
+++ /dev/null
-// gate-test-macro_attributes_in_derive_output
-// aux-build: test-macros.rs
-
-#![feature(proc_macro_hygiene)]
-#![feature(stmt_expr_attributes)]
-
-#[macro_use]
-extern crate test_macros;
-
-#[derive(Empty)]
-#[empty_attr] //~ ERROR macro attributes in `#[derive]` output are unstable
-struct S1 {
- field: [u8; 10],
-}
-
-#[derive(Empty)]
-#[empty_helper]
-#[empty_attr] //~ ERROR macro attributes in `#[derive]` output are unstable
-struct S2 {
- field: [u8; 10],
-}
-
-#[derive(Empty)]
-struct S3 {
- field: [u8; #[identity_attr] 10], //~ ERROR macro attributes in `#[derive]` output are unstable
-}
-
-#[derive(Empty)]
-struct S4 {
- field: [u8; {
- #[derive(Empty)] // OK, not gated
- struct Inner;
- 10
- }]
-}
-
-fn main() {}
+++ /dev/null
-error[E0658]: macro attributes in `#[derive]` output are unstable
- --> $DIR/attribute-after-derive-feature-gate.rs:11:3
- |
-LL | #[empty_attr]
- | ^^^^^^^^^^
- |
- = note: see issue #81119 <https://github.com/rust-lang/rust/issues/81119> for more information
- = help: add `#![feature(macro_attributes_in_derive_output)]` to the crate attributes to enable
-
-error[E0658]: macro attributes in `#[derive]` output are unstable
- --> $DIR/attribute-after-derive-feature-gate.rs:18:3
- |
-LL | #[empty_attr]
- | ^^^^^^^^^^
- |
- = note: see issue #81119 <https://github.com/rust-lang/rust/issues/81119> for more information
- = help: add `#![feature(macro_attributes_in_derive_output)]` to the crate attributes to enable
-
-error[E0658]: macro attributes in `#[derive]` output are unstable
- --> $DIR/attribute-after-derive-feature-gate.rs:25:19
- |
-LL | field: [u8; #[identity_attr] 10],
- | ^^^^^^^^^^^^^
- |
- = note: see issue #81119 <https://github.com/rust-lang/rust/issues/81119> for more information
- = help: add `#![feature(macro_attributes_in_derive_output)]` to the crate attributes to enable
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
// compile-flags: -Z span-debug
// aux-build: test-macros.rs
-#![feature(macro_attributes_in_derive_output)]
-
#![no_std] // Don't load unnecessary hygiene information from std
extern crate std;
Punct {
ch: '#',
spacing: Alone,
- span: $DIR/attribute-after-derive.rs:17:1: 17:2 (#0),
+ span: $DIR/attribute-after-derive.rs:15:1: 15:2 (#0),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "derive",
- span: $DIR/attribute-after-derive.rs:17:3: 17:9 (#0),
+ span: $DIR/attribute-after-derive.rs:15:3: 15:9 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "Print",
- span: $DIR/attribute-after-derive.rs:17:10: 17:15 (#0),
+ span: $DIR/attribute-after-derive.rs:15:10: 15:15 (#0),
},
],
- span: $DIR/attribute-after-derive.rs:17:9: 17:16 (#0),
+ span: $DIR/attribute-after-derive.rs:15:9: 15:16 (#0),
},
],
- span: $DIR/attribute-after-derive.rs:17:2: 17:17 (#0),
+ span: $DIR/attribute-after-derive.rs:15:2: 15:17 (#0),
},
Ident {
ident: "struct",
- span: $DIR/attribute-after-derive.rs:18:1: 18:7 (#0),
+ span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0),
},
Ident {
ident: "AttributeDerive",
- span: $DIR/attribute-after-derive.rs:18:8: 18:23 (#0),
+ span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0),
},
Group {
delimiter: Brace,
Punct {
ch: '#',
spacing: Alone,
- span: $DIR/attribute-after-derive.rs:19:5: 19:6 (#0),
+ span: $DIR/attribute-after-derive.rs:17:5: 17:6 (#0),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "cfg",
- span: $DIR/attribute-after-derive.rs:19:7: 19:10 (#0),
+ span: $DIR/attribute-after-derive.rs:17:7: 17:10 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "FALSE",
- span: $DIR/attribute-after-derive.rs:19:11: 19:16 (#0),
+ span: $DIR/attribute-after-derive.rs:17:11: 17:16 (#0),
},
],
- span: $DIR/attribute-after-derive.rs:19:10: 19:17 (#0),
+ span: $DIR/attribute-after-derive.rs:17:10: 17:17 (#0),
},
],
- span: $DIR/attribute-after-derive.rs:19:6: 19:18 (#0),
+ span: $DIR/attribute-after-derive.rs:17:6: 17:18 (#0),
},
Ident {
ident: "field",
- span: $DIR/attribute-after-derive.rs:20:5: 20:10 (#0),
+ span: $DIR/attribute-after-derive.rs:18:5: 18:10 (#0),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/attribute-after-derive.rs:20:10: 20:11 (#0),
+ span: $DIR/attribute-after-derive.rs:18:10: 18:11 (#0),
},
Ident {
ident: "u8",
- span: $DIR/attribute-after-derive.rs:20:12: 20:14 (#0),
+ span: $DIR/attribute-after-derive.rs:18:12: 18:14 (#0),
},
Punct {
ch: ',',
spacing: Alone,
- span: $DIR/attribute-after-derive.rs:20:14: 20:15 (#0),
+ span: $DIR/attribute-after-derive.rs:18:14: 18:15 (#0),
},
],
- span: $DIR/attribute-after-derive.rs:18:24: 21:2 (#0),
+ span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0),
},
]
PRINT-DERIVE INPUT (DISPLAY): struct AttributeDerive { }
PRINT-DERIVE INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
- span: $DIR/attribute-after-derive.rs:18:1: 18:7 (#0),
+ span: $DIR/attribute-after-derive.rs:16:1: 16:7 (#0),
},
Ident {
ident: "AttributeDerive",
- span: $DIR/attribute-after-derive.rs:18:8: 18:23 (#0),
+ span: $DIR/attribute-after-derive.rs:16:8: 16:23 (#0),
},
Group {
delimiter: Brace,
stream: TokenStream [],
- span: $DIR/attribute-after-derive.rs:18:24: 21:2 (#0),
+ span: $DIR/attribute-after-derive.rs:16:24: 19:2 (#0),
},
]
PRINT-DERIVE INPUT (DISPLAY): #[print_attr] struct DeriveAttribute { }
Punct {
ch: '#',
spacing: Alone,
- span: $DIR/attribute-after-derive.rs:24:1: 24:2 (#0),
+ span: $DIR/attribute-after-derive.rs:22:1: 22:2 (#0),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "print_attr",
- span: $DIR/attribute-after-derive.rs:24:3: 24:13 (#0),
+ span: $DIR/attribute-after-derive.rs:22:3: 22:13 (#0),
},
],
- span: $DIR/attribute-after-derive.rs:24:2: 24:14 (#0),
+ span: $DIR/attribute-after-derive.rs:22:2: 22:14 (#0),
},
Ident {
ident: "struct",
- span: $DIR/attribute-after-derive.rs:25:1: 25:7 (#0),
+ span: $DIR/attribute-after-derive.rs:23:1: 23:7 (#0),
},
Ident {
ident: "DeriveAttribute",
- span: $DIR/attribute-after-derive.rs:25:8: 25:23 (#0),
+ span: $DIR/attribute-after-derive.rs:23:8: 23:23 (#0),
},
Group {
delimiter: Brace,
stream: TokenStream [],
- span: $DIR/attribute-after-derive.rs:25:24: 28:2 (#0),
+ span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0),
},
]
-PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { }
+PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { #[cfg(FALSE)] field : u8, }
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
- span: $DIR/attribute-after-derive.rs:25:1: 25:7 (#0),
+ span: $DIR/attribute-after-derive.rs:23:1: 23:7 (#0),
},
Ident {
ident: "DeriveAttribute",
- span: $DIR/attribute-after-derive.rs:25:8: 25:23 (#0),
+ span: $DIR/attribute-after-derive.rs:23:8: 23:23 (#0),
},
Group {
delimiter: Brace,
- stream: TokenStream [],
- span: $DIR/attribute-after-derive.rs:25:24: 28:2 (#0),
+ stream: TokenStream [
+ Punct {
+ ch: '#',
+ spacing: Alone,
+ span: $DIR/attribute-after-derive.rs:24:5: 24:6 (#0),
+ },
+ Group {
+ delimiter: Bracket,
+ stream: TokenStream [
+ Ident {
+ ident: "cfg",
+ span: $DIR/attribute-after-derive.rs:24:7: 24:10 (#0),
+ },
+ Group {
+ delimiter: Parenthesis,
+ stream: TokenStream [
+ Ident {
+ ident: "FALSE",
+ span: $DIR/attribute-after-derive.rs:24:11: 24:16 (#0),
+ },
+ ],
+ span: $DIR/attribute-after-derive.rs:24:10: 24:17 (#0),
+ },
+ ],
+ span: $DIR/attribute-after-derive.rs:24:6: 24:18 (#0),
+ },
+ Ident {
+ ident: "field",
+ span: $DIR/attribute-after-derive.rs:25:5: 25:10 (#0),
+ },
+ Punct {
+ ch: ':',
+ spacing: Alone,
+ span: $DIR/attribute-after-derive.rs:25:10: 25:11 (#0),
+ },
+ Ident {
+ ident: "u8",
+ span: $DIR/attribute-after-derive.rs:25:12: 25:14 (#0),
+ },
+ Punct {
+ ch: ',',
+ spacing: Alone,
+ span: $DIR/attribute-after-derive.rs:25:14: 25:15 (#0),
+ },
+ ],
+ span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0),
},
]
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
fn sums_to(v: Vec<isize> , sum: isize) -> bool {
let mut i = 0;
let mut sum0 = 0;
fn sums_to_using_uniq(v: Vec<isize> , sum: isize) -> bool {
let mut i = 0;
- let mut sum0: Box<_> = box 0;
+ let mut sum0: Box<_> = 0.into();
while i < v.len() {
*sum0 += v[i];
i += 1;
fn sums_to_using_uniq_rec(v: Vec<isize> , sum: isize) -> bool {
let mut i = 0;
- let mut sum0 = F::<Box<_>> {f: box 0};
+ let mut sum0 = F::<Box<_>> {f: 0.into() };
while i < v.len() {
*sum0.f += v[i];
i += 1;
// run-pass
#![allow(non_camel_case_types)]
-#![feature(box_syntax)]
trait get {
fn get(self) -> isize;
}
pub fn main() {
- let x: Box<_> = box 6;
+ let x: Box<_> = 6.into();
let y = x.get();
println!("y={}", y);
assert_eq!(y, 6);
-#![feature(box_syntax)]
#![allow(unused_variables)]
+
#![deny(unreachable_code)]
fn main() {
#![feature(box_patterns)]
-#![feature(box_syntax)]
+
#![allow(dead_code)]
#![deny(unreachable_patterns)]
//~ ERROR cycle detected when computing layout of `S`
-//~| NOTE ...which requires computing layout of `std::option::Option<<S as Mirror>::It>`...
-//~| NOTE ...which requires computing layout of `std::option::Option<S>`...
+//~| NOTE ...which requires computing layout of `core::option::Option<<S as Mirror>::It>`...
+//~| NOTE ...which requires computing layout of `core::option::Option<S>`...
//~| NOTE ...which again requires computing layout of `S`, completing the cycle
-//~| NOTE cycle used when computing layout of `std::option::Option<S>`
+//~| NOTE cycle used when computing layout of `core::option::Option<S>`
// build-fail
error[E0391]: cycle detected when computing layout of `S`
|
- = note: ...which requires computing layout of `std::option::Option<<S as Mirror>::It>`...
- = note: ...which requires computing layout of `std::option::Option<S>`...
+ = note: ...which requires computing layout of `core::option::Option<<S as Mirror>::It>`...
+ = note: ...which requires computing layout of `core::option::Option<S>`...
= note: ...which again requires computing layout of `S`, completing the cycle
- = note: cycle used when computing layout of `std::option::Option<S>`
+ = note: cycle used when computing layout of `core::option::Option<S>`
error: aborting due to previous error
--- /dev/null
+#![recursion_limit = 123] //~ ERROR malformed `recursion_limit` attribute
+
+fn main() {}
--- /dev/null
+error: malformed `recursion_limit` attribute input
+ --> $DIR/invalid_digit_type.rs:1:1
+ |
+LL | #![recursion_limit = 123]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]`
+
+error: aborting due to previous error
+
--- /dev/null
+#![recursion_limit = foo!()] //~ ERROR malformed `recursion_limit` attribute
+
+macro_rules! foo {
+ () => {"128"};
+}
+
+fn main() {}
--- /dev/null
+error: malformed `recursion_limit` attribute input
+ --> $DIR/invalid_macro.rs:1:1
+ |
+LL | #![recursion_limit = foo!()]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]`
+
+error: aborting due to previous error
+
-#![feature(box_syntax)]
-
trait X {
fn get_i(&self) -> isize;
}
+
+
struct B {
i: isize
}
}
fn make_make_a<'a>() -> A<'a> {
- let b: Box<B> = box B {i:1};
+ let b: Box<B> = Box::new(B { i: 1 });
let bb: &B = &*b;
make_a(bb) //~ ERROR cannot return value referencing local data `*b`
}
// run-pass
-#![feature(box_syntax)]
fn foo(x: &usize) -> usize {
*x
}
pub fn main() {
- let p: Box<_> = box 22;
+ let p: Box<_> = Box::new(22);
let r = foo(&*p);
println!("r={}", r);
assert_eq!(r, 22);
// run-pass
-#![feature(box_syntax)]
fn foo(x: &usize) -> usize {
*x
}
pub fn main() {
- let p: Box<_> = box 3;
+ let p: Box<_> = Box::new(3);
let r = foo(&*p);
assert_eq!(r, 3);
}
-#![feature(box_syntax)]
-
trait X {}
+
+
trait Iter {
type Item: X;
fn bad2<T: Iter>(v: T) -> Box<dyn X + 'static>
where Box<T::Item> : X
{
- let item: Box<_> = box v.into_item();
+ let item: Box<_> = Box::new(v.into_item());
Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
}
fn bad4<'a, T: Iter>(v: T) -> Box<dyn X + 'a>
where Box<T::Item> : X
{
- let item: Box<_> = box v.into_item();
+ let item: Box<_> = Box::new(v.into_item());
Box::new(item) //~ ERROR associated type `<T as Iter>::Item` may not live long enough
}
-#![feature(box_syntax)]
#![allow(warnings)]
trait A<T> { }
+
struct B<'a, T:'a>(&'a (A<T>+'a));
trait X { }
impl<'a, T> X for B<'a, T> {}
fn f<'a, T:'static, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
- box B(&*v) as Box<X> //~ ERROR cannot return value referencing local data `*v`
+ Box::new(B(&*v)) as Box<X> //~ ERROR cannot return value referencing local data `*v`
}
fn main() {}
error[E0515]: cannot return value referencing local data `*v`
--> $DIR/regions-close-object-into-object-1.rs:12:5
|
-LL | box B(&*v) as Box<X>
- | ^^^^^^---^^^^^^^^^^^
- | | |
- | | `*v` is borrowed here
+LL | Box::new(B(&*v)) as Box<X>
+ | ^^^^^^^^^^^---^^^^^^^^^^^^
+ | | |
+ | | `*v` is borrowed here
| returns a value referencing data owned by the current function
error: aborting due to previous error
error: lifetime may not live long enough
- --> $DIR/regions-close-object-into-object-2.rs:10:5
+ --> $DIR/regions-close-object-into-object-2.rs:9:5
|
LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
| -- lifetime `'a` defined here
-LL | box B(&*v) as Box<dyn X>
- | ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
= help: consider replacing `'a` with `'static`
error[E0515]: cannot return value referencing local data `*v`
- --> $DIR/regions-close-object-into-object-2.rs:10:5
+ --> $DIR/regions-close-object-into-object-2.rs:9:5
|
-LL | box B(&*v) as Box<dyn X>
- | ^^^^^^---^^^^^^^^^^^^^^^
- | | |
- | | `*v` is borrowed here
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^
+ | | |
+ | | `*v` is borrowed here
| returns a value referencing data owned by the current function
error: aborting due to 2 previous errors
-#![feature(box_syntax)]
-
trait A<T> { }
+
struct B<'a, T:'a>(&'a (dyn A<T> + 'a));
trait X { }
impl<'a, T> X for B<'a, T> {}
fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
- box B(&*v) as Box<dyn X> //~ ERROR E0759
+ Box::new(B(&*v)) as Box<dyn X> //~ ERROR E0759
}
fn main() { }
error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
- --> $DIR/regions-close-object-into-object-2.rs:10:11
+ --> $DIR/regions-close-object-into-object-2.rs:9:16
|
LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
| ------------------ this data with lifetime `'a`...
-LL | box B(&*v) as Box<dyn X>
- | ^^^ ...is captured here, requiring it to live as long as `'static`
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^ ...is captured here, requiring it to live as long as `'static`
|
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
|
-#![feature(box_syntax)]
#![allow(warnings)]
trait A<T> { }
+
struct B<'a, T:'a>(&'a (A<T>+'a));
trait X { }
impl<'a, T> X for B<'a, T> {}
fn h<'a, T, U:'static>(v: Box<A<U>+'static>) -> Box<X+'static> {
- box B(&*v) as Box<X> //~ ERROR cannot return value referencing local data `*v`
+ Box::new(B(&*v)) as Box<X> //~ ERROR cannot return value referencing local data `*v`
}
fn main() {}
error[E0515]: cannot return value referencing local data `*v`
--> $DIR/regions-close-object-into-object-3.rs:11:5
|
-LL | box B(&*v) as Box<X>
- | ^^^^^^---^^^^^^^^^^^
- | | |
- | | `*v` is borrowed here
+LL | Box::new(B(&*v)) as Box<X>
+ | ^^^^^^^^^^^---^^^^^^^^^^^^
+ | | |
+ | | `*v` is borrowed here
| returns a value referencing data owned by the current function
error: aborting due to previous error
error[E0310]: the parameter type `U` may not live long enough
- --> $DIR/regions-close-object-into-object-4.rs:10:5
+ --> $DIR/regions-close-object-into-object-4.rs:9:5
|
-LL | box B(&*v) as Box<dyn X>
- | ^^^^^^^^^^
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `U: 'static`...
+
+error[E0310]: the parameter type `U` may not live long enough
+ --> $DIR/regions-close-object-into-object-4.rs:9:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `U: 'static`...
+
+error[E0310]: the parameter type `U` may not live long enough
+ --> $DIR/regions-close-object-into-object-4.rs:9:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `U: 'static`...
error: lifetime may not live long enough
- --> $DIR/regions-close-object-into-object-4.rs:10:5
+ --> $DIR/regions-close-object-into-object-4.rs:9:5
|
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| -- lifetime `'a` defined here
-LL | box B(&*v) as Box<dyn X>
- | ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
= help: consider replacing `'a` with `'static`
error[E0515]: cannot return value referencing local data `*v`
- --> $DIR/regions-close-object-into-object-4.rs:10:5
+ --> $DIR/regions-close-object-into-object-4.rs:9:5
|
-LL | box B(&*v) as Box<dyn X>
- | ^^^^^^---^^^^^^^^^^^^^^^
- | | |
- | | `*v` is borrowed here
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^
+ | | |
+ | | `*v` is borrowed here
| returns a value referencing data owned by the current function
error[E0310]: the parameter type `U` may not live long enough
- --> $DIR/regions-close-object-into-object-4.rs:10:9
+ --> $DIR/regions-close-object-into-object-4.rs:9:14
|
-LL | box B(&*v) as Box<dyn X>
- | ^^^^^^
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^
|
= help: consider adding an explicit lifetime bound `U: 'static`...
-error: aborting due to 4 previous errors
+error: aborting due to 6 previous errors
Some errors have detailed explanations: E0310, E0515.
For more information about an error, try `rustc --explain E0310`.
-#![feature(box_syntax)]
-
trait A<T> { }
+
struct B<'a, T:'a>(&'a (dyn A<T> + 'a));
trait X { }
impl<'a, T> X for B<'a, T> {}
fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
- box B(&*v) as Box<dyn X> //~ ERROR E0759
+ Box::new(B(&*v)) as Box<dyn X> //~ ERROR E0759
}
fn main() {}
error[E0759]: `v` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
- --> $DIR/regions-close-object-into-object-4.rs:10:11
+ --> $DIR/regions-close-object-into-object-4.rs:9:16
|
LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
| ---------------- this data with lifetime `'a`...
-LL | box B(&*v) as Box<dyn X>
- | ^^^ ...is captured here, requiring it to live as long as `'static`
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^ ...is captured here, requiring it to live as long as `'static`
|
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
|
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/regions-close-object-into-object-5.rs:17:5
|
-LL | box B(&*v) as Box<X>
- | ^^^^^^^^^^
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `T: 'static`...
+
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/regions-close-object-into-object-5.rs:17:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `T: 'static`...
+
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/regions-close-object-into-object-5.rs:17:5
+ |
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `T: 'static`...
error[E0515]: cannot return value referencing local data `*v`
--> $DIR/regions-close-object-into-object-5.rs:17:5
|
-LL | box B(&*v) as Box<X>
- | ^^^^^^---^^^^^^^^^^^
- | | |
- | | `*v` is borrowed here
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^---^^^^^^^^^^^^^^^^
+ | | |
+ | | `*v` is borrowed here
| returns a value referencing data owned by the current function
error[E0310]: the parameter type `T` may not live long enough
- --> $DIR/regions-close-object-into-object-5.rs:17:9
+ --> $DIR/regions-close-object-into-object-5.rs:17:14
|
-LL | box B(&*v) as Box<X>
- | ^^^^^^
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^
|
= help: consider adding an explicit lifetime bound `T: 'static`...
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
Some errors have detailed explanations: E0310, E0515.
For more information about an error, try `rustc --explain E0310`.
-#![feature(box_syntax)]
#![allow(warnings)]
+
trait A<T>
{
fn get(&self) -> T { panic!() }
fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
// oh dear!
- box B(&*v) as Box<X>
+ Box::new(B(&*v)) as Box<dyn X>
//~^ ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
//~| ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
}
fn main() {}
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
-LL | box B(&*v) as Box<X>
- | ^^^^^^^^^^ ...so that the type `B<'_, T>` will meet its required lifetime bounds
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
+ |
+note: ...that is required by this bound
+ --> $DIR/regions-close-object-into-object-5.rs:9:17
+ |
+LL | struct B<'a, T: 'a>(&'a (A<T> + 'a));
+ | ^^
+
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/regions-close-object-into-object-5.rs:17:5
+ |
+LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
+ | - help: consider adding an explicit lifetime bound...: `T: 'static`
+LL | // oh dear!
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^^^^^^^^^^^ ...so that the type `B<'_, T>` will meet its required lifetime bounds
error[E0310]: the parameter type `T` may not live long enough
- --> $DIR/regions-close-object-into-object-5.rs:17:9
+ --> $DIR/regions-close-object-into-object-5.rs:17:14
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
-LL | box B(&*v) as Box<X>
- | ^ ...so that the type `T` will meet its required lifetime bounds
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^ ...so that the type `T` will meet its required lifetime bounds
error[E0310]: the parameter type `T` may not live long enough
- --> $DIR/regions-close-object-into-object-5.rs:17:9
+ --> $DIR/regions-close-object-into-object-5.rs:17:14
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
-LL | box B(&*v) as Box<X>
- | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
|
note: ...that is required by this bound
--> $DIR/regions-close-object-into-object-5.rs:9:17
| ^^
error[E0310]: the parameter type `T` may not live long enough
- --> $DIR/regions-close-object-into-object-5.rs:17:11
+ --> $DIR/regions-close-object-into-object-5.rs:17:16
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
-LL | box B(&*v) as Box<X>
- | ^^^ ...so that the reference type `&dyn A<T>` does not outlive the data it points at
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^ ...so that the reference type `&dyn A<T>` does not outlive the data it points at
error[E0310]: the parameter type `T` may not live long enough
- --> $DIR/regions-close-object-into-object-5.rs:17:11
+ --> $DIR/regions-close-object-into-object-5.rs:17:16
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
-LL | box B(&*v) as Box<X>
- | ^^^ ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^ ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
error[E0310]: the parameter type `T` may not live long enough
- --> $DIR/regions-close-object-into-object-5.rs:17:11
+ --> $DIR/regions-close-object-into-object-5.rs:17:16
|
LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
| - help: consider adding an explicit lifetime bound...: `T: 'static`
LL | // oh dear!
-LL | box B(&*v) as Box<X>
- | ^^^ ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
+LL | Box::new(B(&*v)) as Box<dyn X>
+ | ^^^ ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0310`.
error[E0310]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:12:5
|
-LL | box v as Box<dyn SomeTrait + 'static>
- | ^^^^^
+LL | Box::new(v) as Box<dyn SomeTrait + 'static>
+ | ^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `A: 'static`...
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:21:5
|
-LL | box v as Box<dyn SomeTrait + 'b>
- | ^^^^^
+LL | Box::new(v) as Box<dyn SomeTrait + 'b>
+ | ^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `A: 'b`...
-#![feature(box_syntax)]
-
// Test for what happens when a type parameter `A` is closed over into
// an object. This should yield errors unless `A` (and the object)
// both have suitable bounds.
+
trait SomeTrait {
fn get(&self) -> isize;
}
+
fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
- box v as Box<dyn SomeTrait + 'static>
+ Box::new(v) as Box<dyn SomeTrait + 'static>
//~^ ERROR the parameter type `A` may not live long enough
}
fn make_object2<'a, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'a> {
- box v as Box<dyn SomeTrait + 'a>
+ Box::new(v) as Box<dyn SomeTrait + 'a>
}
fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
- box v as Box<dyn SomeTrait + 'b>
+ Box::new(v) as Box<dyn SomeTrait + 'b>
//~^ ERROR the parameter type `A` may not live long enough
}
|
LL | fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
| -- help: consider adding an explicit lifetime bound...: `A: 'static +`
-LL | box v as Box<dyn SomeTrait + 'static>
- | ^^^^^ ...so that the type `A` will meet its required lifetime bounds
+LL | Box::new(v) as Box<dyn SomeTrait + 'static>
+ | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
error[E0309]: the parameter type `A` may not live long enough
--> $DIR/regions-close-over-type-parameter-1.rs:21:5
|
LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
| -- help: consider adding an explicit lifetime bound...: `A: 'b +`
-LL | box v as Box<dyn SomeTrait + 'b>
- | ^^^^^ ...so that the type `A` will meet its required lifetime bounds
+LL | Box::new(v) as Box<dyn SomeTrait + 'b>
+ | ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
error: aborting due to 2 previous errors
| |
| lifetime `'a` defined here
LL | // A outlives 'a AND 'b...but not 'c.
-LL | box v as Box<dyn SomeTrait + 'a>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'c`
+LL | Box::new(v) as Box<dyn SomeTrait + 'a>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'c`
|
= help: consider adding the following bound: `'a: 'c`
-#![feature(box_syntax)]
-
// Various tests where we over type parameters with multiple lifetime
// bounds.
+
trait SomeTrait { fn get(&self) -> isize; }
+
fn make_object_good1<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'a> {
// A outlives 'a AND 'b...
- box v as Box<dyn SomeTrait + 'a> // ...hence this type is safe.
+ Box::new(v) as Box<dyn SomeTrait + 'a> // ...hence this type is safe.
}
fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'b> {
// A outlives 'a AND 'b...
- box v as Box<dyn SomeTrait + 'b> // ...hence this type is safe.
+ Box::new(v) as Box<dyn SomeTrait + 'b> // ...hence this type is safe.
}
fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<dyn SomeTrait + 'c> {
// A outlives 'a AND 'b...but not 'c.
- box v as Box<dyn SomeTrait + 'a> //~ ERROR cannot infer an appropriate lifetime
+ Box::new(v) as Box<dyn SomeTrait + 'a> //~ ERROR cannot infer an appropriate lifetime
}
fn main() {
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
|
-LL | box v as Box<dyn SomeTrait + 'a>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | Box::new(v) as Box<dyn SomeTrait + 'a>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 18:20...
--> $DIR/regions-close-over-type-parameter-multiple.rs:18:20
note: ...so that the declared lifetime parameter bounds are satisfied
--> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
|
-LL | box v as Box<dyn SomeTrait + 'a>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | Box::new(v) as Box<dyn SomeTrait + 'a>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'c` as defined on the function body at 18:26...
--> $DIR/regions-close-over-type-parameter-multiple.rs:18:26
|
note: ...so that the types are compatible
--> $DIR/regions-close-over-type-parameter-multiple.rs:20:5
|
-LL | box v as Box<dyn SomeTrait + 'a>
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | Box::new(v) as Box<dyn SomeTrait + 'a>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `Box<(dyn SomeTrait + 'c)>`
found `Box<dyn SomeTrait>`
// A test where we (successfully) close over a reference into
// an object.
-#![feature(box_syntax)]
-
trait SomeTrait { fn get(&self) -> isize; }
impl<'a> SomeTrait for &'a isize {
}
fn make_object<'a,A:SomeTrait+'a>(v: A) -> Box<dyn SomeTrait+'a> {
- box v as Box<dyn SomeTrait+'a>
+ Box::new(v) as Box<dyn SomeTrait+'a>
}
fn main() {
// Issue #3148.
#![feature(box_patterns)]
-#![feature(box_syntax)]
struct A {
value: B
v2: [23, 24, 25],
v3: vec![26, 27, 28],
v4: C { f: 29 },
- v5: box C { f: 30 },
+ v5: Box::new(C { f: 30 }),
v6: Some(C { f: 31 })}};
let p = get_v1(&a);
// Tests that you can use an early-bound lifetime parameter as
// on of the generic parameters in a trait.
-#![feature(box_syntax)]
-
trait Trait<'a> {
fn long(&'a self) -> isize;
fn short<'b>(&'b self) -> isize;
impl<'t> MakerTrait for Box<dyn Trait<'t>+'static> {
fn mk() -> Box<dyn Trait<'t>+'static> {
- let tup: Box<(isize, isize)> = box (4,5);
+ let tup: Box<(isize, isize)> = Box::new((4,5));
tup as Box<dyn Trait>
}
}
// run-pass
-#![feature(box_syntax)]
-
fn foo(x: &usize) -> &usize { x }
fn bar(x: &usize) -> usize { *x }
pub fn main() {
- let p: Box<_> = box 3;
+ let p: Box<_> = Box::new(3);
assert_eq!(bar(foo(&*p)), 3);
}
// run-pass
-#![feature(box_syntax)]
fn borrow<T>(x: &T) -> &T {x}
pub fn main() {
- let x: Box<_> = box 3;
+ let x: Box<_> = Box::new(3);
loop {
let y = borrow(&*x);
assert_eq!(*x, *y);
// run-pass
#![allow(dead_code)]
-#![feature(box_syntax)]
struct Point {x: isize, y: isize}
}
pub fn main() {
- let p: Box<_> = box Point {x: 3, y: 4};
+ let p: Box<_> = Box::new(Point {x: 3, y: 4});
let xc = x_coord(&*p);
assert_eq!(*xc, 3);
}
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
pub fn main() {
fn explicit() {
fn test<F>(_x: Option<Box<F>>) where F: FnMut(Box<dyn for<'a> FnMut(&'a isize)>) {}
- test(Some(box |_f: Box<dyn for<'a> FnMut(&'a isize)>| {}));
+ test(Some(Box::new(|_f: Box<dyn for<'a> FnMut(&'a isize)>| {})));
}
// The code below is shorthand for the code above (and more likely
// to represent what one encounters in practice).
fn implicit() {
fn test<F>(_x: Option<Box<F>>) where F: FnMut(Box<dyn FnMut(& isize)>) {}
- test(Some(box |_f: Box<dyn FnMut(& isize)>| {}));
+ test(Some(Box::new(|_f: Box<dyn FnMut(& isize)>| {})));
}
explicit();
#![feature(box_patterns)]
-#![feature(box_syntax)]
+
fn arg_item(box ref x: Box<isize>) -> &'static isize {
x //~ ERROR cannot return value referencing function parameter
}
-fn with<R, F>(f: F) -> R where F: FnOnce(Box<isize>) -> R { f(box 3) }
+fn with<R, F>(f: F) -> R where F: FnOnce(Box<isize>) -> R { f(Box::new(3)) }
fn arg_closure() -> &'static isize {
with(|box ref x| x) //~ ERROR cannot return value referencing function parameter
// changes were caught. However, those uses in the compiler could
// easily get changed or refactored away in the future.
-#![feature(box_syntax)]
-
struct Ctxt<'tcx> {
x: &'tcx Vec<isize>
}
-#![feature(box_syntax)]
-
// Issue #12470.
trait X {
}
fn make_make_a<'a>() -> A<'a> {
- let b: Box<B> = box B {
+
+ let b: Box<B> = Box::new(B {
i: 1,
- };
+ });
+
let bb: &B = &*b;
make_a(bb) //~ ERROR cannot return value referencing local data `*b`
}
--- /dev/null
+// run-pass
+
+#![feature(stmt_expr_attributes)]
+#![feature(closure_track_caller)]
+#![feature(generator_trait)]
+#![feature(generators)]
+
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+use std::panic::Location;
+
+type Loc = &'static Location<'static>;
+
+#[track_caller]
+fn mono_invoke_fn<F: Fn(&'static str, bool) -> (&'static str, bool, Loc)>(
+ val: &F
+) -> (&'static str, bool, Loc) {
+ val("from_mono", false)
+}
+
+#[track_caller]
+fn mono_invoke_fn_once<F: FnOnce(&'static str, bool) -> (&'static str, bool, Loc)>(
+ val: F
+) -> (&'static str, bool, Loc) {
+ val("from_mono", false)
+}
+
+#[track_caller]
+fn dyn_invoke_fn_mut(
+ val: &mut dyn FnMut(&'static str, bool) -> (&'static str, bool, Loc)
+) -> (&'static str, bool, Loc) {
+ val("from_dyn", false)
+}
+
+#[track_caller]
+fn dyn_invoke_fn_once(
+ val: Box<dyn FnOnce(&'static str, bool) -> (&'static str, bool, Loc)>
+) -> (&'static str, bool, Loc) {
+ val("from_dyn", false)
+}
+
+
+fn test_closure() {
+ let mut track_closure = #[track_caller] |first: &'static str, second: bool| {
+ (first, second, Location::caller())
+ };
+ let (first_arg, first_bool, first_loc) = track_closure("first_arg", true);
+ let first_line = line!() - 1;
+ assert_eq!(first_arg, "first_arg");
+ assert_eq!(first_bool, true);
+ assert_eq!(first_loc.file(), file!());
+ assert_eq!(first_loc.line(), first_line);
+ assert_eq!(first_loc.column(), 46);
+
+ let (dyn_arg, dyn_bool, dyn_loc) = dyn_invoke_fn_mut(&mut track_closure);
+ assert_eq!(dyn_arg, "from_dyn");
+ assert_eq!(dyn_bool, false);
+ // `FnMut::call_mut` does not have `#[track_caller]`,
+ // so this will not match
+ assert_ne!(dyn_loc.file(), file!());
+
+ let (dyn_arg, dyn_bool, dyn_loc) = dyn_invoke_fn_once(Box::new(track_closure));
+ assert_eq!(dyn_arg, "from_dyn");
+ assert_eq!(dyn_bool, false);
+ // `FnOnce::call_once` does not have `#[track_caller]`
+ // so this will not match
+ assert_ne!(dyn_loc.file(), file!());
+
+
+ let (mono_arg, mono_bool, mono_loc) = mono_invoke_fn(&track_closure);
+ let mono_line = line!() - 1;
+ assert_eq!(mono_arg, "from_mono");
+ assert_eq!(mono_bool, false);
+ assert_eq!(mono_loc.file(), file!());
+ assert_eq!(mono_loc.line(), mono_line);
+ assert_eq!(mono_loc.column(), 43);
+
+ let (mono_arg, mono_bool, mono_loc) = mono_invoke_fn_once(track_closure);
+ let mono_line = line!() - 1;
+ assert_eq!(mono_arg, "from_mono");
+ assert_eq!(mono_bool, false);
+ assert_eq!(mono_loc.file(), file!());
+ assert_eq!(mono_loc.line(), mono_line);
+ assert_eq!(mono_loc.column(), 43);
+
+ let non_tracked_caller = || Location::caller();
+ let non_tracked_line = line!() - 1; // This is the line of the closure, not its caller
+ let non_tracked_loc = non_tracked_caller();
+ assert_eq!(non_tracked_loc.file(), file!());
+ assert_eq!(non_tracked_loc.line(), non_tracked_line);
+ assert_eq!(non_tracked_loc.column(), 33);
+}
+
+
+#[track_caller]
+fn mono_generator<F: Generator<String, Yield = (&'static str, String, Loc), Return = ()>>(
+ val: Pin<&mut F>
+) -> (&'static str, String, Loc) {
+ match val.resume("Mono".to_string()) {
+ GeneratorState::Yielded(val) => val,
+ _ => unreachable!()
+ }
+}
+
+#[track_caller]
+fn dyn_generator(
+ val: Pin<&mut dyn Generator<String, Yield = (&'static str, String, Loc), Return = ()>>
+) -> (&'static str, String, Loc) {
+ match val.resume("Dyn".to_string()) {
+ GeneratorState::Yielded(val) => val,
+ _ => unreachable!()
+ }
+}
+
+fn test_generator() {
+ let generator = #[track_caller] |arg: String| {
+ yield ("first", arg.clone(), Location::caller());
+ yield ("second", arg.clone(), Location::caller());
+ };
+
+ let mut pinned = Box::pin(generator);
+ let (dyn_ret, dyn_arg, dyn_loc) = dyn_generator(pinned.as_mut());
+ assert_eq!(dyn_ret, "first");
+ assert_eq!(dyn_arg, "Dyn".to_string());
+ // The `Generator` trait does not have `#[track_caller]` on `resume`, so
+ // this will not match.
+ assert_ne!(dyn_loc.file(), file!());
+
+
+ let (mono_ret, mono_arg, mono_loc) = mono_generator(pinned.as_mut());
+ let mono_line = line!() - 1;
+ assert_eq!(mono_ret, "second");
+ // The generator ignores the argument to the second `resume` call
+ assert_eq!(mono_arg, "Dyn".to_string());
+ assert_eq!(mono_loc.file(), file!());
+ assert_eq!(mono_loc.line(), mono_line);
+ assert_eq!(mono_loc.column(), 42);
+
+ let non_tracked_generator = || { yield Location::caller(); };
+ let non_tracked_line = line!() - 1; // This is the line of the generator, not its caller
+ let non_tracked_loc = match Box::pin(non_tracked_generator).as_mut().resume(()) {
+ GeneratorState::Yielded(val) => val,
+ _ => unreachable!()
+ };
+ assert_eq!(non_tracked_loc.file(), file!());
+ assert_eq!(non_tracked_loc.line(), non_tracked_line);
+ assert_eq!(non_tracked_loc.column(), 44);
+
+}
+
+fn main() {
+ test_closure();
+ test_generator();
+}
// run-pass
#![allow(unreachable_patterns)]
-#![feature(box_syntax, box_patterns)]
+#![feature(box_patterns)]
struct Foo{}
pub fn main() {
- let b = box Foo{};
+ let b = Box::new(Foo{});
let box f = &b;
let _: &Foo = f;
// run-pass
#![allow(dead_code)]
-#![feature(box_syntax)]
#[derive(Copy, Clone)]
struct LM { resize_at: usize, size: usize }
}
pub fn main() {
- let mut m: Box<_> = box linear_map::<(),()>();
+ let mut m: Box<_> = Box::new(linear_map::<(),()>());
assert_eq!(m.len(), 0);
}
// run-pass
-#![feature(box_syntax)]
trait Foo {
fn f(self: Box<Self>);
}
pub fn main() {
- let x = box S { x: 3 };
+ let x = Box::new(S { x: 3 });
let y = x as Box<dyn Foo>;
y.f();
}
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
-#![feature(box_syntax)]
-
static tau: f64 = 2.0*3.14159265358979323;
struct Point {x: f64, y: f64}
impl Nus for thing { fn f(&self) {} }
pub fn main() {
- let y: Box<_> = box thing(A {a: 10});
+ let y: Box<_> = Box::new(thing(A {a: 10}));
assert_eq!(y.clone().bar(), 10);
assert_eq!(y.quux(), 10);
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
struct Foo;
// Test uses on inherent impl.
let _: Self::SuperQux = true;
let _: <Self as SuperBar>::SuperQux = true;
- box Baz { f: 42 }
+ Box::new(Baz { f: 42 })
}
}
fn main() {
- let _: Foo = Foo::foo(Foo, &Foo, box Foo);
- let _: Box<Baz<isize>> = Bar::bar(box Baz { f: 42 },
- &box Baz { f: 42 },
- box box Baz { f: 42 },
+ let _: Foo = Foo::foo(Foo, &Foo, Box::new(Foo));
+ let _: Box<Baz<isize>> = Bar::bar(Box::new(Baz { f: 42 }),
+ &Box::new(Baz { f: 42 }),
+ Box::new(Box::new(Baz { f: 42 })),
true);
}
// run-pass
-#![feature(box_syntax)]
struct X {
a: isize
let new_x = x.change();
assert_eq!(new_x.a, 55);
- let x: Box<_> = box new_x;
+ let x: Box<_> = Box::new(new_x);
let new_x = x.change_again();
assert_eq!(new_x.a, 45);
}
// Ensure assigning an owned or managed variable to itself works. In particular,
// that we do not glue_drop before we glue_take (#3290).
-#![feature(box_syntax)]
#![allow(dead_code)]
use std::rc::Rc;
pub fn main() {
- let mut x: Box<_> = box 3;
+ let mut x: Box<_> = Box::new(3);
x = x;
assert_eq!(*x, 3);
// run-pass
-#![feature(box_syntax)]
#![allow(dead_code)]
#[derive(Copy, Clone)]
}
fn main() {
- let foo: Box<_> = box Foo {
+ let foo: Box<_> = Box::new(Foo {
f: 1,
- };
+ });
println!("{} {} {}", foo.foo(2), foo.bar(2), foo.baz(2));
- let bar: Box<_> = box Bar {
+ let bar: Box<_> = Box::new(Bar {
f: 1,
- };
+ });
println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2));
let bar: Box<Bar<isize>> = bar;
println!("{} {} {}", bar.foo(2), bar.bar(2), bar.baz(2));
// run-pass
-#![feature(box_syntax)]
struct X {
a: isize
}
pub fn main() {
- let x: Box<_> = box X { a: 32 };
+ let x: Box<_> = Box::new(X { a: 32 });
let new_x = x.change();
assert_eq!(new_x.a, 55);
}
// Test that shadowed lifetimes generate an error.
-#![feature(box_syntax)]
struct Foo<T>(T);
+
impl<T> Foo<T> {
fn shadow_in_method<T>(&self) {}
//~^ ERROR the name `T` is already used
-#![feature(box_syntax)]
-
fn test(_x: &mut String) {}
+
fn test2(_x: &mut i32) {}
+
fn main() {
let x: usize = String::new();
//~^ ERROR E0308
test2(&y);
//~^ ERROR E0308
let f;
- f = box f;
+ f = Box::new(f);
//~^ ERROR E0308
let s = &mut String::new();
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:17:9
|
-LL | f = box f;
- | ^^^^^ cyclic type of infinite size
- |
-help: try using a conversion method
- |
-LL | f = (box f).to_string();
- | + +++++++++++++
+LL | f = Box::new(f);
+ | ^^^^^^^^^^^- help: try using a conversion method: `.to_string()`
+ | |
+ | cyclic type of infinite size
error[E0308]: mismatched types
--> $DIR/coerce-suggestions.rs:21:9
-#![feature(box_syntax, unboxed_closures)]
+#![feature(unboxed_closures)]
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
fn main() {
let r = {
- let x: Box<_> = box 42;
+ let x: Box<_> = Box::new(42);
let f = to_fn_once(move|| &x); //~ ERROR cannot return reference to local data `x`
f()
};
-#![feature(box_syntax)]
-
fn id<T>(x: T) -> T { x }
trait Foo { }
impl<'a> Foo for &'a isize { }
fn main() {
+
let blah;
+
{
let ss: &isize = &id(1);
//~^ ERROR temporary value dropped while borrowed
- blah = box ss as Box<dyn Foo>;
+ blah = Box::new(ss) as Box<dyn Foo>;
}
}
-#![feature(box_syntax)]
-
// Test for what happens when a type parameter `A` is closed over into
// an object. This should yield errors unless `A` (and the object)
// both have suitable bounds.
trait Foo { fn get(&self); }
impl<A> Foo for A {
- fn get(&self) { }
+ fn get(&self) {
+ }
}
fn repeater3<'a,A:'a>(v: A) -> Box<dyn Foo + 'a> {
- box v as Box<dyn Foo+'a>
+ Box::new(v) as Box<dyn Foo+'a>
}
fn main() {
+
// Error results because the type of is inferred to be
// ~Repeat<&'blk isize> where blk is the lifetime of the block below.
-#![feature(box_syntax)]
-
fn id<T>(x: T) -> T { x }
fn f<T:'static>(_: T) {}
fn main() {
- let x: Box<_> = box 3;
+
+ let x: Box<_> = Box::new(3);
f(x);
+
let x = &id(3); //~ ERROR temporary value dropped while borrowed
f(x);
}
// run-pass
// aux-build:cci_class_cast.rs
-#![feature(box_syntax)]
-
extern crate cci_class_cast;
use std::string::ToString;
}
pub fn main() {
- let nyan: Box<dyn ToString> = box cat(0, 2, "nyan".to_string()) as Box<dyn ToString>;
+ let nyan: Box<dyn ToString> = Box::new(cat(0, 2, "nyan".to_string())) as Box<dyn ToString>;
print_out(nyan, "nyan".to_string());
}
#![allow(dead_code)]
#![allow(non_camel_case_types)]
-#![feature(box_syntax)]
-
use std::fmt;
struct cat {
}
pub fn main() {
- let nyan: Box<dyn ToString> = box cat(0, 2, "nyan".to_string()) as Box<dyn ToString>;
+ let nyan: Box<dyn ToString> = Box::new(cat(0, 2, "nyan".to_string())) as Box<dyn ToString>;
print_out(nyan, "nyan".to_string());
}
// run-pass
-#![feature(box_syntax)]
/*!
* This is a regression test for a bug in LLVM, fixed in upstream r179587,
enum List<X> { Nil, Cons(X, Box<List<X>>) }
pub fn main() {
- match List::Cons(10, box List::Nil) {
+ match List::Cons(10, Box::new(List::Nil)) {
List::Cons(10, _) => {}
List::Nil => {}
_ => panic!()
// edition:2018
-// compile-flags: -Cincremental=tmp/issue-72766
+// incremental
pub struct SadGirl;
--- /dev/null
+// run-rustfix
+
+fn two_type_params<A, B>(_: B) {}
+
+fn main() {
+ two_type_params::<String, _>(100); //~ ERROR this function takes 2 generic arguments
+ two_type_params::<String, _>(100);
+}
--- /dev/null
+// run-rustfix
+
+fn two_type_params<A, B>(_: B) {}
+
+fn main() {
+ two_type_params::<String>(100); //~ ERROR this function takes 2 generic arguments
+ two_type_params::<String, _>(100);
+}
--- /dev/null
+error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
+ --> $DIR/missing-type-param-used-in-param.rs:6:5
+ |
+LL | two_type_params::<String>(100);
+ | ^^^^^^^^^^^^^^^ ------ supplied 1 generic argument
+ | |
+ | expected 2 generic arguments
+ |
+note: function defined here, with 2 generic parameters: `A`, `B`
+ --> $DIR/missing-type-param-used-in-param.rs:3:4
+ |
+LL | fn two_type_params<A, B>(_: B) {}
+ | ^^^^^^^^^^^^^^^ - -
+help: add missing generic argument
+ |
+LL | two_type_params::<String, _>(100);
+ | +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
// run-pass
// ignore-emscripten no threads support
-#![feature(box_syntax)]
-
use std::thread;
pub fn main() { test05(); }
}
fn test05() {
- let three: Box<_> = box 3;
+ let three: Box<_> = Box::new(3);
let fn_to_send = move|n:isize| {
println!("{}", *three + n); // will copy x into the closure
assert_eq!(*three, 3);
#![allow(unused_must_use)]
// ignore-emscripten no threads support
-#![feature(box_syntax)]
-
use std::thread;
use std::sync::mpsc::channel;
pub fn main() {
let (tx, rx) = channel::<usize>();
- let x: Box<isize> = box 1;
+ let x: Box<isize> = Box::new(1);
let x_in_parent = &(*x) as *const isize as usize;
let t = thread::spawn(move || {
// ignore-emscripten no threads support
-#![feature(box_syntax)]
-
use std::sync::Arc;
use std::sync::mpsc::channel;
use std::thread;
swim_speed: 998,
name: "alec_guinness".to_string(),
};
- let arc = Arc::new(vec![box catte as Box<dyn Pet+Sync+Send>,
- box dogge1 as Box<dyn Pet+Sync+Send>,
- box fishe as Box<dyn Pet+Sync+Send>,
- box dogge2 as Box<dyn Pet+Sync+Send>]);
+ let arc = Arc::new(vec![
+ Box::new(catte) as Box<dyn Pet+Sync+Send>,
+ Box::new(dogge1) as Box<dyn Pet+Sync+Send>,
+ Box::new(fishe) as Box<dyn Pet+Sync+Send>,
+ Box::new(dogge2) as Box<dyn Pet+Sync+Send>]);
let (tx1, rx1) = channel();
let arc1 = arc.clone();
let t1 = thread::spawn(move|| { check_legs(arc1); tx1.send(()); });
#![allow(dead_code)]
#![allow(unused_mut)]
#![allow(unused_variables)]
-#![feature(box_syntax)]
use std::io::{self, Write};
// blanket impl for T:Copy coexists with an impl for Box<T>, because
// Box does not impl Copy.
-#![feature(box_syntax)]
trait Get {
fn get(&self) -> Self;
}
impl Get for Box<i32> {
- fn get(&self) -> Box<i32> { box get_it(&**self) }
+ fn get(&self) -> Box<i32> { Box::new(get_it(&**self)) }
}
fn get_it<T:Get>(t: &T) -> T {
// run-pass
-#![feature(box_syntax)]
-
use std::collections::HashMap;
trait Graph<Node, Edge> {
}
pub fn main() {
- let g : Box<HashMap<isize,isize>> = box HashMap::new();
+ let g : Box<HashMap<isize,isize>> = Box::new(HashMap::new());
let _g2 : Box<dyn Graph<isize,isize>> = g as Box<dyn Graph<isize,isize>>;
}
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
-#![feature(box_syntax)]
-
trait repeat<A> { fn get(&self) -> A; }
impl<A:Clone + 'static> repeat<A> for Box<A> {
}
fn repeater<A:Clone + 'static>(v: Box<A>) -> Box<dyn repeat<A>+'static> {
- box v as Box<dyn repeat<A>+'static> // No
+ Box::new(v) as Box<dyn repeat<A>+'static> // No
}
pub fn main() {
let x = 3;
- let y = repeater(box x);
+ let y = repeater(Box::new(x));
assert_eq!(x, y.get());
}
// Testing creating two vtables with the same self type, but different
// traits.
-#![feature(box_syntax)]
-
use std::any::Any;
trait Wrap {
}
fn main() {
- let x = box 22isize as Box<dyn Wrap>;
+ let x = Box::new(22isize) as Box<dyn Wrap>;
println!("x={}", x.get());
let y = x.wrap();
}
// run-pass
// test for #8664
-#![feature(box_syntax)]
-
use std::marker;
pub trait Trait2<A> {
}
pub fn main() {
- let a = box () as Box<dyn Trait<u8, u8>>;
+ let a = Box::new(()) as Box<dyn Trait<u8, u8>>;
assert_eq!(a.method(Type::Constant((1, 2))), 0);
}
-#![feature(box_syntax)]
-
#[allow(non_camel_case_types)]
+
+
trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
//~^ ERROR this associated function takes 0 generic arguments but 1
10.blah::<i32, i32>();
//~^ ERROR this associated function takes 1 generic argument but 2
- (box 10 as Box<dyn bar>).dup();
+ (Box::new(10) as Box<dyn bar>).dup();
//~^ ERROR E0038
//~| ERROR E0038
+ //~| ERROR E0038
}
| ^^^^ -
error[E0038]: the trait `bar` cannot be made into an object
- --> $DIR/test-2.rs:13:16
+ --> $DIR/test-2.rs:13:22
|
-LL | (box 10 as Box<dyn bar>).dup();
- | ^^^^^^^^^^^^ `bar` cannot be made into an object
+LL | (Box::new(10) as Box<dyn bar>).dup();
+ | ^^^^^^^^^^^^ `bar` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/test-2.rs:4:30
+ |
+LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
+ | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters
+ | | |
+ | | ...because method `dup` references the `Self` type in its return type
+ | this trait cannot be made into an object...
+ = help: consider moving `dup` to another trait
+ = help: consider moving `blah` to another trait
+
+error[E0038]: the trait `bar` cannot be made into an object
+ --> $DIR/test-2.rs:13:5
+ |
+LL | (Box::new(10) as Box<dyn bar>).dup();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/test-2.rs:4:30
error[E0038]: the trait `bar` cannot be made into an object
--> $DIR/test-2.rs:13:6
|
-LL | (box 10 as Box<dyn bar>).dup();
- | ^^^^^^ `bar` cannot be made into an object
+LL | (Box::new(10) as Box<dyn bar>).dup();
+ | ^^^^^^^^^^^^ `bar` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $DIR/test-2.rs:4:30
= note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn bar>>` for `Box<{integer}>`
= note: required by cast to type `Box<dyn bar>`
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
Some errors have detailed explanations: E0038, E0107.
For more information about an error, try `rustc --explain E0038`.
// run-pass
-#![feature(box_syntax, trait_upcasting)]
+#![feature(trait_upcasting)]
#![allow(incomplete_features)]
struct Test {
fn main() {
let closure: Box<dyn Fn() + 'static> = Box::new(|| ());
- let mut test = box Test { func: closure };
+ let mut test = Box::new(Test { func: closure });
(test.func)();
}
|
LL | is_send(foo());
| ^^^^^^^
- = note: ...which requires evaluating trait selection obligation `impl std::fmt::Debug: std::marker::Send`...
+ = note: ...which requires evaluating trait selection obligation `impl core::fmt::Debug: core::marker::Send`...
= note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
note: cycle used when checking item types in module `m`
--> $DIR/auto-trait-leakage3.rs:6:1
}
type Foo<V> = impl Trait<V>;
+//~^ ERROR could not find defining uses
trait Trait<U> {}
fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
//~^ ERROR non-defining opaque type use in defining scope
+ //~| ERROR non-defining opaque type use in defining scope
+ //~| ERROR non-defining opaque type use in defining scope
+ //~| ERROR `T` is part of concrete type but not used in parameter list
+ //~| ERROR `T` is part of concrete type but not used in parameter list
()
}
+error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+ --> $DIR/bound_reduction2.rs:16:60
+ |
+LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+ | ____________________________________________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | ()
+LL | | }
+ | |_^
+
+error: type parameter `T` is part of concrete type but not used in parameter list for the `impl Trait` type alias
+ --> $DIR/bound_reduction2.rs:16:60
+ |
+LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+ | ____________________________________________________________^
+LL | |
+LL | |
+LL | |
+... |
+LL | | ()
+LL | | }
+ | |_^
+
error: non-defining opaque type use in defining scope
- --> $DIR/bound_reduction2.rs:15:46
+ --> $DIR/bound_reduction2.rs:16:1
|
LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
- | ^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: used non-generic type `<T as TraitWithAssoc>::Assoc` for generic parameter
--> $DIR/bound_reduction2.rs:9:10
LL | type Foo<V> = impl Trait<V>;
| ^
-error: aborting due to previous error
+error: non-defining opaque type use in defining scope
+ --> $DIR/bound_reduction2.rs:16:1
+ |
+LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: used non-generic type `_` for generic parameter
+ --> $DIR/bound_reduction2.rs:9:10
+ |
+LL | type Foo<V> = impl Trait<V>;
+ | ^
+
+error: non-defining opaque type use in defining scope
+ --> $DIR/bound_reduction2.rs:16:1
+ |
+LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: used non-generic type `_` for generic parameter
+ --> $DIR/bound_reduction2.rs:9:10
+ |
+LL | type Foo<V> = impl Trait<V>;
+ | ^
+
+error: could not find defining uses
+ --> $DIR/bound_reduction2.rs:9:15
+ |
+LL | type Foo<V> = impl Trait<V>;
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
fn main() {}
type Two<'a, 'b> = impl std::fmt::Debug;
+//~^ ERROR could not find defining uses
fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
//~^ ERROR non-defining opaque type use
error: non-defining opaque type use in defining scope
- --> $DIR/generic_duplicate_lifetime_param.rs:7:26
+ --> $DIR/generic_duplicate_lifetime_param.rs:8:26
|
LL | fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
| ^^^^^^^^^^^
LL | type Two<'a, 'b> = impl std::fmt::Debug;
| ^^ ^^
-error: aborting due to previous error
+error: could not find defining uses
+ --> $DIR/generic_duplicate_lifetime_param.rs:5:20
+ |
+LL | type Two<'a, 'b> = impl std::fmt::Debug;
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
// test that unused generic parameters are ok
type TwoTys<T, U> = impl Debug;
+//~^ ERROR could not find defining uses
type TwoLifetimes<'a, 'b> = impl Debug;
+//~^ ERROR could not find defining uses
type TwoConsts<const X: usize, const Y: usize> = impl Debug;
+//~^ ERROR could not find defining uses
fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
//~^ ERROR non-defining opaque type use in defining scope
error: non-defining opaque type use in defining scope
- --> $DIR/generic_duplicate_param_use.rs:12:30
+ --> $DIR/generic_duplicate_param_use.rs:15:30
|
LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
| ^^^^^^^^^^^^
LL | type TwoTys<T, U> = impl Debug;
| ^ ^
+error: could not find defining uses
+ --> $DIR/generic_duplicate_param_use.rs:8:21
+ |
+LL | type TwoTys<T, U> = impl Debug;
+ | ^^^^^^^^^^
+
error: non-defining opaque type use in defining scope
- --> $DIR/generic_duplicate_param_use.rs:17:36
+ --> $DIR/generic_duplicate_param_use.rs:20:36
|
LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
| ^^^^^^^^^^^^^^^^^^^^
|
note: lifetime used multiple times
- --> $DIR/generic_duplicate_param_use.rs:9:19
+ --> $DIR/generic_duplicate_param_use.rs:10:19
|
LL | type TwoLifetimes<'a, 'b> = impl Debug;
| ^^ ^^
+error: could not find defining uses
+ --> $DIR/generic_duplicate_param_use.rs:10:29
+ |
+LL | type TwoLifetimes<'a, 'b> = impl Debug;
+ | ^^^^^^^^^^
+
error: non-defining opaque type use in defining scope
- --> $DIR/generic_duplicate_param_use.rs:22:50
+ --> $DIR/generic_duplicate_param_use.rs:25:50
|
LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
| ^^^^^^^^^^^^^^^
|
note: constant used multiple times
- --> $DIR/generic_duplicate_param_use.rs:10:22
+ --> $DIR/generic_duplicate_param_use.rs:12:22
|
LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
| ^ ^
-error: aborting due to 3 previous errors
+error: could not find defining uses
+ --> $DIR/generic_duplicate_param_use.rs:12:50
+ |
+LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
+ | ^^^^^^^^^^
+
+error: aborting due to 6 previous errors
// test that unused generic parameters are ok
type Two<T, U> = impl Debug;
+//~^ ERROR `T` doesn't implement `Debug`
fn one<T: Debug>(t: T) -> Two<T, T> {
//~^ ERROR non-defining opaque type use in defining scope
error: non-defining opaque type use in defining scope
- --> $DIR/generic_duplicate_param_use2.rs:10:27
+ --> $DIR/generic_duplicate_param_use2.rs:11:27
|
LL | fn one<T: Debug>(t: T) -> Two<T, T> {
| ^^^^^^^^^
LL | type Two<T, U> = impl Debug;
| ^ ^
-error: aborting due to previous error
+error[E0277]: `T` doesn't implement `Debug`
+ --> $DIR/generic_duplicate_param_use2.rs:8:18
+ |
+LL | type Two<T, U> = impl Debug;
+ | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+help: consider restricting type parameter `T`
+ |
+LL | type Two<T: std::fmt::Debug, U> = impl Debug;
+ | +++++++++++++++++
+
+error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0277`.
// test that unused generic parameters are ok
type Two<T, U> = impl Debug;
+//~^ ERROR `T` doesn't implement `Debug`
fn one<T: Debug>(t: T) -> Two<T, T> {
//~^ ERROR non-defining opaque type use in defining scope
}
fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
+ //~^ ERROR concrete type differs from previous defining opaque type use
u
}
error: non-defining opaque type use in defining scope
- --> $DIR/generic_duplicate_param_use3.rs:10:27
+ --> $DIR/generic_duplicate_param_use3.rs:11:27
|
LL | fn one<T: Debug>(t: T) -> Two<T, T> {
| ^^^^^^^^^
LL | type Two<T, U> = impl Debug;
| ^ ^
-error: aborting due to previous error
+error: concrete type differs from previous defining opaque type use
+ --> $DIR/generic_duplicate_param_use3.rs:20:1
+ |
+LL | fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `U`
+ |
+note: previous use here
+ --> $DIR/generic_duplicate_param_use3.rs:16:1
+ |
+LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `T` doesn't implement `Debug`
+ --> $DIR/generic_duplicate_param_use3.rs:8:18
+ |
+LL | type Two<T, U> = impl Debug;
+ | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+help: consider restricting type parameter `T`
+ |
+LL | type Two<T: std::fmt::Debug, U> = impl Debug;
+ | +++++++++++++++++
+
+error: aborting due to 3 previous errors
+For more information about this error, try `rustc --explain E0277`.
// test that unused generic parameters are ok
type Two<T, U> = impl Debug;
+//~^ ERROR `U` doesn't implement `Debug`
fn one<T: Debug>(t: T) -> Two<T, T> {
//~^ ERROR non-defining opaque type use in defining scope
error: non-defining opaque type use in defining scope
- --> $DIR/generic_duplicate_param_use4.rs:10:27
+ --> $DIR/generic_duplicate_param_use4.rs:11:27
|
LL | fn one<T: Debug>(t: T) -> Two<T, T> {
| ^^^^^^^^^
LL | type Two<T, U> = impl Debug;
| ^ ^
-error: aborting due to previous error
+error[E0277]: `U` doesn't implement `Debug`
+ --> $DIR/generic_duplicate_param_use4.rs:8:18
+ |
+LL | type Two<T, U> = impl Debug;
+ | ^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+help: consider restricting type parameter `U`
+ |
+LL | type Two<T, U: std::fmt::Debug> = impl Debug;
+ | +++++++++++++++++
+
+error: aborting due to 2 previous errors
+For more information about this error, try `rustc --explain E0277`.
fn main() {}
type OneTy<T> = impl Debug;
+//~^ ERROR could not find defining uses
type OneLifetime<'a> = impl Debug;
+//~^ ERROR could not find defining uses
type OneConst<const X: usize> = impl Debug;
+//~^ ERROR could not find defining uses
// Not defining uses, because they doesn't define *all* possible generics.
error: non-defining opaque type use in defining scope
- --> $DIR/generic_nondefining_use.rs:13:21
+ --> $DIR/generic_nondefining_use.rs:16:21
|
LL | fn concrete_ty() -> OneTy<u32> {
| ^^^^^^^^^^
LL | type OneTy<T> = impl Debug;
| ^
+error: could not find defining uses
+ --> $DIR/generic_nondefining_use.rs:7:17
+ |
+LL | type OneTy<T> = impl Debug;
+ | ^^^^^^^^^^
+
error: non-defining opaque type use in defining scope
- --> $DIR/generic_nondefining_use.rs:18:27
+ --> $DIR/generic_nondefining_use.rs:21:27
|
LL | type OneLifetime<'a> = impl Debug;
| -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
LL | fn concrete_lifetime() -> OneLifetime<'static> {
| ^^^^^^^^^^^^^^^^^^^^
+error: could not find defining uses
+ --> $DIR/generic_nondefining_use.rs:9:24
+ |
+LL | type OneLifetime<'a> = impl Debug;
+ | ^^^^^^^^^^
+
error: non-defining opaque type use in defining scope
- --> $DIR/generic_nondefining_use.rs:23:24
+ --> $DIR/generic_nondefining_use.rs:26:24
|
LL | fn concrete_const() -> OneConst<{ 123 }> {
| ^^^^^^^^^^^^^^^^^
|
note: used non-generic constant `123_usize` for generic parameter
- --> $DIR/generic_nondefining_use.rs:9:21
+ --> $DIR/generic_nondefining_use.rs:11:21
|
LL | type OneConst<const X: usize> = impl Debug;
| ^
-error: aborting due to 3 previous errors
+error: could not find defining uses
+ --> $DIR/generic_nondefining_use.rs:11:33
+ |
+LL | type OneConst<const X: usize> = impl Debug;
+ | ^^^^^^^^^^
+
+error: aborting due to 6 previous errors
}
fn baz() -> Foo {
- //~^ ERROR: concrete type differs from previous defining opaque type use
Some(())
}
LL | None
| ^^^^ cannot infer type for type parameter `T` declared on the enum `Option`
-error: concrete type differs from previous defining opaque type use
- --> $DIR/incomplete-inference.rs:10:1
- |
-LL | fn baz() -> Foo {
- | ^^^^^^^^^^^^^^^ expected `[type error]`, got `Option<()>`
- |
-note: previous use here
- --> $DIR/incomplete-inference.rs:5:1
- |
-LL | fn bar() -> Foo {
- | ^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.
|
LL | is_send(foo()); // Today: error
| ^^^^^^^
- = note: ...which requires evaluating trait selection obligation `impl std::fmt::Debug: std::marker::Send`...
+ = note: ...which requires evaluating trait selection obligation `impl core::fmt::Debug: core::marker::Send`...
= note: ...which again requires computing type of `m::Foo::{opaque#0}`, completing the cycle
note: cycle used when checking item types in module `m`
--> $DIR/inference-cycle.rs:4:1
const FUN: fn() -> Self::Item = || ();
//~^ ERROR the trait bound `(): Bug` is not satisfied
+ //~| ERROR non-defining opaque type use in defining scope
}
fn main() {}
= help: the following implementations were found:
<&() as Bug>
-error: aborting due to 2 previous errors
+error: non-defining opaque type use in defining scope
+ --> $DIR/issue-60371.rs:12:37
+ |
+LL | impl Bug for &() {
+ | - cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+...
+LL | const FUN: fn() -> Self::Item = || ();
+ | ^^^^^
+
+error: aborting due to 3 previous errors
Some errors have detailed explanations: E0277, E0658.
For more information about an error, try `rustc --explain E0277`.
}
type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
+//~^ ERROR could not find defining uses
impl<T: Copy, E> IterBits for T
where
error: non-defining opaque type use in defining scope
- --> $DIR/issue-60564.rs:19:34
+ --> $DIR/issue-60564.rs:20:34
|
LL | fn iter_bits(self, n: u8) -> Self::BitsIter {
| ^^^^^^^^^^^^^^
LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
| ^
-error: aborting due to previous error
+error: could not find defining uses
+ --> $DIR/issue-60564.rs:8:30
+ |
+LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
--- /dev/null
+// Regression test for issue #68368
+// Ensures that we don't ICE when emitting an error
+// for a non-defining use when lifetimes are involved
+
+#![feature(type_alias_impl_trait)]
+trait Trait<T> {}
+type Alias<'a, U> = impl Trait<U>;
+//~^ ERROR could not find defining uses
+fn f<'a>() -> Alias<'a, ()> {}
+//~^ ERROR non-defining opaque type use in defining scope
+
+fn main() {}
+
+impl<X> Trait<X> for () {}
--- /dev/null
+error: non-defining opaque type use in defining scope
+ --> $DIR/issue-68368-non-defining-use-2.rs:9:15
+ |
+LL | fn f<'a>() -> Alias<'a, ()> {}
+ | ^^^^^^^^^^^^^
+ |
+note: used non-generic type `()` for generic parameter
+ --> $DIR/issue-68368-non-defining-use-2.rs:7:16
+ |
+LL | type Alias<'a, U> = impl Trait<U>;
+ | ^
+
+error: could not find defining uses
+ --> $DIR/issue-68368-non-defining-use-2.rs:7:21
+ |
+LL | type Alias<'a, U> = impl Trait<U>;
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
#![feature(type_alias_impl_trait)]
trait Trait<T> {}
type Alias<'a, U> = impl Trait<U>;
+//~^ ERROR could not find defining uses
fn f<'a>() -> Alias<'a, ()> {}
//~^ ERROR non-defining opaque type use in defining scope
error: non-defining opaque type use in defining scope
- --> $DIR/issue-68368-non-defining-use.rs:8:15
+ --> $DIR/issue-68368-non-defining-use.rs:9:15
|
LL | fn f<'a>() -> Alias<'a, ()> {}
| ^^^^^^^^^^^^^
LL | type Alias<'a, U> = impl Trait<U>;
| ^
-error: aborting due to previous error
+error: could not find defining uses
+ --> $DIR/issue-68368-non-defining-use.rs:7:21
+ |
+LL | type Alias<'a, U> = impl Trait<U>;
+ | ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
}
fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
- //~^ ERROR concrete type differs from previous defining opaque type
(a, b)
//~^ ERROR mismatched types
}
error[E0308]: mismatched types
- --> $DIR/multiple-def-uses-in-one-fn3.rs:15:9
+ --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9
|
LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
| - - found type parameter
| |
| expected type parameter
-LL |
LL | (a, b)
| ^ expected type parameter `A`, found type parameter `B`
|
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
-error: concrete type differs from previous defining opaque type use
- --> $DIR/multiple-def-uses-in-one-fn3.rs:13:1
- |
-LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `A`, got `[type error]`
- |
-note: previous use here
- --> $DIR/multiple-def-uses-in-one-fn3.rs:9:1
- |
-LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0308`.
fn main() {}
type Two<T, U> = impl Debug;
+//~^ ERROR `T` doesn't implement `Debug`
fn two<T: Debug>(t: T) -> Two<T, u32> {
//~^ ERROR non-defining opaque type use in defining scope
}
fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
+ //~^ ERROR concrete type differs from previous
(t, <U as Bar>::FOO)
}
error: non-defining opaque type use in defining scope
- --> $DIR/not_a_defining_use.rs:9:27
+ --> $DIR/not_a_defining_use.rs:10:27
|
LL | fn two<T: Debug>(t: T) -> Two<T, u32> {
| ^^^^^^^^^^^
LL | type Two<T, U> = impl Debug;
| ^
-error: aborting due to previous error
+error: concrete type differs from previous defining opaque type use
+ --> $DIR/not_a_defining_use.rs:29:1
+ |
+LL | fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
+ |
+note: previous use here
+ --> $DIR/not_a_defining_use.rs:15:1
+ |
+LL | fn three<T: Debug, U>(t: T) -> Two<T, U> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `T` doesn't implement `Debug`
+ --> $DIR/not_a_defining_use.rs:7:18
+ |
+LL | type Two<T, U> = impl Debug;
+ | ^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ |
+ = note: required because of the requirements on the impl of `Debug` for `(T, i8)`
+help: consider restricting type parameter `T`
+ |
+LL | type Two<T: std::fmt::Debug, U> = impl Debug;
+ | +++++++++++++++++
+
+error: aborting due to 3 previous errors
+For more information about this error, try `rustc --explain E0277`.
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
fn p_foo<T>(_pinned: T) { }
fn s_foo<T>(_shared: T) { }
fn u_foo<T:Send>(_unique: T) { }
pub fn main() {
p_foo(r(10));
- p_foo::<Box<_>>(box r(10));
- p_foo::<Box<_>>(box 10);
+ p_foo::<Box<_>>(Box::new(r(10)));
+ p_foo::<Box<_>>(Box::new(10));
p_foo(10);
- s_foo::<Box<_>>(box 10);
+ s_foo::<Box<_>>(Box::new(10));
s_foo(10);
- u_foo::<Box<_>>(box 10);
+ u_foo::<Box<_>>(Box::new(10));
u_foo(10);
}
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
-#![feature(box_syntax)]
// Example from lkuper's intern talk, August 2012 -- now with static
// methods!
assert!(Equal::isEq(&leaf(cyan), &leaf(cyan)));
assert!(!Equal::isEq(&leaf(cyan), &leaf(yellow)));
- assert!(Equal::isEq(&branch(box leaf(magenta), box leaf(cyan)),
- &branch(box leaf(magenta), box leaf(cyan))));
+ assert!(Equal::isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))),
+ &branch(Box::new(leaf(magenta)), Box::new(leaf(cyan)))));
- assert!(!Equal::isEq(&branch(box leaf(magenta), box leaf(cyan)),
- &branch(box leaf(magenta), box leaf(magenta))));
+ assert!(!Equal::isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan))),
+ &branch(Box::new(leaf(magenta)), Box::new(leaf(magenta)))));
println!("Assertions all succeeded!");
}
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
-#![feature(box_syntax)]
// Example from lkuper's intern talk, August 2012.
use Color::{cyan, magenta, yellow, black};
assert!(leaf(cyan).isEq(&leaf(cyan)));
assert!(!leaf(cyan).isEq(&leaf(yellow)));
- assert!(branch(box leaf(magenta), box leaf(cyan))
- .isEq(&branch(box leaf(magenta), box leaf(cyan))));
+ assert!(branch(Box::new(leaf(magenta)), Box::new(leaf(cyan)))
+ .isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(cyan)))));
- assert!(!branch(box leaf(magenta), box leaf(cyan))
- .isEq(&branch(box leaf(magenta), box leaf(magenta))));
+ assert!(!branch(Box::new(leaf(magenta)), Box::new(leaf(cyan)))
+ .isEq(&branch(Box::new(leaf(magenta)), Box::new(leaf(magenta)))));
println!("Assertions all succeeded!");
}
-#![feature(box_syntax)]
-
struct Foo {
f: isize,
}
+
+
impl Foo {
fn foo(self: isize, x: isize) -> isize {
//~^ ERROR invalid `self` parameter type
}
fn main() {
- let foo = box Foo {
+ let foo = Box::new(Foo {
f: 1,
- };
+ });
println!("{}", foo.foo(2));
- let bar = box Bar {
+ let bar = Box::new(Bar {
f: 1,
- };
+ });
println!("{} {}", bar.foo(2), bar.bar(2));
}
// run-pass
-#![feature(box_syntax)]
use std::ops::FnMut;
fn make_adder(x: i32) -> Box<dyn FnMut(i32)->i32+'static> {
- (box move |y: i32| -> i32 { x + y }) as
+ Box::new(move |y: i32| -> i32 { x + y }) as
Box<dyn FnMut(i32)->i32+'static>
}
#![feature(box_patterns)]
-#![feature(box_syntax)]
#![feature(never_type)]
#![feature(exhaustive_patterns)]
+
#![deny(unreachable_patterns)]
mod foo {
-#![feature(box_syntax)]
-
trait Foo {
fn f(&self);
}
}
}
+
+
fn main() {
- let x = box Bar { x: 10 };
+ let x = Box::new(Bar { x: 10 });
let y: Box<dyn Foo> = x as Box<dyn Foo>;
let _z = y.clone(); //~ ERROR the method
}
// run-pass
-#![feature(box_syntax)]
pub fn main() {
- let mut i: Box<_> = box 1;
+ let mut i: Box<_> = Box::new(1);
// Should be a copy
let mut j;
j = i.clone();
// run-pass
#![allow(unused_assignments)]
-#![feature(box_syntax)]
-
pub fn main() {
- let i: Box<_> = box 1;
- let mut j: Box<_> = box 2;
+ let i: Box<_> = Box::new(1);
+ let mut j: Box<_> = Box::new(2);
// Should drop the previous value of j
j = i;
assert_eq!(*j, 1);
// run-pass
-#![feature(box_syntax)]
fn f<T>(t: T) -> T {
let t1 = t;
}
pub fn main() {
- let t = f::<Box<_>>(box 100);
- assert_eq!(t, box 100);
+ let t = f::<Box<_>>(Box::new(100));
+ assert_eq!(t, Box::new(100));
}
// run-pass
#![allow(unused_mut)]
-#![feature(box_syntax)]
pub fn main() {
let mut i: Box<_>;
- i = box 1;
+ i = Box::new(1);
assert_eq!(*i, 1);
}
// run-pass
-#![feature(box_syntax)]
struct J { j: isize }
pub fn main() {
- let i: Box<_> = box J {
+ let i: Box<_> = Box::new(J {
j: 100
- };
+ });
assert_eq!(i.j, 100);
}
// run-pass
-#![feature(box_syntax)]
pub fn main() {
- let i: Box<_> = box vec![100];
+ let i: Box<_> = Box::new(vec![100]);
assert_eq!((*i)[0], 100);
}
// run-pass
#![allow(unused_allocation)]
-#![feature(box_syntax)]
pub fn main() {
- let i: Box<_> = box 100;
- assert_eq!(i, box 100);
- assert!(i < box 101);
- assert!(i <= box 100);
- assert!(i > box 99);
- assert!(i >= box 99);
+ let i: Box<_> = Box::new(100);
+ assert_eq!(i, Box::new(100));
+ assert!(i < Box::new(101));
+ assert!(i <= Box::new(100));
+ assert!(i > Box::new(99));
+ assert!(i >= Box::new(99));
}
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
pub fn main() {
enum t { t1(isize), t2(isize), }
- let _x: Box<_> = box t::t1(10);
+ let _x: Box<_> = Box::new(t::t1(10));
/*alt *x {
t1(a) {
}*/
/*alt x {
- box t1(a) {
+ Box::new(t1(a) {
assert_eq!(a, 10);
- }
+ })
_ { panic!(); }
}*/
}
#![allow(dead_code)]
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
pub fn main() {
- let _: Box<_> = box 100;
+ let _: Box<_> = Box::new(100);
}
fn vec() {
// run-pass
-#![feature(box_syntax)]
pub fn main() {
- let mut i: Box<_> = box 1;
+ let mut i: Box<_> = Box::new(1);
// Should be a copy
let mut j = i.clone();
*i = 2;
// run-pass
-#![feature(box_syntax)]
pub fn main() {
- let i: Box<_> = box 1;
+ let i: Box<_> = Box::new(1);
let j = i;
assert_eq!(*j, 1);
}
// run-pass
-#![feature(box_syntax)]
pub fn main() {
- let i: Box<_> = box 100;
+ let i: Box<_> = Box::new(100);
let j = i;
assert_eq!(*j, 100);
}
// run-pass
-#![feature(box_syntax)]
pub fn main() {
- let i: Box<_> = box 100;
+ let i: Box<_> = Box::new(100);
assert_eq!(*i, 100);
}
// run-pass
#![feature(box_patterns)]
-#![feature(box_syntax)]
struct Foo { a: isize, b: isize }
pub fn main() {
- let box Foo{a, b} = box Foo{a: 100, b: 200};
+ let box Foo{ a, b } = Box::new(Foo { a: 100, b: 200 });
assert_eq!(a + b, 300);
}
// run-pass
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
pub fn main() {
- let _x: Box<_> = box vec![0,0,0,0,0];
+ let _x: Box<_> = Box::new(vec![0,0,0,0,0]);
}
// run-pass
-#![feature(box_syntax)]
fn f(i: Box<isize>) {
assert_eq!(*i, 100);
}
pub fn main() {
- let i = box 100;
+ let i = Box::new(100);
f(i);
}
// run-pass
-#![feature(box_syntax)]
fn f(i: &mut Box<isize>) {
- *i = box 200;
+ *i = Box::new(200);
}
pub fn main() {
- let mut i = box 100;
+ let mut i = Box::new(100);
f(&mut i);
assert_eq!(*i, 200);
}
// run-pass
-#![feature(box_syntax)]
fn f(i: Box<isize>) {
assert_eq!(*i, 100);
}
pub fn main() {
- f(box 100);
- let i = box 100;
+ f(Box::new(100));
+ let i = Box::new(100);
f(i);
}
// run-pass
-#![feature(box_syntax)]
fn f() -> Box<isize> {
- box 100
+ Box::new(100)
}
pub fn main() {
- assert_eq!(f(), box 100);
+ assert_eq!(f(), Box::new(100));
}
#![allow(dead_code)]
#![allow(non_camel_case_types)]
-#![feature(box_syntax)]
-
fn test1() {
enum bar { u(Box<isize>), w(isize), }
- let x = bar::u(box 10);
+ let x = bar::u(Box::new(10));
assert!(match x {
bar::u(a) => {
println!("{}", a);
// run-pass
-#![feature(box_syntax)]
pub fn main() {
- let mut a: Vec<Box<_>> = vec![box 10];
+ let mut a: Vec<Box<_>> = vec![Box::new(10)];
let b = a.clone();
assert_eq!(*a[0], 10);
// run-pass
-#![feature(box_syntax)]
pub fn main() {
- let vect : Vec<Box<_>> = vec![box 100];
- assert_eq!(vect[0], box 100);
+ let vect : Vec<Box<_>> = vec![Box::new(100)];
+ assert_eq!(vect[0], Box::new(100));
}
// run-pass
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
pub fn main() {
- let _i: Box<_> = box 100;
+ let _i: Box<_> = Box::new(100);
}
// run-pass
-#![feature(box_syntax)]
use std::cmp::PartialEq;
use std::fmt::Debug;
assert!(i != j);
}
- let i: Box<_> = box 100;
- let j: Box<_> = box 100;
+ let i: Box<_> = Box::new(100);
+ let j: Box<_> = Box::new(100);
f(i, j);
- let i: Box<_> = box 100;
- let j: Box<_> = box 101;
+ let i: Box<_> = Box::new(100);
+ let j: Box<_> = Box::new(101);
g(i, j);
}
assert!(i != j);
}
- let i: Box<_> = box 100;
- let j: Box<_> = box 100;
+ let i: Box<_> = Box::new(100);
+ let j: Box<_> = Box::new(100);
f(i, j);
- let i: Box<_> = box 100;
- let j: Box<_> = box 101;
+ let i: Box<_> = Box::new(100);
+ let j: Box<_> = Box::new(101);
g(i, j);
}
assert!(i != j);
}
- let i: Box<_> = box 100;
- let j: Box<_> = box 100;
+ let i: Box<_> = Box::new(100);
+ let j: Box<_> = Box::new(100);
f(i, j);
- let i: Box<_> = box 100;
- let j: Box<_> = box 101;
+ let i: Box<_> = Box::new(100);
+ let j: Box<_> = Box::new(101);
g(i, j);
}
// run-pass
-#![feature(box_syntax)]
pub fn main() {
- let i: Box<_> = box 100;
+ let i: Box<_> = Box::new(100);
println!("{}", i);
}
// run-pass
#![allow(unused_variables)]
-#![feature(box_syntax)]
pub fn main() {
- let i: Box<_> = box 100;
- let j: Box<_> = box 200;
+ let i: Box<_> = Box::new(100);
+ let j: Box<_> = Box::new(200);
let j = i;
assert_eq!(*j, 100);
}
// run-pass
#![allow(unused_mut)]
-#![feature(box_syntax)]
pub fn main() {
let mut i: Box<_>;
- i = box 100;
+ i = Box::new(100);
assert_eq!(*i, 100);
}
// run-pass
#![allow(unused_mut)]
-#![feature(box_syntax)]
pub fn main() {
- let i: Box<_> = box 100;
+ let i: Box<_> = Box::new(100);
let mut j;
j = i;
assert_eq!(*j, 100);
// run-pass
-#![feature(box_syntax)]
pub fn main() {
- let mut i: Box<_> = box 0;
+ let mut i: Box<_> = Box::new(0);
*i = 1;
assert_eq!(*i, 1);
}
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
pub trait EventLoop { fn foo(&self) {} }
pub struct UvEventLoop {
impl EventLoop for UvEventLoop { }
pub fn main() {
- let loop_: Box<dyn EventLoop> = box UvEventLoop { uvio: 0 } as Box<dyn EventLoop>;
+ let loop_: Box<dyn EventLoop> = Box::new(UvEventLoop { uvio: 0 }) as Box<dyn EventLoop>;
let _loop2_ = loop_;
}
#![allow(non_shorthand_field_patterns)]
#![feature(box_patterns)]
-#![feature(box_syntax)]
struct Foo {a: isize, b: usize}
enum bar { u(Box<Foo>), w(isize), }
pub fn main() {
- assert!(match bar::u(box Foo{a: 10, b: 40}) {
- bar::u(box Foo{a: a, b: b}) => { a + (b as isize) }
- _ => { 66 }
- } == 50);
+ let v = match bar::u(Box::new(Foo{ a: 10, b: 40 })) {
+ bar::u(box Foo{ a: a, b: b }) => { a + (b as isize) }
+ _ => { 66 }
+ };
+ assert_eq!(v, 50);
}
#![allow(dead_code)]
#![allow(non_camel_case_types)]
-#![feature(box_syntax)]
-
enum bar { u(Box<isize>), w(isize), }
pub fn main() {
- assert!(match bar::u(box 10) {
- bar::u(a) => {
- println!("{}", a);
- *a
- }
- _ => { 66 }
- } == 10);
+ let v = match bar::u(10.into()) {
+ bar::u(a) => {
+ println!("{}", a);
+ *a
+ }
+ _ => { 66 }
+ };
+ assert_eq!(v, 10);
}
// run-pass
#![feature(box_patterns)]
-#![feature(box_syntax)]
fn simple() {
- match box true {
+ match Box::new(true) {
box true => { }
_ => { panic!(); }
}
// run-pass
-#![feature(box_syntax)]
struct X { x: isize }
pub fn main() {
- let x: Box<_> = box X {x: 1};
+ let x: Box<_> = Box::new(X {x: 1});
let bar = x;
assert_eq!(bar.x, 1);
}
#![allow(unused_must_use)]
// ignore-emscripten no threads support
-#![feature(box_syntax)]
-
use std::sync::mpsc::{channel, Sender};
use std::thread;
fn child(tx: &Sender<Box<usize>>, i: usize) {
- tx.send(box i).unwrap();
+ tx.send(Box::new(i)).unwrap();
}
pub fn main() {
// run-pass
-#![feature(box_syntax)]
use std::sync::mpsc::channel;
pub fn main() {
let (tx, rx) = channel::<Box<_>>();
- tx.send(box 100).unwrap();
+ tx.send(Box::new(100)).unwrap();
let v = rx.recv().unwrap();
- assert_eq!(v, box 100);
+ assert_eq!(v, Box::new(100));
}
// run-pass
-#![feature(box_syntax)]
use std::mem::swap;
pub fn main() {
- let mut i: Box<_> = box 100;
- let mut j: Box<_> = box 200;
+ let mut i: Box<_> = Box::new(100);
+ let mut j: Box<_> = Box::new(200);
swap(&mut i, &mut j);
- assert_eq!(i, box 200);
- assert_eq!(j, box 100);
+ assert_eq!(i, Box::new(200));
+ assert_eq!(j, Box::new(100));
}
#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_imports)]
-#![feature(box_syntax)]
// Test sized-ness checking in substitution.
struct S;
impl T2 for S {
fn f() -> Box<S> {
- box S
+ Box::new(S)
}
}
fn f5<X: ?Sized+T2>(x: &X) {
}
impl T3 for S {
fn f() -> Box<S> {
- box S
+ Box::new(S)
}
}
fn f7<X: ?Sized+T3>(x: &X) {
// Test structs with always-unsized fields.
#![allow(warnings)]
-#![feature(box_syntax, unsize, ptr_metadata)]
+#![feature(unsize, ptr_metadata)]
use std::mem;
use std::ptr;
f: [T; 3],
}
- let data: Box<Foo_<i32>> = box Foo_ { f: [1, 2, 3] };
+ let data: Box<Foo_<i32>> = Box::new(Foo_ { f: [1, 2, 3] });
let x: &Foo<i32> = mem::transmute(slice::from_raw_parts(&*data, 3));
assert_eq!(x.f.len(), 3);
assert_eq!(x.f[0], 1);
}
let data: Box<_> =
- box Baz_ { f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] };
+ Box::new(Baz_ { f1: 42, f2: ['a' as u8, 'b' as u8, 'c' as u8, 'd' as u8, 'e' as u8] });
let x: &Baz = mem::transmute(slice::from_raw_parts(&*data, 5));
assert_eq!(x.f1, 42);
let chs: Vec<char> = x.f2.chars().collect();
f: St,
}
- let obj: Box<St> = box St { f: 42 };
+ let obj: Box<St> = Box::new(St { f: 42 });
let obj: &Tr = &*obj;
- let data: Box<_> = box Qux_ { f: St { f: 234 } };
+ let data: Box<_> = Box::new(Qux_ { f: St { f: 234 } });
let x: &Qux = &*ptr::from_raw_parts::<Qux>((&*data as *const _).cast(), ptr::metadata(obj));
assert_eq!(x.f.foo(), 234);
}
// run-pass
// pretty-expanded FIXME #23616
-#![feature(box_syntax)]
-
pub fn main() {
- let _x: Box<_> = box 1;
+ let _x: Box<_> = Box::new(1);
let lam_move = || {};
lam_move();
}
// pretty-expanded FIXME #23616
#![allow(path_statements)]
-#![feature(box_syntax)]
-pub fn main()
-{
- let y: Box<_> = box 1;
+pub fn main() {
+ let y: Box<_> = Box::new(1);
y;
}
// run-pass
// ignore-emscripten no threads support
-#![feature(box_syntax)]
-
use std::thread;
fn f() {
- let _a: Box<_> = box 0;
+ let _a: Box<_> = Box::new(0);
panic!();
}
-#![feature(box_syntax)]
-
use std::fmt;
struct Number {
}
fn main() {
- let n: Box<_> = box Number { n: 42 };
- let mut l: Box<_> = box List { list: Vec::new() };
+
+ let n: Box<_> = Number { n: 42 }.into();
+ let mut l: Box<_> = List { list: Vec::new() }.into();
l.push(n);
+
let x = n.to_string();
//~^ ERROR: borrow of moved value: `n`
}
error[E0382]: borrow of moved value: `n`
--> $DIR/use-after-move-implicity-coerced-object.rs:28:13
|
-LL | let n: Box<_> = box Number { n: 42 };
+LL | let n: Box<_> = Number { n: 42 }.into();
| - move occurs because `n` has type `Box<Number>`, which does not implement the `Copy` trait
-LL | let mut l: Box<_> = box List { list: Vec::new() };
+LL | let mut l: Box<_> = List { list: Vec::new() }.into();
LL | l.push(n);
| - value moved here
+LL |
LL | let x = n.to_string();
| ^ value borrowed here after move
-#![feature(box_syntax)]
-
struct S {
x: Box<isize>,
}
+
+
impl S {
pub fn foo(self) -> isize {
self.bar();
}
fn main() {
- let x = S { x: box 1 };
+ let x = S { x: 1.into() };
println!("{}", x.foo());
}
// Regression test for #87549.
-// compile-flags: -C incremental=tmp/wf/hir-wf-check-erase-regions
+// incremental
pub struct Table<T, const N: usize>([Option<T>; N]);
[package]
name = "build-manifest"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[dependencies]
toml = "0.5"
[package]
name = "bump-stage0"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-Subproject commit 9a28ac83c9eb73e42ffafac552c0a55f00dbf40c
+Subproject commit 0121d66aa2ef5ffa9735f86c2b56f5fdc5a837a6
[package]
name = "cargotest2"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[[bin]]
name = "cargotest"
// be sure we have `self` parameter in this function
if let AssocItemKind::Fn { has_self: true } = trait_item.kind {
trait_self_ty =
- Some(TraitRef::identity(cx.tcx, trait_item.id.def_id.to_def_id()).self_ty());
+ Some(TraitRef::identity(cx.tcx, trait_item.id.def_id.to_def_id()).self_ty().skip_binder());
}
}
}
}
}
-fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef<'_>]) {
+fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[hir::ImplItemRef]) {
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::{Expr, ExprKind, ImplItemKind, QPath};
declare_clippy_lint! {
/// ### What it does
/// Checks for use of `.iter().nth()` (and the related
- /// `.iter_mut().nth()`) on standard library types with O(1) element access.
+ /// `.iter_mut().nth()`) on standard library types with *O*(1) element access.
///
/// ### Why is this bad?
/// `.get()` and `.get_mut()` are more efficient and more
then {
let first_arg_span = first_arg_ty.span;
let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty);
- let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty();
+ let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty().skip_binder();
wrong_self_convention::check(
cx,
&item.ident.name.as_str(),
if item.ident.name == sym::new;
if let TraitItemKind::Fn(_, _) = item.kind;
let ret_ty = return_ty(cx, item.hir_id());
- let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty();
+ let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty().skip_binder();
if !contains_ty(cx.tcx, ret_ty, self_ty);
then {
if_else,
) = expr.kind
{
- let hir = cx.tcx.hir();
- let mut iter = hir.parent_iter(expr.hir_id);
+ let mut iter = cx.tcx.hir().parent_iter(expr.hir_id);
if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next() {
if let Some((
_,
if let ExpnKind::Macro(_, name) = expr.span.ctxt().outer_expn_data().kind;
let name = name.as_str();
if name.ends_with("format_args") || name.ends_with("format_args_nl");
-
- if let ExprKind::Match(inner_match, [arm], _) = expr.kind;
-
- // `match match`, if you will
- if let ExprKind::Match(args, [inner_arm], _) = inner_match.kind;
- if let ExprKind::Tup(value_args) = args.kind;
- if let Some(value_args) = value_args
- .iter()
- .map(|e| match e.kind {
- ExprKind::AddrOf(_, _, e) => Some(e),
- _ => None,
- })
- .collect();
- if let ExprKind::Array(args) = inner_arm.body.kind;
-
- if let ExprKind::Block(Block { stmts: [], expr: Some(expr), .. }, _) = arm.body.kind;
- if let ExprKind::Call(_, call_args) = expr.kind;
- if let Some((strs_ref, fmt_expr)) = match call_args {
+ if let ExprKind::Call(_, args) = expr.kind;
+ if let Some((strs_ref, args, fmt_expr)) = match args {
// Arguments::new_v1
- [strs_ref, _] => Some((strs_ref, None)),
+ [strs_ref, args] => Some((strs_ref, args, None)),
// Arguments::new_v1_formatted
- [strs_ref, _, fmt_expr] => Some((strs_ref, Some(fmt_expr))),
+ [strs_ref, args, fmt_expr, _unsafe_arg] => Some((strs_ref, args, Some(fmt_expr))),
_ => None,
};
if let ExprKind::AddrOf(BorrowKind::Ref, _, strs_arr) = strs_ref.kind;
None
})
.collect();
+ if let ExprKind::AddrOf(BorrowKind::Ref, _, args) = args.kind;
+ if let ExprKind::Match(args, [arm], _) = args.kind;
+ if let ExprKind::Tup(value_args) = args.kind;
+ if let Some(value_args) = value_args
+ .iter()
+ .map(|e| match e.kind {
+ ExprKind::AddrOf(_, _, e) => Some(e),
+ _ => None,
+ })
+ .collect();
+ if let ExprKind::Array(args) = arm.body.kind;
then {
Some(FormatArgsExpn {
format_string_span: strs_ref.span,
ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(_), .. }))
));
- let map = cx.tcx.hir();
let mut child_id = e.hir_id;
let mut capture = CaptureKind::Value;
let mut capture_expr_ty = e;
- for (parent_id, parent) in map.parent_iter(e.hir_id) {
+ for (parent_id, parent) in cx.tcx.hir().parent_iter(e.hir_id) {
if let [Adjustment {
kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
target,
/// Gets the loop or closure enclosing the given expression, if any.
pub fn get_enclosing_loop_or_closure(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
- let map = tcx.hir();
- for (_, node) in map.parent_iter(expr.hir_id) {
+ for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
match node {
Node::Expr(
e
/// Gets the parent node if it's an impl block.
pub fn get_parent_as_impl(tcx: TyCtxt<'_>, id: HirId) -> Option<&Impl<'_>> {
- let map = tcx.hir();
- match map.parent_iter(id).next() {
+ match tcx.hir().parent_iter(id).next() {
Some((
_,
Node::Item(Item {
/// Checks if the given expression is the else clause of either an `if` or `if let` expression.
pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
- let map = tcx.hir();
- let mut iter = map.parent_iter(expr.hir_id);
+ let mut iter = tcx.hir().parent_iter(expr.hir_id);
match iter.next() {
Some((
_,
/// Gets the node where an expression is either used, or it's type is unified with another branch.
pub fn get_expr_use_or_unification_node(tcx: TyCtxt<'tcx>, expr: &Expr<'_>) -> Option<Node<'tcx>> {
- let map = tcx.hir();
let mut child_id = expr.hir_id;
- let mut iter = map.parent_iter(child_id);
+ let mut iter = tcx.hir().parent_iter(child_id);
loop {
match iter.next() {
None => break None,
},
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => Ok(()),
Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())),
+ Rvalue::ShallowInitBox(_, _) => Ok(()),
Rvalue::UnaryOp(_, operand) => {
let ty = operand.ty(body, tcx);
if ty.is_integral() || ty.is_bool() {
[package]
name = "compiletest"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
colored = "2"
pub fn output_base_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
output_base_dir(config, testpaths, revision).join(testpaths.file.file_stem().unwrap())
}
+
+/// Absolute path to the directory to use for incremental compilation. Example:
+/// /path/to/build/host-triple/test/ui/relative/testname.mode/testname.inc
+pub fn incremental_dir(config: &Config, testpaths: &TestPaths) -> PathBuf {
+ output_base_name(config, testpaths, None).with_extension("inc")
+}
// testing harness and used when generating compilation
// arguments. (In particular, it propagates to the aux-builds.)
pub incremental_dir: Option<PathBuf>,
+ // If `true`, this test will use incremental compilation.
+ //
+ // This can be set manually with the `incremental` header, or implicitly
+ // by being a part of an incremental mode test. Using the `incremental`
+ // header should be avoided if possible; using an incremental mode test is
+ // preferred. Incremental mode tests support multiple passes, which can
+ // verify that the incremental cache can be loaded properly after being
+ // created. Just setting the header will only verify the behavior with
+ // creating an incremental cache, but doesn't check that it is created
+ // correctly.
+ //
+ // Compiletest will create the incremental directory, and ensure it is
+ // empty before the test starts. Incremental mode tests will reuse the
+ // incremental directory between passes in the same test.
+ pub incremental: bool,
// How far should the test proceed while still passing.
pass_mode: Option<PassMode>,
// Ignore `--pass` overrides from the command line for this test.
pretty_compare_only: false,
forbid_output: vec![],
incremental_dir: None,
+ incremental: false,
pass_mode: None,
fail_mode: None,
ignore_pass: false,
if !self.stderr_per_bitwidth {
self.stderr_per_bitwidth = config.parse_stderr_per_bitwidth(ln);
}
+
+ if !self.incremental {
+ self.incremental = config.parse_incremental(ln);
+ }
});
}
self.failure_status = 101;
}
+ if config.mode == Mode::Incremental {
+ self.incremental = true;
+ }
+
for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
if let Ok(val) = env::var(key) {
if self.exec_env.iter().find(|&&(ref x, _)| x == key).is_none() {
fn parse_edition(&self, line: &str) -> Option<String> {
self.parse_name_value_directive(line, "edition")
}
+
+ fn parse_incremental(&self, line: &str) -> bool {
+ self.parse_name_directive(line, "incremental")
+ }
}
fn expand_variables(mut value: String, config: &Config) -> String {
// ignore-tidy-filelength
use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT};
-use crate::common::{output_base_dir, output_base_name, output_testname_unique};
+use crate::common::{incremental_dir, output_base_dir, output_base_name, output_testname_unique};
use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJson, Ui};
use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc};
use crate::common::{CompareMode, FailMode, PassMode};
print!("\n\n");
}
debug!("running {:?}", testpaths.file.display());
- let props = TestProps::from_file(&testpaths.file, revision, &config);
+ let mut props = TestProps::from_file(&testpaths.file, revision, &config);
+ if props.incremental {
+ props.incremental_dir = Some(incremental_dir(&config, testpaths));
+ }
let cx = TestCx { config: &config, props: &props, testpaths, revision };
create_dir_all(&cx.output_base_dir()).unwrap();
+ if props.incremental {
+ cx.init_incremental_test();
+ }
if config.mode == Incremental {
// Incremental tests are special because they cannot be run in
// parallel.
assert!(!props.revisions.is_empty(), "Incremental tests require revisions.");
- cx.init_incremental_test();
for revision in &props.revisions {
- let revision_props = TestProps::from_file(&testpaths.file, Some(revision), &config);
+ let mut revision_props = TestProps::from_file(&testpaths.file, Some(revision), &config);
+ revision_props.incremental_dir = props.incremental_dir.clone();
let rev_cx = TestCx {
config: &config,
props: &revision_props,
// incremental workproduct directory. Delete any old
// incremental work products that may be there from prior
// runs.
- let incremental_dir = self.incremental_dir();
+ let incremental_dir = self.props.incremental_dir.as_ref().unwrap();
if incremental_dir.exists() {
// Canonicalizing the path will convert it to the //?/ format
// on Windows, which enables paths longer than 260 character
fs::create_dir_all(&incremental_dir).unwrap();
if self.config.verbose {
- print!("init_incremental_test: incremental_dir={}", incremental_dir.display());
+ println!("init_incremental_test: incremental_dir={}", incremental_dir.display());
}
}
let revision = self.revision.expect("incremental tests require a list of revisions");
// Incremental workproduct directory should have already been created.
- let incremental_dir = self.incremental_dir();
+ let incremental_dir = self.props.incremental_dir.as_ref().unwrap();
assert!(incremental_dir.exists(), "init_incremental_test failed to create incremental dir");
- // Add an extra flag pointing at the incremental directory.
- let mut revision_props = self.props.clone();
- revision_props.incremental_dir = Some(incremental_dir);
-
- let revision_cx = TestCx {
- config: self.config,
- props: &revision_props,
- testpaths: self.testpaths,
- revision: self.revision,
- };
-
if self.config.verbose {
- print!("revision={:?} revision_props={:#?}", revision, revision_props);
+ print!("revision={:?} props={:#?}", revision, self.props);
}
if revision.starts_with("rpass") {
- if revision_cx.props.should_ice {
- revision_cx.fatal("can only use should-ice in cfail tests");
+ if self.props.should_ice {
+ self.fatal("can only use should-ice in cfail tests");
}
- revision_cx.run_rpass_test();
+ self.run_rpass_test();
} else if revision.starts_with("rfail") {
- if revision_cx.props.should_ice {
- revision_cx.fatal("can only use should-ice in cfail tests");
+ if self.props.should_ice {
+ self.fatal("can only use should-ice in cfail tests");
}
- revision_cx.run_rfail_test();
+ self.run_rfail_test();
} else if revision.starts_with("cfail") {
- revision_cx.run_cfail_test();
+ self.run_cfail_test();
} else {
- revision_cx.fatal("revision name must begin with rpass, rfail, or cfail");
+ self.fatal("revision name must begin with rpass, rfail, or cfail");
}
}
- /// Directory where incremental work products are stored.
- fn incremental_dir(&self) -> PathBuf {
- self.output_base_name().with_extension("inc")
- }
-
fn run_rmake_test(&self) {
let cwd = env::current_dir().unwrap();
let src_root = self.config.src_base.parent().unwrap().parent().unwrap().parent().unwrap();
];
pub const LSAN_SUPPORTED_TARGETS: &[&str] = &[
- "aarch64-apple-darwin",
+ // FIXME: currently broken, see #88132
+ // "aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-unknown-linux-gnu",
[package]
name = "error_index_generator"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
[dependencies]
rustdoc = { path = "../../librustdoc" }
[package]
name = "expand-yaml-anchors"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[dependencies]
yaml-rust = "0.4.3"
[package]
name = "html-checker"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[[bin]]
name = "html-checker"
[package]
name = "jsondocck"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[dependencies]
jsonpath_lib = "0.2"
[package]
name = "linkchecker"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[[bin]]
name = "linkchecker"
[package]
name = "lint-docs"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
description = "A script to extract the lint documentation for the rustc book."
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
} else if line.starts_with("// ") {
// Ignore comments.
continue;
+ } else if line.starts_with("#[allow") {
+ // Ignore allow of lints (useful for
+ // invalid_rust_codeblocks).
+ continue;
} else {
let name = lint_name(line).map_err(|e| {
format!(
[package]
name = "remote-test-client"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[dependencies]
[package]
name = "remote-test-server"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[dependencies]
-Subproject commit b73b321478d3b2a98d380eb79de717e01620c4e9
+Subproject commit f1d7f98ed07b9934286b9c4809dd4d7a47537879
[package]
name = "rust-demangler"
version = "0.0.1"
-edition = "2018"
+edition = "2021"
[dependencies]
regex = "1.0"
name = "rustbook"
version = "0.1.0"
license = "MIT OR Apache-2.0"
-edition = "2018"
+edition = "2021"
[dependencies]
clap = "2.25.0"
description = """
Hack for the compiler's own build system
"""
-edition = "2018"
+edition = "2021"
[lib]
path = "lib.rs"
[package]
name = "rustdoc-themes"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[[bin]]
name = "rustdoc-themes"
[package]
name = "rustdoc-tool"
version = "0.0.0"
-edition = "2018"
+edition = "2021"
# Cargo adds a number of paths to the dylib search path on windows, which results in
# the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
license = "Apache-2.0/MIT"
build = "build.rs"
categories = ["development-tools"]
-edition = "2018"
+edition = "2021"
[[bin]]
name = "rustfmt"
[package]
name = "tidy"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
autobins = false
[dependencies]
-//! Tidy check to ensure that crate `edition` is '2018'
+//! Tidy check to ensure that crate `edition` is '2018' or '2021'.
use std::path::Path;
fn is_edition_2018(mut line: &str) -> bool {
line = line.trim();
- line == "edition = \"2018\"" || line == "edition = \'2018\'"
+ line == "edition = \"2018\""
+}
+
+fn is_edition_2021(mut line: &str) -> bool {
+ line = line.trim();
+ line == "edition = \"2021\""
}
pub fn check(path: &Path, bad: &mut bool) {
&mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
&mut |entry, contents| {
let file = entry.path();
+ let filestr = file.to_string_lossy().replace("\\", "/");
let filename = file.file_name().unwrap();
if filename != "Cargo.toml" {
return;
}
- let has_edition = contents.lines().any(is_edition_2018);
- if !has_edition {
- tidy_error!(
- bad,
- "{} doesn't have `edition = \"2018\"` on a separate line",
- file.display()
- );
+
+ // Library crates are not yet ready to migrate to 2021.
+ //
+ // The reference and rustc-dev-guide are submodules, so are left at
+ // 2018 for now. They should be removed from this exception list
+ // when bumped.
+ if path.components().any(|c| c.as_os_str() == "library")
+ || filestr.contains("src/doc/reference/style-check/Cargo.toml")
+ || filestr.contains("src/doc/rustc-dev-guide/ci/date-check/Cargo.toml")
+ {
+ let has = contents.lines().any(is_edition_2018);
+ if !has {
+ tidy_error!(
+ bad,
+ "{} doesn't have `edition = \"2018\"` on a separate line",
+ file.display()
+ );
+ }
+ } else {
+ let is_2021 = contents.lines().any(is_edition_2021);
+ if !is_2021 {
+ tidy_error!(
+ bad,
+ "{} doesn't have `edition = \"2021\"` on a separate line",
+ file.display()
+ );
+ }
}
},
);
[package]
name = "tier-check"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
license = "MIT OR Apache-2.0"
[dependencies]
[package]
name = "unicode-bdd"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
name = "unstable-book-gen"
version = "0.1.0"
license = "MIT OR Apache-2.0"
-edition = "2018"
+edition = "2021"
[dependencies]
tidy = { path = "../tidy" }
name = "x"
version = "0.1.0"
description = "Run x.py slightly more conveniently"
-edition = "2018"
+edition = "2021"
publish = false