[[package]]
name = "cargo-platform"
-version = "0.1.1"
+version = "0.1.2"
dependencies = [
"serde",
]
[[package]]
name = "jobserver"
-version = "0.1.22"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd"
+checksum = "f5ca711fd837261e14ec9e674f092cbb931d3fa1482b017ae59328ddc6f3212b"
dependencies = [
"libc",
]
[[package]]
name = "libc"
-version = "0.2.98"
+version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
+checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
dependencies = [
"rustc-std-workspace-core",
]
};
ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout()));
};
+
+ black_box, (c a) {
+ // FIXME implement black_box semantics
+ ret.write_cvalue(fx, a);
+ };
}
if let Some((_, dest)) = destination {
}
}
-fn inline_asm_call(
+pub(crate) fn inline_asm_call(
bx: &mut Builder<'a, 'll, 'tcx>,
asm: &str,
cons: &str,
use crate::va_arg::emit_va_arg;
use crate::value::Value;
+use rustc_ast as ast;
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh};
use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
}
}
+ sym::black_box => {
+ args[0].val.store(self, result);
+
+ // We need to "use" the argument in some way LLVM can't introspect, and on
+ // targets that support it we can typically leverage inline assembly to do
+ // this. LLVM's interpretation of inline assembly is that it's, well, a black
+ // box. This isn't the greatest implementation since it probably deoptimizes
+ // more than we want, but it's so far good enough.
+ crate::asm::inline_asm_call(
+ self,
+ "",
+ "r,~{memory}",
+ &[result.llval],
+ self.type_void(),
+ true,
+ false,
+ ast::LlvmAsmDialect::Att,
+ &[span],
+ )
+ .unwrap_or_else(|| bug!("failed to generate inline asm call for `black_box`"));
+
+ // We have copied the value to `result` already.
+ return;
+ }
+
_ if name_str.starts_with("simd_") => {
match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
Ok(llval) => llval,
.with_indent_lines(true)
.with_ansi(color_logs)
.with_targets(true)
- .with_wraparound(10)
- .with_verbose_exit(true)
- .with_verbose_entry(true)
.with_indent_amount(2);
#[cfg(parallel_compiler)]
let layer = layer.with_thread_ids(true).with_thread_names(true);
self.cx.force_mode = orig_force_mode;
// Finally incorporate all the expanded macros into the input AST fragment.
- let mut placeholder_expander = PlaceholderExpander::default();
+ let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
while let Some(expanded_fragments) = expanded_fragments.pop() {
for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() {
placeholder_expander
}
}
+ // The placeholder expander gives ids to statements, so we avoid folding the id here.
// We don't use `assign_id!` - it will be called when we visit statement's contents
// (e.g. an expression, item, or local)
- let res = noop_flat_map_stmt(stmt, self);
+ let ast::Stmt { id, kind, span } = stmt;
+ let res = noop_flat_map_stmt_kind(kind, self)
+ .into_iter()
+ .map(|kind| ast::Stmt { id, kind, span })
+ .collect();
self.cx.current_expansion.is_trailing_mac = false;
res
#![feature(proc_macro_internals)]
#![feature(proc_macro_span)]
#![feature(try_blocks)]
-#![recursion_limit = "256"]
#[macro_use]
extern crate rustc_macros;
+use crate::base::ExtCtxt;
use crate::expand::{AstFragment, AstFragmentKind};
use rustc_ast as ast;
}
}
-#[derive(Default)]
-pub struct PlaceholderExpander {
+pub struct PlaceholderExpander<'a, 'b> {
expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
+ cx: &'a mut ExtCtxt<'b>,
+ monotonic: bool,
}
-impl PlaceholderExpander {
+impl<'a, 'b> PlaceholderExpander<'a, 'b> {
+ pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
+ PlaceholderExpander { cx, expanded_fragments: FxHashMap::default(), monotonic }
+ }
+
pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) {
fragment.mut_visit_with(self);
self.expanded_fragments.insert(id, fragment);
}
}
-impl MutVisitor for PlaceholderExpander {
+impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
if arm.is_placeholder {
self.remove(arm.id).make_arms()
_ => noop_visit_ty(ty, self),
}
}
+
+ fn visit_block(&mut self, block: &mut P<ast::Block>) {
+ noop_visit_block(block, self);
+
+ for stmt in block.stmts.iter_mut() {
+ if self.monotonic {
+ assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
+ stmt.id = self.cx.resolver.next_node_id();
+ }
+ }
+ }
}
/// After a line ending with '\', the next line contains whitespace
/// characters that are not skipped.
UnskippedWhitespaceWarning,
+
+ /// After a line ending with '\', multiple lines are skipped.
+ MultipleSkippedLinesWarning,
}
impl EscapeError {
pub fn is_fatal(&self) -> bool {
match self {
EscapeError::UnskippedWhitespaceWarning => false,
+ EscapeError::MultipleSkippedLinesWarning => false,
_ => true,
}
}
where
F: FnMut(Range<usize>, Result<char, EscapeError>),
{
- let str = chars.as_str();
- let first_non_space = str
+ let tail = chars.as_str();
+ let first_non_space = tail
.bytes()
.position(|b| b != b' ' && b != b'\t' && b != b'\n' && b != b'\r')
- .unwrap_or(str.len());
- let tail = &str[first_non_space..];
+ .unwrap_or(tail.len());
+ if tail[1..first_non_space].contains('\n') {
+ // The +1 accounts for the escaping slash.
+ let end = start + first_non_space + 1;
+ callback(start..end, Err(EscapeError::MultipleSkippedLinesWarning));
+ }
+ let tail = &tail[first_non_space..];
if let Some(c) = tail.chars().nth(0) {
// For error reporting, we would like the span to contain the character that was not
// skipped. The +1 is necessary to account for the leading \ that started the escape.
assert_eq!(unescaped, expected);
}
+ // Check we can handle escaped newlines at the end of a file.
+ check("\\\n", &[]);
+ check("\\\n ", &[]);
+
check(
"\\\n \u{a0} x",
&[
(6..7, Ok('x')),
],
);
+ check("\\\n \n x", &[(0..7, Err(EscapeError::MultipleSkippedLinesWarning)), (7..8, Ok('x'))]);
}
#[test]
Warn,
"detects calling `into_iter` on arrays in Rust 2015 and 2018",
@future_incompatible = FutureIncompatibleInfo {
- reference: "issue #66145 <https://github.com/rust-lang/rust/issues/66145>",
+ reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>",
reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2021),
};
}
Warn,
"`...` range patterns are deprecated",
@future_incompatible = FutureIncompatibleInfo {
- reference: "issue #80165 <https://github.com/rust-lang/rust/issues/80165>",
+ reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>",
reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
};
}
use rustc_ast as ast;
use rustc_errors::{pluralize, Applicability};
use rustc_hir as hir;
+use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_parse_format::{ParseMode, Parser, Piece};
use rustc_session::lint::FutureIncompatibilityReason;
let (span, panic, symbol_str) = panic_call(cx, f);
+ if in_external_macro(cx.sess(), span) {
+ // Nothing that can be done about it in the current crate.
+ return;
+ }
+
// Find the span of the argument to `panic!()`, before expansion in the
// case of `panic!(some_macro!())`.
// We don't use source_callsite(), because this `panic!(..)` might itself
return;
}
+ let (span, _, _) = panic_call(cx, f);
+
+ if in_external_macro(cx.sess(), span) && in_external_macro(cx.sess(), arg.span) {
+ // Nothing that can be done about it in the current crate.
+ return;
+ }
+
let fmt_span = arg.span.source_callsite();
let (snippet, style) = match cx.sess().parse_sess.source_map().span_to_snippet(fmt_span) {
Parser::new(fmt.as_ref(), style, snippet.clone(), false, ParseMode::Format);
let n_arguments = (&mut fmt_parser).filter(|a| matches!(a, Piece::NextArgument(_))).count();
- let (span, _, _) = panic_call(cx, f);
-
if n_arguments > 0 && fmt_parser.errors.is_empty() {
let arg_spans: Vec<_> = match &fmt_parser.arg_places[..] {
[] => vec![fmt_span],
Warn,
"suggest using `dyn Trait` for trait objects",
@future_incompatible = FutureIncompatibleInfo {
- reference: "issue #80165 <https://github.com/rust-lang/rust/issues/80165>",
+ reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>",
reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
};
}
Allow,
"detects usage of old versions of or-patterns",
@future_incompatible = FutureIncompatibleInfo {
- reference: "issue #84869 <https://github.com/rust-lang/rust/issues/84869>",
+ reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>",
reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
};
}
"detects the usage of trait methods which are ambiguous with traits added to the \
prelude in future editions",
@future_incompatible = FutureIncompatibleInfo {
- reference: "issue #85684 <https://github.com/rust-lang/rust/issues/85684>",
+ reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>",
reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
};
}
Allow,
"identifiers that will be parsed as a prefix in Rust 2021",
@future_incompatible = FutureIncompatibleInfo {
- reference: "issue #84978 <https://github.com/rust-lang/rust/issues/84978>",
+ reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>",
reason: FutureIncompatibilityReason::EditionError(Edition::Edition2021),
};
crate_level_only
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
-use rustc_data_structures::vec_map::VecMap;
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_index::vec::{Idx, IndexVec};
use rustc_macros::HashStable;
use rustc_middle::mir::FakeReadCause;
-use rustc_middle::ty::OpaqueTypeKey;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
use rustc_session::lint::{Level, Lint};
/// All the opaque types that are restricted to concrete types
/// by this function.
- pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
+ pub concrete_opaque_types: FxHashSet<DefId>,
/// Tracks the minimum captures required for a closure;
/// see `MinCaptureInformationMap` for more details.
let unsigned_fit = Integer::fit_unsigned(cmp::max(min as u128, max as u128));
let signed_fit = cmp::max(Integer::fit_signed(min), Integer::fit_signed(max));
- let mut min_from_extern = None;
- let min_default = I8;
-
if let Some(ity) = repr.int {
let discr = Integer::from_attr(&tcx, ity);
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
return (discr, ity.is_signed());
}
- if repr.c() {
- match &tcx.sess.target.arch[..] {
- "hexagon" => min_from_extern = Some(I8),
- // WARNING: the ARM EABI has two variants; the one corresponding
- // to `at_least == I32` appears to be used on Linux and NetBSD,
- // but some systems may use the variant corresponding to no
- // lower bound. However, we don't run on those yet...?
- "arm" => min_from_extern = Some(I32),
- _ => min_from_extern = Some(I32),
- }
- }
-
- let at_least = min_from_extern.unwrap_or(min_default);
+ let at_least = if repr.c() {
+ // This is usually I32, however it can be different on some platforms,
+ // notably hexagon and arm-none/thumb-none
+ tcx.data_layout().c_enum_min_size
+ } else {
+ // repr(Rust) enums try to be as small as possible
+ I8
+ };
// If there are no negative values, we can use the unsigned fit.
if min >= 0 {
use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir::*;
use rustc_middle::ty;
use rustc_span::source_map::DesugaringKind;
);
} else if matches!(span.desugaring_kind(), Some(DesugaringKind::ForLoop(_))) {
let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
- Some(def_id) => type_known_to_meet_bound_modulo_regions(
- &self.infcx,
- self.param_env,
- self.infcx.tcx.mk_imm_ref(self.infcx.tcx.lifetimes.re_erased, ty),
- def_id,
- DUMMY_SP,
- ),
+ Some(def_id) => self.infcx.tcx.infer_ctxt().enter(|infcx| {
+ type_known_to_meet_bound_modulo_regions(
+ &infcx,
+ self.param_env,
+ infcx
+ .tcx
+ .mk_imm_ref(infcx.tcx.lifetimes.re_erased, infcx.tcx.erase_regions(ty)),
+ def_id,
+ DUMMY_SP,
+ )
+ }),
_ => false,
};
if suggest {
);
self.copy_op(&self.operand_index(&args[0], index)?, dest)?;
}
- sym::likely | sym::unlikely => {
+ sym::likely | sym::unlikely | sym::black_box => {
// These just return their argument
self.copy_op(&args[0], dest)?;
}
format!("non-ASCII whitespace symbol '{}' is not skipped", c.escape_unicode());
handler.struct_span_warn(span, &msg).span_label(char_span, &msg).emit();
}
+ EscapeError::MultipleSkippedLinesWarning => {
+ let msg = "multiple lines skipped by escaped newline";
+ let bottom_msg = "skipping everything up to and including this point";
+ handler.struct_span_warn(span, msg).span_label(span, bottom_msg).emit();
+ }
}
}
bitreverse,
bitxor,
bitxor_assign,
+ black_box,
block,
bool,
borrowck_graphviz_format,
pub vector_align: Vec<(Size, AbiAndPrefAlign)>,
pub instruction_address_space: AddressSpace,
+
+ /// Minimum size of #[repr(C)] enums (default I32 bits)
+ pub c_enum_min_size: Integer,
}
impl Default for TargetDataLayout {
(Size::from_bits(128), AbiAndPrefAlign::new(align(128))),
],
instruction_address_space: AddressSpace::DATA,
+ c_enum_min_size: Integer::I32,
}
}
}
));
}
+ dl.c_enum_min_size = Integer::from_size(Size::from_bits(target.c_enum_min_bits))?;
+
Ok(dl)
}
}
I8
}
+
+ fn from_size(size: Size) -> Result<Self, String> {
+ match size.bits() {
+ 8 => Ok(Integer::I8),
+ 16 => Ok(Integer::I16),
+ 32 => Ok(Integer::I32),
+ 64 => Ok(Integer::I64),
+ 128 => Ok(Integer::I128),
+ _ => Err(format!("rust does not support integers with {} bits", size.bits())),
+ }
+ }
}
/// Fundamental unit of memory access and layout.
panic_strategy: PanicStrategy::Abort,
max_atomic_width: Some(32),
emit_debug_gdb_scripts: false,
+ // GCC and Clang default to 8 for arm-none here
+ c_enum_min_bits: 8,
..Default::default()
},
}
features: "+vfp3,-d32,-fp16".to_string(),
max_atomic_width: Some(32),
emit_debug_gdb_scripts: false,
+ // GCC and Clang default to 8 for arm-none here
+ c_enum_min_bits: 8,
..Default::default()
},
}
max_atomic_width: Some(64),
panic_strategy: PanicStrategy::Abort,
emit_debug_gdb_scripts: false,
+ c_enum_min_bits: 8,
..Default::default()
};
Target {
max_atomic_width: Some(64),
panic_strategy: PanicStrategy::Abort,
emit_debug_gdb_scripts: false,
+ // GCC and Clang default to 8 for arm-none here
+ c_enum_min_bits: 8,
..Default::default()
};
Target {
panic_strategy: PanicStrategy::Abort,
max_atomic_width: Some(32),
emit_debug_gdb_scripts: false,
+ // GCC and Clang default to 8 for arm-none here
+ c_enum_min_bits: 8,
..Default::default()
},
}
features: "+vfp3,-d32,-fp16".to_string(),
max_atomic_width: Some(32),
emit_debug_gdb_scripts: false,
+ // GCC and Clang default to 8 for arm-none here
+ c_enum_min_bits: 8,
..Default::default()
},
}
base.dynamic_linking = true;
base.executables = true;
+ base.c_enum_min_bits = 8;
+
Target {
llvm_target: "hexagon-unknown-linux-musl".to_string(),
pointer_width: 32,
("riscv32i-unknown-none-elf", riscv32i_unknown_none_elf),
("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf),
+ ("riscv32imc-esp-espidf", riscv32imc_esp_espidf),
("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu),
("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl),
/// If present it's a default value to use for adjusting the C ABI.
pub default_adjusted_cabi: Option<Abi>,
+
+ /// Minimum number of bits in #[repr(C)] enum. Defaults to 32.
+ pub c_enum_min_bits: u64,
}
impl Default for TargetOptions {
split_debuginfo: SplitDebuginfo::Off,
supported_sanitizers: SanitizerSet::empty(),
default_adjusted_cabi: None,
+ c_enum_min_bits: 32,
}
}
}
base.$key_name = s;
}
} );
+ ($key_name:ident, u64) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
+ base.$key_name = s;
+ }
+ } );
($key_name:ident, Option<u32>) => ( {
let name = (stringify!($key_name)).replace("_", "-");
if let Some(s) = obj.remove_key(&name).and_then(|j| Json::as_u64(&j)) {
key!(split_debuginfo, SplitDebuginfo)?;
key!(supported_sanitizers, SanitizerSet)?;
key!(default_adjusted_cabi, Option<Abi>)?;
+ key!(c_enum_min_bits, u64);
if base.is_builtin {
// This can cause unfortunate ICEs later down the line.
target_option_val!(has_thumb_interworking);
target_option_val!(split_debuginfo);
target_option_val!(supported_sanitizers);
+ target_option_val!(c_enum_min_bits);
if let Some(abi) = self.default_adjusted_cabi {
d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json());
--- /dev/null
+use crate::spec::{LinkerFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
+ llvm_target: "riscv32".to_string(),
+ pointer_width: 32,
+ arch: "riscv32".to_string(),
+
+ options: TargetOptions {
+ families: vec!["unix".to_string()],
+ os: "espidf".to_string(),
+ env: "newlib".to_string(),
+ vendor: "espressif".to_string(),
+ linker_flavor: LinkerFlavor::Gcc,
+ linker: Some("riscv32-esp-elf-gcc".to_string()),
+ cpu: "generic-rv32".to_string(),
+
+ // While the RiscV32IMC architecture does not natively support atomics, ESP-IDF does support
+ // the __atomic* and __sync* GCC builtins, so setting `max_atomic_width` to `Some(32)`
+ // and `atomic_cas` to `true` will cause the compiler to emit libcalls to these builtins.
+ //
+ // Support for atomics is necessary for the Rust STD library, which is supported by the ESP-IDF framework.
+ max_atomic_width: Some(32),
+ atomic_cas: true,
+
+ features: "+m,+c".to_string(),
+ executables: true,
+ panic_strategy: PanicStrategy::Abort,
+ relocation_model: RelocModel::Static,
+ emit_debug_gdb_scripts: false,
+ eh_frame_header: false,
+ ..Default::default()
+ },
+ }
+}
// LLVM is eager to trash the link register when calling `noreturn` functions, which
// breaks debugging. Preserve LR by default to prevent that from happening.
frame_pointer: FramePointer::Always,
+ // ARM supports multiple ABIs for enums, the linux one matches the default of 32 here
+ // but any arm-none or thumb-none target will be defaulted to 8 on GCC and clang
+ c_enum_min_bits: 8,
..Default::default()
}
}
| sym::maxnumf64
| sym::type_name
| sym::forget
+ | sym::black_box
| sym::variant_count => hir::Unsafety::Normal,
_ => hir::Unsafety::Unsafe,
}
(1, vec![param_ty; 2], tcx.types.bool)
}
+ sym::black_box => (1, vec![param(0)], param(0)),
+
other => {
tcx.sess.emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other });
return;
};
use rustc_session::lint;
use rustc_span::sym;
-use rustc_span::{MultiSpan, Span, Symbol};
+use rustc_span::{MultiSpan, Span, Symbol, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_data_structures::stable_map::FxHashMap;
for (captured_hir_id, captured_name, reasons) in diagnostics_info.iter() {
if let Some(captured_hir_id) = captured_hir_id {
let cause_span = self.tcx.hir().span(*captured_hir_id);
- diagnostics_builder.span_label(cause_span, format!("in Rust 2018, closure captures all of `{}`, but in Rust 2021, it only captures `{}`",
+ diagnostics_builder.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
self.tcx.hir().name(*var_hir_id),
captured_name,
));
if reasons.contains("drop order") {
let drop_location_span = drop_location_span(self.tcx, &closure_hir_id);
- diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` would be dropped here, but in Rust 2021, only `{}` would be dropped here alongside the closure",
+ diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure",
self.tcx.hir().name(*var_hir_id),
captured_name,
));
if reasons.contains("trait implementation") {
let missing_trait = &reasons[..reasons.find("trait implementation").unwrap() - 1];
- diagnostics_builder.span_label(closure_head_span, format!("in Rust 2018, this closure would implement {} as `{}` implements {}, but in Rust 2021, this closure would no longer implement {} as `{}` does not implement {}",
+ diagnostics_builder.span_label(closure_head_span, format!("in Rust 2018, this closure implements {} as `{}` implements {}, but in Rust 2021, this closure will no longer implement {} as `{}` does not implement {}",
missing_trait,
self.tcx.hir().name(*var_hir_id),
missing_trait,
}
}
diagnostics_builder.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>");
- let closure_body_span = self.tcx.hir().span(body_id.hir_id);
- let (sugg, app) =
+
+ let mut closure_body_span = self.tcx.hir().span(body_id.hir_id);
+
+ // If the body was entirely expanded from a macro
+ // invocation, i.e. the body is not contained inside the
+ // closure span, then we walk up the expansion until we
+ // find the span before the expansion.
+ while !closure_body_span.is_dummy() && !closure_span.contains(closure_body_span) {
+ closure_body_span = closure_body_span.parent().unwrap_or(DUMMY_SP);
+ }
+
+ let (span, sugg, app) =
match self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
Ok(s) => {
let trimmed = s.trim_start();
+ let mut lines = trimmed.lines();
+ let line1 = lines.next().unwrap_or_default();
// If the closure contains a block then replace the opening brace
// with "{ let _ = (..); "
- let sugg = if let Some('{') = trimmed.chars().next() {
- format!("{{ {}; {}", migration_string, &trimmed[1..])
+ let sugg = if line1.trim_end() == "{" {
+ // This is a multi-line closure with just a `{` on the first line,
+ // so we put the `let` on its own line.
+ // We take the indentation from the next non-empty line.
+ let line2 = lines.filter(|line| !line.is_empty()).next().unwrap_or_default();
+ let indent = line2.split_once(|c: char| !c.is_whitespace()).unwrap_or_default().0;
+ format!("{{\n{}{};{}", indent, migration_string, &trimmed[line1.len()..])
+ } else if line1.starts_with('{') {
+ format!("{{ {}; {}", migration_string, &trimmed[1..].trim_start())
} else {
format!("{{ {}; {} }}", migration_string, s)
};
- (sugg, Applicability::MachineApplicable)
+ (closure_body_span, sugg, Applicability::MachineApplicable)
}
- Err(_) => (migration_string.clone(), Applicability::HasPlaceholders),
+ Err(_) => (closure_span, migration_string.clone(), Applicability::HasPlaceholders),
};
let diagnostic_msg = format!(
);
diagnostics_builder.span_suggestion(
- closure_body_span,
+ span,
&diagnostic_msg,
sugg,
app,
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let trait_item = tcx.hir().expect_trait_item(hir_id);
- let method_sig = match trait_item.kind {
- hir::TraitItemKind::Fn(ref sig, _) => Some(sig),
- _ => None,
+ let (method_sig, span) = match trait_item.kind {
+ hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
+ hir::TraitItemKind::Type(_bounds, Some(ty)) => (None, ty.span),
+ _ => (None, trait_item.span),
};
check_object_unsafe_self_trait_by_name(tcx, &trait_item);
- check_associated_item(tcx, trait_item.hir_id(), trait_item.span, method_sig);
+ check_associated_item(tcx, trait_item.hir_id(), span, method_sig);
}
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let impl_item = tcx.hir().expect_impl_item(hir_id);
- let method_sig = match impl_item.kind {
- hir::ImplItemKind::Fn(ref sig, _) => Some(sig),
- _ => None,
+ let (method_sig, span) = match impl_item.kind {
+ hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
+ hir::ImplItemKind::TyAlias(ty) => (None, ty.span),
+ _ => (None, impl_item.span),
};
- check_associated_item(tcx, impl_item.hir_id(), impl_item.span, method_sig);
+ check_associated_item(tcx, impl_item.hir_id(), span, method_sig);
}
fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
// in some other location, or we'll end up emitting an error due
// to the lack of defining usage
if !skip_add {
- let old_concrete_ty = self
- .typeck_results
- .concrete_opaque_types
- .insert(opaque_type_key, definition_ty);
- if let Some(old_concrete_ty) = old_concrete_ty {
- if old_concrete_ty != definition_ty {
- span_bug!(
- span,
- "`visit_opaque_types` tried to write different types for the same \
- opaque type: {:?}, {:?}, {:?}, {:?}",
- opaque_type_key.def_id,
- definition_ty,
- opaque_defn,
- old_concrete_ty,
- );
- }
- }
+ self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id);
}
}
}
}
// Calling `mir_borrowck` can lead to cycle errors through
// const-checking, avoid calling it if we don't have to.
- if self
- .tcx
- .typeck(def_id)
- .concrete_opaque_types
- .any_value_matching(|(key, _)| key.def_id == self.def_id)
- .is_none()
- {
+ if !self.tcx.typeck(def_id).concrete_opaque_types.contains(&self.def_id) {
debug!("no constraints in typeck results");
return;
}
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
///
/// [`std::convert::identity`]: crate::convert::identity
-#[cfg_attr(not(miri), inline)]
-#[cfg_attr(miri, inline(never))]
+#[inline]
#[unstable(feature = "bench_black_box", issue = "64102")]
-#[cfg_attr(miri, allow(unused_mut))]
+#[cfg_attr(not(bootstrap), allow(unused_mut))]
pub fn black_box<T>(mut dummy: T) -> T {
- // We need to "use" the argument in some way LLVM can't introspect, and on
- // targets that support it we can typically leverage inline assembly to do
- // this. LLVM's interpretation of inline assembly is that it's, well, a black
- // box. This isn't the greatest implementation since it probably deoptimizes
- // more than we want, but it's so far good enough.
-
- #[cfg(not(miri))] // This is just a hint, so it is fine to skip in Miri.
+ #[cfg(bootstrap)]
// SAFETY: the inline assembly is a no-op.
unsafe {
- // FIXME: Cannot use `asm!` because it doesn't support MIPS and other architectures.
llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
+ dummy
}
- dummy
+ #[cfg(not(bootstrap))]
+ {
+ crate::intrinsics::black_box(dummy)
+ }
}
/// which is UB if any of their inputs are `undef`.)
#[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")]
pub fn raw_eq<T>(a: &T, b: &T) -> bool;
+
+ /// See documentation of [`std::hint::black_box`] for details.
+ ///
+ /// [`std::hint::black_box`]: crate::hint::black_box
+ #[cfg(not(bootstrap))]
+ pub fn black_box<T>(dummy: T) -> T;
}
// Some functions are defined here because they accidentally got made
}
fn extend_one(&mut self, _item: ()) {}
}
+
+#[stable(feature = "extend_for_tuple", since = "1.56.0")]
+impl<A, B, ExtendA, ExtendB> Extend<(A, B)> for (ExtendA, ExtendB)
+where
+ ExtendA: Extend<A>,
+ ExtendB: Extend<B>,
+{
+ /// Allows to `extend` a tuple of collections that also implement `Extend`.
+ ///
+ /// See also: [`Iterator::unzip`]
+ ///
+ /// # Examples
+ /// ```
+ /// let mut tuple = (vec![0], vec![1]);
+ /// tuple.extend(vec![(2, 3), (4, 5), (6, 7)]);
+ /// assert_eq!(tuple.0, vec![0, 2, 4, 6]);
+ /// assert_eq!(tuple.1, vec![1, 3, 5, 7]);
+ ///
+ /// // also allows for arbitrarily nested tuples
+ /// let mut nested_tuple = (vec![(1, -1)], vec![(2, -2)]);
+ /// nested_tuple.extend(vec![((3, -3), (4, -4)), ((5, -5), (6, -6))]);
+ ///
+ /// assert_eq!(nested_tuple.0, vec![(1, -1), (3, -3), (5, -5)]);
+ /// assert_eq!(nested_tuple.1, vec![(2, -2), (4, -4), (6, -6)]);
+ /// ```
+ fn extend<T: IntoIterator<Item = (A, B)>>(&mut self, into_iter: T) {
+ let (a, b) = self;
+ let iter = into_iter.into_iter();
+
+ fn extend<'a, A, B>(
+ a: &'a mut impl Extend<A>,
+ b: &'a mut impl Extend<B>,
+ ) -> impl FnMut((), (A, B)) + 'a {
+ move |(), (t, u)| {
+ a.extend_one(t);
+ b.extend_one(u);
+ }
+ }
+
+ let (lower_bound, _) = iter.size_hint();
+ if lower_bound > 0 {
+ a.extend_reserve(lower_bound);
+ b.extend_reserve(lower_bound);
+ }
+
+ iter.fold((), extend(a, b));
+ }
+
+ fn extend_one(&mut self, item: (A, B)) {
+ self.0.extend_one(item.0);
+ self.1.extend_one(item.1);
+ }
+
+ fn extend_reserve(&mut self, additional: usize) {
+ self.0.extend_reserve(additional);
+ self.1.extend_reserve(additional);
+ }
+}
///
/// assert_eq!(left, [1, 3]);
/// assert_eq!(right, [2, 4]);
+ ///
+ /// // you can also unzip multiple nested tuples at once
+ /// let a = [(1, (2, 3)), (4, (5, 6))];
+ ///
+ /// let (x, (y, z)): (Vec<_>, (Vec<_>, Vec<_>)) = a.iter().cloned().unzip();
+ /// assert_eq!(x, [1, 4]);
+ /// assert_eq!(y, [2, 5]);
+ /// assert_eq!(z, [3, 6]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB)
FromB: Default + Extend<B>,
Self: Sized + Iterator<Item = (A, B)>,
{
- fn extend<'a, A, B>(
- ts: &'a mut impl Extend<A>,
- us: &'a mut impl Extend<B>,
- ) -> impl FnMut((), (A, B)) + 'a {
- move |(), (t, u)| {
- ts.extend_one(t);
- us.extend_one(u);
- }
- }
-
- let mut ts: FromA = Default::default();
- let mut us: FromB = Default::default();
-
- let (lower_bound, _) = self.size_hint();
- if lower_bound > 0 {
- ts.extend_reserve(lower_bound);
- us.extend_reserve(lower_bound);
- }
-
- self.fold((), extend(&mut ts, &mut us));
-
- (ts, us)
+ let mut unzipped: (FromA, FromB) = Default::default();
+ unzipped.extend(self);
+ unzipped
}
/// Creates an iterator which copies all of its elements.
} else if #[cfg(any(
all(target_family = "windows", target_env = "gnu"),
target_os = "psp",
- target_family = "unix",
+ all(target_family = "unix", not(target_os = "espidf")),
all(target_vendor = "fortanix", target_env = "sgx"),
))] {
// Rust runtime's startup objects depend on these symbols, so make them public.
// - arch=wasm32
// - os=none ("bare metal" targets)
// - os=uefi
+ // - os=espidf
// - nvptx64-nvidia-cuda
// - arch=avr
#[path = "dummy.rs"]
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
-libc = { version = "0.2.98", default-features = false, features = ['rustc-dep-of-std'] }
+libc = { version = "0.2.99", default-features = false, features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "0.1.44" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
|| target.contains("vxworks")
|| target.contains("wasm32")
|| target.contains("asmjs")
+ || target.contains("espidf")
{
// These platforms don't have any special requirements.
} else {
--- /dev/null
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
+
+#[allow(deprecated)]
+use crate::os::espidf::raw;
+
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: crate::fs::Metadata
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+ #[stable(feature = "metadata_ext", since = "1.1.0")]
+ #[rustc_deprecated(
+ since = "1.8.0",
+ reason = "deprecated in favor of the accessor \
+ methods of this trait"
+ )]
+ #[allow(deprecated)]
+ fn as_raw_stat(&self) -> &raw::stat;
+
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_dev(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_ino(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_mode(&self) -> u32;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_nlink(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_uid(&self) -> u32;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_gid(&self) -> u32;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_rdev(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_size(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_atime(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_atime_nsec(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_mtime(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_mtime_nsec(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_ctime(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_ctime_nsec(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_blksize(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_blocks(&self) -> u64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_spare4(&self) -> [u32; 2];
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for Metadata {
+ #[allow(deprecated)]
+ fn as_raw_stat(&self) -> &raw::stat {
+ unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat) }
+ }
+ fn st_dev(&self) -> u64 {
+ self.as_inner().as_inner().st_dev as u64
+ }
+ fn st_ino(&self) -> u64 {
+ self.as_inner().as_inner().st_ino as u64
+ }
+ fn st_mode(&self) -> u32 {
+ self.as_inner().as_inner().st_mode as u32
+ }
+ fn st_nlink(&self) -> u64 {
+ self.as_inner().as_inner().st_nlink as u64
+ }
+ fn st_uid(&self) -> u32 {
+ self.as_inner().as_inner().st_uid as u32
+ }
+ fn st_gid(&self) -> u32 {
+ self.as_inner().as_inner().st_gid as u32
+ }
+ fn st_rdev(&self) -> u64 {
+ self.as_inner().as_inner().st_rdev as u64
+ }
+ fn st_size(&self) -> u64 {
+ self.as_inner().as_inner().st_size as u64
+ }
+ fn st_atime(&self) -> i64 {
+ self.as_inner().as_inner().st_atime as i64
+ }
+ fn st_atime_nsec(&self) -> i64 {
+ 0
+ }
+ fn st_mtime(&self) -> i64 {
+ self.as_inner().as_inner().st_mtime as i64
+ }
+ fn st_mtime_nsec(&self) -> i64 {
+ 0
+ }
+ fn st_ctime(&self) -> i64 {
+ self.as_inner().as_inner().st_ctime as i64
+ }
+ fn st_ctime_nsec(&self) -> i64 {
+ 0
+ }
+ fn st_blksize(&self) -> u64 {
+ self.as_inner().as_inner().st_blksize as u64
+ }
+ fn st_blocks(&self) -> u64 {
+ self.as_inner().as_inner().st_blocks as u64
+ }
+ fn st_spare4(&self) -> [u32; 2] {
+ let spare4 = self.as_inner().as_inner().st_spare4;
+ [spare4[0] as u32, spare4[1] as u32]
+ }
+}
--- /dev/null
+//! Definitions for the ESP-IDF framework.
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod fs;
+pub mod raw;
--- /dev/null
+//! Raw type definitions for the ESP-IDF framework.
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+#![rustc_deprecated(
+ since = "1.8.0",
+ reason = "these type aliases are no longer supported by \
+ the standard library, the `libc` crate on \
+ crates.io should be used instead for the correct \
+ definitions"
+)]
+
+use crate::os::raw::c_long;
+use crate::os::unix::raw::{gid_t, uid_t};
+
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub type pthread_t = libc::pthread_t;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type blkcnt_t = libc::blkcnt_t;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type blksize_t = libc::blksize_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type dev_t = libc::dev_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type ino_t = libc::ino_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type mode_t = libc::mode_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type nlink_t = libc::nlink_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type off_t = libc::off_t;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type time_t = libc::time_t;
+
+#[repr(C)]
+#[derive(Clone)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub struct stat {
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_dev: dev_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_ino: ino_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_mode: mode_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_nlink: nlink_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_uid: uid_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_gid: gid_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_rdev: dev_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_size: off_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_atime: time_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_mtime: time_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_ctime: time_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_blksize: blksize_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_blocks: blkcnt_t,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_spare4: [c_long; 2usize],
+}
pub mod dragonfly;
#[cfg(target_os = "emscripten")]
pub mod emscripten;
+ #[cfg(target_os = "espidf")]
+ pub mod espidf;
#[cfg(target_os = "freebsd")]
pub mod freebsd;
#[cfg(target_os = "fuchsia")]
pub use crate::os::dragonfly::*;
#[cfg(target_os = "emscripten")]
pub use crate::os::emscripten::*;
+ #[cfg(target_os = "espidf")]
+ pub use crate::os::espidf::*;
#[cfg(target_os = "freebsd")]
pub use crate::os::freebsd::*;
#[cfg(target_os = "fuchsia")]
target_arch = "asmjs",
target_arch = "wasm32",
target_arch = "hexagon",
- target_arch = "riscv32"
+ target_arch = "riscv32",
+ target_arch = "xtensa"
)))]
pub const MIN_ALIGN: usize = 8;
#[cfg(all(any(
target_os = "android",
target_os = "illumos",
target_os = "redox",
- target_os = "solaris"
+ target_os = "solaris",
+ target_os = "espidf"
))] {
#[inline]
unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
Args { iter: res.into_iter() }
}
}
+
+#[cfg(target_os = "espidf")]
+mod imp {
+ use super::Args;
+
+ #[inline(always)]
+ pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
+
+ pub fn args() -> Args {
+ Args { iter: Vec::new().into_iter() }
+ }
+}
))]
pub unsafe fn init(&mut self) {}
+ // NOTE: ESP-IDF's PTHREAD_COND_INITIALIZER support is not released yet
+ // So on that platform, init() should always be called
+ // Moreover, that platform does not have pthread_condattr_setclock support,
+ // hence that initialization should be skipped as well
+ #[cfg(target_os = "espidf")]
+ pub unsafe fn init(&mut self) {
+ let r = libc::pthread_cond_init(self.inner.get(), crate::ptr::null());
+ assert_eq!(r, 0);
+ }
+
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_os = "l4re",
target_os = "android",
- target_os = "redox"
+ target_os = "redox",
+ target_os = "espidf"
)))]
pub unsafe fn init(&mut self) {
use crate::mem::MaybeUninit;
// where we configure condition variable to use monotonic clock (instead of
// default system clock). This approach avoids all problems that result
// from changes made to the system time.
- #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "android")))]
+ #[cfg(not(any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "android",
+ target_os = "espidf"
+ )))]
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
use crate::mem;
// This implementation is modeled after libcxx's condition_variable
// https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
// https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
+ #[cfg(any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "android",
+ target_os = "espidf"
+ ))]
pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
use crate::ptr;
use crate::time::Instant;
pub const EXE_SUFFIX: &str = "";
pub const EXE_EXTENSION: &str = "";
}
+
+#[cfg(target_os = "espidf")]
+pub mod os {
+ pub const FAMILY: &str = "unix";
+ pub const OS: &str = "espidf";
+ pub const DLL_PREFIX: &str = "lib";
+ pub const DLL_SUFFIX: &str = ".so";
+ pub const DLL_EXTENSION: &str = "so";
+ pub const EXE_SUFFIX: &str = "";
+ pub const EXE_EXTENSION: &str = "";
+}
Ok(ret as usize)
}
+ #[cfg(not(target_os = "espidf"))]
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
let ret = cvt(unsafe {
libc::readv(
Ok(ret as usize)
}
+ #[cfg(target_os = "espidf")]
+ pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+ return crate::io::default_read_vectored(|b| self.read(b), bufs);
+ }
+
#[inline]
pub fn is_read_vectored(&self) -> bool {
- true
+ cfg!(not(target_os = "espidf"))
}
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
Ok(ret as usize)
}
+ #[cfg(not(target_os = "espidf"))]
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
let ret = cvt(unsafe {
libc::writev(
Ok(ret as usize)
}
+ #[cfg(target_os = "espidf")]
+ pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+ return crate::io::default_write_vectored(|b| self.write(b), bufs);
+ }
+
#[inline]
pub fn is_write_vectored(&self) -> bool {
- true
+ cfg!(not(target_os = "espidf"))
}
pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
}
}
#[cfg(any(
- target_env = "newlib",
+ all(target_env = "newlib", not(target_os = "espidf")),
target_os = "solaris",
target_os = "illumos",
target_os = "emscripten",
Ok(())
}
}
+ #[cfg(target_os = "espidf")]
+ pub fn set_cloexec(&self) -> io::Result<()> {
+ // FD_CLOEXEC is not supported in ESP-IDF but there's no need to,
+ // because ESP-IDF does not support spawning processes either.
+ Ok(())
+ }
#[cfg(target_os = "linux")]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
// We want to atomically duplicate this file descriptor and set the
// CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
// is a POSIX flag that was added to Linux in 2.6.24.
- let fd = cvt(unsafe { libc::fcntl(self.raw(), libc::F_DUPFD_CLOEXEC, 0) })?;
+ #[cfg(not(target_os = "espidf"))]
+ let cmd = libc::F_DUPFD_CLOEXEC;
+
+ // For ESP-IDF, F_DUPFD is used instead, because the CLOEXEC semantics
+ // will never be supported, as this is a bare metal framework with
+ // no capabilities for multi-process execution. While F_DUPFD is also
+ // not supported yet, it might be (currently it returns ENOSYS).
+ #[cfg(target_os = "espidf")]
+ let cmd = libc::F_DUPFD;
+
+ let fd = cvt(unsafe { libc::fcntl(self.raw(), cmd, 0) })?;
Ok(FileDesc::new(fd))
}
}
#[cfg(not(target_os = "netbsd"))]
impl FileAttr {
- #[cfg(not(target_os = "vxworks"))]
+ #[cfg(all(not(target_os = "vxworks"), not(target_os = "espidf")))]
pub fn modified(&self) -> io::Result<SystemTime> {
Ok(SystemTime::from(libc::timespec {
tv_sec: self.stat.st_mtime as libc::time_t,
}))
}
- #[cfg(target_os = "vxworks")]
+ #[cfg(any(target_os = "vxworks", target_os = "espidf"))]
pub fn modified(&self) -> io::Result<SystemTime> {
Ok(SystemTime::from(libc::timespec {
tv_sec: self.stat.st_mtime as libc::time_t,
}))
}
- #[cfg(not(target_os = "vxworks"))]
+ #[cfg(all(not(target_os = "vxworks"), not(target_os = "espidf")))]
pub fn accessed(&self) -> io::Result<SystemTime> {
Ok(SystemTime::from(libc::timespec {
tv_sec: self.stat.st_atime as libc::time_t,
}))
}
- #[cfg(target_os = "vxworks")]
+ #[cfg(any(target_os = "vxworks", target_os = "espidf"))]
pub fn accessed(&self) -> io::Result<SystemTime> {
Ok(SystemTime::from(libc::timespec {
tv_sec: self.stat.st_atime as libc::time_t,
target_os = "l4re",
target_os = "fuchsia",
target_os = "redox",
- target_os = "vxworks"
+ target_os = "vxworks",
+ target_os = "espidf"
))]
pub fn ino(&self) -> u64 {
self.entry.d_ino as u64
target_os = "emscripten",
target_os = "l4re",
target_os = "haiku",
- target_os = "vxworks"
+ target_os = "vxworks",
+ target_os = "espidf"
))]
fn name_bytes(&self) -> &[u8] {
unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes() }
let original = cstr(original)?;
let link = cstr(link)?;
cfg_if::cfg_if! {
- if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android"))] {
- // VxWorks and Redox lack `linkat`, so use `link` instead. POSIX leaves
+ if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf"))] {
+ // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
// it implementation-defined whether `link` follows symlinks, so rely on the
// `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
// Android has `linkat` on newer versions, but we happen to know `link`
Ok((reader, metadata))
}
+#[cfg(target_os = "espidf")]
+fn open_to_and_set_permissions(
+ to: &Path,
+ reader_metadata: crate::fs::Metadata,
+) -> io::Result<(crate::fs::File, crate::fs::Metadata)> {
+ use crate::fs::OpenOptions;
+ let writer = OpenOptions::new().open(to)?;
+ let writer_metadata = writer.metadata()?;
+ Ok((writer, writer_metadata))
+}
+
+#[cfg(not(target_os = "espidf"))]
fn open_to_and_set_permissions(
to: &Path,
reader_metadata: crate::fs::Metadata,
pub use self::rand::hashmap_random_keys;
pub use libc::strlen;
+#[cfg(not(target_os = "espidf"))]
#[macro_use]
pub mod weak;
pub mod thread_local_key;
pub mod time;
+#[cfg(target_os = "espidf")]
+pub fn init(argc: isize, argv: *const *const u8) {}
+
+#[cfg(not(target_os = "espidf"))]
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
pub unsafe fn init(argc: isize, argv: *const *const u8) {
extern "C" {}
}
}
+
+#[cfg(target_os = "espidf")]
+mod unsupported {
+ use crate::io;
+
+ pub fn unsupported<T>() -> io::Result<T> {
+ Err(unsupported_err())
+ }
+
+ pub fn unsupported_err() -> io::Error {
+ io::Error::new_const(
+ io::ErrorKind::Unsupported,
+ &"operation not supported on this platform",
+ )
+ }
+}
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::{Duration, Instant};
-use libc::{c_int, c_void, size_t, sockaddr, socklen_t, EAI_SYSTEM, MSG_PEEK};
+use libc::{c_int, c_void, size_t, sockaddr, socklen_t, MSG_PEEK};
pub use crate::sys::{cvt, cvt_r};
// We may need to trigger a glibc workaround. See on_resolver_failure() for details.
on_resolver_failure();
- if err == EAI_SYSTEM {
+ #[cfg(not(target_os = "espidf"))]
+ if err == libc::EAI_SYSTEM {
return Err(io::Error::last_os_error());
}
+ #[cfg(not(target_os = "espidf"))]
let detail = unsafe {
str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap().to_owned()
};
+
+ #[cfg(target_os = "espidf")]
+ let detail = "";
+
Err(io::Error::new(
io::ErrorKind::Uncategorized,
&format!("failed to lookup address information: {}", detail)[..],
}
}
+#[cfg(target_os = "espidf")]
+pub fn getcwd() -> io::Result<PathBuf> {
+ Ok(PathBuf::from("/"))
+}
+
+#[cfg(not(target_os = "espidf"))]
pub fn getcwd() -> io::Result<PathBuf> {
let mut buf = Vec::with_capacity(512);
loop {
}
}
+#[cfg(target_os = "espidf")]
+pub fn chdir(p: &path::Path) -> io::Result<()> {
+ super::unsupported::unsupported()
+}
+
+#[cfg(not(target_os = "espidf"))]
pub fn chdir(p: &path::Path) -> io::Result<()> {
let p: &OsStr = p.as_ref();
let p = CString::new(p.as_bytes())?;
path.canonicalize()
}
+#[cfg(target_os = "espidf")]
+pub fn current_exe() -> io::Result<PathBuf> {
+ super::unsupported::unsupported()
+}
+
pub struct Env {
iter: vec::IntoIter<(OsString, OsString)>,
}
}
}
+#[cfg(not(target_os = "espidf"))]
pub fn page_size() -> usize {
unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize }
}
target_os = "ios",
target_os = "emscripten",
target_os = "redox",
- target_os = "vxworks"
+ target_os = "vxworks",
+ target_os = "espidf"
))]
unsafe fn fallback() -> Option<OsString> {
None
target_os = "ios",
target_os = "emscripten",
target_os = "redox",
- target_os = "vxworks"
+ target_os = "vxworks",
+ target_os = "espidf"
)))]
unsafe fn fallback() -> Option<OsString> {
let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
} else if #[cfg(target_os = "vxworks")] {
#[path = "process_vxworks.rs"]
mod process_inner;
+ } else if #[cfg(target_os = "espidf")] {
+ #[path = "process_unsupported.rs"]
+ mod process_inner;
} else {
#[path = "process_unix.rs"]
mod process_inner;
--- /dev/null
+use crate::convert::{TryFrom, TryInto};
+use crate::fmt;
+use crate::io;
+use crate::io::ErrorKind;
+use crate::num::NonZeroI32;
+use crate::os::raw::NonZero_c_int;
+use crate::sys;
+use crate::sys::cvt;
+use crate::sys::pipe::AnonPipe;
+use crate::sys::process::process_common::*;
+use crate::sys::unix::unsupported::*;
+
+use libc::{c_int, pid_t};
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+impl Command {
+ pub fn spawn(
+ &mut self,
+ default: Stdio,
+ needs_stdin: bool,
+ ) -> io::Result<(Process, StdioPipes)> {
+ unsupported()
+ }
+
+ pub fn exec(&mut self, default: Stdio) -> io::Error {
+ unsupported_err()
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Processes
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct Process {
+ handle: pid_t,
+}
+
+impl Process {
+ pub fn id(&self) -> u32 {
+ 0
+ }
+
+ pub fn kill(&mut self) -> io::Result<()> {
+ unsupported()
+ }
+
+ pub fn wait(&mut self) -> io::Result<ExitStatus> {
+ unsupported()
+ }
+
+ pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
+ unsupported()
+ }
+}
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitStatus(c_int);
+
+impl ExitStatus {
+ pub fn success(&self) -> bool {
+ self.code() == Some(0)
+ }
+
+ pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
+ Err(ExitStatusError(1.try_into().unwrap()))
+ }
+
+ pub fn code(&self) -> Option<i32> {
+ None
+ }
+
+ pub fn signal(&self) -> Option<i32> {
+ None
+ }
+
+ pub fn core_dumped(&self) -> bool {
+ false
+ }
+
+ pub fn stopped_signal(&self) -> Option<i32> {
+ None
+ }
+
+ pub fn continued(&self) -> bool {
+ false
+ }
+
+ pub fn into_raw(&self) -> c_int {
+ 0
+ }
+}
+
+/// Converts a raw `c_int` to a type-safe `ExitStatus` by wrapping it without copying.
+impl From<c_int> for ExitStatus {
+ fn from(a: c_int) -> ExitStatus {
+ ExitStatus(a as i32)
+ }
+}
+
+impl fmt::Display for ExitStatus {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "exit code: {}", self.0)
+ }
+}
+
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitStatusError(NonZero_c_int);
+
+impl Into<ExitStatus> for ExitStatusError {
+ fn into(self) -> ExitStatus {
+ ExitStatus(self.0.into())
+ }
+}
+
+impl ExitStatusError {
+ pub fn code(self) -> Option<NonZeroI32> {
+ ExitStatus(self.0.into()).code().map(|st| st.try_into().unwrap())
+ }
+}
unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) }
}
- #[cfg(not(any(target_os = "linux", target_os = "android")))]
+ #[cfg(target_os = "espidf")]
+ fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
+ unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }
+ }
+
+ #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "espidf")))]
fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool {
false
}
- #[cfg(any(target_os = "linux", target_os = "android"))]
+ #[cfg(any(target_os = "linux", target_os = "android", target_os = "espidf"))]
fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sys::os::errno;
#[cfg(any(target_os = "linux", target_os = "solaris", target_os = "illumos"))]
use crate::sys::weak::weak;
-#[cfg(not(any(target_os = "l4re", target_os = "vxworks")))]
+#[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))]
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
#[cfg(target_os = "l4re")]
pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024;
#[cfg(target_os = "vxworks")]
pub const DEFAULT_MIN_STACK_SIZE: usize = 256 * 1024;
+#[cfg(target_os = "espidf")]
+pub const DEFAULT_MIN_STACK_SIZE: usize = 0; // 0 indicates that the stack size configured in the ESP-IDF menuconfig system should be used
#[cfg(target_os = "fuchsia")]
mod zircon {
let mut attr: libc::pthread_attr_t = mem::zeroed();
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
- let stack_size = cmp::max(stack, min_stack_size(&attr));
-
- match libc::pthread_attr_setstacksize(&mut attr, stack_size) {
- 0 => {}
- n => {
- assert_eq!(n, libc::EINVAL);
- // EINVAL means |stack_size| is either too small or not a
- // multiple of the system page size. Because it's definitely
- // >= PTHREAD_STACK_MIN, it must be an alignment issue.
- // Round up to the nearest page and try again.
- let page_size = os::page_size();
- let stack_size =
- (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1);
- assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
- }
- };
+ #[cfg(target_os = "espidf")]
+ if stack > 0 {
+ // Only set the stack if a non-zero value is passed
+ // 0 is used as an indication that the default stack size configured in the ESP-IDF menuconfig system should be used
+ assert_eq!(
+ libc::pthread_attr_setstacksize(&mut attr, cmp::max(stack, min_stack_size(&attr))),
+ 0
+ );
+ }
+
+ #[cfg(not(target_os = "espidf"))]
+ {
+ let stack_size = cmp::max(stack, min_stack_size(&attr));
+
+ match libc::pthread_attr_setstacksize(&mut attr, stack_size) {
+ 0 => {}
+ n => {
+ assert_eq!(n, libc::EINVAL);
+ // EINVAL means |stack_size| is either too small or not a
+ // multiple of the system page size. Because it's definitely
+ // >= PTHREAD_STACK_MIN, it must be an alignment issue.
+ // Round up to the nearest page and try again.
+ let page_size = os::page_size();
+ let stack_size =
+ (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1);
+ assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
+ }
+ };
+ }
let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _);
// Note: if the thread creation fails and this assert fails, then p will
// Newlib, Emscripten, and VxWorks have no way to set a thread name.
}
+ #[cfg(not(target_os = "espidf"))]
pub fn sleep(dur: Duration) {
let mut secs = dur.as_secs();
let mut nsecs = dur.subsec_nanos() as _;
}
}
+ #[cfg(target_os = "espidf")]
+ pub fn sleep(dur: Duration) {
+ let mut micros = dur.as_micros();
+ unsafe {
+ while micros > 0 {
+ let st = if micros > u32::MAX as u128 { u32::MAX } else { micros as u32 };
+ libc::usleep(st);
+
+ micros -= st as u128;
+ }
+ }
+ }
+
pub fn join(self) {
unsafe {
let ret = libc::pthread_join(self.id, ptr::null_mut());
}
}
- #[cfg(not(target_os = "dragonfly"))]
+ #[cfg(not(any(target_os = "dragonfly", target_os = "espidf")))]
pub type clock_t = libc::c_int;
- #[cfg(target_os = "dragonfly")]
+ #[cfg(any(target_os = "dragonfly", target_os = "espidf"))]
pub type clock_t = libc::c_ulong;
fn now(clock: clock_t) -> Timespec {
#[cfg(test)]
mod tests;
-use crate::borrow::Borrow;
use crate::cmp;
use crate::collections::BTreeMap;
use crate::convert::{TryFrom, TryInto};
utf16: Vec<u16>,
}
+impl EnvKey {
+ fn new<T: Into<OsString>>(key: T) -> Self {
+ EnvKey::from(key.into())
+ }
+}
+
// Comparing Windows environment variable keys[1] are behaviourally the
// composition of two operations[2]:
//
}
}
}
+impl PartialOrd<str> for EnvKey {
+ fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
+ Some(self.cmp(&EnvKey::new(other)))
+ }
+}
+impl PartialEq<str> for EnvKey {
+ fn eq(&self, other: &str) -> bool {
+ if self.os_string.len() != other.len() {
+ false
+ } else {
+ self.cmp(&EnvKey::new(other)) == cmp::Ordering::Equal
+ }
+ }
+}
// Environment variable keys should preserve their original case even though
// they are compared using a caseless string mapping.
}
}
-impl Borrow<OsStr> for EnvKey {
- fn borrow(&self) -> &OsStr {
- &self.os_string
+impl From<&OsStr> for EnvKey {
+ fn from(k: &OsStr) -> Self {
+ Self::from(k.to_os_string())
}
}
// to read the *child's* PATH if one is provided. See #15149 for more
// details.
let program = maybe_env.as_ref().and_then(|env| {
- if let Some(v) = env.get(OsStr::new("PATH")) {
+ if let Some(v) = env.get(&EnvKey::new("PATH")) {
// Split the value and test each path to see if the
// program exists.
for path in split_paths(&v) {
-pub const DEFAULT_BUF_SIZE: usize = 8 * 1024;
+// Bare metal platforms usually have very small amounts of RAM
+// (in the order of hundreds of KB)
+pub const DEFAULT_BUF_SIZE: usize = if cfg!(target_os = "espidf") { 512 } else { 8 * 1024 };
#[cfg(test)]
#[allow(dead_code)] // not used on emscripten
// The following functions build up changes
pub fn set(&mut self, key: &OsStr, value: &OsStr) {
+ let key = EnvKey::from(key);
self.maybe_saw_path(&key);
- self.vars.insert(key.to_owned().into(), Some(value.to_owned()));
+ self.vars.insert(key, Some(value.to_owned()));
}
pub fn remove(&mut self, key: &OsStr) {
+ let key = EnvKey::from(key);
self.maybe_saw_path(&key);
if self.clear {
- self.vars.remove(key);
+ self.vars.remove(&key);
} else {
- self.vars.insert(key.to_owned().into(), None);
+ self.vars.insert(key, None);
}
}
self.saw_path || self.clear
}
- fn maybe_saw_path(&mut self, key: &OsStr) {
+ fn maybe_saw_path(&mut self, key: &EnvKey) {
if !self.saw_path && key == "PATH" {
self.saw_path = true;
}
} else if #[cfg(any(
target_os = "l4re",
target_os = "none",
+ target_os = "espidf",
))] {
// These "unix" family members do not have unwinder.
// Note this also matches x86_64-unknown-none-linuxkernel.
-Subproject commit a07036f864b37896b31eb996cd7aedb489f69a1f
+Subproject commit 7e49659102f0977d9142190e1ba23345c0f00eb1
-Subproject commit 09986cd352404eb4659db44613b27cac9aa652fc
+Subproject commit 4f9fcaa30d11ba52b641e6fd5206536d65838af9
-Subproject commit f51734eb5566c826b471977747ea3d7d6915bbe9
+Subproject commit 0c7e5bd1428e7838252bb57b7f0fbfda4ec82f02
-Subproject commit 3b7be075af5d6e402a18efff672a8a265b4596fd
+Subproject commit 4884fe45c14f8b22121760fb117181bb4da8dfe0
-Subproject commit 09343d6f921d2a07c66f8c41ec3d65bf1fa52556
+Subproject commit c4644b427cbdaafc7a87be0ccdf5d8aaa07ac35f
`powerpc64le-unknown-linux-musl` | ? | |
`riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33)
`riscv32gc-unknown-linux-musl` | | | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches)
+`riscv32imc-esp-espidf` | ✓ | | RISC-V ESP-IDF
`riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0)
`s390x-unknown-linux-musl` | | | S390x Linux (kernel 2.6.32, MUSL)
`sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux
--- /dev/null
+// This test check for headers text and background colors for the different themes.
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+
+// This is needed so that the text color is computed.
+show-text: true
+
+// Ayu theme
+local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"}
+reload:
+
+assert-css: (".impl", {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"}, ALL)
+assert-css: (".impl .code-header", {"color": "rgb(230, 225, 207)", "background-color": "rgb(15, 20, 25)"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl
+assert-css: ("#impl", {"color": "rgb(197, 197, 197)", "background-color": "rgba(255, 236, 164, 0.06)"})
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
+assert-css: ("#method\.must_use", {"color": "rgb(197, 197, 197)", "background-color": "rgba(255, 236, 164, 0.06)"}, ALL)
+
+// Dark theme
+local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+
+assert-css: (".impl", {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, ALL)
+assert-css: (".impl .code-header", {"color": "rgb(221, 221, 221)", "background-color": "rgb(53, 53, 53)"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl
+assert-css: ("#impl", {"color": "rgb(221, 221, 221)", "background-color": "rgb(73, 74, 61)"})
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
+assert-css: ("#method\.must_use", {"color": "rgb(221, 221, 221)", "background-color": "rgb(73, 74, 61)"}, ALL)
+
+// Light theme
+local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
+reload:
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+
+assert-css: (".impl", {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, ALL)
+assert-css: (".impl .code-header", {"color": "rgb(0, 0, 0)", "background-color": "rgb(255, 255, 255)"}, ALL)
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl
+assert-css: ("#impl", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"})
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
+assert-css: ("#method\.must_use", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"}, ALL)
goto: file://|DOC_PATH|/test_docs/index.html
-// We set the theme so we're sure that the corect values will be used, whatever the computer
+// We set the theme so we're sure that the correct values will be used, whatever the computer
// this test is running on.
local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
// If the text isn't displayed, the browser doesn't compute color style correctly...
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
- --> $DIR/defaults-cyclic-fail-1.rs:26:5
+ --> $DIR/defaults-cyclic-fail-1.rs:26:14
|
LL | type A = Box<Self::B>;
- | ^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^
error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
- --> $DIR/defaults-cyclic-fail-1.rs:32:5
+ --> $DIR/defaults-cyclic-fail-1.rs:32:14
|
LL | type B = &'static Self::A;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
- --> $DIR/defaults-cyclic-fail-2.rs:27:5
+ --> $DIR/defaults-cyclic-fail-2.rs:27:14
|
LL | type A = Box<Self::B>;
- | ^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^
error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
- --> $DIR/defaults-cyclic-fail-2.rs:33:5
+ --> $DIR/defaults-cyclic-fail-2.rs:33:14
|
LL | type B = &'static Self::A;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
#[macro_export]
macro_rules! fancy_panic {
+ () => {
+ panic!("{}");
+ };
($msg:expr) => {
panic!($msg)
};
let fptr = SendPointer(&mut f as *mut i32);
thread::spawn(move || { let _ = &fptr; unsafe {
//~^ ERROR: `Send` trait implementation for closure
- //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
+ //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0 = 20;
- //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
} });
}
let fptr = SyncPointer(f);
thread::spawn(move || { let _ = &fptr; unsafe {
//~^ ERROR: `Sync`, `Send` trait implementation for closure
- //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+ //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0.0 = 20;
- //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
} });
}
fn test_clone_trait() {
let f = U(S(String::from("Hello World")), T(0));
- let c = || { let _ = &f;
+ let c = || {
+ let _ = &f;
//~^ ERROR: `Clone` trait implementation for closure and drop order
- //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f` to be fully captured
let f_1 = f.1;
- //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1`
println!("{:?}", f_1.0);
};
c_clone();
}
-//~^ NOTE: in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `f` is dropped here, but in Rust 2021, only `f.1` will be dropped here as part of the closure
fn main() {
test_send_trait();
let fptr = SendPointer(&mut f as *mut i32);
thread::spawn(move || unsafe {
//~^ ERROR: `Send` trait implementation for closure
- //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
+ //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0 = 20;
- //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
});
}
let fptr = SyncPointer(f);
thread::spawn(move || unsafe {
//~^ ERROR: `Sync`, `Send` trait implementation for closure
- //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+ //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0.0 = 20;
- //~^ NOTE: in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
});
}
let f = U(S(String::from("Hello World")), T(0));
let c = || {
//~^ ERROR: `Clone` trait implementation for closure and drop order
- //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f` to be fully captured
let f_1 = f.1;
- //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1`
println!("{:?}", f_1.0);
};
c_clone();
}
-//~^ NOTE: in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `f` is dropped here, but in Rust 2021, only `f.1` will be dropped here as part of the closure
fn main() {
test_send_trait();
--> $DIR/auto_traits.rs:14:19
|
LL | thread::spawn(move || unsafe {
- | ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Send` as `fptr` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr.0` does not implement `Send`
+ | ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
...
LL | *fptr.0 = 20;
- | ------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0`
+ | ------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
|
note: the lint level is defined here
--> $DIR/auto_traits.rs:2:9
--> $DIR/auto_traits.rs:34:19
|
LL | thread::spawn(move || unsafe {
- | ^^^^^^^^^^^^^^ in Rust 2018, this closure would implement `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
+ | ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Sync`, `Send` as `fptr` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr.0.0` does not implement `Sync`, `Send`
...
LL | *fptr.0.0 = 20;
- | --------- in Rust 2018, closure captures all of `fptr`, but in Rust 2021, it only captures `fptr.0.0`
+ | --------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `fptr` to be fully captured
--> $DIR/auto_traits.rs:58:13
|
LL | let c = || {
- | ^^ in Rust 2018, this closure would implement `Clone` as `f` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f.1` does not implement `Clone`
+ | ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f.1` does not implement `Clone`
...
LL | let f_1 = f.1;
- | --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.1`
+ | --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1`
...
LL | }
- | - in Rust 2018, `f` would be dropped here, but in Rust 2021, only `f.1` would be dropped here alongside the closure
+ | - in Rust 2018, `f` is dropped here, but in Rust 2021, only `f.1` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f` to be fully captured
|
-LL ~ let c = || { let _ = &f;
+LL ~ let c = || {
+LL + let _ = &f;
LL +
LL +
LL +
LL +
-LL + let f_1 = f.1;
...
error: aborting due to 3 previous errors
let t1 = (String::new(), String::new());
let t2 = (String::new(), String::new());
- let c = || { let _ = (&t, &t1, &t2);
+ let c = || {
+ let _ = (&t, &t1, &t2);
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _t1 = t1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
let _t2 = t2.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
-//~| in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
+//~| in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
// String implements drop and therefore should be migrated.
// But in this test cases, `t2` is completely captured and when it is dropped won't be affected
let t1 = (String::new(), String::new());
let t2 = (String::new(), String::new());
- let c = || { let _ = (&t, &t1);
+ let c = || {
+ let _ = (&t, &t1);
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _t1 = t1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
let _t2 = t2;
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
// If a variable would've not been captured by value then it would've not been
// dropped with the closure and therefore doesn't need migration.
fn test3_only_by_value_need_migration() {
let t = (String::new(), String::new());
let t1 = (String::new(), String::new());
- let c = || { let _ = &t;
+ let c = || {
+ let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
println!("{}", t1.1);
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
// Copy types get copied into the closure instead of move. Therefore we don't need to
// migrate then as their drop order isn't tied to the closure.
// `t1` is Copy because all of its elements are Copy
let t1 = (0i32, 0i32);
- let c = || { let _ = &t;
+ let c = || {
+ let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _t1 = t1.0;
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
fn test5_only_drop_types_need_migration() {
struct S(i32, i32);
// `s` doesn't implement Drop or any elements within it, and doesn't need migration
let s = S(0i32, 0i32);
- let c = || { let _ = &t;
+ let c = || {
+ let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _s = s.0;
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
// Since we are using a move closure here, both `t` and `t1` get moved
// even though they are being used by ref inside the closure.
fn test6_move_closures_non_copy_types_might_need_migration() {
let t = (String::new(), String::new());
let t1 = (String::new(), String::new());
- let c = move || { let _ = (&t1, &t);
+ let c = move || {
+ let _ = (&t1, &t);
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
println!("{} {}", t1.1, t.1);
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
- //~| NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
+ //~| NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
-//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
+//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
// Test migration analysis in case of Drop + Non Drop aggregates.
// Note we need migration here only because the non-copy (because Drop type) is captured,
fn test7_drop_non_drop_aggregate_need_migration() {
let t = (String::new(), String::new(), 0i32);
- let c = || { let _ = &t;
+ let c = || {
+ let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
fn main() {
test1_all_need_migration();
//~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _t1 = t1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
let _t2 = t2.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
-//~| in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
+//~| in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
// String implements drop and therefore should be migrated.
// But in this test cases, `t2` is completely captured and when it is dropped won't be affected
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _t1 = t1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
let _t2 = t2;
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
// If a variable would've not been captured by value then it would've not been
// dropped with the closure and therefore doesn't need migration.
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
println!("{}", t1.1);
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
// Copy types get copied into the closure instead of move. Therefore we don't need to
// migrate then as their drop order isn't tied to the closure.
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _t1 = t1.0;
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
fn test5_only_drop_types_need_migration() {
struct S(i32, i32);
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _s = s.0;
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
// Since we are using a move closure here, both `t` and `t1` get moved
// even though they are being used by ref inside the closure.
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
println!("{} {}", t1.1, t.1);
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
- //~| NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
+ //~| NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
-//~| in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
+//~| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
// Test migration analysis in case of Drop + Non Drop aggregates.
// Note we need migration here only because the non-copy (because Drop type) is captured,
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
};
c();
}
-//~^ in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
fn main() {
test1_all_need_migration();
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
LL |
LL | let _t1 = t1.0;
- | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+ | ---- in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
LL |
LL | let _t2 = t2.0;
- | ---- in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+ | ---- in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
...
LL | }
| -
| |
- | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
- | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
- | in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
+ | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+ | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
+ | in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
|
note: the lint level is defined here
--> $DIR/insignificant_drop.rs:3:9
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
|
-LL ~ let c = || { let _ = (&t, &t1, &t2);
+LL ~ let c = || {
+LL + let _ = (&t, &t1, &t2);
LL +
LL +
LL +
LL +
-LL + let _t = t.0;
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
LL |
LL | let _t1 = t1.0;
- | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+ | ---- in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
...
LL | }
| -
| |
- | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
- | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+ | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+ | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1` to be fully captured
|
-LL ~ let c = || { let _ = (&t, &t1);
+LL ~ let c = || {
+LL + let _ = (&t, &t1);
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
-LL ~ let c = || { let _ = &t;
+LL ~ let c = || {
+LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
-LL ~ let c = || { let _ = &t;
+LL ~ let c = || {
+LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
-LL ~ let c = || { let _ = &t;
+LL ~ let c = || {
+LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^^^^^^
...
LL | println!("{} {}", t1.1, t.1);
- | ---- --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ | ---- --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
| |
- | in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+ | in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
...
LL | }
| -
| |
- | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
- | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+ | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
+ | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t1`, `t` to be fully captured
|
-LL ~ let c = move || { let _ = (&t1, &t);
+LL ~ let c = move || {
+LL + let _ = (&t1, &t);
LL +
LL +
LL +
LL + println!("{} {}", t1.1, t.1);
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
-LL ~ let c = || { let _ = &t;
+LL ~ let c = || {
+LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: aborting due to 7 previous errors
fn significant_drop_needs_migration() {
let t = (SigDrop {}, SigDrop {});
- let c = || { let _ = &t;
+ let c = || {
+ let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
// Even if a type implements an insignificant drop, if it's
// elements have a significant drop then the overall type is
let t = Wrapper(GenericStruct(SigDrop {}, SigDrop {}), 5);
// move is used to force i32 to be copied instead of being a ref
- let c = move || { let _ = &t;
+ let c = move || {
+ let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.1;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
fn main() {
significant_drop_needs_migration();
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
// Even if a type implements an insignificant drop, if it's
// elements have a significant drop then the overall type is
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.1;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
fn main() {
significant_drop_needs_migration();
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
note: the lint level is defined here
--> $DIR/insignificant_drop_attr_migrations.rs:3:9
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
-LL ~ let c = || { let _ = &t;
+LL ~ let c = || {
+LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^^^^^^
...
LL | let _t = t.1;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
-LL ~ let c = move || { let _ = &t;
+LL ~ let c = move || {
+LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.1;
-LL +
...
error: aborting due to 2 previous errors
--- /dev/null
+// run-rustfix
+
+// See https://github.com/rust-lang/rust/issues/87955
+
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
+
+fn main() {
+ let a = ("hey".to_string(), "123".to_string());
+ let _ = || { let _ = &a; dbg!(a.0) };
+ //~^ ERROR: drop order
+ //~| NOTE: will only capture `a.0`
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `a` to be fully captured
+}
+//~^ NOTE: dropped here
--- /dev/null
+// run-rustfix
+
+// See https://github.com/rust-lang/rust/issues/87955
+
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE: the lint level is defined here
+
+fn main() {
+ let a = ("hey".to_string(), "123".to_string());
+ let _ = || dbg!(a.0);
+ //~^ ERROR: drop order
+ //~| NOTE: will only capture `a.0`
+ //~| NOTE: for more information, see
+ //~| HELP: add a dummy let to cause `a` to be fully captured
+}
+//~^ NOTE: dropped here
--- /dev/null
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/macro.rs:10:13
+ |
+LL | let _ = || dbg!(a.0);
+ | ^^^^^^^^---^
+ | |
+ | in Rust 2018, this closure captures all of `a`, but in Rust 2021, it will only capture `a.0`
+...
+LL | }
+ | - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure
+ |
+note: the lint level is defined here
+ --> $DIR/macro.rs:5:9
+ |
+LL | #![deny(rust_2021_incompatible_closure_captures)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+help: add a dummy let to cause `a` to be fully captured
+ |
+LL | let _ = || { let _ = &a; dbg!(a.0) };
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
fn closure_contains_block() {
let t = (Foo(0), Foo(0));
- let c = || { let _ = &t;
+ let c = || {
+ let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
fn closure_doesnt_contain_block() {
let t = (Foo(0), Foo(0));
let c = || { let _ = &t; t.0 };
//~^ ERROR: drop order
- //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
fn main() {
closure_contains_block();
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
fn closure_doesnt_contain_block() {
let t = (Foo(0), Foo(0));
let c = || t.0;
//~^ ERROR: drop order
- //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
fn main() {
closure_contains_block();
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
note: the lint level is defined here
--> $DIR/migrations_rustfix.rs:2:9
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
-LL ~ let c = || { let _ = &t;
+LL ~ let c = || {
+LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
LL | let c = || t.0;
| ^^^---
| |
- | in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
F: FnOnce(),
{
let f = panic::AssertUnwindSafe(f);
- let result = panic::catch_unwind(move || { let _ = &f;
+ let result = panic::catch_unwind(move || {
+ let _ = &f;
//~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
- //~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+ //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f` to be fully captured
f.0()
- //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0`
});
if let Ok(..) = result {
panic!("diverging function returned");
let f = panic::AssertUnwindSafe(f);
let result = panic::catch_unwind(move || {
//~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
- //~| NOTE: in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+ //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f` to be fully captured
f.0()
- //~^ NOTE: in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0`
});
if let Ok(..) = result {
panic!("diverging function returned");
--> $DIR/mir_calls_to_shims.rs:20:38
|
LL | let result = panic::catch_unwind(move || {
- | ^^^^^^^ in Rust 2018, this closure would implement `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure would no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
+ | ^^^^^^^ in Rust 2018, this closure implements `UnwindSafe`, `RefUnwindSafe` as `f` implements `UnwindSafe`, `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe`, `RefUnwindSafe` as `f.0` does not implement `UnwindSafe`, `RefUnwindSafe`
...
LL | f.0()
- | --- in Rust 2018, closure captures all of `f`, but in Rust 2021, it only captures `f.0`
+ | --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0`
|
note: the lint level is defined here
--> $DIR/mir_calls_to_shims.rs:3:9
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f` to be fully captured
|
-LL ~ let result = panic::catch_unwind(move || { let _ = &f;
+LL ~ let result = panic::catch_unwind(move || {
+LL + let _ = &f;
LL +
LL +
LL +
LL +
-LL + f.0()
...
error: aborting due to previous error
fn test_multi_issues() {
let f1 = U(S(String::from("foo")), T(0));
let f2 = U(S(String::from("bar")), T(0));
- let c = || { let _ = (&f1, &f2);
+ let c = || {
+ let _ = (&f1, &f2);
//~^ ERROR: `Clone` trait implementation for closure and drop order
- //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
let _f_1 = f1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
let _f_2 = f2.1;
- //~^ NOTE: in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f2`, but in Rust 2021, it will only capture `f2.1`
};
let c_clone = c.clone();
c_clone();
}
-//~^ NOTE: in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `f2` is dropped here, but in Rust 2021, only `f2.1` will be dropped here as part of the closure
fn test_capturing_all_disjoint_fields_individually() {
let f1 = U(S(String::from("foo")), T(0));
- let c = || { let _ = &f1;
+ let c = || {
+ let _ = &f1;
//~^ ERROR: `Clone` trait implementation for closure
- //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1` to be fully captured
let _f_1 = f1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
let _f_2 = f1.1;
};
fn test_capturing_several_disjoint_fields_individually_1() {
let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
- let c = || { let _ = &f1;
+ let c = || {
+ let _ = &f1;
//~^ ERROR: `Clone` trait implementation for closure
- //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
- //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1` to be fully captured
let _f_0 = f1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
let _f_2 = f1.2;
- //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.2`
};
let c_clone = c.clone();
fn test_capturing_several_disjoint_fields_individually_2() {
let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
- let c = || { let _ = &f1;
+ let c = || {
+ let _ = &f1;
//~^ ERROR: `Clone` trait implementation for closure and drop order
- //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1` to be fully captured
let _f_0 = f1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
let _f_1 = f1.1;
- //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.1`
};
let c_clone = c.clone();
c_clone();
}
-//~^ NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.1` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.0` will be dropped here as part of the closure
struct SendPointer(*mut i32);
unsafe impl Send for SendPointer {}
let fptr2 = SendPointer(&mut f2 as *mut i32);
thread::spawn(move || { let _ = (&fptr1, &fptr2); unsafe {
//~^ ERROR: `Sync`, `Send` trait implementation for closure
- //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
- //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send`
+ //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
+ //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
*fptr1.0.0 = 20;
- //~^ NOTE: in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
*fptr2.0 = 20;
- //~^ NOTE: in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0`
} });
}
let f2 = U(S(String::from("bar")), T(0));
let c = || {
//~^ ERROR: `Clone` trait implementation for closure and drop order
- //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
let _f_1 = f1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
let _f_2 = f2.1;
- //~^ NOTE: in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f2`, but in Rust 2021, it will only capture `f2.1`
};
let c_clone = c.clone();
c_clone();
}
-//~^ NOTE: in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `f2` is dropped here, but in Rust 2021, only `f2.1` will be dropped here as part of the closure
fn test_capturing_all_disjoint_fields_individually() {
let f1 = U(S(String::from("foo")), T(0));
let c = || {
//~^ ERROR: `Clone` trait implementation for closure
- //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1` to be fully captured
let _f_1 = f1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
let _f_2 = f1.1;
};
let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
let c = || {
//~^ ERROR: `Clone` trait implementation for closure
- //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
- //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1` to be fully captured
let _f_0 = f1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
let _f_2 = f1.2;
- //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.2`
};
let c_clone = c.clone();
let f1 = U1(S(String::from("foo")), T(0), S(String::from("bar")));
let c = || {
//~^ ERROR: `Clone` trait implementation for closure and drop order
- //~| NOTE: in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1` to be fully captured
let _f_0 = f1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
let _f_1 = f1.1;
- //~^ NOTE: in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.1`
};
let c_clone = c.clone();
c_clone();
}
-//~^ NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.1` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.0` will be dropped here as part of the closure
struct SendPointer(*mut i32);
unsafe impl Send for SendPointer {}
let fptr2 = SendPointer(&mut f2 as *mut i32);
thread::spawn(move || unsafe {
//~^ ERROR: `Sync`, `Send` trait implementation for closure
- //~| NOTE: in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
- //~| NOTE: in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send`
+ //~| NOTE: in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
+ //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
*fptr1.0.0 = 20;
- //~^ NOTE: in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
*fptr2.0 = 20;
- //~^ NOTE: in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0`
});
}
--> $DIR/multi_diagnostics.rs:23:13
|
LL | let c = || {
- | ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
...
LL | let _f_1 = f1.0;
- | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
LL |
LL | let _f_2 = f2.1;
- | ---- in Rust 2018, closure captures all of `f2`, but in Rust 2021, it only captures `f2.1`
+ | ---- in Rust 2018, this closure captures all of `f2`, but in Rust 2021, it will only capture `f2.1`
...
LL | }
- | - in Rust 2018, `f2` would be dropped here, but in Rust 2021, only `f2.1` would be dropped here alongside the closure
+ | - in Rust 2018, `f2` is dropped here, but in Rust 2021, only `f2.1` will be dropped here as part of the closure
|
note: the lint level is defined here
--> $DIR/multi_diagnostics.rs:2:9
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f1`, `f2` to be fully captured
|
-LL ~ let c = || { let _ = (&f1, &f2);
+LL ~ let c = || {
+LL + let _ = (&f1, &f2);
LL +
LL +
LL +
LL +
-LL + let _f_1 = f1.0;
...
error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
--> $DIR/multi_diagnostics.rs:42:13
|
LL | let c = || {
- | ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
...
LL | let _f_1 = f1.0;
- | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f1` to be fully captured
|
-LL ~ let c = || { let _ = &f1;
+LL ~ let c = || {
+LL + let _ = &f1;
LL +
LL +
LL +
LL +
-LL + let _f_1 = f1.0;
...
error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
LL | let c = || {
| ^^
| |
- | in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
- | in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.2` does not implement `Clone`
+ | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
+ | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.2` does not implement `Clone`
...
LL | let _f_0 = f1.0;
- | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
LL |
LL | let _f_2 = f1.2;
- | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.2`
+ | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.2`
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f1` to be fully captured
|
-LL ~ let c = || { let _ = &f1;
-LL +
+LL ~ let c = || {
+LL + let _ = &f1;
LL +
LL +
LL +
--> $DIR/multi_diagnostics.rs:86:13
|
LL | let c = || {
- | ^^ in Rust 2018, this closure would implement `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure would no longer implement `Clone` as `f1.0` does not implement `Clone`
+ | ^^ in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` as `f1.0` does not implement `Clone`
...
LL | let _f_0 = f1.0;
- | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.0`
+ | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
LL |
LL | let _f_1 = f1.1;
- | ---- in Rust 2018, closure captures all of `f1`, but in Rust 2021, it only captures `f1.1`
+ | ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.1`
...
LL | }
| -
| |
- | in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.0` would be dropped here alongside the closure
- | in Rust 2018, `f1` would be dropped here, but in Rust 2021, only `f1.1` would be dropped here alongside the closure
+ | in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.0` will be dropped here as part of the closure
+ | in Rust 2018, `f1` is dropped here, but in Rust 2021, only `f1.1` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f1` to be fully captured
|
-LL ~ let c = || { let _ = &f1;
+LL ~ let c = || {
+LL + let _ = &f1;
LL +
LL +
LL +
LL +
-LL + let _f_0 = f1.0;
...
error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
LL | thread::spawn(move || unsafe {
| ^^^^^^^^^^^^^^
| |
- | in Rust 2018, this closure would implement `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure would no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
- | in Rust 2018, this closure would implement `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure would no longer implement `Send` as `fptr2.0` does not implement `Send`
+ | in Rust 2018, this closure implements `Sync`, `Send` as `fptr1` implements `Sync`, `Send`, but in Rust 2021, this closure will no longer implement `Sync`, `Send` as `fptr1.0.0` does not implement `Sync`, `Send`
+ | in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr2.0` does not implement `Send`
...
LL | *fptr1.0.0 = 20;
- | ---------- in Rust 2018, closure captures all of `fptr1`, but in Rust 2021, it only captures `fptr1.0.0`
+ | ---------- in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
LL |
LL | *fptr2.0 = 20;
- | -------- in Rust 2018, closure captures all of `fptr2`, but in Rust 2021, it only captures `fptr2.0`
+ | -------- in Rust 2018, this closure captures all of `fptr2`, but in Rust 2021, it will only capture `fptr2.0`
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
fn test_precise_analysis_drop_paths_not_captured_by_move() {
let t = ConstainsDropField(Foo(10), Foo(20));
- let c = || { let _ = &t;
+ let c = || {
+ let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _t = &t.1;
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
struct S;
impl Drop for S {
fn test_precise_analysis_long_path_missing() {
let u = U(T(S, S), T(S, S));
- let c = || { let _ = &u;
+ let c = || {
+ let _ = &u;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `u` to be fully captured
let _x = u.0.0;
- //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.0`
let _x = u.0.1;
- //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.1`
let _x = u.1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.1.0`
};
c();
}
-//~^ NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.1` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.1.0` will be dropped here as part of the closure
fn main() {
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _t = &t.1;
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
struct S;
impl Drop for S {
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `u` to be fully captured
let _x = u.0.0;
- //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.0`
let _x = u.0.1;
- //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.1`
let _x = u.1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.1.0`
};
c();
}
-//~^ NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.1` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.1.0` will be dropped here as part of the closure
fn main() {
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
note: the lint level is defined here
--> $DIR/precise.rs:3:9
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
-LL ~ let c = || { let _ = &t;
+LL ~ let c = || {
+LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | let _x = u.0.0;
- | ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.0`
+ | ----- in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.0`
LL |
LL | let _x = u.0.1;
- | ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.0.1`
+ | ----- in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.0.1`
LL |
LL | let _x = u.1.0;
- | ----- in Rust 2018, closure captures all of `u`, but in Rust 2021, it only captures `u.1.0`
+ | ----- in Rust 2018, this closure captures all of `u`, but in Rust 2021, it will only capture `u.1.0`
...
LL | }
| -
| |
- | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.0` would be dropped here alongside the closure
- | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.0.1` would be dropped here alongside the closure
- | in Rust 2018, `u` would be dropped here, but in Rust 2021, only `u.1.0` would be dropped here alongside the closure
+ | in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.0` will be dropped here as part of the closure
+ | in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.0.1` will be dropped here as part of the closure
+ | in Rust 2018, `u` is dropped here, but in Rust 2021, only `u.1.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `u` to be fully captured
|
-LL ~ let c = || { let _ = &u;
+LL ~ let c = || {
+LL + let _ = &u;
LL +
LL +
LL +
LL + let _x = u.0.0;
-LL +
...
error: aborting due to 2 previous errors
let t1 = (Foo(0), Foo(0));
let t2 = (Foo(0), Foo(0));
- let c = || { let _ = (&t, &t1, &t2);
+ let c = || {
+ let _ = (&t, &t1, &t2);
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _t1 = t1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
let _t2 = t2.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
// String implements drop and therefore should be migrated.
// But in this test cases, `t2` is completely captured and when it is dropped won't be affected
let t1 = (Foo(0), Foo(0));
let t2 = (Foo(0), Foo(0));
- let c = || { let _ = (&t, &t1);
+ let c = || {
+ let _ = (&t, &t1);
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _t1 = t1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
let _t2 = t2;
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
// If a variable would've not been captured by value then it would've not been
// dropped with the closure and therefore doesn't need migration.
fn test3_only_by_value_need_migration() {
let t = (Foo(0), Foo(0));
let t1 = (Foo(0), Foo(0));
- let c = || { let _ = &t;
+ let c = || {
+ let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
println!("{:?}", t1.1);
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
// The root variable might not implement drop themselves but some path starting
// at the root variable might implement Drop.
fn test4_type_contains_drop_need_migration() {
let t = ConstainsDropField(Foo(0), Foo(0));
- let c = || { let _ = &t;
+ let c = || {
+ let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
// Test migration analysis in case of Drop + Non Drop aggregates.
// Note we need migration here only because the non-copy (because Drop type) is captured,
fn test5_drop_non_drop_aggregate_need_migration() {
let t = (Foo(0), Foo(0), 0i32);
- let c = || { let _ = &t;
+ let c = || {
+ let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
// Test migration analysis in case of Significant and Insignificant Drop aggregates.
fn test6_significant_insignificant_drop_aggregate_need_migration() {
let t = (Foo(0), String::new());
- let c = || { let _ = &t;
+ let c = || {
+ let _ = &t;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.1;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
// Since we are using a move closure here, both `t` and `t1` get moved
// even though they are being used by ref inside the closure.
let t = (Foo(0), Foo(0));
let t1 = (Foo(0), Foo(0), Foo(0));
- let c = move || { let _ = (&t1, &t);
+ let c = move || {
+ let _ = (&t1, &t);
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
println!("{:?} {:?}", t1.1, t.1);
- //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
- //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
+ //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
fn test8_drop_order_and_blocks() {
let tuple =
(String::from("foo"), String::from("bar"));
{
- let c = || { let _ = &tuple;
+ let c = || {
+ let _ = &tuple;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `tuple` to be fully captured
tuple.0;
- //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
};
c();
}
- //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+ //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
}
}
let tuple =
(String::from("foo"), String::from("bar"));
let b = || {
- let c = || { let _ = &tuple;
+ let c = || {
+ let _ = &tuple;
//~^ ERROR: drop order
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `tuple` to be fully captured
tuple.0;
- //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
};
c();
};
- //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+ //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
b();
}
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _t1 = t1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
let _t2 = t2.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
// String implements drop and therefore should be migrated.
// But in this test cases, `t2` is completely captured and when it is dropped won't be affected
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t`, `t1` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
let _t1 = t1.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
let _t2 = t2;
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
// If a variable would've not been captured by value then it would've not been
// dropped with the closure and therefore doesn't need migration.
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
println!("{:?}", t1.1);
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
// The root variable might not implement drop themselves but some path starting
// at the root variable might implement Drop.
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
// Test migration analysis in case of Drop + Non Drop aggregates.
// Note we need migration here only because the non-copy (because Drop type) is captured,
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.0;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
// Test migration analysis in case of Significant and Insignificant Drop aggregates.
fn test6_significant_insignificant_drop_aggregate_need_migration() {
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t` to be fully captured
let _t = t.1;
- //~^ NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
// Since we are using a move closure here, both `t` and `t1` get moved
// even though they are being used by ref inside the closure.
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `t1`, `t` to be fully captured
println!("{:?} {:?}", t1.1, t.1);
- //~^ NOTE: in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
- //~| NOTE: in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ //~^ NOTE: in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
+ //~| NOTE: in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
};
c();
}
-//~^ NOTE: in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
-//~| NOTE: in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
+//~^ NOTE: in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
+//~| NOTE: in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
fn test8_drop_order_and_blocks() {
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `tuple` to be fully captured
tuple.0;
- //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
};
c();
}
- //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+ //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
}
}
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `tuple` to be fully captured
tuple.0;
- //~^ NOTE: in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+ //~^ NOTE: in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
};
c();
};
- //~^ NOTE: in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+ //~^ NOTE: in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
b();
}
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
LL |
LL | let _t1 = t1.0;
- | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+ | ---- in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
LL |
LL | let _t2 = t2.0;
- | ---- in Rust 2018, closure captures all of `t2`, but in Rust 2021, it only captures `t2.0`
+ | ---- in Rust 2018, this closure captures all of `t2`, but in Rust 2021, it will only capture `t2.0`
...
LL | }
| -
| |
- | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
- | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
- | in Rust 2018, `t2` would be dropped here, but in Rust 2021, only `t2.0` would be dropped here alongside the closure
+ | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+ | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
+ | in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
|
note: the lint level is defined here
--> $DIR/significant_drop.rs:2:9
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
|
-LL ~ let c = || { let _ = (&t, &t1, &t2);
+LL ~ let c = || {
+LL + let _ = (&t, &t1, &t2);
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
LL |
LL | let _t1 = t1.0;
- | ---- in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.0`
+ | ---- in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.0`
...
LL | }
| -
| |
- | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
- | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.0` would be dropped here alongside the closure
+ | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
+ | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1` to be fully captured
|
-LL ~ let c = || { let _ = (&t, &t1);
+LL ~ let c = || {
+LL + let _ = (&t, &t1);
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
-LL ~ let c = || { let _ = &t;
+LL ~ let c = || {
+LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
-LL ~ let c = || { let _ = &t;
+LL ~ let c = || {
+LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | let _t = t.0;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.0`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.0`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.0` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
-LL ~ let c = || { let _ = &t;
+LL ~ let c = || {
+LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | let _t = t.1;
- | --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ | --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
...
LL | }
- | - in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+ | - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
-LL ~ let c = || { let _ = &t;
+LL ~ let c = || {
+LL + let _ = &t;
LL +
LL +
LL +
LL + let _t = t.1;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^^^^^^
...
LL | println!("{:?} {:?}", t1.1, t.1);
- | ---- --- in Rust 2018, closure captures all of `t`, but in Rust 2021, it only captures `t.1`
+ | ---- --- in Rust 2018, this closure captures all of `t`, but in Rust 2021, it will only capture `t.1`
| |
- | in Rust 2018, closure captures all of `t1`, but in Rust 2021, it only captures `t1.1`
+ | in Rust 2018, this closure captures all of `t1`, but in Rust 2021, it will only capture `t1.1`
...
LL | }
| -
| |
- | in Rust 2018, `t1` would be dropped here, but in Rust 2021, only `t1.1` would be dropped here alongside the closure
- | in Rust 2018, `t` would be dropped here, but in Rust 2021, only `t.1` would be dropped here alongside the closure
+ | in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.1` will be dropped here as part of the closure
+ | in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.1` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t1`, `t` to be fully captured
|
-LL ~ let c = move || { let _ = (&t1, &t);
+LL ~ let c = move || {
+LL + let _ = (&t1, &t);
LL +
LL +
LL +
LL + println!("{:?} {:?}", t1.1, t.1);
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | tuple.0;
- | ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+ | ------- in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
...
LL | }
- | - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+ | - in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `tuple` to be fully captured
|
-LL ~ let c = || { let _ = &tuple;
+LL ~ let c = || {
+LL + let _ = &tuple;
LL +
LL +
LL +
LL + tuple.0;
-LL +
...
error: changes to closure capture in Rust 2021 will affect drop order
| ^^
...
LL | tuple.0;
- | ------- in Rust 2018, closure captures all of `tuple`, but in Rust 2021, it only captures `tuple.0`
+ | ------- in Rust 2018, this closure captures all of `tuple`, but in Rust 2021, it will only capture `tuple.0`
...
LL | };
- | - in Rust 2018, `tuple` would be dropped here, but in Rust 2021, only `tuple.0` would be dropped here alongside the closure
+ | - in Rust 2018, `tuple` is dropped here, but in Rust 2021, only `tuple.0` will be dropped here as part of the closure
|
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `tuple` to be fully captured
|
-LL ~ let c = || { let _ = &tuple;
+LL ~ let c = || {
+LL + let _ = &tuple;
LL +
LL +
LL +
LL + tuple.0;
-LL +
...
error: aborting due to 9 previous errors
let err = (res == -1)
.then(|| Error::last_os_error())
.expect("probe syscall should not succeed");
- err.raw_os_error() != Some(libc::ENOSYS)
+
+ // If the `clone3` syscall is not implemented in the current kernel version it should return an
+ // `ENOSYS` error. Docker also blocks the whole syscall inside unprivileged containers, and
+ // returns `EPERM` (instead of `ENOSYS`) when a program tries to invoke the syscall. Because of
+ // that we need to check for *both* `ENOSYS` and `EPERM`.
+ //
+ // Note that Docker's behavior is breaking other projects (notably glibc), so they're planning
+ // to update their filtering to return `ENOSYS` in a future release:
+ //
+ // https://github.com/moby/moby/issues/42680
+ //
+ err.raw_os_error() != Some(libc::ENOSYS) && err.raw_os_error() != Some(libc::EPERM)
}
fn main() {
|
= note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error[E0747]: type provided when a constant was expected
--> $DIR/const-expression-suggest-missing-braces.rs:11:11
LL | #[deny(bare_trait_objects)]
| ^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: trait objects without an explicit `dyn` are deprecated
--> $DIR/dyn-2018-edition-lint.rs:4:35
| ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: trait objects without an explicit `dyn` are deprecated
--> $DIR/dyn-2018-edition-lint.rs:9:14
| ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: aborting due to 3 previous errors
a");
//~^ ERROR invalid format string
format!("{ \
-
+ \
b");
//~^ ERROR invalid format string
format!(r#"{ \
{ \
\
b \
-
+ \
");
//~^^^ ERROR invalid format string
format!(r#"
raw { \
-
+ \
c"#);
//~^^^ ERROR invalid format string
format!(r#"
|
LL | format!("{ \
| - because of this opening brace
-LL |
+LL | \
LL | b");
| ^ expected `}` in format string
|
|
= note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error[E0107]: this associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
--> $DIR/gat-trait-path-parenthesised-args.rs:7:27
error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
- --> $DIR/projection-bound-cycle-generic.rs:44:5
+ --> $DIR/projection-bound-cycle-generic.rs:44:18
|
LL | struct OnlySized<T> where T: Sized { f: T }
| - required by this bound in `OnlySized`
...
LL | type Assoc = OnlySized<<T as Foo>::Item>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
error[E0275]: overflow evaluating the requirement `<T as Foo>::Item: Sized`
- --> $DIR/projection-bound-cycle.rs:46:5
+ --> $DIR/projection-bound-cycle.rs:46:18
|
LL | struct OnlySized<T> where T: Sized { f: T }
| - required by this bound in `OnlySized`
...
LL | type Assoc = OnlySized<<T as Foo>::Item>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
error[E0275]: overflow evaluating the requirement `<FooStruct as Foo>::A == _`
- --> $DIR/issue-21946.rs:8:5
+ --> $DIR/issue-21946.rs:8:14
|
LL | type A = <FooStruct as Foo>::A;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
error[E0275]: overflow evaluating the requirement `<GetNext<T> as Next>::Next == _`
- --> $DIR/issue-23122-1.rs:10:5
+ --> $DIR/issue-23122-1.rs:10:17
|
LL | type Next = <GetNext<T> as Next>::Next;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
- --> $DIR/issue-23122-2.rs:9:5
+ --> $DIR/issue-23122-2.rs:9:17
|
LL | type Next = <GetNext<T::Next> as Next>::Next;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`)
note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
|
= note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error[E0107]: missing generics for trait `Foo`
--> $DIR/issue-86756.rs:5:15
|
= note: `#[warn(array_into_iter)]` on by default
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | let _: Iter<'_, i32> = array.iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | let _: Iter<'_, i32> = Box::new(array).iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | for _ in [1, 2, 3].iter() {}
|
= note: `#[warn(array_into_iter)]` on by default
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | small.iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | [1, 2].iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | big.iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | [0u8; 33].iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new(small).iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new([1, 2]).iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new(big).iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new([0u8; 33]).iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new(Box::new(small)).iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new(Box::new([1, 2])).iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new(Box::new(big)).iter();
| ^^^^^^^^^
|
= warning: this changes meaning in Rust 2021
- = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | Box::new(Box::new([0u8; 33])).iter();
--- /dev/null
+// compile-flags: --target thumbv8m.main-none-eabihf
+// needs-llvm-components: arm
+//
+// Verify that thumb targets implement the repr(C) for enums correctly.
+//
+// See #87917
+#![feature(never_type, rustc_attrs, no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang="sized"]
+trait Sized {}
+
+#[rustc_layout(debug)]
+#[repr(C)]
+enum A { Apple } //~ ERROR: layout_of
+
+#[rustc_layout(debug)]
+#[repr(C)]
+enum B { Banana = 255, } //~ ERROR: layout_of
+
+#[rustc_layout(debug)]
+#[repr(C)]
+enum C { Chaenomeles = 256, } //~ ERROR: layout_of
+
+#[rustc_layout(debug)]
+#[repr(C)]
+enum P { Peach = 0x1000_0000isize, } //~ ERROR: layout_of
+
+const TANGERINE: usize = 0x8100_0000; // hack to get negative numbers without negation operator!
+
+#[rustc_layout(debug)]
+#[repr(C)]
+enum T { Tangerine = TANGERINE as isize } //~ ERROR: layout_of
--- /dev/null
+error: layout_of(A) = Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 0,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Multiple {
+ tag: Scalar {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=0,
+ },
+ tag_encoding: Direct,
+ tag_field: 0,
+ variants: [
+ Layout {
+ fields: Arbitrary {
+ offsets: [],
+ memory_index: [],
+ },
+ variants: Single {
+ index: 0,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: Align {
+ pow2: 2,
+ },
+ },
+ size: Size {
+ raw: 1,
+ },
+ },
+ ],
+ },
+ abi: Scalar(
+ Scalar {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=0,
+ },
+ ),
+ largest_niche: Some(
+ Niche {
+ offset: Size {
+ raw: 0,
+ },
+ scalar: Scalar {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 0..=0,
+ },
+ },
+ ),
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: Align {
+ pow2: 2,
+ },
+ },
+ size: Size {
+ raw: 1,
+ },
+}
+ --> $DIR/thumb-enum.rs:16:1
+ |
+LL | enum A { Apple }
+ | ^^^^^^^^^^^^^^^^
+
+error: layout_of(B) = Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 0,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Multiple {
+ tag: Scalar {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 255..=255,
+ },
+ tag_encoding: Direct,
+ tag_field: 0,
+ variants: [
+ Layout {
+ fields: Arbitrary {
+ offsets: [],
+ memory_index: [],
+ },
+ variants: Single {
+ index: 0,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: Align {
+ pow2: 2,
+ },
+ },
+ size: Size {
+ raw: 1,
+ },
+ },
+ ],
+ },
+ abi: Scalar(
+ Scalar {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 255..=255,
+ },
+ ),
+ largest_niche: Some(
+ Niche {
+ offset: Size {
+ raw: 0,
+ },
+ scalar: Scalar {
+ value: Int(
+ I8,
+ false,
+ ),
+ valid_range: 255..=255,
+ },
+ },
+ ),
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 0,
+ },
+ pref: Align {
+ pow2: 2,
+ },
+ },
+ size: Size {
+ raw: 1,
+ },
+}
+ --> $DIR/thumb-enum.rs:20:1
+ |
+LL | enum B { Banana = 255, }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: layout_of(C) = Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 0,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Multiple {
+ tag: Scalar {
+ value: Int(
+ I16,
+ false,
+ ),
+ valid_range: 256..=256,
+ },
+ tag_encoding: Direct,
+ tag_field: 0,
+ variants: [
+ Layout {
+ fields: Arbitrary {
+ offsets: [],
+ memory_index: [],
+ },
+ variants: Single {
+ index: 0,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 1,
+ },
+ pref: Align {
+ pow2: 2,
+ },
+ },
+ size: Size {
+ raw: 2,
+ },
+ },
+ ],
+ },
+ abi: Scalar(
+ Scalar {
+ value: Int(
+ I16,
+ false,
+ ),
+ valid_range: 256..=256,
+ },
+ ),
+ largest_niche: Some(
+ Niche {
+ offset: Size {
+ raw: 0,
+ },
+ scalar: Scalar {
+ value: Int(
+ I16,
+ false,
+ ),
+ valid_range: 256..=256,
+ },
+ },
+ ),
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 1,
+ },
+ pref: Align {
+ pow2: 2,
+ },
+ },
+ size: Size {
+ raw: 2,
+ },
+}
+ --> $DIR/thumb-enum.rs:24:1
+ |
+LL | enum C { Chaenomeles = 256, }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: layout_of(P) = Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 0,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Multiple {
+ tag: Scalar {
+ value: Int(
+ I32,
+ false,
+ ),
+ valid_range: 268435456..=268435456,
+ },
+ tag_encoding: Direct,
+ tag_field: 0,
+ variants: [
+ Layout {
+ fields: Arbitrary {
+ offsets: [],
+ memory_index: [],
+ },
+ variants: Single {
+ index: 0,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 2,
+ },
+ pref: Align {
+ pow2: 2,
+ },
+ },
+ size: Size {
+ raw: 4,
+ },
+ },
+ ],
+ },
+ abi: Scalar(
+ Scalar {
+ value: Int(
+ I32,
+ false,
+ ),
+ valid_range: 268435456..=268435456,
+ },
+ ),
+ largest_niche: Some(
+ Niche {
+ offset: Size {
+ raw: 0,
+ },
+ scalar: Scalar {
+ value: Int(
+ I32,
+ false,
+ ),
+ valid_range: 268435456..=268435456,
+ },
+ },
+ ),
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 2,
+ },
+ pref: Align {
+ pow2: 2,
+ },
+ },
+ size: Size {
+ raw: 4,
+ },
+}
+ --> $DIR/thumb-enum.rs:28:1
+ |
+LL | enum P { Peach = 0x1000_0000isize, }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: layout_of(T) = Layout {
+ fields: Arbitrary {
+ offsets: [
+ Size {
+ raw: 0,
+ },
+ ],
+ memory_index: [
+ 0,
+ ],
+ },
+ variants: Multiple {
+ tag: Scalar {
+ value: Int(
+ I32,
+ true,
+ ),
+ valid_range: 2164260864..=2164260864,
+ },
+ tag_encoding: Direct,
+ tag_field: 0,
+ variants: [
+ Layout {
+ fields: Arbitrary {
+ offsets: [],
+ memory_index: [],
+ },
+ variants: Single {
+ index: 0,
+ },
+ abi: Aggregate {
+ sized: true,
+ },
+ largest_niche: None,
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 2,
+ },
+ pref: Align {
+ pow2: 2,
+ },
+ },
+ size: Size {
+ raw: 4,
+ },
+ },
+ ],
+ },
+ abi: Scalar(
+ Scalar {
+ value: Int(
+ I32,
+ true,
+ ),
+ valid_range: 2164260864..=2164260864,
+ },
+ ),
+ largest_niche: Some(
+ Niche {
+ offset: Size {
+ raw: 0,
+ },
+ scalar: Scalar {
+ value: Int(
+ I32,
+ true,
+ ),
+ valid_range: 2164260864..=2164260864,
+ },
+ },
+ ),
+ align: AbiAndPrefAlign {
+ abi: Align {
+ pow2: 2,
+ },
+ pref: Align {
+ pow2: 2,
+ },
+ },
+ size: Size {
+ raw: 4,
+ },
+}
+ --> $DIR/thumb-enum.rs:34:1
+ |
+LL | enum T { Tangerine = TANGERINE as isize }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
|
= note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/bare-trait-objects-path.rs:17:5
| ^^^^^ help: use `dyn`: `<dyn (::Dyn)>`
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/bare-trait-objects-path.rs:20:5
| ^^^ help: use `dyn`: `<dyn Dyn>`
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: aborting due to previous error; 3 warnings emitted
|
= note: requested on the command line with `--force-warn bare-trait-objects`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: 1 warning emitted
|
= note: requested on the command line with `--force-warn bare-trait-objects`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: 1 warning emitted
|
= note: `--force-warn ellipsis-inclusive-range-patterns` implied by `--force-warn rust-2021-compatibility`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: 1 warning emitted
|
= note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: 1 warning emitted
|
= note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: 1 warning emitted
LL | #![warn(ellipsis_inclusive_range_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: `...` range patterns are deprecated
--> $DIR/inclusive-range-pattern-syntax.rs:16:9
| ^^^^^^ help: use `..=` for an inclusive range: `&(1..=2)`
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: 2 warnings emitted
LL | #![deny(rust_2021_incompatible_or_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>
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:13:23
| ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>
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:19:21
| ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>
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:23:26
| ^^^^^^^^ help: use pat_param to preserve semantics: `$pat:pat_param`
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #84869 <https://github.com/rust-lang/rust/issues/84869>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>
error: aborting due to 4 previous errors
fancy_panic::fancy_panic!("test {} 123");
//~^ WARN panic message contains an unused formatting placeholder
- fancy_panic::fancy_panic!(S);
- //~^ WARN panic message is not a string literal
+ fancy_panic::fancy_panic!(); // OK
+ fancy_panic::fancy_panic!(S); // OK
macro_rules! a {
() => { 123 };
|
= note: this message is not used as a format string when given without arguments, but will be in Rust 2021
-warning: panic message is not a string literal
- --> $DIR/non-fmt-panic.rs:29:31
- |
-LL | fancy_panic::fancy_panic!(S);
- | ^
- |
- = note: this usage of panic!() is deprecated; it will be a hard error in Rust 2021
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
-
warning: panic message is not a string literal
--> $DIR/non-fmt-panic.rs:36:12
|
LL | std::panic::panic_any(123);
| ~~~~~~~~~~~~~~~~~~~~~~ ~
-warning: 20 warnings emitted
+warning: 19 warnings emitted
|
= note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error[E0224]: at least one trait is required for an object type
--> $DIR/issue-68890-2.rs:3:14
|
= note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/issue-73568-lifetime-after-mut.rs:19:23
| ^^ help: use `dyn`: `dyn 'a`
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error[E0224]: at least one trait is required for an object type
--> $DIR/issue-73568-lifetime-after-mut.rs:14:18
|
= note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error[E0224]: at least one trait is required for an object type
--> $DIR/trait-object-macro-matcher.rs:11:8
LL | #![deny(ellipsis_inclusive_range_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
--> $DIR/recover-range-pats.rs:45:13
| ^^^ help: use `..=` for an inclusive range
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
--> $DIR/recover-range-pats.rs:48:13
| ^^^ help: use `..=` for an inclusive range
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
--> $DIR/recover-range-pats.rs:51:13
| ^^^ help: use `..=` for an inclusive range
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
--> $DIR/recover-range-pats.rs:54:16
| ^^^ help: use `..=` for an inclusive range
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
--> $DIR/recover-range-pats.rs:57:13
| ^^^ help: use `..=` for an inclusive range
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
--> $DIR/recover-range-pats.rs:60:14
| ^^^ help: use `..=` for an inclusive range
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
--> $DIR/recover-range-pats.rs:64:13
| ^^^ help: use `..=` for an inclusive range
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
--> $DIR/recover-range-pats.rs:138:20
| ------------ in this macro invocation
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
= note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0029]: only `char` and numeric types are allowed in range patterns
|
= note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/trait-object-trait-parens.rs:13:16
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn ?Sized + (for<'a> Trait<'a>) + (Obj)`
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: trait objects without an explicit `dyn` are deprecated
--> $DIR/trait-object-trait-parens.rs:18:16
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `dyn for<'a> Trait<'a> + (Obj) + (?Sized)`
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-object-trait-parens.rs:8:35
LL | #![warn(ellipsis_inclusive_range_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: aborting due to previous error; 1 warning emitted
LL | #![warn(ellipsis_inclusive_range_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: aborting due to previous error; 1 warning emitted
error[E0491]: in type `&'a Foo<'b>`, reference has a longer lifetime than the data it references
- --> $DIR/regions-outlives-nominal-type-region-rev.rs:17:9
+ --> $DIR/regions-outlives-nominal-type-region-rev.rs:17:20
|
LL | type Out = &'a Foo<'b>;
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^
|
note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10
--> $DIR/regions-outlives-nominal-type-region-rev.rs:16:10
error[E0491]: in type `&'a Foo<'b>`, reference has a longer lifetime than the data it references
- --> $DIR/regions-outlives-nominal-type-region.rs:17:9
+ --> $DIR/regions-outlives-nominal-type-region.rs:17:20
|
LL | type Out = &'a Foo<'b>;
- | ^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^
|
note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10
--> $DIR/regions-outlives-nominal-type-region.rs:16:10
error[E0491]: in type `&'a Foo<&'b i32>`, reference has a longer lifetime than the data it references
- --> $DIR/regions-outlives-nominal-type-type-rev.rs:17:9
+ --> $DIR/regions-outlives-nominal-type-type-rev.rs:17:20
|
LL | type Out = &'a Foo<&'b i32>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
|
note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10
--> $DIR/regions-outlives-nominal-type-type-rev.rs:16:10
error[E0491]: in type `&'a Foo<&'b i32>`, reference has a longer lifetime than the data it references
- --> $DIR/regions-outlives-nominal-type-type.rs:17:9
+ --> $DIR/regions-outlives-nominal-type-type.rs:17:20
|
LL | type Out = &'a Foo<&'b i32>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^
|
note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10
--> $DIR/regions-outlives-nominal-type-type.rs:16:10
error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-struct-not-wf.rs:13:5
+ --> $DIR/regions-struct-not-wf.rs:13:16
|
LL | impl<'a, T> Trait<'a, T> for usize {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | type Out = &'a T;
- | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
+ | ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/regions-struct-not-wf.rs:21:5
+ --> $DIR/regions-struct-not-wf.rs:21:16
|
LL | impl<'a, T> Trait<'a, T> for u32 {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | type Out = RefOk<'a, T>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
+ | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
|
note: ...that is required by this bound
--> $DIR/regions-struct-not-wf.rs:16:20
| ^^
error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data it references
- --> $DIR/regions-struct-not-wf.rs:25:5
+ --> $DIR/regions-struct-not-wf.rs:25:16
|
LL | type Out = &'a &'b T;
- | ^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^
|
note: the pointer is valid for the lifetime `'a` as defined on the impl at 24:6
--> $DIR/regions-struct-not-wf.rs:24:6
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-generic.rs:31:5
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<i32, i32> as MyFromIter>::from_iter`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-generic.rs:34:5
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic::<_, _> as MyFromIter>::from_iter`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: 3 warnings emitted
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-imported.rs:40:22
| ^^^^^^^^^^^^^^ help: disambiguate the associated function: `crate::m::TryIntoU32::try_into(3u8)`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-imported.rs:53:22
| ^^^^^^^^^^^^^^ help: disambiguate the associated function: `super::m::TryIntoU32::try_into(3u8)`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: 3 warnings emitted
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait-associated function `try_from` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:61:13
| ^^^^^^^^^^^^^ help: disambiguate the associated function: `<u32 as TryFromU8>::try_from`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:66:13
| ^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Vec<u8> as FromByteIterator>::from_iter`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait-associated function `try_from` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:74:18
| ^^^^^^^^^^^^^ help: disambiguate the associated function: `<_ as TryFromU8>::try_from`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:79:18
| ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(*(&3u8))`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:84:18
| ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(&3.0)`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:90:18
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(mut_ptr as *const _)`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait-associated function `try_from` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:95:13
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<U32Alias as TryFromU8>::try_from`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: 8 warnings emitted
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: 1 warning emitted
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #85684 <https://github.com/rust-lang/rust/issues/85684>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: 1 warning emitted
LL | #![warn(rust_2021_prefixes_incompatible_syntax)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #84978 <https://github.com/rust-lang/rust/issues/84978>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>
help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
|
LL - m2!(z"hey");
| ^^^^^^ unknown prefix
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #84978 <https://github.com/rust-lang/rust/issues/84978>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>
help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
|
LL - m2!(prefix"hey");
| ^^^ unknown prefix
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #84978 <https://github.com/rust-lang/rust/issues/84978>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>
help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
|
LL - m3!(hey#123);
| ^^^ unknown prefix
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #84978 <https://github.com/rust-lang/rust/issues/84978>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>
help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
|
LL - m3!(hey#hey);
| ^^^^ unknown prefix
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see issue #84978 <https://github.com/rust-lang/rust/issues/84978>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>
help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
|
LL - #name = #kind#value
// run-fail
// error-pattern: MemorySanitizer: use-of-uninitialized-value
// error-pattern: Uninitialized value was created by an allocation
-// error-pattern: in the stack frame of function 'random'
+// error-pattern: in the stack frame of function 'main'
//
// This test case intentionally limits the usage of the std,
// since it will be linked with an uninstrumented version of it.
error: unconstrained generic constant
- --> $DIR/issue-51892.rs:15:5
+ --> $DIR/issue-51892.rs:15:17
|
LL | type Type = [u8; std::mem::size_of::<<T as Trait>::Type>()];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<<T as Trait>::Type>()]:`
--- /dev/null
+// check-pass
+fn main() {
+ let s = "\
+
+ ";
+ //~^^^ WARNING multiple lines skipped by escaped newline
+ let s = "foo\
+ Â bar
+ ";
+ //~^^^ WARNING non-ASCII whitespace symbol '\u{a0}' is not skipped
+}
--- /dev/null
+warning: multiple lines skipped by escaped newline
+ --> $DIR/str-escape.rs:3:14
+ |
+LL | let s = "\
+ | ______________^
+LL | |
+LL | | ";
+ | |_____________^ skipping everything up to and including this point
+
+warning: non-ASCII whitespace symbol '\u{a0}' is not skipped
+ --> $DIR/str-escape.rs:7:17
+ |
+LL | let s = "foo\
+ | _________________^
+LL | | Â bar
+ | | ^ non-ASCII whitespace symbol '\u{a0}' is not skipped
+ | |___|
+ |
+
+warning: 2 warnings emitted
+
}
}
+const LOADERS: &Vec<&'static u8> = &Vec::new();
+
+pub fn break_code() -> Option<&'static u8> {
+ for loader in &*LOADERS { //~ ERROR cannot move out of a shared reference
+ return Some(loader);
+ }
+ None
+}
+
fn main() {}
}
}
+const LOADERS: &Vec<&'static u8> = &Vec::new();
+
+pub fn break_code() -> Option<&'static u8> {
+ for loader in *LOADERS { //~ ERROR cannot move out of a shared reference
+ return Some(loader);
+ }
+ None
+}
+
fn main() {}
LL | for _ in &self.h {
| +
-error: aborting due to 2 previous errors
+error[E0507]: cannot move out of a shared reference
+ --> $DIR/for-i-in-vec.rs:21:19
+ |
+LL | for loader in *LOADERS {
+ | ^^^^^^^^ move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait
+ |
+help: consider iterating over a slice of the `Vec<&u8>`'s content
+ |
+LL | for loader in &*LOADERS {
+ | +
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0507`.
LL | #![deny(bare_trait_objects)]
| ^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: trait objects without an explicit `dyn` are deprecated
--> $DIR/issue-61963.rs:18:1
| ^^^ help: use `dyn`: `dyn pub`
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: aborting due to 2 previous errors
|
= note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time
--> $DIR/not-on-bare-trait.rs:7:8
error[E0277]: `&T` is not an iterator
- --> $DIR/hir-wf-check-erase-regions.rs:7:5
+ --> $DIR/hir-wf-check-erase-regions.rs:7:21
|
LL | type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&T` is not an iterator
|
::: $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
|
error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/wf-impl-associated-type-region.rs:10:5
+ --> $DIR/wf-impl-associated-type-region.rs:10:16
|
LL | impl<'a, T> Foo<'a> for T {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | type Bar = &'a T;
- | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
+ | ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
error: aborting due to previous error
error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:5
+ --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:16
|
LL | impl<'a, T> Trait<'a, T> for usize {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | type Out = &'a fn(T);
- | ^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a fn(T)` does not outlive the data it points at
+ | ^^^^^^^^^ ...so that the reference type `&'a fn(T)` does not outlive the data it points at
error[E0309]: the parameter type `T` may not live long enough
- --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5
+ --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:16
|
LL | impl<'a, T> Trait<'a, T> for u32 {
| - help: consider adding an explicit lifetime bound...: `T: 'a`
LL | type Out = &'a dyn Baz<T>;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a (dyn Baz<T> + 'a)` does not outlive the data it points at
+ | ^^^^^^^^^^^^^^ ...so that the reference type `&'a (dyn Baz<T> + 'a)` does not outlive the data it points at
error: aborting due to 2 previous errors
error[E0309]: the associated type `<Self as SomeTrait<'a>>::Type1` may not live long enough
- --> $DIR/wf-trait-associated-type-region.rs:9:5
+ --> $DIR/wf-trait-associated-type-region.rs:9:18
|
LL | type Type2 = &'a Self::Type1;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<Self as SomeTrait<'a>>::Type1: 'a`...
= note: ...so that the reference type `&'a <Self as SomeTrait<'a>>::Type1` does not outlive the data it points at
-Subproject commit cc17afbb0067b1f57d8882640f63b2168d5b7624
+Subproject commit b51439fd8b505d4800a257acfecf3c69f81e35cf
*What is the advantage of the recommended code over the original code*
For example:
-- Remove bounce checking inserted by ...
-- Remove the need to duplicating/storing/typo ...
+- Remove bounds check inserted by ...
+- Remove the need to duplicate/store ...
+- Remove typo ...
### Drawbacks
echo "LD_LIBRARY_PATH=${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" >> $GITHUB_ENV
- name: Build
- run: cargo build --features deny-warnings,internal-lints
+ run: cargo build --features deny-warnings,internal-lints,metadata-collector-lint
- name: Test
- run: cargo test --features deny-warnings,internal-lints
+ run: cargo test --features deny-warnings,internal-lints,metadata-collector-lint
- name: Test clippy_lints
- run: cargo test --features deny-warnings,internal-lints
+ run: cargo test --features deny-warnings,internal-lints,metadata-collector-lint
working-directory: clippy_lints
- name: Test rustc_tools_util
echo "$SYSROOT/bin" >> $GITHUB_PATH
- name: Build
- run: cargo build --features deny-warnings,internal-lints
+ run: cargo build --features deny-warnings,internal-lints,metadata-collector-lint
- name: Test
- run: cargo test --features deny-warnings,internal-lints
+ run: cargo test --features deny-warnings,internal-lints,metadata-collector-lint
- name: Test clippy_lints
- run: cargo test --features deny-warnings,internal-lints
+ run: cargo test --features deny-warnings,internal-lints,metadata-collector-lint
working-directory: clippy_lints
- name: Test rustc_tools_util
- name: Setup Node.js
uses: actions/setup-node@v1.4.4
+ with:
+ node-version: '12.x'
- name: Install remark
run: npm install remark-cli remark-lint remark-lint-maximum-line-length remark-preset-lint-recommended remark-gfm
## Unreleased / In Rust Nightly
-[3ae8faf...master](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...master)
+[74d1561...master](https://github.com/rust-lang/rust-clippy/compare/74d1561...master)
+
+## Rust 1.55
+
+Current beta, release 2021-09-09
+
+[3ae8faf...74d1561](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...74d1561)
+
+### Important Changes
+
+* Stabilized `cargo clippy --fix` :tada:
+ [#7405](https://github.com/rust-lang/rust-clippy/pull/7405)
+
+### New Lints
+
+* [`rc_mutex`]
+ [#7316](https://github.com/rust-lang/rust-clippy/pull/7316)
+* [`nonstandard_macro_braces`]
+ [#7299](https://github.com/rust-lang/rust-clippy/pull/7299)
+* [`strlen_on_c_strings`]
+ [#7243](https://github.com/rust-lang/rust-clippy/pull/7243)
+* [`self_named_constructors`]
+ [#7403](https://github.com/rust-lang/rust-clippy/pull/7403)
+* [`disallowed_script_idents`]
+ [#7400](https://github.com/rust-lang/rust-clippy/pull/7400)
+* [`disallowed_type`]
+ [#7315](https://github.com/rust-lang/rust-clippy/pull/7315)
+* [`missing_enforced_import_renames`]
+ [#7300](https://github.com/rust-lang/rust-clippy/pull/7300)
+* [`extend_with_drain`]
+ [#7270](https://github.com/rust-lang/rust-clippy/pull/7270)
+
+### Moves and Deprecations
+
+* Moved [`from_iter_instead_of_collect`] to `pedantic`
+ [#7375](https://github.com/rust-lang/rust-clippy/pull/7375)
+* Added `suspicious` as a new lint group for *code that is most likely wrong or useless*
+ [#7350](https://github.com/rust-lang/rust-clippy/pull/7350)
+ * Moved [`blanket_clippy_restriction_lints`] to `suspicious`
+ * Moved [`empty_loop`] to `suspicious`
+ * Moved [`eval_order_dependence`] to `suspicious`
+ * Moved [`float_equality_without_abs`] to `suspicious`
+ * Moved [`for_loops_over_fallibles`] to `suspicious`
+ * Moved [`misrefactored_assign_op`] to `suspicious`
+ * Moved [`mut_range_bound`] to `suspicious`
+ * Moved [`mutable_key_type`] to `suspicious`
+ * Moved [`suspicious_arithmetic_impl`] to `suspicious`
+ * Moved [`suspicious_assignment_formatting`] to `suspicious`
+ * Moved [`suspicious_else_formatting`] to `suspicious`
+ * Moved [`suspicious_map`] to `suspicious`
+ * Moved [`suspicious_op_assign_impl`] to `suspicious`
+ * Moved [`suspicious_unary_op_formatting`] to `suspicious`
+
+### Enhancements
+
+* [`while_let_on_iterator`]: Now suggests `&mut iter` inside closures
+ [#7262](https://github.com/rust-lang/rust-clippy/pull/7262)
+* [`doc_markdown`]:
+ * Now detects unbalanced ticks
+ [#7357](https://github.com/rust-lang/rust-clippy/pull/7357)
+ * Add `FreeBSD` to the default configuration as an allowed identifier
+ [#7334](https://github.com/rust-lang/rust-clippy/pull/7334)
+* [`wildcard_enum_match_arm`], [`match_wildcard_for_single_variants`]: Now allows wildcards for enums with unstable
+ or hidden variants
+ [#7407](https://github.com/rust-lang/rust-clippy/pull/7407)
+* [`redundant_allocation`]: Now additionally supports the `Arc<>` type
+ [#7308](https://github.com/rust-lang/rust-clippy/pull/7308)
+* [`blacklisted_name`]: Now allows blacklisted names in test code
+ [#7379](https://github.com/rust-lang/rust-clippy/pull/7379)
+* [`redundant_closure`]: Suggests `&mut` for `FnMut`
+ [#7437](https://github.com/rust-lang/rust-clippy/pull/7437)
+* [`disallowed_method`], [`disallowed_type`]: The configuration values `disallowed-method` and `disallowed-type`
+ no longer require fully qualified paths
+ [#7345](https://github.com/rust-lang/rust-clippy/pull/7345)
+* [`zst_offset`]: Fixed lint invocation after it was accidentally suppressed
+ [#7396](https://github.com/rust-lang/rust-clippy/pull/7396)
+
+### False Positive Fixes
+
+* [`default_numeric_fallback`]: No longer lints on float literals as function arguments
+ [#7446](https://github.com/rust-lang/rust-clippy/pull/7446)
+* [`use_self`]: No longer lints on type parameters
+ [#7288](https://github.com/rust-lang/rust-clippy/pull/7288)
+* [`unimplemented`]: Now ignores the `assert` and `debug_assert` macros
+ [#7439](https://github.com/rust-lang/rust-clippy/pull/7439)
+* [`branches_sharing_code`]: Now always checks for block expressions
+ [#7462](https://github.com/rust-lang/rust-clippy/pull/7462)
+* [`field_reassign_with_default`]: No longer triggers in macros
+ [#7160](https://github.com/rust-lang/rust-clippy/pull/7160)
+* [`redundant_clone`]: No longer lints on required clones for borrowed data
+ [#7346](https://github.com/rust-lang/rust-clippy/pull/7346)
+* [`default_numeric_fallback`]: No longer triggers in external macros
+ [#7325](https://github.com/rust-lang/rust-clippy/pull/7325)
+* [`needless_bool`]: No longer lints in macros
+ [#7442](https://github.com/rust-lang/rust-clippy/pull/7442)
+* [`useless_format`]: No longer triggers when additional text is being appended
+ [#7442](https://github.com/rust-lang/rust-clippy/pull/7442)
+* [`assertions_on_constants`]: `cfg!(...)` is no longer considered to be a constant
+ [#7319](https://github.com/rust-lang/rust-clippy/pull/7319)
+
+### Suggestion Fixes/Improvements
+
+* [`needless_collect`]: Now show correct lint messages for shadowed values
+ [#7289](https://github.com/rust-lang/rust-clippy/pull/7289)
+* [`wrong_pub_self_convention`]: The deprecated message now suggest the correct configuration value
+ [#7382](https://github.com/rust-lang/rust-clippy/pull/7382)
+* [`semicolon_if_nothing_returned`]: Allow missing semicolon in blocks with only one expression
+ [#7326](https://github.com/rust-lang/rust-clippy/pull/7326)
+
+### ICE Fixes
+
+* [`zero_sized_map_values`]
+ [#7470](https://github.com/rust-lang/rust-clippy/pull/7470)
+* [`redundant_pattern_matching`]
+ [#7471](https://github.com/rust-lang/rust-clippy/pull/7471)
+* [`modulo_one`]
+ [#7473](https://github.com/rust-lang/rust-clippy/pull/7473)
+* [`use_self`]
+ [#7428](https://github.com/rust-lang/rust-clippy/pull/7428)
+
+### Documentation Improvements
+
+* Reworked Clippy's website:
+ [#7279](https://github.com/rust-lang/rust-clippy/pull/7279)
+ [#7172](https://github.com/rust-lang/rust-clippy/issues/7172)
+ * Added applicability information about lints
+ * Added a link to jump into the implementation
+ * Improved loading times
+ * Adapted some styling
+* Clippy now uses a lint to generate its documentation
+ [#7298](https://github.com/rust-lang/rust-clippy/pull/7298)
## Rust 1.54
-Current beta, release 2021-07-29
+Current stable, released 2021-07-29
[7c7683c...3ae8faf](https://github.com/rust-lang/rust-clippy/compare/7c7683c...3ae8faf)
### Moves and Deprecations
- Deprecate `pub_enum_variant_names` and `wrong_pub_self_convention` in favor of
- the new `avoid_breaking_exported_api` config option (see
+ the new `avoid-breaking-exported-api` config option (see
[Enhancements](#1-54-enhancements))
[#7187](https://github.com/rust-lang/rust-clippy/pull/7187)
- Move [`inconsistent_struct_constructor`] to `pedantic`
[#7163](https://github.com/rust-lang/rust-clippy/pull/7163)
- [`if_then_some_else_none`]: Now works with the MSRV config
[#7177](https://github.com/rust-lang/rust-clippy/pull/7177)
-- Add `avoid_breaking_exported_api` config option for the lints
+- Add `avoid-breaking-exported-api` config option for the lints
[`enum_variant_names`], [`large_types_passed_by_value`],
[`trivially_copy_pass_by_ref`], [`unnecessary_wraps`],
[`upper_case_acronyms`], and [`wrong_self_convention`]. We recommend to set
## Rust 1.53
-Current stable, released 2021-06-17
+Released 2021-06-17
[6ed6f1e...7c7683c](https://github.com/rust-lang/rust-clippy/compare/6ed6f1e...7c7683c)
[`unused_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_unit
[`unusual_byte_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unusual_byte_groupings
[`unwrap_in_result`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_in_result
+[`unwrap_or_else_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_or_else_default
[`unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used
[`upper_case_acronyms`]: https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms
[`use_debug`]: https://rust-lang.github.io/rust-clippy/master/index.html#use_debug
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_ast::ast::{Expr, ExprKind};
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
impl EarlyLintPass for AsConversions {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
- if in_external_macro(cx.sess(), expr.span) {
+ if in_external_macro(cx.sess, expr.span) {
return;
}
panic_span: None,
};
fpu.visit_expr(&body.value);
- lint_for_missing_headers(
- cx,
- item.def_id,
- item.span,
- sig,
- headers,
- Some(body_id),
- fpu.panic_span,
- );
+ lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span);
}
},
hir::ItemKind::Impl(ref impl_) => {
panic_span: None,
};
fpu.visit_expr(&body.value);
- lint_for_missing_headers(
- cx,
- item.def_id,
- item.span,
- sig,
- headers,
- Some(body_id),
- fpu.panic_span,
- );
+ lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span);
}
}
}
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_ast::ast::{Expr, ExprKind};
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
impl EarlyLintPass for ElseIfWithoutElse {
fn check_expr(&mut self, cx: &EarlyContext<'_>, mut item: &Expr) {
- if in_external_macro(cx.sess(), item.span) {
+ if in_external_macro(cx.sess, item.span) {
return;
}
hir_id: hir::HirId,
) {
too_many_arguments::check_fn(cx, kind, decl, span, hir_id, self.too_many_arguments_threshold);
- too_many_lines::check_fn(cx, span, body, self.too_many_lines_threshold);
+ too_many_lines::check_fn(cx, kind, span, body, self.too_many_lines_threshold);
not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, hir_id);
}
use rustc_hir as hir;
+use rustc_hir::intravisit::FnKind;
use rustc_lint::{LateContext, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_span::Span;
use super::TOO_MANY_LINES;
-pub(super) fn check_fn(cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'_>, too_many_lines_threshold: u64) {
- if in_external_macro(cx.sess(), span) {
+pub(super) fn check_fn(
+ cx: &LateContext<'_>,
+ kind: FnKind<'tcx>,
+ span: Span,
+ body: &'tcx hir::Body<'_>,
+ too_many_lines_threshold: u64,
+) {
+ // Closures must be contained in a parent body, which will be checked for `too_many_lines`.
+ // Don't check closures for `too_many_lines` to avoid duplicated lints.
+ if matches!(kind, FnKind::Closure) || in_external_macro(cx.sess(), span) {
return;
}
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp};
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
impl EarlyLintPass for IfNotElse {
fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
- if in_external_macro(cx.sess(), item.span) {
+ if in_external_macro(cx.sess, item.span) {
return;
}
if let ExprKind::If(ref cond, _, Some(ref els)) = item.kind {
use clippy_utils::diagnostics::span_lint;
use rustc_ast::ast::{Block, ItemKind, StmtKind};
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
impl EarlyLintPass for ItemsAfterStatements {
fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) {
- if in_external_macro(cx.sess(), item.span) {
+ if in_external_macro(cx.sess, item.span) {
return;
}
// lint on all further items
for stmt in stmts {
if let StmtKind::Item(ref it) = *stmt {
- if in_external_macro(cx.sess(), it.span) {
+ if in_external_macro(cx.sess, it.span) {
return;
}
if let ItemKind::MacroDef(..) = it.kind {
}
}
- if cx.access_levels.is_exported(visited_trait.def_id)
- && trait_items.iter().any(|i| is_named_self(cx, i, sym::len))
+ if cx.access_levels.is_exported(visited_trait.def_id) && trait_items.iter().any(|i| is_named_self(cx, i, sym::len))
{
let mut current_and_super_traits = DefIdSet::default();
fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx);
None,
None,
),
- Some(is_empty) if !cx.access_levels.is_exported(is_empty.def_id.expect_local()) => {
- (
- format!(
- "{} `{}` has a public `len` method, but a private `is_empty` method",
- item_kind,
- item_name.as_str(),
- ),
- Some(cx.tcx.def_span(is_empty.def_id)),
- None,
- )
- },
+ Some(is_empty) if !cx.access_levels.is_exported(is_empty.def_id.expect_local()) => (
+ format!(
+ "{} `{}` has a public `len` method, but a private `is_empty` method",
+ item_kind,
+ item_name.as_str(),
+ ),
+ Some(cx.tcx.def_span(is_empty.def_id)),
+ None,
+ ),
Some(is_empty)
if !(is_empty.fn_has_self_parameter
&& check_is_empty_sig(cx.tcx.fn_sig(is_empty.def_id).skip_binder(), self_kind, output)) =>
methods::UNNECESSARY_FILTER_MAP,
methods::UNNECESSARY_FOLD,
methods::UNNECESSARY_LAZY_EVALUATIONS,
+ methods::UNWRAP_OR_ELSE_DEFAULT,
methods::UNWRAP_USED,
methods::USELESS_ASREF,
methods::WRONG_SELF_CONVENTION,
LintId::of(methods::UNNECESSARY_FILTER_MAP),
LintId::of(methods::UNNECESSARY_FOLD),
LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS),
+ LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT),
LintId::of(methods::USELESS_ASREF),
LintId::of(methods::WRONG_SELF_CONVENTION),
LintId::of(methods::ZST_OFFSET),
LintId::of(methods::STRING_EXTEND_CHARS),
LintId::of(methods::UNNECESSARY_FOLD),
LintId::of(methods::UNNECESSARY_LAZY_EVALUATIONS),
+ LintId::of(methods::UNWRAP_OR_ELSE_DEFAULT),
LintId::of(methods::WRONG_SELF_CONVENTION),
LintId::of(misc::TOPLEVEL_REF_ARG),
LintId::of(misc::ZERO_PTR),
use if_chain::if_chain;
use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind};
use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use std::iter;
impl EarlyLintPass for LiteralDigitGrouping {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
- if in_external_macro(cx.sess(), expr.span) {
+ if in_external_macro(cx.sess, expr.span) {
return;
}
impl EarlyLintPass for DecimalLiteralRepresentation {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
- if in_external_macro(cx.sess(), expr.span) {
+ if in_external_macro(cx.sess, expr.span) {
return;
}
+use super::utils::make_iterator_snippet;
use super::NEVER_LOOP;
-use clippy_utils::diagnostics::span_lint;
-use rustc_hir::{Block, Expr, ExprKind, HirId, InlineAsmOperand, Stmt, StmtKind};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::higher;
+use clippy_utils::source::snippet;
+use rustc_errors::Applicability;
+use rustc_hir::{Block, Expr, ExprKind, HirId, InlineAsmOperand, LoopSource, Node, Pat, Stmt, StmtKind};
use rustc_lint::LateContext;
use std::iter::{once, Iterator};
pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- if let ExprKind::Loop(block, _, _, _) = expr.kind {
+ if let ExprKind::Loop(block, _, source, _) = expr.kind {
match never_loop_block(block, expr.hir_id) {
- NeverLoopResult::AlwaysBreak => span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"),
+ NeverLoopResult::AlwaysBreak => {
+ span_lint_and_then(cx, NEVER_LOOP, expr.span, "this loop never actually loops", |diag| {
+ if_chain! {
+ if let LoopSource::ForLoop = source;
+ if let Some((_, Node::Expr(parent_match))) = cx.tcx.hir().parent_iter(expr.hir_id).nth(1);
+ if let Some((pat, iterator, _, for_span)) = higher::for_loop(parent_match);
+ then {
+ // Suggests using an `if let` instead. This is `Unspecified` because the
+ // loop may (probably) contain `break` statements which would be invalid
+ // in an `if let`.
+ diag.span_suggestion_verbose(
+ for_span.with_hi(iterator.span.hi()),
+ "if you need the first element of the iterator, try writing",
+ for_to_if_let_sugg(cx, iterator, pat),
+ Applicability::Unspecified,
+ );
+ }
+ };
+ });
+ },
NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (),
}
}
e.map(|e| never_loop_expr(e, main_loop_id))
.fold(NeverLoopResult::AlwaysBreak, combine_branches)
}
+
+fn for_to_if_let_sugg(cx: &LateContext<'_>, iterator: &Expr<'_>, pat: &Pat<'_>) -> String {
+ let pat_snippet = snippet(cx, pat.span, "_");
+ let iter_snippet = make_iterator_snippet(cx, iterator, &mut Applicability::Unspecified);
+
+ format!(
+ "if let Some({pat}) = {iter}.next()",
+ pat = pat_snippet,
+ iter = iter_snippet
+ )
+}
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor};
-use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, MatchSource, Node, PatKind, QPath, UnOp};
+use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, MatchSource, Mutability, Node, PatKind, QPath, UnOp};
use rustc_lint::LateContext;
use rustc_span::{symbol::sym, Span, Symbol};
// borrowed mutably. TODO: If the struct can be partially moved from and the struct isn't used
// afterwards a mutable borrow of a field isn't necessary.
let ref_mut = if !iter_expr.fields.is_empty() || needs_mutable_borrow(cx, &iter_expr, loop_expr) {
- "&mut "
+ if cx.typeck_results().node_type(iter_expr.hir_id).ref_mutability() == Some(Mutability::Mut) {
+ // Reborrow for mutable references. It may not be possible to get a mutable reference here.
+ "&mut *"
+ } else {
+ "&mut "
+ }
} else {
""
};
struct IterExpr {
/// The span of the whole expression, not just the path and fields stored here.
span: Span,
+ /// The HIR id of the whole expression, not just the path and fields stored here.
+ hir_id: HirId,
/// The fields used, in order of child to parent.
fields: Vec<Symbol>,
/// The path being used.
/// the expression might have side effects.
fn try_parse_iter_expr(cx: &LateContext<'_>, mut e: &Expr<'_>) -> Option<IterExpr> {
let span = e.span;
+ let hir_id = e.hir_id;
let mut fields = Vec::new();
loop {
match e.kind {
ExprKind::Path(ref path) => {
break Some(IterExpr {
span,
+ hir_id,
fields,
path: cx.qpath_res(path, e.hir_id),
});
match expr.kind {
ExprKind::Field(base, name) => {
if let Some((head_field, tail_fields)) = fields.split_first() {
- if name.name == *head_field && is_expr_same_field(cx, base, fields, path_res) {
+ if name.name == *head_field && is_expr_same_field(cx, base, tail_fields, path_res) {
return true;
}
// Check if the expression is a parent field
//check source object
if let ExprKind::MethodCall(src_method, _, [drain_vec, drain_arg], _) = &arg.kind;
if src_method.ident.as_str() == "drain";
- if let src_ty = cx.typeck_results().expr_ty(drain_vec).peel_refs();
+ let src_ty = cx.typeck_results().expr_ty(drain_vec);
+ //check if actual src type is mutable for code suggestion
+ let immutable = src_ty.is_mutable_ptr();
+ let src_ty = src_ty.peel_refs();
if is_type_diagnostic_item(cx, src_ty, sym::vec_type);
//check drain range
if let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs();
"use of `extend` instead of `append` for adding the full range of a second vector",
"try this",
format!(
- "{}.append(&mut {})",
+ "{}.append({}{})",
snippet_with_applicability(cx, recv.span, "..", &mut applicability),
+ if immutable { "" } else { "&mut " },
snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability)
),
applicability,
use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_opt;
use clippy_utils::ty::implements_trait;
use clippy_utils::{is_expr_path_def_path, paths, sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
-use rustc_lint::{LateContext, LintContext};
+use rustc_lint::LateContext;
use rustc_middle::ty::Ty;
use rustc_span::sym;
let call_site = expr.span.source_callsite();
if_chain! {
- if let Ok(snippet) = cx.sess().source_map().span_to_snippet(call_site);
+ if let Some(snippet) = snippet_opt(cx, call_site);
let snippet_split = snippet.split("::").collect::<Vec<_>>();
if let Some((_, elements)) = snippet_split.split_last();
);
}
- // lint if caller of `.map().flatten()` is an Option
- if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::option_type) {
- let func_snippet = snippet(cx, map_arg.span, "..");
- let hint = format!(".and_then({})", func_snippet);
- span_lint_and_sugg(
- cx,
- MAP_FLATTEN,
- expr.span.with_lo(recv.span.hi()),
- "called `map(..).flatten()` on an `Option`",
- "try using `and_then` instead",
- hint,
- Applicability::MachineApplicable,
- );
- }
+ // lint if caller of `.map().flatten()` is an Option or Result
+ let caller_type = match cx.typeck_results().expr_ty(recv).kind() {
+ ty::Adt(adt, _) => {
+ if cx.tcx.is_diagnostic_item(sym::option_type, adt.did) {
+ "Option"
+ } else if cx.tcx.is_diagnostic_item(sym::result_type, adt.did) {
+ "Result"
+ } else {
+ return;
+ }
+ },
+ _ => {
+ return;
+ },
+ };
+
+ let func_snippet = snippet(cx, map_arg.span, "..");
+ let hint = format!(".and_then({})", func_snippet);
+ let lint_info = format!("called `map(..).flatten()` on an `{}`", caller_type);
+ span_lint_and_sugg(
+ cx,
+ MAP_FLATTEN,
+ expr.span.with_lo(recv.span.hi()),
+ &lint_info,
+ "try using `and_then` instead",
+ hint,
+ Applicability::MachineApplicable,
+ );
}
mod unnecessary_filter_map;
mod unnecessary_fold;
mod unnecessary_lazy_eval;
+mod unwrap_or_else_default;
mod unwrap_used;
mod useless_asref;
mod utils;
"using `ok().expect()`, which gives worse error messages than calling `expect` directly on the Result"
}
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for usages of `_.unwrap_or_else(Default::default)` on `Option` and
+ /// `Result` values.
+ ///
+ /// ### Why is this bad?
+ /// Readability, these can be written as `_.unwrap_or_default`, which is
+ /// simpler and more concise.
+ ///
+ /// ### Examples
+ /// ```rust
+ /// # let x = Some(1);
+ ///
+ /// // Bad
+ /// x.unwrap_or_else(Default::default);
+ /// x.unwrap_or_else(u32::default);
+ ///
+ /// // Good
+ /// x.unwrap_or_default();
+ /// ```
+ pub UNWRAP_OR_ELSE_DEFAULT,
+ style,
+ "using `.unwrap_or_else(Default::default)`, which is more succinctly expressed as `.unwrap_or_default()`"
+}
+
declare_clippy_lint! {
/// ### What it does
/// Checks for usage of `option.map(_).unwrap_or(_)` or `option.map(_).unwrap_or_else(_)` or
SHOULD_IMPLEMENT_TRAIT,
WRONG_SELF_CONVENTION,
OK_EXPECT,
+ UNWRAP_OR_ELSE_DEFAULT,
MAP_UNWRAP_OR,
RESULT_MAP_OR_INTO_OPTION,
OPTION_MAP_OR_NONE,
},
("unwrap_or_else", [u_arg]) => match method_call!(recv) {
Some(("map", [recv, map_arg], _)) if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, msrv) => {},
- _ => unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or"),
+ _ => {
+ unwrap_or_else_default::check(cx, expr, recv, u_arg);
+ unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or");
+ },
},
_ => {},
}
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::eager_or_lazy::is_lazyness_candidate;
+use clippy_utils::is_trait_item;
use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_macro_callsite};
-use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type};
+use clippy_utils::ty::implements_trait;
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
use clippy_utils::{contains_return, last_path_segment, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
or_has_args: bool,
span: Span,
) -> bool {
+ let is_default_default = || is_trait_item(cx, fun, sym::Default);
+
+ let implements_default = |arg, default_trait_id| {
+ let arg_ty = cx.typeck_results().expr_ty(arg);
+ implements_trait(cx, arg_ty, default_trait_id, &[])
+ };
+
if_chain! {
if !or_has_args;
if name == "unwrap_or";
if let hir::ExprKind::Path(ref qpath) = fun.kind;
- let path = last_path_segment(qpath).ident.name;
- if matches!(path, kw::Default | sym::new);
- let arg_ty = cx.typeck_results().expr_ty(arg);
if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default);
- if implements_trait(cx, arg_ty, default_trait_id, &[]);
+ let path = last_path_segment(qpath).ident.name;
+ // needs to target Default::default in particular or be *::new and have a Default impl
+ // available
+ if (matches!(path, kw::Default) && is_default_default())
+ || (matches!(path, sym::new) && implements_default(arg, default_trait_id));
then {
let mut applicability = Applicability::MachineApplicable;
--- /dev/null
+//! Lint for `some_result_or_option.unwrap_or_else(Default::default)`
+
+use super::UNWRAP_OR_ELSE_DEFAULT;
+use clippy_utils::{
+ diagnostics::span_lint_and_sugg, is_trait_item, source::snippet_with_applicability, ty::is_type_diagnostic_item,
+};
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::LateContext;
+use rustc_span::sym;
+
+pub(super) fn check<'tcx>(
+ cx: &LateContext<'tcx>,
+ expr: &'tcx hir::Expr<'_>,
+ recv: &'tcx hir::Expr<'_>,
+ u_arg: &'tcx hir::Expr<'_>,
+) {
+ // something.unwrap_or_else(Default::default)
+ // ^^^^^^^^^- recv ^^^^^^^^^^^^^^^^- u_arg
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- expr
+ let recv_ty = cx.typeck_results().expr_ty(recv);
+ let is_option = is_type_diagnostic_item(cx, recv_ty, sym::option_type);
+ let is_result = is_type_diagnostic_item(cx, recv_ty, sym::result_type);
+
+ if_chain! {
+ if is_option || is_result;
+ if is_trait_item(cx, u_arg, sym::Default);
+ then {
+ let mut applicability = Applicability::MachineApplicable;
+
+ span_lint_and_sugg(
+ cx,
+ UNWRAP_OR_ELSE_DEFAULT,
+ expr.span,
+ "use of `.unwrap_or_else(..)` to construct default value",
+ "try",
+ format!(
+ "{}.unwrap_or_default()",
+ snippet_with_applicability(cx, recv.span, "..", &mut applicability)
+ ),
+ applicability,
+ );
+ }
+ }
+}
use rustc_ast::ast::{Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
use rustc_ast::visit::FnKind;
use rustc_data_structures::fx::FxHashMap;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
}
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
- if in_external_macro(cx.sess(), expr.span) {
+ if in_external_macro(cx.sess, expr.span) {
return;
}
double_neg::check(cx, expr);
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::source::snippet_opt;
use rustc_ast::ast::{Pat, PatKind};
-use rustc_lint::{EarlyContext, LintContext};
+use rustc_lint::EarlyContext;
use super::UNNEEDED_FIELD_PATTERN;
match field.pat.kind {
PatKind::Wild => {},
_ => {
- if let Ok(n) = cx.sess().source_map().span_to_snippet(field.span) {
+ if let Some(n) = snippet_opt(cx, field.span) {
normal.push(n);
}
},
///
/// ### Example
/// ```rust
+ /// fn fun(_a: &i32) {}
+ ///
/// // Bad
/// let x: &i32 = &&&&&&5;
+ /// fun(&x);
///
/// // Good
/// let x: &i32 = &5;
+ /// fun(x);
/// ```
pub NEEDLESS_BORROW,
style,
///
/// is transformed to
///
-/// ```ignore
+/// ```text
/// {
/// let x = 5;
/// ```
/// 2. Detect use of `return` in `Loop` in the closure body.
///
/// NOTE: The functionality of this type is similar to
-/// [`crate::utilts::visitors::find_all_ret_expressions`], but we can't use
+/// [`clippy_utils::visitors::find_all_ret_expressions`], but we can't use
/// `find_all_ret_expressions` instead of this type. The reasons are:
/// 1. `find_all_ret_expressions` passes the argument of `ExprKind::Ret` to a callback, but what we
/// need here is `ExprKind::Ret` itself.
use clippy_utils::ty::has_drop;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource};
+use rustc_hir::{is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, Stmt, StmtKind, UnsafeSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use std::ops::Deref;
ExprKind::Call(callee, args) => {
if let ExprKind::Path(ref qpath) = callee.kind {
let res = cx.qpath_res(qpath, callee.hir_id);
- match res {
- Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..) => {
- !has_drop(cx, cx.typeck_results().expr_ty(expr))
- && args.iter().all(|arg| has_no_effect(cx, arg))
- },
- _ => false,
+ let def_matched = matches!(
+ res,
+ Res::Def(DefKind::Struct | DefKind::Variant | DefKind::Ctor(..), ..)
+ );
+ if def_matched || is_range_literal(expr) {
+ !has_drop(cx, cx.typeck_results().expr_ty(expr)) && args.iter().all(|arg| has_no_effect(cx, arg))
+ } else {
+ false
}
} else {
false
&["qpath", "path"],
&["lit", "lint"],
&["wparam", "lparam"],
+ &["iter", "item"],
];
struct SimilarNamesNameVisitor<'a, 'tcx, 'b>(&'b mut SimilarNamesLocalVisitor<'a, 'tcx>);
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir::def_id::DefId;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
}
fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, mac_braces: &'a MacroBraces) -> Option<MacroInfo<'a>> {
+ let unnested_or_local = || {
+ let nested = in_macro(span.ctxt().outer_expn_data().call_site);
+ !nested
+ || span
+ .macro_backtrace()
+ .last()
+ .map_or(false, |e| e.macro_def_id.map_or(false, DefId::is_local))
+ };
if_chain! {
+ // Make sure we are only one level deep otherwise there are to many FP's
if in_macro(span);
if let Some((name, braces)) = find_matching_macro(span, &mac_braces.macro_braces);
if let Some(snip) = snippet_opt(cx, span.ctxt().outer_expn_data().call_site);
// we must check only invocation sites
// https://github.com/rust-lang/rust-clippy/issues/7422
- if snip.starts_with(name);
+ if snip.starts_with(&format!("{}!", name));
+ if unnested_or_local();
// make formatting consistent
let c = snip.replace(" ", "");
if !c.starts_with(&format!("{}!{}", name, braces.0));
use std::iter;
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_self_ty;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_copy;
+use clippy_utils::{is_self, is_self_ty};
use if_chain::if_chain;
use rustc_ast::attr;
use rustc_errors::Applicability;
if size <= self.ref_min_size;
if let hir::TyKind::Rptr(_, MutTy { ty: decl_ty, .. }) = input.kind;
then {
- let value_type = if is_self_ty(decl_ty) {
+ let value_type = if fn_body.and_then(|body| body.params.get(index)).map_or(false, is_self) {
"self".into()
} else {
snippet(cx, decl_ty.span, "_").into()
use rustc_hir as hir;
use rustc_hir::intravisit as hir_visit;
use rustc_hir::intravisit::Visitor as HirVisitor;
-use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
impl EarlyLintPass for RedundantClosureCall {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
- if in_external_macro(cx.sess(), expr.span) {
+ if in_external_macro(cx.sess, expr.span) {
return;
}
if_chain! {
then {
let mut applicability = Applicability::MachineApplicable;
let sugg = if e.span.from_expansion() {
- if let Ok(macro_source) = cx.sess.source_map().span_to_snippet(e.span) {
+ #[allow(clippy::option_if_let_else)]
+ if let Some(macro_source) = snippet_opt(cx, e.span) {
// Remove leading whitespace from the given span
// e.g: ` $visitor` turns into `$visitor`
let trim_leading_whitespaces = |span| {
-use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{differing_macro_contexts, eq_expr_value};
+use clippy_utils::{can_mut_borrow_both, differing_macro_contexts, eq_expr_value};
use if_chain::if_chain;
use rustc_errors::Applicability;
-use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, StmtKind};
+use rustc_hir::{BinOpKind, Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::sym;
+use rustc_span::source_map::Spanned;
+use rustc_span::{sym, Span};
declare_clippy_lint! {
/// ### What it does
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) {
check_manual_swap(cx, block);
check_suspicious_swap(cx, block);
+ check_xor_swap(cx, block);
}
}
+fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, span: Span, is_xor_based: bool) {
+ let mut applicability = Applicability::MachineApplicable;
+
+ if !can_mut_borrow_both(cx, e1, e2) {
+ if let ExprKind::Index(lhs1, idx1) = e1.kind {
+ if let ExprKind::Index(lhs2, idx2) = e2.kind {
+ if eq_expr_value(cx, lhs1, lhs2) {
+ let ty = cx.typeck_results().expr_ty(lhs1).peel_refs();
+
+ if matches!(ty.kind(), ty::Slice(_))
+ || matches!(ty.kind(), ty::Array(_, _))
+ || is_type_diagnostic_item(cx, ty, sym::vec_type)
+ || is_type_diagnostic_item(cx, ty, sym::vecdeque_type)
+ {
+ let slice = Sugg::hir_with_applicability(cx, lhs1, "<slice>", &mut applicability);
+ span_lint_and_sugg(
+ cx,
+ MANUAL_SWAP,
+ span,
+ &format!("this looks like you are swapping elements of `{}` manually", slice),
+ "try",
+ format!(
+ "{}.swap({}, {})",
+ slice.maybe_par(),
+ snippet_with_applicability(cx, idx1.span, "..", &mut applicability),
+ snippet_with_applicability(cx, idx2.span, "..", &mut applicability),
+ ),
+ applicability,
+ );
+ }
+ }
+ }
+ }
+ return;
+ }
+
+ let first = Sugg::hir_with_applicability(cx, e1, "..", &mut applicability);
+ let second = Sugg::hir_with_applicability(cx, e2, "..", &mut applicability);
+ span_lint_and_then(
+ cx,
+ MANUAL_SWAP,
+ span,
+ &format!("this looks like you are swapping `{}` and `{}` manually", first, second),
+ |diag| {
+ diag.span_suggestion(
+ span,
+ "try",
+ format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr()),
+ applicability,
+ );
+ if !is_xor_based {
+ diag.note("or maybe you should use `std::mem::replace`?");
+ }
+ },
+ );
+}
+
/// Implementation of the `MANUAL_SWAP` lint.
fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) {
for w in block.stmts.windows(3) {
if eq_expr_value(cx, tmp_init, lhs1);
if eq_expr_value(cx, rhs1, lhs2);
then {
- if let ExprKind::Field(lhs1, _) = lhs1.kind {
- if let ExprKind::Field(lhs2, _) = lhs2.kind {
- if lhs1.hir_id.owner == lhs2.hir_id.owner {
- return;
- }
- }
- }
-
- let mut applicability = Applicability::MachineApplicable;
-
- let slice = check_for_slice(cx, lhs1, lhs2);
- let (replace, what, sugg) = if let Slice::NotSwappable = slice {
- return;
- } else if let Slice::Swappable(slice, idx1, idx2) = slice {
- if let Some(slice) = Sugg::hir_opt(cx, slice) {
- (
- false,
- format!(" elements of `{}`", slice),
- format!(
- "{}.swap({}, {})",
- slice.maybe_par(),
- snippet_with_applicability(cx, idx1.span, "..", &mut applicability),
- snippet_with_applicability(cx, idx2.span, "..", &mut applicability),
- ),
- )
- } else {
- (false, String::new(), String::new())
- }
- } else if let (Some(first), Some(second)) = (Sugg::hir_opt(cx, lhs1), Sugg::hir_opt(cx, rhs1)) {
- (
- true,
- format!(" `{}` and `{}`", first, second),
- format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr()),
- )
- } else {
- (true, String::new(), String::new())
- };
-
let span = w[0].span.to(second.span);
-
- span_lint_and_then(
- cx,
- MANUAL_SWAP,
- span,
- &format!("this looks like you are swapping{} manually", what),
- |diag| {
- if !sugg.is_empty() {
- diag.span_suggestion(
- span,
- "try",
- sugg,
- applicability,
- );
-
- if replace {
- diag.note("or maybe you should use `std::mem::replace`?");
- }
- }
- }
- );
- }
- }
- }
-}
-
-enum Slice<'a> {
- /// `slice.swap(idx1, idx2)` can be used
- ///
- /// ## Example
- ///
- /// ```rust
- /// # let mut a = vec![0, 1];
- /// let t = a[1];
- /// a[1] = a[0];
- /// a[0] = t;
- /// // can be written as
- /// a.swap(0, 1);
- /// ```
- Swappable(&'a Expr<'a>, &'a Expr<'a>, &'a Expr<'a>),
- /// The `swap` function cannot be used.
- ///
- /// ## Example
- ///
- /// ```rust
- /// # let mut a = [vec![1, 2], vec![3, 4]];
- /// let t = a[0][1];
- /// a[0][1] = a[1][0];
- /// a[1][0] = t;
- /// ```
- NotSwappable,
- /// Not a slice
- None,
-}
-
-/// Checks if both expressions are index operations into "slice-like" types.
-fn check_for_slice<'a>(cx: &LateContext<'_>, lhs1: &'a Expr<'_>, lhs2: &'a Expr<'_>) -> Slice<'a> {
- if let ExprKind::Index(lhs1, idx1) = lhs1.kind {
- if let ExprKind::Index(lhs2, idx2) = lhs2.kind {
- if eq_expr_value(cx, lhs1, lhs2) {
- let ty = cx.typeck_results().expr_ty(lhs1).peel_refs();
-
- if matches!(ty.kind(), ty::Slice(_))
- || matches!(ty.kind(), ty::Array(_, _))
- || is_type_diagnostic_item(cx, ty, sym::vec_type)
- || is_type_diagnostic_item(cx, ty, sym::vecdeque_type)
- {
- return Slice::Swappable(lhs1, idx1, idx2);
- }
- } else {
- return Slice::NotSwappable;
+ generate_swap_warning(cx, lhs1, lhs2, span, false);
}
}
}
-
- Slice::None
}
/// Implementation of the `ALMOST_SWAPPED` lint.
}
}
}
+
+/// Implementation of the xor case for `MANUAL_SWAP` lint.
+fn check_xor_swap(cx: &LateContext<'_>, block: &Block<'_>) {
+ for window in block.stmts.windows(3) {
+ if_chain! {
+ if let Some((lhs0, rhs0)) = extract_sides_of_xor_assign(&window[0]);
+ if let Some((lhs1, rhs1)) = extract_sides_of_xor_assign(&window[1]);
+ if let Some((lhs2, rhs2)) = extract_sides_of_xor_assign(&window[2]);
+ if eq_expr_value(cx, lhs0, rhs1);
+ if eq_expr_value(cx, lhs2, rhs1);
+ if eq_expr_value(cx, lhs1, rhs0);
+ if eq_expr_value(cx, lhs1, rhs2);
+ then {
+ let span = window[0].span.to(window[2].span);
+ generate_swap_warning(cx, lhs0, rhs0, span, true);
+ }
+ };
+ }
+}
+
+/// Returns the lhs and rhs of an xor assignment statement.
+fn extract_sides_of_xor_assign<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(&'a Expr<'hir>, &'a Expr<'hir>)> {
+ if let StmtKind::Semi(expr) = stmt.kind {
+ if let ExprKind::AssignOp(
+ Spanned {
+ node: BinOpKind::BitXor,
+ ..
+ },
+ lhs,
+ rhs,
+ ) = expr.kind
+ {
+ return Some((lhs, rhs));
+ }
+ }
+ None
+}
/// Checks for use of redundant allocations anywhere in the code.
///
/// ### Why is this bad?
- /// Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Arc<T>>`, `Rc<Box<T>>`, Arc<&T>`, `Arc<Rc<T>>`,
+ /// Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Arc<T>>`, `Rc<Box<T>>`, `Arc<&T>`, `Arc<Rc<T>>`,
/// `Arc<Arc<T>>`, `Arc<Box<T>>`, `Box<&T>`, `Box<Rc<T>>`, `Box<Arc<T>>`, `Box<Box<T>>`, add an unnecessary level of indirection.
///
/// ### Example
/// ```
/// Use instead:
/// ```rust
- /// #![feature(or_patterns)]
- ///
/// fn main() {
/// if let Some(0 | 2) = Some(0) {}
/// }
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::position_before_rarrow;
+use clippy_utils::source::{position_before_rarrow, snippet_opt};
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_ast::visit::FnKind;
use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::BytePos;
}
fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) {
- let (ret_span, appl) = if let Ok(fn_source) = cx.sess().source_map().span_to_snippet(span.with_hi(ty.span.hi())) {
- position_before_rarrow(&fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
- (
- #[allow(clippy::cast_possible_truncation)]
- ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
- Applicability::MachineApplicable,
- )
- })
- } else {
- (ty.span, Applicability::MaybeIncorrect)
- };
+ let (ret_span, appl) =
+ snippet_opt(cx, span.with_hi(ty.span.hi())).map_or((ty.span, Applicability::MaybeIncorrect), |fn_source| {
+ position_before_rarrow(&fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
+ (
+ #[allow(clippy::cast_possible_truncation)]
+ ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
+ Applicability::MachineApplicable,
+ )
+ })
+ });
span_lint_and_sugg(
cx,
UNUSED_UNIT,
/// See (rust-clippy#7172)
macro_rules! define_Conf {
($(
- #[doc = $doc:literal]
+ $(#[doc = $doc:literal])+
$(#[conf_deprecated($dep:literal)])?
($name:ident: $ty:ty = $default:expr),
)*) => {
/// Clippy lint configuration
pub struct Conf {
- $(#[doc = $doc] pub $name: $ty,)*
+ $($(#[doc = $doc])+ pub $name: $ty,)*
}
mod defaults {
stringify!($name),
stringify!($ty),
format!("{:?}", super::defaults::$name()),
- $doc,
+ concat!($($doc, '\n',)*),
deprecation_reason,
)
},
// N.B., this macro is parsed by util/lintlib.py
define_Conf! {
- /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION. Suppress lints whenever the suggested change would cause breakage for other crates.
+ /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION.
+ ///
+ /// Suppress lints whenever the suggested change would cause breakage for other crates.
(avoid_breaking_exported_api: bool = true),
- /// Lint: MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE. The minimum rust version that the project supports
+ /// Lint: MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE.
+ ///
+ /// The minimum rust version that the project supports
(msrv: Option<String> = None),
- /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses
+ /// Lint: BLACKLISTED_NAME.
+ ///
+ /// The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses
(blacklisted_names: Vec<String> = ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()),
- /// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have
+ /// Lint: COGNITIVE_COMPLEXITY.
+ ///
+ /// The maximum cognitive complexity a function can have
(cognitive_complexity_threshold: u64 = 25),
- /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. Use the Cognitive Complexity lint instead.
+ /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY.
+ ///
+ /// Use the Cognitive Complexity lint instead.
#[conf_deprecated("Please use `cognitive-complexity-threshold` instead")]
(cyclomatic_complexity_threshold: Option<u64> = None),
- /// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks
+ /// Lint: DOC_MARKDOWN.
+ ///
+ /// The list of words this lint should not consider as identifiers needing ticks
(doc_valid_idents: Vec<String> = [
"KiB", "MiB", "GiB", "TiB", "PiB", "EiB",
"DirectX",
"MinGW",
"CamelCase",
].iter().map(ToString::to_string).collect()),
- /// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have
+ /// Lint: TOO_MANY_ARGUMENTS.
+ ///
+ /// The maximum number of argument a function or method can have
(too_many_arguments_threshold: u64 = 7),
- /// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have
+ /// Lint: TYPE_COMPLEXITY.
+ ///
+ /// The maximum complexity a type can have
(type_complexity_threshold: u64 = 250),
- /// Lint: MANY_SINGLE_CHAR_NAMES. The maximum number of single char bindings a scope may have
+ /// Lint: MANY_SINGLE_CHAR_NAMES.
+ ///
+ /// The maximum number of single char bindings a scope may have
(single_char_binding_names_threshold: u64 = 4),
- /// Lint: BOXED_LOCAL, USELESS_VEC. The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
+ /// Lint: BOXED_LOCAL, USELESS_VEC.
+ ///
+ /// The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
(too_large_for_stack: u64 = 200),
- /// Lint: ENUM_VARIANT_NAMES. The minimum number of enum variants for the lints about variant names to trigger
+ /// Lint: ENUM_VARIANT_NAMES.
+ ///
+ /// The minimum number of enum variants for the lints about variant names to trigger
(enum_variant_name_threshold: u64 = 3),
- /// Lint: LARGE_ENUM_VARIANT. The maximum size of a enum's variant to avoid box suggestion
+ /// Lint: LARGE_ENUM_VARIANT.
+ ///
+ /// The maximum size of a enum's variant to avoid box suggestion
(enum_variant_size_threshold: u64 = 200),
- /// Lint: VERBOSE_BIT_MASK. The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
+ /// Lint: VERBOSE_BIT_MASK.
+ ///
+ /// The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
(verbose_bit_mask_threshold: u64 = 1),
- /// Lint: DECIMAL_LITERAL_REPRESENTATION. The lower bound for linting decimal literals
+ /// Lint: DECIMAL_LITERAL_REPRESENTATION.
+ ///
+ /// The lower bound for linting decimal literals
(literal_representation_threshold: u64 = 16384),
- /// Lint: TRIVIALLY_COPY_PASS_BY_REF. The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference.
+ /// Lint: TRIVIALLY_COPY_PASS_BY_REF.
+ ///
+ /// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference.
(trivial_copy_size_limit: Option<u64> = None),
- /// Lint: LARGE_TYPE_PASS_BY_MOVE. The minimum size (in bytes) to consider a type for passing by reference instead of by value.
+ /// Lint: LARGE_TYPE_PASS_BY_MOVE.
+ ///
+ /// The minimum size (in bytes) to consider a type for passing by reference instead of by value.
(pass_by_value_size_limit: u64 = 256),
- /// Lint: TOO_MANY_LINES. The maximum number of lines a function or method can have
+ /// Lint: TOO_MANY_LINES.
+ ///
+ /// The maximum number of lines a function or method can have
(too_many_lines_threshold: u64 = 100),
- /// Lint: LARGE_STACK_ARRAYS, LARGE_CONST_ARRAYS. The maximum allowed size for arrays on the stack
+ /// Lint: LARGE_STACK_ARRAYS, LARGE_CONST_ARRAYS.
+ ///
+ /// The maximum allowed size for arrays on the stack
(array_size_threshold: u64 = 512_000),
- /// Lint: VEC_BOX. The size of the boxed type in bytes, where boxing in a `Vec` is allowed
+ /// Lint: VEC_BOX.
+ ///
+ /// The size of the boxed type in bytes, where boxing in a `Vec` is allowed
(vec_box_size_threshold: u64 = 4096),
- /// Lint: TYPE_REPETITION_IN_BOUNDS. The maximum number of bounds a trait can have to be linted
+ /// Lint: TYPE_REPETITION_IN_BOUNDS.
+ ///
+ /// The maximum number of bounds a trait can have to be linted
(max_trait_bounds: u64 = 3),
- /// Lint: STRUCT_EXCESSIVE_BOOLS. The maximum number of bool fields a struct can have
+ /// Lint: STRUCT_EXCESSIVE_BOOLS.
+ ///
+ /// The maximum number of bool fields a struct can have
(max_struct_bools: u64 = 3),
- /// Lint: FN_PARAMS_EXCESSIVE_BOOLS. The maximum number of bool parameters a function can have
+ /// Lint: FN_PARAMS_EXCESSIVE_BOOLS.
+ ///
+ /// The maximum number of bool parameters a function can have
(max_fn_params_bools: u64 = 3),
- /// Lint: WILDCARD_IMPORTS. Whether to allow certain wildcard imports (prelude, super in tests).
+ /// Lint: WILDCARD_IMPORTS.
+ ///
+ /// Whether to allow certain wildcard imports (prelude, super in tests).
(warn_on_all_wildcard_imports: bool = false),
- /// Lint: DISALLOWED_METHOD. The list of disallowed methods, written as fully qualified paths.
+ /// Lint: DISALLOWED_METHOD.
+ ///
+ /// The list of disallowed methods, written as fully qualified paths.
(disallowed_methods: Vec<String> = Vec::new()),
- /// Lint: DISALLOWED_TYPE. The list of disallowed types, written as fully qualified paths.
+ /// Lint: DISALLOWED_TYPE.
+ ///
+ /// The list of disallowed types, written as fully qualified paths.
(disallowed_types: Vec<String> = Vec::new()),
- /// Lint: UNREADABLE_LITERAL. Should the fraction of a decimal be linted to include separators.
+ /// Lint: UNREADABLE_LITERAL.
+ ///
+ /// Should the fraction of a decimal be linted to include separators.
(unreadable_literal_lint_fractions: bool = true),
- /// Lint: UPPER_CASE_ACRONYMS. Enables verbose mode. Triggers if there is more than one uppercase char next to each other
+ /// Lint: UPPER_CASE_ACRONYMS.
+ ///
+ /// Enables verbose mode. Triggers if there is more than one uppercase char next to each other
(upper_case_acronyms_aggressive: bool = false),
- /// Lint: _CARGO_COMMON_METADATA. For internal testing only, ignores the current `publish` settings in the Cargo manifest.
+ /// Lint: _CARGO_COMMON_METADATA.
+ ///
+ /// For internal testing only, ignores the current `publish` settings in the Cargo manifest.
(cargo_ignore_publish: bool = false),
- /// Lint: NONSTANDARD_MACRO_BRACES. Enforce the named macros always use the braces specified. <br> A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro is could be used with a full path two `MacroMatcher`s have to be added one with the full path `crate_name::macro_name` and one with just the macro name.
+ /// Lint: NONSTANDARD_MACRO_BRACES.
+ ///
+ /// Enforce the named macros always use the braces specified.
+ ///
+ /// A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
+ /// is could be used with a full path two `MacroMatcher`s have to be added one with the full path
+ /// `crate_name::macro_name` and one with just the macro name.
(standard_macro_braces: Vec<crate::nonstandard_macro_braces::MacroMatcher> = Vec::new()),
- /// Lint: MISSING_ENFORCED_IMPORT_RENAMES. The list of imports to always rename, a fully qualified path followed by the rename.
+ /// Lint: MISSING_ENFORCED_IMPORT_RENAMES.
+ ///
+ /// The list of imports to always rename, a fully qualified path followed by the rename.
(enforced_import_renames: Vec<crate::utils::conf::Rename> = Vec::new()),
- /// Lint: RESTRICTED_SCRIPTS. The list of unicode scripts allowed to be used in the scope.
+ /// Lint: RESTRICTED_SCRIPTS.
+ ///
+ /// The list of unicode scripts allowed to be used in the scope.
(allowed_scripts: Vec<String> = vec!["Latin".to_string()]),
}
/// `default`
macro_rules! CONFIGURATION_VALUE_TEMPLATE {
() => {
- "* {name}: {ty}: {doc} (defaults to `{default}`)\n"
+ "* {name}: `{ty}`: {doc} (defaults to `{default}`)\n"
};
}
if let Some(split_pos) = doc_comment.find('.');
then {
let mut doc_comment = doc_comment.to_string();
- let documentation = doc_comment.split_off(split_pos);
+ let mut documentation = doc_comment.split_off(split_pos);
+ // Extract lints
doc_comment.make_ascii_lowercase();
let lints: Vec<String> = doc_comment.split_off(DOC_START.len()).split(", ").map(str::to_string).collect();
+ // Format documentation correctly
+ // split off leading `.` from lint name list and indent for correct formatting
+ documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n ");
+
Some((lints, documentation))
} else {
None
///
/// # Example
///
-/// ```ignore
+/// ```text
/// error: constant division of 0.0 with 0.0 will always result in NaN
/// --> $DIR/zero_div_zero.rs:6:25
/// |
///
/// # Example
///
-/// ```ignore
+/// ```text
/// error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
/// --> $DIR/drop_forget_ref.rs:10:5
/// |
///
/// # Example
///
-/// ```ignore
+/// ```text
/// error: This `.fold` can be more succinctly expressed as `.any`
/// --> $DIR/methods.rs:390:13
/// |
/// - `assert!`, `assert_eq!` and `assert_ne!`
/// - `debug_assert!`, `debug_assert_eq!` and `debug_assert_ne!`
/// For example:
-/// `assert!(expr)` will return Some([expr])
-/// `debug_assert_eq!(a, b)` will return Some([a, b])
+/// `assert!(expr)` will return `Some([expr])`
+/// `debug_assert_eq!(a, b)` will return `Some([a, b])`
pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx Expr<'tcx>>> {
/// Try to match the AST for a pattern that contains a match, for example when two args are
/// compared
/// String literal expressions which represent the format string split by "{}"
pub format_string_parts: &'tcx [Expr<'tcx>],
- /// Symbols corresponding to [`format_string_parts`]
+ /// Symbols corresponding to [`Self::format_string_parts`]
pub format_string_symbols: Vec<Symbol>,
/// Expressions like `ArgumentV1::new(arg0, Debug::fmt)`
pub args: &'tcx [Expr<'tcx>],
.map_or(false, |did| is_diag_trait_item(cx, did, diag_item))
}
+/// Checks if the given expression is a path referring an item on the trait
+/// that is marked with the given diagnostic item.
+///
+/// For checking method call expressions instead of path expressions, use
+/// [`is_trait_method`].
+///
+/// For example, this can be used to find if an expression like `u64::default`
+/// refers to an item of the trait `Default`, which is associated with the
+/// `diag_item` of `sym::Default`.
+pub fn is_trait_item(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol) -> bool {
+ if let hir::ExprKind::Path(ref qpath) = expr.kind {
+ cx.qpath_res(qpath, expr.hir_id)
+ .opt_def_id()
+ .map_or(false, |def_id| is_diag_trait_item(cx, def_id, diag_item))
+ } else {
+ false
+ }
+}
+
pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
match *path {
QPath::Resolved(_, path) => path.segments.last().expect("A path must have at least one segment"),
None
}
+/// This method will return tuple of projection stack and root of the expression,
+/// used in `can_mut_borrow_both`.
+///
+/// For example, if `e` represents the `v[0].a.b[x]`
+/// this method will return a tuple, composed of a `Vec`
+/// containing the `Expr`s for `v[0], v[0].a, v[0].a.b, v[0].a.b[x]`
+/// and a `Expr` for root of them, `v`
+fn projection_stack<'a, 'hir>(mut e: &'a Expr<'hir>) -> (Vec<&'a Expr<'hir>>, &'a Expr<'hir>) {
+ let mut result = vec![];
+ let root = loop {
+ match e.kind {
+ ExprKind::Index(ep, _) | ExprKind::Field(ep, _) => {
+ result.push(e);
+ e = ep;
+ },
+ _ => break e,
+ };
+ };
+ result.reverse();
+ (result, root)
+}
+
+/// Checks if two expressions can be mutably borrowed simultaneously
+/// and they aren't dependent on borrowing same thing twice
+pub fn can_mut_borrow_both(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>) -> bool {
+ let (s1, r1) = projection_stack(e1);
+ let (s2, r2) = projection_stack(e2);
+ if !eq_expr_value(cx, r1, r2) {
+ return true;
+ }
+ for (x1, x2) in s1.iter().zip(s2.iter()) {
+ match (&x1.kind, &x2.kind) {
+ (ExprKind::Field(_, i1), ExprKind::Field(_, i2)) => {
+ if i1 != i2 {
+ return true;
+ }
+ },
+ (ExprKind::Index(_, i1), ExprKind::Index(_, i2)) => {
+ if !eq_expr_value(cx, i1, i2) {
+ return false;
+ }
+ },
+ _ => return false,
+ }
+ }
+ false
+}
+
/// Checks if the top level expression can be moved into a closure as is.
pub fn can_move_expr_to_closure_no_visit(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, jump_targets: &[HirId]) -> bool {
match expr.kind {
snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)
}
-/// Same as `snippet`, but it adapts the applicability level by following rules:
+/// Same as [`snippet`], but it adapts the applicability level by following rules:
///
/// - Applicability level `Unspecified` will never be changed.
/// - If the span is inside a macro, change the applicability level to `MaybeIncorrect`.
/// Checks whether a type implements a trait.
/// The function returns false in case the type contains an inference variable.
-/// See also `get_trait_def_id`.
+/// See also [`get_trait_def_id`](super::get_trait_def_id).
pub fn implements_trait<'tcx>(
cx: &LateContext<'tcx>,
ty: Ty<'tcx>,
```
> **DO NOT** install using `cargo install --path . --force` since this will overwrite rustup
-[proxies](https://rust-lang.github.io/rustup/concepts/proxies.html). That is, `~/.cargo/bin/cargo-clippy` and
-`~/.cargo/bin/clippy-driver` should be hard or soft links to `~/.cargo/bin/rustup`. You can repair these by running
-`rustup update`.
+> [proxies](https://rust-lang.github.io/rustup/concepts/proxies.html). That is, `~/.cargo/bin/cargo-clippy` and
+> `~/.cargo/bin/clippy-driver` should be hard or soft links to `~/.cargo/bin/rustup`. You can repair these by running
+> `rustup update`.
[glossary]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html
[toolchain]
-channel = "nightly-2021-07-29"
+channel = "nightly-2021-08-12"
components = ["llvm-tools-preview", "rustc-dev", "rust-src"]
+++ /dev/null
-pub trait A {}
-
-macro_rules! __implicit_hasher_test_macro {
- (impl< $($impl_arg:tt),* > for $kind:ty where $($bounds:tt)*) => {
- __implicit_hasher_test_macro!( ($($impl_arg),*) ($kind) ($($bounds)*) );
- };
-
- (($($impl_arg:tt)*) ($($kind_arg:tt)*) ($($bounds:tt)*)) => {
- impl< $($impl_arg)* > test_macro::A for $($kind_arg)* where $($bounds)* { }
- };
-}
+// edition:2018
+
#![warn(clippy::too_many_lines)]
// This function should be considered one line.
println!("This is bad.");
}
+// This should only fail once (#7517).
+async fn async_too_many_lines() {
+ println!("This is bad.");
+ println!("This is bad.");
+}
+
+// This should fail only once, without failing on the closure.
+fn closure_too_many_lines() {
+ let _ = {
+ println!("This is bad.");
+ println!("This is bad.");
+ };
+}
+
// This should be considered one line.
#[rustfmt::skip]
fn comment_starts_after_code() {
error: this function has too many lines (2/1)
- --> $DIR/test.rs:18:1
+ --> $DIR/test.rs:20:1
|
LL | / fn too_many_lines() {
LL | | println!("This is bad.");
|
= note: `-D clippy::too-many-lines` implied by `-D warnings`
+error: this function has too many lines (4/1)
+ --> $DIR/test.rs:26:1
+ |
+LL | / async fn async_too_many_lines() {
+LL | | println!("This is bad.");
+LL | | println!("This is bad.");
+LL | | }
+ | |_^
+
+error: this function has too many lines (4/1)
+ --> $DIR/test.rs:32:1
+ |
+LL | / fn closure_too_many_lines() {
+LL | | let _ = {
+LL | | println!("This is bad.");
+LL | | println!("This is bad.");
+LL | | };
+LL | | }
+ | |_^
+
error: this function has too many lines (2/1)
- --> $DIR/test.rs:38:1
+ --> $DIR/test.rs:54:1
|
LL | / fn comment_before_code() {
LL | | let _ = "test";
LL | | }
| |_^
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
};
}
+macro_rules! printlnfoo {
+ ($thing:expr) => {
+ println!("{}", $thing)
+ };
+}
+
#[rustfmt::skip]
fn main() {
let _ = vec! {1, 2, 3};
let _ = format!["ugh {} stop being such a good compiler", "hello"];
let _ = quote!(let x = 1;);
let _ = quote::quote!(match match match);
- let _ = test!();
+ let _ = test!(); // trigger when macro def is inside our own crate
let _ = vec![1,2,3];
let _ = quote::quote! {true || false};
let _: type_pos!(usize) = vec![];
eprint!("test if user config overrides defaults");
+
+ printlnfoo!["test if printlnfoo is triggered by println"];
}
error: use of irregular braces for `vec!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:37:13
+ --> $DIR/conf_nonstandard_macro_braces.rs:43:13
|
LL | let _ = vec! {1, 2, 3};
| ^^^^^^^^^^^^^^
|
= note: `-D clippy::nonstandard-macro-braces` implied by `-D warnings`
help: consider writing `vec![1, 2, 3]`
- --> $DIR/conf_nonstandard_macro_braces.rs:37:13
+ --> $DIR/conf_nonstandard_macro_braces.rs:43:13
|
LL | let _ = vec! {1, 2, 3};
| ^^^^^^^^^^^^^^
error: use of irregular braces for `format!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:38:13
+ --> $DIR/conf_nonstandard_macro_braces.rs:44:13
|
LL | let _ = format!["ugh {} stop being such a good compiler", "hello"];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider writing `format!("ugh () stop being such a good compiler", "hello")`
- --> $DIR/conf_nonstandard_macro_braces.rs:38:13
+ --> $DIR/conf_nonstandard_macro_braces.rs:44:13
|
LL | let _ = format!["ugh {} stop being such a good compiler", "hello"];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: use of irregular braces for `quote!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:39:13
+ --> $DIR/conf_nonstandard_macro_braces.rs:45:13
|
LL | let _ = quote!(let x = 1;);
| ^^^^^^^^^^^^^^^^^^
|
help: consider writing `quote! {let x = 1;}`
- --> $DIR/conf_nonstandard_macro_braces.rs:39:13
+ --> $DIR/conf_nonstandard_macro_braces.rs:45:13
|
LL | let _ = quote!(let x = 1;);
| ^^^^^^^^^^^^^^^^^^
error: use of irregular braces for `quote::quote!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:40:13
+ --> $DIR/conf_nonstandard_macro_braces.rs:46:13
|
LL | let _ = quote::quote!(match match match);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider writing `quote::quote! {match match match}`
- --> $DIR/conf_nonstandard_macro_braces.rs:40:13
+ --> $DIR/conf_nonstandard_macro_braces.rs:46:13
|
LL | let _ = quote::quote!(match match match);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | vec!{0, 0, 0}
| ^^^^^^^^^^^^^
...
-LL | let _ = test!();
+LL | let _ = test!(); // trigger when macro def is inside our own crate
| ------- in this macro invocation
|
help: consider writing `vec![0, 0, 0]`
LL | vec!{0, 0, 0}
| ^^^^^^^^^^^^^
...
-LL | let _ = test!();
+LL | let _ = test!(); // trigger when macro def is inside our own crate
| ------- in this macro invocation
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
error: use of irregular braces for `type_pos!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:49:12
+ --> $DIR/conf_nonstandard_macro_braces.rs:55:12
|
LL | let _: type_pos!(usize) = vec![];
| ^^^^^^^^^^^^^^^^
|
help: consider writing `type_pos![usize]`
- --> $DIR/conf_nonstandard_macro_braces.rs:49:12
+ --> $DIR/conf_nonstandard_macro_braces.rs:55:12
|
LL | let _: type_pos!(usize) = vec![];
| ^^^^^^^^^^^^^^^^
error: use of irregular braces for `eprint!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:51:5
+ --> $DIR/conf_nonstandard_macro_braces.rs:57:5
|
LL | eprint!("test if user config overrides defaults");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider writing `eprint!["test if user config overrides defaults"];`
- --> $DIR/conf_nonstandard_macro_braces.rs:51:5
+ --> $DIR/conf_nonstandard_macro_braces.rs:57:5
|
LL | eprint!("test if user config overrides defaults");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
--- /dev/null
+pub trait A {}
+
+macro_rules! __implicit_hasher_test_macro {
+ (impl< $($impl_arg:tt),* > for $kind:ty where $($bounds:tt)*) => {
+ __implicit_hasher_test_macro!( ($($impl_arg),*) ($kind) ($($bounds)*) );
+ };
+
+ (($($impl_arg:tt)*) ($($kind_arg:tt)*) ($($bounds:tt)*)) => {
+ impl< $($impl_arg)* > test_macro::A for $($kind_arg)* where $($bounds)* { }
+ };
+}
|
= note: `-D bare-trait-objects` implied by `-D warnings`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: trait objects without an explicit `dyn` are deprecated
--> $DIR/ice-3969.rs:27:16
| ^ help: use `dyn`: `dyn A`
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: trait objects without an explicit `dyn` are deprecated
--> $DIR/ice-3969.rs:27:57
| ^ help: use `dyn`: `dyn A`
|
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: aborting due to 3 previous errors
let mut heap = BinaryHeap::from(vec![1, 3]);
let mut heap2 = BinaryHeap::from(vec![]);
- heap2.extend(heap.drain())
+ heap2.extend(heap.drain());
+
+ let mut x = vec![0, 1, 2, 3, 5];
+ let ref_x = &mut x;
+ let mut y = Vec::new();
+ y.append(ref_x);
}
fn return_vector() -> Vec<u8> {
let mut heap = BinaryHeap::from(vec![1, 3]);
let mut heap2 = BinaryHeap::from(vec![]);
- heap2.extend(heap.drain())
+ heap2.extend(heap.drain());
+
+ let mut x = vec![0, 1, 2, 3, 5];
+ let ref_x = &mut x;
+ let mut y = Vec::new();
+ y.extend(ref_x.drain(..));
}
fn return_vector() -> Vec<u8> {
LL | vec11.extend(return_vector().drain(..));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `vec11.append(&mut return_vector())`
-error: aborting due to 3 previous errors
+error: use of `extend` instead of `append` for adding the full range of a second vector
+ --> $DIR/extend_with_drain.rs:49:5
+ |
+LL | y.extend(ref_x.drain(..));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `y.append(ref_x)`
+
+error: aborting due to 4 previous errors
// and should not cause an ICE
// See #2707
#[macro_use]
-#[path = "../auxiliary/test_macro.rs"]
+#[path = "auxiliary/test_macro.rs"]
pub mod test_macro;
__implicit_hasher_test_macro!(impl<K, V> for HashMap<K, V> where V: test_macro::A);
#![allow(clippy::missing_docs_in_private_items)]
#![allow(clippy::map_identity)]
#![allow(clippy::unnecessary_wraps)]
+#![feature(result_flattening)]
fn main() {
// mapping to Option on Iterator
// mapping to Option on Option
let _: Option<_> = (Some(Some(1))).and_then(|x| x);
+
+ // mapping to Result on Result
+ let _: Result<_, &str> = (Ok(Ok(1))).and_then(|x| x);
}
#![allow(clippy::missing_docs_in_private_items)]
#![allow(clippy::map_identity)]
#![allow(clippy::unnecessary_wraps)]
+#![feature(result_flattening)]
fn main() {
// mapping to Option on Iterator
// mapping to Option on Option
let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
+
+ // mapping to Result on Result
+ let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
}
error: called `map(..).flatten()` on an `Iterator`
- --> $DIR/map_flatten.rs:16:46
+ --> $DIR/map_flatten.rs:17:46
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(option_id)`
= note: `-D clippy::map-flatten` implied by `-D warnings`
error: called `map(..).flatten()` on an `Iterator`
- --> $DIR/map_flatten.rs:17:46
+ --> $DIR/map_flatten.rs:18:46
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(option_id_ref)`
error: called `map(..).flatten()` on an `Iterator`
- --> $DIR/map_flatten.rs:18:46
+ --> $DIR/map_flatten.rs:19:46
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(option_id_closure)`
error: called `map(..).flatten()` on an `Iterator`
- --> $DIR/map_flatten.rs:19:46
+ --> $DIR/map_flatten.rs:20:46
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `filter_map` instead: `.filter_map(|x| x.checked_add(1))`
error: called `map(..).flatten()` on an `Iterator`
- --> $DIR/map_flatten.rs:22:46
+ --> $DIR/map_flatten.rs:23:46
|
LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `flat_map` instead: `.flat_map(|x| 0..x)`
error: called `map(..).flatten()` on an `Option`
- --> $DIR/map_flatten.rs:25:39
+ --> $DIR/map_flatten.rs:26:39
|
LL | let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
| ^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `.and_then(|x| x)`
-error: aborting due to 6 previous errors
+error: called `map(..).flatten()` on an `Result`
+ --> $DIR/map_flatten.rs:29:41
+ |
+LL | let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
+ | ^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `.and_then(|x| x)`
+
+error: aborting due to 7 previous errors
LL | | }
LL | | }
| |_____^
+ |
+help: if you need the first element of the iterator, try writing
+ |
+LL | if let Some(x) = (0..10).next() {
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: this loop never actually loops
--> $DIR/never_loop.rs:157:5
LL | 5..6;
| ^^^^^
+error: statement with no effect
+ --> $DIR/no_effect.rs:83:5
+ |
+LL | 5..=6;
+ | ^^^^^^
+
error: statement with no effect
--> $DIR/no_effect.rs:84:5
|
LL | FooString { s: s };
| ^^^^^^^^^^^^^^^^^^^
-error: aborting due to 25 previous errors
+error: aborting due to 26 previous errors
}
}
+ struct FakeDefault;
+ impl FakeDefault {
+ fn default() -> Self {
+ FakeDefault
+ }
+ }
+
+ impl Default for FakeDefault {
+ fn default() -> Self {
+ FakeDefault
+ }
+ }
+
enum Enum {
A(i32),
}
let with_default_type = Some(1);
with_default_type.unwrap_or_default();
+ let self_default = None::<FakeDefault>;
+ self_default.unwrap_or_else(<FakeDefault>::default);
+
+ let real_default = None::<FakeDefault>;
+ real_default.unwrap_or_default();
+
let with_vec = Some(vec![1]);
with_vec.unwrap_or_default();
}
}
+ struct FakeDefault;
+ impl FakeDefault {
+ fn default() -> Self {
+ FakeDefault
+ }
+ }
+
+ impl Default for FakeDefault {
+ fn default() -> Self {
+ FakeDefault
+ }
+ }
+
enum Enum {
A(i32),
}
let with_default_type = Some(1);
with_default_type.unwrap_or(u64::default());
+ let self_default = None::<FakeDefault>;
+ self_default.unwrap_or(<FakeDefault>::default());
+
+ let real_default = None::<FakeDefault>;
+ real_default.unwrap_or(<FakeDefault as Default>::default());
+
let with_vec = Some(vec![1]);
with_vec.unwrap_or(vec![]);
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:33:19
+ --> $DIR/or_fun_call.rs:46:19
|
LL | with_const_fn.unwrap_or(Duration::from_secs(5));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Duration::from_secs(5))`
= note: `-D clippy::or-fun-call` implied by `-D warnings`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:36:22
+ --> $DIR/or_fun_call.rs:49:22
|
LL | with_constructor.unwrap_or(make());
| ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)`
error: use of `unwrap_or` followed by a call to `new`
- --> $DIR/or_fun_call.rs:39:5
+ --> $DIR/or_fun_call.rs:52:5
|
LL | with_new.unwrap_or(Vec::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:42:21
+ --> $DIR/or_fun_call.rs:55:21
|
LL | with_const_args.unwrap_or(Vec::with_capacity(12));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:45:14
+ --> $DIR/or_fun_call.rs:58:14
|
LL | with_err.unwrap_or(make());
| ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:48:19
+ --> $DIR/or_fun_call.rs:61:19
|
LL | with_err_args.unwrap_or(Vec::with_capacity(12));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))`
error: use of `unwrap_or` followed by a call to `default`
- --> $DIR/or_fun_call.rs:51:5
+ --> $DIR/or_fun_call.rs:64:5
|
LL | with_default_trait.unwrap_or(Default::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()`
error: use of `unwrap_or` followed by a call to `default`
- --> $DIR/or_fun_call.rs:54:5
+ --> $DIR/or_fun_call.rs:67:5
|
LL | with_default_type.unwrap_or(u64::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()`
+error: use of `unwrap_or` followed by a function call
+ --> $DIR/or_fun_call.rs:70:18
+ |
+LL | self_default.unwrap_or(<FakeDefault>::default());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(<FakeDefault>::default)`
+
+error: use of `unwrap_or` followed by a call to `default`
+ --> $DIR/or_fun_call.rs:73:5
+ |
+LL | real_default.unwrap_or(<FakeDefault as Default>::default());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `real_default.unwrap_or_default()`
+
error: use of `unwrap_or` followed by a call to `new`
- --> $DIR/or_fun_call.rs:57:5
+ --> $DIR/or_fun_call.rs:76:5
|
LL | with_vec.unwrap_or(vec![]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_default()`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:60:21
+ --> $DIR/or_fun_call.rs:79:21
|
LL | without_default.unwrap_or(Foo::new());
| ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)`
error: use of `or_insert` followed by a function call
- --> $DIR/or_fun_call.rs:63:19
+ --> $DIR/or_fun_call.rs:82:19
|
LL | map.entry(42).or_insert(String::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)`
error: use of `or_insert` followed by a function call
- --> $DIR/or_fun_call.rs:66:23
+ --> $DIR/or_fun_call.rs:85:23
|
LL | map_vec.entry(42).or_insert(vec![]);
| ^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(Vec::new)`
error: use of `or_insert` followed by a function call
- --> $DIR/or_fun_call.rs:69:21
+ --> $DIR/or_fun_call.rs:88:21
|
LL | btree.entry(42).or_insert(String::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)`
error: use of `or_insert` followed by a function call
- --> $DIR/or_fun_call.rs:72:25
+ --> $DIR/or_fun_call.rs:91:25
|
LL | btree_vec.entry(42).or_insert(vec![]);
| ^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(Vec::new)`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:75:21
+ --> $DIR/or_fun_call.rs:94:21
|
LL | let _ = stringy.unwrap_or("".to_owned());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:83:21
+ --> $DIR/or_fun_call.rs:102:21
|
LL | let _ = Some(1).unwrap_or(map[&1]);
| ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:85:21
+ --> $DIR/or_fun_call.rs:104:21
|
LL | let _ = Some(1).unwrap_or(map[&1]);
| ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])`
error: use of `or` followed by a function call
- --> $DIR/or_fun_call.rs:109:35
+ --> $DIR/or_fun_call.rs:128:35
|
LL | let _ = Some("a".to_string()).or(Some("b".to_string()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))`
error: use of `or` followed by a function call
- --> $DIR/or_fun_call.rs:113:10
+ --> $DIR/or_fun_call.rs:132:10
|
LL | .or(Some(Bar(b, Duration::from_secs(2))));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some(Bar(b, Duration::from_secs(2))))`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:141:14
+ --> $DIR/or_fun_call.rs:160:14
|
LL | None.unwrap_or(s.as_mut_vec());
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| s.as_mut_vec())`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:146:14
+ --> $DIR/or_fun_call.rs:165:14
|
LL | None.unwrap_or(unsafe { s.as_mut_vec() });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { s.as_mut_vec() })`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:148:14
+ --> $DIR/or_fun_call.rs:167:14
|
LL | None.unwrap_or( unsafe { s.as_mut_vec() } );
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { s.as_mut_vec() })`
-error: aborting due to 22 previous errors
+error: aborting due to 24 previous errors
// names often used in win32 code (for example WindowProc)
let wparam: i32;
let lparam: i32;
+
+ let iter: i32;
+ let item: i32;
}
fn foo() {
| ^^^^^^
error: binding's name is too similar to existing binding
- --> $DIR/similar_names.rs:85:16
+ --> $DIR/similar_names.rs:88:16
|
LL | bpple: sprang,
| ^^^^^^
|
note: existing binding defined here
- --> $DIR/similar_names.rs:84:16
+ --> $DIR/similar_names.rs:87:16
|
LL | apple: spring,
| ^^^^^^
clippy::no_effect,
clippy::redundant_clone,
redundant_semicolons,
+ dead_code,
unused_assignments
)]
fn field() {
let mut bar = Bar { a: 1, b: 2 };
- let temp = bar.a;
- bar.a = bar.b;
- bar.b = temp;
+ std::mem::swap(&mut bar.a, &mut bar.b);
let mut baz = vec![bar.clone(), bar.clone()];
let temp = baz[0].a;
foo[1][0] = temp;
// swap(foo[0][1], foo[1][0]) would fail
+ // this could use split_at_mut and mem::swap, but that is not much simpler.
}
fn vec() {
foo.swap(0, 1);
}
+fn xor_swap_locals() {
+ // This is an xor-based swap of local variables.
+ let mut a = 0;
+ let mut b = 1;
+ std::mem::swap(&mut a, &mut b)
+}
+
+fn xor_field_swap() {
+ // This is an xor-based swap of fields in a struct.
+ let mut bar = Bar { a: 0, b: 1 };
+ std::mem::swap(&mut bar.a, &mut bar.b)
+}
+
+fn xor_slice_swap() {
+ // This is an xor-based swap of a slice
+ let foo = &mut [1, 2];
+ foo.swap(0, 1)
+}
+
+fn xor_no_swap() {
+ // This is a sequence of xor-assignment statements that doesn't result in a swap.
+ let mut a = 0;
+ let mut b = 1;
+ let mut c = 2;
+ a ^= b;
+ b ^= c;
+ a ^= c;
+ c ^= a;
+}
+
+fn xor_unswappable_slice() {
+ let foo = &mut [vec![1, 2], vec![3, 4]];
+ foo[0][1] ^= foo[1][0];
+ foo[1][0] ^= foo[0][0];
+ foo[0][1] ^= foo[1][0];
+
+ // swap(foo[0][1], foo[1][0]) would fail
+ // this could use split_at_mut and mem::swap, but that is not much simpler.
+}
+
+fn distinct_slice() {
+ let foo = &mut [vec![1, 2], vec![3, 4]];
+ let bar = &mut [vec![1, 2], vec![3, 4]];
+ std::mem::swap(&mut foo[0][1], &mut bar[1][0]);
+}
+
#[rustfmt::skip]
fn main() {
- field();
- array();
- slice();
- unswappable_slice();
- vec();
let mut a = 42;
let mut b = 1337;
clippy::no_effect,
clippy::redundant_clone,
redundant_semicolons,
+ dead_code,
unused_assignments
)]
foo[1][0] = temp;
// swap(foo[0][1], foo[1][0]) would fail
+ // this could use split_at_mut and mem::swap, but that is not much simpler.
}
fn vec() {
foo.swap(0, 1);
}
+fn xor_swap_locals() {
+ // This is an xor-based swap of local variables.
+ let mut a = 0;
+ let mut b = 1;
+ a ^= b;
+ b ^= a;
+ a ^= b;
+}
+
+fn xor_field_swap() {
+ // This is an xor-based swap of fields in a struct.
+ let mut bar = Bar { a: 0, b: 1 };
+ bar.a ^= bar.b;
+ bar.b ^= bar.a;
+ bar.a ^= bar.b;
+}
+
+fn xor_slice_swap() {
+ // This is an xor-based swap of a slice
+ let foo = &mut [1, 2];
+ foo[0] ^= foo[1];
+ foo[1] ^= foo[0];
+ foo[0] ^= foo[1];
+}
+
+fn xor_no_swap() {
+ // This is a sequence of xor-assignment statements that doesn't result in a swap.
+ let mut a = 0;
+ let mut b = 1;
+ let mut c = 2;
+ a ^= b;
+ b ^= c;
+ a ^= c;
+ c ^= a;
+}
+
+fn xor_unswappable_slice() {
+ let foo = &mut [vec![1, 2], vec![3, 4]];
+ foo[0][1] ^= foo[1][0];
+ foo[1][0] ^= foo[0][0];
+ foo[0][1] ^= foo[1][0];
+
+ // swap(foo[0][1], foo[1][0]) would fail
+ // this could use split_at_mut and mem::swap, but that is not much simpler.
+}
+
+fn distinct_slice() {
+ let foo = &mut [vec![1, 2], vec![3, 4]];
+ let bar = &mut [vec![1, 2], vec![3, 4]];
+ let temp = foo[0][1];
+ foo[0][1] = bar[1][0];
+ bar[1][0] = temp;
+}
+
#[rustfmt::skip]
fn main() {
- field();
- array();
- slice();
- unswappable_slice();
- vec();
let mut a = 42;
let mut b = 1337;
+error: this looks like you are swapping `bar.a` and `bar.b` manually
+ --> $DIR/swap.rs:24:5
+ |
+LL | / let temp = bar.a;
+LL | | bar.a = bar.b;
+LL | | bar.b = temp;
+ | |________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b)`
+ |
+ = note: `-D clippy::manual-swap` implied by `-D warnings`
+ = note: or maybe you should use `std::mem::replace`?
+
error: this looks like you are swapping elements of `foo` manually
- --> $DIR/swap.rs:35:5
+ --> $DIR/swap.rs:36:5
|
LL | / let temp = foo[0];
LL | | foo[0] = foo[1];
LL | | foo[1] = temp;
| |_________________^ help: try: `foo.swap(0, 1)`
- |
- = note: `-D clippy::manual-swap` implied by `-D warnings`
error: this looks like you are swapping elements of `foo` manually
- --> $DIR/swap.rs:44:5
+ --> $DIR/swap.rs:45:5
|
LL | / let temp = foo[0];
LL | | foo[0] = foo[1];
| |_________________^ help: try: `foo.swap(0, 1)`
error: this looks like you are swapping elements of `foo` manually
- --> $DIR/swap.rs:62:5
+ --> $DIR/swap.rs:64:5
|
LL | / let temp = foo[0];
LL | | foo[0] = foo[1];
| |_________________^ help: try: `foo.swap(0, 1)`
error: this looks like you are swapping `a` and `b` manually
- --> $DIR/swap.rs:83:7
+ --> $DIR/swap.rs:75:5
+ |
+LL | / a ^= b;
+LL | | b ^= a;
+LL | | a ^= b;
+ | |___________^ help: try: `std::mem::swap(&mut a, &mut b)`
+
+error: this looks like you are swapping `bar.a` and `bar.b` manually
+ --> $DIR/swap.rs:83:5
+ |
+LL | / bar.a ^= bar.b;
+LL | | bar.b ^= bar.a;
+LL | | bar.a ^= bar.b;
+ | |___________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b)`
+
+error: this looks like you are swapping elements of `foo` manually
+ --> $DIR/swap.rs:91:5
+ |
+LL | / foo[0] ^= foo[1];
+LL | | foo[1] ^= foo[0];
+LL | | foo[0] ^= foo[1];
+ | |_____________________^ help: try: `foo.swap(0, 1)`
+
+error: this looks like you are swapping `foo[0][1]` and `bar[1][0]` manually
+ --> $DIR/swap.rs:120:5
+ |
+LL | / let temp = foo[0][1];
+LL | | foo[0][1] = bar[1][0];
+LL | | bar[1][0] = temp;
+ | |____________________^ help: try: `std::mem::swap(&mut foo[0][1], &mut bar[1][0])`
+ |
+ = note: or maybe you should use `std::mem::replace`?
+
+error: this looks like you are swapping `a` and `b` manually
+ --> $DIR/swap.rs:134:7
|
LL | ; let t = a;
| _______^
= note: or maybe you should use `std::mem::replace`?
error: this looks like you are swapping `c.0` and `a` manually
- --> $DIR/swap.rs:92:7
+ --> $DIR/swap.rs:143:7
|
LL | ; let t = c.0;
| _______^
= note: or maybe you should use `std::mem::replace`?
error: this looks like you are trying to swap `a` and `b`
- --> $DIR/swap.rs:80:5
+ --> $DIR/swap.rs:131:5
|
LL | / a = b;
LL | | b = a;
= note: or maybe you should use `std::mem::replace`?
error: this looks like you are trying to swap `c.0` and `a`
- --> $DIR/swap.rs:89:5
+ --> $DIR/swap.rs:140:5
|
LL | / c.0 = a;
LL | | a = c.0;
|
= note: or maybe you should use `std::mem::replace`?
-error: aborting due to 7 previous errors
+error: aborting due to 12 previous errors
fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
fn bad2(x: &u32, y: &Foo, z: &Baz) {}
+
+ fn bad_issue7518(self, other: &Self) {}
}
impl AsRef<u32> for Foo {
| ^^^^ help: consider passing by value instead: `Baz`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:72:16
+ --> $DIR/trivially_copy_pass_by_ref.rs:62:35
+ |
+LL | fn bad_issue7518(self, other: &Self) {}
+ | ^^^^^ help: consider passing by value instead: `Self`
+
+error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
+ --> $DIR/trivially_copy_pass_by_ref.rs:74:16
|
LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `u32`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:72:25
+ --> $DIR/trivially_copy_pass_by_ref.rs:74:25
|
LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `Foo`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:72:34
+ --> $DIR/trivially_copy_pass_by_ref.rs:74:34
|
LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `Baz`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:76:34
+ --> $DIR/trivially_copy_pass_by_ref.rs:78:34
|
LL | fn trait_method(&self, _foo: &Foo);
| ^^^^ help: consider passing by value instead: `Foo`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:108:21
+ --> $DIR/trivially_copy_pass_by_ref.rs:110:21
|
LL | fn foo_never(x: &i32) {
| ^^^^ help: consider passing by value instead: `i32`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:113:15
+ --> $DIR/trivially_copy_pass_by_ref.rs:115:15
|
LL | fn foo(x: &i32) {
| ^^^^ help: consider passing by value instead: `i32`
-error: aborting due to 16 previous errors
+error: aborting due to 17 previous errors
--- /dev/null
+// run-rustfix
+
+#![warn(clippy::unwrap_or_else_default)]
+#![allow(dead_code)]
+#![allow(clippy::unnecessary_wraps)]
+
+/// Checks implementation of the `UNWRAP_OR_ELSE_DEFAULT` lint.
+fn unwrap_or_else_default() {
+ struct Foo;
+
+ impl Foo {
+ fn new() -> Foo {
+ Foo
+ }
+
+ // fake default, we should not trigger on this
+ fn default() -> Foo {
+ Foo
+ }
+ }
+
+ struct HasDefaultAndDuplicate;
+
+ impl HasDefaultAndDuplicate {
+ fn default() -> Self {
+ HasDefaultAndDuplicate
+ }
+ }
+
+ impl Default for HasDefaultAndDuplicate {
+ fn default() -> Self {
+ HasDefaultAndDuplicate
+ }
+ }
+
+ enum Enum {
+ A(),
+ }
+
+ fn make<T, V>(_: V) -> T {
+ unimplemented!();
+ }
+
+ let with_enum = Some(Enum::A());
+ with_enum.unwrap_or_else(Enum::A);
+
+ let with_new = Some(vec![1]);
+ with_new.unwrap_or_else(Vec::new);
+
+ let with_err: Result<_, ()> = Ok(vec![1]);
+ with_err.unwrap_or_else(make);
+
+ // should not be changed
+ let with_fake_default = None::<Foo>;
+ with_fake_default.unwrap_or_else(Foo::default);
+
+ // should not be changed
+ let with_fake_default2 = None::<HasDefaultAndDuplicate>;
+ with_fake_default2.unwrap_or_else(<HasDefaultAndDuplicate>::default);
+
+ let with_real_default = None::<HasDefaultAndDuplicate>;
+ with_real_default.unwrap_or_default();
+
+ let with_default_trait = Some(1);
+ with_default_trait.unwrap_or_default();
+
+ let with_default_type = Some(1);
+ with_default_type.unwrap_or_default();
+}
+
+fn main() {}
--- /dev/null
+// run-rustfix
+
+#![warn(clippy::unwrap_or_else_default)]
+#![allow(dead_code)]
+#![allow(clippy::unnecessary_wraps)]
+
+/// Checks implementation of the `UNWRAP_OR_ELSE_DEFAULT` lint.
+fn unwrap_or_else_default() {
+ struct Foo;
+
+ impl Foo {
+ fn new() -> Foo {
+ Foo
+ }
+
+ // fake default, we should not trigger on this
+ fn default() -> Foo {
+ Foo
+ }
+ }
+
+ struct HasDefaultAndDuplicate;
+
+ impl HasDefaultAndDuplicate {
+ fn default() -> Self {
+ HasDefaultAndDuplicate
+ }
+ }
+
+ impl Default for HasDefaultAndDuplicate {
+ fn default() -> Self {
+ HasDefaultAndDuplicate
+ }
+ }
+
+ enum Enum {
+ A(),
+ }
+
+ fn make<T, V>(_: V) -> T {
+ unimplemented!();
+ }
+
+ let with_enum = Some(Enum::A());
+ with_enum.unwrap_or_else(Enum::A);
+
+ let with_new = Some(vec![1]);
+ with_new.unwrap_or_else(Vec::new);
+
+ let with_err: Result<_, ()> = Ok(vec![1]);
+ with_err.unwrap_or_else(make);
+
+ // should not be changed
+ let with_fake_default = None::<Foo>;
+ with_fake_default.unwrap_or_else(Foo::default);
+
+ // should not be changed
+ let with_fake_default2 = None::<HasDefaultAndDuplicate>;
+ with_fake_default2.unwrap_or_else(<HasDefaultAndDuplicate>::default);
+
+ let with_real_default = None::<HasDefaultAndDuplicate>;
+ with_real_default.unwrap_or_else(<HasDefaultAndDuplicate as Default>::default);
+
+ let with_default_trait = Some(1);
+ with_default_trait.unwrap_or_else(Default::default);
+
+ let with_default_type = Some(1);
+ with_default_type.unwrap_or_else(u64::default);
+}
+
+fn main() {}
--- /dev/null
+error: use of `.unwrap_or_else(..)` to construct default value
+ --> $DIR/unwrap_or_else_default.rs:62:5
+ |
+LL | with_real_default.unwrap_or_else(<HasDefaultAndDuplicate as Default>::default);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_real_default.unwrap_or_default()`
+ |
+ = note: `-D clippy::unwrap-or-else-default` implied by `-D warnings`
+
+error: use of `.unwrap_or_else(..)` to construct default value
+ --> $DIR/unwrap_or_else_default.rs:65:5
+ |
+LL | with_default_trait.unwrap_or_else(Default::default);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_default_trait.unwrap_or_default()`
+
+error: use of `.unwrap_or_else(..)` to construct default value
+ --> $DIR/unwrap_or_else_default.rs:68:5
+ |
+LL | with_default_type.unwrap_or_else(u64::default);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `with_default_type.unwrap_or_default()`
+
+error: aborting due to 3 previous errors
+
x();
}
+fn issue7510() {
+ let mut it = 0..10;
+ let it = &mut it;
+ // Needs to reborrow `it` as the binding isn't mutable
+ for x in &mut *it {
+ if x % 2 == 0 {
+ break;
+ }
+ }
+ println!("{}", it.next().unwrap());
+
+ struct S<T>(T);
+ let mut it = 0..10;
+ let it = S(&mut it);
+ // Needs to reborrow `it.0` as the binding isn't mutable
+ for x in &mut *it.0 {
+ if x % 2 == 0 {
+ break;
+ }
+ }
+ println!("{}", it.0.next().unwrap());
+}
+
+fn exact_match_with_single_field() {
+ struct S<T>(T);
+ let mut s = S(0..10);
+ // Don't lint. `s.0` is used inside the loop.
+ while let Some(_) = s.0.next() {
+ let _ = &mut s.0;
+ }
+}
+
fn main() {
let mut it = 0..20;
for _ in it {
x();
}
+fn issue7510() {
+ let mut it = 0..10;
+ let it = &mut it;
+ // Needs to reborrow `it` as the binding isn't mutable
+ while let Some(x) = it.next() {
+ if x % 2 == 0 {
+ break;
+ }
+ }
+ println!("{}", it.next().unwrap());
+
+ struct S<T>(T);
+ let mut it = 0..10;
+ let it = S(&mut it);
+ // Needs to reborrow `it.0` as the binding isn't mutable
+ while let Some(x) = it.0.next() {
+ if x % 2 == 0 {
+ break;
+ }
+ }
+ println!("{}", it.0.next().unwrap());
+}
+
+fn exact_match_with_single_field() {
+ struct S<T>(T);
+ let mut s = S(0..10);
+ // Don't lint. `s.0` is used inside the loop.
+ while let Some(_) = s.0.next() {
+ let _ = &mut s.0;
+ }
+}
+
fn main() {
let mut it = 0..20;
while let Some(..) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in &mut it`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:339:5
+ --> $DIR/while_let_on_iterator.rs:341:5
+ |
+LL | while let Some(x) = it.next() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in &mut *it`
+
+error: this loop could be written as a `for` loop
+ --> $DIR/while_let_on_iterator.rs:352:5
+ |
+LL | while let Some(x) = it.0.next() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in &mut *it.0`
+
+error: this loop could be written as a `for` loop
+ --> $DIR/while_let_on_iterator.rs:371:5
|
LL | while let Some(..) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it`
-error: aborting due to 19 previous errors
+error: aborting due to 21 previous errors
-Subproject commit ea105f9396a9dab68e71efb06016b7c76c83ba7c
+Subproject commit 5664a2b0b31403024ce5ab927760d630d5ddc9a4
// will blow up. Template strings are not tested and might also be
// broken.
function extractFunction(content, functionName) {
- var indent = 0;
+ var level = 0;
var splitter = "function " + functionName + "(";
+ var stop;
+ var pos, start;
while (true) {
- var start = content.indexOf(splitter);
+ start = content.indexOf(splitter);
if (start === -1) {
break;
}
- var pos = start;
+ pos = start;
while (pos < content.length && content[pos] !== ')') {
pos += 1;
}
}
while (pos < content.length) {
// Eat single-line comments
- if (content[pos] === '/' && pos > 0 && content[pos-1] === '/') {
+ if (content[pos] === '/' && pos > 0 && content[pos - 1] === '/') {
do {
pos += 1;
} while (pos < content.length && content[pos] !== '\n');
+ // Eat multiline comment.
+ } else if (content[pos] === '*' && pos > 0 && content[pos - 1] === '/') {
+ do {
+ pos += 1;
+ } while (pos < content.length && content[pos] !== '/' && content[pos - 1] !== '*');
+
// Eat quoted strings
} else if (content[pos] === '"' || content[pos] === "'" || content[pos] === "`") {
- var stop = content[pos];
- var is_escaped = false;
+ stop = content[pos];
do {
if (content[pos] === '\\') {
- pos += 2;
- } else {
pos += 1;
}
- } while (pos < content.length &&
- (content[pos] !== stop || content[pos - 1] === '\\'));
+ pos += 1;
+ } while (pos < content.length && content[pos] !== stop);
- // Otherwise, check for indent
+ // Otherwise, check for block level.
} else if (content[pos] === '{') {
- indent += 1;
+ level += 1;
} else if (content[pos] === '}') {
- indent -= 1;
- if (indent === 0) {
+ level -= 1;
+ if (level === 0) {
return content.slice(start, pos + 1);
}
}