If you cannot produce a minimal reproduction case (something that would work in
isolation), please provide the steps or even link to a repository that causes
-the problematic output to occur.
+the problematic output to occur.
-->
Given the following code: <!-- Please provide a link to play.rust-lang.org -->
name: Library Tracking Issue
about: A tracking issue for an unstable library feature.
title: Tracking Issue for XXX
-labels: C-tracking-issue, T-libs
+labels: C-tracking-issue, T-libs-api
---
<!--
Thank you for creating a tracking issue!
If this feature didn't go through the RFC process, a final commenting period
(FCP) is always needed before stabilization. This works as follows:
-A library team member can kick off the stabilization process, at which point
+A library API team member can kick off the stabilization process, at which point
the rfcbot will ask all the team members to verify they agree with
stabilization. Once enough members agree and there are no concerns, the final
commenting period begins: this issue will be marked as such and will be listed
"libc",
"merge",
"num_cpus",
+ "once_cell",
"opener",
"pretty_assertions",
"serde",
"regex",
]
+[[package]]
+name = "globwalk"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
+dependencies = [
+ "bitflags",
+ "ignore",
+ "walkdir",
+]
+
[[package]]
name = "gsgdt"
version = "0.1.2"
"serde_json",
"smallvec",
"tempfile",
+ "tera",
"tracing",
"tracing-subscriber",
"tracing-tree",
[[package]]
name = "rustversion"
-version = "1.0.4"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd"
+checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
[[package]]
name = "ryu"
"utf-8",
]
+[[package]]
+name = "tera"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81060acb882480c8793782eb96bc86f5c83d2fc7175ad46c375c6956ef7afa62"
+dependencies = [
+ "globwalk",
+ "lazy_static",
+ "pest",
+ "pest_derive",
+ "regex",
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "term"
version = "0.0.0"
The Rust build system uses a Python script called `x.py` to build the compiler,
which manages the bootstrapping process. It lives in the root of the project.
-The `x.py` command can be run directly on most systems in the following format:
+The `x.py` command can be run directly on most systems in the following format:
```sh
./x.py <subcommand> [flags]
--------
- [You can now parameterize items such as functions, traits, and `struct`s by constant
values in addition to by types and lifetimes.][79135] Also known as "const generics"
- E.g. you can now write the following. Note: Only values of primitive integers,
+ E.g. you can now write the following. Note: Only values of primitive integers,
`bool`, or `char` types are currently permitted.
```rust
struct GenericArray<T, const LENGTH: usize> {
- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning
that you can create an enum that has the exact layout and ABI of the type
it contains.
+- [You can now use outer attribute procedural macros on inline modules.][64273]
- [There are some *syntax-only* changes:][67131]
- `default` is syntactically allowed before items in `trait` definitions.
- Items in `impl`s (i.e. `const`s, `type`s, and `fn`s) may syntactically
[67935]: https://github.com/rust-lang/rust/pull/67935/
[68339]: https://github.com/rust-lang/rust/pull/68339/
[68122]: https://github.com/rust-lang/rust/pull/68122/
+[64273]: https://github.com/rust-lang/rust/pull/64273/
[67712]: https://github.com/rust-lang/rust/pull/67712/
[67887]: https://github.com/rust-lang/rust/pull/67887/
[67131]: https://github.com/rust-lang/rust/pull/67131/
/// ```
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Arm {
- pub attrs: Vec<Attribute>,
+ pub attrs: AttrVec,
/// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`
pub pat: P<Pat>,
/// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Variant {
/// Attributes of the variant.
- pub attrs: Vec<Attribute>,
+ pub attrs: AttrVec,
/// Id of the variant (not the constructor, see `VariantData::ctor_id()`).
pub id: NodeId,
/// Span
/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FieldDef {
- pub attrs: Vec<Attribute>,
+ pub attrs: AttrVec,
pub id: NodeId,
pub span: Span,
pub vis: Visibility,
pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
- visit_attrs(attrs, vis);
+ visit_thin_attrs(attrs, vis);
vis.visit_id(id);
vis.visit_pat(pat);
visit_opt(guard, |guard| vis.visit_expr(guard));
let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
visitor.visit_ident(ident);
visitor.visit_vis(vis);
- visit_attrs(attrs, visitor);
+ visit_thin_attrs(attrs, visitor);
visitor.visit_id(id);
visitor.visit_variant_data(data);
visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
visitor.visit_vis(vis);
visitor.visit_id(id);
visitor.visit_ty(ty);
- visit_attrs(attrs, visitor);
+ visit_thin_attrs(attrs, visitor);
smallvec![fd]
}
kind: ast::VisibilityKind::Inherited,
tokens: None,
},
- attrs: Vec::new(),
+ attrs: ast::AttrVec::new(),
id: ast::DUMMY_NODE_ID,
data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
disr_expr: None,
annotatable: Annotatable,
) -> Vec<Annotatable> {
check_builtin_macro_attribute(ecx, meta_item, sym::cfg_eval);
- cfg_eval(ecx, annotatable)
+ vec![cfg_eval(ecx, annotatable)]
}
-crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Vec<Annotatable> {
- let mut visitor = CfgEval {
+crate fn cfg_eval(ecx: &ExtCtxt<'_>, annotatable: Annotatable) -> Annotatable {
+ CfgEval {
cfg: &mut StripUnconfigured {
sess: ecx.sess,
features: ecx.ecfg.features,
config_tokens: true,
},
- };
- let annotatable = visitor.configure_annotatable(annotatable);
- vec![annotatable]
+ }
+ .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> {
cfg: &'a mut StripUnconfigured<'b>,
}
-fn flat_map_annotatable(vis: &mut impl MutVisitor, annotatable: Annotatable) -> Annotatable {
- // Since the item itself has already been configured by the InvocationCollector,
- // we know that fold result vector will contain exactly one element
+fn flat_map_annotatable(
+ vis: &mut impl MutVisitor,
+ annotatable: Annotatable,
+) -> Option<Annotatable> {
match annotatable {
- Annotatable::Item(item) => Annotatable::Item(vis.flat_map_item(item).pop().unwrap()),
+ Annotatable::Item(item) => vis.flat_map_item(item).pop().map(Annotatable::Item),
Annotatable::TraitItem(item) => {
- Annotatable::TraitItem(vis.flat_map_trait_item(item).pop().unwrap())
+ vis.flat_map_trait_item(item).pop().map(Annotatable::TraitItem)
}
Annotatable::ImplItem(item) => {
- Annotatable::ImplItem(vis.flat_map_impl_item(item).pop().unwrap())
+ vis.flat_map_impl_item(item).pop().map(Annotatable::ImplItem)
}
Annotatable::ForeignItem(item) => {
- Annotatable::ForeignItem(vis.flat_map_foreign_item(item).pop().unwrap())
+ vis.flat_map_foreign_item(item).pop().map(Annotatable::ForeignItem)
}
Annotatable::Stmt(stmt) => {
- Annotatable::Stmt(stmt.map(|stmt| vis.flat_map_stmt(stmt).pop().unwrap()))
+ vis.flat_map_stmt(stmt.into_inner()).pop().map(P).map(Annotatable::Stmt)
}
- Annotatable::Expr(mut expr) => Annotatable::Expr({
+ Annotatable::Expr(mut expr) => {
vis.visit_expr(&mut expr);
- expr
- }),
- Annotatable::Arm(arm) => Annotatable::Arm(vis.flat_map_arm(arm).pop().unwrap()),
- Annotatable::ExprField(field) => {
- Annotatable::ExprField(vis.flat_map_expr_field(field).pop().unwrap())
+ Some(Annotatable::Expr(expr))
}
- Annotatable::PatField(fp) => {
- Annotatable::PatField(vis.flat_map_pat_field(fp).pop().unwrap())
+ Annotatable::Arm(arm) => vis.flat_map_arm(arm).pop().map(Annotatable::Arm),
+ Annotatable::ExprField(field) => {
+ vis.flat_map_expr_field(field).pop().map(Annotatable::ExprField)
}
+ Annotatable::PatField(fp) => vis.flat_map_pat_field(fp).pop().map(Annotatable::PatField),
Annotatable::GenericParam(param) => {
- Annotatable::GenericParam(vis.flat_map_generic_param(param).pop().unwrap())
- }
- Annotatable::Param(param) => Annotatable::Param(vis.flat_map_param(param).pop().unwrap()),
- Annotatable::FieldDef(sf) => {
- Annotatable::FieldDef(vis.flat_map_field_def(sf).pop().unwrap())
+ vis.flat_map_generic_param(param).pop().map(Annotatable::GenericParam)
}
- Annotatable::Variant(v) => Annotatable::Variant(vis.flat_map_variant(v).pop().unwrap()),
+ Annotatable::Param(param) => vis.flat_map_param(param).pop().map(Annotatable::Param),
+ Annotatable::FieldDef(sf) => vis.flat_map_field_def(sf).pop().map(Annotatable::FieldDef),
+ Annotatable::Variant(v) => vis.flat_map_variant(v).pop().map(Annotatable::Variant),
}
}
self.cfg.configure(node)
}
- pub fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Annotatable {
+ fn configure_annotatable(&mut self, mut annotatable: Annotatable) -> Option<Annotatable> {
// Tokenizing and re-parsing the `Annotatable` can have a significant
// performance impact, so try to avoid it if possible
if !CfgFinder::has_cfg_or_cfg_attr(&annotatable) {
- return annotatable;
+ return Some(annotatable);
}
// The majority of parsed attribute targets will never need to have early cfg-expansion
return ExpandResult::Ready(vec![item]);
}
+ let item = cfg_eval(ecx, item);
+
let result =
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
let template =
report_path_args(sess, &meta);
meta.path
})
- .map(|path| (path, None))
+ .map(|path| (path, item.clone(), None))
.collect()
});
match result {
- Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)),
+ Ok(()) => ExpandResult::Ready(vec![item]),
Err(Indeterminate) => ExpandResult::Retry(item),
}
}
use crate::traits::*;
use rustc_data_structures::graph::dominators::Dominators;
use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::vec::IndexVec;
use rustc_middle::mir::traversal;
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{self, Location, TerminatorKind};
fx: &FunctionCx<'a, 'tcx, Bx>,
) -> BitSet<mir::Local> {
let mir = fx.mir;
- let mut analyzer = LocalAnalyzer::new(fx);
+ let dominators = mir.dominators();
+ let locals = mir
+ .local_decls
+ .iter()
+ .map(|decl| {
+ let ty = fx.monomorphize(decl.ty);
+ let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
+ if layout.is_zst() {
+ LocalKind::ZST
+ } else if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) {
+ LocalKind::Unused
+ } else {
+ LocalKind::Memory
+ }
+ })
+ .collect();
+
+ let mut analyzer = LocalAnalyzer { fx, dominators, locals };
+
+ // Arguments get assigned to by means of the function being called
+ for arg in mir.args_iter() {
+ analyzer.assign(arg, mir::START_BLOCK.start_location());
+ }
// If there exists a local definition that dominates all uses of that local,
// the definition should be visited first. Traverse blocks in preorder which
analyzer.visit_basic_block_data(bb, data);
}
- for (local, decl) in mir.local_decls.iter_enumerated() {
- let ty = fx.monomorphize(decl.ty);
- debug!("local {:?} has type `{}`", local, ty);
- let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
- if fx.cx.is_backend_immediate(layout) {
- // These sorts of types are immediates that we can store
- // in an Value without an alloca.
- } else if fx.cx.is_backend_scalar_pair(layout) {
- // We allow pairs and uses of any of their 2 fields.
- } else {
- // These sorts of types require an alloca. Note that
- // is_llvm_immediate() may *still* be true, particularly
- // for newtypes, but we currently force some types
- // (e.g., structs) into an alloca unconditionally, just so
- // that we don't have to deal with having two pathways
- // (gep vs extractvalue etc).
- analyzer.not_ssa(local);
+ let mut non_ssa_locals = BitSet::new_empty(analyzer.locals.len());
+ for (local, kind) in analyzer.locals.iter_enumerated() {
+ if matches!(kind, LocalKind::Memory) {
+ non_ssa_locals.insert(local);
}
}
- analyzer.non_ssa_locals
+ non_ssa_locals
+}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+enum LocalKind {
+ ZST,
+ /// A local that requires an alloca.
+ Memory,
+ /// A scalar or a scalar pair local that is neither defined nor used.
+ Unused,
+ /// A scalar or a scalar pair local with a single definition that dominates all uses.
+ SSA(mir::Location),
}
struct LocalAnalyzer<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
fx: &'mir FunctionCx<'a, 'tcx, Bx>,
dominators: Dominators<mir::BasicBlock>,
- non_ssa_locals: BitSet<mir::Local>,
- // The location of the first visited direct assignment to each
- // local, or an invalid location (out of bounds `block` index).
- first_assignment: IndexVec<mir::Local, Location>,
+ locals: IndexVec<mir::Local, LocalKind>,
}
impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
- fn new(fx: &'mir FunctionCx<'a, 'tcx, Bx>) -> Self {
- let invalid_location = mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location();
- let dominators = fx.mir.dominators();
- let mut analyzer = LocalAnalyzer {
- fx,
- dominators,
- non_ssa_locals: BitSet::new_empty(fx.mir.local_decls.len()),
- first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls),
- };
-
- // Arguments get assigned to by means of the function being called
- for arg in fx.mir.args_iter() {
- analyzer.first_assignment[arg] = mir::START_BLOCK.start_location();
- }
-
- analyzer
- }
-
- fn first_assignment(&self, local: mir::Local) -> Option<Location> {
- let location = self.first_assignment[local];
- if location.block.index() < self.fx.mir.basic_blocks().len() {
- Some(location)
- } else {
- None
- }
- }
-
- fn not_ssa(&mut self, local: mir::Local) {
- debug!("marking {:?} as non-SSA", local);
- self.non_ssa_locals.insert(local);
- }
-
fn assign(&mut self, local: mir::Local, location: Location) {
- if self.first_assignment(local).is_some() {
- self.not_ssa(local);
- } else {
- self.first_assignment[local] = location;
+ let kind = &mut self.locals[local];
+ match *kind {
+ LocalKind::ZST => {}
+ LocalKind::Memory => {}
+ LocalKind::Unused => {
+ *kind = LocalKind::SSA(location);
+ }
+ LocalKind::SSA(_) => {
+ *kind = LocalKind::Memory;
+ }
}
}
) {
debug!("visit_assign(place={:?}, rvalue={:?})", place, rvalue);
- if let Some(index) = place.as_local() {
- self.assign(index, location);
- let decl_span = self.fx.mir.local_decls[index].source_info.span;
- if !self.fx.rvalue_creates_operand(rvalue, decl_span) {
- self.not_ssa(index);
+ if let Some(local) = place.as_local() {
+ self.assign(local, location);
+ if self.locals[local] != LocalKind::Memory {
+ let decl_span = self.fx.mir.local_decls[local].source_info.span;
+ if !self.fx.rvalue_creates_operand(rvalue, decl_span) {
+ self.locals[local] = LocalKind::Memory;
+ }
}
} else {
self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location);
PlaceContext::NonMutatingUse(
NonMutatingUseContext::Copy | NonMutatingUseContext::Move,
- ) => {
+ ) => match &mut self.locals[local] {
+ LocalKind::ZST => {}
+ LocalKind::Memory => {}
+ LocalKind::SSA(def) if def.dominates(location, &self.dominators) => {}
// Reads from uninitialized variables (e.g., in dead code, after
// optimizations) require locals to be in (uninitialized) memory.
// N.B., there can be uninitialized reads of a local visited after
// an assignment to that local, if they happen on disjoint paths.
- let ssa_read = match self.first_assignment(local) {
- Some(assignment_location) => {
- assignment_location.dominates(location, &self.dominators)
- }
- None => {
- debug!("No first assignment found for {:?}", local);
- // We have not seen any assignment to the local yet,
- // but before marking not_ssa, check if it is a ZST,
- // in which case we don't need to initialize the local.
- let ty = self.fx.mir.local_decls[local].ty;
- let ty = self.fx.monomorphize(ty);
-
- let is_zst = self.fx.cx.layout_of(ty).is_zst();
- debug!("is_zst: {}", is_zst);
- is_zst
- }
- };
- if !ssa_read {
- self.not_ssa(local);
+ kind @ (LocalKind::Unused | LocalKind::SSA(_)) => {
+ *kind = LocalKind::Memory;
}
- }
+ },
PlaceContext::MutatingUse(
MutatingUseContext::Store
| NonMutatingUseContext::AddressOf
| NonMutatingUseContext::Projection,
) => {
- self.not_ssa(local);
+ self.locals[local] = LocalKind::Memory;
}
PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
- let ty = self.fx.mir.local_decls[local].ty;
- let ty = self.fx.monomorphize(ty);
-
- // Only need the place if we're actually dropping it.
- if self.fx.cx.type_needs_drop(ty) {
- self.not_ssa(local);
+ let kind = &mut self.locals[local];
+ if *kind != LocalKind::Memory {
+ let ty = self.fx.mir.local_decls[local].ty;
+ let ty = self.fx.monomorphize(ty);
+ if self.fx.cx.type_needs_drop(ty) {
+ // Only need the place if we're actually dropping it.
+ *kind = LocalKind::Memory;
+ }
}
}
}
/// Error type that denotes indeterminacy.
pub struct Indeterminate;
-pub type DeriveResolutions = Vec<(ast::Path, Option<Lrc<SyntaxExtension>>)>;
+pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExtension>>)>;
pub trait ResolverExpand {
fn next_node_id(&mut self) -> NodeId;
pub fn arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm {
ast::Arm {
- attrs: vec![],
+ attrs: AttrVec::new(),
pat,
guard: None,
body: expr,
pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
let orig_expansion_data = self.cx.current_expansion.clone();
let orig_force_mode = self.cx.force_mode;
- self.cx.current_expansion.depth = 0;
// Collect all macro invocations and replace them with placeholders.
let (mut fragment_with_placeholders, mut invocations) =
};
let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
+ let depth = depth - orig_expansion_data.depth;
self.cx.current_expansion = invoc.expansion_data.clone();
self.cx.force_mode = force;
.resolver
.take_derive_resolutions(expn_id)
.map(|derives| {
- enum AnnotatableRef<'a> {
- Item(&'a P<ast::Item>),
- Stmt(&'a ast::Stmt),
- }
- let item = match &fragment {
- AstFragment::Items(items) => match &items[..] {
- [item] => AnnotatableRef::Item(item),
- _ => unreachable!(),
- },
- AstFragment::Stmts(stmts) => match &stmts[..] {
- [stmt] => AnnotatableRef::Stmt(stmt),
- _ => unreachable!(),
- },
- _ => unreachable!(),
- };
-
derive_invocations.reserve(derives.len());
derives
.into_iter()
- .map(|(path, _exts)| {
+ .map(|(path, item, _exts)| {
// FIXME: Consider using the derive resolutions (`_exts`)
// instead of enqueuing the derives to be resolved again later.
let expn_id = ExpnId::fresh(None);
derive_invocations.push((
Invocation {
- kind: InvocationKind::Derive {
- path,
- item: match item {
- AnnotatableRef::Item(item) => {
- Annotatable::Item(item.clone())
- }
- AnnotatableRef::Stmt(stmt) => {
- Annotatable::Stmt(P(stmt.clone()))
- }
- },
- },
+ kind: InvocationKind::Derive { path, item },
fragment_kind,
expansion_data: ExpansionData {
id: expn_id,
pub enum BlockCheckMode {
DefaultBlock,
UnsafeBlock(UnsafeSource),
- PushUnsafeBlock(UnsafeSource),
- PopUnsafeBlock(UnsafeSource),
}
#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
) {
match blk.rules {
hir::BlockCheckMode::UnsafeBlock(..) => self.word_space("unsafe"),
- hir::BlockCheckMode::PushUnsafeBlock(..) => self.word_space("push_unsafe"),
- hir::BlockCheckMode::PopUnsafeBlock(..) => self.word_space("pop_unsafe"),
hir::BlockCheckMode::DefaultBlock => (),
}
self.maybe_print_comment(blk.span.lo());
tracked!(no_codegen, true);
tracked!(no_generate_arange_section, true);
tracked!(no_link, true);
- tracked!(no_profiler_runtime, true);
tracked!(osx_rpath_install_name, true);
tracked!(panic_abort_tests, true);
tracked!(plt, Some(true));
tracked!(print_fuel, Some("abc".to_string()));
tracked!(profile, true);
tracked!(profile_emit, Some(PathBuf::from("abc")));
+ tracked!(profiler_runtime, None);
tracked!(relax_elf_relocations, Some(true));
tracked!(relro_level, Some(RelroLevel::Full));
tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
| hir::BinOpKind::Shl
| hir::BinOpKind::Shr => Some("bitwise operation"),
},
+ hir::ExprKind::AddrOf(..) => Some("borrow"),
hir::ExprKind::Unary(..) => Some("unary operation"),
_ => None,
};
pub OR_PATTERNS_BACK_COMPAT,
Allow,
"detects usage of old versions of or-patterns",
+ @future_incompatible = FutureIncompatibleInfo {
+ reference: "issue #84869 <https://github.com/rust-lang/rust/issues/84869>",
+ edition: Some(Edition::Edition2021),
+ };
}
quote! {}
} else if let Some(project) = attrs.project {
quote! {
- &#bi.#project.hash_stable(__hcx, __hasher);
+ (&#bi.#project).hash_stable(__hcx, __hasher);
}
} else {
quote! {
quote! {}
} else if let Some(project) = attrs.project {
quote! {
- &#bi.#project.hash_stable(__hcx, __hasher);
+ (&#bi.#project).hash_stable(__hcx, __hasher);
}
} else {
quote! {
}
fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
- if (self.sess.instrument_coverage()
- || self.sess.opts.debugging_opts.profile
- || self.sess.opts.cg.profile_generate.enabled())
- && !self.sess.opts.debugging_opts.no_profiler_runtime
+ let profiler_runtime = &self.sess.opts.debugging_opts.profiler_runtime;
+
+ if !(profiler_runtime.is_some()
+ && (self.sess.instrument_coverage()
+ || self.sess.opts.debugging_opts.profile
+ || self.sess.opts.cg.profile_generate.enabled()))
{
- info!("loading profiler");
+ return;
+ }
- if self.sess.contains_name(&krate.attrs, sym::no_core) {
- self.sess.err(
- "`profiler_builtins` crate (required by compiler options) \
- is not compatible with crate attribute `#![no_core]`",
- );
- }
+ info!("loading profiler");
+
+ let name = Symbol::intern(profiler_runtime.as_ref().unwrap());
+ if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
+ self.sess.err(
+ "`profiler_builtins` crate (required by compiler options) \
+ is not compatible with crate attribute `#![no_core]`",
+ );
+ }
- let name = sym::profiler_builtins;
- let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
- let data = self.cstore.get_crate_data(cnum);
+ let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
+ let data = self.cstore.get_crate_data(cnum);
- // Sanity check the loaded crate to ensure it is indeed a profiler runtime
- if !data.is_profiler_runtime() {
- self.sess.err("the crate `profiler_builtins` is not a profiler runtime");
- }
+ // Sanity check the loaded crate to ensure it is indeed a profiler runtime
+ if !data.is_profiler_runtime() {
+ self.sess.err(&format!("the crate `{}` is not a profiler runtime", name));
}
}
if sess.is_nightly_build() && std::env::var("CARGO").is_ok() {
err.help("consider building the standard library from source with `cargo build -Zbuild-std`");
}
- } else if crate_name == sym::profiler_builtins {
+ } else if Some(crate_name)
+ == sess.opts.debugging_opts.profiler_runtime.as_deref().map(Symbol::intern)
+ {
err.note(&"the compiler may have been built without the profiler runtime");
}
err.span_label(span, "can't find crate");
use InterpError::*;
match *self {
MachineStop(ref err) => err.is_hard_err(),
+ InterpError::UndefinedBehavior(_) => true,
_ => false,
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum Safety {
Safe,
- /// Unsafe because of a PushUnsafeBlock
- BuiltinUnsafe,
/// Unsafe because of an unsafe fn
FnUnsafe,
/// Unsafe because of an `unsafe` block
pub enum BlockSafety {
Safe,
ExplicitUnsafe(hir::HirId),
- PushUnsafe,
- PopUnsafe,
}
#[derive(Debug, HashStable)]
/// (including late-bound regions) are replaced with free
/// equivalents. This table is not used in codegen (since regions
/// are erased there) and hence is not serialized to metadata.
+ ///
+ /// This table also contains the "revealed" values for any `impl Trait`
+ /// that appear in the signature and whose values are being inferred
+ /// by this function.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// fn foo(x: &u32) -> impl Debug { *x }
+ /// ```
+ ///
+ /// The function signature here would be:
+ ///
+ /// ```
+ /// for<'a> fn(&'a u32) -> Foo
+ /// ```
+ ///
+ /// where `Foo` is an opaque type created for this function.
+ ///
+ ///
+ /// The *liberated* form of this would be
+ ///
+ /// ```
+ /// fn(&'a u32) -> u32
+ /// ```
+ ///
+ /// Note that `'a` is not bound (it would be an `ReFree`) and
+ /// that the `Foo` opaque type is replaced by its hidden type.
liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
/// For each FRU expression, record the normalized types of the fields
// SIMD vector types.
ty::Adt(def, substs) if def.repr.simd() => {
+ if !def.is_struct() {
+ // Should have yielded E0517 by now.
+ tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ "#[repr(simd)] was applied to an ADT that is not a struct",
+ );
+ return Err(LayoutError::Unknown(ty));
+ }
+
// Supported SIMD vectors are homogeneous ADTs with at least one field:
//
// * #[repr(simd)] struct S(T, T, T, T);
Ok(())
}
+ /// Equates a type `anon_ty` that may contain opaque types whose
+ /// values are to be inferred by the MIR with def-id `anon_owner_def_id`.
+ ///
+ /// The type `revealed_ty` contains the same type as `anon_ty`, but with the
+ /// hidden types for impl traits revealed.
+ ///
+ /// # Example
+ ///
+ /// Consider a piece of code like
+ ///
+ /// ```rust
+ /// type Foo<U> = impl Debug;
+ ///
+ /// fn foo<T: Debug>(t: T) -> Box<Foo<T>> {
+ /// Box::new((t, 22_u32))
+ /// }
+ /// ```
+ ///
+ /// Here, the function signature would be something like
+ /// `fn(T) -> Box<impl Debug>`. The MIR return slot would have
+ /// the type with the opaque type revealed, so `Box<(T, u32)>`.
+ ///
+ /// In terms of our function parameters:
+ ///
+ /// * `anon_ty` would be `Box<Foo<T>>` where `Foo<T>` is an opaque type
+ /// scoped to this function (note that it is parameterized by the
+ /// generics of `foo`). Note that `anon_ty` is not just the opaque type,
+ /// but the entire return type (which may contain opaque types within it).
+ /// * `revealed_ty` would be `Box<(T, u32)>`
+ /// * `anon_owner_def_id` would be the def-id of `foo`
fn eq_opaque_type_and_type(
&mut self,
revealed_ty: Ty<'tcx>,
let tcx = infcx.tcx;
let param_env = self.param_env;
let body = self.body;
+
+ // the "concrete opaque types" maps
let concrete_opaque_types = &tcx.typeck(anon_owner_def_id).concrete_opaque_types;
let mut opaque_type_values = VecMap::new();
let mut obligations = ObligationAccumulator::default();
let dummy_body_id = hir::CRATE_HIR_ID;
+
+ // Replace the opaque types defined by this function with
+ // inference variables, creating a map. In our example above,
+ // this would transform the type `Box<Foo<T>>` (where `Foo` is an opaque type)
+ // to `Box<?T>`, returning an `opaque_type_map` mapping `{Foo<T> -> ?T}`.
+ // (Note that the key of the map is both the def-id of `Foo` along with
+ // any generic parameters.)
let (output_ty, opaque_type_map) =
obligations.add(infcx.instantiate_opaque_types(
anon_owner_def_id,
revealed_ty={:?}",
output_ty, opaque_type_map, revealed_ty
);
+
// Make sure that the inferred types are well-formed. I'm
// not entirely sure this is needed (the HIR type check
// didn't do this) but it seems sensible to prevent opaque
.eq(output_ty, revealed_ty)?,
);
+ // For each opaque type `Foo<T>` inferred by this value, we want to equate
+ // the inference variable `?T` with the revealed type that was computed
+ // earlier by type check.
for &(opaque_type_key, opaque_decl) in &opaque_type_map {
let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty);
let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
false
};
+ // The revealed type computed by the earlier phase of type check.
+ // In our example, this would be `(U, u32)`. Note that this references
+ // the type parameter `U` from the definition of `Foo`.
let concrete_ty = match concrete_opaque_types
.get_by(|(key, _)| key.def_id == opaque_type_key.def_id)
{
Some(concrete_ty) => concrete_ty,
};
debug!("concrete_ty = {:?}", concrete_ty);
+
+ // Apply the substitution, in this case `[U -> T]`, so that the
+ // concrete type becomes `Foo<(T, u32)>`
let subst_opaque_defn_ty = concrete_ty.subst(tcx, opaque_type_key.substs);
+
+ // "Renumber" this, meaning that we replace all the regions
+ // with fresh inference variables. Not relevant to our example.
let renumbered_opaque_defn_ty =
renumber::renumber_regions(infcx, subst_opaque_defn_ty);
);
if !concrete_is_opaque {
- // Equate concrete_ty (an inference variable) with
- // the renumbered type from typeck.
+ // Equate the instantiated opaque type `opaque_decl.concrete_ty` (`?T`,
+ // in our example) with the renumbered version that we took from
+ // the type check results (`Foo<(T, u32)>`).
obligations.add(
infcx
.at(&ObligationCause::dummy(), param_env)
}
false
}
- Safety::BuiltinUnsafe => true,
Safety::ExplicitUnsafe(hir_id) => {
// mark unsafe block as used if there are any unsafe operations inside
if !violations.is_empty() {
let mut eval_to_int = |op| {
// This can be `None` if the lhs wasn't const propagated and we just
// triggered the assert on the value of the rhs.
- match self.eval_operand(op, source_info) {
- Some(op) => DbgVal::Val(
- self.ecx.read_immediate(&op).unwrap().to_const_int(),
- ),
- None => DbgVal::Underscore,
- }
+ self.eval_operand(op, source_info).map_or(DbgVal::Underscore, |op| {
+ DbgVal::Val(self.ecx.read_immediate(&op).unwrap().to_const_int())
+ })
};
let msg = match msg {
AssertKind::DivisionByZero(op) => {
// First we build all the statements in the block.
let mut let_scope_stack = Vec::with_capacity(8);
let outer_source_scope = this.source_scope;
- let outer_push_unsafe_count = this.push_unsafe_count;
- let outer_unpushed_unsafe = this.unpushed_unsafe;
+ let outer_in_scope_unsafe = this.in_scope_unsafe;
this.update_source_scope_for_safety_mode(span, safety_mode);
let source_info = this.source_info(span);
}
// Restore the original source scope.
this.source_scope = outer_source_scope;
- this.push_unsafe_count = outer_push_unsafe_count;
- this.unpushed_unsafe = outer_unpushed_unsafe;
+ this.in_scope_unsafe = outer_in_scope_unsafe;
block.unit()
}
let new_unsafety = match safety_mode {
BlockSafety::Safe => None,
BlockSafety::ExplicitUnsafe(hir_id) => {
- assert_eq!(self.push_unsafe_count, 0);
- match self.unpushed_unsafe {
+ match self.in_scope_unsafe {
Safety::Safe => {}
// no longer treat `unsafe fn`s as `unsafe` contexts (see RFC #2585)
Safety::FnUnsafe
!= Level::Allow => {}
_ => return,
}
- self.unpushed_unsafe = Safety::ExplicitUnsafe(hir_id);
+ self.in_scope_unsafe = Safety::ExplicitUnsafe(hir_id);
Some(Safety::ExplicitUnsafe(hir_id))
}
- BlockSafety::PushUnsafe => {
- self.push_unsafe_count += 1;
- Some(Safety::BuiltinUnsafe)
- }
- BlockSafety::PopUnsafe => {
- self.push_unsafe_count = self
- .push_unsafe_count
- .checked_sub(1)
- .unwrap_or_else(|| span_bug!(span, "unsafe count underflow"));
- if self.push_unsafe_count == 0 { Some(self.unpushed_unsafe) } else { None }
- }
};
if let Some(unsafety) = new_unsafety {
/// `{ STMTS; EXPR1 } + EXPR2`.
block_context: BlockContext,
- /// The current unsafe block in scope, even if it is hidden by
- /// a `PushUnsafeBlock`.
- unpushed_unsafe: Safety,
-
- /// The number of `push_unsafe_block` levels in scope.
- push_unsafe_count: usize,
+ /// The current unsafe block in scope
+ in_scope_unsafe: Safety,
/// The vector of all scopes that we have created thus far;
/// we track this for debuginfo later.
source_scopes: IndexVec::new(),
source_scope: OUTERMOST_SOURCE_SCOPE,
guard_context: vec![],
- push_unsafe_count: 0,
- unpushed_unsafe: safety,
+ in_scope_unsafe: safety,
local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1),
canonical_user_type_annotations: IndexVec::new(),
upvar_mutbls: vec![],
safety_mode: match block.rules {
hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe,
hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(block.hir_id),
- hir::BlockCheckMode::PushUnsafeBlock(..) => BlockSafety::PushUnsafe,
- hir::BlockCheckMode::PopUnsafeBlock(..) => BlockSafety::PopUnsafe,
},
}
}
_ => {
let pattern_error = match res {
Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span),
+ Res::Def(DefKind::Static, _) => PatternError::StaticInPattern(span),
_ => PatternError::NonConstPath(span),
};
self.errors.push(pattern_error);
let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) {
Ok(Some(i)) => i,
Ok(None) => {
- self.errors.push(if is_associated_const {
- PatternError::AssocConstInPattern(span)
- } else {
- PatternError::StaticInPattern(span)
- });
+ // It should be assoc consts if there's no error but we cannot resolve it.
+ debug_assert!(is_associated_const);
+
+ self.errors.push(PatternError::AssocConstInPattern(span));
return pat_from_kind(PatKind::Wild);
}
walk_arm(self, arm);
}
+ fn visit_pat(&mut self, pat: &Pat<'tcx>) {
+ walk_pat(self, pat);
+ }
+
fn visit_const(&mut self, _cnst: &'tcx Const<'tcx>) {}
}
initializer,
remainder_scope: _,
init_scope: _,
- pattern: _,
+ ref pattern,
lint_level: _,
} => {
if let Some(init) = initializer {
visitor.visit_expr(&visitor.thir()[init]);
}
+ visitor.visit_pat(pattern);
}
}
}
pub fn walk_arm<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, arm: &Arm<'tcx>) {
match arm.guard {
Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
- Some(Guard::IfLet(ref _pat, expr)) => {
+ Some(Guard::IfLet(ref pat, expr)) => {
+ visitor.visit_pat(pat);
visitor.visit_expr(&visitor.thir()[expr]);
}
None => {}
}
+ visitor.visit_pat(&arm.pattern);
visitor.visit_expr(&visitor.thir()[arm.body]);
}
+
+pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'tcx>) {
+ use PatKind::*;
+ match pat.kind.as_ref() {
+ AscribeUserType { subpattern, ascription: _ }
+ | Deref { subpattern }
+ | Binding {
+ subpattern: Some(subpattern),
+ mutability: _,
+ mode: _,
+ var: _,
+ ty: _,
+ is_primary: _,
+ name: _,
+ } => visitor.visit_pat(&subpattern),
+ Binding { .. } | Wild => {}
+ Variant { subpatterns, adt_def: _, substs: _, variant_index: _ } | Leaf { subpatterns } => {
+ for subpattern in subpatterns {
+ visitor.visit_pat(&subpattern.pattern);
+ }
+ }
+ Constant { value } => visitor.visit_const(value),
+ Range(range) => {
+ visitor.visit_const(range.lo);
+ visitor.visit_const(range.hi);
+ }
+ Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => {
+ for subpattern in prefix {
+ visitor.visit_pat(&subpattern);
+ }
+ if let Some(pat) = slice {
+ visitor.visit_pat(pat);
+ }
+ for subpattern in suffix {
+ visitor.visit_pat(&subpattern);
+ }
+ }
+ Or { pats } => {
+ for pat in pats {
+ visitor.visit_pat(&pat);
+ }
+ }
+ };
+}
let span = body.span;
return Ok((
ast::Arm {
- attrs,
+ attrs: attrs.into(),
pat,
guard,
body,
Ok((
ast::Arm {
- attrs,
+ attrs: attrs.into(),
pat,
guard,
body: expr,
ident,
vis,
id: DUMMY_NODE_ID,
- attrs: variant_attrs,
+ attrs: variant_attrs.into(),
data: struct_def,
disr_expr,
span: vlo.to(this.prev_token.span),
ident: None,
id: DUMMY_NODE_ID,
ty,
- attrs,
+ attrs: attrs.into(),
is_placeholder: false,
},
TrailingToken::MaybeComma,
vis,
id: DUMMY_NODE_ID,
ty,
- attrs,
+ attrs: attrs.into(),
is_placeholder: false,
})
}
has_derive_copy: false,
});
let parent_scope = self.invocation_parent_scopes[&expn_id];
- for (i, (path, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
+ for (i, (path, _, opt_ext)) in entry.resolutions.iter_mut().enumerate() {
if opt_ext.is_none() {
*opt_ext = Some(
match self.resolve_macro_path(
}
}
+ /// If the Json value is an Object, deletes the value associated with the
+ /// provided key from the Object and returns it. Otherwise, returns None.
+ pub fn remove_key(&mut self, key: &str) -> Option<Json> {
+ match *self {
+ Json::Object(ref mut map) => map.remove(key),
+ _ => None,
+ }
+ }
+
/// Attempts to get a nested Json Object for each key in `keys`.
/// If any key is found not to exist, `find_path` will return `None`.
/// Otherwise, it will return the Json value associated with the final key.
use rustc_data_structures::impl_stable_hash_via_hash;
use rustc_target::abi::{Align, TargetDataLayout};
-use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple};
+use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple, TargetWarnings};
use rustc_serialize::json;
target_override: Option<Target>,
sysroot: &PathBuf,
) -> Target {
- let target_result =
- target_override.map_or_else(|| Target::search(&opts.target_triple, sysroot), Ok);
- let target = target_result.unwrap_or_else(|e| {
+ let target_result = target_override.map_or_else(
+ || Target::search(&opts.target_triple, sysroot),
+ |t| Ok((t, TargetWarnings::empty())),
+ );
+ let (target, target_warnings) = target_result.unwrap_or_else(|e| {
early_error(
opts.error_format,
&format!(
),
)
});
+ for warning in target_warnings.warning_messages() {
+ early_warn(opts.error_format, &warning)
+ }
if !matches!(target.pointer_width, 16 | 32 | 64) {
early_error(
"compile without linking"),
no_parallel_llvm: bool = (false, parse_no_flag, [UNTRACKED],
"run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
- no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED],
- "prevent automatic injection of the profiler_builtins crate"),
normalize_docs: bool = (false, parse_bool, [TRACKED],
"normalize associated items in rustdoc when generating documentation"),
osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
profile_emit: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"file path to emit profiling data at runtime when using 'profile' \
(default based on relative source path)"),
+ profiler_runtime: Option<String> = (Some(String::from("profiler_builtins")), parse_opt_string, [TRACKED],
+ "name of the profiler runtime crate to automatically inject, or None to disable"),
query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
"enable queries of the dependency graph for regression testing (default: no)"),
query_stats: bool = (false, parse_bool, [UNTRACKED],
let target_cfg = config::build_target_config(&sopts, target_override, &sysroot);
let host_triple = TargetTriple::from_triple(config::host_triple());
- let host = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
+ let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
early_error(sopts.error_format, &format!("Error loading host specification: {}", e))
});
+ for warning in target_warnings.warning_messages() {
+ early_warn(sopts.error_format, &warning)
+ }
let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
let hash_kind = sopts.debugging_opts.src_hash_algorithm.unwrap_or_else(|| {
pub mod asm;
pub mod spec;
+#[cfg(test)]
+mod tests;
+
/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
/// instead of implementing everything in `rustc_middle`.
("bpfel-unknown-none", bpfel_unknown_none),
}
+/// Warnings encountered when parsing the target `json`.
+///
+/// Includes fields that weren't recognized and fields that don't have the expected type.
+#[derive(Debug, PartialEq)]
+pub struct TargetWarnings {
+ unused_fields: Vec<String>,
+ incorrect_type: Vec<String>,
+}
+
+impl TargetWarnings {
+ pub fn empty() -> Self {
+ Self { unused_fields: Vec::new(), incorrect_type: Vec::new() }
+ }
+
+ pub fn warning_messages(&self) -> Vec<String> {
+ let mut warnings = vec![];
+ if !self.unused_fields.is_empty() {
+ warnings.push(format!(
+ "target json file contains unused fields: {}",
+ self.unused_fields.join(", ")
+ ));
+ }
+ if !self.incorrect_type.is_empty() {
+ warnings.push(format!(
+ "target json file contains fields whose value doesn't have the correct json type: {}",
+ self.incorrect_type.join(", ")
+ ));
+ }
+ warnings
+ }
+}
+
/// Everything `rustc` knows about how to compile for a specific target.
///
/// Every field here must be specified, and has no default value.
}
/// Loads a target descriptor from a JSON object.
- pub fn from_json(obj: Json) -> Result<Target, String> {
+ pub fn from_json(mut obj: Json) -> Result<(Target, TargetWarnings), String> {
// While ugly, this code must remain this way to retain
// compatibility with existing JSON fields and the internal
// expected naming of the Target and TargetOptions structs.
// are round-tripped through this code to catch cases where
// the JSON parser is not updated to match the structs.
- let get_req_field = |name: &str| {
- obj.find(name)
- .and_then(Json::as_string)
- .map(str::to_string)
+ let mut get_req_field = |name: &str| {
+ obj.remove_key(name)
+ .and_then(|j| Json::as_string(&j).map(str::to_string))
.ok_or_else(|| format!("Field {} in target specification is required", name))
};
options: Default::default(),
};
+ let mut incorrect_type = vec![];
+
macro_rules! key {
($key_name:ident) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- if let Some(s) = obj.find(&name).and_then(Json::as_string) {
- base.$key_name = s.to_string();
+ if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_string(&j).map(str::to_string)) {
+ base.$key_name = s;
}
} );
($key_name:ident = $json_name:expr) => ( {
let name = $json_name;
- if let Some(s) = obj.find(&name).and_then(Json::as_string) {
- base.$key_name = s.to_string();
+ if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_string(&j).map(str::to_string)) {
+ base.$key_name = s;
}
} );
($key_name:ident, bool) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- if let Some(s) = obj.find(&name).and_then(Json::as_boolean) {
+ if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_boolean(&j)) {
base.$key_name = s;
}
} );
($key_name:ident, Option<u32>) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- if let Some(s) = obj.find(&name).and_then(Json::as_u64) {
+ if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
if s < 1 || s > 5 {
return Err("Not a valid DWARF version number".to_string());
}
} );
($key_name:ident, Option<u64>) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- if let Some(s) = obj.find(&name).and_then(Json::as_u64) {
+ if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
base.$key_name = Some(s);
}
} );
($key_name:ident, MergeFunctions) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+ obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
match s.parse::<MergeFunctions>() {
Ok(mergefunc) => base.$key_name = mergefunc,
_ => return Some(Err(format!("'{}' is not a valid value for \
} );
($key_name:ident, RelocModel) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+ obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
match s.parse::<RelocModel>() {
Ok(relocation_model) => base.$key_name = relocation_model,
_ => return Some(Err(format!("'{}' is not a valid relocation model. \
} );
($key_name:ident, CodeModel) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+ obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
match s.parse::<CodeModel>() {
Ok(code_model) => base.$key_name = Some(code_model),
_ => return Some(Err(format!("'{}' is not a valid code model. \
} );
($key_name:ident, TlsModel) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+ obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
match s.parse::<TlsModel>() {
Ok(tls_model) => base.$key_name = tls_model,
_ => return Some(Err(format!("'{}' is not a valid TLS model. \
} );
($key_name:ident, PanicStrategy) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+ obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
match s {
"unwind" => base.$key_name = PanicStrategy::Unwind,
"abort" => base.$key_name = PanicStrategy::Abort,
} );
($key_name:ident, RelroLevel) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+ obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
match s.parse::<RelroLevel>() {
Ok(level) => base.$key_name = level,
_ => return Some(Err(format!("'{}' is not a valid value for \
} );
($key_name:ident, SplitDebuginfo) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+ obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
match s.parse::<SplitDebuginfo>() {
Ok(level) => base.$key_name = level,
_ => return Some(Err(format!("'{}' is not a valid value for \
} );
($key_name:ident, list) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- if let Some(v) = obj.find(&name).and_then(Json::as_array) {
- base.$key_name = v.iter()
- .map(|a| a.as_string().unwrap().to_string())
- .collect();
+ if let Some(j) = obj.remove_key(&name){
+ if let Some(v) = Json::as_array(&j) {
+ base.$key_name = v.iter()
+ .map(|a| a.as_string().unwrap().to_string())
+ .collect();
+ } else {
+ incorrect_type.push(name)
+ }
}
} );
($key_name:ident, opt_list) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- if let Some(v) = obj.find(&name).and_then(Json::as_array) {
- base.$key_name = Some(v.iter()
- .map(|a| a.as_string().unwrap().to_string())
- .collect());
+ if let Some(j) = obj.remove_key(&name) {
+ if let Some(v) = Json::as_array(&j) {
+ base.$key_name = Some(v.iter()
+ .map(|a| a.as_string().unwrap().to_string())
+ .collect());
+ } else {
+ incorrect_type.push(name)
+ }
}
} );
($key_name:ident, optional) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- if let Some(o) = obj.find(&name[..]) {
+ if let Some(o) = obj.remove_key(&name[..]) {
base.$key_name = o
.as_string()
.map(|s| s.to_string() );
} );
($key_name:ident, LldFlavor) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+ obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
if let Some(flavor) = LldFlavor::from_str(&s) {
base.$key_name = flavor;
} else {
} );
($key_name:ident, LinkerFlavor) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+ obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
match LinkerFlavor::from_str(s) {
Some(linker_flavor) => base.$key_name = linker_flavor,
_ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \
} );
($key_name:ident, StackProbeType) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| match StackProbeType::from_json(o) {
+ obj.remove_key(&name[..]).and_then(|o| match StackProbeType::from_json(&o) {
Ok(v) => {
base.$key_name = v;
Some(Ok(()))
} );
($key_name:ident, SanitizerSet) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| o.as_array()).and_then(|a| {
- for s in a {
- base.$key_name |= match s.as_string() {
- Some("address") => SanitizerSet::ADDRESS,
- Some("leak") => SanitizerSet::LEAK,
- Some("memory") => SanitizerSet::MEMORY,
- Some("thread") => SanitizerSet::THREAD,
- Some("hwaddress") => SanitizerSet::HWADDRESS,
- Some(s) => return Some(Err(format!("unknown sanitizer {}", s))),
- _ => return Some(Err(format!("not a string: {:?}", s))),
- };
+ if let Some(o) = obj.remove_key(&name[..]) {
+ if let Some(a) = o.as_array() {
+ for s in a {
+ base.$key_name |= match s.as_string() {
+ Some("address") => SanitizerSet::ADDRESS,
+ Some("leak") => SanitizerSet::LEAK,
+ Some("memory") => SanitizerSet::MEMORY,
+ Some("thread") => SanitizerSet::THREAD,
+ Some("hwaddress") => SanitizerSet::HWADDRESS,
+ Some(s) => return Err(format!("unknown sanitizer {}", s)),
+ _ => return Err(format!("not a string: {:?}", s)),
+ };
+ }
+ } else {
+ incorrect_type.push(name)
}
- Some(Ok(()))
- }).unwrap_or(Ok(()))
+ }
+ Ok::<(), String>(())
} );
($key_name:ident, crt_objects_fallback) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+ obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
match s.parse::<CrtObjectsFallback>() {
Ok(fallback) => base.$key_name = Some(fallback),
_ => return Some(Err(format!("'{}' is not a valid CRT objects fallback. \
} );
($key_name:ident, link_objects) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- if let Some(val) = obj.find(&name[..]) {
+ if let Some(val) = obj.remove_key(&name[..]) {
let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
JSON object with fields per CRT object kind.", name))?;
let mut args = CrtObjects::new();
} );
($key_name:ident, link_args) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- if let Some(val) = obj.find(&name[..]) {
+ if let Some(val) = obj.remove_key(&name[..]) {
let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
JSON object with fields per linker-flavor.", name))?;
let mut args = LinkArgs::new();
} );
($key_name:ident, env) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- if let Some(a) = obj.find(&name[..]).and_then(|o| o.as_array()) {
- for o in a {
- if let Some(s) = o.as_string() {
- let p = s.split('=').collect::<Vec<_>>();
- if p.len() == 2 {
- let k = p[0].to_string();
- let v = p[1].to_string();
- base.$key_name.push((k, v));
+ if let Some(o) = obj.remove_key(&name[..]) {
+ if let Some(a) = o.as_array() {
+ for o in a {
+ if let Some(s) = o.as_string() {
+ let p = s.split('=').collect::<Vec<_>>();
+ if p.len() == 2 {
+ let k = p[0].to_string();
+ let v = p[1].to_string();
+ base.$key_name.push((k, v));
+ }
}
}
+ } else {
+ incorrect_type.push(name)
}
}
} );
($key_name:ident, Option<Abi>) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+ obj.remove_key(&name[..]).and_then(|o| o.as_string().and_then(|s| {
match lookup_abi(s) {
Some(abi) => base.$key_name = Some(abi),
_ => return Some(Err(format!("'{}' is not a valid value for abi", s))),
})).unwrap_or(Ok(()))
} );
($key_name:ident, TargetFamilies) => ( {
- let value = obj.find("target-family");
- if let Some(v) = value.and_then(Json::as_array) {
- base.$key_name = v.iter()
- .map(|a| a.as_string().unwrap().to_string())
- .collect();
- } else if let Some(v) = value.and_then(Json::as_string) {
- base.$key_name = vec![v.to_string()];
+ if let Some(value) = obj.remove_key("target-family") {
+ if let Some(v) = Json::as_array(&value) {
+ base.$key_name = v.iter()
+ .map(|a| a.as_string().unwrap().to_string())
+ .collect();
+ } else if let Some(v) = Json::as_string(&value) {
+ base.$key_name = vec![v.to_string()];
+ }
}
} );
}
- if let Some(s) = obj.find("target-endian").and_then(Json::as_string) {
- base.endian = s.parse()?;
+ if let Some(j) = obj.remove_key("target-endian") {
+ if let Some(s) = Json::as_string(&j) {
+ base.endian = s.parse()?;
+ } else {
+ incorrect_type.push("target-endian".to_string())
+ }
}
+
key!(is_builtin, bool);
key!(c_int_width = "target-c-int-width");
key!(os);
// NB: The old name is deprecated, but support for it is retained for
// compatibility.
for name in ["abi-blacklist", "unsupported-abis"].iter() {
- if let Some(array) = obj.find(name).and_then(Json::as_array) {
- for name in array.iter().filter_map(|abi| abi.as_string()) {
- match lookup_abi(name) {
- Some(abi) => {
- if abi.generic() {
+ if let Some(j) = obj.remove_key(name) {
+ if let Some(array) = Json::as_array(&j) {
+ for name in array.iter().filter_map(|abi| abi.as_string()) {
+ match lookup_abi(name) {
+ Some(abi) => {
+ if abi.generic() {
+ return Err(format!(
+ "The ABI \"{}\" is considered to be supported on all \
+ targets and cannot be marked unsupported",
+ abi
+ ));
+ }
+
+ base.unsupported_abis.push(abi)
+ }
+ None => {
return Err(format!(
- "The ABI \"{}\" is considered to be supported on all \
- targets and cannot be marked unsupported",
- abi
+ "Unknown ABI \"{}\" in target specification",
+ name
));
}
-
- base.unsupported_abis.push(abi)
- }
- None => {
- return Err(format!(
- "Unknown ABI \"{}\" in target specification",
- name
- ));
}
}
}
}
}
- Ok(base)
+ // Each field should have been read using `Json::remove_key` so any keys remaining are unused.
+ let remaining_keys = obj.as_object().ok_or("Expected JSON object for target")?.keys();
+ Ok((
+ base,
+ TargetWarnings { unused_fields: remaining_keys.cloned().collect(), incorrect_type },
+ ))
}
/// Search for a JSON file specifying the given target triple.
///
/// The error string could come from any of the APIs called, including filesystem access and
/// JSON decoding.
- pub fn search(target_triple: &TargetTriple, sysroot: &PathBuf) -> Result<Target, String> {
+ pub fn search(
+ target_triple: &TargetTriple,
+ sysroot: &PathBuf,
+ ) -> Result<(Target, TargetWarnings), String> {
use rustc_serialize::json;
use std::env;
use std::fs;
- fn load_file(path: &Path) -> Result<Target, String> {
+ fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> {
let contents = fs::read(path).map_err(|e| e.to_string())?;
let obj = json::from_reader(&mut &contents[..]).map_err(|e| e.to_string())?;
Target::from_json(obj)
TargetTriple::TargetTriple(ref target_triple) => {
// check if triple is in list of built-in targets
if let Some(t) = load_builtin(target_triple) {
- return Ok(t);
+ return Ok((t, TargetWarnings::empty()));
}
// search for a file named `target_triple`.json in RUST_TARGET_PATH
// Test target self-consistency and JSON encoding/decoding roundtrip.
pub(super) fn test_target(target: Target) {
target.check_consistency();
- assert_eq!(Target::from_json(target.to_json()), Ok(target));
+ assert_eq!(Target::from_json(target.to_json()).map(|(j, _)| j), Ok(target));
}
impl Target {
--- /dev/null
+use crate::spec::Target;
+use rustc_serialize::json::Json;
+use std::str::FromStr;
+
+#[test]
+fn report_unused_fields() {
+ let json = Json::from_str(
+ r#"
+ {
+ "arch": "powerpc64",
+ "data-layout": "e-m:e-i64:64-n32:64",
+ "llvm-target": "powerpc64le-elf",
+ "target-pointer-width": "64",
+ "code-mode": "foo"
+ }
+ "#,
+ )
+ .unwrap();
+ let warnings = Target::from_json(json).unwrap().1;
+ assert_eq!(warnings.warning_messages().len(), 1);
+ assert!(warnings.warning_messages().join("\n").contains("code-mode"));
+}
+
+#[test]
+fn report_incorrect_json_type() {
+ let json = Json::from_str(
+ r#"
+ {
+ "arch": "powerpc64",
+ "data-layout": "e-m:e-i64:64-n32:64",
+ "llvm-target": "powerpc64le-elf",
+ "target-pointer-width": "64",
+ "link-env-remove": "foo"
+ }
+ "#,
+ )
+ .unwrap();
+ let warnings = Target::from_json(json).unwrap().1;
+ assert_eq!(warnings.warning_messages().len(), 1);
+ assert!(warnings.warning_messages().join("\n").contains("link-env-remove"));
+}
+
+#[test]
+fn no_warnings_for_valid_target() {
+ let json = Json::from_str(
+ r#"
+ {
+ "arch": "powerpc64",
+ "data-layout": "e-m:e-i64:64-n32:64",
+ "llvm-target": "powerpc64le-elf",
+ "target-pointer-width": "64",
+ "link-env-remove": ["foo"]
+ }
+ "#,
+ )
+ .unwrap();
+ let warnings = Target::from_json(json).unwrap().1;
+ assert_eq!(warnings.warning_messages().len(), 0);
+}
use rustc_data_structures::vec_map::VecMap;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::Node;
use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
use rustc_infer::infer::free_regions::FreeRegionRelations;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
let opaque_parent_hir_id = tcx.hir().get_parent_item(opaque_hir_id);
parent_def_id == tcx.hir().local_def_id(opaque_parent_hir_id)
};
- let (in_definition_scope, origin) = match tcx.hir().find(opaque_hir_id) {
- Some(Node::Item(item)) => match item.kind {
+ let (in_definition_scope, origin) =
+ match tcx.hir().expect_item(opaque_hir_id).kind {
// Anonymous `impl Trait`
hir::ItemKind::OpaqueTy(hir::OpaqueTy {
impl_trait_fn: Some(parent),
origin,
),
_ => (def_scope_default(), hir::OpaqueTyOrigin::Misc),
- },
- _ => bug!(
- "expected item, found {}",
- tcx.hir().node_to_string(opaque_hir_id),
- ),
- };
+ };
if in_definition_scope {
let opaque_type_key =
OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty);
}
-/// Returns `true` if the given intrinsic is unsafe to call or not.
+/// Returns the unsafety of the given intrinsic.
pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
match intrinsic {
sym::abort
pub struct UnsafetyState {
pub def: hir::HirId,
pub unsafety: hir::Unsafety,
- pub unsafe_push_count: u32,
from_fn: bool,
}
impl UnsafetyState {
pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
- UnsafetyState { def, unsafety, unsafe_push_count: 0, from_fn: true }
+ UnsafetyState { def, unsafety, from_fn: true }
}
pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
hir::Unsafety::Unsafe if self.from_fn => self,
unsafety => {
- let (unsafety, def, count) = match blk.rules {
- BlockCheckMode::PushUnsafeBlock(..) => {
- (unsafety, blk.hir_id, self.unsafe_push_count.checked_add(1).unwrap())
- }
- BlockCheckMode::PopUnsafeBlock(..) => {
- (unsafety, blk.hir_id, self.unsafe_push_count.checked_sub(1).unwrap())
- }
- BlockCheckMode::UnsafeBlock(..) => {
- (hir::Unsafety::Unsafe, blk.hir_id, self.unsafe_push_count)
- }
- BlockCheckMode::DefaultBlock => (unsafety, self.def, self.unsafe_push_count),
+ let (unsafety, def) = match blk.rules {
+ BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
+ BlockCheckMode::DefaultBlock => (unsafety, self.def),
};
- UnsafetyState { def, unsafety, unsafe_push_count: count, from_fn: false }
+ UnsafetyState { def, unsafety, from_fn: false }
}
}
}
// Obtain the level of indentation ending in `sugg_sp`.
let indentation = tcx.sess.source_map().span_to_margin(sugg_sp).unwrap_or(0);
// Make the whitespace that will make the suggestion have the right indentation.
- let padding: String = std::iter::repeat(" ").take(indentation).collect();
+ let padding: String = " ".repeat(indentation);
for trait_item in missing_items {
let snippet = suggestion_signature(&trait_item, tcx);
match it.kind {
hir::ItemKind::Fn(..) => tcx.ensure().fn_sig(def_id),
hir::ItemKind::OpaqueTy(..) => tcx.ensure().item_bounds(def_id),
+ hir::ItemKind::Const(ty, ..) | hir::ItemKind::Static(ty, ..) => {
+ // (#75889): Account for `const C: dyn Fn() -> _ = "";`
+ if let hir::TyKind::TraitObject(..) = ty.kind {
+ let mut visitor = PlaceholderHirTyCollector::default();
+ visitor.visit_item(it);
+ placeholder_type_error(tcx, None, &[], visitor.0, false, None);
+ }
+ }
_ => (),
}
}
# On Linux target, if crt-static is not enabled, 'no' means dynamic link to
# `libgcc_s.so`, 'in-tree' means static link to the in-tree build of llvm libunwind
# and 'system' means dynamic link to `libunwind.so`. If crt-static is enabled,
-# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both
-# means static link to the in-tree build of llvm libunwind, and 'system' means
+# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both
+# means static link to the in-tree build of llvm libunwind, and 'system' means
# static link to `libunwind.a` provided by system. Due to the limitation of glibc,
# it must link to `libgcc_eh.a` to get a working output, and this option have no effect.
#llvm-libunwind = 'no'
bench_iteration_mut(b, 100000);
}
-fn bench_first_and_last(b: &mut Bencher, size: i32) {
+fn bench_first_and_last_nightly(b: &mut Bencher, size: i32) {
let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
b.iter(|| {
for _ in 0..10 {
});
}
+fn bench_first_and_last_stable(b: &mut Bencher, size: i32) {
+ let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
+ b.iter(|| {
+ for _ in 0..10 {
+ black_box(map.iter().next());
+ black_box(map.iter().next_back());
+ }
+ });
+}
+
+#[bench]
+pub fn first_and_last_0_nightly(b: &mut Bencher) {
+ bench_first_and_last_nightly(b, 0);
+}
+
+#[bench]
+pub fn first_and_last_0_stable(b: &mut Bencher) {
+ bench_first_and_last_stable(b, 0);
+}
+
+#[bench]
+pub fn first_and_last_100_nightly(b: &mut Bencher) {
+ bench_first_and_last_nightly(b, 100);
+}
+
#[bench]
-pub fn first_and_last_0(b: &mut Bencher) {
- bench_first_and_last(b, 0);
+pub fn first_and_last_100_stable(b: &mut Bencher) {
+ bench_first_and_last_stable(b, 100);
}
#[bench]
-pub fn first_and_last_100(b: &mut Bencher) {
- bench_first_and_last(b, 100);
+pub fn first_and_last_10k_nightly(b: &mut Bencher) {
+ bench_first_and_last_nightly(b, 10_000);
}
#[bench]
-pub fn first_and_last_10k(b: &mut Bencher) {
- bench_first_and_last(b, 10_000);
+pub fn first_and_last_10k_stable(b: &mut Bencher) {
+ bench_first_and_last_stable(b, 10_000);
}
const BENCH_RANGE_SIZE: i32 = 145;
None
} else {
self.length -= 1;
- Some(unsafe { self.range.next_unchecked() })
+ Some(unsafe { self.range.inner.next_unchecked() })
}
}
None
} else {
self.length -= 1;
- Some(unsafe { self.range.next_back_unchecked() })
+ Some(unsafe { self.range.inner.next_back_unchecked() })
}
}
}
None
} else {
self.length -= 1;
- Some(unsafe { self.range.next_unchecked() })
+ Some(unsafe { self.range.inner.next_unchecked() })
}
}
None
} else {
self.length -= 1;
- Some(unsafe { self.range.next_back_unchecked() })
+ Some(unsafe { self.range.inner.next_back_unchecked() })
}
}
}
#[stable(feature = "btree_drop", since = "1.7.0")]
impl<K, V> Drop for IntoIter<K, V> {
fn drop(&mut self) {
- if let Some(front) = self.range.front.take() {
+ if let Some(front) = self.range.take_front() {
Dropper { front, remaining_length: self.length };
}
}
None
} else {
self.length -= 1;
- let front = self.range.front.as_mut().unwrap();
- let kv = unsafe { front.deallocating_next_unchecked() };
+ let kv = unsafe { self.range.deallocating_next_unchecked() };
Some(kv.into_key_val())
}
}
None
} else {
self.length -= 1;
- let back = self.range.back.as_mut().unwrap();
- let kv = unsafe { back.deallocating_next_back_unchecked() };
+ let kv = unsafe { self.range.deallocating_next_back_unchecked() };
Some(kv.into_key_val())
}
}
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option<(&'a K, &'a V)> {
- if self.inner.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) }
+ self.inner.next_checked()
}
fn last(mut self) -> Option<(&'a K, &'a V)> {
#[stable(feature = "fused", since = "1.26.0")]
impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
-impl<'a, K, V> Range<'a, K, V> {
- unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
- unsafe { self.inner.front.as_mut().unwrap_unchecked().next_unchecked() }
- }
-}
-
#[stable(feature = "map_into_keys_values", since = "1.54.0")]
impl<K, V> Iterator for IntoKeys<K, V> {
type Item = K;
#[stable(feature = "btree_range", since = "1.17.0")]
impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> {
fn next_back(&mut self) -> Option<(&'a K, &'a V)> {
- if self.inner.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) }
- }
-}
-
-impl<'a, K, V> Range<'a, K, V> {
- unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
- unsafe { self.inner.back.as_mut().unwrap_unchecked().next_back_unchecked() }
+ self.inner.next_back_checked()
}
}
#[stable(feature = "btree_range", since = "1.17.0")]
impl<K, V> Clone for Range<'_, K, V> {
fn clone(&self) -> Self {
- Range { inner: LeafRange { front: self.inner.front, back: self.inner.back } }
+ Range { inner: self.inner.clone() }
}
}
type Item = (&'a K, &'a mut V);
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
- if self.inner.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) }
+ self.inner.next_checked()
}
fn last(mut self) -> Option<(&'a K, &'a mut V)> {
}
impl<'a, K, V> RangeMut<'a, K, V> {
- unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
- unsafe { self.inner.front.as_mut().unwrap_unchecked().next_unchecked() }
- }
-
/// Returns an iterator of references over the remaining items.
#[inline]
pub(super) fn iter(&self) -> Range<'_, K, V> {
#[stable(feature = "btree_range", since = "1.17.0")]
impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> {
fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> {
- if self.inner.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) }
+ self.inner.next_back_checked()
}
}
#[stable(feature = "fused", since = "1.26.0")]
impl<K, V> FusedIterator for RangeMut<'_, K, V> {}
-impl<'a, K, V> RangeMut<'a, K, V> {
- unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
- unsafe { self.inner.back.as_mut().unwrap_unchecked().next_back_unchecked() }
- }
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> BTreeMap<K, V> {
use super::node::{marker, ForceResult::*, Handle, NodeRef};
+// `front` and `back` are always both `None` or both `Some`.
pub struct LeafRange<BorrowType, K, V> {
- pub front: Option<Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>>,
- pub back: Option<Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>>,
+ front: Option<Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>>,
+ back: Option<Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>>,
+}
+
+impl<'a, K: 'a, V: 'a> Clone for LeafRange<marker::Immut<'a>, K, V> {
+ fn clone(&self) -> Self {
+ LeafRange { front: self.front.clone(), back: self.back.clone() }
+ }
}
impl<BorrowType, K, V> LeafRange<BorrowType, K, V> {
LeafRange { front: None, back: None }
}
- pub fn is_empty(&self) -> bool {
+ fn is_empty(&self) -> bool {
self.front == self.back
}
}
}
+impl<'a, K, V> LeafRange<marker::Immut<'a>, K, V> {
+ #[inline]
+ pub fn next_checked(&mut self) -> Option<(&'a K, &'a V)> {
+ if self.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) }
+ }
+
+ #[inline]
+ pub fn next_back_checked(&mut self) -> Option<(&'a K, &'a V)> {
+ if self.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) }
+ }
+
+ #[inline]
+ pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
+ debug_assert!(self.front.is_some());
+ unsafe { self.front.as_mut().unwrap_unchecked().next_unchecked() }
+ }
+
+ #[inline]
+ pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
+ debug_assert!(self.back.is_some());
+ unsafe { self.back.as_mut().unwrap_unchecked().next_back_unchecked() }
+ }
+}
+
+impl<'a, K, V> LeafRange<marker::ValMut<'a>, K, V> {
+ #[inline]
+ pub fn next_checked(&mut self) -> Option<(&'a K, &'a mut V)> {
+ if self.is_empty() { None } else { Some(unsafe { self.next_unchecked() }) }
+ }
+
+ #[inline]
+ pub fn next_back_checked(&mut self) -> Option<(&'a K, &'a mut V)> {
+ if self.is_empty() { None } else { Some(unsafe { self.next_back_unchecked() }) }
+ }
+
+ #[inline]
+ pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
+ debug_assert!(self.front.is_some());
+ unsafe { self.front.as_mut().unwrap_unchecked().next_unchecked() }
+ }
+
+ #[inline]
+ pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
+ debug_assert!(self.back.is_some());
+ unsafe { self.back.as_mut().unwrap_unchecked().next_back_unchecked() }
+ }
+}
+
+impl<K, V> LeafRange<marker::Dying, K, V> {
+ #[inline]
+ pub fn take_front(
+ &mut self,
+ ) -> Option<Handle<NodeRef<marker::Dying, K, V, marker::Leaf>, marker::Edge>> {
+ self.front.take()
+ }
+
+ #[inline]
+ pub unsafe fn deallocating_next_unchecked(
+ &mut self,
+ ) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
+ debug_assert!(self.front.is_some());
+ let front = self.front.as_mut().unwrap();
+ unsafe { front.deallocating_next_unchecked() }
+ }
+
+ #[inline]
+ pub unsafe fn deallocating_next_back_unchecked(
+ &mut self,
+ ) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
+ debug_assert!(self.back.is_some());
+ let back = self.back.as_mut().unwrap();
+ unsafe { back.deallocating_next_back_unchecked() }
+ }
+}
+
impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
/// Finds the distinct leaf edges delimiting a specified range in a tree.
///
/// result will eventually reach the same edge.
///
/// If there are no such edges, i.e., if the tree contains no key within
- /// the range, returns a pair of empty options.
+ /// the range, returns an empty `front` and `back`.
///
/// # Safety
/// Unless `BorrowType` is `Immut`, do not use the handles to visit the same
/// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
/// on the left side, which is either in the same leaf node or in an ancestor node.
/// If the leaf edge is the first one in the tree, returns [`Result::Err`] with the root node.
- pub fn next_back_kv(
+ fn next_back_kv(
self,
) -> Result<
Handle<NodeRef<BorrowType, K, V, marker::LeafOrInternal>, marker::KV>,
/// Given an internal edge handle, returns [`Result::Ok`] with a handle to the neighboring KV
/// on the right side, which is either in the same internal node or in an ancestor node.
/// If the internal edge is the last one in the tree, returns [`Result::Err`] with the root node.
- pub fn next_kv(
+ fn next_kv(
self,
) -> Result<
Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::KV>,
/// - The returned KV handle is only valid to access the key and value,
/// and only valid until the next call to this method or counterpart
/// `deallocating_next_back`.
- pub unsafe fn deallocating_next(
+ unsafe fn deallocating_next(
self,
) -> Option<(Self, Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV>)>
{
///
/// # Safety
/// There must be another KV in the direction travelled.
- pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
+ unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) {
super::mem::replace(self, |leaf_edge| {
let kv = leaf_edge.next_kv();
+ debug_assert!(kv.is_ok());
let kv = unsafe { kv.ok().unwrap_unchecked() };
(kv.next_leaf_edge(), kv.into_kv())
})
///
/// # Safety
/// There must be another KV in the direction travelled.
- pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
+ unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) {
super::mem::replace(self, |leaf_edge| {
let kv = leaf_edge.next_back_kv();
+ debug_assert!(kv.is_ok());
let kv = unsafe { kv.ok().unwrap_unchecked() };
(kv.next_back_leaf_edge(), kv.into_kv())
})
///
/// # Safety
/// There must be another KV in the direction travelled.
- pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
+ unsafe fn next_unchecked(&mut self) -> (&'a K, &'a mut V) {
let kv = super::mem::replace(self, |leaf_edge| {
let kv = leaf_edge.next_kv();
+ debug_assert!(kv.is_ok());
let kv = unsafe { kv.ok().unwrap_unchecked() };
(unsafe { ptr::read(&kv) }.next_leaf_edge(), kv)
});
///
/// # Safety
/// There must be another KV in the direction travelled.
- pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
+ unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a mut V) {
let kv = super::mem::replace(self, |leaf_edge| {
let kv = leaf_edge.next_back_kv();
+ debug_assert!(kv.is_ok());
let kv = unsafe { kv.ok().unwrap_unchecked() };
(unsafe { ptr::read(&kv) }.next_back_leaf_edge(), kv)
});
///
/// The only safe way to proceed with the updated handle is to compare it, drop it,
/// or call this method or counterpart `deallocating_next_unchecked` again.
- pub unsafe fn deallocating_next_back_unchecked(
+ unsafe fn deallocating_next_back_unchecked(
&mut self,
) -> Handle<NodeRef<marker::Dying, K, V, marker::LeafOrInternal>, marker::KV> {
super::mem::replace(self, |leaf_edge| unsafe {
}
/// Returns the leaf edge closest to a KV for backward navigation.
- pub fn next_back_leaf_edge(
- self,
- ) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
+ fn next_back_leaf_edge(self) -> Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge> {
match self.force() {
Leaf(leaf_kv) => leaf_kv.left_edge(),
Internal(internal_kv) => {
unsafe {
ptr::copy(self.vec.as_ptr().add(idx), self.vec.as_mut_ptr().add(idx + amt), len - idx);
- ptr::copy(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
+ ptr::copy_nonoverlapping(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
self.vec.set_len(len + amt);
}
}
#[test]
#[should_panic]
fn test_slice_fail() {
- &"中华Việt Nam"[0..2];
+ let _ = &"中华Việt Nam"[0..2];
}
panic_cases! {
#[test]
#[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
fn test_slice_fail_truncated_1() {
- &LOREM_PARAGRAPH[..1024];
+ let _ = &LOREM_PARAGRAPH[..1024];
}
// check the truncation in the panic message
#[test]
#[should_panic(expected = "luctus, im`[...]")]
fn test_slice_fail_truncated_2() {
- &LOREM_PARAGRAPH[..1024];
+ let _ = &LOREM_PARAGRAPH[..1024];
}
}
#[should_panic]
fn test_str_slice_rangetoinclusive_notok() {
let s = "abcαβγ";
- &s[..=3];
+ let _ = &s[..=3];
}
#[test]
fn test_str_slicemut_rangetoinclusive_notok() {
let mut s = "abcαβγ".to_owned();
let s: &mut str = &mut s;
- &mut s[..=3];
+ let _ = &mut s[..=3];
}
#[test]
#[should_panic]
fn test_slice_out_of_bounds_1() {
let x = vec![1, 2, 3, 4, 5];
- &x[!0..];
+ let _ = &x[!0..];
}
#[test]
#[should_panic]
fn test_slice_out_of_bounds_2() {
let x = vec![1, 2, 3, 4, 5];
- &x[..6];
+ let _ = &x[..6];
}
#[test]
#[should_panic]
fn test_slice_out_of_bounds_3() {
let x = vec![1, 2, 3, 4, 5];
- &x[!0..4];
+ let _ = &x[!0..4];
}
#[test]
#[should_panic]
fn test_slice_out_of_bounds_4() {
let x = vec![1, 2, 3, 4, 5];
- &x[1..6];
+ let _ = &x[1..6];
}
#[test]
#[should_panic]
fn test_slice_out_of_bounds_5() {
let x = vec![1, 2, 3, 4, 5];
- &x[3..2];
+ let _ = &x[3..2];
}
#[test]
/// This call borrows `Cell` mutably (at compile-time) which guarantees
/// that we possess the only reference.
///
+ /// However be cautious: this method expects `self` to be mutable, which is
+ /// generally not the case when using a `Cell`. If you require interior
+ /// mutability by reference, consider using `RefCell` which provides
+ /// run-time checked mutable borrows through its [`borrow_mut`] method.
+ ///
+ /// [`borrow_mut`]: RefCell::borrow_mut()
+ ///
/// # Examples
///
/// ```
// Stores the location of the earliest currently active borrow.
// This gets updated whenver we go from having zero borrows
// to having a single borrow. When a borrow occurs, this gets included
- // in the generated `BorroeError/`BorrowMutError`
+ // in the generated `BorrowError/`BorrowMutError`
#[cfg(feature = "debug_refcell")]
borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>,
value: UnsafeCell<T>,
/// Trait for equality comparisons which are [partial equivalence
/// relations](https://en.wikipedia.org/wiki/Partial_equivalence_relation).
///
+/// `x.eq(y)` can also be written `x == y`, and `x.ne(y)` can be written `x != y`.
+/// We use the easier-to-read infix notation in the remainder of this documentation.
+///
/// This trait allows for partial equality, for types that do not have a full
/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
/// so floating point types implement `PartialEq` but not [`trait@Eq`].
///
-/// Formally, the equality must be (for all `a`, `b`, `c` of type `A`, `B`,
-/// `C`):
+/// Implementations must ensure that `eq` and `ne` are consistent with each other:
+///
+/// - `a != b` if and only if `!(a == b)`
+/// (ensured by the default implementation).
+///
+/// If [`PartialOrd`] or [`Ord`] are also implemented for `Self` and `Rhs`, their methods must also
+/// be consistent with `PartialEq` (see the documentation of those traits for the exact
+/// requirememts). It's easy to accidentally make them disagree by deriving some of the traits and
+/// manually implementing others.
+///
+/// The equality relation `==` must satisfy the following conditions
+/// (for all `a`, `b`, `c` of type `A`, `B`, `C`):
///
/// - **Symmetric**: if `A: PartialEq<B>` and `B: PartialEq<A>`, then **`a == b`
/// implies `b == a`**; and
///
/// ## How can I implement `PartialEq`?
///
-/// `PartialEq` only requires the [`eq`] method to be implemented; [`ne`] is defined
-/// in terms of it by default. Any manual implementation of [`ne`] *must* respect
-/// the rule that [`eq`] is a strict inverse of [`ne`]; that is, `!(a == b)` if and
-/// only if `a != b`.
-///
-/// Implementations of `PartialEq`, [`PartialOrd`], and [`Ord`] *must* agree with
-/// each other. It's easy to accidentally make them disagree by deriving some
-/// of the traits and manually implementing others.
-///
/// An example implementation for a domain in which two books are considered
/// the same book if their ISBN matches, even if the formats differ:
///
/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
///
-/// An order is a total order if it is (for all `a`, `b` and `c`):
+/// Implementations must be consistent with the [`PartialOrd`] implementation, and ensure
+/// `max`, `min`, and `clamp` are consistent with `cmp`:
+///
+/// - `partial_cmp(a, b) == Some(cmp(a, b))`.
+/// - `max(a, b) == max_by(a, b, cmp)` (ensured by the default implementation).
+/// - `min(a, b) == min_by(a, b, cmp)` (ensured by the default implementation).
+/// - For `a.clamp(min, max)`, see the [method docs](#method.clamp)
+/// (ensured by the default implementation).
+///
+/// It's easy to accidentally make `cmp` and `partial_cmp` disagree by
+/// deriving some of the traits and manually implementing others.
+///
+/// ## Corollaries
+///
+/// From the above and the requirements of `PartialOrd`, it follows that `<` defines a strict total order.
+/// This means that for all `a`, `b` and `c`:
///
-/// - total and asymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and
-/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
+/// - exactly one of `a < b`, `a == b` or `a > b` is true; and
+/// - `<` is transitive: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
///
/// ## Derivable
///
/// Then you must define an implementation for [`cmp`]. You may find it useful to use
/// [`cmp`] on your type's fields.
///
-/// Implementations of [`PartialEq`], [`PartialOrd`], and `Ord` *must*
-/// agree with each other. That is, `a.cmp(b) == Ordering::Equal` if
-/// and only if `a == b` and `Some(a.cmp(b)) == a.partial_cmp(b)` for
-/// all `a` and `b`. It's easy to accidentally make them disagree by
-/// deriving some of the traits and manually implementing others.
-///
/// Here's an example where you want to sort people by height only, disregarding `id`
/// and `name`:
///
/// Trait for values that can be compared for a sort-order.
///
+/// The `lt`, `le`, `gt`, and `ge` methods of this trait can be called using
+/// the `<`, `<=`, `>`, and `>=` operators, respectively.
+///
+/// The methods of this trait must be consistent with each other and with those of `PartialEq` in
+/// the following sense:
+///
+/// - `a == b` if and only if `partial_cmp(a, b) == Some(Equal)`.
+/// - `a < b` if and only if `partial_cmp(a, b) == Some(Less)`
+/// (ensured by the default implementation).
+/// - `a > b` if and only if `partial_cmp(a, b) == Some(Greater)`
+/// (ensured by the default implementation).
+/// - `a <= b` if and only if `a < b || a == b`
+/// (ensured by the default implementation).
+/// - `a >= b` if and only if `a > b || a == b`
+/// (ensured by the default implementation).
+/// - `a != b` if and only if `!(a == b)` (already part of `PartialEq`).
+///
+/// If [`Ord`] is also implemented for `Self` and `Rhs`, it must also be consistent with
+/// `partial_cmp` (see the documentation of that trait for the exact requirements). It's
+/// easy to accidentally make them disagree by deriving some of the traits and manually
+/// implementing others.
+///
/// The comparison must satisfy, for all `a`, `b` and `c`:
///
-/// - asymmetry: if `a < b` then `!(a > b)`, as well as `a > b` implying `!(a < b)`; and
/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
+/// - duality: `a < b` if and only if `b > a`.
///
/// Note that these requirements mean that the trait itself must be implemented symmetrically and
/// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
/// PartialOrd<V>`.
///
+/// ## Corollaries
+///
+/// The following corollaries follow from the above requirements:
+///
+/// - irreflexivity of `<` and `>`: `!(a < a)`, `!(a > a)`
+/// - transitivity of `>`: if `a > b` and `b > c` then `a > c`
+/// - duality of `partial_cmp`: `partial_cmp(a, b) == partial_cmp(b, a).map(Ordering::reverse)`
+///
/// ## Derivable
///
/// This trait can be used with `#[derive]`. When `derive`d on structs, it will produce a
///
/// `PartialOrd` requires your type to be [`PartialEq`].
///
-/// Implementations of [`PartialEq`], `PartialOrd`, and [`Ord`] *must* agree with each other. It's
-/// easy to accidentally make them disagree by deriving some of the traits and manually
-/// implementing others.
-///
/// If your type is [`Ord`], you can implement [`partial_cmp`] by using [`cmp`]:
///
/// ```
let sz_a = self.a.size();
if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len {
for _ in 0..sz_a - self.len {
+ self.a_len -= 1;
self.a.next_back();
}
- self.a_len = self.len;
+ debug_assert_eq!(self.a_len, self.len);
}
let sz_b = self.b.size();
if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len {
assert_eq!(z2.next().unwrap(), ((1, 1), 1));
}
+#[test]
+#[cfg(panic = "unwind")]
+fn test_zip_trusted_random_access_next_back_drop() {
+ use std::panic::catch_unwind;
+ use std::panic::AssertUnwindSafe;
+
+ let mut counter = 0;
+
+ let it = [42].iter().map(|e| {
+ let c = counter;
+ counter += 1;
+ if c == 0 {
+ panic!("bomb");
+ }
+
+ e
+ });
+ let it2 = [(); 0].iter();
+ let mut zip = it.zip(it2);
+ catch_unwind(AssertUnwindSafe(|| {
+ zip.next_back();
+ }))
+ .unwrap_err();
+ assert!(zip.next().is_none());
+ assert_eq!(counter, 1);
+}
+
#[test]
fn test_double_ended_zip() {
let xs = [1, 2, 3, 4, 5, 6];
/// pub fn span_open(&self) -> Span {
/// ^
/// ```
- #[unstable(feature = "proc_macro_span", issue = "54725")]
+ #[stable(feature = "proc_macro_group_span", since = "1.55.0")]
pub fn span_open(&self) -> Span {
Span(self.0.span_open())
}
/// pub fn span_close(&self) -> Span {
/// ^
/// ```
- #[unstable(feature = "proc_macro_span", issue = "54725")]
+ #[stable(feature = "proc_macro_group_span", since = "1.55.0")]
pub fn span_close(&self) -> Span {
Span(self.0.span_close())
}
self.file_type().is_file()
}
+ /// Returns `true` if this metadata is for a symbolic link.
+ ///
+ /// # Examples
+ ///
+ #[cfg_attr(unix, doc = "```no_run")]
+ #[cfg_attr(not(unix), doc = "```ignore")]
+ /// #![feature(is_symlink)]
+ /// use std::fs;
+ /// use std::path::Path;
+ /// use std::os::unix::fs::symlink;
+ ///
+ /// fn main() -> std::io::Result<()> {
+ /// let link_path = Path::new("link");
+ /// symlink("/origin_does_not_exists/", link_path)?;
+ ///
+ /// let metadata = fs::symlink_metadata(link_path)?;
+ ///
+ /// assert!(metadata.is_symlink());
+ /// Ok(())
+ /// }
+ /// ```
+ #[unstable(feature = "is_symlink", issue = "85748")]
+ pub fn is_symlink(&self) -> bool {
+ self.file_type().is_symlink()
+ }
+
/// Returns the size of the file, in bytes, this metadata is for.
///
/// # Examples
#[stable(feature = "rust1", since = "1.0.0")]
fn consume(&mut self, amt: usize);
+ /// Check if the underlying `Read` has any data left to be read.
+ ///
+ /// This function may fill the buffer to check for data,
+ /// so this functions returns `Result<bool>`, not `bool`.
+ ///
+ /// Default implementation calls `fill_buf` and checks that
+ /// returned slice is empty (which means that there is no data left,
+ /// since EOF is reached).
+ ///
+ /// Examples
+ ///
+ /// ```
+ /// #![feature(buf_read_has_data_left)]
+ /// use std::io;
+ /// use std::io::prelude::*;
+ ///
+ /// let stdin = io::stdin();
+ /// let mut stdin = stdin.lock();
+ ///
+ /// while stdin.has_data_left().unwrap() {
+ /// let mut line = String::new();
+ /// stdin.read_line(&mut line).unwrap();
+ /// // work with line
+ /// println!("{:?}", line);
+ /// }
+ /// ```
+ #[unstable(feature = "buf_read_has_data_left", reason = "recently added", issue = "86423")]
+ fn has_data_left(&mut self) -> Result<bool> {
+ self.fill_buf().map(|b| !b.is_empty())
+ }
+
/// Read all bytes into `buf` until the delimiter `byte` or EOF is reached.
///
/// This function will read bytes from the underlying stream until the
assert!(s.next().is_none());
}
+#[test]
+fn buf_read_has_data_left() {
+ let mut buf = Cursor::new(&b"abcd"[..]);
+ assert!(buf.has_data_left().unwrap());
+ buf.read_exact(&mut [0; 2]).unwrap();
+ assert!(buf.has_data_left().unwrap());
+ buf.read_exact(&mut [0; 2]).unwrap();
+ assert!(!buf.has_data_left().unwrap());
+}
+
#[test]
fn read_to_end() {
let mut c = Cursor::new(&b""[..]);
#![feature(allocator_internals)]
#![feature(allow_internal_unsafe)]
#![feature(allow_internal_unstable)]
-#![feature(async_stream)]
#![feature(arbitrary_self_types)]
#![feature(array_error_internals)]
#![feature(asm)]
#![feature(assert_matches)]
#![feature(associated_type_bounds)]
+#![feature(async_stream)]
#![feature(atomic_mut_ptr)]
+#![feature(auto_traits)]
#![feature(bench_black_box)]
#![feature(box_syntax)]
#![feature(c_variadic)]
#![feature(concat_idents)]
#![feature(const_cstr_unchecked)]
#![feature(const_fn_floating_point_arithmetic)]
-#![feature(const_fn_transmute)]
#![feature(const_fn_fn_ptr_basics)]
+#![feature(const_fn_transmute)]
#![feature(const_io_structs)]
#![feature(const_ip)]
+#![feature(const_ipv4)]
#![feature(const_ipv6)]
#![feature(const_raw_ptr_deref)]
#![feature(const_socketaddr)]
-#![feature(const_ipv4)]
#![feature(container_error_extra)]
#![feature(core_intrinsics)]
#![feature(custom_test_frameworks)]
#![feature(nll)]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(once_cell)]
-#![feature(auto_traits)]
#![feature(panic_info_message)]
#![feature(panic_internals)]
#![feature(panic_unwind)]
#![feature(unboxed_closures)]
#![feature(unsafe_cell_raw_get)]
#![feature(unwind_attributes)]
+#![feature(unwrap_infallible)]
#![feature(vec_into_raw_parts)]
#![feature(vec_spare_capacity)]
// NB: the above list is sorted to minimize merge conflicts.
#![unstable(feature = "sgx_platform", issue = "56975")]
+#[path = "../unix/ffi/os_str.rs"]
+mod os_str;
+
#[unstable(feature = "sgx_platform", issue = "56975")]
-pub use crate::sys_common::os_str_bytes::*;
+pub use self::os_str::{OsStrExt, OsStringExt};
#![stable(feature = "rust1", since = "1.0.0")]
+#[path = "../unix/ffi/os_str.rs"]
+mod os_str;
+
#[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::sys_common::os_str_bytes::*;
+pub use self::os_str::{OsStrExt, OsStringExt};
+++ /dev/null
-//! Unix-specific extension to the primitives in the `std::ffi` module.
-//!
-//! # Examples
-//!
-//! ```
-//! use std::ffi::OsString;
-//! use std::os::unix::ffi::OsStringExt;
-//!
-//! let bytes = b"foo".to_vec();
-//!
-//! // OsStringExt::from_vec
-//! let os_string = OsString::from_vec(bytes);
-//! assert_eq!(os_string.to_str(), Some("foo"));
-//!
-//! // OsStringExt::into_vec
-//! let bytes = os_string.into_vec();
-//! assert_eq!(bytes, b"foo");
-//! ```
-//!
-//! ```
-//! use std::ffi::OsStr;
-//! use std::os::unix::ffi::OsStrExt;
-//!
-//! let bytes = b"foo";
-//!
-//! // OsStrExt::from_bytes
-//! let os_str = OsStr::from_bytes(bytes);
-//! assert_eq!(os_str.to_str(), Some("foo"));
-//!
-//! // OsStrExt::as_bytes
-//! let bytes = os_str.as_bytes();
-//! assert_eq!(bytes, b"foo");
-//! ```
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::sys_common::os_str_bytes::*;
--- /dev/null
+//! Unix-specific extension to the primitives in the `std::ffi` module.
+//!
+//! # Examples
+//!
+//! ```
+//! use std::ffi::OsString;
+//! use std::os::unix::ffi::OsStringExt;
+//!
+//! let bytes = b"foo".to_vec();
+//!
+//! // OsStringExt::from_vec
+//! let os_string = OsString::from_vec(bytes);
+//! assert_eq!(os_string.to_str(), Some("foo"));
+//!
+//! // OsStringExt::into_vec
+//! let bytes = os_string.into_vec();
+//! assert_eq!(bytes, b"foo");
+//! ```
+//!
+//! ```
+//! use std::ffi::OsStr;
+//! use std::os::unix::ffi::OsStrExt;
+//!
+//! let bytes = b"foo";
+//!
+//! // OsStrExt::from_bytes
+//! let os_str = OsStr::from_bytes(bytes);
+//! assert_eq!(os_str.to_str(), Some("foo"));
+//!
+//! // OsStrExt::as_bytes
+//! let bytes = os_str.as_bytes();
+//! assert_eq!(bytes, b"foo");
+//! ```
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+mod os_str;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::os_str::{OsStrExt, OsStringExt};
--- /dev/null
+use crate::ffi::{OsStr, OsString};
+use crate::mem;
+use crate::sealed::Sealed;
+use crate::sys::os_str::Buf;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+
+// Note: this file is currently reused in other `std::os::{platform}::ffi` modules to reduce duplication.
+// Keep this in mind when applying changes to this file that only apply to `unix`.
+
+/// Platform-specific extensions to [`OsString`].
+///
+/// This trait is sealed: it cannot be implemented outside the standard library.
+/// This is so that future additional methods are not breaking changes.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStringExt: Sealed {
+ /// Creates an [`OsString`] from a byte vector.
+ ///
+ /// See the module documentation for an example.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn from_vec(vec: Vec<u8>) -> Self;
+
+ /// Yields the underlying byte vector of this [`OsString`].
+ ///
+ /// See the module documentation for an example.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn into_vec(self) -> Vec<u8>;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStringExt for OsString {
+ fn from_vec(vec: Vec<u8>) -> OsString {
+ FromInner::from_inner(Buf { inner: vec })
+ }
+ fn into_vec(self) -> Vec<u8> {
+ self.into_inner().inner
+ }
+}
+
+/// Platform-specific extensions to [`OsStr`].
+///
+/// This trait is sealed: it cannot be implemented outside the standard library.
+/// This is so that future additional methods are not breaking changes.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStrExt: Sealed {
+ #[stable(feature = "rust1", since = "1.0.0")]
+ /// Creates an [`OsStr`] from a byte slice.
+ ///
+ /// See the module documentation for an example.
+ fn from_bytes(slice: &[u8]) -> &Self;
+
+ /// Gets the underlying byte view of the [`OsStr`] slice.
+ ///
+ /// See the module documentation for an example.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn as_bytes(&self) -> &[u8];
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStrExt for OsStr {
+ #[inline]
+ fn from_bytes(slice: &[u8]) -> &OsStr {
+ unsafe { mem::transmute(slice) }
+ }
+ #[inline]
+ fn as_bytes(&self) -> &[u8] {
+ &self.as_inner().inner
+ }
+}
#![stable(feature = "rust1", since = "1.0.0")]
+#[path = "../unix/ffi/os_str.rs"]
+mod os_str;
+
#[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::sys_common::os_str_bytes::*;
+pub use self::os_str::{OsStrExt, OsStringExt};
fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
}
+ /// Returns true if the path exists on disk and is pointing at a symbolic link.
+ ///
+ /// This function will not traverse symbolic links.
+ /// In case of a broken symbolic link this will also return true.
+ ///
+ /// If you cannot access the directory containing the file, e.g., because of a
+ /// permission error, this will return false.
+ ///
+ /// # Examples
+ ///
+ #[cfg_attr(unix, doc = "```no_run")]
+ #[cfg_attr(not(unix), doc = "```ignore")]
+ /// #![feature(is_symlink)]
+ /// use std::path::Path;
+ /// use std::os::unix::fs::symlink;
+ ///
+ /// let link_path = Path::new("link");
+ /// symlink("/origin_does_not_exists/", link_path).unwrap();
+ /// assert_eq!(link_path.is_symlink(), true);
+ /// assert_eq!(link_path.exists(), false);
+ /// ```
+ #[unstable(feature = "is_symlink", issue = "85748")]
+ pub fn is_symlink(&self) -> bool {
+ fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false)
+ }
+
/// Converts a [`Box<Path>`](Box) into a [`PathBuf`] without copying or
/// allocating.
#[stable(feature = "into_boxed_path", since = "1.20.0")]
main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindSafe),
argc: isize,
argv: *const *const u8,
-) -> isize {
- use crate::panic;
- use crate::sys_common;
-
+) -> Result<isize, !> {
+ use crate::{mem, panic, sys, sys_common};
+ let rt_abort = move |e| {
+ mem::forget(e);
+ rtabort!("initialization or cleanup bug");
+ };
+ // Guard against the code called by this function from unwinding outside of the Rust-controlled
+ // code, which is UB. This is a requirement imposed by a combination of how the
+ // `#[lang="start"]` attribute is implemented as well as by the implementation of the panicking
+ // mechanism itself.
+ //
+ // There are a couple of instances where unwinding can begin. First is inside of the
+ // `rt::init`, `rt::cleanup` and similar functions controlled by libstd. In those instances a
+ // panic is a libstd implementation bug. A quite likely one too, as there isn't any way to
+ // prevent libstd from accidentally introducing a panic to these functions. Another is from
+ // user code from `main` or, more nefariously, as described in e.g. issue #86030.
// SAFETY: Only called once during runtime initialization.
- unsafe { sys_common::rt::init(argc, argv) };
-
- let exit_code = panic::catch_unwind(main);
-
- sys_common::rt::cleanup();
-
- exit_code.unwrap_or(101) as isize
+ panic::catch_unwind(move || unsafe { sys_common::rt::init(argc, argv) }).map_err(rt_abort)?;
+ let ret_code = panic::catch_unwind(move || panic::catch_unwind(main).unwrap_or(101) as isize)
+ .map_err(move |e| {
+ mem::forget(e);
+ rtprintpanic!("drop of the panic payload panicked");
+ sys::abort_internal()
+ });
+ panic::catch_unwind(sys_common::rt::cleanup).map_err(rt_abort)?;
+ ret_code
}
#[cfg(not(test))]
argc,
argv,
)
+ .into_ok()
}
mod imp {
use super::Args;
use crate::ffi::{CStr, OsString};
+ use crate::os::unix::ffi::OsStringExt;
use crate::ptr;
- use crate::sys_common::os_str_bytes::*;
use crate::sys_common::mutex::StaticMutex;
use crate::hash::{Hash, Hasher};
use crate::io::{self, Error, ErrorKind};
use crate::io::{IoSlice, IoSliceMut, SeekFrom};
+use crate::os::unix::ffi::OsStrExt;
use crate::path::{Path, PathBuf};
use crate::sys::cvt;
use crate::sys::hermit::abi;
use crate::sys::hermit::fd::FileDesc;
use crate::sys::time::SystemTime;
use crate::sys::unsupported;
-use crate::sys_common::os_str_bytes::OsStrExt;
pub use crate::sys_common::fs::{copy, try_exists};
//pub use crate::sys_common::fs::remove_dir_all;
use crate::fmt;
use crate::io;
use crate::marker::PhantomData;
+use crate::os::unix::ffi::OsStringExt;
use crate::path::{self, PathBuf};
use crate::str;
use crate::sync::Mutex;
use crate::sys::hermit::abi;
use crate::sys::memchr;
use crate::sys::unsupported;
-use crate::sys_common::os_str_bytes::*;
use crate::vec;
pub fn errno() -> i32 {
//! systems: just a `Vec<u8>`/`[u8]`.
use crate::borrow::Cow;
-use crate::ffi::{OsStr, OsString};
+
use crate::fmt;
use crate::mem;
use crate::rc::Rc;
-use crate::sealed::Sealed;
use crate::str;
use crate::sync::Arc;
use crate::sys_common::bytestring::debug_fmt_bytestring;
-use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::sys_common::{AsInner, IntoInner};
use core::str::lossy::Utf8Lossy;
#[derive(Hash)]
-pub(crate) struct Buf {
+#[repr(transparent)]
+pub struct Buf {
pub inner: Vec<u8>,
}
-// FIXME:
-// `Buf::as_slice` current implementation relies
-// on `Slice` being layout-compatible with `[u8]`.
-// When attribute privacy is implemented, `Slice` should be annotated as `#[repr(transparent)]`.
-// Anyway, `Slice` representation and layout are considered implementation detail, are
-// not documented and must not be relied upon.
-pub(crate) struct Slice {
+#[repr(transparent)]
+pub struct Slice {
pub inner: [u8],
}
self.inner.eq_ignore_ascii_case(&other.inner)
}
}
-
-/// Platform-specific extensions to [`OsString`].
-///
-/// This trait is sealed: it cannot be implemented outside the standard library.
-/// This is so that future additional methods are not breaking changes.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait OsStringExt: Sealed {
- /// Creates an [`OsString`] from a byte vector.
- ///
- /// See the module documentation for an example.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn from_vec(vec: Vec<u8>) -> Self;
-
- /// Yields the underlying byte vector of this [`OsString`].
- ///
- /// See the module documentation for an example.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn into_vec(self) -> Vec<u8>;
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl OsStringExt for OsString {
- fn from_vec(vec: Vec<u8>) -> OsString {
- FromInner::from_inner(Buf { inner: vec })
- }
- fn into_vec(self) -> Vec<u8> {
- self.into_inner().inner
- }
-}
-
-/// Platform-specific extensions to [`OsStr`].
-///
-/// This trait is sealed: it cannot be implemented outside the standard library.
-/// This is so that future additional methods are not breaking changes.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait OsStrExt: Sealed {
- #[stable(feature = "rust1", since = "1.0.0")]
- /// Creates an [`OsStr`] from a byte slice.
- ///
- /// See the module documentation for an example.
- fn from_bytes(slice: &[u8]) -> &Self;
-
- /// Gets the underlying byte view of the [`OsStr`] slice.
- ///
- /// See the module documentation for an example.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn as_bytes(&self) -> &[u8];
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl OsStrExt for OsStr {
- #[inline]
- fn from_bytes(slice: &[u8]) -> &OsStr {
- unsafe { mem::transmute(slice) }
- }
- #[inline]
- fn as_bytes(&self) -> &[u8] {
- &self.as_inner().inner
- }
-}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, high) = self.code_points.size_hint();
+ let ext = (self.extra != 0) as usize;
// every code point gets either one u16 or two u16,
// so this iterator is between 1 or 2 times as
// long as the underlying iterator.
- (low, high.and_then(|n| n.checked_mul(2)))
+ (low + ext, high.and_then(|n| n.checked_mul(2)).and_then(|n| n.checked_add(ext)))
}
}
#[test]
#[should_panic]
fn wtf8_slice_not_code_point_boundary() {
- &Wtf8::from_str("aé 💩")[2..4];
+ let _ = &Wtf8::from_str("aé 💩")[2..4];
}
#[test]
#[test]
#[should_panic]
fn wtf8_slice_from_not_code_point_boundary() {
- &Wtf8::from_str("aé 💩")[2..];
+ let _ = &Wtf8::from_str("aé 💩")[2..];
}
#[test]
#[test]
#[should_panic]
fn wtf8_slice_to_not_code_point_boundary() {
- &Wtf8::from_str("aé 💩")[5..];
+ let _ = &Wtf8::from_str("aé 💩")[5..];
}
#[test]
vec![0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]
);
}
+
+#[test]
+fn wtf8_encode_wide_size_hint() {
+ let string = Wtf8Buf::from_str("\u{12345}");
+ let mut iter = string.encode_wide();
+ assert_eq!((1, Some(8)), iter.size_hint());
+ iter.next().unwrap();
+ assert_eq!((1, Some(1)), iter.size_hint());
+ iter.next().unwrap();
+ assert_eq!((0, Some(0)), iter.size_hint());
+ assert!(iter.next().is_none());
+}
name=\"{}\" time=\"{}\">",
class_name,
test_name,
- duration.as_secs()
+ duration.as_secs_f64()
))?;
self.write_message("<failure type=\"assert\"/>")?;
self.write_message("</testcase>")?;
name=\"{}\" time=\"{}\">",
class_name,
test_name,
- duration.as_secs()
+ duration.as_secs_f64()
))?;
self.write_message(&*format!("<failure message=\"{}\" type=\"assert\"/>", m))?;
self.write_message("</testcase>")?;
name=\"{}\" time=\"{}\">",
class_name,
test_name,
- duration.as_secs()
+ duration.as_secs_f64()
))?;
self.write_message("<failure type=\"timeout\"/>")?;
self.write_message("</testcase>")?;
name=\"{}\" time=\"{}\"/>",
class_name,
test_name,
- duration.as_secs()
+ duration.as_secs_f64()
))?;
}
}
ignore = "0.4.10"
opener = "0.4"
merge = "0.1.0"
+once_cell = "1.7.2"
[target.'cfg(windows)'.dependencies.winapi]
version = "0.3"
use crate::{Build, DocTests, GitRepo, Mode};
pub use crate::Compiler;
+// FIXME: replace with std::lazy after it gets stabilized and reaches beta
+use once_cell::sync::Lazy;
pub struct Builder<'a> {
pub build: &'a Build,
if paths.is_empty() || builder.config.include_default_paths {
for (desc, should_run) in v.iter().zip(&should_runs) {
- if desc.default && should_run.is_really_default {
+ if desc.default && should_run.is_really_default() {
for pathset in &should_run.paths {
desc.maybe_run(builder, pathset);
}
}
}
-#[derive(Clone)]
+enum ReallyDefault<'a> {
+ Bool(bool),
+ Lazy(Lazy<bool, Box<dyn Fn() -> bool + 'a>>),
+}
+
pub struct ShouldRun<'a> {
pub builder: &'a Builder<'a>,
// use a BTreeSet to maintain sort order
// If this is a default rule, this is an additional constraint placed on
// its run. Generally something like compiler docs being enabled.
- is_really_default: bool,
+ is_really_default: ReallyDefault<'a>,
}
impl<'a> ShouldRun<'a> {
ShouldRun {
builder,
paths: BTreeSet::new(),
- is_really_default: true, // by default no additional conditions
+ is_really_default: ReallyDefault::Bool(true), // by default no additional conditions
}
}
pub fn default_condition(mut self, cond: bool) -> Self {
- self.is_really_default = cond;
+ self.is_really_default = ReallyDefault::Bool(cond);
+ self
+ }
+
+ pub fn lazy_default_condition(mut self, lazy_cond: Box<dyn Fn() -> bool + 'a>) -> Self {
+ self.is_really_default = ReallyDefault::Lazy(Lazy::new(lazy_cond));
self
}
+ pub fn is_really_default(&self) -> bool {
+ match &self.is_really_default {
+ ReallyDefault::Bool(val) => *val,
+ ReallyDefault::Lazy(lazy) => *lazy.deref(),
+ }
+ }
+
/// Indicates it should run if the command-line selects the given crate or
/// any of its (local) dependencies.
///
// Note that the stages here are +1 than what they actually are because
// Rustdoc::run swaps out the compiler with stage minus 1 if --stage is
// not 0.
+ //
+ // The stage 0 copy is the one downloaded for bootstrapping. It is
+ // (currently) needed to run "cargo test" on the linkchecker, and
+ // should be relatively "free".
assert_eq!(
first(builder.cache.all::<tool::Rustdoc>()),
&[
+ tool::Rustdoc { compiler: Compiler { host: a, stage: 0 } },
tool::Rustdoc { compiler: Compiler { host: a, stage: 1 } },
tool::Rustdoc { compiler: Compiler { host: a, stage: 2 } },
]
builder.info(&format!("Linkcheck ({})", host));
+ // Test the linkchecker itself.
+ let bootstrap_host = builder.config.build;
+ let compiler = builder.compiler(0, bootstrap_host);
+ let cargo = tool::prepare_tool_cargo(
+ builder,
+ compiler,
+ Mode::ToolBootstrap,
+ bootstrap_host,
+ "test",
+ "src/tools/linkchecker",
+ SourceType::InTree,
+ &[],
+ );
+ try_run(builder, &mut cargo.into());
+
+ // Build all the default documentation.
builder.default_doc(&[]);
+ // Run the linkchecker.
let _time = util::timeit(&builder);
try_run(
builder,
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
let run = run.suite_path("src/test/rustdoc-gui");
- run.default_condition(
+ run.lazy_default_condition(Box::new(move || {
builder.config.nodejs.is_some()
&& builder
.config
.npm
.as_ref()
.map(|p| check_if_browser_ui_test_is_installed(p))
- .unwrap_or(false),
- )
+ .unwrap_or(false)
+ }))
}
fn make_run(run: RunConfig<'_>) {
# https://github.com/puppeteer/puppeteer/issues/375
#
# We also specify the version in case we need to update it to go around cache limitations.
-RUN npm install -g browser-ui-test@0.2.14 --unsafe-perm=true
+RUN npm install -g browser-ui-test@0.3.0 --unsafe-perm=true
ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
rustdoc-json-types = { path = "../rustdoc-json-types" }
tracing = "0.1"
tracing-tree = "0.1.9"
+tera = { version = "1.10.0", default-features = false }
[dependencies.tracing-subscriber]
version = "0.2.13"
use std::path::Path;
use std::str;
-#[derive(Clone, Debug)]
+use serde::Serialize;
+
+#[derive(Clone, Debug, Serialize)]
crate struct ExternalHtml {
/// Content that will be included inline in the <head> section of a
/// rendered Markdown file or generated documentation
use crate::html::format::{Buffer, Print};
use crate::html::render::{ensure_trailing_slash, StylePath};
-#[derive(Clone)]
+use serde::Serialize;
+
+#[derive(Clone, Serialize)]
crate struct Layout {
crate logo: String,
crate favicon: String,
crate generate_search_filter: bool,
}
+#[derive(Serialize)]
crate struct Page<'a> {
crate title: &'a str,
crate css_class: &'a str,
}
}
+#[derive(Serialize)]
+struct PageLayout<'a> {
+ static_root_path: &'a str,
+ page: &'a Page<'a>,
+ layout: &'a Layout,
+ style_files: String,
+ sidebar: String,
+ content: String,
+ krate_with_trailing_slash: String,
+}
+
crate fn render<T: Print, S: Print>(
+ templates: &tera::Tera,
layout: &Layout,
page: &Page<'_>,
sidebar: S,
style_files: &[StylePath],
) -> String {
let static_root_path = page.get_static_root_path();
- format!(
- "<!DOCTYPE html>\
-<html lang=\"en\">\
-<head>\
- <meta charset=\"utf-8\">\
- <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
- <meta name=\"generator\" content=\"rustdoc\">\
- <meta name=\"description\" content=\"{description}\">\
- <meta name=\"keywords\" content=\"{keywords}\">\
- <title>{title}</title>\
- <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
- <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
- id=\"mainThemeStyle\">\
- {style_files}\
- <script id=\"default-settings\"{default_settings}></script>\
- <script src=\"{static_root_path}storage{suffix}.js\"></script>\
- <script src=\"{root_path}crates{suffix}.js\"></script>\
- <noscript><link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\"></noscript>\
- {css_extension}\
- {favicon}\
- {in_header}\
- <style type=\"text/css\">\
- #crate-search{{background-image:url(\"{static_root_path}down-arrow{suffix}.svg\");}}\
- </style>\
-</head>\
-<body class=\"rustdoc {css_class}\">\
- <!--[if lte IE 11]>\
- <div class=\"warning\">\
- This old browser is unsupported and will most likely display funky \
- things.\
- </div>\
- <![endif]-->\
- {before_content}\
- <nav class=\"sidebar\">\
- <div class=\"sidebar-menu\" role=\"button\">☰</div>\
- {logo}\
- {sidebar}\
- </nav>\
- <div class=\"theme-picker\">\
- <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\" title=\"themes\">\
- <img src=\"{static_root_path}brush{suffix}.svg\" \
- width=\"18\" height=\"18\" \
- alt=\"Pick another theme!\">\
- </button>\
- <div id=\"theme-choices\" role=\"menu\"></div>\
- </div>\
- <nav class=\"sub\">\
- <form class=\"search-form\">\
- <div class=\"search-container\">\
- <div>{filter_crates}\
- <input class=\"search-input\" name=\"search\" \
- disabled \
- autocomplete=\"off\" \
- spellcheck=\"false\" \
- placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
- type=\"search\">\
- </div>\
- <button type=\"button\" id=\"help-button\" title=\"help\">?</button>\
- <a id=\"settings-menu\" href=\"{root_path}settings.html\" title=\"settings\">\
- <img src=\"{static_root_path}wheel{suffix}.svg\" \
- width=\"18\" height=\"18\" \
- alt=\"Change settings\">\
- </a>\
- </div>\
- </form>\
- </nav>\
- <section id=\"main\" class=\"content\">{content}</section>\
- <section id=\"search\" class=\"content hidden\"></section>\
- {after_content}\
- <div id=\"rustdoc-vars\" data-root-path=\"{root_path}\" data-current-crate=\"{krate}\" \
- data-search-index-js=\"{root_path}search-index{suffix}.js\" \
- data-search-js=\"{static_root_path}search{suffix}.js\"></div>\
- <script src=\"{static_root_path}main{suffix}.js\"></script>\
- {extra_scripts}\
-</body>\
-</html>",
- css_extension = if layout.css_file_extension.is_some() {
+ let krate_with_trailing_slash = ensure_trailing_slash(&layout.krate).to_string();
+ let style_files = style_files
+ .iter()
+ .filter_map(|t| {
+ if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
+ })
+ .filter_map(|t| if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None })
+ .map(|t| {
format!(
- "<link rel=\"stylesheet\" \
- type=\"text/css\" \
- href=\"{static_root_path}theme{suffix}.css\">",
- static_root_path = static_root_path,
- suffix = page.resource_suffix
- )
- } else {
- String::new()
- },
- content = Buffer::html().to_display(t),
- static_root_path = static_root_path,
- root_path = page.root_path,
- css_class = page.css_class,
- logo = {
- if layout.logo.is_empty() {
- format!(
- "<a href='{root}{path}index.html'>\
- <div class='logo-container rust-logo'>\
- <img src='{static_root_path}rust-logo{suffix}.png' alt='logo'></div></a>",
- root = page.root_path,
- path = ensure_trailing_slash(&layout.krate),
- static_root_path = static_root_path,
- suffix = page.resource_suffix
- )
- } else {
- format!(
- "<a href='{root}{path}index.html'>\
- <div class='logo-container'><img src='{logo}' alt='logo'></div></a>",
- root = page.root_path,
- path = ensure_trailing_slash(&layout.krate),
- logo = layout.logo
- )
- }
- },
- title = page.title,
- description = Escape(page.description),
- keywords = page.keywords,
- favicon = if layout.favicon.is_empty() {
- format!(
- r##"<link rel="icon" type="image/svg+xml" href="{static_root_path}favicon{suffix}.svg">
-<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-16x16{suffix}.png">
-<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-32x32{suffix}.png">"##,
- static_root_path = static_root_path,
- suffix = page.resource_suffix
- )
- } else {
- format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
- },
- in_header = layout.external_html.in_header,
- before_content = layout.external_html.before_content,
- after_content = layout.external_html.after_content,
- sidebar = Buffer::html().to_display(sidebar),
- krate = layout.krate,
- default_settings = layout
- .default_settings
- .iter()
- .map(|(k, v)| format!(r#" data-{}="{}""#, k.replace('-', "_"), Escape(v)))
- .collect::<String>(),
- style_files = style_files
- .iter()
- .filter_map(|t| {
- if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
- })
- .filter_map(|t| {
- if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }
- })
- .map(|t| format!(
r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
if t.1 { "disabled" } else { "" },
if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
- ))
- .collect::<String>(),
- suffix = page.resource_suffix,
- extra_scripts = page
- .static_extra_scripts
- .iter()
- .map(|e| {
- format!(
- "<script src=\"{static_root_path}{extra_script}.js\"></script>",
- static_root_path = static_root_path,
- extra_script = e
- )
- })
- .chain(page.extra_scripts.iter().map(|e| {
- format!(
- "<script src=\"{root_path}{extra_script}.js\"></script>",
- root_path = page.root_path,
- extra_script = e
- )
- }))
- .collect::<String>(),
- filter_crates = if layout.generate_search_filter {
- "<select id=\"crate-search\">\
- <option value=\"All crates\">All crates</option>\
- </select>"
- } else {
- ""
- },
- )
+ )
+ })
+ .collect::<String>();
+ let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
+ let sidebar = Buffer::html().to_display(sidebar);
+ let teractx = tera::Context::from_serialize(PageLayout {
+ static_root_path,
+ page,
+ layout,
+ style_files,
+ sidebar,
+ content,
+ krate_with_trailing_slash,
+ })
+ .unwrap();
+ templates.render("page.html", &teractx).unwrap()
}
crate fn redirect(url: &str) -> String {
use std::cell::RefCell;
use std::collections::BTreeMap;
+use std::error::Error as StdError;
use std::io;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use crate::html::escape::Escape;
use crate::html::format::Buffer;
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
+use crate::html::static_files::PAGE;
use crate::html::{layout, sources};
/// Major driving force in all rustdoc rendering. This contains information
/// to `Some(...)`, it'll store redirections and then generate a JSON file at the top level of
/// the crate.
redirections: Option<RefCell<FxHashMap<String, String>>>,
+
+ pub(crate) templates: tera::Tera,
}
impl SharedContext<'_> {
if !self.render_redirect_pages {
layout::render(
+ &self.shared.templates,
&self.shared.layout,
&page,
|buf: &mut _| print_sidebar(self, it, buf),
let mut issue_tracker_base_url = None;
let mut include_sources = true;
+ let mut templates = tera::Tera::default();
+ templates.add_raw_template("page.html", PAGE).map_err(|e| Error {
+ file: "page.html".into(),
+ error: format!("{}: {}", e, e.source().map(|e| e.to_string()).unwrap_or_default()),
+ })?;
+
// Crawl the crate attributes looking for attributes which control how we're
// going to emit HTML
for attr in krate.module.attrs.lists(sym::doc) {
errors: receiver,
redirections: if generate_redirect_map { Some(Default::default()) } else { None },
show_type_layout,
+ templates,
};
// Add the default themes to the `Vec` of stylepaths
};
let all = self.shared.all.replace(AllTypes::new());
let v = layout::render(
+ &self.shared.templates,
&self.shared.layout,
&page,
sidebar,
let sidebar = "<p class=\"location\">Settings</p><div class=\"sidebar-elems\"></div>";
style_files.push(StylePath { path: PathBuf::from("settings.css"), disabled: false });
let v = layout::render(
+ &self.shared.templates,
&self.shared.layout,
&page,
sidebar,
out.push_str("</div>");
}
}
-
- // Recurse into any further impls that might exist for `target`
- if let Some(target_did) = target.def_id_full(c) {
- if let Some(target_impls) = c.impls.get(&target_did) {
- if let Some(target_deref_impl) = target_impls
- .iter()
- .filter(|i| i.inner_impl().trait_.is_some())
- .find(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_trait_did)
- {
- sidebar_deref_methods(cx, out, target_deref_impl, target_impls);
- }
- }
- }
}
}
}
w.write_str(")");
}
- w.write_str("</code></div>");
+ w.write_str("</code>");
+ render_stability_since(w, variant, it, cx.tcx());
+ w.write_str("</div>");
document(w, cx, variant, Some(it));
document_non_exhaustive(w, variant);
w.write_str("</div></div>");
toggle_close(w);
}
- render_stability_since(w, variant, it, cx.tcx());
}
}
let def_id = it.def_id.expect_real();
})
.collect::<String>()
);
- let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.style_files);
+ let v = layout::render(
+ &cx.shared.templates,
+ &cx.shared.layout,
+ &page,
+ "",
+ content,
+ &cx.shared.style_files,
+ );
cx.shared.fs.write(&dst, v.as_bytes())?;
}
}
static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)],
};
let v = layout::render(
+ &self.scx.templates,
&self.scx.layout,
&page,
"",
Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A.
-with Reserved Font Name < Fira >,
+with Reserved Font Name < Fira >,
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
+fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
background: transparent;
}
+.small-section-header {
+ display: flex;
+ justify-content: space-between;
+ position: relative;
+}
+
.small-section-header:hover > .anchor {
display: initial;
}
crate static RUST_FAVICON_PNG_16: &[u8] = include_bytes!("static/favicon-16x16.png");
crate static RUST_FAVICON_PNG_32: &[u8] = include_bytes!("static/favicon-32x32.png");
+crate static PAGE: &str = include_str!("templates/page.html");
+
/// The built-in themes given to every documentation site.
crate mod themes {
/// The "light" theme, selected by default when no setting is available. Used as the basis for
--- /dev/null
+# Style for Templates
+
+This directory has templates in the [Tera templating language](teradoc), which is very
+similar to [Jinja2](jinjadoc) and [Django](djangodoc) templates, and also to [Askama](askamadoc).
+
+[teradoc]: https://tera.netlify.app/docs/#templates
+[jinjadoc]: https://jinja.palletsprojects.com/en/3.0.x/templates/
+[djangodoc]: https://docs.djangoproject.com/en/3.2/topics/templates/
+[askamadoc]: https://docs.rs/askama/0.10.5/askama/
+
+We want our rendered output to have as little unnecessary whitespace as
+possible, so that pages load quickly. To achieve that we use Tera's
+[whitespace control] features. At the end of most lines, we put an empty comment
+tag with the whitespace control characters: `{#- -#}`. This causes all
+whitespace between the end of the line and the beginning of the next, including
+indentation, to be omitted on render. Sometimes we want to preserve a single
+space. In those cases we put the space at the end of the line, followed by
+`{# -#}`, which is a directive to remove following whitespace but not preceding.
+We also use the whitespace control characters in most instances of tags with
+control flow, for example `{%- if foo -%}`.
+
+[whitespace control]: https://tera.netlify.app/docs/#whitespace-control
+
+We want our templates to be readable, so we use indentation and newlines
+liberally. We indent by four spaces after opening an HTML tag _or_ a Tera
+tag. In most cases an HTML tag should be followed by a newline, but if the
+tag has simple contents and fits with its close tag on a single line, the
+contents don't necessarily need a new line.
+
+Tera templates support quite sophisticated control flow. To keep our templates
+simple and understandable, we use only a subset: `if` and `for`. In particular
+we avoid [assignments in the template logic](assignments) and [Tera
+macros](macros). This also may make things easier if we switch to a different
+Jinja-style template system, like Askama, in the future.
+
+[assignments]: https://tera.netlify.app/docs/#assignments
+[macros]: https://tera.netlify.app/docs/#macros
--- /dev/null
+<!DOCTYPE html> {#- -#}
+<html lang="en"> {#- -#}
+<head> {#- -#}
+ <meta charset="utf-8"> {#- -#}
+ <meta name="viewport" content="width=device-width, initial-scale=1.0"> {#- -#}
+ <meta name="generator" content="rustdoc"> {#- -#}
+ <meta name="description" content="{{page.description}}"> {#- -#}
+ <meta name="keywords" content="{{page.keywords}}"> {#- -#}
+ <title>{{page.title}}</title> {#- -#}
+ <link rel="stylesheet" type="text/css" {# -#}
+ href="{{static_root_path | safe}}normalize{{page.resource_suffix}}.css"> {#- -#}
+ <link rel="stylesheet" type="text/css" {# -#}
+ href="{{static_root_path | safe}}rustdoc{{page.resource_suffix}}.css" {# -#}
+ id="mainThemeStyle"> {#- -#}
+ {{- style_files | safe -}}
+ <script id="default-settings" {# -#}
+ {% for k, v in layout.default_settings %}
+ data-{{k}}="{{v}}"
+ {%- endfor -%}
+ ></script> {#- -#}
+ <script src="{{static_root_path | safe}}storage{{page.resource_suffix}}.js"></script> {#- -#}
+ <script src="{{page.root_path | safe}}crates{{page.resource_suffix}}.js"></script> {#- -#}
+ <noscript> {#- -#}
+ <link rel="stylesheet" {# -#}
+ href="{{static_root_path | safe}}noscript{{page.resource_suffix}}.css"> {#- -#}
+ </noscript> {#- -#}
+ {%- if layout.css_file_extension -%}
+ <link rel="stylesheet" type="text/css" {# -#}
+ href="{{static_root_path | safe}}theme{{page.resource_suffix}}.css"> {#- -#}
+ {%- endif -%}
+ {%- if layout.favicon -%}
+ <link rel="shortcut icon" href="{{layout.favicon}}"> {#- -#}
+ {%- else -%}
+ <link rel="icon" type="image/svg+xml" {# -#}
+ href="{{static_root_path | safe}}favicon{{page.resource_suffix}}.svg"> {#- -#}
+ <link rel="alternate icon" type="image/png" {# -#}
+ href="{{static_root_path | safe}}favicon-16x16{{page.resource_suffix}}.png"> {#- -#}
+ <link rel="alternate icon" type="image/png" {# -#}
+ href="{{static_root_path | safe}}favicon-32x32{{page.resource_suffix}}.png"> {#- -#}
+ {%- endif -%}
+ {{- layout.external_html.in_header | safe -}}
+ <style type="text/css"> {#- -#}
+ #crate-search{ {#- -#}
+ background-image:url("{{static_root_path | safe}}down-arrow{{page.resource_suffix}}.svg"); {#- -#}
+ } {#- -#}
+ </style> {#- -#}
+</head> {#- -#}
+<body class="rustdoc {{page.css_class}}"> {#- -#}
+ <!--[if lte IE 11]> {#- -#}
+ <div class="warning"> {#- -#}
+ This old browser is unsupported and will most likely display funky things. {#- -#}
+ </div> {#- -#}
+ <![endif]--> {#- -#}
+ {{- layout.external_html.before_content | safe -}}
+ <nav class="sidebar"> {#- -#}
+ <div class="sidebar-menu" role="button">☰</div> {#- -#}
+ <a href='{{page.root_path | safe}}{{krate_with_trailing_slash | safe}}index.html'> {#- -#}
+ <div class='logo-container rust-logo'> {#- -#}
+ <img src='
+ {%- if layout.logo -%}
+ {{layout.logo}}
+ {%- else -%}
+ {{static_root_path | safe}}rust-logo{{page.resource_suffix}}.png
+ {%- endif -%}
+ ' alt='logo'> {#- -#}
+ </div> {#- -#}
+ </a> {#- -#}
+ {{- sidebar | safe -}}
+ </nav> {#- -#}
+ <div class="theme-picker"> {#- -#}
+ <button id="theme-picker" aria-label="Pick another theme!" aria-haspopup="menu" title="themes"> {#- -#}
+ <img width="18" height="18" alt="Pick another theme!" {# -#}
+ src="{{static_root_path | safe}}brush{{page.resource_suffix}}.svg"> {#- -#}
+ </button> {#- -#}
+ <div id="theme-choices" role="menu"></div> {#- -#}
+ </div> {#- -#}
+ <nav class="sub"> {#- -#}
+ <form class="search-form"> {#- -#}
+ <div class="search-container"> {#- -#}
+ <div>{%- if layout.generate_search_filter -%}
+ <select id="crate-search"> {#- -#}
+ <option value="All crates">All crates</option> {#- -#}
+ </select> {#- -#}
+ {%- endif -%}
+ <input {# -#}
+ class="search-input"{# -#}
+ name="search" {# -#}
+ disabled {# -#}
+ autocomplete="off" {# -#}
+ spellcheck="false" {# -#}
+ placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#}
+ type="search"> {#- -#}
+ </div> {#- -#}
+ <button type="button" id="help-button" title="help">?</button> {#- -#}
+ <a id="settings-menu" href="{{page.root_path | safe}}settings.html" title="settings"> {#- -#}
+ <img width="18" height="18" alt="Change settings" {# -#}
+ src="{{static_root_path | safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
+ </a> {#- -#}
+ </div> {#- -#}
+ </form> {#- -#}
+ </nav> {#- -#}
+ <section id="main" class="content">{{- content | safe -}}</section> {#- -#}
+ <section id="search" class="content hidden"></section> {#- -#}
+ {{- layout.external_html.after_content | safe -}}
+ <div id="rustdoc-vars" {# -#}
+ data-root-path="{{page.root_path | safe}}" {# -#}
+ data-current-crate="{{layout.krate}}" {# -#}
+ data-search-index-js="{{page.root_path | safe}}search-index{{page.resource_suffix}}.js" {# -#}
+ data-search-js="{{static_root_path | safe}}search{{page.resource_suffix}}.js"> {#- -#}
+ </div>
+ <script src="{{static_root_path | safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
+ {%- for script in page.static_extra_scripts -%}
+ <script src="{{static_root_path | safe}}{{script}}.js"></script> {#- -#}
+ {% endfor %}
+ {%- for script in page.extra_scripts -%}
+ <script src="{{page.root_path | safe}}{{script}}.js"></script> {#- -#}
+ {% endfor %}
+</body> {#- -#}
+</html> {#- -#}
goto: file://|DOC_PATH|/test_docs/index.html
click: ".srclink"
-assert: (".line-numbers", 1)
+assert-count: (".line-numbers", 1)
goto: ./fn.check_list_code_block.html
// If the codeblock is the first element of the docblock, the information tooltip must have
// have some top margin to avoid going over the toggle (the "[+]").
-assert: (".docblock > .information > .compile_fail", { "margin-top": "16px" })
+assert-css: (".docblock > .information > .compile_fail", { "margin-top": "16px" })
// Checks that the other codeblocks don't have this top margin.
-assert: ("ol > li > .information > .compile_fail", { "margin-top": "0px" })
-assert: ("ol > li > .information > .ignore", { "margin-top": "0px" })
-assert: (".docblock > .information > .ignore", { "margin-top": "0px" })
+assert-css: ("ol > li > .information > .compile_fail", { "margin-top": "0px" })
+assert-css: ("ol > li > .information > .ignore", { "margin-top": "0px" })
+assert-css: (".docblock > .information > .ignore", { "margin-top": "0px" })
click: "#sidebar-toggle"
wait-for: 500
fail: true
-assert: ("#source-sidebar", { "left": "-300px" })
+assert-css: ("#source-sidebar", { "left": "-300px" })
// First, we check that the search results are hidden when the Escape key is pressed.
write: (".search-input", "test")
wait-for: "#search > h1" // The search element is empty before the first search
-assert: ("#search", "class", "content")
-assert: ("#main", "class", "content hidden")
+assert-attr: ("#search", {"class": "content"})
+assert-attr: ("#main", {"class": "content hidden"})
press-key: "Escape"
-assert: ("#search", "class", "content hidden")
-assert: ("#main", "class", "content")
+assert-attr: ("#search", {"class": "content hidden"})
+assert-attr: ("#main", {"class": "content"})
// Check that focusing the search input brings back the search results
focus: ".search-input"
-assert: ("#search", "class", "content")
-assert: ("#main", "class", "content hidden")
+assert-attr: ("#search", {"class": "content"})
+assert-attr: ("#main", {"class": "content hidden"})
// Now let's check that when the help popup is displayed and we press Escape, it doesn't
// hide the search results too.
click: "#help-button"
-assert: ("#help", "class", "")
+assert-attr: ("#help", {"class": ""})
press-key: "Escape"
-assert: ("#help", "class", "hidden")
-assert: ("#search", "class", "content")
-assert: ("#main", "class", "content hidden")
+assert-attr: ("#help", {"class": "hidden"})
+assert-attr: ("#search", {"class": "content"})
+assert-attr: ("#main", {"class": "content hidden"})
// Check that Escape hides the search results when a search result is focused.
focus: ".search-input"
assert-false: ".search-input:focus"
assert: "#results a:focus"
press-key: "Escape"
-assert: ("#help", "class", "hidden")
-assert: ("#search", "class", "content hidden")
-assert: ("#main", "class", "content")
+assert-attr: ("#help", {"class": "hidden"})
+assert-attr: ("#search", {"class": "content hidden"})
+assert-attr: ("#main", {"class": "content"})
goto: file://|DOC_PATH|/lib2/struct.Foo.html
// This test checks that the font weight is correctly applied.
-assert: ("//*[@class='docblock type-decl']//a[text()='Alias']", {"font-weight": "400"})
-assert: ("//*[@class='structfield small-section-header']//a[text()='Alias']", {"font-weight": "400"})
-assert: ("#method\.a_method > code", {"font-weight": "600"})
-assert: ("#associatedtype\.X > code", {"font-weight": "600"})
-assert: ("#associatedconstant\.Y > code", {"font-weight": "600"})
+assert-css: ("//*[@class='docblock type-decl']//a[text()='Alias']", {"font-weight": "400"})
+assert-css: ("//*[@class='structfield small-section-header']//a[text()='Alias']", {"font-weight": "400"})
+assert-css: ("#method\.a_method > code", {"font-weight": "600"})
+assert-css: ("#associatedtype\.X > code", {"font-weight": "600"})
+assert-css: ("#associatedconstant\.Y > code", {"font-weight": "600"})
// This test ensures that the element corresponding to the hash is displayed.
goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.borrow
// In the blanket implementations list, "Borrow" is the second one, hence the ":nth(2)".
-assert: ("#blanket-implementations-list > details:nth-child(2)", "open", "")
+assert-attr: ("#blanket-implementations-list > details:nth-child(2)", {"open": ""})
// We first check that the impl block is open by default.
-assert: ("#implementations + details", "open", "")
+assert-attr: ("#implementations + details", {"open": ""})
// We collapse it.
click: "#implementations + details > summary"
// We check that it was collapsed as expected.
-assert-false: ("#implementations + details", "open", "")
+assert-attr-false: ("#implementations + details", {"open": ""})
// To ensure that we will click on the currently hidden method.
-assert: (".sidebar-links > a", "must_use")
+assert-text: (".sidebar-links > a", "must_use")
click: ".sidebar-links > a"
// We check that the impl block was opened as expected so that we can see the method.
-assert: ("#implementations + details", "open", "")
+assert-attr: ("#implementations + details", {"open": ""})
// This test ensures that the impl blocks are open by default.
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
-assert: ("#main > details.implementors-toggle", "open", "")
+assert-attr: ("#main > details.implementors-toggle", {"open": ""})
// Waiting for the search results to appear...
wait-for: "#titles"
// Checking that the colors for the alias element are the ones expected.
-assert: (".result-name > .alias", {"color": "rgb(255, 255, 255)"})
-assert: (".result-name > .alias > .grey", {"color": "rgb(204, 204, 204)"})
+assert-css: (".result-name > .alias", {"color": "rgb(255, 255, 255)"})
+assert-css: (".result-name > .alias > .grey", {"color": "rgb(204, 204, 204)"})
goto: file://|DOC_PATH|/test_docs/index.html?search=some_more_function
// Waiting for the search results to appear...
wait-for: "#titles"
-assert: (".search-results .desc code", "format!")
+assert-text: (".search-results .desc code", "format!")
wait-for: "#titles"
// The width is returned by "getComputedStyle" which returns the exact number instead of the
// CSS rule which is "50%"...
-assert: (".search-results div.desc", {"width": "320px"})
+assert-css: (".search-results div.desc", {"width": "320px"})
size: (600, 100)
// As counter-intuitive as it may seem, in this width, the width is "100%", which is why
// when computed it's larger.
-assert: (".search-results div.desc", {"width": "570px"})
+assert-css: (".search-results div.desc", {"width": "570px"})
// less good.
//
// Checking that the CSS is displaying " (keyword)" in italic.
-assert: (".result-name span.keyword > i", "(keyword)")
-assert: (".result-name span.keyword", "CookieMonster (keyword)")
+assert-text: (".result-name span.keyword > i", "(keyword)")
+assert-text: (".result-name span.keyword", "CookieMonster (keyword)")
write: (".search-input", "Foo")
// Waiting for the search results to appear...
wait-for: "#titles"
-assert: ("#titles > button:nth-of-type(1)", "class", "selected")
+assert-attr: ("#titles > button:nth-of-type(1)", {"class": "selected"})
// To go back to the original "state"
goto: file://|DOC_PATH|/test_docs/index.html
// Waiting for the search results to appear...
wait-for: "#titles"
// With this search, only the last tab shouldn't be empty so it should be selected.
-assert: ("#titles > button:nth-of-type(3)", "class", "selected")
+assert-attr: ("#titles > button:nth-of-type(3)", {"class": "selected"})
// To go back to the original "state"
goto: file://|DOC_PATH|/test_docs/index.html
// Waiting for the search results to appear...
wait-for: "#titles"
// With this search, all the tabs are empty so the first one should remain selected.
-assert: ("#titles > button:nth-of-type(1)", "class", "selected")
+assert-attr: ("#titles > button:nth-of-type(1)", {"class": "selected"})
assert-false: "input.search-input:focus"
// We now check for the help popup.
press-key: "?"
-assert: ("#help", {"display": "flex"})
+assert-css: ("#help", {"display": "flex"})
assert-false: "#help.hidden"
press-key: "Escape"
-assert: ("#help.hidden", {"display": "none"})
+assert-css: ("#help.hidden", {"display": "none"})
// Check for the themes list.
-assert: ("#theme-choices", {"display": "none"})
+assert-css: ("#theme-choices", {"display": "none"})
press-key: "t"
-assert: ("#theme-choices", {"display": "block"})
+assert-css: ("#theme-choices", {"display": "block"})
press-key: "t"
// We ensure that 't' hides back the menu.
-assert: ("#theme-choices", {"display": "none"})
+assert-css: ("#theme-choices", {"display": "none"})
press-key: "t"
-assert: ("#theme-choices", {"display": "block"})
+assert-css: ("#theme-choices", {"display": "block"})
press-key: "Escape"
// We ensure that 'Escape' hides the menu too.
-assert: ("#theme-choices", {"display": "none"})
+assert-css: ("#theme-choices", {"display": "none"})
goto: file://|DOC_PATH|/test_docs/index.html
-assert: (".sidebar > .location", "Crate test_docs")
+assert-text: (".sidebar > .location", "Crate test_docs")
// In modules, we only have one "location" element.
-assert: (".sidebar .location", 1)
-assert: (".sidebar-elems > #all-types", "See all test_docs's items")
+assert-count: (".sidebar .location", 1)
+assert-text: (".sidebar-elems > #all-types", "See all test_docs's items")
// We check that we have the crates list and that the "current" on is "test_docs".
-assert: (".sidebar-elems > .crate > ul > li > a.current", "test_docs")
+assert-text: (".sidebar-elems > .crate > ul > li > a.current", "test_docs")
// And we're also supposed to have the list of items in the current module.
-assert: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
-assert: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
-assert: (".sidebar-elems > .items > ul > li:nth-child(3)", "Enums")
-assert: (".sidebar-elems > .items > ul > li:nth-child(4)", "Traits")
-assert: (".sidebar-elems > .items > ul > li:nth-child(5)", "Functions")
-assert: (".sidebar-elems > .items > ul > li:nth-child(6)", "Type Definitions")
-assert: (".sidebar-elems > .items > ul > li:nth-child(7)", "Keywords")
-assert: ("#structs + table td > a", "Foo")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Enums")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Traits")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Functions")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(6)", "Type Definitions")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(7)", "Keywords")
+assert-text: ("#structs + table td > a", "Foo")
click: "#structs + table td > a"
// PAGE: struct.Foo.html
-assert: (".sidebar .location", 2)
+assert-count: (".sidebar .location", 2)
// We check that there is no crate listed outside of the top level.
assert-false: ".sidebar-elems > .crate"
// We now go back to the crate page to click on the "lib2" crate link.
// PAGE: lib2/index.html
goto: file://|DOC_PATH|/lib2/index.html
-assert: (".sidebar > .location", "Crate lib2")
+assert-text: (".sidebar > .location", "Crate lib2")
// We check that we have the crates list and that the "current" on is now "lib2".
-assert: (".sidebar-elems > .crate > ul > li > a.current", "lib2")
+assert-text: (".sidebar-elems > .crate > ul > li > a.current", "lib2")
// We now go to the "foobar" function page.
-assert: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
-assert: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
-assert: (".sidebar-elems > .items > ul > li:nth-child(3)", "Traits")
-assert: (".sidebar-elems > .items > ul > li:nth-child(4)", "Functions")
-assert: (".sidebar-elems > .items > ul > li:nth-child(5)", "Type Definitions")
-assert: ("#functions + table td > a", "foobar")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Traits")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Functions")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Type Definitions")
+assert-text: ("#functions + table td > a", "foobar")
click: "#functions + table td > a"
// PAGE: fn.foobar.html
// In items containing no items (like functions or constants) and in modules, we have one
// "location" elements.
-assert: (".sidebar .location", 1)
+assert-count: (".sidebar .location", 1)
// There is a "<br>" tag between "in" and "lib2", but it doesn't count as a space.
-assert: (".sidebar .sidebar-elems .location", "Other items inlib2")
+assert-text: (".sidebar .sidebar-elems .location", "Other items inlib2")
// We check that we don't have the crate list.
assert-false: ".sidebar-elems > .crate"
goto: ./module/index.html
-assert: (".sidebar > .location", "Module module")
+assert-text: (".sidebar > .location", "Module module")
// We check that we don't have the crate list.
assert-false: ".sidebar-elems > .crate"
goto: ./sub_module/sub_sub_module/index.html
-assert: (".sidebar > .location", "Module sub_sub_module")
+assert-text: (".sidebar > .location", "Module sub_sub_module")
// We check that we don't have the crate list.
assert-false: ".sidebar-elems > .crate"
-assert: (".sidebar-elems > .items > ul > li:nth-child(1)", "Functions")
-assert: ("#functions + table td > a", "foo")
+assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Functions")
+assert-text: ("#functions + table td > a", "foo")
click: (40, 224) // This is the position of the span for line 4.
// Unfortunately, "#4" isn't a valid query selector, so we have to go around that limitation
// by instead getting the nth span.
-assert: (".line-numbers > span:nth-child(4)", "class", "line-highlighted")
+assert-attr: (".line-numbers > span:nth-child(4)", {"class": "line-highlighted"})
// We now check that the good spans are highlighted
goto: file://|DOC_PATH|/src/test_docs/lib.rs.html#4-6
-assert-false: (".line-numbers > span:nth-child(3)", "class", "line-highlighted")
-assert: (".line-numbers > span:nth-child(4)", "class", "line-highlighted")
-assert: (".line-numbers > span:nth-child(5)", "class", "line-highlighted")
-assert: (".line-numbers > span:nth-child(6)", "class", "line-highlighted")
-assert-false: (".line-numbers > span:nth-child(7)", "class", "line-highlighted")
+assert-attr-false: (".line-numbers > span:nth-child(3)", {"class": "line-highlighted"})
+assert-attr: (".line-numbers > span:nth-child(4)", {"class": "line-highlighted"})
+assert-attr: (".line-numbers > span:nth-child(5)", {"class": "line-highlighted"})
+assert-attr: (".line-numbers > span:nth-child(6)", {"class": "line-highlighted"})
+assert-attr-false: (".line-numbers > span:nth-child(7)", {"class": "line-highlighted"})
click: "#theme-choices > button:first-child"
wait-for: 500
// should be the ayu theme so let's check the color
-assert: ("body", { "background-color": "rgb(15, 20, 25)" })
+assert-css: ("body", { "background-color": "rgb(15, 20, 25)" })
click: "#theme-choices > button:last-child"
wait-for: 500
// should be the light theme so let's check the color
-assert: ("body", { "background-color": "rgb(255, 255, 255)" })
+assert-css: ("body", { "background-color": "rgb(255, 255, 255)" })
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
size: (433, 600)
-assert: (".top-doc", "open", "")
+assert-attr: (".top-doc", {"open": ""})
click: (4, 280) // This is the position of the top doc comment toggle
-assert-false: (".top-doc", "open", "")
+assert-attr-false: (".top-doc", {"open": ""})
click: (4, 280)
-assert: (".top-doc", "open", "")
+assert-attr: (".top-doc", {"open": ""})
// To ensure that the toggle isn't over the text, we check that the toggle isn't clicked.
click: (3, 280)
-assert: (".top-doc", "open", "")
+assert-attr: (".top-doc", {"open": ""})
// Now we do the same but with a little bigger width
size: (600, 600)
-assert: (".top-doc", "open", "")
+assert-attr: (".top-doc", {"open": ""})
click: (4, 240) // New Y position since all search elements are back on one line.
-assert-false: (".top-doc", "open", "")
+assert-attr-false: (".top-doc", {"open": ""})
click: (4, 240)
-assert: (".top-doc", "open", "")
+assert-attr: (".top-doc", {"open": ""})
// To ensure that the toggle isn't over the text, we check that the toggle isn't clicked.
click: (3, 240)
-assert: (".top-doc", "open", "")
+assert-attr: (".top-doc", {"open": ""})
goto: file://|DOC_PATH|/test_docs/index.html
-assert: ("#main > details.top-doc", "open", "")
+assert-attr: ("#main > details.top-doc", {"open": ""})
click: "#toggle-all-docs"
wait-for: 1000
// This is now collapsed so there shouldn't be the "open" attribute on details.
-assert-false: ("#main > details.top-doc", "open", "")
+assert-attr-false: ("#main > details.top-doc", {"open": ""})
click: "#toggle-all-docs"
wait-for: 1000
// Not collapsed anymore so the "open" attribute should be back.
-assert: ("#main > details.top-doc", "open", "")
+assert-attr: ("#main > details.top-doc", {"open": ""})
// has all the implementations toggled open by default, so users can
// find method names in those implementations with Ctrl-F.
goto: file://|DOC_PATH|/test_docs/struct.Foo.html
-assert: (".rustdoc-toggle.implementors-toggle", "open", "")
+assert-attr: (".rustdoc-toggle.implementors-toggle", {"open": ""})
goto: file://|DOC_PATH|/test_docs/trait.AnotherOne.html
-assert: (".sidebar-links a:nth-of-type(1)", "another")
-assert: (".sidebar-links a:nth-of-type(2)", "func1")
-assert: (".sidebar-links a:nth-of-type(3)", "func2")
-assert: (".sidebar-links a:nth-of-type(4)", "func3")
-assert: (".sidebar-links a:nth-of-type(5)", "hello")
-assert: (".sidebar-links a:nth-of-type(6)", "why_not")
+assert-text: (".sidebar-links a:nth-of-type(1)", "another")
+assert-text: (".sidebar-links a:nth-of-type(2)", "func1")
+assert-text: (".sidebar-links a:nth-of-type(3)", "func2")
+assert-text: (".sidebar-links a:nth-of-type(4)", "func3")
+assert-text: (".sidebar-links a:nth-of-type(5)", "hello")
+assert-text: (".sidebar-links a:nth-of-type(6)", "why_not")
--- /dev/null
+use std::ops::Deref;
+
+pub struct A {}
+impl A { pub fn foo_a(&self) {} }
+
+pub struct B {}
+impl B { pub fn foo_b(&self) {} }
+
+pub struct C {}
+impl C { pub fn foo_c(&self) {} }
+
+// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_b'
+impl Deref for A {
+ type Target = B;
+ fn deref(&self) -> &B { todo!() }
+}
+
+// @!has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c'
+impl Deref for B {
+ type Target = C;
+ fn deref(&self) -> &C { todo!() }
+}
--- /dev/null
+use std::ops::Deref;
+
+pub struct A;
+pub struct B;
+
+// @has recursive_deref/struct.A.html '//code' 'impl Deref for A'
+impl Deref for A {
+ type Target = B;
+
+ fn deref(&self) -> &Self::Target {
+ panic!()
+ }
+}
+
+// @has recursive_deref/struct.B.html '//code' 'impl Deref for B'
+impl Deref for B {
+ type Target = A;
+
+ fn deref(&self) -> &Self::Target {
+ panic!()
+ }
+}
fn foo() {
let x: &[_] = &[Foo, Foo];
- &x[3..4];
+ let _ = &x[3..4];
}
fn main() {
fn foo() {
let x: &[_] = &[Foo, Foo];
- &x[3..bar()];
+ let _ = &x[3..bar()];
}
fn main() {
fn main() {
let mut x = Foo;
- &x[..];
- &x[Foo..];
- &x[..Foo];
- &x[Foo..Foo];
- &mut x[..];
- &mut x[Foo..];
- &mut x[..Foo];
- &mut x[Foo..Foo];
+ let _ = &x[..];
+ let _ = &x[Foo..];
+ let _ = &x[..Foo];
+ let _ = &x[Foo..Foo];
+ let _ = &mut x[..];
+ let _ = &mut x[Foo..];
+ let _ = &mut x[..Foo];
+ let _ = &mut x[Foo..Foo];
unsafe {
assert_eq!(COUNT, 8);
}
// works:
//
// let n = N;
- // &n;
+ // let _ = &n;
- &N;
+ let _ = &N;
}
fn main() {
// Make sure we error with the right kind of error on a too large slice.
const TEST: () = { unsafe {
let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
- let _val = &*slice; //~ ERROR: any use of this value will cause an error
+ let _val = &*slice; //~ ERROR: evaluation of constant value failed
//~| slice is bigger than largest supported object
- //~| WARN this was previously accepted by the compiler but is being phased out
} };
fn main() {}
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/dangling.rs:8:16
|
-LL | / const TEST: () = { unsafe {
-LL | | let slice: *const [u8] = mem::transmute((1usize, usize::MAX));
-LL | | let _val = &*slice;
- | | ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object
-LL | |
-LL | |
-LL | | } };
- | |____-
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | let _val = &*slice;
+ | ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0080`.
const fn foo() -> i32 {
unsafe {
let _ = intrinsics::const_allocate(4, 3) as * mut i32;
- //~^ error: any use of this value will cause an error [const_err]
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ error: evaluation of constant value failed
}
1
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/alloc_intrinsic_errors.rs:10:17
|
LL | const FOO: i32 = foo();
- | -----------------------
+ | ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:7:18
...
LL | let _ = intrinsics::const_allocate(4, 3) as * mut i32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| align has to be a power of 2, `3` is not a power of 2
| inside `foo` at $DIR/alloc_intrinsic_errors.rs:10:17
- | inside `FOO` at $DIR/alloc_intrinsic_errors.rs:7:18
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0080`.
unsafe { transmute(&x) }
}
const X: u64 = *wat(42);
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
fn main() {
println!("{}", X);
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/issue-49296.rs:19:16
|
LL | const X: u64 = *wat(42);
- | ---------------^^^^^^^^-
- | |
- | pointer to alloc1 was dereferenced after this allocation got freed
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^ pointer to alloc1 was dereferenced after this allocation got freed
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0080`.
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/ub-incorrect-vtable.rs:19:14
|
-LL | / const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
-LL | | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
- | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
- | |
- | invalid vtable: alignment `1000` is not a power of 2
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: alignment `1000` is not a power of 2
-error: any use of this value will cause an error
- --> $DIR/ub-incorrect-vtable.rs:25:14
- |
-LL | / const INVALID_VTABLE_SIZE: &dyn Trait =
-LL | | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
- | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
- | |
- | invalid vtable: size is bigger than largest supported object
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-incorrect-vtable.rs:24:14
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: size is bigger than largest supported object
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-incorrect-vtable.rs:36:1
+ --> $DIR/ub-incorrect-vtable.rs:34:1
|
LL | / const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-incorrect-vtable.rs:41:1
+ --> $DIR/ub-incorrect-vtable.rs:39:1
|
LL | / const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) };
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/ub-incorrect-vtable.rs:19:14
|
-LL | / const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
-LL | | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
- | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
- | |
- | invalid vtable: alignment `1000` is not a power of 2
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: alignment `1000` is not a power of 2
-error: any use of this value will cause an error
- --> $DIR/ub-incorrect-vtable.rs:25:14
- |
-LL | / const INVALID_VTABLE_SIZE: &dyn Trait =
-LL | | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
- | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__-
- | |
- | invalid vtable: size is bigger than largest supported object
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-incorrect-vtable.rs:24:14
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid vtable: size is bigger than largest supported object
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-incorrect-vtable.rs:36:1
+ --> $DIR/ub-incorrect-vtable.rs:34:1
|
LL | / const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-incorrect-vtable.rs:41:1
+ --> $DIR/ub-incorrect-vtable.rs:39:1
|
LL | / const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
LL | | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) };
const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
-//~^ ERROR any use of this value will cause an error
-//~| WARNING this was previously accepted by the compiler
+//~^ ERROR evaluation of constant value failed
//~| invalid vtable: alignment `1000` is not a power of 2
const INVALID_VTABLE_SIZE: &dyn Trait =
unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
-//~^ ERROR any use of this value will cause an error
-//~| WARNING this was previously accepted by the compiler
+//~^ ERROR evaluation of constant value failed
//~| invalid vtable: size is bigger than largest supported object
#[repr(transparent)]
00 00 00 00 │ ....
}
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/ub-nonnull.rs:19:30
|
-LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
-LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
-LL | | // Use address-of-element for pointer arithmetic. This could wrap around to null!
-LL | | let out_of_bounds_ptr = &ptr[255];
- | | ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
-LL | |
-LL | | mem::transmute(out_of_bounds_ptr)
-LL | | } };
- | |____-
- |
-note: the lint level is defined here
- --> $DIR/ub-nonnull.rs:15:8
- |
-LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | let out_of_bounds_ptr = &ptr[255];
+ | ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:24:1
+ --> $DIR/ub-nonnull.rs:23:1
|
LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:26:1
+ --> $DIR/ub-nonnull.rs:25:1
|
LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:34:1
+ --> $DIR/ub-nonnull.rs:33:1
|
LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:42:1
+ --> $DIR/ub-nonnull.rs:41:1
|
LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:48:1
+ --> $DIR/ub-nonnull.rs:47:1
|
LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
00 00 00 00 00 00 00 00 │ ........
}
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/ub-nonnull.rs:19:30
|
-LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
-LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
-LL | | // Use address-of-element for pointer arithmetic. This could wrap around to null!
-LL | | let out_of_bounds_ptr = &ptr[255];
- | | ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
-LL | |
-LL | | mem::transmute(out_of_bounds_ptr)
-LL | | } };
- | |____-
- |
-note: the lint level is defined here
- --> $DIR/ub-nonnull.rs:15:8
- |
-LL | #[deny(const_err)] // this triggers a `const_err` so validation does not even happen
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | let out_of_bounds_ptr = &ptr[255];
+ | ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:24:1
+ --> $DIR/ub-nonnull.rs:23:1
|
LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:26:1
+ --> $DIR/ub-nonnull.rs:25:1
|
LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:34:1
+ --> $DIR/ub-nonnull.rs:33:1
|
LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered uninitialized bytes, but expected initialized plain (non-pointer) bytes
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:42:1
+ --> $DIR/ub-nonnull.rs:41:1
|
LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something in the range 10..=30
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:48:1
+ --> $DIR/ub-nonnull.rs:47:1
|
LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 20, but expected something less or equal to 10, or greater or equal to 30
const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
// Use address-of-element for pointer arithmetic. This could wrap around to null!
- let out_of_bounds_ptr = &ptr[255]; //~ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ let out_of_bounds_ptr = &ptr[255]; //~ ERROR evaluation of constant value failed
mem::transmute(out_of_bounds_ptr)
} };
-warning: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/validate_uninhabited_zsts.rs:5:14
|
LL | unsafe { std::mem::transmute(()) }
| |
| transmuting to uninhabited type
| inside `foo` at $DIR/validate_uninhabited_zsts.rs:5:14
- | inside `FOO` at $DIR/validate_uninhabited_zsts.rs:15:26
...
LL | const FOO: [Empty; 3] = [foo(); 3];
- | -----------------------------------
- |
-note: the lint level is defined here
- --> $DIR/validate_uninhabited_zsts.rs:14:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:14:26
error[E0080]: it is undefined behavior to use this value
- --> $DIR/validate_uninhabited_zsts.rs:18:1
+ --> $DIR/validate_uninhabited_zsts.rs:17:1
|
LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty
= note: the `!` type has no valid value
warning: the type `Empty` does not permit zero-initialization
- --> $DIR/validate_uninhabited_zsts.rs:18:35
+ --> $DIR/validate_uninhabited_zsts.rs:17:35
|
LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: enums with no variants have no valid value
-error: aborting due to previous error; 3 warnings emitted
+error: aborting due to 2 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0080`.
-warning: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/validate_uninhabited_zsts.rs:5:14
|
LL | unsafe { std::mem::transmute(()) }
| |
| transmuting to uninhabited type
| inside `foo` at $DIR/validate_uninhabited_zsts.rs:5:14
- | inside `FOO` at $DIR/validate_uninhabited_zsts.rs:15:26
...
LL | const FOO: [Empty; 3] = [foo(); 3];
- | -----------------------------------
- |
-note: the lint level is defined here
- --> $DIR/validate_uninhabited_zsts.rs:14:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:14:26
error[E0080]: it is undefined behavior to use this value
- --> $DIR/validate_uninhabited_zsts.rs:18:1
+ --> $DIR/validate_uninhabited_zsts.rs:17:1
|
LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at [0]: encountered a value of uninhabited type Empty
= note: the `!` type has no valid value
warning: the type `Empty` does not permit zero-initialization
- --> $DIR/validate_uninhabited_zsts.rs:18:35
+ --> $DIR/validate_uninhabited_zsts.rs:17:35
|
LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: enums with no variants have no valid value
-error: aborting due to previous error; 3 warnings emitted
+error: aborting due to 2 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0080`.
const fn foo() -> ! {
unsafe { std::mem::transmute(()) }
- //~^ WARN any use of this value will cause an error [const_err]
+ //~^ ERROR evaluation of constant value failed
//~| WARN the type `!` does not permit zero-initialization [invalid_value]
- //~| WARN this was previously accepted by the compiler but is being phased out
}
#[derive(Clone, Copy)]
// unsigned types:
const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// signed types:
const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// and make sure we capture y < 0:
const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// and that there's no special relation to the value -1 by picking some
// negative values at random:
const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// Repeat it all over for `unchecked_shr`
// unsigned types:
const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// signed types:
const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// and make sure we capture y < 0:
const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// and that there's no special relation to the value -1 by picking some
// negative values at random:
const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// Other arithmetic functions:
const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::MIN, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// capture fault with zero value
const _: u32 = unsafe { std::intrinsics::ctlz_nonzero(0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const _: u32 = unsafe { std::intrinsics::cttz_nonzero(0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
fn main() {}
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:15:29
|
LL | const SHL_U8: u8 = unsafe { intrinsics::unchecked_shl(5_u8, 8) };
- | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 8 in `unchecked_shl`
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:18:31
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:17:31
|
LL | const SHL_U16: u16 = unsafe { intrinsics::unchecked_shl(5_u16, 16) };
- | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 16 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:21:31
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:19:31
|
LL | const SHL_U32: u32 = unsafe { intrinsics::unchecked_shl(5_u32, 32) };
- | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 32 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:24:31
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:21:31
|
LL | const SHL_U64: u64 = unsafe { intrinsics::unchecked_shl(5_u64, 64) };
- | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 64 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:27:33
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:23:33
|
LL | const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
- | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 128 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:33:29
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:28:29
|
LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
- | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 8 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:36:31
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:30:31
|
LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) };
- | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 16 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:39:31
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:32:31
|
LL | const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
- | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 32 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:42:31
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:34:31
|
LL | const SHL_I64: i64 = unsafe { intrinsics::unchecked_shl(5_i64, 64) };
- | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 64 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:45:33
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:36:33
|
LL | const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
- | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 128 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:51:33
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:41:33
|
LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
- | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 255 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:54:35
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:43:35
|
LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) };
- | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 65535 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:57:35
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:45:35
|
LL | const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
- | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 4294967295 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:60:35
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:47:35
|
LL | const SHL_I64_NEG: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -1) };
- | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 18446744073709551615 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:63:37
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:49:37
|
LL | const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
- | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:70:40
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:55:40
|
LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
- | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 250 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:73:42
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:57:42
|
LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) };
- | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 65523 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:76:42
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:59:42
|
LL | const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
- | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 4294967271 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:79:42
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:61:42
|
LL | const SHL_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shl(5_i64, -30) };
- | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 18446744073709551586 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:82:44
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:63:44
|
LL | const SHL_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -93) };
- | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shl`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:90:29
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:70:29
|
LL | const SHR_U8: u8 = unsafe { intrinsics::unchecked_shr(5_u8, 8) };
- | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 8 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:93:31
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:72:31
|
LL | const SHR_U16: u16 = unsafe { intrinsics::unchecked_shr(5_u16, 16) };
- | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 16 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:96:31
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:74:31
|
LL | const SHR_U32: u32 = unsafe { intrinsics::unchecked_shr(5_u32, 32) };
- | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 32 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:99:31
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:76:31
|
LL | const SHR_U64: u64 = unsafe { intrinsics::unchecked_shr(5_u64, 64) };
- | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 64 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:102:33
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:78:33
|
LL | const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
- | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 128 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:108:29
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:83:29
|
LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
- | ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 8 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 8 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:111:31
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:85:31
|
LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) };
- | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 16 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:114:31
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:87:31
|
LL | const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
- | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 32 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 32 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:117:31
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:89:31
|
LL | const SHR_I64: i64 = unsafe { intrinsics::unchecked_shr(5_i64, 64) };
- | ------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 64 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 64 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:120:33
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:91:33
|
LL | const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
- | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 128 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 128 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:126:33
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:96:33
|
LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
- | --------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 255 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 255 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:129:35
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:98:35
|
LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) };
- | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 65535 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65535 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:132:35
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:100:35
|
LL | const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
- | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 4294967295 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967295 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:135:35
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:102:35
|
LL | const SHR_I64_NEG: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -1) };
- | ----------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 18446744073709551615 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551615 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:138:37
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:104:37
|
LL | const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
- | ------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211455 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:145:40
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:110:40
|
LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
- | ---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 250 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 250 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:148:42
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:112:42
|
LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) };
- | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 65523 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 65523 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:151:42
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:114:42
|
LL | const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
- | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 4294967271 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 4294967271 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:154:42
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:116:42
|
LL | const SHR_I64_NEG_RANDOM: i64 = unsafe { intrinsics::unchecked_shr(5_i64, -30) };
- | -----------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 18446744073709551586 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 18446744073709551586 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:157:44
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:118:44
|
LL | const SHR_I128_NEG_RANDOM: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -93) };
- | -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 340282366920938463463374607431768211363 in `unchecked_shr`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:163:25
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:123:25
|
LL | const _: u16 = unsafe { std::intrinsics::unchecked_add(40000u16, 30000) };
- | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflow executing `unchecked_add`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_add`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:167:25
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:126:25
|
LL | const _: u32 = unsafe { std::intrinsics::unchecked_sub(14u32, 22) };
- | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflow executing `unchecked_sub`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_sub`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:171:25
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:129:25
|
LL | const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) };
- | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflow executing `unchecked_mul`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_mul`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:175:25
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:132:25
|
LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) };
- | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | dividing by zero
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dividing by zero
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:178:25
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:134:25
|
LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::MIN, -1) };
- | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflow executing `unchecked_div`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_div`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:182:25
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:137:25
|
LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) };
- | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | calculating the remainder with a divisor of zero
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calculating the remainder with a divisor of zero
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:185:25
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:139:25
|
LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) };
- | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | overflow executing `unchecked_rem`
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow executing `unchecked_rem`
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:191:25
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:144:25
|
LL | const _: u32 = unsafe { std::intrinsics::ctlz_nonzero(0) };
- | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | `ctlz_nonzero` called on 0
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ctlz_nonzero` called on 0
-error: any use of this value will cause an error
- --> $DIR/const-int-unchecked.rs:194:25
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-int-unchecked.rs:146:25
|
LL | const _: u32 = unsafe { std::intrinsics::cttz_nonzero(0) };
- | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
- | |
- | `cttz_nonzero` called on 0
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `cttz_nonzero` called on 0
error: aborting due to 49 previous errors
+For more information about this error, try `rustc --explain E0080`.
-// build-fail
-
+// error-pattern: evaluation of constant value failed
#![feature(const_unreachable_unchecked)]
const unsafe fn foo(x: bool) -> bool {
}
}
-#[warn(const_err)]
const BAR: bool = unsafe { foo(false) };
fn main() {
assert_eq!(BAR, true);
- //~^ ERROR E0080
- //~| ERROR erroneous constant
- //~| WARN this was previously accepted by the compiler but is being phased out
}
-warning: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/hint.rs:LL:COL
|
LL | unsafe { intrinsics::unreachable() }
| |
| entering unreachable code
| inside `unreachable_unchecked` at $SRC_DIR/core/src/hint.rs:LL:COL
- | inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:8:18
- | inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:13:28
|
- ::: $DIR/const_unsafe_unreachable_ub.rs:13:1
+ ::: $DIR/const_unsafe_unreachable_ub.rs:7:18
|
+LL | false => std::hint::unreachable_unchecked(),
+ | ---------------------------------- inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:7:18
+...
LL | const BAR: bool = unsafe { foo(false) };
- | ----------------------------------------
- |
-note: the lint level is defined here
- --> $DIR/const_unsafe_unreachable_ub.rs:12:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error[E0080]: evaluation of constant value failed
- --> $DIR/const_unsafe_unreachable_ub.rs:16:14
- |
-LL | assert_eq!(BAR, true);
- | ^^^ referenced constant has errors
-
-error: erroneous constant used
- --> $DIR/const_unsafe_unreachable_ub.rs:16:3
- |
-LL | assert_eq!(BAR, true);
- | ^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+ | ---------- inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:11:28
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0080`.
#![feature(const_raw_ptr_deref)]
#![feature(const_ptr_offset_from)]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::ptr_offset_from;
#[repr(C)]
struct Struct {
}
pub const DIFFERENT_ALLOC: usize = {
- //~^ NOTE
let uninit = std::mem::MaybeUninit::<Struct>::uninit();
let base_ptr: *const Struct = &uninit as *const _ as *const Struct;
let uninit2 = std::mem::MaybeUninit::<Struct>::uninit();
let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct;
- let offset = unsafe { field_ptr.offset_from(base_ptr) };
+ let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) }; //~ERROR evaluation of constant value failed
+ //~| cannot compute offset of pointers into different allocations.
offset as usize
};
pub const NOT_PTR: usize = {
- //~^ NOTE
unsafe { (42 as *const u8).offset_from(&5u8) as usize }
};
pub const NOT_MULTIPLE_OF_SIZE: isize = {
- //~^ NOTE
let data = [5u8, 6, 7];
let base_ptr = data.as_ptr();
let field_ptr = &data[1] as *const u8 as *const u16;
- unsafe { field_ptr.offset_from(base_ptr as *const u16) }
+ unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) } //~ERROR evaluation of constant value failed
+ //~| 1_isize cannot be divided by 2_isize without remainder
};
pub const OFFSET_FROM_NULL: isize = {
- //~^ NOTE
let ptr = 0 as *const u8;
- unsafe { ptr.offset_from(ptr) }
+ unsafe { ptr_offset_from(ptr, ptr) } //~ERROR evaluation of constant value failed
+ //~| null pointer is not a valid pointer
};
pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC
- //~^ NOTE
let ptr1 = 8 as *const u8;
let ptr2 = 16 as *const u8;
- unsafe { ptr2.offset_from(ptr1) }
+ unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR any use of this value will cause an error
+ //~| WARN previously accepted
};
fn main() {}
-error: any use of this value will cause an error
- --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
-LL | unsafe { intrinsics::ptr_offset_from(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | ptr_offset_from cannot compute offset of pointers into different allocations.
- | inside `ptr::const_ptr::<impl *const Struct>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `DIFFERENT_ALLOC` at $DIR/offset_from_ub.rs:16:27
- |
- ::: $DIR/offset_from_ub.rs:10:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/offset_from_ub.rs:18:27
|
-LL | / pub const DIFFERENT_ALLOC: usize = {
-LL | |
-LL | | let uninit = std::mem::MaybeUninit::<Struct>::uninit();
-LL | | let base_ptr: *const Struct = &uninit as *const _ as *const Struct;
-... |
-LL | | offset as usize
-LL | | };
- | |__-
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from cannot compute offset of pointers into different allocations.
error: any use of this value will cause an error
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
| |
| unable to turn bytes into a pointer
| inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `NOT_PTR` at $DIR/offset_from_ub.rs:22:14
+ | inside `NOT_PTR` at $DIR/offset_from_ub.rs:24:14
|
- ::: $DIR/offset_from_ub.rs:20:1
+ ::: $DIR/offset_from_ub.rs:23:1
|
LL | / pub const NOT_PTR: usize = {
-LL | |
LL | | unsafe { (42 as *const u8).offset_from(&5u8) as usize }
LL | | };
| |__-
|
+ = note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
-LL | unsafe { intrinsics::ptr_offset_from(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | exact_div: 1_isize cannot be divided by 2_isize without remainder
- | inside `ptr::const_ptr::<impl *const u16>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `NOT_MULTIPLE_OF_SIZE` at $DIR/offset_from_ub.rs:30:14
- |
- ::: $DIR/offset_from_ub.rs:25:1
- |
-LL | / pub const NOT_MULTIPLE_OF_SIZE: isize = {
-LL | |
-LL | | let data = [5u8, 6, 7];
-LL | | let base_ptr = data.as_ptr();
-LL | | let field_ptr = &data[1] as *const u8 as *const u16;
-LL | | unsafe { field_ptr.offset_from(base_ptr as *const u16) }
-LL | | };
- | |__-
+error[E0080]: evaluation of constant value failed
+ --> $DIR/offset_from_ub.rs:31:14
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exact_div: 1_isize cannot be divided by 2_isize without remainder
-error: any use of this value will cause an error
- --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
-LL | unsafe { intrinsics::ptr_offset_from(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | null pointer is not a valid pointer for this operation
- | inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `OFFSET_FROM_NULL` at $DIR/offset_from_ub.rs:36:14
- |
- ::: $DIR/offset_from_ub.rs:33:1
- |
-LL | / pub const OFFSET_FROM_NULL: isize = {
-LL | |
-LL | | let ptr = 0 as *const u8;
-LL | | unsafe { ptr.offset_from(ptr) }
-LL | | };
- | |__-
+error[E0080]: evaluation of constant value failed
+ --> $DIR/offset_from_ub.rs:37:14
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | unsafe { ptr_offset_from(ptr, ptr) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ null pointer is not a valid pointer for this operation
error: any use of this value will cause an error
- --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- |
-LL | unsafe { intrinsics::ptr_offset_from(self, origin) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | unable to turn bytes into a pointer
- | inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `DIFFERENT_INT` at $DIR/offset_from_ub.rs:43:14
- |
- ::: $DIR/offset_from_ub.rs:39:1
+ --> $DIR/offset_from_ub.rs:44:14
|
LL | / pub const DIFFERENT_INT: isize = { // offset_from with two different integers: like DIFFERENT_ALLOC
-LL | |
LL | | let ptr1 = 8 as *const u8;
LL | | let ptr2 = 16 as *const u8;
-LL | | unsafe { ptr2.offset_from(ptr1) }
+LL | | unsafe { ptr_offset_from(ptr2, ptr1) }
+ | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn bytes into a pointer
+LL | |
LL | | };
| |__-
|
error: aborting due to 5 previous errors
+For more information about this error, try `rustc --explain E0080`.
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
LL | unsafe { intrinsics::offset(self, count) }
| |
| overflowing in-bounds pointer arithmetic
| inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `BEFORE_START` at $DIR/offset_ub.rs:6:46
|
- ::: $DIR/offset_ub.rs:6:1
+ ::: $DIR/offset_ub.rs:6:46
|
LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) };
- | ------------------------------------------------------------------------------
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ------------------------------ inside `BEFORE_START` at $DIR/offset_ub.rs:6:46
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
LL | unsafe { intrinsics::offset(self, count) }
| |
| pointer arithmetic failed: pointer must be in-bounds at offset 2, but is outside bounds of allocN which has size 1
| inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `AFTER_END` at $DIR/offset_ub.rs:7:43
|
- ::: $DIR/offset_ub.rs:7:1
+ ::: $DIR/offset_ub.rs:7:43
|
LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
- | --------------------------------------------------------------------------
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ----------------------------- inside `AFTER_END` at $DIR/offset_ub.rs:7:43
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
LL | unsafe { intrinsics::offset(self, count) }
| |
| pointer arithmetic failed: pointer must be in-bounds at offset 101, but is outside bounds of allocN which has size 100
| inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `AFTER_ARRAY` at $DIR/offset_ub.rs:8:45
|
- ::: $DIR/offset_ub.rs:8:1
+ ::: $DIR/offset_ub.rs:8:45
|
LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) };
- | ------------------------------------------------------------------------------
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ------------------------------- inside `AFTER_ARRAY` at $DIR/offset_ub.rs:8:45
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
LL | unsafe { intrinsics::offset(self, count) }
| |
| overflowing in-bounds pointer arithmetic
| inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `OVERFLOW` at $DIR/offset_ub.rs:10:43
|
- ::: $DIR/offset_ub.rs:10:1
+ ::: $DIR/offset_ub.rs:10:43
|
LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) };
- | ----------------------------------------------------------------------------------
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ------------------------------------- inside `OVERFLOW` at $DIR/offset_ub.rs:10:43
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
LL | unsafe { intrinsics::offset(self, count) }
| |
| overflowing in-bounds pointer arithmetic
| inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `UNDERFLOW` at $DIR/offset_ub.rs:11:44
|
- ::: $DIR/offset_ub.rs:11:1
+ ::: $DIR/offset_ub.rs:11:44
|
LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) };
- | -----------------------------------------------------------------------------------
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ------------------------------------- inside `UNDERFLOW` at $DIR/offset_ub.rs:11:44
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
LL | unsafe { intrinsics::offset(self, count) }
| |
| overflowing in-bounds pointer arithmetic
| inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:12:56
|
- ::: $DIR/offset_ub.rs:12:1
+ ::: $DIR/offset_ub.rs:12:56
|
LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) };
- | ---------------------------------------------------------------------------------------------
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ----------------------------------- inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:12:56
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
LL | unsafe { intrinsics::offset(self, count) }
| |
| overflowing in-bounds pointer arithmetic
| inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:57
|
- ::: $DIR/offset_ub.rs:13:1
+ ::: $DIR/offset_ub.rs:13:57
|
LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) };
- | --------------------------------------------------------------------------------------
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | --------------------------- inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:57
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
LL | unsafe { intrinsics::offset(self, count) }
| |
| pointer arithmetic failed: pointer must be in-bounds at offset 1, but is outside bounds of allocN which has size 0
| inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:15:50
|
- ::: $DIR/offset_ub.rs:15:1
+ ::: $DIR/offset_ub.rs:15:50
|
LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) };
- | -------------------------------------------------------------------------------
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | --------------------------- inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:15:50
error: any use of this value will cause an error
--> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) };
| ---------------------------------------------------------------------------------------------
|
+ = note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
LL | unsafe { intrinsics::offset(self, count) }
| |
| pointer arithmetic failed: 0x0 is not a valid pointer
| inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:19:50
|
- ::: $DIR/offset_ub.rs:19:1
+ ::: $DIR/offset_ub.rs:19:50
|
LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0) };
- | -------------------------------------------------------------------------------
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | --------------------------- inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:19:50
error: any use of this value will cause an error
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
error: aborting due to 11 previous errors
+For more information about this error, try `rustc --explain E0080`.
const _: *const u8 =
unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
+//~| pointer must be in-bounds
const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
//~^ ERROR any use of this value will cause an error
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
LL | unsafe { intrinsics::offset(self, count) }
| |
| pointer arithmetic failed: pointer must be in-bounds at offset $TWO_WORDS, but is outside bounds of alloc2 which has size $WORD
| inside `ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `_` at $DIR/ptr_comparisons.rs:61:34
|
- ::: $DIR/ptr_comparisons.rs:61:1
+ ::: $DIR/ptr_comparisons.rs:61:34
|
LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
- | -------------------------------------------------------------------
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:61:34
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/ptr_comparisons.rs:64:33
|
-LL | / const _: *const u8 =
-LL | | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
- | |_________________________________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___-
- | |
- | memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD
error: any use of this value will cause an error
--> $DIR/ptr_comparisons.rs:68:27
| |
| cannot cast pointer to integer because it was not created by cast from integer
|
+ = note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to 4 previous errors
+For more information about this error, try `rustc --explain E0080`.
fn main() {
assert_eq!(&S[0], "hello");
- &T[0];
+ let _ = &T[0];
// let x = &x as &Debug;
}
static BAR: _ = "test"; //~ ERROR E0121
-fn main() {
-}
+fn main() {}
yield ();
4i32
};
- &a;
+ let _ = &a;
};
}
}
LL | | // during the yield expression. Type checking will also compute liveness
LL | | // and it should also find out that `a` is not live.
... |
-LL | | &a;
+LL | | let _ = &a;
LL | | };
| |__________^
|
yield;
true
};
- &opt;
+ let _ = &opt;
}
};
}
pub fn parse_summary<R: Read>(_: R, _: &Path) {
let path_from_root = Path::new("");
- Path::new(&iter::repeat("../")
- .take(path_from_root.components().count() - 1)
- .collect::<String>());
+ Path::new(&"../".repeat(path_from_root.components().count() - 1));
}
fn foo() {
+++ /dev/null
-fn main() {
- let i = 5;
- let index = 6;
-
- match i {
- 0..=index => println!("winner"),
- //~^ ERROR runtime values cannot be referenced in patterns
- _ => println!("hello"),
- }
-}
+++ /dev/null
-error[E0080]: runtime values cannot be referenced in patterns
- --> $DIR/issue-27895.rs:6:13
- |
-LL | 0..=index => println!("winner"),
- | ^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
// run-pass
fn main() {
- &&[()][0];
+ let _ = &&[()][0];
println!("{:?}", &[(),()][1]);
}
impl FontTableTagConversions for FontTableTag {
fn tag_to_string(self) {
- &self;
+ let _ = &self;
}
}
fn main() {
// We shouldn't promote this
- &(main as fn() == main as fn());
+ let _ = &(main as fn() == main as fn());
// Also check nested case
- &(&(main as fn()) == &(main as fn()));
+ let _ = &(&(main as fn()) == &(main as fn()));
}
error: values of the type `[u8; 18446744073709551615]` are too big for the current architecture
- --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:12
+ --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:5
|
LL | Bug::V([0; !0]);
- | ^^^^^^^
+ | ^^^^^^^^^^^^^^^
error: aborting due to previous error
--- /dev/null
+#![deny(unused_must_use)]
+
+fn foo(_: i32) -> bool { todo!() }
+
+fn bar() -> &'static i32 {
+ &42;
+ //~^ unused
+
+ &mut foo(42);
+ //~^ unused
+
+ &&42;
+ //~^ unused
+
+ &&mut 42;
+ //~^ unused
+
+ &mut &42;
+ //~^ unused
+
+ let _result = foo(4)
+ && foo(2); // Misplaced semi-colon (perhaps due to reordering of lines)
+ && foo(42);
+ //~^ unused
+
+ let _ = &42; // ok
+
+ &42 // ok
+}
+
+fn main() {
+ let _ = bar();
+}
--- /dev/null
+error: unused borrow that must be used
+ --> $DIR/unused-borrows.rs:6:5
+ |
+LL | &42;
+ | ^^^
+ |
+note: the lint level is defined here
+ --> $DIR/unused-borrows.rs:1:9
+ |
+LL | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: unused borrow that must be used
+ --> $DIR/unused-borrows.rs:9:5
+ |
+LL | &mut foo(42);
+ | ^^^^^^^^^^^^
+
+error: unused borrow that must be used
+ --> $DIR/unused-borrows.rs:12:5
+ |
+LL | &&42;
+ | ^^^^
+
+error: unused borrow that must be used
+ --> $DIR/unused-borrows.rs:15:5
+ |
+LL | &&mut 42;
+ | ^^^^^^^^
+
+error: unused borrow that must be used
+ --> $DIR/unused-borrows.rs:18:5
+ |
+LL | &mut &42;
+ | ^^^^^^^^
+
+error: unused borrow that must be used
+ --> $DIR/unused-borrows.rs:23:5
+ |
+LL | && foo(42);
+ | ^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
--- /dev/null
+// Regression test for #84632: Recursion limit is ignored
+// for builtin macros that eagerly expands.
+
+#![recursion_limit = "15"]
+macro_rules! a {
+ () => ("");
+ (A) => (concat!("", a!()));
+ (A, $($A:ident),*) => (concat!("", a!($($A),*)))
+ //~^ ERROR recursion limit reached
+ //~| HELP consider adding
+}
+
+fn main() {
+ a!(A, A, A, A, A);
+ a!(A, A, A, A, A, A, A, A, A, A, A);
+}
--- /dev/null
+error: recursion limit reached while expanding `concat!`
+ --> $DIR/issue-84632-eager-expansion-recursion-limit.rs:8:28
+ |
+LL | (A, $($A:ident),*) => (concat!("", a!($($A),*)))
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | a!(A, A, A, A, A, A, A, A, A, A, A);
+ | ------------------------------------ in this macro invocation
+ |
+ = help: consider adding a `#![recursion_limit="30"]` attribute to your crate (`issue_84632_eager_expansion_recursion_limit`)
+ = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
#![deny(or_patterns_back_compat)]
#![allow(unused_macros)]
-macro_rules! foo { ($x:pat_param | $y:pat) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-macro_rules! bar { ($($x:pat_param)+ | $($y:pat)+) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+
+macro_rules! foo { ($x:pat_param | $y:pat) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this was previously accepted
+macro_rules! bar { ($($x:pat_param)+ | $($y:pat)+) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this was previously accepted
macro_rules! baz { ($x:pat_param | $y:pat_param) => {} } // should be ok
macro_rules! qux { ($x:pat_param | $y:pat) => {} } // should be ok
-macro_rules! ogg { ($x:pat_param | $y:pat_param) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+macro_rules! ogg { ($x:pat_param | $y:pat_param) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this was previously accepted
macro_rules! match_any {
- ( $expr:expr , $( $( $pat:pat_param )|+ => $expr_arm:expr ),+ ) => { //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+ ( $expr:expr , $( $( $pat:pat_param )|+ => $expr_arm:expr ),+ ) => {
+ //~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+ //~| WARN this was previously accepted
match $expr {
$(
$( $pat => $expr_arm, )+
#![deny(or_patterns_back_compat)]
#![allow(unused_macros)]
-macro_rules! foo { ($x:pat | $y:pat) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
-macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+
+macro_rules! foo { ($x:pat | $y:pat) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this was previously accepted
+macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this was previously accepted
macro_rules! baz { ($x:pat_param | $y:pat_param) => {} } // should be ok
macro_rules! qux { ($x:pat_param | $y:pat) => {} } // should be ok
-macro_rules! ogg { ($x:pat | $y:pat_param) => {} } //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+macro_rules! ogg { ($x:pat | $y:pat_param) => {} }
+//~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+//~| WARN this was previously accepted
macro_rules! match_any {
- ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => { //~ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+ ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
+ //~^ ERROR the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
+ //~| WARN this was previously accepted
match $expr {
$(
$( $pat => $expr_arm, )+
error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
- --> $DIR/macro-or-patterns-back-compat.rs:5:21
+ --> $DIR/macro-or-patterns-back-compat.rs:6:21
|
LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
| ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
|
LL | #![deny(or_patterns_back_compat)]
| ^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+ = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
- --> $DIR/macro-or-patterns-back-compat.rs:6:23
+ --> $DIR/macro-or-patterns-back-compat.rs:9:23
|
LL | macro_rules! bar { ($($x:pat)+ | $($y:pat)+) => {} }
| ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+ = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
- --> $DIR/macro-or-patterns-back-compat.rs:9:21
+ --> $DIR/macro-or-patterns-back-compat.rs:14:21
|
LL | macro_rules! ogg { ($x:pat | $y:pat_param) => {} }
| ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+ = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
- --> $DIR/macro-or-patterns-back-compat.rs:11:26
+ --> $DIR/macro-or-patterns-back-compat.rs:18:26
|
LL | ( $expr:expr , $( $( $pat:pat )|+ => $expr_arm:expr ),+ ) => {
| ^^^^^^^^ help: use pat_param to preserve semantics: `$pat:pat_param`
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+ = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
error: aborting due to 4 previous errors
+++ /dev/null
-fn main() {
- let x = 0;
- match 1 {
- 0 ..= x => {}
- //~^ ERROR runtime values cannot be referenced in patterns
- };
-}
+++ /dev/null
-error[E0080]: runtime values cannot be referenced in patterns
- --> $DIR/non-constant-in-const-path.rs:4:15
- |
-LL | 0 ..= x => {}
- | ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
+++ /dev/null
-fn main() {
- let x = 255u8;
- let 0u8..=x = 0;
- //~^ ERROR runtime values cannot be referenced in patterns
-}
+++ /dev/null
-error[E0080]: runtime values cannot be referenced in patterns
- --> $DIR/issue-68394-let-pat-runtime-value.rs:3:15
- |
-LL | let 0u8..=x = 0;
- | ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
--- /dev/null
+// Checks if we emit `PatternError`s correctly.
+// This is also a regression test for #27895 and #68394.
+
+static FOO: u8 = 10;
+
+fn main() {
+ let x = 0;
+ let 0u8..=x = 0;
+ //~^ ERROR: runtime values cannot be referenced in patterns
+ let 0u8..=FOO = 0;
+ //~^ ERROR: statics cannot be referenced in patterns
+ match 1 {
+ 0 ..= x => {}
+ //~^ ERROR: runtime values cannot be referenced in patterns
+ 0 ..= FOO => {}
+ //~^ ERROR: statics cannot be referenced in patterns
+ };
+}
--- /dev/null
+error[E0080]: runtime values cannot be referenced in patterns
+ --> $DIR/non-constant-in-const-path.rs:8:15
+ |
+LL | let 0u8..=x = 0;
+ | ^
+
+error[E0158]: statics cannot be referenced in patterns
+ --> $DIR/non-constant-in-const-path.rs:10:15
+ |
+LL | let 0u8..=FOO = 0;
+ | ^^^
+
+error[E0080]: runtime values cannot be referenced in patterns
+ --> $DIR/non-constant-in-const-path.rs:13:15
+ |
+LL | 0 ..= x => {}
+ | ^
+
+error[E0158]: statics cannot be referenced in patterns
+ --> $DIR/non-constant-in-const-path.rs:15:15
+ |
+LL | 0 ..= FOO => {}
+ | ^^^
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0080, E0158.
+For more information about an error, try `rustc --explain E0080`.
--- /dev/null
+// Regression test for the ICE described in #83505.
+
+#![crate_type="lib"]
+
+#[repr(simd)]
+//~^ ERROR: attribute should be applied to a struct [E0517]
+//~| ERROR: unsupported representation for zero-variant enum [E0084]
+enum Es {}
+static CLs: Es;
+//~^ ERROR: free static item without body
--- /dev/null
+error: free static item without body
+ --> $DIR/issue-83505-repr-simd.rs:9:1
+ |
+LL | static CLs: Es;
+ | ^^^^^^^^^^^^^^-
+ | |
+ | help: provide a definition for the static: `= <expr>;`
+
+error[E0517]: attribute should be applied to a struct
+ --> $DIR/issue-83505-repr-simd.rs:5:8
+ |
+LL | #[repr(simd)]
+ | ^^^^
+...
+LL | enum Es {}
+ | ---------- not a struct
+
+error[E0084]: unsupported representation for zero-variant enum
+ --> $DIR/issue-83505-repr-simd.rs:5:1
+ |
+LL | #[repr(simd)]
+ | ^^^^^^^^^^^^^
+...
+LL | enum Es {}
+ | ---------- zero-variant enum
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0084, E0517.
+For more information about an error, try `rustc --explain E0084`.
--- /dev/null
+// run-pass
+// ignore-emscripten no processes
+// ignore-sgx no processes
+// ignore-wasm32-bare no unwinding panic
+// ignore-avr no unwinding panic
+// ignore-nvptx64 no unwinding panic
+
+use std::env;
+use std::process::Command;
+
+struct Bomb;
+
+impl Drop for Bomb {
+ fn drop(&mut self) {
+ std::panic::panic_any(Bomb);
+ }
+}
+
+fn main() {
+ let args = env::args().collect::<Vec<_>>();
+ let output = match &args[..] {
+ [me] => Command::new(&me).arg("plant the").output(),
+ [..] => std::panic::panic_any(Bomb),
+ }.expect("running the command should have succeeded");
+ println!("{:#?}", output);
+ let stderr = std::str::from_utf8(&output.stderr);
+ assert!(stderr.map(|v| {
+ v.ends_with("drop of the panic payload panicked")
+ }).unwrap_or(false));
+}
--- /dev/null
+// check-pass
+//
+// Regression test for issue #78632
+
+#![crate_type = "lib"]
+
+pub trait Corge<T> {
+ type Fred;
+}
+
+impl Corge<u8> for () {
+ type Fred = u32;
+}
+
+pub trait Waldo {
+ type Quax;
+}
+
+impl Waldo for u32 {
+ type Quax = u8;
+}
+
+pub trait Grault
+where
+ (): Corge<Self::Thud>,
+{
+ type Thud;
+ fn bar(_: <() as Corge<Self::Thud>>::Fred) {}
+}
+
+impl<T> Grault for T
+where
+ T: Waldo,
+ (): Corge<T::Quax>,
+ <() as Corge<T::Quax>>::Fred: Waldo,
+{
+ type Thud = u8;
+}
+
+pub trait Plugh<I> {
+ fn baz();
+}
+
+#[derive(Copy, Clone, Debug)]
+pub struct Qiz<T> {
+ foo: T,
+}
+
+impl<T> Plugh<<() as Corge<T::Thud>>::Fred> for Qiz<T>
+where
+ T: Grault,
+ (): Corge<T::Thud>,
+{
+ fn baz() {}
+}
+
+pub fn test() {
+ <Qiz<u32> as Plugh<u32>>::baz();
+}
--- /dev/null
+#![feature(min_type_alias_impl_trait)]
+#![feature(impl_trait_in_bindings)]
+#![allow(incomplete_features)]
+
+type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+//~^ ERROR: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+//~| ERROR: the type `&'<empty> str` does not fulfill the required lifetime
+//~| ERROR: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+
+trait Output<'a> {}
+
+impl<'a> Output<'a> for &'a str {}
+
+fn cool_fn<'a>(arg: &'a str) -> OpaqueOutputImpl<'a> {
+ let out: OpaqueOutputImpl<'a> = arg;
+ arg
+}
+
+fn main() {
+ let s = String::from("wassup");
+ cool_fn(&s);
+}
--- /dev/null
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ --> $DIR/issue-85113.rs:5:29
+ |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+note: hidden type `&'<empty> str` captures lifetime smaller than the function body
+ --> $DIR/issue-85113.rs:5:29
+ |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0477]: the type `&'<empty> str` does not fulfill the required lifetime
+ --> $DIR/issue-85113.rs:5:29
+ |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+note: type must outlive the lifetime `'a` as defined on the item at 5:23
+ --> $DIR/issue-85113.rs:5:23
+ |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+ | ^^
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+ --> $DIR/issue-85113.rs:5:29
+ |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: first, the lifetime cannot outlive the empty lifetime...
+note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the item at 5:23...
+ --> $DIR/issue-85113.rs:5:23
+ |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+ | ^^
+note: ...so that the types are compatible
+ --> $DIR/issue-85113.rs:5:29
+ |
+LL | type OpaqueOutputImpl<'a> = impl Output<'a> + 'a;
+ | ^^^^^^^^^^^^^^^^^^^^
+ = note: expected `Output<'a>`
+ found `Output<'_>`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0477, E0495, E0700.
+For more information about an error, try `rustc --explain E0477`.
--- /dev/null
+// Regression test for #75889.
+
+const FOO: dyn Fn() -> _ = ""; //~ ERROR E0121
+static BOO: dyn Fn() -> _ = ""; //~ ERROR E0121
+
+fn main() {}
--- /dev/null
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+ --> $DIR/issue-75889.rs:3:24
+ |
+LL | const FOO: dyn Fn() -> _ = "";
+ | ^ not allowed in type signatures
+
+error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+ --> $DIR/issue-75889.rs:4:25
+ |
+LL | static BOO: dyn Fn() -> _ = "";
+ | ^ not allowed in type signatures
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0121`.
= help: consider replacing `'new` with `'static`
error: lifetime may not live long enough
- --> $DIR/variance-btree-invariant-types.rs:18:5
+ --> $DIR/variance-btree-invariant-types.rs:17:5
+ |
+LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> {
+ | ---- lifetime `'new` defined here
+LL | v
+ | ^ returning this value requires that `'new` must outlive `'static`
+ |
+ = help: consider replacing `'new` with `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/variance-btree-invariant-types.rs:20:5
+ |
+LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> {
+ | ---- lifetime `'new` defined here
+LL | v
+ | ^ returning this value requires that `'new` must outlive `'static`
+ |
+ = help: consider replacing `'new` with `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/variance-btree-invariant-types.rs:23:5
+ |
+LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> {
+ | ---- lifetime `'new` defined here
+LL | v
+ | ^ returning this value requires that `'new` must outlive `'static`
+ |
+ = help: consider replacing `'new` with `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/variance-btree-invariant-types.rs:26:5
+ |
+LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> {
+ | ---- lifetime `'new` defined here
+LL | v
+ | ^ returning this value requires that `'new` must outlive `'static`
+ |
+ = help: consider replacing `'new` with `'static`
+
+error: lifetime may not live long enough
+ --> $DIR/variance-btree-invariant-types.rs:31:5
|
LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>)
| ---- lifetime `'new` defined here
= help: consider replacing `'new` with `'static`
error: lifetime may not live long enough
- --> $DIR/variance-btree-invariant-types.rs:22:5
+ --> $DIR/variance-btree-invariant-types.rs:35:5
|
LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>)
| ---- lifetime `'new` defined here
= help: consider replacing `'new` with `'static`
error: lifetime may not live long enough
- --> $DIR/variance-btree-invariant-types.rs:26:5
+ --> $DIR/variance-btree-invariant-types.rs:39:5
|
LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>)
| ---- lifetime `'new` defined here
= help: consider replacing `'new` with `'static`
error: lifetime may not live long enough
- --> $DIR/variance-btree-invariant-types.rs:30:5
+ --> $DIR/variance-btree-invariant-types.rs:43:5
|
LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>)
| ---- lifetime `'new` defined here
= help: consider replacing `'new` with `'static`
error: lifetime may not live long enough
- --> $DIR/variance-btree-invariant-types.rs:35:5
+ --> $DIR/variance-btree-invariant-types.rs:48:5
|
LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>)
| ---- lifetime `'new` defined here
= help: consider replacing `'new` with `'static`
error: lifetime may not live long enough
- --> $DIR/variance-btree-invariant-types.rs:39:5
+ --> $DIR/variance-btree-invariant-types.rs:52:5
|
LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>)
| ---- lifetime `'new` defined here
= help: consider replacing `'new` with `'static`
error: lifetime may not live long enough
- --> $DIR/variance-btree-invariant-types.rs:43:5
+ --> $DIR/variance-btree-invariant-types.rs:56:5
|
LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>)
| ---- lifetime `'new` defined here
= help: consider replacing `'new` with `'static`
error: lifetime may not live long enough
- --> $DIR/variance-btree-invariant-types.rs:47:5
+ --> $DIR/variance-btree-invariant-types.rs:60:5
|
LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>)
| ---- lifetime `'new` defined here
|
= help: consider replacing `'new` with `'static`
-error: aborting due to 12 previous errors
+error: aborting due to 16 previous errors
-use std::collections::btree_map::{IterMut, OccupiedEntry, VacantEntry};
+use std::collections::btree_map::{IterMut, OccupiedEntry, RangeMut, VacantEntry};
fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> {
v //~ ERROR mismatched types
v //~ ERROR mismatched types
}
+fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> {
+ v //~ ERROR mismatched types
+}
+fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> {
+ v //~ ERROR mismatched types
+}
+fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> {
+ v //~ ERROR mismatched types
+}
+fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> {
+ v //~ ERROR mismatched types
+}
+
fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>)
-> OccupiedEntry<'a, &'new (), ()> {
v //~ ERROR mismatched types
= note: ...does not necessarily outlive the static lifetime
error[E0308]: mismatched types
- --> $DIR/variance-btree-invariant-types.rs:18:5
+ --> $DIR/variance-btree-invariant-types.rs:17:5
+ |
+LL | v
+ | ^ lifetime mismatch
+ |
+ = note: expected struct `RangeMut<'_, &'new (), _>`
+ found struct `RangeMut<'_, &'static (), _>`
+note: the lifetime `'new` as defined on the function body at 16:22...
+ --> $DIR/variance-btree-invariant-types.rs:16:22
+ |
+LL | fn range_cov_key<'a, 'new>(v: RangeMut<'a, &'static (), ()>) -> RangeMut<'a, &'new (), ()> {
+ | ^^^^
+ = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+ --> $DIR/variance-btree-invariant-types.rs:20:5
+ |
+LL | v
+ | ^ lifetime mismatch
+ |
+ = note: expected struct `RangeMut<'_, _, &'new ()>`
+ found struct `RangeMut<'_, _, &'static ()>`
+note: the lifetime `'new` as defined on the function body at 19:22...
+ --> $DIR/variance-btree-invariant-types.rs:19:22
+ |
+LL | fn range_cov_val<'a, 'new>(v: RangeMut<'a, (), &'static ()>) -> RangeMut<'a, (), &'new ()> {
+ | ^^^^
+ = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+ --> $DIR/variance-btree-invariant-types.rs:23:5
+ |
+LL | v
+ | ^ lifetime mismatch
+ |
+ = note: expected struct `RangeMut<'_, &'static (), _>`
+ found struct `RangeMut<'_, &'new (), _>`
+note: the lifetime `'new` as defined on the function body at 22:25...
+ --> $DIR/variance-btree-invariant-types.rs:22:25
+ |
+LL | fn range_contra_key<'a, 'new>(v: RangeMut<'a, &'new (), ()>) -> RangeMut<'a, &'static (), ()> {
+ | ^^^^
+ = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+ --> $DIR/variance-btree-invariant-types.rs:26:5
+ |
+LL | v
+ | ^ lifetime mismatch
+ |
+ = note: expected struct `RangeMut<'_, _, &'static ()>`
+ found struct `RangeMut<'_, _, &'new ()>`
+note: the lifetime `'new` as defined on the function body at 25:25...
+ --> $DIR/variance-btree-invariant-types.rs:25:25
+ |
+LL | fn range_contra_val<'a, 'new>(v: RangeMut<'a, (), &'new ()>) -> RangeMut<'a, (), &'static ()> {
+ | ^^^^
+ = note: ...does not necessarily outlive the static lifetime
+
+error[E0308]: mismatched types
+ --> $DIR/variance-btree-invariant-types.rs:31:5
|
LL | v
| ^ lifetime mismatch
|
= note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>`
found struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>`
-note: the lifetime `'new` as defined on the function body at 16:20...
- --> $DIR/variance-btree-invariant-types.rs:16:20
+note: the lifetime `'new` as defined on the function body at 29:20...
+ --> $DIR/variance-btree-invariant-types.rs:29:20
|
LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>)
| ^^^^
= note: ...does not necessarily outlive the static lifetime
error[E0308]: mismatched types
- --> $DIR/variance-btree-invariant-types.rs:22:5
+ --> $DIR/variance-btree-invariant-types.rs:35:5
|
LL | v
| ^ lifetime mismatch
|
= note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>`
found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>`
-note: the lifetime `'new` as defined on the function body at 20:20...
- --> $DIR/variance-btree-invariant-types.rs:20:20
+note: the lifetime `'new` as defined on the function body at 33:20...
+ --> $DIR/variance-btree-invariant-types.rs:33:20
|
LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>)
| ^^^^
= note: ...does not necessarily outlive the static lifetime
error[E0308]: mismatched types
- --> $DIR/variance-btree-invariant-types.rs:26:5
+ --> $DIR/variance-btree-invariant-types.rs:39:5
|
LL | v
| ^ lifetime mismatch
|
= note: expected struct `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>`
found struct `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>`
-note: the lifetime `'new` as defined on the function body at 24:23...
- --> $DIR/variance-btree-invariant-types.rs:24:23
+note: the lifetime `'new` as defined on the function body at 37:23...
+ --> $DIR/variance-btree-invariant-types.rs:37:23
|
LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>)
| ^^^^
= note: ...does not necessarily outlive the static lifetime
error[E0308]: mismatched types
- --> $DIR/variance-btree-invariant-types.rs:30:5
+ --> $DIR/variance-btree-invariant-types.rs:43:5
|
LL | v
| ^ lifetime mismatch
|
= note: expected struct `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>`
found struct `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>`
-note: the lifetime `'new` as defined on the function body at 28:23...
- --> $DIR/variance-btree-invariant-types.rs:28:23
+note: the lifetime `'new` as defined on the function body at 41:23...
+ --> $DIR/variance-btree-invariant-types.rs:41:23
|
LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>)
| ^^^^
= note: ...does not necessarily outlive the static lifetime
error[E0308]: mismatched types
- --> $DIR/variance-btree-invariant-types.rs:35:5
+ --> $DIR/variance-btree-invariant-types.rs:48:5
|
LL | v
| ^ lifetime mismatch
|
= note: expected struct `std::collections::btree_map::VacantEntry<'_, &'new (), _>`
found struct `std::collections::btree_map::VacantEntry<'_, &'static (), _>`
-note: the lifetime `'new` as defined on the function body at 33:20...
- --> $DIR/variance-btree-invariant-types.rs:33:20
+note: the lifetime `'new` as defined on the function body at 46:20...
+ --> $DIR/variance-btree-invariant-types.rs:46:20
|
LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>)
| ^^^^
= note: ...does not necessarily outlive the static lifetime
error[E0308]: mismatched types
- --> $DIR/variance-btree-invariant-types.rs:39:5
+ --> $DIR/variance-btree-invariant-types.rs:52:5
|
LL | v
| ^ lifetime mismatch
|
= note: expected struct `std::collections::btree_map::VacantEntry<'_, _, &'new ()>`
found struct `std::collections::btree_map::VacantEntry<'_, _, &'static ()>`
-note: the lifetime `'new` as defined on the function body at 37:20...
- --> $DIR/variance-btree-invariant-types.rs:37:20
+note: the lifetime `'new` as defined on the function body at 50:20...
+ --> $DIR/variance-btree-invariant-types.rs:50:20
|
LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>)
| ^^^^
= note: ...does not necessarily outlive the static lifetime
error[E0308]: mismatched types
- --> $DIR/variance-btree-invariant-types.rs:43:5
+ --> $DIR/variance-btree-invariant-types.rs:56:5
|
LL | v
| ^ lifetime mismatch
|
= note: expected struct `std::collections::btree_map::VacantEntry<'_, &'static (), _>`
found struct `std::collections::btree_map::VacantEntry<'_, &'new (), _>`
-note: the lifetime `'new` as defined on the function body at 41:23...
- --> $DIR/variance-btree-invariant-types.rs:41:23
+note: the lifetime `'new` as defined on the function body at 54:23...
+ --> $DIR/variance-btree-invariant-types.rs:54:23
|
LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>)
| ^^^^
= note: ...does not necessarily outlive the static lifetime
error[E0308]: mismatched types
- --> $DIR/variance-btree-invariant-types.rs:47:5
+ --> $DIR/variance-btree-invariant-types.rs:60:5
|
LL | v
| ^ lifetime mismatch
|
= note: expected struct `std::collections::btree_map::VacantEntry<'_, _, &'static ()>`
found struct `std::collections::btree_map::VacantEntry<'_, _, &'new ()>`
-note: the lifetime `'new` as defined on the function body at 45:23...
- --> $DIR/variance-btree-invariant-types.rs:45:23
+note: the lifetime `'new` as defined on the function body at 58:23...
+ --> $DIR/variance-btree-invariant-types.rs:58:23
|
LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>)
| ^^^^
= note: ...does not necessarily outlive the static lifetime
-error: aborting due to 12 previous errors
+error: aborting due to 16 previous errors
For more information about this error, try `rustc --explain E0308`.
- [P-low][p-low]: Requires attention (fix/response/evaluation) by a team member but isn't urgent.
- [P-medium][p-medium]: Should be addressed by a team member until the next sync.
- [P-high][p-high]: Should be immediately addressed and will require an out-of-cycle sync or a backport.
-- [L-sync-blocker][l-sync-blocker]: An issue that "blocks" a sync.
+- [L-sync-blocker][l-sync-blocker]: An issue that "blocks" a sync.
Or rather: before the sync this should be addressed,
e.g. by removing a lint again, so it doesn't hit beta/stable.
If you want to run Clippy **only** on the given crate, use the `--no-deps` option like this:
```terminal
-cargo clippy -p example -- --no-deps
+cargo clippy -p example -- --no-deps
```
### As a rustc replacement (`clippy-driver`)
if let ExprKind::Block(block, _) = expr.kind {
match block.rules {
- BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided)
- | BlockCheckMode::PushUnsafeBlock(UnsafeSource::UserProvided)
- | BlockCheckMode::PopUnsafeBlock(UnsafeSource::UserProvided) => {
+ BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => {
self.has_unsafe = true;
},
_ => {},
(Path(lq, lp), Path(rq, rp)) => both(lq, rq, |l, r| eq_qself(l, r)) && eq_path(lp, rp),
(MacCall(l), MacCall(r)) => eq_mac_call(l, r),
(Struct(lse), Struct(rse)) => {
- eq_maybe_qself(&lse.qself, &rse.qself)
+ eq_maybe_qself(&lse.qself, &rse.qself)
&& eq_path(&lse.path, &rse.path)
&& eq_struct_rest(&lse.rest, &rse.rest)
&& unordered_over(&lse.fields, &rse.fields, |l, r| eq_field(l, r))
## lintcheck
`cargo lintcheck` will build and run clippy on a fixed set of crates and generate a log of the results.
-You can `git diff` the updated log against its previous version and
+You can `git diff` the updated log against its previous version and
see what impact your lint made on a small set of crates.
-If you add a new lint, please audit the resulting warnings and make sure
+If you add a new lint, please audit the resulting warnings and make sure
there are no false positives and that the suggestions are valid.
Refer to the tools [README] for more details.
print a warning if Clippys suggestions fail to apply (if the resulting code does not build).
This lets us spot bad suggestions or false positives automatically in some cases.
-Please note that the target dir should be cleaned afterwards since clippy will modify
+Please note that the target dir should be cleaned afterwards since clippy will modify
the downloaded sources which can lead to unexpected results when running lintcheck again afterwards.
fn main() {
let s = String::from("String");
s.as_bytes().get(3);
- &s.as_bytes().get(3);
+ let _ = &s.as_bytes().get(3);
s[..].as_bytes().get(3);
}
fn main() {
let s = String::from("String");
s.bytes().nth(3);
- &s.bytes().nth(3);
+ let _ = &s.bytes().nth(3);
s[..].bytes().nth(3);
}
= note: `-D clippy::bytes-nth` implied by `-D warnings`
error: called `.byte().nth()` on a `String`
- --> $DIR/bytes_nth.rs:9:6
+ --> $DIR/bytes_nth.rs:9:14
|
-LL | &s.bytes().nth(3);
- | ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
+LL | let _ = &s.bytes().nth(3);
+ | ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
error: called `.byte().nth()` on a `str`
--> $DIR/bytes_nth.rs:10:5
linked_list.push_back(1);
binary_heap.push(1);
- &vec[..].len();
+ let _ = &vec[..].len();
vec.len();
boxed_slice.len();
vec_deque.len();
binary_heap.len();
vec.len();
- &vec[..].len();
+ let _ = &vec[..].len();
vec_deque.len();
hash_map.len();
b_tree_map.len();
linked_list.len();
- &vec[..].len();
+ let _ = &vec[..].len();
vec.len();
vec_deque.len();
hash_set.len();
linked_list.push_back(1);
binary_heap.push(1);
- &vec[..].iter().count();
+ let _ = &vec[..].iter().count();
vec.iter().count();
boxed_slice.iter().count();
vec_deque.iter().count();
binary_heap.iter().count();
vec.iter_mut().count();
- &vec[..].iter_mut().count();
+ let _ = &vec[..].iter_mut().count();
vec_deque.iter_mut().count();
hash_map.iter_mut().count();
b_tree_map.iter_mut().count();
linked_list.iter_mut().count();
- &vec[..].into_iter().count();
+ let _ = &vec[..].into_iter().count();
vec.into_iter().count();
vec_deque.into_iter().count();
hash_set.into_iter().count();
error: called `.iter().count()` on a `slice`
- --> $DIR/iter_count.rs:53:6
+ --> $DIR/iter_count.rs:53:14
|
-LL | &vec[..].iter().count();
- | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
+LL | let _ = &vec[..].iter().count();
+ | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
|
= note: `-D clippy::iter-count` implied by `-D warnings`
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.len()`
error: called `.iter_mut().count()` on a `slice`
- --> $DIR/iter_count.rs:65:6
+ --> $DIR/iter_count.rs:65:14
|
-LL | &vec[..].iter_mut().count();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
+LL | let _ = &vec[..].iter_mut().count();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
error: called `.iter_mut().count()` on a `VecDeque`
--> $DIR/iter_count.rs:66:5
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `linked_list.len()`
error: called `.into_iter().count()` on a `slice`
- --> $DIR/iter_count.rs:71:6
+ --> $DIR/iter_count.rs:71:14
|
-LL | &vec[..].into_iter().count();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
+LL | let _ = &vec[..].into_iter().count();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec[..].len()`
error: called `.into_iter().count()` on a `Vec`
--> $DIR/iter_count.rs:72:5
$scope.bySearch = function (lint, index, array) {
let searchStr = $scope.search;
- // It can be `null` I haven't missed this value
+ // It can be `null` I haven't missed this value
if (searchStr == null || searchStr.length < 3) {
return true;
}
}
// Search the description
- // The use of `for`-loops instead of `foreach` enables us to return early
+ // The use of `for`-loops instead of `foreach` enables us to return early
let terms = searchStr.split(" ");
for (index = 0; index < terms.length; index++) {
if (lint.id.indexOf(terms[index]) !== -1) {
let children = themeMenu.children;
for (let index = 0; index < children.length; index++) {
- let child = children[index];
+ let child = children[index];
child.addEventListener("click", function(e) {
setTheme(child.id, true);
});
let enableHighlight = false;
let enableNight = false;
let enableAyu = false;
-
+
if (theme == "ayu") {
enableAyu = true;
} else if (theme == "coal" || theme == "navy") {
} else {
report.errors += 1;
print!("{}:{}: broken link fragment ", pretty_path, i + 1);
- println!("`#{}` pointing to `{}`", fragment, pretty_path);
+ println!("`#{}` pointing to `{}`", fragment, target_pretty_path);
};
}
});
<html lang="en">
<head>
<meta http-equiv="refresh" content="0;URL=sometarget">
+ <title>Redirection</title>
</head>
<body>
<p>Redirecting to <a href="sometarget">sometarget</a>...</p>
fn broken_test(dirname: &str, expected: &str) {
let (status, stdout, stderr) = run(dirname);
assert!(!status.success());
- if !stdout.contains(expected) {
+ if !contains(expected, &stdout) {
panic!(
"stdout did not contain expected text: {}\n\
--- stdout:\n\
}
}
+fn contains(expected: &str, actual: &str) -> bool {
+ // Normalize for Windows paths.
+ let actual = actual.replace('\\', "/");
+ actual.lines().any(|mut line| {
+ for (i, part) in expected.split("[..]").enumerate() {
+ match line.find(part) {
+ Some(j) => {
+ if i == 0 && j != 0 {
+ return false;
+ }
+ line = &line[j + part.len()..];
+ }
+ None => return false,
+ }
+ }
+ line.is_empty() || expected.ends_with("[..]")
+ })
+}
+
fn valid_test(dirname: &str) {
let (status, stdout, stderr) = run(dirname);
if !status.success() {
#[test]
fn basic_broken() {
- broken_test("basic_broken", "bar.html");
+ broken_test("basic_broken", "foo.html:3: broken link - `bar.html`");
}
#[test]
fn broken_fragment_local() {
- broken_test("broken_fragment_local", "#somefrag");
+ broken_test(
+ "broken_fragment_local",
+ "foo.html:3: broken link fragment `#somefrag` pointing to `foo.html`",
+ );
}
#[test]
fn broken_fragment_remote() {
- broken_test("broken_fragment_remote/inner", "#somefrag");
+ broken_test(
+ "broken_fragment_remote/inner",
+ "foo.html:3: broken link fragment `#somefrag` pointing to \
+ `[..]/broken_fragment_remote/bar.html`",
+ );
}
#[test]
fn broken_redir() {
- broken_test("broken_redir", "sometarget");
+ broken_test(
+ "broken_redir",
+ "foo.html:3: broken redirect from `redir-bad.html` to `sometarget`",
+ );
}
#[test]
fn directory_link() {
- broken_test("directory_link", "somedir");
+ broken_test(
+ "directory_link",
+ "foo.html:3: directory link to `somedir` (directory links should use index.html instead)",
+ );
}
#[test]
fn redirect_loop() {
- broken_test("redirect_loop", "redir-bad.html");
+ broken_test(
+ "redirect_loop",
+ "foo.html:3: redirect from `redir-bad.html` to `[..]redirect_loop/redir-bad.html` \
+ which is also a redirect (not supported)",
+ );
}
<html lang="en">
<head>
<meta http-equiv="refresh" content="0;URL=redir-bad.html">
+ <title>Redirection</title>
</head>
<body>
<p>Redirecting to <a href="redir-bad.html">redir-bad.html</a>...</p>
<html lang="en">
<head>
<meta http-equiv="refresh" content="0;URL=xxx">
+ <title>Redirection</title>
</head>
<body>
<p>Redirecting to <a href="xxx">xxx</a>...</p>
<html lang="en">
<head>
<meta http-equiv="refresh" content="0;URL=redir-target.html">
+ <title>Redirection</title>
</head>
<body>
<p>Redirecting to <a href="redir-target.html">redir-target.html</a>...</p>
-Subproject commit 35af23b6a94459da538ee1479e863c7699620f84
+Subproject commit 23f05fc603252b7906bd7e44208ab24038f8da12
### Changed
-- Original comment indentation for trailing comments within an `if` is now taken into account when determining the indentation level to use for the trailing comment in formatted code. This does not modify any existing code formatted with rustfmt; it simply gives the programmer discretion to specify whether the comment is associated to the `else` block, or if the trailing comment is just a member of the `if` block. ([#1575](https://github.com/rust-lang/rustfmt/issues/1575), [#4120](https://github.com/rust-lang/rustfmt/issues/4120), [#4506](https://github.com/rust-lang/rustfmt/issues/4506))
+- Original comment indentation for trailing comments within an `if` is now taken into account when determining the indentation level to use for the trailing comment in formatted code. This does not modify any existing code formatted with rustfmt; it simply gives the programmer discretion to specify whether the comment is associated to the `else` block, or if the trailing comment is just a member of the `if` block. ([#1575](https://github.com/rust-lang/rustfmt/issues/1575), [#4120](https://github.com/rust-lang/rustfmt/issues/4120), [#4506](https://github.com/rust-lang/rustfmt/issues/4506))
In this example the `// else comment` refers to the `else`:
```rust
### Fixed
- Formatting of empty blocks with attributes which only contained comments is no longer butchered.([#4475](https://github.com/rust-lang/rustfmt/issues/4475), [#4467](https://github.com/rust-lang/rustfmt/issues/4467), [#4452](https://github.com/rust-lang/rustfmt/issues/4452#issuecomment-705886282), [#4522](https://github.com/rust-lang/rustfmt/issues/4522))
-- Indentation of trailing comments in non-empty extern blocks is now correct. ([#4120](https://github.com/rust-lang/rustfmt/issues/4120#issuecomment-696491872))
+- Indentation of trailing comments in non-empty extern blocks is now correct. ([#4120](https://github.com/rust-lang/rustfmt/issues/4120#issuecomment-696491872))
### Install/Download Options
- **crates.io package** - *pending*
- Fix aligning comments of different group
- Fix flattening imports with a single `self`.
- Fix removing attributes on function parameters.
-- Fix removing `impl` keyword from opaque type.
+- Fix removing `impl` keyword from opaque type.
## [1.4.8] 2019-09-08
- Add `--message-format` command line option to `cargo-fmt`.
- Add `-l,--files-with-diff` command line option to `rustfmt`.
-- Add `json` emit mode.
+- Add `json` emit mode.
### Fixed
### Added
-- Add new attribute `rustfmt::skip::attributes` to prevent rustfmt
+- Add new attribute `rustfmt::skip::attributes` to prevent rustfmt
from formatting an attribute #3665
### Changed
Below you find a detailed visual guide on all the supported configuration options of rustfmt:
-## `array_width`
+## `array_width`
Maximum width of an array literal before falling back to vertical formatting.
- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
- **Stable**: Yes
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `array_width` will take precedence.
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `array_width` will take precedence.
See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
-## `attr_fn_like_width`
+## `attr_fn_like_width`
Maximum width of the args of a function-like attributes before falling back to vertical formatting.
- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
- **Stable**: Yes
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `attr_fn_like_width` will take precedence.
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `attr_fn_like_width` will take precedence.
See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
}
```
-## `chain_width`
+## `chain_width`
Maximum width of a chain to fit on one line.
- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
- **Stable**: Yes
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `chain_width` will take precedence.
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `chain_width` will take precedence.
See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
}
```
-## `fn_call_width`
+## `fn_call_width`
Maximum width of the args of a function call before falling back to vertical formatting.
- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
- **Stable**: Yes
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `fn_call_width` will take precedence.
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `fn_call_width` will take precedence.
See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
- **Possible values**: `true`, `false`
- **Stable**: No (tracking issue: #3389)
-## `single_line_if_else_max_width`
+## `single_line_if_else_max_width`
Maximum line length for single line if-else expressions. A value of `0` (zero) results in if-else expressions always being broken into multiple lines. Note this occurs when `use_small_heuristics` is set to `Off`.
- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
- **Stable**: Yes
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `single_line_if_else_max_width` will take precedence.
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `single_line_if_else_max_width` will take precedence.
See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
See also: [`indent_style`](#indent_style).
-## `struct_lit_width`
+## `struct_lit_width`
Maximum width in the body of a struct literal before falling back to vertical formatting. A value of `0` (zero) results in struct literals always being broken into multiple lines. Note this occurs when `use_small_heuristics` is set to `Off`.
- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
- **Stable**: Yes
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `struct_lit_width` will take precedence.
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `struct_lit_width` will take precedence.
See also [`max_width`](#max_width), [`use_small_heuristics`](#use_small_heuristics), and [`struct_lit_single_line`](#struct_lit_single_line)
-## `struct_variant_width`
+## `struct_variant_width`
Maximum width in the body of a struct variant before falling back to vertical formatting. A value of `0` (zero) results in struct literals always being broken into multiple lines. Note this occurs when `use_small_heuristics` is set to `Off`.
- **Possible values**: any positive integer that is less than or equal to the value specified for [`max_width`](#max_width)
- **Stable**: Yes
-By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `struct_variant_width` will take precedence.
+By default this option is set as a percentage of [`max_width`](#max_width) provided by [`use_small_heuristics`](#use_small_heuristics), but a value set directly for `struct_variant_width` will take precedence.
See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
This option can be used to simplify the management and bulk updates of the granular width configuration settings ([`fn_call_width`](#fn_call_width), [`attr_fn_like_width`](#attr_fn_like_width), [`struct_lit_width`](#struct_lit_width), [`struct_variant_width`](#struct_variant_width), [`array_width`](#array_width), [`chain_width`](#chain_width), [`single_line_if_else_max_width`](#single_line_if_else_max_width)), that respectively control when formatted constructs are multi-lined/vertical based on width.
-Note that explicitly provided values for the width configuration settings take precedence and override the calculated values determined by `use_small_heuristics`.
+Note that explicitly provided values for the width configuration settings take precedence and override the calculated values determined by `use_small_heuristics`.
- **Default value**: `"Default"`
- **Possible values**: `"Default"`, `"Off"`, `"Max"`
```
#### `Off`:
-When `use_small_heuristics` is set to `Off`, the granular width settings are functionally disabled and ignored. See the documentation for the respective width config options for specifics.
+When `use_small_heuristics` is set to `Off`, the granular width settings are functionally disabled and ignored. See the documentation for the respective width config options for specifics.
```rust
enum Lorem {
identified.
Without explicit settings, the tests will be run using rustfmt's default
-configuration. It is possible to run a test using non-default settings in several
+configuration. It is possible to run a test using non-default settings in several
ways. Firstly, you can include configuration parameters in comments at the top
of the file. For example: to use 3 spaces per tab, start your test with
`// rustfmt-tab_spaces: 3`. Just remember that the comment is part of the input,
Our visitor keeps track of the desired current indent due to blocks (
`block_indent`). Each `visit_*` method reformats code according to this indent,
-`config.comment_width()` and `config.max_width()`. Most reformatting that is done
-in the `visit_*` methods is a bit hacky and is meant to be temporary until it can
+`config.comment_width()` and `config.max_width()`. Most reformatting that is done
+in the `visit_*` methods is a bit hacky and is meant to be temporary until it can
be done properly.
There are a bunch of methods called `rewrite_*`. They do the bulk of the
* For things you do not want rustfmt to mangle, use `#[rustfmt::skip]`
* To prevent rustfmt from formatting a macro or an attribute,
- use `#[rustfmt::skip::macros(target_macro_name)]` or
+ use `#[rustfmt::skip::macros(target_macro_name)]` or
`#[rustfmt::skip::attributes(target_attribute_name)]`
Example:
```rust
- #![rustfmt::skip::attributes(custom_attribute)]
+ #![rustfmt::skip::attributes(custom_attribute)]
#[custom_attribute(formatting , here , should , be , Skipped)]
#[rustfmt::skip::macros(html)]
# it again.
#
#which cargo-fmt || cargo install --force
-CFG_RELEASE=nightly CFG_RELEASE_CHANNEL=nightly cargo install --path . --force
+CFG_RELEASE=nightly CFG_RELEASE_CHANNEL=nightly cargo install --path . --force
echo "Integration tests for: ${INTEGRATION}"
cargo fmt -- --version
outputHtml() {
const ast = this.configurationDescriptions
.filter(({ head, text, stable }) => {
-
+
if (
text.includes(this.searchCondition) === false &&
head.includes(this.searchCondition) === false
},
created: async function() {
const res = await axios.get(ConfigurationMdUrl);
- const {
+ const {
about,
configurationAbout,
configurationDescriptions
const lastIndex = stack.length - 1;
stack[lastIndex].push(next);
return stack;
- },
+ },
[[]]);
});
}
configurationAbout, ...configurationDescriptions
] = configurations;
configurationAbout.value.links = {};
-
+
return {
about,
configurationAbout: configurationAbout.value,
use std::iter::ExactSizeIterator;
use std::ops::Deref;
-use rustc_ast::ast::{self, FnRetTy, Mutability};
+use rustc_ast::ast::{self, AttrVec, FnRetTy, Mutability};
use rustc_span::{symbol::kw, symbol::Ident, BytePos, Pos, Span};
use crate::config::lists::*;
);
let data = ast::VariantData::Struct(fields.clone(), recovered);
let variant = ast::Variant {
- attrs: vec![],
+ attrs: AttrVec::new(),
id: self.id,
span: self.span,
vis: DEFAULT_VISIBILITY,
);
let data = ast::VariantData::Struct(fields.clone(), recovered);
let variant = ast::Variant {
- attrs: vec![],
+ attrs: AttrVec::new(),
id: self.id,
span: self.span,
vis: DEFAULT_VISIBILITY,