name = "clippy"
version = "0.1.58"
dependencies = [
- "cargo_metadata 0.12.0",
+ "cargo_metadata 0.14.0",
"clippy_lints",
"clippy_utils",
"compiletest_rs",
"regex",
"rustc-workspace-hack",
"rustc_tools_util 0.2.0",
- "semver 0.11.0",
+ "semver 1.0.3",
"serde",
"syn",
"tempfile",
name = "clippy_lints"
version = "0.1.58"
dependencies = [
- "cargo_metadata 0.12.0",
+ "cargo_metadata 0.14.0",
"clippy_utils",
"if_chain",
"itertools 0.10.1",
"quine-mc_cluskey",
"regex-syntax",
"rustc-semver",
- "semver 0.11.0",
+ "semver 1.0.3",
"serde",
"serde_json",
"toml",
[[package]]
name = "compiletest_rs"
-version = "0.7.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64698e5e2435db061a85e6320af12c30c5fd88eb84b35d2c1e03ce4f143255ca"
+checksum = "29843cb8d351febf86557681d049d1e1652b81a086a190fa1173c07fd17fbf83"
dependencies = [
"diff",
"filetime",
[[package]]
name = "libc"
-version = "0.2.103"
+version = "0.2.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
+checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673"
dependencies = [
"rustc-std-workspace-core",
]
"rustc_span",
"tracing",
"unicode-normalization",
+ "unicode-width",
]
[[package]]
+Version 1.56.1 (2021-11-01)
+===========================
+
+- New lints to detect the presence of bidirectional-override Unicode
+ codepoints in the compiled source code ([CVE-2021-42574])
+
+[CVE-2021-42574]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-42574
+
Version 1.56.0 (2021-10-21)
========================
The `rustc_ast` crate contains those things concerned purely with syntax
-– that is, the AST ("abstract syntax tree"), parser, pretty-printer,
-lexer, macro expander, and utilities for traversing ASTs.
+– that is, the AST ("abstract syntax tree"), along with some definitions for tokens and token streams, data structures/traits for mutating ASTs, and shared definitions for other AST-related parts of the compiler (like the lexer and macro-expansion).
For more information about how these things work in rustc, see the
rustc dev guide:
}
#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct TraitKind(
- pub IsAuto,
- pub Unsafe,
- pub Generics,
- pub GenericBounds,
- pub Vec<P<AssocItem>>,
-);
+pub struct Trait {
+ pub unsafety: Unsafe,
+ pub is_auto: IsAuto,
+ pub generics: Generics,
+ pub bounds: GenericBounds,
+ pub items: Vec<P<AssocItem>>,
+}
#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct TyAliasKind(pub Defaultness, pub Generics, pub GenericBounds, pub Option<P<Ty>>);
+pub struct TyAlias {
+ pub defaultness: Defaultness,
+ pub generics: Generics,
+ pub bounds: GenericBounds,
+ pub ty: Option<P<Ty>>,
+}
#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct ImplKind {
- pub unsafety: Unsafe,
- pub polarity: ImplPolarity,
+pub struct Impl {
pub defaultness: Defaultness,
- pub constness: Const,
+ pub unsafety: Unsafe,
pub generics: Generics,
-
+ pub constness: Const,
+ pub polarity: ImplPolarity,
/// The trait being implemented, if any.
pub of_trait: Option<TraitRef>,
-
pub self_ty: P<Ty>,
pub items: Vec<P<AssocItem>>,
}
#[derive(Clone, Encodable, Decodable, Debug)]
-pub struct FnKind(pub Defaultness, pub FnSig, pub Generics, pub Option<P<Block>>);
+pub struct Fn {
+ pub defaultness: Defaultness,
+ pub generics: Generics,
+ pub sig: FnSig,
+ pub body: Option<P<Block>>,
+}
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ItemKind {
/// A function declaration (`fn`).
///
/// E.g., `fn foo(bar: usize) -> usize { .. }`.
- Fn(Box<FnKind>),
+ Fn(Box<Fn>),
/// A module declaration (`mod`).
///
/// E.g., `mod foo;` or `mod foo { .. }`.
/// A type alias (`type`).
///
/// E.g., `type Foo = Bar<u8>;`.
- TyAlias(Box<TyAliasKind>),
+ TyAlias(Box<TyAlias>),
/// An enum definition (`enum`).
///
/// E.g., `enum Foo<A, B> { C<A>, D<B> }`.
/// A trait declaration (`trait`).
///
/// E.g., `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}`.
- Trait(Box<TraitKind>),
+ Trait(Box<Trait>),
/// Trait alias
///
/// E.g., `trait Foo = Bar + Quux;`.
/// An implementation.
///
/// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
- Impl(Box<ImplKind>),
+ Impl(Box<Impl>),
/// A macro invocation.
///
/// E.g., `foo!(..)`.
pub fn generics(&self) -> Option<&Generics> {
match self {
- Self::Fn(box FnKind(_, _, generics, _))
- | Self::TyAlias(box TyAliasKind(_, generics, ..))
+ Self::Fn(box Fn { generics, .. })
+ | Self::TyAlias(box TyAlias { generics, .. })
| Self::Enum(_, generics)
| Self::Struct(_, generics)
| Self::Union(_, generics)
- | Self::Trait(box TraitKind(_, _, generics, ..))
+ | Self::Trait(box Trait { generics, .. })
| Self::TraitAlias(generics, _)
- | Self::Impl(box ImplKind { generics, .. }) => Some(generics),
+ | Self::Impl(box Impl { generics, .. }) => Some(generics),
_ => None,
}
}
/// If `def` is parsed, then the constant is provided, and otherwise required.
Const(Defaultness, P<Ty>, Option<P<Expr>>),
/// An associated function.
- Fn(Box<FnKind>),
+ Fn(Box<Fn>),
/// An associated type.
- TyAlias(Box<TyAliasKind>),
+ TyAlias(Box<TyAlias>),
/// A macro expanding to associated items.
MacCall(MacCall),
}
impl AssocItemKind {
pub fn defaultness(&self) -> Defaultness {
match *self {
- Self::Const(def, ..)
- | Self::Fn(box FnKind(def, ..))
- | Self::TyAlias(box TyAliasKind(def, ..)) => def,
+ Self::Const(defaultness, ..)
+ | Self::Fn(box Fn { defaultness, .. })
+ | Self::TyAlias(box TyAlias { defaultness, .. }) => defaultness,
Self::MacCall(..) => Defaultness::Final,
}
}
/// A foreign static item (`static FOO: u8`).
Static(P<Ty>, Mutability, Option<P<Expr>>),
/// An foreign function.
- Fn(Box<FnKind>),
+ Fn(Box<Fn>),
/// An foreign type.
- TyAlias(Box<TyAliasKind>),
+ TyAlias(Box<TyAlias>),
/// A macro expanding to foreign items.
MacCall(MacCall),
}
-//! The Rust parser and macro expander.
+//! The Rust Abstract Syntax Tree (AST).
//!
//! # Note
//!
#![feature(nll)]
#![feature(min_specialization)]
#![recursion_limit = "256"]
+#![feature(slice_internals)]
#[macro_use]
extern crate rustc_macros;
pub mod comments;
pub mod literal;
pub mod parser;
+ pub mod unicode;
}
pub mod ast;
vis.visit_mt(mt);
}
TyKind::BareFn(bft) => {
- let BareFnTy { unsafety: _, ext: _, generic_params, decl } = bft.deref_mut();
+ let BareFnTy { unsafety, ext: _, generic_params, decl } = bft.deref_mut();
+ visit_unsafety(unsafety, vis);
generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
vis.visit_fn_decl(decl);
}
}
pub fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis: &mut T) {
- let ForeignMod { unsafety: _, abi: _, items } = foreign_mod;
+ let ForeignMod { unsafety, abi: _, items } = foreign_mod;
+ visit_unsafety(unsafety, vis);
items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
}
}
}
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_defaultness<T: MutVisitor>(defaultness: &mut Defaultness, vis: &mut T) {
+ match defaultness {
+ Defaultness::Default(span) => vis.visit_span(span),
+ Defaultness::Final => {}
+ }
+}
+
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_unsafety<T: MutVisitor>(unsafety: &mut Unsafe, vis: &mut T) {
+ match unsafety {
+ Unsafe::Yes(span) => vis.visit_span(span),
+ Unsafe::No => {}
+ }
+}
+
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_polarity<T: MutVisitor>(polarity: &mut ImplPolarity, vis: &mut T) {
+ match polarity {
+ ImplPolarity::Positive => {}
+ ImplPolarity::Negative(span) => vis.visit_span(span),
+ }
+}
+
+// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
+pub fn visit_constness<T: MutVisitor>(constness: &mut Const, vis: &mut T) {
+ match constness {
+ Const::Yes(span) => vis.visit_span(span),
+ Const::No => {}
+ }
+}
+
pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut Async, vis: &mut T) {
match asyncness {
Async::Yes { span: _, closure_id, return_impl_trait_id } => {
match kind {
ItemKind::ExternCrate(_orig_name) => {}
ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree),
- ItemKind::Static(ty, _, expr) | ItemKind::Const(_, ty, expr) => {
+ ItemKind::Static(ty, _, expr) => {
vis.visit_ty(ty);
visit_opt(expr, |expr| vis.visit_expr(expr));
}
- ItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+ ItemKind::Const(defaultness, ty, expr) => {
+ visit_defaultness(defaultness, vis);
+ vis.visit_ty(ty);
+ visit_opt(expr, |expr| vis.visit_expr(expr));
+ }
+ ItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
+ visit_defaultness(defaultness, vis);
visit_fn_sig(sig, vis);
vis.visit_generics(generics);
visit_opt(body, |body| vis.visit_block(body));
}
- ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
- ModKind::Loaded(items, _inline, inner_span) => {
- vis.visit_span(inner_span);
- items.flat_map_in_place(|item| vis.flat_map_item(item));
+ ItemKind::Mod(unsafety, mod_kind) => {
+ visit_unsafety(unsafety, vis);
+ match mod_kind {
+ ModKind::Loaded(items, _inline, inner_span) => {
+ vis.visit_span(inner_span);
+ items.flat_map_in_place(|item| vis.flat_map_item(item));
+ }
+ ModKind::Unloaded => {}
}
- ModKind::Unloaded => {}
- },
+ }
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
ItemKind::GlobalAsm(asm) => noop_visit_inline_asm(asm, vis),
- ItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+ ItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+ visit_defaultness(defaultness, vis);
vis.visit_generics(generics);
visit_bounds(bounds, vis);
visit_opt(ty, |ty| vis.visit_ty(ty));
vis.visit_variant_data(variant_data);
vis.visit_generics(generics);
}
- ItemKind::Impl(box ImplKind {
- unsafety: _,
- polarity: _,
- defaultness: _,
- constness: _,
+ ItemKind::Impl(box Impl {
+ defaultness,
+ unsafety,
generics,
+ constness,
+ polarity,
of_trait,
self_ty,
items,
}) => {
+ visit_defaultness(defaultness, vis);
+ visit_unsafety(unsafety, vis);
vis.visit_generics(generics);
+ visit_constness(constness, vis);
+ visit_polarity(polarity, vis);
visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref));
vis.visit_ty(self_ty);
items.flat_map_in_place(|item| vis.flat_map_impl_item(item));
}
- ItemKind::Trait(box TraitKind(.., generics, bounds, items)) => {
+ ItemKind::Trait(box Trait { unsafety, is_auto: _, generics, bounds, items }) => {
+ visit_unsafety(unsafety, vis);
vis.visit_generics(generics);
visit_bounds(bounds, vis);
items.flat_map_in_place(|item| vis.flat_map_trait_item(item));
visitor.visit_vis(vis);
visit_attrs(attrs, visitor);
match kind {
- AssocItemKind::Const(_, ty, expr) => {
+ AssocItemKind::Const(defaultness, ty, expr) => {
+ visit_defaultness(defaultness, visitor);
visitor.visit_ty(ty);
visit_opt(expr, |expr| visitor.visit_expr(expr));
}
- AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+ AssocItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
+ visit_defaultness(defaultness, visitor);
visitor.visit_generics(generics);
visit_fn_sig(sig, visitor);
visit_opt(body, |body| visitor.visit_block(body));
}
- AssocItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+ AssocItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+ visit_defaultness(defaultness, visitor);
visitor.visit_generics(generics);
visit_bounds(bounds, visitor);
visit_opt(ty, |ty| visitor.visit_ty(ty));
}
pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
- let FnHeader { unsafety: _, asyncness, constness: _, ext: _ } = header;
+ let FnHeader { unsafety, asyncness, constness, ext: _ } = header;
+ visit_constness(constness, vis);
vis.visit_asyncness(asyncness);
+ visit_unsafety(unsafety, vis);
}
// FIXME: Avoid visiting the crate as a `Mod` item, flat map only the inner items if possible,
visitor.visit_ty(ty);
visit_opt(expr, |expr| visitor.visit_expr(expr));
}
- ForeignItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+ ForeignItemKind::Fn(box Fn { defaultness, generics, sig, body }) => {
+ visit_defaultness(defaultness, visitor);
visitor.visit_generics(generics);
visit_fn_sig(sig, visitor);
visit_opt(body, |body| visitor.visit_block(body));
}
- ForeignItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+ ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty }) => {
+ visit_defaultness(defaultness, visitor);
visitor.visit_generics(generics);
visit_bounds(bounds, visitor);
visit_opt(ty, |ty| visitor.visit_ty(ty));
/// parentheses while having a high degree of confidence on the correctness of the suggestion.
pub fn can_continue_expr_unambiguously(&self) -> bool {
use AssocOp::*;
- match self {
+ matches!(
+ self,
BitXor | // `{ 42 } ^ 3`
Assign | // `{ 42 } = { 42 }`
Divide | // `{ 42 } / 42`
As | // `{ 42 } as usize`
// Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect
// NotEqual | // `{ 42 } != { 42 } struct literals parser recovery.
- Colon => true, // `{ 42 }: usize`
- _ => false,
- }
+ Colon, // `{ 42 }: usize`
+ )
}
}
--- /dev/null
+pub const TEXT_FLOW_CONTROL_CHARS: &[char] = &[
+ '\u{202A}', '\u{202B}', '\u{202D}', '\u{202E}', '\u{2066}', '\u{2067}', '\u{2068}', '\u{202C}',
+ '\u{2069}',
+];
+
+#[inline]
+pub fn contains_text_flow_control_chars(s: &str) -> bool {
+ // Char - UTF-8
+ // U+202A - E2 80 AA
+ // U+202B - E2 80 AB
+ // U+202C - E2 80 AC
+ // U+202D - E2 80 AD
+ // U+202E - E2 80 AE
+ // U+2066 - E2 81 A6
+ // U+2067 - E2 81 A7
+ // U+2068 - E2 81 A8
+ // U+2069 - E2 81 A9
+ let mut bytes = s.as_bytes();
+ loop {
+ match core::slice::memchr::memchr(0xE2, &bytes) {
+ Some(idx) => {
+ // bytes are valid UTF-8 -> E2 must be followed by two bytes
+ let ch = &bytes[idx..idx + 3];
+ match ch {
+ [_, 0x80, 0xAA..=0xAE] | [_, 0x81, 0xA6..=0xA9] => break true,
+ _ => {}
+ }
+ bytes = &bytes[idx + 3..];
+ }
+ None => {
+ break false;
+ }
+ }
+ }
+}
visitor.visit_ty(typ);
walk_list!(visitor, visit_expr, expr);
}
- ItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body)) => {
+ ItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
visitor.visit_generics(generics);
let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
visitor.visit_fn(kind, item.span, item.id)
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
}
ItemKind::GlobalAsm(ref asm) => walk_inline_asm(visitor, asm),
- ItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref ty)) => {
+ ItemKind::TyAlias(box TyAlias { defaultness: _, ref generics, ref bounds, ref ty }) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, ty);
visitor.visit_generics(generics);
visitor.visit_enum_def(enum_definition, generics, item.id, item.span)
}
- ItemKind::Impl(box ImplKind {
- unsafety: _,
- polarity: _,
+ ItemKind::Impl(box Impl {
defaultness: _,
- constness: _,
+ unsafety: _,
ref generics,
+ constness: _,
+ polarity: _,
ref of_trait,
ref self_ty,
ref items,
visitor.visit_generics(generics);
visitor.visit_variant_data(struct_definition);
}
- ItemKind::Trait(box TraitKind(.., ref generics, ref bounds, ref items)) => {
+ ItemKind::Trait(box Trait {
+ unsafety: _,
+ is_auto: _,
+ ref generics,
+ ref bounds,
+ ref items,
+ }) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
visitor.visit_ty(ty);
walk_list!(visitor, visit_expr, expr);
}
- ForeignItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+ ForeignItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
visitor.visit_generics(generics);
let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref());
visitor.visit_fn(kind, span, id);
}
- ForeignItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+ ForeignItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, ty);
visitor.visit_ty(ty);
walk_list!(visitor, visit_expr, expr);
}
- AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+ AssocItemKind::Fn(box Fn { defaultness: _, ref generics, ref sig, ref body }) => {
visitor.visit_generics(generics);
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref());
visitor.visit_fn(kind, span, id);
}
- AssocItemKind::TyAlias(box TyAliasKind(_, generics, bounds, ty)) => {
+ AssocItemKind::TyAlias(box TyAlias { defaultness: _, generics, bounds, ty }) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_ty, ty);
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
-use rustc_span::{Span, Symbol};
+use rustc_session::parse::feature_err;
+use rustc_span::{sym, Span, Symbol};
use rustc_target::asm;
use std::collections::hash_map::Entry;
use std::fmt::Write;
struct_span_err!(self.sess, sp, E0472, "inline assembly is unsupported on this target")
.emit();
}
+ if let Some(asm_arch) = asm_arch {
+ // Inline assembly is currently only stable for these architectures.
+ let is_stable = matches!(
+ asm_arch,
+ asm::InlineAsmArch::X86
+ | asm::InlineAsmArch::X86_64
+ | asm::InlineAsmArch::Arm
+ | asm::InlineAsmArch::AArch64
+ | asm::InlineAsmArch::RiscV32
+ | asm::InlineAsmArch::RiscV64
+ );
+ if !is_stable && !self.sess.features_untracked().asm_experimental_arch {
+ feature_err(
+ &self.sess.parse_sess,
+ sym::asm_experimental_arch,
+ sp,
+ "inline assembly is not stable yet on this architecture",
+ )
+ .emit();
+ }
+ }
if asm.options.contains(InlineAsmOptions::ATT_SYNTAX)
&& !matches!(asm_arch, Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64))
&& !self.sess.opts.actually_rustdoc
out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
}
}
- InlineAsmOperand::Const { ref anon_const } => hir::InlineAsmOperand::Const {
- anon_const: self.lower_anon_const(anon_const),
- },
+ InlineAsmOperand::Const { ref anon_const } => {
+ if !self.sess.features_untracked().asm_const {
+ feature_err(
+ &self.sess.parse_sess,
+ sym::asm_const,
+ *op_sp,
+ "const operands for inline assembly are unstable",
+ )
+ .emit();
+ }
+ hir::InlineAsmOperand::Const {
+ anon_const: self.lower_anon_const(anon_const),
+ }
+ }
InlineAsmOperand::Sym { ref expr } => {
+ if !self.sess.features_untracked().asm_sym {
+ feature_err(
+ &self.sess.parse_sess,
+ sym::asm_sym,
+ *op_sp,
+ "sym operands for inline assembly are unstable",
+ )
+ .emit();
+ }
hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
}
};
self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
let this = &mut ItemLowerer { lctx: this };
match item.kind {
- ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
+ ItemKind::Impl(box Impl { ref of_trait, .. }) => {
this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
}
_ => visit::walk_item(this, item),
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
hir::ItemKind::Const(ty, body_id)
}
- ItemKind::Fn(box FnKind(
- _,
- FnSig { ref decl, header, span: fn_sig_span },
+ ItemKind::Fn(box Fn {
+ sig: FnSig { ref decl, header, span: fn_sig_span },
ref generics,
ref body,
- )) => {
+ ..
+ }) => {
let fn_def_id = self.resolver.local_def_id(id);
self.with_new_scopes(|this| {
this.current_item = Some(ident.span);
ItemKind::GlobalAsm(ref asm) => {
hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm))
}
- ItemKind::TyAlias(box TyAliasKind(_, ref gen, _, Some(ref ty))) => {
+ ItemKind::TyAlias(box TyAlias { ref generics, ty: Some(ref ty), .. }) => {
// We lower
//
// type Foo = impl Trait
capturable_lifetimes: &mut FxHashSet::default(),
},
);
- let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
+ let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
hir::ItemKind::TyAlias(ty, generics)
}
- ItemKind::TyAlias(box TyAliasKind(_, ref generics, _, None)) => {
+ ItemKind::TyAlias(box TyAlias { ref generics, ty: None, .. }) => {
let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
hir::ItemKind::TyAlias(ty, generics)
self.lower_generics(generics, ImplTraitContext::disallowed()),
)
}
- ItemKind::Impl(box ImplKind {
+ ItemKind::Impl(box Impl {
unsafety,
polarity,
defaultness,
items: new_impl_items,
})
}
- ItemKind::Trait(box TraitKind(
+ ItemKind::Trait(box Trait {
is_auto,
unsafety,
ref generics,
ref bounds,
ref items,
- )) => {
+ }) => {
let bounds = self.lower_param_bounds(bounds, ImplTraitContext::disallowed());
let items = self
.arena
def_id,
ident: self.lower_ident(i.ident),
kind: match i.kind {
- ForeignItemKind::Fn(box FnKind(_, ref sig, ref generics, _)) => {
+ ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
let fdec = &sig.decl;
let (generics, (fn_dec, fn_args)) = self.add_in_band_defs(
generics,
let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
(hir::Generics::empty(), hir::TraitItemKind::Const(ty, body))
}
- AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, None)) => {
+ AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => {
let names = self.lower_fn_params_to_names(&sig.decl);
let (generics, sig) =
self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
}
- AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, Some(ref body))) => {
+ AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => {
let asyncness = sig.header.asyncness;
let body_id =
self.lower_maybe_async_body(i.span, &sig.decl, asyncness, Some(&body));
);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
}
- AssocItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref default)) => {
- let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed()));
+ AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
+ let ty = ty.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed()));
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
let kind = hir::TraitItemKind::Type(
self.lower_param_bounds(bounds, ImplTraitContext::disallowed()),
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
let (kind, has_default) = match &i.kind {
AssocItemKind::Const(_, _, default) => (hir::AssocItemKind::Const, default.is_some()),
- AssocItemKind::TyAlias(box TyAliasKind(_, _, _, default)) => {
- (hir::AssocItemKind::Type, default.is_some())
+ AssocItemKind::TyAlias(box TyAlias { ty, .. }) => {
+ (hir::AssocItemKind::Type, ty.is_some())
}
- AssocItemKind::Fn(box FnKind(_, sig, _, default)) => {
- (hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }, default.is_some())
+ AssocItemKind::Fn(box Fn { sig, body, .. }) => {
+ (hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }, body.is_some())
}
AssocItemKind::MacCall(..) => unimplemented!(),
};
hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
)
}
- AssocItemKind::Fn(box FnKind(_, sig, generics, body)) => {
+ AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
self.current_item = Some(i.span);
let asyncness = sig.header.asyncness;
let body_id =
(generics, hir::ImplItemKind::Fn(sig, body_id))
}
- AssocItemKind::TyAlias(box TyAliasKind(_, generics, _, ty)) => {
+ AssocItemKind::TyAlias(box TyAlias { generics, ty, .. }) => {
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
let kind = match ty {
None => {
kind: match &i.kind {
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type,
- AssocItemKind::Fn(box FnKind(_, sig, ..)) => {
+ AssocItemKind::Fn(box Fn { sig, .. }) => {
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
}
AssocItemKind::MacCall(..) => unimplemented!(),
}
match item.kind {
- ItemKind::Impl(box ImplKind {
+ ItemKind::Impl(box Impl {
unsafety,
polarity,
defaultness: _,
});
return; // Avoid visiting again.
}
- ItemKind::Impl(box ImplKind {
+ ItemKind::Impl(box Impl {
unsafety,
polarity,
defaultness,
.emit();
}
}
- ItemKind::Fn(box FnKind(def, ref sig, ref generics, ref body)) => {
- self.check_defaultness(item.span, def);
+ ItemKind::Fn(box Fn { defaultness, ref sig, ref generics, ref body }) => {
+ self.check_defaultness(item.span, defaultness);
if body.is_none() {
let msg = "free function without a body";
}
}
}
- ItemKind::Trait(box TraitKind(
- is_auto,
- _,
- ref generics,
- ref bounds,
- ref trait_items,
- )) => {
+ ItemKind::Trait(box Trait { is_auto, ref generics, ref bounds, ref items, .. }) => {
if is_auto == IsAuto::Yes {
// Auto traits cannot have generics, super traits nor contain items.
self.deny_generic_params(generics, item.ident.span);
self.deny_super_traits(bounds, item.ident.span);
self.deny_where_clause(&generics.where_clause, item.ident.span);
- self.deny_items(trait_items, item.ident.span);
+ self.deny_items(items, item.ident.span);
}
self.no_questions_in_bounds(bounds, "supertraits", true);
self.visit_ident(item.ident);
self.visit_generics(generics);
self.with_banned_tilde_const(|this| walk_list!(this, visit_param_bound, bounds));
- walk_list!(self, visit_assoc_item, trait_items, AssocCtxt::Trait);
+ walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait);
walk_list!(self, visit_attribute, &item.attrs);
return;
}
let msg = "free static item without body";
self.error_item_without_body(item.span, "static", msg, " = <expr>;");
}
- ItemKind::TyAlias(box TyAliasKind(def, _, ref bounds, ref body)) => {
- self.check_defaultness(item.span, def);
- if body.is_none() {
+ ItemKind::TyAlias(box TyAlias { defaultness, ref bounds, ref ty, .. }) => {
+ self.check_defaultness(item.span, defaultness);
+ if ty.is_none() {
let msg = "free type alias without body";
self.error_item_without_body(item.span, "type", msg, " = <type>;");
}
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
match &fi.kind {
- ForeignItemKind::Fn(box FnKind(def, sig, _, body)) => {
- self.check_defaultness(fi.span, *def);
+ ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
+ self.check_defaultness(fi.span, *defaultness);
self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
self.check_foreign_item_ascii_only(fi.ident);
}
- ForeignItemKind::TyAlias(box TyAliasKind(def, generics, bounds, body)) => {
- self.check_defaultness(fi.span, *def);
- self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span));
+ ForeignItemKind::TyAlias(box TyAlias { defaultness, generics, bounds, ty, .. }) => {
+ self.check_defaultness(fi.span, *defaultness);
+ self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
self.check_type_no_bounds(bounds, "`extern` blocks");
self.check_foreign_ty_genericless(generics);
self.check_foreign_item_ascii_only(fi.ident);
AssocItemKind::Const(_, _, body) => {
self.check_impl_item_provided(item.span, body, "constant", " = <expr>;");
}
- AssocItemKind::Fn(box FnKind(_, _, _, body)) => {
+ AssocItemKind::Fn(box Fn { body, .. }) => {
self.check_impl_item_provided(item.span, body, "function", " { <body> }");
}
- AssocItemKind::TyAlias(box TyAliasKind(_, _, bounds, body)) => {
- self.check_impl_item_provided(item.span, body, "type", " = <type>;");
+ AssocItemKind::TyAlias(box TyAlias { bounds, ty, .. }) => {
+ self.check_impl_item_provided(item.span, ty, "type", " = <type>;");
self.check_type_no_bounds(bounds, "`impl`s");
}
_ => {}
if ctxt == AssocCtxt::Trait || self.in_trait_impl {
self.invalid_visibility(&item.vis, None);
- if let AssocItemKind::Fn(box FnKind(_, sig, _, _)) = &item.kind {
+ if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
self.check_trait_fn_not_const(sig.header.constness);
self.check_trait_fn_not_async(item.span, sig.header.asyncness);
}
}
match item.kind {
- AssocItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref ty))
+ AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. })
if ctxt == AssocCtxt::Trait =>
{
self.visit_vis(&item.vis);
});
walk_list!(self, visit_ty, ty);
}
- AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body))
+ AssocItemKind::Fn(box Fn { ref sig, ref generics, ref body, .. })
if self.in_const_trait_impl
|| ctxt == AssocCtxt::Trait
|| matches!(sig.header.constness, Const::Yes(_)) =>
}
}
- ast::ItemKind::Impl(box ast::ImplKind {
- polarity, defaultness, ref of_trait, ..
- }) => {
+ ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => {
if let ast::ImplPolarity::Negative(span) = polarity {
gate_feature_post!(
&self,
}
}
- ast::ItemKind::Trait(box ast::TraitKind(ast::IsAuto::Yes, ..)) => {
+ ast::ItemKind::Trait(box ast::Trait { is_auto: ast::IsAuto::Yes, .. }) => {
gate_feature_post!(
&self,
auto_traits,
gate_feature_post!(&self, decl_macro, i.span, msg);
}
- ast::ItemKind::TyAlias(box ast::TyAliasKind(_, _, _, Some(ref ty))) => {
+ ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ref ty), .. }) => {
self.check_impl_trait(&ty)
}
ast::ExprKind::TryBlock(_) => {
gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
}
- ast::ExprKind::Block(_, opt_label) => {
- if let Some(label) = opt_label {
- gate_feature_post!(
- &self,
- label_break_value,
- label.ident.span,
- "labels on blocks are unstable"
- );
- }
+ ast::ExprKind::Block(_, Some(label)) => {
+ gate_feature_post!(
+ &self,
+ label_break_value,
+ label.ident.span,
+ "labels on blocks are unstable"
+ );
}
_ => {}
}
fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
let is_fn = match i.kind {
ast::AssocItemKind::Fn(_) => true,
- ast::AssocItemKind::TyAlias(box ast::TyAliasKind(_, ref generics, _, ref ty)) => {
+ ast::AssocItemKind::TyAlias(box ast::TyAlias { ref generics, ref ty, .. }) => {
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
gate_feature_post!(
&self,
self.maybe_print_comment(span.lo());
self.print_outer_attributes(attrs);
match kind {
- ast::ForeignItemKind::Fn(box ast::FnKind(def, sig, gen, body)) => {
- self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
+ ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
+ self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
}
ast::ForeignItemKind::Static(ty, mutbl, body) => {
let def = ast::Defaultness::Final;
self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
}
- ast::ForeignItemKind::TyAlias(box ast::TyAliasKind(def, generics, bounds, ty)) => {
- self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
+ ast::ForeignItemKind::TyAlias(box ast::TyAlias {
+ defaultness,
+ generics,
+ bounds,
+ ty,
+ }) => {
+ self.print_associated_type(
+ ident,
+ generics,
+ bounds,
+ ty.as_deref(),
+ vis,
+ *defaultness,
+ );
}
ast::ForeignItemKind::MacCall(m) => {
self.print_mac(m);
ast::ItemKind::Const(def, ref ty, ref body) => {
self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis, def);
}
- ast::ItemKind::Fn(box ast::FnKind(def, ref sig, ref gen, ref body)) => {
+ ast::ItemKind::Fn(box ast::Fn { defaultness, ref sig, ref generics, ref body }) => {
let body = body.as_deref();
- self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs);
+ self.print_fn_full(
+ sig,
+ item.ident,
+ generics,
+ &item.vis,
+ defaultness,
+ body,
+ &item.attrs,
+ );
}
ast::ItemKind::Mod(unsafety, ref mod_kind) => {
self.head(self.to_string(|s| {
self.print_inline_asm(asm);
self.end();
}
- ast::ItemKind::TyAlias(box ast::TyAliasKind(def, ref generics, ref bounds, ref ty)) => {
+ ast::ItemKind::TyAlias(box ast::TyAlias {
+ defaultness,
+ ref generics,
+ ref bounds,
+ ref ty,
+ }) => {
let ty = ty.as_deref();
- self.print_associated_type(item.ident, generics, bounds, ty, &item.vis, def);
+ self.print_associated_type(
+ item.ident,
+ generics,
+ bounds,
+ ty,
+ &item.vis,
+ defaultness,
+ );
}
ast::ItemKind::Enum(ref enum_definition, ref params) => {
self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis);
self.head(visibility_qualified(&item.vis, "union"));
self.print_struct(struct_def, generics, item.ident, item.span, true);
}
- ast::ItemKind::Impl(box ast::ImplKind {
+ ast::ItemKind::Impl(box ast::Impl {
unsafety,
polarity,
defaultness,
}
self.bclose(item.span);
}
- ast::ItemKind::Trait(box ast::TraitKind(
+ ast::ItemKind::Trait(box ast::Trait {
is_auto,
unsafety,
ref generics,
ref bounds,
- ref trait_items,
- )) => {
+ ref items,
+ ..
+ }) => {
self.head("");
self.print_visibility(&item.vis);
self.print_unsafety(unsafety);
self.s.word(" ");
self.bopen();
self.print_inner_attributes(&item.attrs);
- for trait_item in trait_items {
+ for trait_item in items {
self.print_assoc_item(trait_item);
}
self.bclose(item.span);
}
}
- crate fn print_record_struct_body(
- &mut self,
- fields: &Vec<ast::FieldDef>,
- span: rustc_span::Span,
- ) {
+ crate fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) {
self.nbsp();
self.bopen();
self.hardbreak_if_not_bol();
self.maybe_print_comment(span.lo());
self.print_outer_attributes(attrs);
match kind {
- ast::AssocItemKind::Fn(box ast::FnKind(def, sig, gen, body)) => {
- self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs);
+ ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
+ self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
}
ast::AssocItemKind::Const(def, ty, body) => {
self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
}
- ast::AssocItemKind::TyAlias(box ast::TyAliasKind(def, generics, bounds, ty)) => {
- self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def);
+ ast::AssocItemKind::TyAlias(box ast::TyAlias { defaultness, generics, bounds, ty }) => {
+ self.print_associated_type(
+ ident,
+ generics,
+ bounds,
+ ty.as_deref(),
+ vis,
+ *defaultness,
+ );
}
ast::AssocItemKind::MacCall(m) => {
self.print_mac(m);
impl BorrowExplanation {
pub(crate) fn is_explained(&self) -> bool {
- match self {
- BorrowExplanation::Unexplained => false,
- _ => true,
- }
+ !matches!(self, BorrowExplanation::Unexplained)
}
pub(crate) fn add_explanation_to_diagnostic<'tcx>(
&self,
_ => constraint_sup_scc != target_scc,
}
} else {
- match categorized_path[*i].category {
+ !matches!(
+ categorized_path[*i].category,
ConstraintCategory::OpaqueType
- | ConstraintCategory::Boring
- | ConstraintCategory::BoringNoLocation
- | ConstraintCategory::Internal
- | ConstraintCategory::Predicate(_) => false,
- _ => true,
- }
+ | ConstraintCategory::Boring
+ | ConstraintCategory::BoringNoLocation
+ | ConstraintCategory::Internal
+ | ConstraintCategory::Predicate(_)
+ )
}
};
// If the region is live at at least one location in the promoted MIR,
// then add a liveness constraint to the main MIR for this region
// at the location provided as an argument to this method
- if let Some(_) = liveness_constraints.get_elements(region).next() {
+ if liveness_constraints.get_elements(region).next().is_some() {
self.cx
.borrowck_context
.constraints
}
pub fn is_fn_def(&self) -> bool {
- match *self {
- DefiningTy::FnDef(..) => true,
- _ => false,
- }
+ matches!(*self, DefiningTy::FnDef(..))
}
pub fn is_const(&self) -> bool {
- match *self {
- DefiningTy::Const(..) => true,
- _ => false,
- }
+ matches!(*self, DefiningTy::Const(..))
}
pub fn def_id(&self) -> DefId {
if let Some(snippet) = &template_snippet {
if let Some(pos) = snippet.find(needle) {
let end = pos
- + &snippet[pos..]
+ + snippet[pos..]
.find(|c| matches!(c, '\n' | ';' | '\\' | '"'))
.unwrap_or(snippet[pos..].len() - 1);
let inner = InnerSpan::new(pos, end);
tokens: None,
},
attrs: Vec::new(),
- kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAliasKind(
- ast::Defaultness::Final,
- Generics::default(),
- Vec::new(),
- Some(type_def.to_ty(cx, self.span, type_ident, generics)),
- ))),
+ kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAlias {
+ defaultness: ast::Defaultness::Final,
+ generics: Generics::default(),
+ bounds: Vec::new(),
+ ty: Some(type_def.to_ty(cx, self.span, type_ident, generics)),
+ })),
tokens: None,
})
});
self.span,
Ident::empty(),
a,
- ast::ItemKind::Impl(Box::new(ast::ImplKind {
+ ast::ItemKind::Impl(Box::new(ast::Impl {
unsafety,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
decl: fn_decl,
span: trait_.span,
};
- let def = ast::Defaultness::Final;
+ let defaultness = ast::Defaultness::Final;
// Create the method.
P(ast::AssocItem {
tokens: None,
},
ident: method_ident,
- kind: ast::AssocItemKind::Fn(Box::new(ast::FnKind(
- def,
+ kind: ast::AssocItemKind::Fn(Box::new(ast::Fn {
+ defaultness,
sig,
- fn_generics,
- Some(body_block),
- ))),
+ generics: fn_generics,
+ body: Some(body_block),
+ })),
tokens: None,
})
}
use rustc_ast as ast;
use rustc_ast::ptr::P;
-use rustc_ast::{ImplKind, ItemKind, MetaItem};
+use rustc_ast::{Impl, ItemKind, MetaItem};
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::Span;
span,
Ident::empty(),
attrs,
- ItemKind::Impl(Box::new(ImplKind {
+ ItemKind::Impl(Box::new(Impl {
unsafety: ast::Unsafe::No,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
};
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, Attribute, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
-use rustc_ast::{FnKind, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
+use rustc_ast::{Fn, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty));
let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() };
let sig = FnSig { decl, header, span: self.span };
- let block = Some(self.cx.block_expr(output_expr));
- let kind = ItemKind::Fn(Box::new(FnKind(
- ast::Defaultness::Final,
+ let body = Some(self.cx.block_expr(output_expr));
+ let kind = ItemKind::Fn(Box::new(Fn {
+ defaultness: ast::Defaultness::Final,
sig,
- Generics::default(),
- block,
- )));
+ generics: Generics::default(),
+ body,
+ }));
let item = self.cx.item(
self.span,
Ident::from_str_and_span(&self.kind.fn_name(method.name), self.span),
fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
let has_should_panic_attr = cx.sess.contains_name(&i.attrs, sym::should_panic);
let sd = &cx.sess.parse_sess.span_diagnostic;
- if let ast::ItemKind::Fn(box ast::FnKind(_, ref sig, ref generics, _)) = i.kind {
+ if let ast::ItemKind::Fn(box ast::Fn { ref sig, ref generics, .. }) = i.kind {
if let ast::Unsafe::Yes(span) = sig.header.unsafety {
sd.struct_span_err(i.span, "unsafe functions cannot be used for tests")
.span_label(span, "`unsafe` because of this")
}
fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
- let has_sig = if let ast::ItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) = i.kind {
+ let has_sig = if let ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) = i.kind {
// N.B., inadequate check, but we're running
// well before resolve, can't get too deep.
sig.decl.inputs.len() == 1
let decl = ecx.fn_decl(vec![], ast::FnRetTy::Ty(main_ret_ty));
let sig = ast::FnSig { decl, header: ast::FnHeader::default(), span: sp };
- let def = ast::Defaultness::Final;
- let main = ast::ItemKind::Fn(Box::new(ast::FnKind(
- def,
+ let defaultness = ast::Defaultness::Final;
+ let main = ast::ItemKind::Fn(Box::new(ast::Fn {
+ defaultness,
sig,
- ast::Generics::default(),
- Some(main_body),
- )));
+ generics: ast::Generics::default(),
+ body: Some(main_body),
+ }));
// Honor the reexport_test_harness_main attribute
let main_id = match cx.reexport_test_harness_main {
use crate::builder::Builder;
use crate::context::CodegenCx;
use crate::llvm::{self, AttributePlace};
-use crate::llvm_util;
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
}
fn should_use_mutable_noalias(cx: &CodegenCx<'_, '_>) -> bool {
- // LLVM prior to version 12 has known miscompiles in the presence of
- // noalias attributes (see #54878). Only enable mutable noalias by
- // default for versions we believe to be safe.
- cx.tcx
- .sess
- .opts
- .debugging_opts
- .mutable_noalias
- .unwrap_or_else(|| llvm_util::get_version() >= (12, 0, 0))
+ // LLVM prior to version 12 had known miscompiles in the presence of
+ // noalias attributes (see #54878), but we don't support earlier
+ // versions at all anymore. We now enable mutable noalias by default.
+ cx.tcx.sess.opts.debugging_opts.mutable_noalias.unwrap_or(true)
}
impl ArgAttributesExt for ArgAttributes {
}
fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> {
- if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() {
+ if !self.fptoint_sat_broken_in_llvm() {
let src_ty = self.cx.val_ty(val);
let float_width = self.cx.float_width(src_ty);
let int_width = self.cx.int_width(dest_ty);
}
fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> {
- if llvm_util::get_version() >= (12, 0, 0) && !self.fptoint_sat_broken_in_llvm() {
+ if !self.fptoint_sat_broken_in_llvm() {
let src_ty = self.cx.val_ty(val);
let float_width = self.cx.float_width(src_ty);
let int_width = self.cx.int_width(dest_ty);
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
let mut target_data_layout = sess.target.data_layout.clone();
- if llvm_util::get_version() < (12, 0, 0) && sess.target.arch == "powerpc64" {
- target_data_layout = target_data_layout.replace("-v256:256:256-v512:512:512", "");
- }
if llvm_util::get_version() < (13, 0, 0) {
if sess.target.arch == "powerpc64" {
target_data_layout = target_data_layout.replace("-S128", "");
#[derive(Clone)]
pub struct LlvmCodegenBackend(());
+struct TimeTraceProfiler {
+ enabled: bool,
+}
+
+impl TimeTraceProfiler {
+ fn new(enabled: bool) -> Self {
+ if enabled {
+ unsafe { llvm::LLVMTimeTraceProfilerInitialize() }
+ }
+ TimeTraceProfiler { enabled }
+ }
+}
+
+impl Drop for TimeTraceProfiler {
+ fn drop(&mut self) {
+ if self.enabled {
+ unsafe { llvm::LLVMTimeTraceProfilerFinishThread() }
+ }
+ }
+}
+
impl ExtraBackendMethods for LlvmCodegenBackend {
fn new_metadata(&self, tcx: TyCtxt<'_>, mod_name: &str) -> ModuleLlvm {
ModuleLlvm::new_metadata(tcx, mod_name)
fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str> {
llvm_util::tune_cpu(sess)
}
+
+ fn spawn_thread<F, T>(time_trace: bool, f: F) -> std::thread::JoinHandle<T>
+ where
+ F: FnOnce() -> T,
+ F: Send + 'static,
+ T: Send + 'static,
+ {
+ std::thread::spawn(move || {
+ let _profiler = TimeTraceProfiler::new(time_trace);
+ f()
+ })
+ }
+
+ fn spawn_named_thread<F, T>(
+ time_trace: bool,
+ name: String,
+ f: F,
+ ) -> std::io::Result<std::thread::JoinHandle<T>>
+ where
+ F: FnOnce() -> T,
+ F: Send + 'static,
+ T: Send + 'static,
+ {
+ std::thread::Builder::new().name(name).spawn(move || {
+ let _profiler = TimeTraceProfiler::new(time_trace);
+ f()
+ })
+ }
}
impl WriteBackendMethods for LlvmCodegenBackend {
pub fn LLVMTimeTraceProfilerInitialize();
+ pub fn LLVMTimeTraceProfilerFinishThread();
+
pub fn LLVMTimeTraceProfilerFinish(FileName: *const c_char);
pub fn LLVMAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>);
}
if sess.opts.debugging_opts.llvm_time_trace {
- // time-trace is not thread safe and running it in parallel will cause seg faults.
- if !sess.opts.debugging_opts.no_parallel_llvm {
- bug!("`-Z llvm-time-trace` requires `-Z no-parallel-llvm")
- }
-
llvm::LLVMTimeTraceProfilerInitialize();
}
("aarch64", "dpb2") => vec!["ccdp"],
("aarch64", "frintts") => vec!["fptoint"],
("aarch64", "fcma") => vec!["complxnum"],
+ ("aarch64", "pmuv3") => vec!["perfmon"],
(_, s) => vec![s],
}
}
// -Ctarget-features
features.extend(sess.opts.cg.target_feature.split(',').flat_map(&filter));
- // FIXME: Move outline-atomics to target definition when earliest supported LLVM is 12.
- if get_version() >= (12, 0, 0) && sess.target.llvm_target.contains("aarch64-unknown-linux") {
- features.push("+outline-atomics".to_string());
- }
-
features
}
}
fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
- fn find_sanitizer_runtime(sess: &Session, filename: &String) -> PathBuf {
+ fn find_sanitizer_runtime(sess: &Session, filename: &str) -> PathBuf {
let session_tlib =
filesearch::make_target_lib_path(&sess.sysroot, sess.opts.target_triple.triple());
- let path = session_tlib.join(&filename);
+ let path = session_tlib.join(filename);
if path.exists() {
return session_tlib;
} else {
pub no_landing_pads: bool,
pub save_temps: bool,
pub fewer_names: bool,
+ pub time_trace: bool,
pub exported_symbols: Option<Arc<ExportedSymbols>>,
pub opts: Arc<config::Options>,
pub crate_types: Vec<CrateType>,
no_landing_pads: sess.panic_strategy() == PanicStrategy::Abort,
fewer_names: sess.fewer_names(),
save_temps: sess.opts.cg.save_temps,
+ time_trace: sess.opts.debugging_opts.llvm_time_trace,
opts: Arc::new(sess.opts.clone()),
prof: sess.prof.clone(),
exported_symbols,
// Each LLVM module is automatically sent back to the coordinator for LTO if
// necessary. There's already optimizations in place to avoid sending work
// back to the coordinator if LTO isn't requested.
- return thread::spawn(move || {
+ return B::spawn_thread(cgcx.time_trace, move || {
let mut worker_id_counter = 0;
let mut free_worker_ids = Vec::new();
let mut get_worker_id = |free_worker_ids: &mut Vec<usize>| {
pub struct WorkerFatalError;
fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>) {
- let builder = thread::Builder::new().name(work.short_description());
- builder
- .spawn(move || {
- // Set up a destructor which will fire off a message that we're done as
- // we exit.
- struct Bomb<B: ExtraBackendMethods> {
- coordinator_send: Sender<Box<dyn Any + Send>>,
- result: Option<Result<WorkItemResult<B>, FatalError>>,
- worker_id: usize,
- }
- impl<B: ExtraBackendMethods> Drop for Bomb<B> {
- fn drop(&mut self) {
- let worker_id = self.worker_id;
- let msg = match self.result.take() {
- Some(Ok(WorkItemResult::Compiled(m))) => {
- Message::Done::<B> { result: Ok(m), worker_id }
- }
- Some(Ok(WorkItemResult::NeedsLink(m))) => {
- Message::NeedsLink::<B> { module: m, worker_id }
- }
- Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
- Message::NeedsFatLTO::<B> { result: m, worker_id }
- }
- Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
- Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
- }
- Some(Err(FatalError)) => {
- Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
- }
- None => Message::Done::<B> { result: Err(None), worker_id },
- };
- drop(self.coordinator_send.send(Box::new(msg)));
- }
+ B::spawn_named_thread(cgcx.time_trace, work.short_description(), move || {
+ // Set up a destructor which will fire off a message that we're done as
+ // we exit.
+ struct Bomb<B: ExtraBackendMethods> {
+ coordinator_send: Sender<Box<dyn Any + Send>>,
+ result: Option<Result<WorkItemResult<B>, FatalError>>,
+ worker_id: usize,
+ }
+ impl<B: ExtraBackendMethods> Drop for Bomb<B> {
+ fn drop(&mut self) {
+ let worker_id = self.worker_id;
+ let msg = match self.result.take() {
+ Some(Ok(WorkItemResult::Compiled(m))) => {
+ Message::Done::<B> { result: Ok(m), worker_id }
+ }
+ Some(Ok(WorkItemResult::NeedsLink(m))) => {
+ Message::NeedsLink::<B> { module: m, worker_id }
+ }
+ Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
+ Message::NeedsFatLTO::<B> { result: m, worker_id }
+ }
+ Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
+ Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
+ }
+ Some(Err(FatalError)) => {
+ Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
+ }
+ None => Message::Done::<B> { result: Err(None), worker_id },
+ };
+ drop(self.coordinator_send.send(Box::new(msg)));
}
+ }
- let mut bomb = Bomb::<B> {
- coordinator_send: cgcx.coordinator_send.clone(),
- result: None,
- worker_id: cgcx.worker,
- };
+ let mut bomb = Bomb::<B> {
+ coordinator_send: cgcx.coordinator_send.clone(),
+ result: None,
+ worker_id: cgcx.worker,
+ };
- // Execute the work itself, and if it finishes successfully then flag
- // ourselves as a success as well.
- //
- // Note that we ignore any `FatalError` coming out of `execute_work_item`,
- // as a diagnostic was already sent off to the main thread - just
- // surface that there was an error in this worker.
- bomb.result = {
- let _prof_timer = work.start_profiling(&cgcx);
- Some(execute_work_item(&cgcx, work))
- };
- })
- .expect("failed to spawn thread");
+ // Execute the work itself, and if it finishes successfully then flag
+ // ourselves as a success as well.
+ //
+ // Note that we ignore any `FatalError` coming out of `execute_work_item`,
+ // as a diagnostic was already sent off to the main thread - just
+ // surface that there was an error in this worker.
+ bomb.result = {
+ let _prof_timer = work.start_profiling(&cgcx);
+ Some(execute_work_item(&cgcx, work))
+ };
+ })
+ .expect("failed to spawn thread");
}
enum SharedEmitterMessage {
// info for MSVC debugger. However, wrapping these types' names in a synthetic type
// causes the .natvis engine for WinDbg to fail to display their data, so we opt these
// types out to aid debugging in MSVC.
- let is_slice_or_str = match *inner_type.kind() {
- ty::Slice(_) | ty::Str => true,
- _ => false,
- };
+ let is_slice_or_str = matches!(*inner_type.kind(), ty::Slice(_) | ty::Str);
if !cpp_like_names {
output.push('&');
// FIXME(rcvalle): Add support for generalized identifiers.
// FIXME(rcvalle): Create distinct unnamed MDNodes for internal identifiers.
let typeid = typeid_for_fnabi(bx.tcx(), fn_abi);
- let typeid_metadata = bx.typeid_metadata(typeid.clone());
+ let typeid_metadata = bx.typeid_metadata(typeid);
// Test whether the function pointer is associated with the type identifier.
let cond = bx.type_test(fn_ptr, typeid_metadata);
// is associated with a type identifier).
if cx.tcx().sess.is_sanitizer_cfi_enabled() {
let typeid = typeid_for_fnabi(cx.tcx(), fn_abi);
- bx.type_metadata(llfn, typeid.clone());
+ bx.type_metadata(llfn, typeid);
}
}
let count = self.codegen_operand(&mut bx, count).immediate();
let pointee_layout = dst_val
.layout
- .pointee_info_at(&mut bx, rustc_target::abi::Size::ZERO)
+ .pointee_info_at(&bx, rustc_target::abi::Size::ZERO)
.expect("Expected pointer");
let bytes = bx.mul(count, bx.const_usize(pointee_layout.size.bytes()));
("thumb-mode", Some(sym::arm_target_feature)),
];
-// Commented features are not available in LLVM 10.0, or have since been renamed
const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
// FEAT_AdvSimd
("neon", Some(sym::aarch64_target_feature)),
// FEAT_DIT
("dit", Some(sym::aarch64_target_feature)),
// FEAT_FLAGM
- // ("flagm", Some(sym::aarch64_target_feature)),
+ ("flagm", Some(sym::aarch64_target_feature)),
// FEAT_SSBS
("ssbs", Some(sym::aarch64_target_feature)),
// FEAT_SB
("sb", Some(sym::aarch64_target_feature)),
// FEAT_PAUTH
- // ("pauth", Some(sym::aarch64_target_feature)),
+ ("pauth", Some(sym::aarch64_target_feature)),
// FEAT_DPB
("dpb", Some(sym::aarch64_target_feature)),
// FEAT_DPB2
// FEAT_I8MM
("i8mm", Some(sym::aarch64_target_feature)),
// FEAT_F32MM
- // ("f32mm", Some(sym::aarch64_target_feature)),
+ ("f32mm", Some(sym::aarch64_target_feature)),
// FEAT_F64MM
- // ("f64mm", Some(sym::aarch64_target_feature)),
+ ("f64mm", Some(sym::aarch64_target_feature)),
// FEAT_BF16
- // ("bf16", Some(sym::aarch64_target_feature)),
+ ("bf16", Some(sym::aarch64_target_feature)),
// FEAT_RAND
("rand", Some(sym::aarch64_target_feature)),
// FEAT_BTI
("sha3", Some(sym::aarch64_target_feature)),
// FEAT_SM3 & FEAT_SM4
("sm4", Some(sym::aarch64_target_feature)),
+ // FEAT_PAN
+ ("pan", Some(sym::aarch64_target_feature)),
+ // FEAT_LOR
+ ("lor", Some(sym::aarch64_target_feature)),
+ // FEAT_VHE
+ ("vh", Some(sym::aarch64_target_feature)),
+ // FEAT_PMUv3
+ ("pmuv3", Some(sym::aarch64_target_feature)),
+ // FEAT_SPE
+ ("spe", Some(sym::aarch64_target_feature)),
("v8.1a", Some(sym::aarch64_target_feature)),
("v8.2a", Some(sym::aarch64_target_feature)),
("v8.3a", Some(sym::aarch64_target_feature)),
("v8.4a", Some(sym::aarch64_target_feature)),
("v8.5a", Some(sym::aarch64_target_feature)),
- // ("v8.6a", Some(sym::aarch64_target_feature)),
- // ("v8.7a", Some(sym::aarch64_target_feature)),
+ ("v8.6a", Some(sym::aarch64_target_feature)),
+ ("v8.7a", Some(sym::aarch64_target_feature)),
];
const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
) -> TargetMachineFactoryFn<Self>;
fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str;
fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str>;
+
+ fn spawn_thread<F, T>(_time_trace: bool, f: F) -> std::thread::JoinHandle<T>
+ where
+ F: FnOnce() -> T,
+ F: Send + 'static,
+ T: Send + 'static,
+ {
+ std::thread::spawn(f)
+ }
+
+ fn spawn_named_thread<F, T>(
+ _time_trace: bool,
+ name: String,
+ f: F,
+ ) -> std::io::Result<std::thread::JoinHandle<T>>
+ where
+ F: FnOnce() -> T,
+ F: Send + 'static,
+ T: Send + 'static,
+ {
+ std::thread::Builder::new().name(name).spawn(f)
+ }
}
impl MachineStopType for ConstEvalErrKind {
fn is_hard_err(&self) -> bool {
- match self {
- Self::Panic { .. } => true,
- _ => false,
- }
+ matches!(self, Self::Panic { .. })
}
}
// If the function itself is not annotated with `const`, it may still be a `const fn`
// if it resides in a const trait impl.
is_parent_const_impl_raw(tcx, hir_id)
- } else if let hir::Node::Ctor(_) = node {
- true
} else {
- false
+ matches!(node, hir::Node::Ctor(_))
}
}
args: &[GenericArg<'tcx>],
) -> Result<Self::Path, Self::Error> {
self = print_prefix(self)?;
- let args = args.iter().cloned().filter(|arg| match arg.unpack() {
- GenericArgKind::Lifetime(_) => false,
- _ => true,
- });
+ let args =
+ args.iter().cloned().filter(|arg| !matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
if args.clone().next().is_some() {
self.generic_delimiters(|cx| cx.comma_sep(args))
} else {
// Figure out how to pass which arguments.
// The Rust ABI is special: ZST get skipped.
- let rust_abi = match caller_abi {
- Abi::Rust | Abi::RustCall => true,
- _ => false,
- };
+ let rust_abi = matches!(caller_abi, Abi::Rust | Abi::RustCall);
+
// We have two iterators: Where the arguments come from,
// and where they go to.
.body
.basic_blocks()
.iter_enumerated()
- .find(|(_, block)| match block.terminator().kind {
- TerminatorKind::Return => true,
- _ => false,
- })
+ .find(|(_, block)| matches!(block.terminator().kind, TerminatorKind::Return))
.map(|(bb, _)| bb);
let return_block = match return_block {
let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const);
selcx.select(&obligation)
});
- match implsrc {
- Ok(Some(ImplSource::ConstDrop(_)))
- | Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => false,
- _ => true,
- }
+ !matches!(
+ implsrc,
+ Ok(Some(
+ ImplSource::ConstDrop(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
+ ))
+ )
}
fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool {
}
}
- fn address_of_allows_mutation(&self, mt: mir::Mutability, place: mir::Place<'tcx>) -> bool {
- match mt {
- mir::Mutability::Mut => true,
- mir::Mutability::Not => self.shared_borrow_allows_mutation(place),
- }
+ fn address_of_allows_mutation(&self, _mt: mir::Mutability, _place: mir::Place<'tcx>) -> bool {
+ // Exact set of permissions granted by AddressOf is undecided. Conservatively assume that
+ // it might allow mutation until resolution of #56604.
+ true
}
fn ref_allows_mutation(&self, kind: mir::BorrowKind, place: mir::Place<'tcx>) -> bool {
}
}
+ /// `&` only allow mutation if the borrowed place is `!Freeze`.
+ ///
+ /// This assumes that it is UB to take the address of a struct field whose type is
+ /// `Freeze`, then use pointer arithmetic to derive a pointer to a *different* field of
+ /// that same struct whose type is `!Freeze`. If we decide that this is not UB, we will
+ /// have to check the type of the borrowed **local** instead of the borrowed **place**
+ /// below. See [rust-lang/unsafe-code-guidelines#134].
+ ///
+ /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool {
!place
.ty(self.ccx.body, self.ccx.tcx)
new_temp
}
- fn promote_candidate(
- mut self,
- candidate: Candidate,
- next_promoted_id: usize,
- ) -> Option<Body<'tcx>> {
+ fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Body<'tcx> {
let def = self.source.source.with_opt_param();
let mut rvalue = {
let promoted = &mut self.promoted;
let span = self.promoted.span;
self.assign(RETURN_PLACE, rvalue, span);
- Some(self.promoted)
+ self.promoted
}
}
keep_original: false,
};
- //FIXME(oli-obk): having a `maybe_push()` method on `IndexVec` might be nice
- if let Some(mut promoted) = promoter.promote_candidate(candidate, promotions.len()) {
- promoted.source.promoted = Some(promotions.next_index());
- promotions.push(promoted);
- }
+ let mut promoted = promoter.promote_candidate(candidate, promotions.len());
+ promoted.source.promoted = Some(promotions.next_index());
+ promotions.push(promoted);
}
// Insert each of `extra_statements` before its indicated location, which
#[track_caller]
pub fn borrow(&self) -> MappedReadGuard<'_, T> {
let borrow = self.value.borrow();
- if let None = &*borrow {
+ if borrow.is_none() {
panic!("attempted to read from stolen value: {}", std::any::type_name::<T>());
}
ReadGuard::map(borrow, |opt| opt.as_ref().unwrap())
E0783: include_str!("./error_codes/E0783.md"),
E0784: include_str!("./error_codes/E0784.md"),
E0785: include_str!("./error_codes/E0785.md"),
+E0786: include_str!("./error_codes/E0786.md"),
;
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard
-// E0019, merged into E0015
-// E0035, merged into E0087/E0089
-// E0036, merged into E0087/E0089
+// E0019, // merged into E0015
+// E0035, // merged into E0087/E0089
+// E0036, // merged into E0087/E0089
// E0068,
// E0085,
// E0086,
// E0134,
// E0135,
// E0141,
-// E0153, unused error code
-// E0157, unused error code
+// E0153, // unused error code
+// E0157, // unused error code
// E0159, // use of trait `{}` as struct constructor
// E0163, // merged into E0071
// E0167,
// between structures with the same definition
// E0385, // {} in an aliasable location
// E0402, // cannot use an outer type parameter in this context
-// E0406, merged into 420
-// E0410, merged into 408
-// E0413, merged into 530
-// E0414, merged into 530
-// E0417, merged into 532
-// E0418, merged into 532
-// E0419, merged into 531
-// E0420, merged into 532
-// E0421, merged into 531
-// E0427, merged into 530
+// E0406, // merged into 420
+// E0410, // merged into 408
+// E0413, // merged into 530
+// E0414, // merged into 530
+// E0417, // merged into 532
+// E0418, // merged into 532
+// E0419, // merged into 531
+// E0420, // merged into 532
+// E0421, // merged into 531
+// E0427, // merged into 530
// E0456, // plugin `..` is not available for triple `..`
E0457, // plugin `..` only found in rlib format, but must be available...
E0460, // found possibly newer version of crate `..`
E0461, // couldn't find crate `..` with expected target triple ..
E0462, // found staticlib `..` instead of rlib or dylib
E0465, // multiple .. candidates for `..` found
-// E0467, removed
-// E0470, removed
+// E0467, // removed
+// E0470, // removed
// E0471, // constant evaluation error (in pattern)
E0472, // llvm_asm! is unsupported on this target
// E0473, // dereference of reference outside its lifetime
E0490, // a value of type `..` is borrowed for too long
E0514, // metadata version mismatch
E0519, // local crate and dependency have same (crate-name, disambiguator)
- // two dependencies have same (crate-name, disambiguator) but different SVH
- E0523,
+ E0523, // two dependencies have same (crate-name, disambiguator) but different SVH
// E0526, // shuffle indices are not constant
// E0540, // multiple rustc_deprecated attributes
// E0548, // replaced with a generic attribute input check
E0711, // a feature has been declared with conflicting stability attributes
E0717, // rustc_promotable without stability attribute
// E0721, // `await` keyword
-// E0723, unstable feature in `const` context
+// E0723, // unstable feature in `const` context
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
--- /dev/null
+A metadata file was invalid.
+
+Erroneous code example:
+
+```ignore (needs extern files)
+use ::foo; // error: found invalid metadata files for crate `foo`
+```
+
+When loading crates, each crate must have a valid metadata file.
+Invalid files could be caused by filesystem corruption,
+an IO error while reading the file, or (rarely) a bug in the compiler itself.
+
+Consider deleting the file and recreating it,
+or reporting a bug against the compiler.
MAX_DIGITS
}
+// We replace some characters so the CLI output is always consistent and underlines aligned.
+const OUTPUT_REPLACEMENTS: &[(char, &str)] = &[
+ ('\t', " "), // We do our own tab replacement
+ ('\u{202A}', ""), // The following unicode text flow control characters are inconsistently
+ ('\u{202B}', ""), // supported accross CLIs and can cause confusion due to the bytes on disk
+ ('\u{202D}', ""), // not corresponding to the visible source code, so we replace them always.
+ ('\u{202E}', ""),
+ ('\u{2066}', ""),
+ ('\u{2067}', ""),
+ ('\u{2068}', ""),
+ ('\u{202C}', ""),
+ ('\u{2069}', ""),
+];
+
fn replace_tabs(str: &str) -> String {
- str.replace('\t', " ")
+ let mut s = str.to_string();
+ for (c, replacement) in OUTPUT_REPLACEMENTS {
+ s = s.replace(*c, replacement);
+ }
+ s
}
fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
(accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None),
/// Allows panicking during const eval (producing compile-time errors).
(accepted, const_panic, "1.57.0", Some(51999), None),
+ /// Lessens the requirements for structs to implement `Unsize`.
+ (accepted, relaxed_struct_unsize, "1.58.0", Some(81793), None),
// -------------------------------------------------------------------------
// feature-group-end: accepted features
}
}
+// See https://rustc-dev-guide.rust-lang.org/feature-gates.html#feature-gates for more
+// documentation about handling feature gates.
+//
// If you change this, please modify `src/doc/unstable-book` as well.
//
-// Don't ever remove anything from this list; move them to `removed.rs`.
+// Don't ever remove anything from this list; move them to `accepted.rs` if
+// accepted or `removed.rs` if removed.
//
// The version numbers here correspond to the version in which the current status
// was set. This is most important for knowing when a particular feature became
/// Allows `extern "C-cmse-nonsecure-call" fn()`.
(active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None),
- /// Lessens the requirements for structs to implement `Unsize`.
- (active, relaxed_struct_unsize, "1.51.0", Some(81793), None),
-
/// Allows associated types in inherent impls.
(incomplete, inherent_associated_types, "1.52.0", Some(8995), None),
/// not changed from prior instances of the same struct (RFC #2528)
(incomplete, type_changing_struct_update, "1.58.0", Some(86555), None),
+ /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
+ (active, doc_auto_cfg, "1.58.0", Some(43781), None),
+
+ /// Allows using `const` operands in inline assembly.
+ (active, asm_const, "1.58.0", Some(72016), None),
+
+ /// Allows using `sym` operands in inline assembly.
+ (active, asm_sym, "1.58.0", Some(72016), None),
+
+ /// Enables experimental inline assembly support for additional architectures.
+ (active, asm_experimental_arch, "1.58.0", Some(72016), None),
+
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
-use rustc_index::vec::IndexVec;
use std::fmt;
/// Uniquely identifies a node in the HIR of the current crate. It is
owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
local_id: ItemLocalId::from_u32(0),
};
-
-/// N.B. This collection is currently unused, but will be used by #72015 and future PRs.
-#[derive(Clone, Default, Debug, Encodable, Decodable)]
-pub struct HirIdVec<T> {
- map: IndexVec<LocalDefId, IndexVec<ItemLocalId, T>>,
-}
-
-impl<T> HirIdVec<T> {
- pub fn push_owner(&mut self, id: LocalDefId) {
- self.map.ensure_contains_elem(id, IndexVec::new);
- }
-
- pub fn push(&mut self, id: HirId, value: T) {
- if id.local_id == ItemLocalId::from_u32(0) {
- self.push_owner(id.owner);
- }
- let submap = &mut self.map[id.owner];
- let _ret_id = submap.push(value);
- debug_assert_eq!(_ret_id, id.local_id);
- }
-
- pub fn push_sparse(&mut self, id: HirId, value: T)
- where
- T: Default,
- {
- self.map.ensure_contains_elem(id.owner, IndexVec::new);
- let submap = &mut self.map[id.owner];
- let i = id.local_id.index();
- let len = submap.len();
- if i >= len {
- submap.extend(std::iter::repeat_with(T::default).take(i - len + 1));
- }
- submap[id.local_id] = value;
- }
-
- pub fn get(&self, id: HirId) -> Option<&T> {
- self.map.get(id.owner)?.get(id.local_id)
- }
-
- pub fn get_owner(&self, id: LocalDefId) -> &IndexVec<ItemLocalId, T> {
- &self.map[id]
- }
-
- pub fn iter(&self) -> impl Iterator<Item = &T> {
- self.map.iter().flat_map(|la| la.iter())
- }
-
- pub fn iter_enumerated(&self) -> impl Iterator<Item = (HirId, &T)> {
- self.map.iter_enumerated().flat_map(|(owner, la)| {
- la.iter_enumerated().map(move |(local_id, attr)| (HirId { owner, local_id }, attr))
- })
- }
-}
-
-impl<T> std::ops::Index<HirId> for HirIdVec<T> {
- type Output = T;
-
- fn index(&self, id: HirId) -> &T {
- &self.map[id.owner][id.local_id]
- }
-}
-
-impl<T> std::ops::IndexMut<HirId> for HirIdVec<T> {
- fn index_mut(&mut self, id: HirId) -> &mut T {
- &mut self.map[id.owner][id.local_id]
- }
-}
// in the sense that a crate is not required to have it defined to use it, but a final product
// is required to define it somewhere. Additionally, there are restrictions on crates that use
// a weak lang item, but do not have it defined.
- Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::None;
+ Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Exact(0);
PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None;
PanicStr, sym::panic_str, panic_str, Target::Fn, GenericRequirement::None;
ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
- PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::None;
+ PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0);
PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None;
PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None;
PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None;
let mut returned_async_output_error = false;
for &sp in values {
if sp.is_desugaring(DesugaringKind::Async) && !returned_async_output_error {
- if &[sp] != err.span.primary_spans() {
+ if [sp] != err.span.primary_spans() {
let mut span: MultiSpan = sp.into();
span.push_span_label(
sp,
use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::SubregionOrigin;
-use rustc_errors::{struct_span_err, ErrorReported};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
+use rustc_hir as hir;
+use rustc_hir::{GenericParamKind, Ty};
+use rustc_middle::ty::Region;
impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
/// Print the error message for lifetime errors when both the concerned regions are anonymous.
}
};
- let mut e = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch");
+ let mut err = struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch");
- e.span_label(span_1, main_label);
- e.span_label(span_2, String::new());
- e.span_label(span, span_label);
+ err.span_label(span_1, main_label);
+ err.span_label(span_2, String::new());
+ err.span_label(span, span_label);
+
+ self.suggest_adding_lifetime_params(sub, ty_sup, ty_sub, &mut err);
if let Some(t) = future_return_type {
let snip = self
(_, "") => None,
_ => Some(s),
})
- .unwrap_or("{unnamed_type}".to_string());
+ .unwrap_or_else(|| "{unnamed_type}".to_string());
- e.span_label(
+ err.span_label(
t.span,
&format!("this `async fn` implicitly returns an `impl Future<Output = {}>`", snip),
);
}
- e.emit();
+ err.emit();
Some(ErrorReported)
}
+
+ fn suggest_adding_lifetime_params(
+ &self,
+ sub: Region<'tcx>,
+ ty_sup: &Ty<'_>,
+ ty_sub: &Ty<'_>,
+ err: &mut DiagnosticBuilder<'_>,
+ ) {
+ if let (
+ hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. },
+ hir::Ty { kind: hir::TyKind::Rptr(lifetime_sup, _), .. },
+ ) = (ty_sub, ty_sup)
+ {
+ if lifetime_sub.name.is_elided() && lifetime_sup.name.is_elided() {
+ if let Some(anon_reg) = self.tcx().is_suitable_region(sub) {
+ let hir_id = self.tcx().hir().local_def_id_to_hir_id(anon_reg.def_id);
+ if let hir::Node::Item(&hir::Item {
+ kind: hir::ItemKind::Fn(_, ref generics, ..),
+ ..
+ }) = self.tcx().hir().get(hir_id)
+ {
+ let (suggestion_param_name, introduce_new) = generics
+ .params
+ .iter()
+ .find(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
+ .and_then(|p| self.tcx().sess.source_map().span_to_snippet(p.span).ok())
+ .map(|name| (name, false))
+ .unwrap_or_else(|| ("'a".to_string(), true));
+
+ let mut suggestions = vec![
+ if let hir::LifetimeName::Underscore = lifetime_sub.name {
+ (lifetime_sub.span, suggestion_param_name.clone())
+ } else {
+ (
+ lifetime_sub.span.shrink_to_hi(),
+ suggestion_param_name.clone() + " ",
+ )
+ },
+ if let hir::LifetimeName::Underscore = lifetime_sup.name {
+ (lifetime_sup.span, suggestion_param_name.clone())
+ } else {
+ (
+ lifetime_sup.span.shrink_to_hi(),
+ suggestion_param_name.clone() + " ",
+ )
+ },
+ ];
+
+ if introduce_new {
+ let new_param_suggestion = match &generics.params {
+ [] => (generics.span, format!("<{}>", suggestion_param_name)),
+ [first, ..] => (
+ first.span.shrink_to_lo(),
+ format!("{}, ", suggestion_param_name),
+ ),
+ };
+
+ suggestions.push(new_param_suggestion);
+ }
+
+ err.multipart_suggestion(
+ "consider introducing a named lifetime parameter",
+ suggestions,
+ Applicability::MaybeIncorrect,
+ );
+ err.note(
+ "each elided lifetime in input position becomes a distinct lifetime",
+ );
+ }
+ }
+ }
+ }
+ }
}
self.tainted_by_errors_flag.set(true)
}
- /// Process the region constraints and report any errors that
+ /// Process the region constraints and return any any errors that
/// result. After this, no more unification operations should be
/// done -- or the compiler will panic -- but it is legal to use
/// `resolve_vars_if_possible` as well as `fully_resolve`.
- pub fn resolve_regions_and_report_errors(
+ pub fn resolve_regions(
&self,
region_context: DefId,
outlives_env: &OutlivesEnvironment<'tcx>,
mode: RegionckMode,
- ) {
+ ) -> Vec<RegionResolutionError<'tcx>> {
let (var_infos, data) = {
let mut inner = self.inner.borrow_mut();
let inner = &mut *inner;
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
assert!(old_value.is_none());
+ errors
+ }
+
+ /// Process the region constraints and report any errors that
+ /// result. After this, no more unification operations should be
+ /// done -- or the compiler will panic -- but it is legal to use
+ /// `resolve_vars_if_possible` as well as `fully_resolve`.
+ pub fn resolve_regions_and_report_errors(
+ &self,
+ region_context: DefId,
+ outlives_env: &OutlivesEnvironment<'tcx>,
+ mode: RegionckMode,
+ ) {
+ let errors = self.resolve_regions(region_context, outlives_env, mode);
+
if !self.is_tainted_by_errors() {
// As a heuristic, just skip reporting region errors
// altogether if other errors have been reported while
use std::io::{self, BufWriter, Write};
use std::lazy::SyncLazy;
use std::marker::PhantomPinned;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::pin::Pin;
use std::rc::Rc;
use std::{env, fs, iter};
None
}
-fn output_contains_path(output_paths: &[PathBuf], input_path: &PathBuf) -> bool {
+fn output_contains_path(output_paths: &[PathBuf], input_path: &Path) -> bool {
let input_path = input_path.canonicalize().ok();
if input_path.is_none() {
return false;
check_output(output_paths, check)
}
-fn escape_dep_filename(filename: &String) -> String {
+fn escape_dep_filename(filename: &str) -> String {
// Apparently clang and gcc *only* escape spaces:
// https://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
filename.replace(" ", "\\ ")
fn visit_item_kind(&mut self, i: &mut ast::ItemKind) {
let is_const = match i {
ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true,
- ast::ItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => Self::is_sig_const(sig),
+ ast::ItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig),
_ => false,
};
self.run(is_const, |s| noop_visit_item_kind(i, s))
fn flat_map_trait_item(&mut self, i: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
let is_const = match i.kind {
ast::AssocItemKind::Const(..) => true,
- ast::AssocItemKind::Fn(box ast::FnKind(_, ref sig, _, _)) => Self::is_sig_const(sig),
+ ast::AssocItemKind::Fn(box ast::Fn { ref sig, .. }) => Self::is_sig_const(sig),
_ => false,
};
self.run(is_const, |s| noop_flat_map_assoc_item(i, s))
impl EscapeError {
/// Returns true for actual errors, as opposed to warnings.
pub fn is_fatal(&self) -> bool {
- match self {
- EscapeError::UnskippedWhitespaceWarning => false,
- EscapeError::MultipleSkippedLinesWarning => false,
- _ => true,
- }
+ !matches!(
+ self,
+ EscapeError::UnskippedWhitespaceWarning | EscapeError::MultipleSkippedLinesWarning
+ )
}
}
fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
match it.kind {
- ast::ItemKind::Trait(box ast::TraitKind(_, ast::Unsafe::Yes(_), ..)) => self
+ ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self
.report_unsafe(cx, it.span, |lint| {
lint.build("declaration of an `unsafe` trait").emit()
}),
- ast::ItemKind::Impl(box ast::ImplKind { unsafety: ast::Unsafe::Yes(_), .. }) => self
+ ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self
.report_unsafe(cx, it.span, |lint| {
lint.build("implementation of an `unsafe` trait").emit()
}),
// This is a hard error in future editions; avoid linting and erroring
return;
}
- if let ast::AssocItemKind::Fn(box FnKind(_, ref sig, _, _)) = it.kind {
+ if let ast::AssocItemKind::Fn(box Fn { ref sig, .. }) = it.kind {
for arg in sig.decl.inputs.iter() {
if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind {
if ident.name == kw::Empty {
false
}
- if let rustc_hir::ExprKind::Unary(ref un_op, ref expr_deref) = expr.kind {
- if let rustc_hir::UnOp::Deref = un_op {
- if is_null_ptr(cx, expr_deref) {
- cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
- let mut err = lint.build("dereferencing a null pointer");
- err.span_label(
- expr.span,
- "this code causes undefined behavior when executed",
- );
- err.emit();
- });
- }
+ if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind {
+ if is_null_ptr(cx, expr_deref) {
+ cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
+ let mut err = lint.build("dereferencing a null pointer");
+ err.span_label(expr.span, "this code causes undefined behavior when executed");
+ err.emit();
+ });
}
}
}
let snippet = template_snippet.as_str();
if let Some(pos) = snippet.find(needle) {
let end = pos
- + &snippet[pos..]
+ + snippet[pos..]
.find(|c| c == ':')
.unwrap_or(snippet[pos..].len() - 1);
let inner = InnerSpan::new(pos, end);
use crate::levels::{is_known_lint_tool, LintLevelsBuilder};
use crate::passes::{EarlyLintPassObject, LateLintPassObject};
+use ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync;
use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
use rustc_session::Session;
use rustc_span::lev_distance::find_best_match_for_name;
-use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
+use rustc_span::{symbol::Symbol, BytePos, MultiSpan, Span, DUMMY_SP};
use rustc_target::abi;
use tracing::debug;
// Now, set up surrounding context.
let sess = self.sess();
match diagnostic {
+ BuiltinLintDiagnostics::UnicodeTextFlow(span, content) => {
+ let spans: Vec<_> = content
+ .char_indices()
+ .filter_map(|(i, c)| {
+ TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
+ let lo = span.lo() + BytePos(2 + i as u32);
+ (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
+ })
+ })
+ .collect();
+ let (an, s) = match spans.len() {
+ 1 => ("an ", ""),
+ _ => ("", "s"),
+ };
+ db.span_label(span, &format!(
+ "this comment contains {}invisible unicode text flow control codepoint{}",
+ an,
+ s,
+ ));
+ for (c, span) in &spans {
+ db.span_label(*span, format!("{:?}", c));
+ }
+ db.note(
+ "these kind of unicode codepoints change the way text flows on \
+ applications that support them, but can cause confusion because they \
+ change the order of characters on the screen",
+ );
+ if !spans.is_empty() {
+ db.multipart_suggestion_with_style(
+ "if their presence wasn't intentional, you can remove them",
+ spans.into_iter().map(|(_, span)| (span, "".to_string())).collect(),
+ Applicability::MachineApplicable,
+ SuggestionStyle::HideCodeAlways,
+ );
+ }
+ },
BuiltinLintDiagnostics::Normal => (),
BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
let (sugg, app) = match sess.source_map().span_to_snippet(span) {
--- /dev/null
+use crate::{EarlyContext, EarlyLintPass, LintContext};
+use ast::util::unicode::{contains_text_flow_control_chars, TEXT_FLOW_CONTROL_CHARS};
+use rustc_ast as ast;
+use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_span::{BytePos, Span, Symbol};
+
+declare_lint! {
+ /// The `text_direction_codepoint_in_literal` lint detects Unicode codepoints that change the
+ /// visual representation of text on screen in a way that does not correspond to their on
+ /// memory representation.
+ ///
+ /// ### Explanation
+ ///
+ /// The unicode characters `\u{202A}`, `\u{202B}`, `\u{202D}`, `\u{202E}`, `\u{2066}`,
+ /// `\u{2067}`, `\u{2068}`, `\u{202C}` and `\u{2069}` make the flow of text on screen change
+ /// its direction on software that supports these codepoints. This makes the text "abc" display
+ /// as "cba" on screen. By leveraging software that supports these, people can write specially
+ /// crafted literals that make the surrounding code seem like it's performing one action, when
+ /// in reality it is performing another. Because of this, we proactively lint against their
+ /// presence to avoid surprises.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,compile_fail
+ /// #![deny(text_direction_codepoint_in_literal)]
+ /// fn main() {
+ /// println!("{:?}", '');
+ /// }
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ pub TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
+ Deny,
+ "detect special Unicode codepoints that affect the visual representation of text on screen, \
+ changing the direction in which text flows",
+}
+
+declare_lint_pass!(HiddenUnicodeCodepoints => [TEXT_DIRECTION_CODEPOINT_IN_LITERAL]);
+
+impl HiddenUnicodeCodepoints {
+ fn lint_text_direction_codepoint(
+ &self,
+ cx: &EarlyContext<'_>,
+ text: Symbol,
+ span: Span,
+ padding: u32,
+ point_at_inner_spans: bool,
+ label: &str,
+ ) {
+ // Obtain the `Span`s for each of the forbidden chars.
+ let spans: Vec<_> = text
+ .as_str()
+ .char_indices()
+ .filter_map(|(i, c)| {
+ TEXT_FLOW_CONTROL_CHARS.contains(&c).then(|| {
+ let lo = span.lo() + BytePos(i as u32 + padding);
+ (c, span.with_lo(lo).with_hi(lo + BytePos(c.len_utf8() as u32)))
+ })
+ })
+ .collect();
+
+ cx.struct_span_lint(TEXT_DIRECTION_CODEPOINT_IN_LITERAL, span, |lint| {
+ let mut err = lint.build(&format!(
+ "unicode codepoint changing visible direction of text present in {}",
+ label
+ ));
+ let (an, s) = match spans.len() {
+ 1 => ("an ", ""),
+ _ => ("", "s"),
+ };
+ err.span_label(
+ span,
+ &format!(
+ "this {} contains {}invisible unicode text flow control codepoint{}",
+ label, an, s,
+ ),
+ );
+ if point_at_inner_spans {
+ for (c, span) in &spans {
+ err.span_label(*span, format!("{:?}", c));
+ }
+ }
+ err.note(
+ "these kind of unicode codepoints change the way text flows on applications that \
+ support them, but can cause confusion because they change the order of \
+ characters on the screen",
+ );
+ if point_at_inner_spans && !spans.is_empty() {
+ err.multipart_suggestion_with_style(
+ "if their presence wasn't intentional, you can remove them",
+ spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
+ Applicability::MachineApplicable,
+ SuggestionStyle::HideCodeAlways,
+ );
+ err.multipart_suggestion(
+ "if you want to keep them but make them visible in your source code, you can \
+ escape them",
+ spans
+ .into_iter()
+ .map(|(c, span)| {
+ let c = format!("{:?}", c);
+ (span, c[1..c.len() - 1].to_string())
+ })
+ .collect(),
+ Applicability::MachineApplicable,
+ );
+ } else {
+ // FIXME: in other suggestions we've reversed the inner spans of doc comments. We
+ // should do the same here to provide the same good suggestions as we do for
+ // literals above.
+ err.note("if their presence wasn't intentional, you can remove them");
+ err.note(&format!(
+ "if you want to keep them but make them visible in your source code, you can \
+ escape them: {}",
+ spans
+ .into_iter()
+ .map(|(c, _)| { format!("{:?}", c) })
+ .collect::<Vec<String>>()
+ .join(", "),
+ ));
+ }
+ err.emit();
+ });
+ }
+}
+impl EarlyLintPass for HiddenUnicodeCodepoints {
+ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
+ if let ast::AttrKind::DocComment(_, comment) = attr.kind {
+ if contains_text_flow_control_chars(&comment.as_str()) {
+ self.lint_text_direction_codepoint(cx, comment, attr.span, 0, false, "doc comment");
+ }
+ }
+ }
+
+ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
+ // byte strings are already handled well enough by `EscapeError::NonAsciiCharInByteString`
+ let (text, span, padding) = match &expr.kind {
+ ast::ExprKind::Lit(ast::Lit { token, kind, span }) => {
+ let text = token.symbol;
+ if !contains_text_flow_control_chars(&text.as_str()) {
+ return;
+ }
+ let padding = match kind {
+ // account for `"` or `'`
+ ast::LitKind::Str(_, ast::StrStyle::Cooked) | ast::LitKind::Char(_) => 1,
+ // account for `r###"`
+ ast::LitKind::Str(_, ast::StrStyle::Raw(val)) => *val as u32 + 2,
+ _ => return,
+ };
+ (text, span, padding)
+ }
+ _ => return,
+ };
+ self.lint_text_direction_codepoint(cx, text, *span, padding, true, "literal");
+ }
+}
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx>) {
match &ty.kind {
- TyKind::Path(qpath) => {
- if let QPath::Resolved(_, path) = qpath {
- if let Some(last) = path.segments.iter().last() {
- if lint_ty_kind_usage(cx, last) {
- cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
- lint.build("usage of `ty::TyKind`")
- .help("try using `Ty` instead")
- .emit();
- })
- } else {
- if ty.span.from_expansion() {
- return;
- }
- if let Some(t) = is_ty_or_ty_ctxt(cx, ty) {
- if path.segments.len() > 1 {
- cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| {
- lint.build(&format!("usage of qualified `ty::{}`", t))
- .span_suggestion(
- path.span,
- "try using it unqualified",
- t,
- // The import probably needs to be changed
- Applicability::MaybeIncorrect,
- )
- .emit();
- })
- }
+ TyKind::Path(QPath::Resolved(_, path)) => {
+ if let Some(last) = path.segments.iter().last() {
+ if lint_ty_kind_usage(cx, last) {
+ cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
+ lint.build("usage of `ty::TyKind`")
+ .help("try using `Ty` instead")
+ .emit();
+ })
+ } else {
+ if ty.span.from_expansion() {
+ return;
+ }
+ if let Some(t) = is_ty_or_ty_ctxt(cx, ty) {
+ if path.segments.len() > 1 {
+ cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| {
+ lint.build(&format!("usage of qualified `ty::{}`", t))
+ .span_suggestion(
+ path.span,
+ "try using it unqualified",
+ t,
+ // The import probably needs to be changed
+ Applicability::MaybeIncorrect,
+ )
+ .emit();
+ })
}
}
}
}
fn is_ty_or_ty_ctxt(cx: &LateContext<'_>, ty: &Ty<'_>) -> Option<String> {
- if let TyKind::Path(qpath) = &ty.kind {
- if let QPath::Resolved(_, path) = qpath {
- match path.res {
- Res::Def(_, def_id) => {
- if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(def_id)
- {
- return Some(format!(
- "{}{}",
- name,
- gen_args(path.segments.last().unwrap())
- ));
- }
+ if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind {
+ match path.res {
+ Res::Def(_, def_id) => {
+ if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(def_id) {
+ return Some(format!("{}{}", name, gen_args(path.segments.last().unwrap())));
}
- // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
- Res::SelfTy(None, Some((did, _))) => {
- if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
- if let Some(name @ (sym::Ty | sym::TyCtxt)) =
- cx.tcx.get_diagnostic_name(adt.did)
- {
- // NOTE: This path is currently unreachable as `Ty<'tcx>` is
- // defined as a type alias meaning that `impl<'tcx> Ty<'tcx>`
- // is not actually allowed.
- //
- // I(@lcnr) still kept this branch in so we don't miss this
- // if we ever change it in the future.
- return Some(format!("{}<{}>", name, substs[0]));
- }
+ }
+ // Only lint on `&Ty` and `&TyCtxt` if it is used outside of a trait.
+ Res::SelfTy(None, Some((did, _))) => {
+ if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
+ if let Some(name @ (sym::Ty | sym::TyCtxt)) =
+ cx.tcx.get_diagnostic_name(adt.did)
+ {
+ // NOTE: This path is currently unreachable as `Ty<'tcx>` is
+ // defined as a type alias meaning that `impl<'tcx> Ty<'tcx>`
+ // is not actually allowed.
+ //
+ // I(@lcnr) still kept this branch in so we don't miss this
+ // if we ever change it in the future.
+ return Some(format!("{}<{}>", name, substs[0]));
}
}
- _ => (),
}
+ _ => (),
}
}
impl EarlyLintPass for LintPassImpl {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
- if let ast::ItemKind::Impl(box ast::ImplKind { of_trait: Some(lint_pass), .. }) = &item.kind
- {
+ if let ast::ItemKind::Impl(box ast::Impl { of_trait: Some(lint_pass), .. }) = &item.kind {
if let Some(last) = lint_pass.path.segments.last() {
if last.ident.name == sym::LintPass {
let expn_data = lint_pass.path.span.ctxt().outer_expn_data();
mod context;
mod early;
mod enum_intrinsics_non_enums;
+pub mod hidden_unicode_codepoints;
mod internal;
mod late;
mod levels;
use array_into_iter::ArrayIntoIter;
use builtin::*;
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
+use hidden_unicode_codepoints::*;
use internal::*;
use methods::*;
use non_ascii_idents::*;
DeprecatedAttr: DeprecatedAttr::new(),
WhileTrue: WhileTrue,
NonAsciiIdents: NonAsciiIdents,
+ HiddenUnicodeCodepoints: HiddenUnicodeCodepoints,
IncompleteFeatures: IncompleteFeatures,
RedundantSemicolons: RedundantSemicolons,
UnusedDocComment: UnusedDocComment,
UNUSED_LABELS,
UNUSED_PARENS,
UNUSED_BRACES,
- MUST_NOT_SUSPEND,
REDUNDANT_SEMICOLONS
);
///
/// ```rust
/// #![feature(must_not_suspend)]
+ /// #![warn(must_not_suspend)]
///
/// #[must_not_suspend]
/// struct SyncThing {}
/// `MutexGuard`'s)
///
pub MUST_NOT_SUSPEND,
- Warn,
+ Allow,
"use of a `#[must_not_suspend]` value across a yield point",
+ @feature_gate = rustc_span::symbol::sym::must_not_suspend;
}
declare_lint! {
BREAK_WITH_LABEL_AND_LOOP,
UNUSED_ATTRIBUTES,
NON_EXHAUSTIVE_OMITTED_PATTERNS,
+ TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
DEREF_INTO_DYN_SUPERTRAIT,
]
}
@feature_gate = sym::non_exhaustive_omitted_patterns_lint;
}
+declare_lint! {
+ /// The `text_direction_codepoint_in_comment` lint detects Unicode codepoints in comments that
+ /// change the visual representation of text on screen in a way that does not correspond to
+ /// their on memory representation.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,compile_fail
+ /// #![deny(text_direction_codepoint_in_comment)]
+ /// fn main() {
+ /// println!("{:?}"); // '');
+ /// }
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// Unicode allows changing the visual flow of text on screen in order to support scripts that
+ /// are written right-to-left, but a specially crafted comment can make code that will be
+ /// compiled appear to be part of a comment, depending on the software used to read the code.
+ /// To avoid potential problems or confusion, such as in CVE-2021-42574, by default we deny
+ /// their use.
+ pub TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
+ Deny,
+ "invisible directionality-changing codepoints in comment"
+}
+
declare_lint! {
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
/// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
TrailingMacro(bool, Ident),
BreakWithLabelAndLoop(Span),
NamedAsmLabel(String),
+ UnicodeTextFlow(Span, String),
}
/// Lints that are buffered up early on in the `Session` before the
/* ProcName */ "rustc");
}
+extern "C" void LLVMTimeTraceProfilerFinishThread() {
+ timeTraceProfilerFinishThread();
+}
+
extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
StringRef FN(FileName);
std::error_code EC;
}
if meta.path().is_ident("project") {
if let Meta::List(list) = meta {
- if let Some(nested) = list.nested.iter().next() {
- if let NestedMeta::Meta(meta) = nested {
- attrs.project = meta.path().get_ident().cloned();
- any_attr = true;
- }
+ if let Some(NestedMeta::Meta(meta)) = list.nested.iter().next() {
+ attrs.project = meta.path().get_ident().cloned();
+ any_attr = true;
}
}
}
use proc_macro::bridge::client::ProcMacro;
use std::collections::BTreeMap;
+use std::ops::Fn;
use std::path::Path;
use std::{cmp, env};
use tracing::{debug, info};
use std::io::{Read, Result as IoResult, Write};
use std::path::{Path, PathBuf};
use std::{cmp, fmt, fs};
-use tracing::{debug, info, warn};
+use tracing::{debug, info};
#[derive(Clone)]
crate struct CrateLocator<'a> {
self.crate_rejections.via_kind.clear();
self.crate_rejections.via_version.clear();
self.crate_rejections.via_filename.clear();
+ self.crate_rejections.via_invalid.clear();
}
crate fn maybe_load_library_crate(&mut self) -> Result<Option<Library>, CrateError> {
continue;
}
}
- Err(err) => {
- warn!("no metadata found: {}", err);
+ Err(MetadataError::LoadFailure(err)) => {
+ info!("no metadata found: {}", err);
+ // The file was present and created by the same compiler version, but we
+ // couldn't load it for some reason. Give a hard error instead of silently
+ // ignoring it, but only if we would have given an error anyway.
+ self.crate_rejections
+ .via_invalid
+ .push(CrateMismatch { path: lib, got: err });
+ continue;
+ }
+ Err(err @ MetadataError::NotPresent(_)) => {
+ info!("no metadata found: {}", err);
continue;
}
};
fn get_metadata_section(
target: &Target,
flavor: CrateFlavor,
- filename: &Path,
+ filename: &'p Path,
loader: &dyn MetadataLoader,
-) -> Result<MetadataBlob, String> {
+) -> Result<MetadataBlob, MetadataError<'p>> {
if !filename.exists() {
- return Err(format!("no such file: '{}'", filename.display()));
+ return Err(MetadataError::NotPresent(filename));
}
let raw_bytes: MetadataRef = match flavor {
- CrateFlavor::Rlib => loader.get_rlib_metadata(target, filename)?,
+ CrateFlavor::Rlib => {
+ loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)?
+ }
CrateFlavor::Dylib => {
- let buf = loader.get_dylib_metadata(target, filename)?;
+ let buf =
+ loader.get_dylib_metadata(target, filename).map_err(MetadataError::LoadFailure)?;
// The header is uncompressed
let header_len = METADATA_HEADER.len();
debug!("checking {} bytes of metadata-version stamp", header_len);
let header = &buf[..cmp::min(header_len, buf.len())];
if header != METADATA_HEADER {
- return Err(format!(
- "incompatible metadata version found: '{}'",
+ return Err(MetadataError::LoadFailure(format!(
+ "invalid metadata version found: {}",
filename.display()
- ));
+ )));
}
// Header is okay -> inflate the actual metadata
match FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated) {
Ok(_) => rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()),
Err(_) => {
- return Err(format!("failed to decompress metadata: {}", filename.display()));
+ return Err(MetadataError::LoadFailure(format!(
+ "failed to decompress metadata: {}",
+ filename.display()
+ )));
}
}
}
CrateFlavor::Rmeta => {
// mmap the file, because only a small fraction of it is read.
- let file = std::fs::File::open(filename)
- .map_err(|_| format!("failed to open rmeta metadata: '{}'", filename.display()))?;
+ let file = std::fs::File::open(filename).map_err(|_| {
+ MetadataError::LoadFailure(format!(
+ "failed to open rmeta metadata: '{}'",
+ filename.display()
+ ))
+ })?;
let mmap = unsafe { Mmap::map(file) };
- let mmap = mmap
- .map_err(|_| format!("failed to mmap rmeta metadata: '{}'", filename.display()))?;
+ let mmap = mmap.map_err(|_| {
+ MetadataError::LoadFailure(format!(
+ "failed to mmap rmeta metadata: '{}'",
+ filename.display()
+ ))
+ })?;
rustc_erase_owner!(OwningRef::new(mmap).map_owner_box())
}
if blob.is_compatible() {
Ok(blob)
} else {
- Err(format!("incompatible metadata version found: '{}'", filename.display()))
+ Err(MetadataError::LoadFailure(format!(
+ "invalid metadata version found: {}",
+ filename.display()
+ )))
}
}
via_kind: Vec<CrateMismatch>,
via_version: Vec<CrateMismatch>,
via_filename: Vec<CrateMismatch>,
+ via_invalid: Vec<CrateMismatch>,
}
/// Candidate rejection reasons collected during crate search.
NonDylibPlugin(Symbol),
}
+enum MetadataError<'a> {
+ /// The file was missing.
+ NotPresent(&'a Path),
+ /// The file was present and invalid.
+ LoadFailure(String),
+}
+
+impl fmt::Display for MetadataError<'_> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ MetadataError::NotPresent(filename) => {
+ f.write_str(&format!("no such file: '{}'", filename.display()))
+ }
+ MetadataError::LoadFailure(msg) => f.write_str(msg),
+ }
+ }
+}
+
impl CrateError {
crate fn report(self, sess: &Session, span: Span, missing_core: bool) -> ! {
let mut err = match self {
}
err.note(&msg);
err
+ } else if !locator.crate_rejections.via_invalid.is_empty() {
+ let mut err = struct_span_err!(
+ sess,
+ span,
+ E0786,
+ "found invalid metadata files for crate `{}`{}",
+ crate_name,
+ add,
+ );
+ for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid {
+ err.note(&got);
+ }
+ err
} else {
let mut err = struct_span_err!(
sess,
.libs
.iter()
.filter_map(|lib| lib.name.as_ref())
- .any(|n| &n.as_str() == &lib.name);
+ .any(|n| n.as_str() == lib.name);
if new_name.is_empty() {
self.tcx.sess.err(&format!(
"an empty renaming target was specified for library `{}`",
/// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors,
/// so this method lets us detect them and `bug!` on unexpected errors.
pub fn formatted_string(&self) -> bool {
- match self {
+ matches!(
+ self,
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
- | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. })
- | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) => true,
- _ => false,
- }
+ | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. })
+ | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
+ )
}
/// Should this error be reported as a hard error, preventing compilation, or a soft error,
mut self,
mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection,
) -> Self {
- self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
+ self.contents = self.contents.into_iter().map(|(proj, span)| (f(proj), span)).collect();
self
}
for statement in statements {
let source_range = source_range_no_file(tcx, &statement.source_info.span);
text.push(format!(
- "\n{}{}: {}: {}",
+ "\n{}{}: {}: {:?}",
TOOLTIP_INDENT,
source_range,
statement_kind_name(&statement),
- format!("{:?}", statement)
+ statement
));
}
if let Some(term) = terminator {
// LLVM's definition of `noalias` is based solely on memory
// dependencies rather than pointer equality
//
- // Due to miscompiles in LLVM < 12, we apply a separate NoAliasMutRef attribute
- // for UniqueBorrowed arguments, so that the codegen backend can decide
- // whether or not to actually emit the attribute.
+ // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
+ // for UniqueBorrowed arguments, so that the codegen backend can decide whether
+ // or not to actually emit the attribute. It can also be controlled with the
+ // `-Zmutable-noalias` debugging option.
let no_alias = match kind {
PointerKind::Shared | PointerKind::UniqueBorrowed => false,
PointerKind::UniqueOwned => true,
p!(print_def_path(did, substs));
if !substs.as_closure().is_valid() {
p!(" closure_substs=(unavailable)");
+ p!(write(" substs={:?}", substs));
} else {
p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
p!(
})
.enumerate()
.map(|(i, r)| match r {
- Err(TypeError::Sorts(exp_found)) => Err(TypeError::ArgumentSorts(exp_found, i)),
- Err(TypeError::Mutability) => Err(TypeError::ArgumentMutability(i)),
+ Err(TypeError::Sorts(exp_found) | TypeError::ArgumentSorts(exp_found, _)) => {
+ Err(TypeError::ArgumentSorts(exp_found, i))
+ }
+ Err(TypeError::Mutability | TypeError::ArgumentMutability(_)) => {
+ Err(TypeError::ArgumentMutability(i))
+ }
r => r,
});
Ok(ty::FnSig {
use crate::{AnalysisDomain, GenKill, GenKillAnalysis};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
-use rustc_middle::ty::{ParamEnv, TyCtxt};
-use rustc_span::DUMMY_SP;
-
-pub type MaybeMutBorrowedLocals<'mir, 'tcx> = MaybeBorrowedLocals<MutBorrow<'mir, 'tcx>>;
/// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points
/// to a given local.
///
-/// The `K` parameter determines what kind of borrows are tracked. By default,
-/// `MaybeBorrowedLocals` looks for *any* borrow of a local. If you are only interested in borrows
-/// that might allow mutation, use the `MaybeMutBorrowedLocals` type alias instead.
-///
/// At present, this is used as a very limited form of alias analysis. For example,
/// `MaybeBorrowedLocals` is used to compute which locals are live during a yield expression for
-/// immovable generators. `MaybeMutBorrowedLocals` is used during const checking to prove that a
-/// local has not been mutated via indirect assignment (e.g., `*p = 42`), the side-effects of a
-/// function call or inline assembly.
-pub struct MaybeBorrowedLocals<K = AnyBorrow> {
- kind: K,
+/// immovable generators.
+pub struct MaybeBorrowedLocals {
ignore_borrow_on_drop: bool,
}
/// A dataflow analysis that records whether a pointer or reference exists that may alias the
/// given local.
pub fn all_borrows() -> Self {
- MaybeBorrowedLocals { kind: AnyBorrow, ignore_borrow_on_drop: false }
- }
-}
-
-impl MaybeMutBorrowedLocals<'mir, 'tcx> {
- /// A dataflow analysis that records whether a pointer or reference exists that may *mutably*
- /// alias the given local.
- ///
- /// This includes `&mut` and pointers derived from an `&mut`, as well as shared borrows of
- /// types with interior mutability.
- pub fn mut_borrows_only(
- tcx: TyCtxt<'tcx>,
- body: &'mir mir::Body<'tcx>,
- param_env: ParamEnv<'tcx>,
- ) -> Self {
- MaybeBorrowedLocals {
- kind: MutBorrow { body, tcx, param_env },
- ignore_borrow_on_drop: false,
- }
+ MaybeBorrowedLocals { ignore_borrow_on_drop: false }
}
}
-impl<K> MaybeBorrowedLocals<K> {
+impl MaybeBorrowedLocals {
/// During dataflow analysis, ignore the borrow that may occur when a place is dropped.
///
/// Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut self` as a
MaybeBorrowedLocals { ignore_borrow_on_drop: true, ..self }
}
- fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T, K> {
- TransferFunction {
- kind: &self.kind,
- trans,
- ignore_borrow_on_drop: self.ignore_borrow_on_drop,
- }
+ fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T> {
+ TransferFunction { trans, ignore_borrow_on_drop: self.ignore_borrow_on_drop }
}
}
-impl<K> AnalysisDomain<'tcx> for MaybeBorrowedLocals<K>
-where
- K: BorrowAnalysisKind<'tcx>,
-{
+impl AnalysisDomain<'tcx> for MaybeBorrowedLocals {
type Domain = BitSet<Local>;
- const NAME: &'static str = K::ANALYSIS_NAME;
+ const NAME: &'static str = "maybe_borrowed_locals";
fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
// bottom = unborrowed
}
}
-impl<K> GenKillAnalysis<'tcx> for MaybeBorrowedLocals<K>
-where
- K: BorrowAnalysisKind<'tcx>,
-{
+impl GenKillAnalysis<'tcx> for MaybeBorrowedLocals {
type Idx = Local;
fn statement_effect(
}
/// A `Visitor` that defines the transfer function for `MaybeBorrowedLocals`.
-struct TransferFunction<'a, T, K> {
+struct TransferFunction<'a, T> {
trans: &'a mut T,
- kind: &'a K,
ignore_borrow_on_drop: bool,
}
-impl<T, K> Visitor<'tcx> for TransferFunction<'a, T, K>
+impl<T> Visitor<'tcx> for TransferFunction<'a, T>
where
T: GenKill<Local>,
- K: BorrowAnalysisKind<'tcx>,
{
fn visit_statement(&mut self, stmt: &Statement<'tcx>, location: Location) {
self.super_statement(stmt, location);
self.super_rvalue(rvalue, location);
match rvalue {
- mir::Rvalue::AddressOf(mt, borrowed_place) => {
- if !borrowed_place.is_indirect() && self.kind.in_address_of(*mt, *borrowed_place) {
+ mir::Rvalue::AddressOf(_mt, borrowed_place) => {
+ if !borrowed_place.is_indirect() {
self.trans.gen(borrowed_place.local);
}
}
- mir::Rvalue::Ref(_, kind, borrowed_place) => {
- if !borrowed_place.is_indirect() && self.kind.in_ref(*kind, *borrowed_place) {
+ mir::Rvalue::Ref(_, _kind, borrowed_place) => {
+ if !borrowed_place.is_indirect() {
self.trans.gen(borrowed_place.local);
}
}
}
}
}
-
-pub struct AnyBorrow;
-
-pub struct MutBorrow<'mir, 'tcx> {
- tcx: TyCtxt<'tcx>,
- body: &'mir Body<'tcx>,
- param_env: ParamEnv<'tcx>,
-}
-
-impl MutBorrow<'mir, 'tcx> {
- /// `&` and `&raw` only allow mutation if the borrowed place is `!Freeze`.
- ///
- /// This assumes that it is UB to take the address of a struct field whose type is
- /// `Freeze`, then use pointer arithmetic to derive a pointer to a *different* field of
- /// that same struct whose type is `!Freeze`. If we decide that this is not UB, we will
- /// have to check the type of the borrowed **local** instead of the borrowed **place**
- /// below. See [rust-lang/unsafe-code-guidelines#134].
- ///
- /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
- fn shared_borrow_allows_mutation(&self, place: Place<'tcx>) -> bool {
- !place.ty(self.body, self.tcx).ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env)
- }
-}
-
-pub trait BorrowAnalysisKind<'tcx> {
- const ANALYSIS_NAME: &'static str;
-
- fn in_address_of(&self, mt: Mutability, place: Place<'tcx>) -> bool;
- fn in_ref(&self, kind: mir::BorrowKind, place: Place<'tcx>) -> bool;
-}
-
-impl BorrowAnalysisKind<'tcx> for AnyBorrow {
- const ANALYSIS_NAME: &'static str = "maybe_borrowed_locals";
-
- fn in_ref(&self, _: mir::BorrowKind, _: Place<'_>) -> bool {
- true
- }
- fn in_address_of(&self, _: Mutability, _: Place<'_>) -> bool {
- true
- }
-}
-
-impl BorrowAnalysisKind<'tcx> for MutBorrow<'mir, 'tcx> {
- const ANALYSIS_NAME: &'static str = "maybe_mut_borrowed_locals";
-
- fn in_ref(&self, kind: mir::BorrowKind, place: Place<'tcx>) -> bool {
- match kind {
- mir::BorrowKind::Mut { .. } => true,
- mir::BorrowKind::Shared | mir::BorrowKind::Shallow | mir::BorrowKind::Unique => {
- self.shared_borrow_allows_mutation(place)
- }
- }
- }
-
- fn in_address_of(&self, mt: Mutability, place: Place<'tcx>) -> bool {
- match mt {
- Mutability::Mut => true,
- Mutability::Not => self.shared_borrow_allows_mutation(place),
- }
- }
-}
mod liveness;
mod storage_liveness;
-pub use self::borrowed_locals::{MaybeBorrowedLocals, MaybeMutBorrowedLocals};
+pub use self::borrowed_locals::MaybeBorrowedLocals;
pub use self::init_locals::MaybeInitializedLocals;
pub use self::liveness::MaybeLiveLocals;
pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageLive};
use rustc_middle::ty::{self, Ty, TyCtxt};
use crate::impls::{
- DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeMutBorrowedLocals,
- MaybeUninitializedPlaces,
+ DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeUninitializedPlaces,
};
use crate::move_paths::{HasMoveData, MoveData};
use crate::move_paths::{LookupResult, MovePathIndex};
sanity_check_via_rustc_peek(tcx, body, &attributes, &flow_def_inits);
}
- if has_rustc_mir_with(sess, &attributes, sym::rustc_peek_indirectly_mutable).is_some() {
- let flow_mut_borrowed = MaybeMutBorrowedLocals::mut_borrows_only(tcx, body, param_env)
- .into_engine(tcx, body)
- .iterate_to_fixpoint();
-
- sanity_check_via_rustc_peek(tcx, body, &attributes, &flow_mut_borrowed);
- }
-
if has_rustc_mir_with(sess, &attributes, sym::rustc_peek_liveness).is_some() {
let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint();
}
}
-impl<'tcx> RustcPeekAt<'tcx> for MaybeMutBorrowedLocals<'_, 'tcx> {
- fn peek_at(
- &self,
- tcx: TyCtxt<'tcx>,
- place: mir::Place<'tcx>,
- flow_state: &BitSet<Local>,
- call: PeekCall,
- ) {
- info!(?place, "peek_at");
- let Some(local) = place.as_local() else {
- tcx.sess.span_err(call.span, "rustc_peek: argument was not a local");
- return;
- };
-
- if !flow_state.contains(local) {
- tcx.sess.span_err(call.span, "rustc_peek: bit not set");
- }
- }
-}
-
impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals {
fn peek_at(
&self,
// Non-code expressions are injected into the coverage map, without generating executable code.
fn inject_intermediate_expression(mir_body: &mut mir::Body<'tcx>, expression: CoverageKind) {
- debug_assert!(if let CoverageKind::Expression { .. } = expression { true } else { false });
+ debug_assert!(matches!(expression, CoverageKind::Expression { .. }));
debug!(" injecting non-code expression {:?}", expression);
let inject_in_bb = mir::START_BLOCK;
let data = &mut mir_body[inject_in_bb];
stmt_index: usize,
) -> Self {
let is_closure = match statement.kind {
- StatementKind::Assign(box (_, Rvalue::Aggregate(box ref kind, _))) => match kind {
- AggregateKind::Closure(_, _) | AggregateKind::Generator(_, _, _) => true,
- _ => false,
- },
+ StatementKind::Assign(box (_, Rvalue::Aggregate(box ref kind, _))) => {
+ matches!(kind, AggregateKind::Closure(_, _) | AggregateKind::Generator(_, _, _))
+ }
_ => false,
};
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// This pass must run before inlining, since we insert callee bodies in RevealAll mode.
// Do not apply this transformation to generators.
- if (tcx.sess.mir_opt_level() >= 3 || !super::inline::is_enabled(tcx))
+ if (tcx.sess.mir_opt_level() >= 3 || super::inline::is_enabled(tcx))
&& body.generator.is_none()
{
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
// This is a temporary solution that handles possibly diverging asm statements.
// Accompanying testcases: mir-opt/unreachable_asm.rs and mir-opt/unreachable_asm_2.rs
let asm_stmt_in_block = || {
- bb_data.statements.iter().any(|stmt: &Statement<'_>| match stmt.kind {
- StatementKind::LlvmInlineAsm(..) => true,
- _ => false,
+ bb_data.statements.iter().any(|stmt: &Statement<'_>| {
+ matches!(stmt.kind, StatementKind::LlvmInlineAsm(..))
})
};
}
}
}
+ mir::TerminatorKind::Assert { ref msg, .. } => {
+ let lang_item = match msg {
+ mir::AssertKind::BoundsCheck { .. } => LangItem::PanicBoundsCheck,
+ _ => LangItem::Panic,
+ };
+ let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, Some(source)));
+ if should_codegen_locally(tcx, &instance) {
+ self.output.push(create_fn_mono_item(tcx, instance, source));
+ }
+ }
mir::TerminatorKind::Goto { .. }
| mir::TerminatorKind::SwitchInt { .. }
| mir::TerminatorKind::Resume
| mir::TerminatorKind::Abort
| mir::TerminatorKind::Return
- | mir::TerminatorKind::Unreachable
- | mir::TerminatorKind::Assert { .. } => {}
+ | mir::TerminatorKind::Unreachable => {}
mir::TerminatorKind::GeneratorDrop
| mir::TerminatorKind::Yield { .. }
| mir::TerminatorKind::FalseEdge { .. }
src_file.prefer_local(),
line_nos
) {
- eprintln!("Error writting to file {}", e.to_string())
+ eprintln!("Error writing to file {}", e)
}
}
}
rustc_span = { path = "../rustc_span" }
rustc_ast = { path = "../rustc_ast" }
unicode-normalization = "0.1.11"
+unicode-width = "0.1.4"
use rustc_ast::ast::{self, AttrStyle};
use rustc_ast::token::{self, CommentKind, Token, TokenKind};
use rustc_ast::tokenstream::{Spacing, TokenStream};
+use rustc_ast::util::unicode::contains_text_flow_control_chars;
use rustc_errors::{error_code, Applicability, DiagnosticBuilder, FatalError, PResult};
use rustc_lexer::unescape::{self, Mode};
use rustc_lexer::{Base, DocStyle, RawStrError};
-use rustc_session::lint::builtin::RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX;
+use rustc_session::lint::builtin::{
+ RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
+};
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_session::parse::ParseSess;
use rustc_span::symbol::{sym, Symbol};
.struct_span_fatal(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c)))
}
+ /// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly
+ /// complain about it.
+ fn lint_unicode_text_flow(&self, start: BytePos) {
+ // Opening delimiter of the length 2 is not included into the comment text.
+ let content_start = start + BytePos(2);
+ let content = self.str_from(content_start);
+ if contains_text_flow_control_chars(content) {
+ let span = self.mk_sp(start, self.pos);
+ self.sess.buffer_lint_with_diagnostic(
+ &TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
+ span,
+ ast::CRATE_NODE_ID,
+ "unicode codepoint changing visible direction of text present in comment",
+ BuiltinLintDiagnostics::UnicodeTextFlow(span, content.to_string()),
+ );
+ }
+ }
+
/// Turns simple `rustc_lexer::TokenKind` enum into a rich
/// `rustc_ast::TokenKind`. This turns strings into interned
/// symbols and runs additional validation.
Some(match token {
rustc_lexer::TokenKind::LineComment { doc_style } => {
// Skip non-doc comments
- let doc_style = doc_style?;
+ let doc_style = if let Some(doc_style) = doc_style {
+ doc_style
+ } else {
+ self.lint_unicode_text_flow(start);
+ return None;
+ };
// Opening delimiter of the length 3 is not included into the symbol.
let content_start = start + BytePos(3);
}
// Skip non-doc comments
- let doc_style = doc_style?;
+ let doc_style = if let Some(doc_style) = doc_style {
+ doc_style
+ } else {
+ self.lint_unicode_text_flow(start);
+ return None;
+ };
// Opening delimiter of the length 3 and closing delimiter of the length 2
// are not included into the symbol.
assert!(mode.is_bytes());
let (c, span) = last_char();
let mut err = handler.struct_span_err(span, "non-ASCII character in byte constant");
- err.span_label(span, "byte constant must be ASCII");
+ let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 {
+ format!(" but is {:?}", c)
+ } else {
+ String::new()
+ };
+ err.span_label(span, &format!("byte constant must be ASCII{}", postfix));
if (c as u32) <= 0xFF {
err.span_suggestion(
span,
&format!(
- "if you meant to use the unicode code point for '{}', use a \\xHH escape",
+ "if you meant to use the unicode code point for {:?}, use a \\xHH escape",
c
),
format!("\\x{:X}", c as u32),
err.span_suggestion(
span,
&format!(
- "if you meant to use the UTF-8 encoding of '{}', use \\xHH escapes",
+ "if you meant to use the UTF-8 encoding of {:?}, use \\xHH escapes",
c
),
utf8.as_bytes()
}
EscapeError::NonAsciiCharInByteString => {
assert!(mode.is_bytes());
- let (_c, span) = last_char();
+ let (c, span) = last_char();
+ let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 {
+ format!(" but is {:?}", c)
+ } else {
+ String::new()
+ };
handler
.struct_span_err(span, "raw byte string must be ASCII")
- .span_label(span, "must be ASCII")
+ .span_label(span, &format!("must be ASCII{}", postfix))
.emit();
}
EscapeError::OutOfRangeHexEscape => {
} else if self.check_fn_front_matter(def_final) {
// FUNCTION ITEM
let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?;
- (ident, ItemKind::Fn(Box::new(FnKind(def(), sig, generics, body))))
+ (ident, ItemKind::Fn(Box::new(Fn { defaultness: def(), sig, generics, body })))
} else if self.eat_keyword(kw::Extern) {
if self.eat_keyword(kw::Crate) {
// EXTERN CRATE
};
let trait_ref = TraitRef { path, ref_id: ty_first.id };
- ItemKind::Impl(Box::new(ImplKind {
+ ItemKind::Impl(Box::new(Impl {
unsafety,
polarity,
defaultness,
}
None => {
// impl Type
- ItemKind::Impl(Box::new(ImplKind {
+ ItemKind::Impl(Box::new(Impl {
unsafety,
polarity,
defaultness,
self.expect_keyword(kw::Trait)?;
let ident = self.parse_ident()?;
- let mut tps = self.parse_generics()?;
+ let mut generics = self.parse_generics()?;
// Parse optional colon and supertrait bounds.
let had_colon = self.eat(&token::Colon);
}
let bounds = self.parse_generic_bounds(None)?;
- tps.where_clause = self.parse_where_clause()?;
+ generics.where_clause = self.parse_where_clause()?;
self.expect_semi()?;
let whole_span = lo.to(self.prev_token.span);
self.sess.gated_spans.gate(sym::trait_alias, whole_span);
- Ok((ident, ItemKind::TraitAlias(tps, bounds)))
+ Ok((ident, ItemKind::TraitAlias(generics, bounds)))
} else {
// It's a normal trait.
- tps.where_clause = self.parse_where_clause()?;
+ generics.where_clause = self.parse_where_clause()?;
let items = self.parse_item_list(attrs, |p| p.parse_trait_item(ForceCollect::No))?;
- Ok((ident, ItemKind::Trait(Box::new(TraitKind(is_auto, unsafety, tps, bounds, items)))))
+ Ok((
+ ident,
+ ItemKind::Trait(Box::new(Trait { is_auto, unsafety, generics, bounds, items })),
+ ))
}
}
/// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ;
/// ```
/// The `"type"` has already been eaten.
- fn parse_type_alias(&mut self, def: Defaultness) -> PResult<'a, ItemInfo> {
+ fn parse_type_alias(&mut self, defaultness: Defaultness) -> PResult<'a, ItemInfo> {
let ident = self.parse_ident()?;
let mut generics = self.parse_generics()?;
if self.eat(&token::Colon) { self.parse_generic_bounds(None)? } else { Vec::new() };
generics.where_clause = self.parse_where_clause()?;
- let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
+ let ty = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
self.expect_semi()?;
- Ok((ident, ItemKind::TyAlias(Box::new(TyAliasKind(def, generics, bounds, default)))))
+ Ok((ident, ItemKind::TyAlias(Box::new(TyAlias { defaultness, generics, bounds, ty }))))
}
/// Parses a `UseTree`.
};
match impl_info.1 {
- ItemKind::Impl(box ImplKind {
- of_trait: Some(ref trai), ref mut constness, ..
- }) => {
+ ItemKind::Impl(box Impl { of_trait: Some(ref trai), ref mut constness, .. }) => {
*constness = Const::Yes(const_span);
let before_trait = trai.path.span.shrink_to_lo();
required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect();
match missing_gates.as_slice() {
- &[] => struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit(),
+ [] => struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit(),
- &[missing_primary, ref missing_secondary @ ..] => {
- let mut err = feature_err(&tcx.sess.parse_sess, missing_primary, span, &msg);
+ [missing_primary, ref missing_secondary @ ..] => {
+ let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, &msg);
// If multiple feature gates would be required to enable this expression, include
// them as help messages. Don't emit a separate error for each missing feature gate.
prof_timer.finish_with_query_invocation_id(dep_node_index.into());
if let Some(result) = result {
+ let prev_fingerprint = tcx
+ .dep_context()
+ .dep_graph()
+ .prev_fingerprint_of(dep_node)
+ .unwrap_or(Fingerprint::ZERO);
// If `-Zincremental-verify-ich` is specified, re-hash results from
// the cache and make sure that they have the expected fingerprint.
- if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) {
+ //
+ // If not, we still seek to verify a subset of fingerprints loaded
+ // from disk. Re-hashing results is fairly expensive, so we can't
+ // currently afford to verify every hash. This subset should still
+ // give us some coverage of potential bugs though.
+ let try_verify = prev_fingerprint.as_value().1 % 32 == 0;
+ if unlikely!(
+ try_verify || tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich
+ ) {
incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
}
use rustc_ast::visit::{self, AssocCtxt, Visitor};
use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
-use rustc_ast::{Block, FnKind, ForeignItem, ForeignItemKind, ImplKind, Item, ItemKind, NodeId};
+use rustc_ast::{Block, Fn, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
use rustc_ast_lowering::ResolverAstLowering;
use rustc_attr as attr;
use rustc_data_structures::sync::Lrc;
}
// These items do not add names to modules.
- ItemKind::Impl(box ImplKind { of_trait: Some(..), .. }) => {
+ ItemKind::Impl(box Impl { of_trait: Some(..), .. }) => {
self.r.trait_impl_items.insert(local_def_id);
}
ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
if ctxt == AssocCtxt::Trait {
let (def_kind, ns) = match item.kind {
AssocItemKind::Const(..) => (DefKind::AssocConst, ValueNS),
- AssocItemKind::Fn(box FnKind(_, ref sig, _, _)) => {
+ AssocItemKind::Fn(box Fn { ref sig, .. }) => {
if sig.decl.has_self() {
self.r.has_self.insert(def_id);
}
err.span_label(span, label);
if let Some((suggestions, msg, applicability)) = suggestion {
+ if suggestions.is_empty() {
+ err.help(&msg);
+ return err;
+ }
err.multipart_suggestion(&msg, suggestions, applicability);
}
}
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
match foreign_item.kind {
- ForeignItemKind::Fn(box FnKind(_, _, ref generics, _))
- | ForeignItemKind::TyAlias(box TyAliasKind(_, ref generics, ..)) => {
+ ForeignItemKind::Fn(box Fn { ref generics, .. })
+ | ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
visit::walk_foreign_item(this, foreign_item);
});
debug!("(resolving item) resolving {} ({:?})", name, item.kind);
match item.kind {
- ItemKind::TyAlias(box TyAliasKind(_, ref generics, _, _))
- | ItemKind::Fn(box FnKind(_, _, ref generics, _)) => {
+ ItemKind::TyAlias(box TyAlias { ref generics, .. })
+ | ItemKind::Fn(box Fn { ref generics, .. }) => {
self.compute_num_lifetime_params(item.id, generics);
self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
visit::walk_item(this, item)
self.resolve_adt(item, generics);
}
- ItemKind::Impl(box ImplKind {
+ ItemKind::Impl(box Impl {
ref generics,
ref of_trait,
ref self_ty,
self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items);
}
- ItemKind::Trait(box TraitKind(.., ref generics, ref bounds, ref trait_items)) => {
+ ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => {
self.compute_num_lifetime_params(item.id, generics);
// Create a new rib for the trait-wide type parameters.
self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| {
});
};
- this.with_trait_items(trait_items, |this| {
- for item in trait_items {
+ this.with_trait_items(items, |this| {
+ for item in items {
match &item.kind {
AssocItemKind::Const(_, ty, default) => {
this.visit_ty(ty);
);
}
}
- AssocItemKind::Fn(box FnKind(_, _, generics, _)) => {
+ AssocItemKind::Fn(box Fn { generics, .. }) => {
walk_assoc_item(this, generics, item);
}
- AssocItemKind::TyAlias(box TyAliasKind(_, generics, _, _)) => {
+ AssocItemKind::TyAlias(box TyAlias { generics, .. }) => {
walk_assoc_item(this, generics, item);
}
AssocItemKind::MacCall(_) => {
},
);
}
- AssocItemKind::Fn(box FnKind(.., generics, _)) => {
+ AssocItemKind::Fn(box Fn { generics, .. }) => {
debug!("resolve_implementation AssocItemKind::Fn");
// We also need a new scope for the impl item type parameters.
this.with_generic_param_rib(
},
);
}
- AssocItemKind::TyAlias(box TyAliasKind(
- _,
- generics,
- _,
- _,
- )) => {
+ AssocItemKind::TyAlias(box TyAlias {
+ generics, ..
+ }) => {
debug!("resolve_implementation AssocItemKind::TyAlias");
// We also need a new scope for the impl item type parameters.
this.with_generic_param_rib(
let candidates = self
.r
.lookup_import_candidates(ident, ns, &self.parent_scope, is_expected)
- .drain(..)
+ .into_iter()
.filter(|ImportSuggestion { did, .. }| {
match (did, res.and_then(|res| res.opt_def_id())) {
(Some(suggestion_did), Some(actual_did)) => *suggestion_did != actual_did,
if assoc_item.ident == ident {
return Some(match &assoc_item.kind {
ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst,
- ast::AssocItemKind::Fn(box ast::FnKind(_, sig, ..))
- if sig.decl.has_self() =>
- {
+ ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) if sig.decl.has_self() => {
AssocSuggestion::MethodWithSelf
}
ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn,
} else {
// Search in module.
let mod_path = &path[..path.len() - 1];
- if let PathResult::Module(module) =
+ if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
self.resolve_path(mod_path, Some(TypeNS), false, span, CrateLint::No)
{
- if let ModuleOrUniformRoot::Module(module) = module {
- self.r.add_module_candidates(module, &mut names, &filter_fn);
- }
+ self.r.add_module_candidates(module, &mut names, &filter_fn);
}
}
if suggest_only_tuple_variants {
// Suggest only tuple variants regardless of whether they have fields and do not
// suggest path with added parentheses.
- let mut suggestable_variants = variants
+ let suggestable_variants = variants
.iter()
.filter(|(.., kind)| *kind == CtorKind::Fn)
.map(|(variant, ..)| path_names_to_string(variant))
err.span_suggestions(
span,
&msg,
- suggestable_variants.drain(..),
+ suggestable_variants.into_iter(),
Applicability::MaybeIncorrect,
);
}
);
}
- let mut suggestable_variants_with_placeholders = variants
+ let suggestable_variants_with_placeholders = variants
.iter()
.filter(|(_, def_id, kind)| needs_placeholder(*def_id, *kind))
.map(|(variant, _, kind)| (path_names_to_string(variant), kind))
err.span_suggestions(
span,
msg,
- suggestable_variants_with_placeholders.drain(..),
+ suggestable_variants_with_placeholders.into_iter(),
Applicability::HasPlaceholders,
);
}
break;
}
}
- hir::TyKind::Path(ref qpath) => {
- if let QPath::Resolved(_, path) = qpath {
- let last_segment = &path.segments[path.segments.len() - 1];
- let generics = last_segment.args();
- for arg in generics.args.iter() {
- if let GenericArg::Lifetime(lt) = arg {
- if lt.name.ident() == name {
- elide_use = Some(lt.span);
- break;
- }
+ hir::TyKind::Path(QPath::Resolved(_, path)) => {
+ let last_segment = &path.segments[path.segments.len() - 1];
+ let generics = last_segment.args();
+ for arg in generics.args.iter() {
+ if let GenericArg::Lifetime(lt) = arg {
+ if lt.name.ident() == name {
+ elide_use = Some(lt.span);
+ break;
}
}
- break;
}
+ break;
}
_ => {}
}
} else {
(
format!("use of undeclared crate or module `{}`", ident),
- self.find_similarly_named_module_or_crate(
- ident.name,
- &parent_scope.module,
- )
- .map(|sugg| {
- (
- vec![(ident.span, sugg.to_string())],
+ if ident.name == sym::alloc {
+ Some((
+ vec![],
String::from(
- "there is a crate or module with a similar name",
+ "add `extern crate alloc` to use the `alloc` crate",
),
Applicability::MaybeIncorrect,
+ ))
+ } else {
+ self.find_similarly_named_module_or_crate(
+ ident.name,
+ &parent_scope.module,
)
- }),
+ .map(|sugg| {
+ (
+ vec![(ident.span, sugg.to_string())],
+ String::from(
+ "there is a crate or module with a similar name",
+ ),
+ Applicability::MaybeIncorrect,
+ )
+ })
+ },
)
}
} else {
id,
span,
name: ident.to_string(),
- qualname: format!("{}::{}", qualname, ident.to_string()),
+ qualname: format!("{}::{}", qualname, ident),
value: typ,
parent: None,
children: vec![],
// Rust uses the id of the pattern for var lookups, so we'll use it too.
if !self.span.filter_generated(ident.span) {
- let qualname = format!("{}${}", ident.to_string(), hir_id);
+ let qualname = format!("{}${}", ident, hir_id);
let id = id_from_hir_id(hir_id, &self.save_ctxt);
let span = self.span_from_span(ident.span);
pub(super) fn build_target_config(
opts: &Options,
target_override: Option<Target>,
- sysroot: &PathBuf,
+ sysroot: &Path,
) -> Target {
let target_result = target_override.map_or_else(
|| Target::search(&opts.target_triple, sysroot),
match v {
Some(s) => {
if !slot.is_empty() {
- slot.push_str(",");
+ slot.push(',');
}
slot.push_str(s);
true
move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
"the size at which the `large_assignments` lint starts to be emitted"),
mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
- "emit noalias metadata for mutable references (default: yes for LLVM >= 12, otherwise no)"),
+ "emit noalias metadata for mutable references (default: yes)"),
new_llvm_pass_manager: Option<bool> = (None, parse_opt_bool, [TRACKED],
"use new LLVM pass manager (default: no)"),
nll_facts: bool = (false, parse_bool, [UNTRACKED],
encoder.emit_enum(|encoder| match *self {
RealFileName::LocalPath(ref local_path) => {
encoder.emit_enum_variant("LocalPath", 0, 1, |encoder| {
- Ok({
- encoder
- .emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
- })
+ encoder.emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
+ Ok(())
})
}
// For privacy and build reproducibility, we must not embed host-dependant path in artifacts
// if they have been remapped by --remap-path-prefix
assert!(local_path.is_none());
- Ok({
- encoder
- .emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
- encoder
- .emit_enum_variant_arg(false, |encoder| virtual_name.encode(encoder))?;
- })
+ encoder.emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
+ encoder.emit_enum_variant_arg(false, |encoder| virtual_name.encode(encoder))?;
+ Ok(())
}),
})
}
as_ptr,
as_str,
asm,
+ asm_const,
+ asm_experimental_arch,
+ asm_sym,
assert,
assert_inhabited,
assert_macro,
div_assign,
doc,
doc_alias,
+ doc_auto_cfg,
doc_cfg,
doc_cfg_hide,
doc_keyword,
rustc_partition_reused,
rustc_peek,
rustc_peek_definite_init,
- rustc_peek_indirectly_mutable,
rustc_peek_liveness,
rustc_peek_maybe_init,
rustc_peek_maybe_uninit,
const NonNull = 1 << 3;
const ReadOnly = 1 << 4;
const InReg = 1 << 5;
- // NoAlias on &mut arguments can only be used with LLVM >= 12 due to miscompiles
- // in earlier versions. FIXME: Remove this distinction once possible.
+ // Due to past miscompiles in LLVM, we use a separate attribute for
+ // &mut arguments, so that the codegen backend can decide whether
+ // or not to actually emit the attribute. It can also be controlled
+ // with the `-Zmutable-noalias` debugging option.
const NoAliasMutRef = 1 << 6;
}
}
pub fn target() -> Target {
let mut base = super::apple_base::opts("macos");
- base.cpu = "apple-a12".to_string();
+ base.cpu = "apple-a14".to_string();
base.max_atomic_width = Some(128);
// FIXME: The leak sanitizer currently fails the tests, see #88132.
data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
options: TargetOptions {
+ features: "+outline-atomics".to_string(),
max_atomic_width: Some(128),
mcount: "\u{1}_mcount".to_string(),
endian: Endian::Big,
arch: "aarch64".to_string(),
options: TargetOptions {
abi: "ilp32".to_string(),
+ features: "+outline-atomics".to_string(),
mcount: "\u{1}_mcount".to_string(),
endian: Endian::Big,
..base
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
options: TargetOptions {
+ features: "+outline-atomics".to_string(),
mcount: "\u{1}_mcount".to_string(),
max_atomic_width: Some(128),
supported_sanitizers: SanitizerSet::ADDRESS
arch: "aarch64".to_string(),
options: TargetOptions {
abi: "ilp32".to_string(),
+ features: "+outline-atomics".to_string(),
max_atomic_width: Some(128),
mcount: "\u{1}_mcount".to_string(),
..super::linux_gnu_base::opts()
pointer_width: 64,
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
arch: "aarch64".to_string(),
- options: TargetOptions { mcount: "\u{1}_mcount".to_string(), ..base },
+ options: TargetOptions {
+ features: "+outline-atomics".to_string(),
+ mcount: "\u{1}_mcount".to_string(),
+ ..base
+ },
}
}
("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf),
+
+ ("x86_64-unknown-none", x86_64_unknown_none),
}
/// Warnings encountered when parsing the target `json`.
/// JSON decoding.
pub fn search(
target_triple: &TargetTriple,
- sysroot: &PathBuf,
+ sysroot: &Path,
) -> Result<(Target, TargetWarnings), String> {
use rustc_serialize::json;
use std::env;
--- /dev/null
+// Generic x86-64 target for bare-metal code - Floating point disabled
+//
+// Can be used in conjunction with the `target-feature` and
+// `target-cpu` compiler flags to opt-in more hardware-specific
+// features.
+
+use super::{
+ CodeModel, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, RelroLevel, StackProbeType,
+ Target, TargetOptions,
+};
+
+pub fn target() -> Target {
+ let opts = TargetOptions {
+ cpu: "x86-64".to_string(),
+ max_atomic_width: Some(64),
+ // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
+ stack_probes: StackProbeType::Call,
+ position_independent_executables: true,
+ static_position_independent_executables: true,
+ relro_level: RelroLevel::Full,
+ relocation_model: RelocModel::Pic,
+ linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker: Some("rust-lld".to_owned()),
+ features:
+ "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
+ .to_string(),
+ executables: true,
+ disable_redzone: true,
+ panic_strategy: PanicStrategy::Abort,
+ code_model: Some(CodeModel::Kernel),
+ ..Default::default()
+ };
+ Target {
+ llvm_target: "x86_64-unknown-none-elf".to_string(),
+ pointer_width: 64,
+ data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+ .to_string(),
+ arch: "x86_64".to_string(),
+ options: opts,
+ }
+}
post.iter().map(|p| format!("- {}", p)).take(4).collect::<Vec<_>>().join("\n"),
post.len() - 4,
)
- } else if post.len() > 1 || (post.len() == 1 && post[0].contains("\n")) {
+ } else if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::<Vec<_>>().join("\n"),)
} else if post.len() == 1 {
format!(": `{}`", post[0])
let sized_trait = self.tcx.lang_items().sized_trait();
debug!("maybe_suggest_unsized_generics: generics.params={:?}", generics.params);
debug!("maybe_suggest_unsized_generics: generics.where_clause={:?}", generics.where_clause);
- let param = generics
- .params
- .iter()
- .filter(|param| param.span == span)
- .filter(|param| {
- // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
- // `Sized` bound is there intentionally and we don't need to suggest relaxing it.
- param
- .bounds
- .iter()
- .all(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) != sized_trait)
- })
- .next();
+ let param = generics.params.iter().filter(|param| param.span == span).find(|param| {
+ // Check that none of the explicit trait bounds is `Sized`. Assume that an explicit
+ // `Sized` bound is there intentionally and we don't need to suggest relaxing it.
+ param
+ .bounds
+ .iter()
+ .all(|bound| bound.trait_ref().and_then(|tr| tr.trait_def_id()) != sized_trait)
+ });
let param = match param {
Some(param) => param,
_ => return,
) -> usize {
let (trait_to_be_found, trait_owning_vtable) = key;
+ // #90177
+ let trait_to_be_found_erased = tcx.erase_regions(trait_to_be_found);
+
let vtable_segment_callback = {
let mut vtable_base = 0;
vtable_base += COMMON_VTABLE_ENTRIES.len();
}
VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
- if trait_ref == trait_to_be_found {
+ if tcx.erase_regions(trait_ref) == trait_to_be_found_erased {
return ControlFlow::Break(vtable_base);
}
vtable_base += util::count_own_vtable_entries(tcx, trait_ref);
ty: ret_type,
});
- confirm_param_env_candidate(selcx, obligation, predicate, false)
+ confirm_param_env_candidate(selcx, obligation, predicate, true)
}
fn confirm_param_env_candidate<'cx, 'tcx>(
);
let cache_projection = cache_entry.projection_ty;
- let obligation_projection = obligation.predicate;
let mut nested_obligations = Vec::new();
+ let obligation_projection = obligation.predicate;
+ let obligation_projection = ensure_sufficient_stack(|| {
+ normalize_with_depth_to(
+ selcx,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ obligation_projection,
+ &mut nested_obligations,
+ )
+ });
let cache_projection = if potentially_unnormalized_candidate {
ensure_sufficient_stack(|| {
normalize_with_depth_to(
cache_projection
};
+ debug!(?cache_projection, ?obligation_projection);
+
match infcx.at(cause, param_env).eq(cache_projection, obligation_projection) {
Ok(InferOk { value: _, obligations }) => {
nested_obligations.extend(obligations);
_ => bug!("closure candidate for non-closure {:?}", obligation),
};
+ let obligation_predicate = obligation.predicate.to_poly_trait_ref();
+ let Normalized { value: obligation_predicate, mut obligations } =
+ ensure_sufficient_stack(|| {
+ normalize_with_depth(
+ self,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ obligation_predicate,
+ )
+ });
+
let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs);
- let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| {
- normalize_with_depth(
- self,
- obligation.param_env,
- obligation.cause.clone(),
- obligation.recursion_depth + 1,
- trait_ref,
- )
- });
+ let Normalized { value: trait_ref, obligations: trait_ref_obligations } =
+ ensure_sufficient_stack(|| {
+ normalize_with_depth(
+ self,
+ obligation.param_env,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ trait_ref,
+ )
+ });
debug!(?closure_def_id, ?trait_ref, ?obligations, "confirm closure candidate obligations");
+ obligations.extend(trait_ref_obligations);
obligations.extend(self.confirm_poly_trait_refs(
obligation.cause.clone(),
obligation.param_env,
- obligation.predicate.to_poly_trait_ref(),
+ obligation_predicate,
trait_ref,
)?);
let tail_field_ty = tcx.type_of(tail_field.did);
let mut unsizing_params = GrowableBitSet::new_empty();
- if tcx.features().relaxed_struct_unsize {
- for arg in tail_field_ty.walk(tcx) {
- if let Some(i) = maybe_unsizing_param_idx(arg) {
- unsizing_params.insert(i);
- }
- }
-
- // Ensure none of the other fields mention the parameters used
- // in unsizing.
- for field in prefix_fields {
- for arg in tcx.type_of(field.did).walk(tcx) {
- if let Some(i) = maybe_unsizing_param_idx(arg) {
- unsizing_params.remove(i);
- }
- }
+ for arg in tail_field_ty.walk(tcx) {
+ if let Some(i) = maybe_unsizing_param_idx(arg) {
+ unsizing_params.insert(i);
}
+ }
- if unsizing_params.is_empty() {
- return Err(Unimplemented);
- }
- } else {
- let mut found = false;
- for arg in tail_field_ty.walk(tcx) {
+ // Ensure none of the other fields mention the parameters used
+ // in unsizing.
+ for field in prefix_fields {
+ for arg in tcx.type_of(field.did).walk(tcx) {
if let Some(i) = maybe_unsizing_param_idx(arg) {
- unsizing_params.insert(i);
- found = true;
+ unsizing_params.remove(i);
}
}
- if !found {
- return Err(Unimplemented);
- }
+ }
- // Ensure none of the other fields mention the parameters used
- // in unsizing.
- // FIXME(eddyb) cache this (including computing `unsizing_params`)
- // by putting it in a query; it would only need the `DefId` as it
- // looks at declared field types, not anything substituted.
- for field in prefix_fields {
- for arg in tcx.type_of(field.did).walk(tcx) {
- if let Some(i) = maybe_unsizing_param_idx(arg) {
- if unsizing_params.contains(i) {
- return Err(Unimplemented);
- }
- }
- }
- }
+ if unsizing_params.is_empty() {
+ return Err(Unimplemented);
}
// Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`.
/// Returns `true` if the trait predicate is considerd `const` to this selection context.
pub fn is_trait_predicate_const(&self, pred: ty::TraitPredicate<'_>) -> bool {
- match pred.constness {
- ty::BoundConstness::ConstIfConst if self.is_in_const_context => true,
- _ => false,
- }
+ matches!(pred.constness, ty::BoundConstness::ConstIfConst) && self.is_in_const_context
}
/// Returns `true` if the predicate is considered `const` to
"reorder the arguments: {}: `<{}>`",
param_types_present
.into_iter()
- .map(|ord| format!("{}s", ord.to_string()))
+ .map(|ord| format!("{}s", ord))
.collect::<Vec<String>>()
.join(", then "),
ordered_params
// Very crude check to see whether the expression must be wrapped
// in parentheses for the suggestion to work (issue #89497).
// Can/should be extended in the future.
- let needs_parens = !has_parens
- && match self.expr.kind {
- hir::ExprKind::Cast(..) => true,
- _ => false,
- };
+ let needs_parens =
+ !has_parens && matches!(self.expr.kind, hir::ExprKind::Cast(..));
let mut suggestion = vec![(self.expr.span.shrink_to_lo(), sugg)];
if needs_parens {
Ok(())
}
+#[instrument(level = "debug", skip(infcx))]
fn extract_spans_for_error_reporting<'a, 'tcx>(
infcx: &infer::InferCtxt<'a, 'tcx>,
terr: &TypeError<'_>,
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
) {
self.annotate_expected_due_to_let_ty(err, expr);
+ self.suggest_box_deref(err, expr, expected, expr_ty);
self.suggest_compatible_variants(err, expr, expected, expr_ty);
self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr);
if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
}
}
+ fn suggest_box_deref(
+ &self,
+ err: &mut DiagnosticBuilder<'_>,
+ expr: &hir::Expr<'_>,
+ expected: Ty<'tcx>,
+ expr_ty: Ty<'tcx>,
+ ) {
+ if expr_ty.is_box() && expr_ty.boxed_ty() == expected {
+ err.span_suggestion_verbose(
+ expr.span.shrink_to_lo(),
+ "try dereferencing the `Box`",
+ "*".to_string(),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+
/// If the expected type is an enum (Issue #55250) with any variants whose
/// sole field is of the found type, suggest such variants. (Issue #42764)
fn suggest_compatible_variants(
(&ty::Str, &ty::Array(arr, _) | &ty::Slice(arr)) if arr == self.tcx.types.u8 => {
if let hir::ExprKind::Lit(_) = expr.kind {
if let Ok(src) = sm.span_to_snippet(sp) {
- if let Some(_) = replace_prefix(&src, "b\"", "\"") {
+ if replace_prefix(&src, "b\"", "\"").is_some() {
let pos = sp.lo() + BytePos(1);
return Some((
sp.with_hi(pos),
(&ty::Array(arr, _) | &ty::Slice(arr), &ty::Str) if arr == self.tcx.types.u8 => {
if let hir::ExprKind::Lit(_) = expr.kind {
if let Ok(src) = sm.span_to_snippet(sp) {
- if let Some(_) = replace_prefix(&src, "\"", "b\"") {
+ if replace_prefix(&src, "\"", "b\"").is_some() {
return Some((
sp.shrink_to_lo(),
"consider adding a leading `b`",
// Save the index of all fields regardless of their visibility in case
// of error recovery.
self.write_field_index(expr.hir_id, index);
+ let adjustments = self.adjust_steps(&autoderef);
if field.vis.is_accessible_from(def_scope, self.tcx) {
- let adjustments = self.adjust_steps(&autoderef);
self.apply_adjustments(base, adjustments);
self.register_predicates(autoderef.into_obligations());
self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None);
return field_ty;
}
- private_candidate = Some((base_def.did, field_ty));
+ private_candidate = Some((adjustments, base_def.did, field_ty));
}
}
ty::Tuple(tys) => {
}
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
- if let Some((did, field_ty)) = private_candidate {
+ if let Some((adjustments, did, field_ty)) = private_candidate {
+ // (#90483) apply adjustments to avoid ExprUseVisitor from
+ // creating erroneous projection.
+ self.apply_adjustments(base, adjustments);
self.ban_private_field_access(expr, expr_t, field, did);
return field_ty;
}
) -> Option<(&Vec<ty::FieldDef>, SubstsRef<'tcx>)> {
debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_t);
- let mut autoderef = self.autoderef(span, base_t);
- while let Some((base_t, _)) = autoderef.next() {
+ for (base_t, _) in self.autoderef(span, base_t) {
match base_t.kind() {
ty::Adt(base_def, substs) if !base_def.is_enum() => {
let fields = &base_def.non_enum_variant().fields;
.type_var_origin(ty)
.map(|origin| origin.span)
.unwrap_or(rustc_span::DUMMY_SP);
- let oty = self.inner.borrow().opaque_types_vars.get(ty).map(|v| *v);
+ let oty = self.inner.borrow().opaque_types_vars.get(ty).copied();
if let Some(opaque_ty) = oty {
debug!(
"fallback_opaque_type_vars(ty={:?}): falling back to opaque type {:?}",
call_expr: &'tcx hir::Expr<'tcx>,
) {
if let hir::ExprKind::Call(path, _) = &call_expr.kind {
- if let hir::ExprKind::Path(qpath) = &path.kind {
- if let hir::QPath::Resolved(_, path) = &qpath {
- for error in errors {
- if let ty::PredicateKind::Trait(predicate) =
- error.obligation.predicate.kind().skip_binder()
+ if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &path.kind {
+ for error in errors {
+ if let ty::PredicateKind::Trait(predicate) =
+ error.obligation.predicate.kind().skip_binder()
+ {
+ // If any of the type arguments in this path segment caused the
+ // `FulfillmentError`, point at its span (#61860).
+ for arg in path
+ .segments
+ .iter()
+ .filter_map(|seg| seg.args.as_ref())
+ .flat_map(|a| a.args.iter())
{
- // If any of the type arguments in this path segment caused the
- // `FulfillmentError`, point at its span (#61860).
- for arg in path
- .segments
- .iter()
- .filter_map(|seg| seg.args.as_ref())
- .flat_map(|a| a.args.iter())
- {
- if let hir::GenericArg::Type(hir_ty) = &arg {
- if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) =
- &hir_ty.kind
- {
- // Avoid ICE with associated types. As this is best
- // effort only, it's ok to ignore the case. It
- // would trigger in `is_send::<T::AssocType>();`
- // from `typeck-default-trait-impl-assoc-type.rs`.
- } else {
- let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty);
- let ty = self.resolve_vars_if_possible(ty);
- if ty == predicate.self_ty() {
- error.obligation.cause.make_mut().span = hir_ty.span;
- }
+ if let hir::GenericArg::Type(hir_ty) = &arg {
+ if let hir::TyKind::Path(hir::QPath::TypeRelative(..)) =
+ &hir_ty.kind
+ {
+ // Avoid ICE with associated types. As this is best
+ // effort only, it's ok to ignore the case. It
+ // would trigger in `is_send::<T::AssocType>();`
+ // from `typeck-default-trait-impl-assoc-type.rs`.
+ } else {
+ let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, hir_ty);
+ let ty = self.resolve_vars_if_possible(ty);
+ if ty == predicate.self_ty() {
+ error.obligation.cause.make_mut().span = hir_ty.span;
}
}
}
let edition_fix = candidates
.iter()
.find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
- .map(|&d| d);
+ .copied();
err.help("items from traits can only be used if the trait is in scope");
let msg = format!(
}
};
if let Ref(_, rty, _) = lhs_ty.kind() {
- if {
- self.infcx.type_is_copy_modulo_regions(self.param_env, rty, lhs_expr.span)
- && self
- .lookup_op_method(rty, &[rhs_ty], Op::Binary(op, is_assign))
- .is_ok()
- } {
+ if self.infcx.type_is_copy_modulo_regions(self.param_env, rty, lhs_expr.span)
+ && self.lookup_op_method(rty, &[rhs_ty], Op::Binary(op, is_assign)).is_ok()
+ {
if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
let msg = &format!(
"`{}{}` can be used on `{}`, you can dereference `{}`",
};
}
-trait OutlivesEnvironmentExt<'tcx> {
+pub(crate) trait OutlivesEnvironmentExt<'tcx> {
fn add_implied_bounds(
&mut self,
infcx: &InferCtxt<'a, 'tcx>,
/// Intermediate format to store the hir_id pointing to the use that resulted in the
/// corresponding place being captured and a String which contains the captured value's
/// name (i.e: a.b.c)
-type CapturesInfo = (Option<hir::HirId>, String);
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+enum UpvarMigrationInfo {
+ /// We previously captured all of `x`, but now we capture some sub-path.
+ CapturingPrecise { source_expr: Option<hir::HirId>, var_name: String },
+ CapturingNothing {
+ // where the variable appears in the closure (but is not captured)
+ use_span: Span,
+ },
+}
+
+/// Reasons that we might issue a migration warning.
+#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+struct MigrationWarningReason {
+ /// When we used to capture `x` in its entirety, we implemented the auto-trait(s)
+ /// in this vec, but now we don't.
+ auto_traits: Vec<&'static str>,
+
+ /// When we used to capture `x` in its entirety, we would execute some destructors
+ /// at a different time.
+ drop_order: bool,
+}
+
+impl MigrationWarningReason {
+ fn migration_message(&self) -> String {
+ let base = "changes to closure capture in Rust 2021 will affect";
+ if !self.auto_traits.is_empty() && self.drop_order {
+ format!("{} drop order and which traits the closure implements", base)
+ } else if self.drop_order {
+ format!("{} drop order", base)
+ } else {
+ format!("{} which traits the closure implements", base)
+ }
+ }
+}
-/// Intermediate format to store information needed to generate migration lint. The tuple
-/// contains the hir_id pointing to the use that resulted in the
-/// corresponding place being captured, a String which contains the captured value's
-/// name (i.e: a.b.c) and a String which contains the reason why migration is needed for that
-/// capture
-type MigrationNeededForCapture = (Option<hir::HirId>, String, String);
+/// Intermediate format to store information needed to generate a note in the migration lint.
+struct MigrationLintNote {
+ captures_info: UpvarMigrationInfo,
+
+ /// reasons why migration is needed for this capture
+ reason: MigrationWarningReason,
+}
/// Intermediate format to store the hir id of the root variable and a HashSet containing
/// information on why the root variable should be fully captured
-type MigrationDiagnosticInfo = (hir::HirId, Vec<MigrationNeededForCapture>);
+struct NeededMigration {
+ var_hir_id: hir::HirId,
+ diagnostics_info: Vec<MigrationLintNote>,
+}
struct InferBorrowKindVisitor<'a, 'tcx> {
fcx: &'a FnCtxt<'a, 'tcx>,
closure_head_span,
|lint| {
let mut diagnostics_builder = lint.build(
- format!(
- "changes to closure capture in Rust 2021 will affect {}",
- reasons
- )
- .as_str(),
+ &reasons.migration_message(),
);
- for (var_hir_id, diagnostics_info) in need_migrations.iter() {
+ for NeededMigration { var_hir_id, diagnostics_info } in &need_migrations {
// Labels all the usage of the captured variable and why they are responsible
// for migration being needed
- 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, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
- self.tcx.hir().name(*var_hir_id),
- captured_name,
- ));
+ for lint_note in diagnostics_info.iter() {
+ match &lint_note.captures_info {
+ UpvarMigrationInfo::CapturingPrecise { source_expr: Some(capture_expr_id), var_name: captured_name } => {
+ let cause_span = self.tcx.hir().span(*capture_expr_id);
+ 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,
+ ));
+ }
+ UpvarMigrationInfo::CapturingNothing { use_span } => {
+ diagnostics_builder.span_label(*use_span, format!("in Rust 2018, this causes the closure to capture `{}`, but in Rust 2021, it has no effect",
+ self.tcx.hir().name(*var_hir_id),
+ ));
+ }
+
+ _ => { }
}
// Add a label pointing to where a captured variable affected by drop order
// is dropped
- if reasons.contains("drop order") {
+ if lint_note.reason.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, `{}` 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,
- ));
+ match &lint_note.captures_info {
+ UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
+ 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,
+ ));
+ }
+ UpvarMigrationInfo::CapturingNothing { use_span: _ } => {
+ diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{v}` is dropped here along with the closure, but in Rust 2021 `{v}` is not part of the closure",
+ v = self.tcx.hir().name(*var_hir_id),
+ ));
+ }
+ }
}
// Add a label explaining why a closure no longer implements a trait
- 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 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,
- missing_trait,
- captured_name,
- missing_trait,
- ));
+ for &missing_trait in &lint_note.reason.auto_traits {
+ // not capturing something anymore cannot cause a trait to fail to be implemented:
+ match &lint_note.captures_info {
+ UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
+ let var_name = self.tcx.hir().name(*var_hir_id);
+ diagnostics_builder.span_label(closure_head_span, format!("\
+ in Rust 2018, this closure implements {missing_trait} \
+ as `{var_name}` implements {missing_trait}, but in Rust 2021, \
+ this closure will no longer implement {missing_trait} \
+ because `{var_name}` is not fully captured \
+ and `{captured_name}` does not implement {missing_trait}"));
+ }
+
+ // Cannot happen: if we don't capture a variable, we impl strictly more traits
+ UpvarMigrationInfo::CapturingNothing { use_span } => span_bug!(*use_span, "missing trait from not capturing something"),
+ }
}
}
}
/// Combines all the reasons for 2229 migrations
fn compute_2229_migrations_reasons(
&self,
- auto_trait_reasons: FxHashSet<&str>,
- drop_reason: bool,
- ) -> String {
- let mut reasons = String::new();
-
- if !auto_trait_reasons.is_empty() {
- reasons = format!(
- "{} trait implementation for closure",
- auto_trait_reasons.clone().into_iter().collect::<Vec<&str>>().join(", ")
- );
- }
+ auto_trait_reasons: FxHashSet<&'static str>,
+ drop_order: bool,
+ ) -> MigrationWarningReason {
+ let mut reasons = MigrationWarningReason::default();
- if !auto_trait_reasons.is_empty() && drop_reason {
- reasons = format!("{} and ", reasons);
+ for auto_trait in auto_trait_reasons {
+ reasons.auto_traits.push(auto_trait);
}
- if drop_reason {
- reasons = format!("{}drop order", reasons);
- }
+ reasons.drop_order = drop_order;
reasons
}
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
var_hir_id: hir::HirId,
closure_clause: hir::CaptureBy,
- ) -> Option<FxHashMap<CapturesInfo, FxHashSet<&str>>> {
+ ) -> Option<FxHashMap<UpvarMigrationInfo, FxHashSet<&'static str>>> {
let auto_traits_def_id = vec![
self.tcx.lang_items().clone_trait(),
self.tcx.lang_items().sync_trait(),
if !capture_problems.is_empty() {
problematic_captures.insert(
- (capture.info.path_expr_id, capture.to_string(self.tcx)),
+ UpvarMigrationInfo::CapturingPrecise {
+ source_expr: capture.info.path_expr_id,
+ var_name: capture.to_string(self.tcx),
+ },
capture_problems,
);
}
///
/// This function only returns a HashSet of CapturesInfo for significant drops. If there
/// are no significant drops than None is returned
+ #[instrument(level = "debug", skip(self))]
fn compute_2229_migrations_for_drop(
&self,
closure_def_id: DefId,
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
closure_clause: hir::CaptureBy,
var_hir_id: hir::HirId,
- ) -> Option<FxHashSet<CapturesInfo>> {
+ ) -> Option<FxHashSet<UpvarMigrationInfo>> {
let ty = self.infcx.resolve_vars_if_possible(self.node_ty(var_hir_id));
if !ty.has_significant_drop(self.tcx, self.tcx.param_env(closure_def_id.expect_local())) {
+ debug!("does not have significant drop");
return None;
}
let Some(root_var_min_capture_list) = min_captures.and_then(|m| m.get(&var_hir_id)) else {
// The upvar is mentioned within the closure but no path starting from it is
- // used.
+ // used. This occurs when you have (e.g.)
+ //
+ // ```
+ // let x = move || {
+ // let _ = y;
+ // });
+ // ```
+ debug!("no path starting from it is used");
+
match closure_clause {
// Only migrate if closure is a move closure
- hir::CaptureBy::Value => return Some(FxHashSet::default()),
+ hir::CaptureBy::Value => {
+ let mut diagnostics_info = FxHashSet::default();
+ let upvars = self.tcx.upvars_mentioned(closure_def_id).expect("must be an upvar");
+ let upvar = upvars[&var_hir_id];
+ diagnostics_info.insert(UpvarMigrationInfo::CapturingNothing { use_span: upvar.span });
+ return Some(diagnostics_info);
+ }
hir::CaptureBy::Ref => {}
}
return None;
};
+ debug!(?root_var_min_capture_list);
let mut projections_list = Vec::new();
let mut diagnostics_info = FxHashSet::default();
// Only care about captures that are moved into the closure
ty::UpvarCapture::ByValue(..) => {
projections_list.push(captured_place.place.projections.as_slice());
- diagnostics_info.insert((
- captured_place.info.path_expr_id,
- captured_place.to_string(self.tcx),
- ));
+ diagnostics_info.insert(UpvarMigrationInfo::CapturingPrecise {
+ source_expr: captured_place.info.path_expr_id,
+ var_name: captured_place.to_string(self.tcx),
+ });
}
ty::UpvarCapture::ByRef(..) => {}
}
}
+ debug!(?projections_list);
+ debug!(?diagnostics_info);
+
let is_moved = !projections_list.is_empty();
+ debug!(?is_moved);
let is_not_completely_captured =
root_var_min_capture_list.iter().any(|capture| !capture.place.projections.is_empty());
+ debug!(?is_not_completely_captured);
if is_moved
&& is_not_completely_captured
/// Returns a tuple containing a vector of MigrationDiagnosticInfo, as well as a String
/// containing the reason why root variables whose HirId is contained in the vector should
/// be captured
+ #[instrument(level = "debug", skip(self))]
fn compute_2229_migrations(
&self,
closure_def_id: DefId,
closure_span: Span,
closure_clause: hir::CaptureBy,
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
- ) -> (Vec<MigrationDiagnosticInfo>, String) {
+ ) -> (Vec<NeededMigration>, MigrationWarningReason) {
let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) else {
- return (Vec::new(), String::new());
+ return (Vec::new(), MigrationWarningReason::default());
};
let mut need_migrations = Vec::new();
// Perform auto-trait analysis
for (&var_hir_id, _) in upvars.iter() {
- let mut responsible_captured_hir_ids = Vec::new();
+ let mut diagnostics_info = Vec::new();
let auto_trait_diagnostic = if let Some(diagnostics_info) =
self.compute_2229_migrations_for_trait(min_captures, var_hir_id, closure_clause)
let mut capture_diagnostic = capture_diagnostic.into_iter().collect::<Vec<_>>();
capture_diagnostic.sort();
- for captured_info in capture_diagnostic.iter() {
+ for captures_info in capture_diagnostic {
// Get the auto trait reasons of why migration is needed because of that capture, if there are any
let capture_trait_reasons =
- if let Some(reasons) = auto_trait_diagnostic.get(captured_info) {
+ if let Some(reasons) = auto_trait_diagnostic.get(&captures_info) {
reasons.clone()
} else {
FxHashSet::default()
};
// Check if migration is needed because of drop reorder as a result of that capture
- let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(captured_info);
+ let capture_drop_reorder_reason = drop_reorder_diagnostic.contains(&captures_info);
// Combine all the reasons of why the root variable should be captured as a result of
// auto trait implementation issues
auto_trait_migration_reasons.extend(capture_trait_reasons.clone());
- responsible_captured_hir_ids.push((
- captured_info.0,
- captured_info.1.clone(),
- self.compute_2229_migrations_reasons(
+ diagnostics_info.push(MigrationLintNote {
+ captures_info,
+ reason: self.compute_2229_migrations_reasons(
capture_trait_reasons,
capture_drop_reorder_reason,
),
- ));
+ });
}
- if !capture_diagnostic.is_empty() {
- need_migrations.push((var_hir_id, responsible_captured_hir_ids));
+ if !diagnostics_info.is_empty() {
+ need_migrations.push(NeededMigration { var_hir_id, diagnostics_info });
}
}
(
tcx.hir().name(var_hir_id)
}
+#[instrument(level = "debug", skip(tcx))]
fn should_do_rust_2021_incompatible_closure_captures_analysis(
tcx: TyCtxt<'_>,
closure_id: hir::HirId,
/// - s2: Comma separated names of the variables being migrated.
fn migration_suggestion_for_2229(
tcx: TyCtxt<'_>,
- need_migrations: &Vec<MigrationDiagnosticInfo>,
+ need_migrations: &Vec<NeededMigration>,
) -> (String, String) {
- let need_migrations_variables =
- need_migrations.iter().map(|(v, _)| var_name(tcx, *v)).collect::<Vec<_>>();
+ let need_migrations_variables = need_migrations
+ .iter()
+ .map(|NeededMigration { var_hir_id: v, .. }| var_name(tcx, *v))
+ .collect::<Vec<_>>();
let migration_ref_concat =
need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::<Vec<_>>().join(", ");
+use crate::check::regionck::OutlivesEnvironmentExt;
use crate::check::{FnCtxt, Inherited};
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
use rustc_hir::itemlikevisit::ParItemLikeVisitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::ItemKind;
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::outlives::obligations::TypeOutlives;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::infer::{self, RegionckMode, SubregionOrigin};
use rustc_middle::hir::map as hir_map;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
- self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
+ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitor,
+ WithConstness,
};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::Span;
-use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+use rustc_span::{Span, DUMMY_SP};
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, WellFormedLoc};
use std::convert::TryInto;
.emit();
}
}
+
+ check_gat_where_clauses(tcx, trait_item, encl_trait_def_id);
+}
+
+/// Require that the user writes where clauses on GATs for the implicit
+/// outlives bounds involving trait parameters in trait functions and
+/// lifetimes passed as GAT substs. See `self-outlives-lint` test.
+///
+/// This trait will be our running example. We are currently WF checking the `Item` item...
+///
+/// ```rust
+/// trait LendingIterator {
+/// type Item<'me>; // <-- WF checking this trait item
+///
+/// fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
+/// }
+/// ```
+fn check_gat_where_clauses(
+ tcx: TyCtxt<'_>,
+ trait_item: &hir::TraitItem<'_>,
+ encl_trait_def_id: DefId,
+) {
+ let item = tcx.associated_item(trait_item.def_id);
+ // If the current trait item isn't a type, it isn't a GAT
+ if !matches!(item.kind, ty::AssocKind::Type) {
+ return;
+ }
+ let generics: &ty::Generics = tcx.generics_of(trait_item.def_id);
+ // If the current associated type doesn't have any (own) params, it's not a GAT
+ // FIXME(jackh726): we can also warn in the more general case
+ if generics.params.len() == 0 {
+ return;
+ }
+ let associated_items: &ty::AssocItems<'_> = tcx.associated_items(encl_trait_def_id);
+ let mut clauses: Option<FxHashSet<ty::Predicate<'_>>> = None;
+ // For every function in this trait...
+ // In our example, this would be the `next` method
+ for item in
+ associated_items.in_definition_order().filter(|item| matches!(item.kind, ty::AssocKind::Fn))
+ {
+ // The clauses we that we would require from this function
+ let mut function_clauses = FxHashSet::default();
+
+ let id = hir::HirId::make_owner(item.def_id.expect_local());
+ let param_env = tcx.param_env(item.def_id.expect_local());
+
+ let sig = tcx.fn_sig(item.def_id);
+ // Get the signature using placeholders. In our example, this would
+ // convert the late-bound 'a into a free region.
+ let sig = tcx.liberate_late_bound_regions(item.def_id, sig);
+ // Collect the arguments that are given to this GAT in the return type
+ // of the function signature. In our example, the GAT in the return
+ // type is `<Self as LendingIterator>::Item<'a>`, so 'a and Self are arguments.
+ let (regions, types) =
+ GATSubstCollector::visit(tcx, trait_item.def_id.to_def_id(), sig.output());
+
+ // If both regions and types are empty, then this GAT isn't in the
+ // return type, and we shouldn't try to do clause analysis
+ // (particularly, doing so would end up with an empty set of clauses,
+ // since the current method would require none, and we take the
+ // intersection of requirements of all methods)
+ if types.is_empty() && regions.is_empty() {
+ continue;
+ }
+
+ // The types we can assume to be well-formed. In our example, this
+ // would be &'a mut Self, from the first argument.
+ let mut wf_tys = FxHashSet::default();
+ wf_tys.extend(sig.inputs());
+
+ // For each region argument (e.g., 'a in our example), check for a
+ // relationship to the type arguments (e.g., Self). If there is an
+ // outlives relationship (`Self: 'a`), then we want to ensure that is
+ // reflected in a where clause on the GAT itself.
+ for (region, region_idx) in ®ions {
+ for (ty, ty_idx) in &types {
+ // In our example, requires that Self: 'a
+ if ty_known_to_outlive(tcx, id, param_env, &wf_tys, *ty, *region) {
+ debug!(?ty_idx, ?region_idx);
+ debug!("required clause: {} must outlive {}", ty, region);
+ // Translate into the generic parameters of the GAT. In
+ // our example, the type was Self, which will also be
+ // Self in the GAT.
+ let ty_param = generics.param_at(*ty_idx, tcx);
+ let ty_param = tcx.mk_ty(ty::Param(ty::ParamTy {
+ index: ty_param.index,
+ name: ty_param.name,
+ }));
+ // Same for the region. In our example, 'a corresponds
+ // to the 'me parameter.
+ let region_param = generics.param_at(*region_idx, tcx);
+ let region_param =
+ tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
+ def_id: region_param.def_id,
+ index: region_param.index,
+ name: region_param.name,
+ }));
+ // The predicate we expect to see. (In our example,
+ // `Self: 'me`.)
+ let clause = ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
+ ty_param,
+ region_param,
+ ));
+ let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
+ function_clauses.insert(clause);
+ }
+ }
+ }
+
+ // For each region argument (e.g., 'a in our example), also check for a
+ // relationship to the other region arguments. If there is an
+ // outlives relationship, then we want to ensure that is
+ // reflected in a where clause on the GAT itself.
+ for (region_a, region_a_idx) in ®ions {
+ for (region_b, region_b_idx) in ®ions {
+ if region_a == region_b {
+ continue;
+ }
+
+ if region_known_to_outlive(tcx, id, param_env, &wf_tys, *region_a, *region_b) {
+ debug!(?region_a_idx, ?region_b_idx);
+ debug!("required clause: {} must outlive {}", region_a, region_b);
+ // Translate into the generic parameters of the GAT.
+ let region_a_param = generics.param_at(*region_a_idx, tcx);
+ let region_a_param =
+ tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
+ def_id: region_a_param.def_id,
+ index: region_a_param.index,
+ name: region_a_param.name,
+ }));
+ // Same for the region.
+ let region_b_param = generics.param_at(*region_b_idx, tcx);
+ let region_b_param =
+ tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion {
+ def_id: region_b_param.def_id,
+ index: region_b_param.index,
+ name: region_b_param.name,
+ }));
+ // The predicate we expect to see.
+ let clause = ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(
+ region_a_param,
+ region_b_param,
+ ));
+ let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
+ function_clauses.insert(clause);
+ }
+ }
+ }
+
+ // Imagine we have:
+ // ```
+ // trait Foo {
+ // type Bar<'me>;
+ // fn gimme(&self) -> Self::Bar<'_>;
+ // fn gimme_default(&self) -> Self::Bar<'static>;
+ // }
+ // ```
+ // We only want to require clauses on `Bar` that we can prove from *all* functions (in this
+ // case, `'me` can be `static` from `gimme_default`)
+ match clauses.as_mut() {
+ Some(clauses) => {
+ clauses.drain_filter(|p| !function_clauses.contains(p));
+ }
+ None => {
+ clauses = Some(function_clauses);
+ }
+ }
+ }
+
+ // If there are any missing clauses, emit an error
+ let mut clauses = clauses.unwrap_or_default();
+ debug!(?clauses);
+ if !clauses.is_empty() {
+ let written_predicates: ty::GenericPredicates<'_> =
+ tcx.explicit_predicates_of(trait_item.def_id);
+ let mut clauses: Vec<_> = clauses
+ .drain_filter(|clause| !written_predicates.predicates.iter().any(|p| &p.0 == clause))
+ .map(|clause| format!("{}", clause))
+ .collect();
+ // We sort so that order is predictable
+ clauses.sort();
+ if !clauses.is_empty() {
+ let mut err = tcx.sess.struct_span_err(
+ trait_item.span,
+ &format!("Missing required bounds on {}", trait_item.ident),
+ );
+
+ let suggestion = format!(
+ "{} {}",
+ if !trait_item.generics.where_clause.predicates.is_empty() {
+ ","
+ } else {
+ " where"
+ },
+ clauses.join(", "),
+ );
+ err.span_suggestion(
+ trait_item.generics.where_clause.tail_span_for_suggestion(),
+ "add the required where clauses",
+ suggestion,
+ Applicability::MachineApplicable,
+ );
+
+ err.emit()
+ }
+ }
+}
+
+// FIXME(jackh726): refactor some of the shared logic between the two functions below
+
+/// Given a known `param_env` and a set of well formed types, can we prove that
+/// `ty` outlives `region`.
+fn ty_known_to_outlive<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ id: hir::HirId,
+ param_env: ty::ParamEnv<'tcx>,
+ wf_tys: &FxHashSet<Ty<'tcx>>,
+ ty: Ty<'tcx>,
+ region: ty::Region<'tcx>,
+) -> bool {
+ // Unfortunately, we have to use a new `InferCtxt` each call, because
+ // region constraints get added and solved there and we need to test each
+ // call individually.
+ tcx.infer_ctxt().enter(|infcx| {
+ let mut outlives_environment = OutlivesEnvironment::new(param_env);
+ outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP);
+ outlives_environment.save_implied_bounds(id);
+ let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap();
+
+ let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation);
+
+ let sup_type = ty;
+ let sub_region = region;
+
+ let origin = SubregionOrigin::from_obligation_cause(&cause, || {
+ infer::RelateParamBound(cause.span, sup_type, None)
+ });
+
+ let outlives = &mut TypeOutlives::new(
+ &infcx,
+ tcx,
+ ®ion_bound_pairs,
+ Some(infcx.tcx.lifetimes.re_root_empty),
+ param_env,
+ );
+ outlives.type_must_outlive(origin, sup_type, sub_region);
+
+ let errors = infcx.resolve_regions(
+ id.expect_owner().to_def_id(),
+ &outlives_environment,
+ RegionckMode::default(),
+ );
+
+ debug!(?errors, "errors");
+
+ // If we were able to prove that the type outlives the region without
+ // an error, it must be because of the implied or explicit bounds...
+ errors.is_empty()
+ })
+}
+
+fn region_known_to_outlive<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ id: hir::HirId,
+ param_env: ty::ParamEnv<'tcx>,
+ wf_tys: &FxHashSet<Ty<'tcx>>,
+ region_a: ty::Region<'tcx>,
+ region_b: ty::Region<'tcx>,
+) -> bool {
+ // Unfortunately, we have to use a new `InferCtxt` each call, because
+ // region constraints get added and solved there and we need to test each
+ // call individually.
+ tcx.infer_ctxt().enter(|infcx| {
+ let mut outlives_environment = OutlivesEnvironment::new(param_env);
+ outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP);
+ outlives_environment.save_implied_bounds(id);
+
+ let cause = ObligationCause::new(DUMMY_SP, id, ObligationCauseCode::MiscObligation);
+
+ let origin = SubregionOrigin::from_obligation_cause(&cause, || {
+ infer::RelateRegionParamBound(cause.span)
+ });
+
+ use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate;
+ (&infcx).push_sub_region_constraint(origin, region_a, region_b);
+
+ let errors = infcx.resolve_regions(
+ id.expect_owner().to_def_id(),
+ &outlives_environment,
+ RegionckMode::default(),
+ );
+
+ debug!(?errors, "errors");
+
+ // If we were able to prove that the type outlives the region without
+ // an error, it must be because of the implied or explicit bounds...
+ errors.is_empty()
+ })
+}
+
+/// TypeVisitor that looks for uses of GATs like
+/// `<P0 as Trait<P1..Pn>>::GAT<Pn..Pm>` and adds the arguments `P0..Pm` into
+/// the two vectors, `regions` and `types` (depending on their kind). For each
+/// parameter `Pi` also track the index `i`.
+struct GATSubstCollector<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ gat: DefId,
+ // Which region appears and which parameter index its subsituted for
+ regions: FxHashSet<(ty::Region<'tcx>, usize)>,
+ // Which params appears and which parameter index its subsituted for
+ types: FxHashSet<(Ty<'tcx>, usize)>,
+}
+
+impl<'tcx> GATSubstCollector<'tcx> {
+ fn visit<T: TypeFoldable<'tcx>>(
+ tcx: TyCtxt<'tcx>,
+ gat: DefId,
+ t: T,
+ ) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) {
+ let mut visitor = GATSubstCollector {
+ tcx,
+ gat,
+ regions: FxHashSet::default(),
+ types: FxHashSet::default(),
+ };
+ t.visit_with(&mut visitor);
+ (visitor.regions, visitor.types)
+ }
+}
+
+impl<'tcx> TypeVisitor<'tcx> for GATSubstCollector<'tcx> {
+ type BreakTy = !;
+
+ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+ match t.kind() {
+ ty::Projection(p) if p.item_def_id == self.gat => {
+ for (idx, subst) in p.substs.iter().enumerate() {
+ match subst.unpack() {
+ GenericArgKind::Lifetime(lt) => {
+ self.regions.insert((lt, idx));
+ }
+ GenericArgKind::Type(t) => {
+ self.types.insert((t, idx));
+ }
+ _ => {}
+ }
+ }
+ }
+ _ => {}
+ }
+ t.super_visit_with(self)
+ }
+
+ fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
+ Some(self.tcx)
+ }
}
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
} else {
err.span_note(
tcx.hir().body(body_id).value.span,
- &format!("however, the inferred type `{}` cannot be named", ty.to_string()),
+ &format!("however, the inferred type `{}` cannot be named", ty),
);
}
}
} else {
diag.span_note(
tcx.hir().body(body_id).value.span,
- &format!("however, the inferred type `{}` cannot be named", ty.to_string()),
+ &format!("however, the inferred type `{}` cannot be named", ty),
);
}
}
#![feature(never_type)]
#![feature(slice_partition_dedup)]
#![feature(control_flow_enum)]
+#![feature(hash_drain_filter)]
#![recursion_limit = "256"]
#[macro_use]
hir::TyKind::Path(hir::QPath::Resolved(
None,
hir::Path { res: hir::def::Res::Def(_, id), .. },
- )) if *id == def_id => true,
+ )) => *id == def_id,
_ => false,
})
})
#![feature(extend_one)]
#![feature(fmt_internals)]
#![feature(fn_traits)]
+#![feature(inherent_ascii_escape)]
#![feature(inplace_iteration)]
#![feature(iter_advance_by)]
#![feature(iter_zip)]
#[stable(feature = "catch_unwind", since = "1.9.0")]
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Rc<T> {}
+#[stable(feature = "rc_ref_unwind_safe", since = "1.58.0")]
+impl<T: RefUnwindSafe + ?Sized> RefUnwindSafe for Rc<T> {}
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
pub use core::slice::ArrayChunksMut;
#[unstable(feature = "array_windows", issue = "75027")]
pub use core::slice::ArrayWindows;
+#[unstable(feature = "inherent_ascii_escape", issue = "77174")]
+pub use core::slice::EscapeAscii;
#[stable(feature = "slice_get_slice", since = "1.28.0")]
pub use core::slice::SliceIndex;
#[stable(feature = "from_ref", since = "1.28.0")]
pub use core::slice::{RSplit, RSplitMut};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut};
+#[stable(feature = "split_inclusive", since = "1.51.0")]
+pub use core::slice::{SplitInclusive, SplitInclusiveMut};
////////////////////////////////////////////////////////////////////////////////
// Basic slice extension methods
pub use core::str::EncodeUtf16;
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
pub use core::str::SplitAsciiWhitespace;
-#[stable(feature = "split_inclusive", since = "1.53.0")]
+#[stable(feature = "split_inclusive", since = "1.51.0")]
pub use core::str::SplitInclusive;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::str::SplitWhitespace;
#![feature(try_blocks)]
#![feature(unboxed_closures)]
#![feature(unsized_fn_params)]
+#![cfg_attr(not(bootstrap), feature(asm_const))]
//
// Target features:
#![feature(aarch64_target_feature)]
}
macro_rules! widening_impl {
- ($SelfT:ty, $WideT:ty, $BITS:literal) => {
+ ($SelfT:ty, $WideT:ty, $BITS:literal, unsigned) => {
+ widening_impl!($SelfT, $WideT, $BITS, "");
+ };
+ ($SelfT:ty, $WideT:ty, $BITS:literal, signed) => {
+ widening_impl!($SelfT, $WideT, $BITS, "# //");
+ };
+ ($SelfT:ty, $WideT:ty, $BITS:literal, $AdaptiveTestPrefix:literal) => {
/// Calculates the complete product `self * rhs` without the possibility to overflow.
///
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
/// assert_eq!(5u32.carrying_mul(2, 10), (20, 0));
/// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2));
/// assert_eq!(1_000_000_000u32.carrying_mul(10, 10), (1410065418, 2));
+ #[doc = concat!($AdaptiveTestPrefix, "assert_eq!(",
+ stringify!($SelfT), "::MAX.carrying_mul(", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX), ",
+ "(0, ", stringify!($SelfT), "::MAX));"
+ )]
+ /// ```
+ ///
+ /// If `carry` is zero, this is similar to [`overflowing_mul`](Self::overflowing_mul),
+ /// except that it gives the value of the overflow instead of just whether one happened:
+ ///
+ /// ```
+ /// #![feature(bigint_helper_methods)]
+ /// let r = u8::carrying_mul(7, 13, 0);
+ /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(7, 13));
+ /// let r = u8::carrying_mul(13, 42, 0);
+ /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(13, 42));
+ /// ```
+ ///
+ /// The value of the first field in the returned tuple matches what you'd get
+ /// by combining the [`wrapping_mul`](Self::wrapping_mul) and
+ /// [`wrapping_add`](Self::wrapping_add) methods:
+ ///
+ /// ```
+ /// #![feature(bigint_helper_methods)]
+ /// assert_eq!(
+ /// 789_u16.carrying_mul(456, 123).0,
+ /// 789_u16.wrapping_mul(456).wrapping_add(123),
+ /// );
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
#[lang = "i8"]
impl i8 {
- widening_impl! { i8, i16, 8 }
int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
"[0x12]", "[0x12]", "", "" }
+ widening_impl! { i8, i16, 8, signed }
}
#[lang = "i16"]
impl i16 {
- widening_impl! { i16, i32, 16 }
int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
"0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
+ widening_impl! { i16, i32, 16, signed }
}
#[lang = "i32"]
impl i32 {
- widening_impl! { i32, i64, 32 }
int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
"[0x12, 0x34, 0x56, 0x78]", "", "" }
+ widening_impl! { i32, i64, 32, signed }
}
#[lang = "i64"]
impl i64 {
- widening_impl! { i64, i128, 64 }
int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12,
"0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
"0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" }
+ widening_impl! { i64, i128, 64, signed }
}
#[lang = "i128"]
#[cfg(target_pointer_width = "16")]
#[lang = "isize"]
impl isize {
- widening_impl! { isize, i32, 16 }
int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234",
"0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+ widening_impl! { isize, i32, 16, signed }
}
#[cfg(target_pointer_width = "32")]
#[lang = "isize"]
impl isize {
- widening_impl! { isize, i64, 32 }
int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
"[0x12, 0x34, 0x56, 0x78]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+ widening_impl! { isize, i64, 32, signed }
}
#[cfg(target_pointer_width = "64")]
#[lang = "isize"]
impl isize {
- widening_impl! { isize, i128, 64 }
int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807,
12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
- "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
- "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
- usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+ "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
+ "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+ usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+ widening_impl! { isize, i128, 64, signed }
}
/// If 6th bit set ascii is upper case.
#[lang = "u8"]
impl u8 {
- widening_impl! { u8, u16, 8 }
uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
"[0x12]", "", "" }
+ widening_impl! { u8, u16, 8, unsigned }
/// Checks if the value is within the ASCII range.
///
#[lang = "u16"]
impl u16 {
- widening_impl! { u16, u32, 16 }
uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
"[0x34, 0x12]", "[0x12, 0x34]", "", "" }
+ widening_impl! { u16, u32, 16, unsigned }
}
#[lang = "u32"]
impl u32 {
- widening_impl! { u32, u64, 32 }
uint_impl! { u32, u32, i32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
+ widening_impl! { u32, u64, 32, unsigned }
}
#[lang = "u64"]
impl u64 {
- widening_impl! { u64, u128, 64 }
uint_impl! { u64, u64, i64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
"", ""}
+ widening_impl! { u64, u128, 64, unsigned }
}
#[lang = "u128"]
#[cfg(target_pointer_width = "16")]
#[lang = "usize"]
impl usize {
- widening_impl! { usize, u32, 16 }
uint_impl! { usize, u16, isize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
"[0x34, 0x12]", "[0x12, 0x34]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+ widening_impl! { usize, u32, 16, unsigned }
}
#[cfg(target_pointer_width = "32")]
#[lang = "usize"]
impl usize {
- widening_impl! { usize, u64, 32 }
uint_impl! { usize, u32, isize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+ widening_impl! { usize, u64, 32, unsigned }
}
#[cfg(target_pointer_width = "64")]
#[lang = "usize"]
impl usize {
- widening_impl! { usize, u128, 64 }
uint_impl! { usize, u64, isize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
- "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
+ "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
+ widening_impl! { usize, u128, 64, unsigned }
}
/// A classification of floating point numbers.
/// additional bit of overflow. This allows for chaining together multiple additions
/// to create "big integers" which represent larger values.
///
+ #[doc = concat!("This can be thought of as a ", stringify!($BITS), "-bit \"full adder\", in the electronics sense.")]
+ ///
/// # Examples
///
/// Basic usage
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (0, true));")]
+ #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(0, true), (0, true));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (1, true));")]
+ #[doc = concat!("assert_eq!(",
+ stringify!($SelfT), "::MAX.carrying_add(", stringify!($SelfT), "::MAX, true), ",
+ "(", stringify!($SelfT), "::MAX, true));"
+ )]
+ /// ```
+ ///
+ /// If `carry` is false, this method is equivalent to [`overflowing_add`](Self::overflowing_add):
+ ///
+ /// ```
+ /// #![feature(bigint_helper_methods)]
+ #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".carrying_add(2, false), 5_", stringify!($SelfT), ".overflowing_add(2));")]
+ #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), ", stringify!($SelfT), "::MAX.overflowing_add(1));")]
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
//! assert_eq!(s.find("you"), Some(4));
//! // char pattern
//! assert_eq!(s.find('n'), Some(2));
+//! // array of chars pattern
+//! assert_eq!(s.find(&['a', 'e', 'i', 'o', 'u']), Some(1));
//! // slice of chars pattern
//! assert_eq!(s.find(&['a', 'e', 'i', 'o', 'u'][..]), Some(1));
//! // closure pattern
/// assert_eq!("abaaa".find('b'), Some(1));
/// assert_eq!("abaaa".find('c'), None);
///
+/// // &[char; N]
+/// assert_eq!("ab".find(&['b', 'a']), Some(0));
+/// assert_eq!("abaaa".find(&['a', 'z']), Some(0));
+/// assert_eq!("abaaa".find(&['c', 'd']), None);
+///
/// // &[char]
/// assert_eq!("ab".find(&['b', 'a'][..]), Some(0));
/// assert_eq!("abaaa".find(&['a', 'z'][..]), Some(0));
}
}
+impl<const N: usize> MultiCharEq for [char; N] {
+ #[inline]
+ fn matches(&mut self, c: char) -> bool {
+ self.iter().any(|&m| m == c)
+ }
+}
+
+impl<const N: usize> MultiCharEq for &[char; N] {
+ #[inline]
+ fn matches(&mut self, c: char) -> bool {
+ self.iter().any(|&m| m == c)
+ }
+}
+
impl MultiCharEq for &[char] {
#[inline]
fn matches(&mut self, c: char) -> bool {
};
}
+/// Associated type for `<[char; N] as Pattern<'a>>::Searcher`.
+#[derive(Clone, Debug)]
+pub struct CharArraySearcher<'a, const N: usize>(
+ <MultiCharEqPattern<[char; N]> as Pattern<'a>>::Searcher,
+);
+
+/// Associated type for `<&[char; N] as Pattern<'a>>::Searcher`.
+#[derive(Clone, Debug)]
+pub struct CharArrayRefSearcher<'a, 'b, const N: usize>(
+ <MultiCharEqPattern<&'b [char; N]> as Pattern<'a>>::Searcher,
+);
+
+/// Searches for chars that are equal to any of the [`char`]s in the array.
+///
+/// # Examples
+///
+/// ```
+/// assert_eq!("Hello world".find(['l', 'l']), Some(2));
+/// assert_eq!("Hello world".find(['l', 'l']), Some(2));
+/// ```
+impl<'a, const N: usize> Pattern<'a> for [char; N] {
+ pattern_methods!(CharArraySearcher<'a, N>, MultiCharEqPattern, CharArraySearcher);
+}
+
+unsafe impl<'a, const N: usize> Searcher<'a> for CharArraySearcher<'a, N> {
+ searcher_methods!(forward);
+}
+
+unsafe impl<'a, const N: usize> ReverseSearcher<'a> for CharArraySearcher<'a, N> {
+ searcher_methods!(reverse);
+}
+
+/// Searches for chars that are equal to any of the [`char`]s in the array.
+///
+/// # Examples
+///
+/// ```
+/// assert_eq!("Hello world".find(&['l', 'l']), Some(2));
+/// assert_eq!("Hello world".find(&['l', 'l']), Some(2));
+/// ```
+impl<'a, 'b, const N: usize> Pattern<'a> for &'b [char; N] {
+ pattern_methods!(CharArrayRefSearcher<'a, 'b, N>, MultiCharEqPattern, CharArrayRefSearcher);
+}
+
+unsafe impl<'a, 'b, const N: usize> Searcher<'a> for CharArrayRefSearcher<'a, 'b, N> {
+ searcher_methods!(forward);
+}
+
+unsafe impl<'a, 'b, const N: usize> ReverseSearcher<'a> for CharArrayRefSearcher<'a, 'b, N> {
+ searcher_methods!(reverse);
+}
+
/////////////////////////////////////////////////////////////////////////////
// Impl for &[char]
/////////////////////////////////////////////////////////////////////////////
if !n.is_finite() {
panic!("Invalid float literal {}", n);
}
- Literal(bridge::client::Literal::float(&n.to_string()))
+ let mut repr = n.to_string();
+ if !repr.contains('.') {
+ repr.push_str(".0");
+ }
+ Literal(bridge::client::Literal::float(&repr))
}
/// Creates a new suffixed floating-point literal.
if !n.is_finite() {
panic!("Invalid float literal {}", n);
}
- Literal(bridge::client::Literal::float(&n.to_string()))
+ let mut repr = n.to_string();
+ if !repr.contains('.') {
+ repr.push_str(".0");
+ }
+ Literal(bridge::client::Literal::float(&repr))
}
/// Creates a new suffixed floating-point literal.
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
-libc = { version = "0.2.103", default-features = false, features = ['rustc-dep-of-std'] }
+libc = { version = "0.2.106", default-features = false, features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "0.1.44" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
#[must_use]
#[inline]
pub const fn is_documentation(&self) -> bool {
- match self.octets() {
- [192, 0, 2, _] => true,
- [198, 51, 100, _] => true,
- [203, 0, 113, _] => true,
- _ => false,
- }
+ matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _])
}
/// Converts this address to an [IPv4-compatible] [`IPv6` address].
#[unstable(feature = "c_size_t", issue = "88345")]
pub type c_size_t = usize;
-/// Equivalent to C's `ssize_t` type, from `stddef.h` (or `cstddef` for C++).
+/// Equivalent to C's `ptrdiff_t` type, from `stddef.h` (or `cstddef` for C++).
+///
+/// This type is currently always [`isize`], however in the future there may be
+/// platforms where this is not the case.
+#[unstable(feature = "c_size_t", issue = "88345")]
+pub type c_ptrdiff_t = isize;
+
+/// Equivalent to C's `ssize_t` (on POSIX) or `SSIZE_T` (on Windows) type.
///
/// This type is currently always [`isize`], however in the future there may be
/// platforms where this is not the case.
#[must_use]
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn is_unnamed(&self) -> bool {
- if let AddressKind::Unnamed = self.address() { true } else { false }
+ matches!(self.address(), AddressKind::Unnamed)
}
/// Returns the contents of this address if it is a `pathname` address.
unsafe { crate::hint::unreachable_unchecked() };
}
-pub fn available_concurrency() -> io::Result<crate::num::NonZeroUsize> {
+pub fn available_parallelism() -> io::Result<crate::num::NonZeroUsize> {
super::unsupported()
}
target_os = "solaris",
target_os = "illumos",
))] {
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ {
+ let mut set: libc::cpu_set_t = unsafe { mem::zeroed() };
+ if unsafe { libc::sched_getaffinity(0, mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
+ let count = unsafe { libc::CPU_COUNT(&set) };
+ return Ok(unsafe { NonZeroUsize::new_unchecked(count as usize) });
+ }
+ }
match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } {
-1 => Err(io::Error::last_os_error()),
0 => Err(io::Error::new_const(io::ErrorKind::NotFound, &"The number of hardware threads is not known for the target platform")),
+//! Implements thread-local destructors that are not associated with any
+//! particular data.
+
#![unstable(feature = "thread_local_internals", issue = "none")]
#![cfg(target_thread_local)]
-pub use crate::sys_common::thread_local_dtor::register_dtor_fallback as register_dtor;
+// Using a per-thread list avoids the problems in synchronizing global state.
+#[thread_local]
+static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();
+
+pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
+ DESTRUCTORS.push((t, dtor));
+}
+
+/// Runs destructors. This should not be called until thread exit.
+pub unsafe fn run_keyless_dtors() {
+ // Drop all the destructors.
+ //
+ // Note: While this is potentially an infinite loop, it *should* be
+ // the case that this loop always terminates because we provide the
+ // guarantee that a TLS key cannot be set after it is flagged for
+ // destruction.
+ while let Some((ptr, dtor)) = DESTRUCTORS.pop() {
+ (dtor)(ptr);
+ }
+ // We're done so free the memory.
+ DESTRUCTORS = Vec::new();
+}
unsafe extern "system" fn on_tls_callback(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID) {
if dwReason == c::DLL_THREAD_DETACH || dwReason == c::DLL_PROCESS_DETACH {
run_dtors();
+ #[cfg(target_thread_local)]
+ super::thread_local_dtor::run_keyless_dtors();
}
// See comments above for what this is doing. Note that we don't need this
pub fn join(mut self) -> Result<T> {
self.0.join()
}
+
+ /// Checks if the the associated thread is still running its main function.
+ ///
+ /// This might return `false` for a brief moment after the thread's main
+ /// function has returned, but before the thread itself has stopped running.
+ #[unstable(feature = "thread_is_running", issue = "90470")]
+ pub fn is_running(&self) -> bool {
+ Arc::strong_count(&self.0.packet.0) > 1
+ }
}
impl<T> AsInner<imp::Thread> for JoinHandle<T> {
use crate::any::Any;
use crate::mem;
use crate::result;
-use crate::sync::mpsc::{channel, Sender};
+use crate::sync::{
+ mpsc::{channel, Sender},
+ Arc, Barrier,
+};
use crate::thread::{self, ThreadId};
use crate::time::Duration;
+use crate::time::Instant;
// !!! These tests are dangerous. If something is buggy, they will hang, !!!
// !!! instead of exiting cleanly. This might wedge the buildbots. !!!
rx.recv().unwrap();
}
+#[test]
+fn test_is_running() {
+ let b = Arc::new(Barrier::new(2));
+ let t = thread::spawn({
+ let b = b.clone();
+ move || {
+ b.wait();
+ 1234
+ }
+ });
+
+ // Thread is definitely running here, since it's still waiting for the barrier.
+ assert_eq!(t.is_running(), true);
+
+ // Unblock the barrier.
+ b.wait();
+
+ // Now check that t.is_running() becomes false within a reasonable time.
+ let start = Instant::now();
+ while t.is_running() {
+ assert!(start.elapsed() < Duration::from_secs(2));
+ thread::sleep(Duration::from_millis(15));
+ }
+
+ // Joining the thread should not block for a significant time now.
+ let join_time = Instant::now();
+ assert_eq!(t.join().unwrap(), 1234);
+ assert!(join_time.elapsed() < Duration::from_secs(2));
+}
+
#[test]
fn test_join_panic() {
match thread::spawn(move || panic!()).join() {
_stdout: &[u8],
_state: &ConsoleTestState,
) -> io::Result<()> {
- // Because the testsuit node holds some of the information as attributes, we can't write it
- // until all of the tests has ran. Instead of writting every result as they come in, we add
+ // Because the testsuite node holds some of the information as attributes, we can't write it
+ // until all of the tests have finished. Instead of writing every result as they come in, we add
// them to a Vec and write them all at once when run is complete.
let duration = exec_time.map(|t| t.0).unwrap_or_default();
self.results.push((desc.clone(), result.clone(), duration));
if self.git_version >= distutils.version.LooseVersion("2.11.0"):
update_args.append("--progress")
update_args.append(module)
- run(update_args, cwd=self.rust_root, verbose=self.verbose, exception=True)
+ try:
+ run(update_args, cwd=self.rust_root, verbose=self.verbose, exception=True)
+ except RuntimeError:
+ print("Failed updating submodule. This is probably due to uncommitted local changes.")
+ print('Either stash the changes by running "git stash" within the submodule\'s')
+ print('directory, reset them by running "git reset --hard", or commit them.')
+ print("To reset all submodules' changes run", end=" ")
+ print('"git submodule foreach --recursive git reset --hard".')
+ raise SystemExit(1)
run(["git", "reset", "-q", "--hard"],
cwd=module_path, verbose=self.verbose)
doc::RustByExample,
doc::RustcBook,
doc::CargoBook,
+ doc::Clippy,
doc::EmbeddedBook,
doc::EditionGuide,
),
t!(fs::create_dir_all(&libdir_self_contained));
let mut target_deps = vec![];
- // Copies the CRT objects.
+ // Copies the libc and CRT objects.
//
// rustc historically provides a more self-contained installation for musl targets
// not requiring the presence of a native musl toolchain. For example, it can fall back
let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
});
- for &obj in &["crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
+ for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
copy_and_stamp(
builder,
&libdir_self_contained,
panic!("Target {:?} does not have a \"wasi-root\" key", target.triple)
})
.join("lib/wasm32-wasi");
- for &obj in &["crt1-command.o", "crt1-reactor.o"] {
+ for &obj in &["libc.a", "crt1-command.o", "crt1-reactor.o"] {
copy_and_stamp(
builder,
&libdir_self_contained,
"src/tools/rustfmt",
["rustfmt-nightly", "rustfmt-config_proc_macro"],
);
+tool_doc!(Clippy, "clippy", "src/tools/clippy", ["clippy_utils"]);
#[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct ErrorIndex {
+# We need recent curl, OpenSSL and CA certificates, so we can download further
+# dependencies in the debian:6 image. We use an ubuntu 20.04 image download
+# those.
+FROM ubuntu:20.04
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ curl \
+ ca-certificates
+WORKDIR /tmp
+COPY host-x86_64/dist-x86_64-linux/download-openssl-curl.sh /tmp/
+RUN ./download-openssl-curl.sh
+
# We use Debian 6 (glibc 2.11, kernel 2.6.32) as a common base for other
# distros that still need Rust support: RHEL 6 (glibc 2.12, kernel 2.6.32) and
# SLES 11 SP4 (glibc 2.11, kernel 3.0).
apt-get install --allow-unauthenticated -y --no-install-recommends \
automake \
bzip2 \
- ca-certificates \
- curl \
file \
g++ \
g++-multilib \
xz-utils \
zlib1g-dev
-# Install new Let's Encrypt root CA certificate and remove the expired one.
-COPY host-x86_64/shared/ISRG_Root_X1.crt /usr/local/share/ca-certificates/ISRG_Root_X1.crt
-RUN sed -i '/mozilla\/DST_Root_CA_X3\.crt/d' /etc/ca-certificates.conf
-RUN /usr/sbin/update-ca-certificates
-
ENV PATH=/rustroot/bin:$PATH
ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib
ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig
# static.rust-lang.org. This'll be used to link into libcurl below (and used
# later as well), so build a copy of OpenSSL with dynamic libraries into our
# generic root.
+COPY --from=0 /tmp/openssl.tar.gz /tmp/openssl.tar.gz
COPY host-x86_64/dist-x86_64-linux/build-openssl.sh /tmp/
RUN ./build-openssl.sh
#
# Note that we also disable a bunch of optional features of curl that we don't
# really need.
+COPY --from=0 /tmp/curl.tar.xz /tmp/curl.tar.xz
COPY host-x86_64/dist-x86_64-linux/build-curl.sh /tmp/
-RUN ./build-curl.sh && apt-get remove -y curl
+RUN ./build-curl.sh
+
+# Use up-to-date curl CA bundle
+COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem
+ENV CURL_CA_BUNDLE /tmp/cacert.pem
# binutils < 2.22 has a bug where the 32-bit executables it generates
# immediately segfault in Rust, so we need to install our own binutils.
+# We need recent curl, OpenSSL and CA certificates, so we can download further
+# dependencies in the debian:6 image. We use an ubuntu 20.04 image download
+# those.
+FROM ubuntu:20.04
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ curl \
+ ca-certificates
+WORKDIR /tmp
+COPY host-x86_64/dist-x86_64-linux/download-openssl-curl.sh /tmp/
+RUN ./download-openssl-curl.sh
+
# We use Debian 6 (glibc 2.11, kernel 2.6.32) as a common base for other
# distros that still need Rust support: RHEL 6 (glibc 2.12, kernel 2.6.32) and
# SLES 11 SP4 (glibc 2.11, kernel 3.0).
apt-get install --allow-unauthenticated -y --no-install-recommends \
automake \
bzip2 \
- ca-certificates \
- curl \
file \
g++ \
g++-multilib \
xz-utils \
zlib1g-dev
-# Install new Let's Encrypt root CA certificate and remove the expired one.
-COPY host-x86_64/shared/ISRG_Root_X1.crt /usr/local/share/ca-certificates/ISRG_Root_X1.crt
-RUN sed -i '/mozilla\/DST_Root_CA_X3\.crt/d' /etc/ca-certificates.conf
-RUN /usr/sbin/update-ca-certificates
-
ENV PATH=/rustroot/bin:$PATH
ENV LD_LIBRARY_PATH=/rustroot/lib64:/rustroot/lib32:/rustroot/lib
ENV PKG_CONFIG_PATH=/rustroot/lib/pkgconfig
# static.rust-lang.org. This'll be used to link into libcurl below (and used
# later as well), so build a copy of OpenSSL with dynamic libraries into our
# generic root.
+COPY --from=0 /tmp/openssl.tar.gz /tmp/openssl.tar.gz
COPY host-x86_64/dist-x86_64-linux/build-openssl.sh /tmp/
RUN ./build-openssl.sh
#
# Note that we also disable a bunch of optional features of curl that we don't
# really need.
+COPY --from=0 /tmp/curl.tar.xz /tmp/curl.tar.xz
COPY host-x86_64/dist-x86_64-linux/build-curl.sh /tmp/
-RUN ./build-curl.sh && apt-get remove -y curl
+RUN ./build-curl.sh
+
+# Use up-to-date curl CA bundle
+COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem
+ENV CURL_CA_BUNDLE /tmp/cacert.pem
# binutils < 2.22 has a bug where the 32-bit executables it generates
# immediately segfault in Rust, so we need to install our own binutils.
set -ex
source shared.sh
-VERSION=7.66.0
-
-# This needs to be downloaded directly from S3, it can't go through the CDN.
-# That's because the CDN is backed by CloudFront, which requires SNI and TLSv1
-# (without paying an absurd amount of money).
-curl https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/curl-$VERSION.tar.xz \
- | xz --decompress \
- | tar xf -
+tar xJf curl.tar.xz
mkdir curl-build
cd curl-build
-hide_output ../curl-$VERSION/configure \
+hide_output ../curl-*/configure \
--prefix=/rustroot \
--with-ssl=/rustroot \
--disable-sspi \
cd ..
rm -rf curl-build
-rm -rf curl-$VERSION
+rm -rf curl-*
set -ex
source shared.sh
-VERSION=1.0.2k
+tar xzf openssl.tar.gz
-# This needs to be downloaded directly from S3, it can't go through the CDN.
-# That's because the CDN is backed by CloudFront, which requires SNI and TLSv1
-# (without paying an absurd amount of money).
-URL=https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/openssl-$VERSION.tar.gz
-
-curl $URL | tar xzf -
-
-cd openssl-$VERSION
+cd openssl-*
hide_output ./config --prefix=/rustroot shared -fPIC
hide_output make -j$(nproc)
hide_output make install
cd ..
-rm -rf openssl-$VERSION
+rm -rf openssl-*
# Make the system cert collection available to the new install.
ln -nsf /etc/pki/tls/cert.pem /rustroot/ssl/
--- /dev/null
+#!/usr/bin/env bash
+
+set -ex
+
+OPENSSL_VERSION=1.0.2k
+CURL_VERSION=7.66.0
+
+curl -f https://ci-mirrors.rust-lang.org/rustc/openssl-$OPENSSL_VERSION.tar.gz -o openssl.tar.gz
+curl -f https://ci-mirrors.rust-lang.org/rustc/curl-$CURL_VERSION.tar.xz -o curl.tar.xz
+curl -f https://curl.se/ca/cacert.pem -o cacert.pem
+++ /dev/null
------BEGIN CERTIFICATE-----
-MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
-TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
-cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
-WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
-ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
-MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
-h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
-0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
-A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
-T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
-B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
-B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
-KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
-OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
-jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
-qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
-rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
-HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
-hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
-ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
-3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
-NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
-ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
-TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
-jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
-oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
-4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
-mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
-emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
------END CERTIFICATE-----
# Look for all source files involves in the COPY command
copied_files=/tmp/.docker-copied-files.txt
rm -f "$copied_files"
- for i in $(sed -n -e 's/^COPY \(.*\) .*$/\1/p' "$docker_dir/$image/Dockerfile"); do
+ for i in $(sed -n -e '/^COPY --from=/! s/^COPY \(.*\) .*$/\1/p' \
+ "$docker_dir/$image/Dockerfile"); do
# List the file names
find "$script_dir/$i" -type f >> $copied_files
done
for lib in c cxxrt gcc_s m thr util; do
files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*")
done
-for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat; do
+for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat kvm; do
files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*")
done
- [Platform Support](platform-support.md)
- [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md)
- [\*-kmc-solid_\*](platform-support/kmc-solid.md)
+ - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
- [Target Tier Policy](target-tier-policy.md)
- [Targets](targets/index.md)
- [Built-in Targets](targets/built-in.md)
`x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
`x86_64-unknown-hermit` | ? | |
`x86_64-unknown-l4re-uclibc` | ? | |
+[`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | | Freestanding/bare-metal x86_64, softfloat
`x86_64-unknown-none-hermitkernel` | ? | | HermitCore kernel
`x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules
`x86_64-unknown-openbsd` | ✓ | ✓ | 64-bit OpenBSD
--- /dev/null
+# `x86_64-unknown-none`
+
+**Tier: 3**
+
+Freestanding/bare-metal x86-64 binaries in ELF format: firmware, kernels, etc.
+
+## Target maintainers
+
+- Harald Hoyer `harald@profian.com`, https://github.com/haraldh
+- Mike Leany, https://github.com/mikeleany
+
+## Requirements
+
+This target is cross-compiled. There is no support for `std`. There is no
+default allocator, but it's possible to use `alloc` by supplying an allocator.
+
+By default, Rust code generated for this target does not use any vector or
+floating-point registers (e.g. SSE, AVX). This allows the generated code to run
+in environments, such as kernels, which may need to avoid the use of such
+registers or which may have special considerations about the use of such
+registers (e.g. saving and restoring them to avoid breaking userspace code
+using the same registers). You can change code generation to use additional CPU
+features via the `-C target-feature=` codegen options to rustc, or via the
+`#[target_feature]` mechanism within Rust code.
+
+By default, code generated with this target should run on any `x86_64`
+hardware; enabling additional target features may raise this baseline.
+
+Code generated with this target will use the `kernel` code model by default.
+You can change this using the `-C code-model=` option to rustc.
+
+On `x86_64-unknown-none`, `extern "C"` uses the [standard System V calling
+convention](https://gitlab.com/x86-psABIs/x86-64-ABI), without red zones.
+
+This target generated binaries in the ELF format. Any alternate formats or
+special considerations for binary layout will require linker options or linker
+scripts.
+
+## Building the target
+
+You can build Rust with support for the target by adding it to the `target`
+list in `config.toml`:
+
+```toml
+[build]
+build-stage = 1
+target = ["x86_64-unknown-none"]
+```
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for
+this target, you will either need to build Rust with the target enabled (see
+"Building the target" above), or build your own copy of `core` by using
+`build-std` or similar.
+
+## Testing
+
+As `x86_64-unknown-none` supports a variety of different environments and does
+not support `std`, this target does not support running the Rust testsuite.
+
+## Cross-compilation toolchains and C code
+
+If you want to compile C code along with Rust (such as for Rust crates with C
+dependencies), you will need an appropriate `x86_64` toolchain.
+
+Rust *may* be able to use an `x86_64-linux-gnu-` toolchain with appropriate
+standalone flags to build for this toolchain (depending on the assumptions of
+that toolchain, see below), or you may wish to use a separate
+`x86_64-unknown-none` (or `x86_64-elf-`) toolchain.
+
+On some `x86_64` hosts that use ELF binaries, you *may* be able to use the host
+C toolchain, if it does not introduce assumptions about the host environment
+that don't match the expectations of a standalone environment. Otherwise, you
+may need a separate toolchain for standalone/freestanding development, just as
+when cross-compiling from a non-`x86_64` platform.
# The Rustdoc Book
- [What is rustdoc?](what-is-rustdoc.md)
+- [How to read rustdoc output](how-to-read-rustdoc.md)
- [How to write documentation](how-to-write-documentation.md)
- [What to include (and exclude)](what-to-include.md)
- [Command-line arguments](command-line-arguments.md)
--- /dev/null
+# How to read rustdoc output
+
+Rustdoc's HTML output includes a friendly and useful navigation interface which
+makes it easier for users to navigate and understand your code.
+This chapter covers the major features of that interface,
+and is a great starting point for documentation authors and users alike.
+
+## Structure
+
+The `rustdoc` output is divided into three sections.
+Along the left side of each page is a quick navigation bar,
+which shows contextual information about the current entry.
+The rest of the page is taken up by the search interface at the top
+and the documentation for the current item below that.
+
+## The Item Documentation
+
+The majority of the screen is taken up with the documentation text for the item
+currently being viewed.
+At the top is some at-a-glance info and controls:
+
+- the type and name of the item,
+ such as "Struct `std::time::Duration`",
+- a button to copy the item's path to the clipboard,
+ which is a clipboard item
+- a button to collapse or expand the top-level documentation for that item
+ (`[+]` or `[-]`),
+- a link to the source code (`[src]`),
+ if [configured](the-doc-attribute.html#html_no_source),
+ and present (the source may not be available if
+ the documentation was created with `cargo doc --no-deps`),
+- and the version in which the item became stable,
+ if it's a stable item in the standard library.
+
+Below this is the main documentation for the item,
+including a definition or function signature if appropriate,
+followed by a list of fields or variants for Rust types.
+Finally, the page lists associated functions and trait implementations,
+including automatic and blanket implementations that `rustdoc` knows about.
+
+### Navigation
+
+Subheadings, variants, fields, and many other things in this documentation
+are anchors and can be clicked on and deep-linked to,
+which is a great way to communicate exactly what you're talking about.
+The typograpical character "§" appears next to lines with anchors on them
+when hovered or given keyboard focus.
+
+## The Navigation Bar
+
+For example, when looking at documentation for the crate root,
+it shows all the crates documented in the documentation bundle,
+and quick links to the modules, structs, traits, functions, and macros available
+from the current crate.
+At the top, it displays a [configurable logo](the-doc-attribute.html#html_logo_url)
+alongside the current crate's name and version,
+or the current item whose documentation is being displayed.
+
+## The Theme Picker and Search Interface
+
+When viewing `rustdoc`'s output in a browser with JavaScript enabled,
+a dynamic interface appears at the top of the page.
+To the left is the theme picker, denoted with a paint-brush icon,
+and the search interface, help screen, and options appear to the right of that.
+
+### The Theme Picker
+
+Clicking on the theme picker provides a list of themes -
+by default `ayu`, `light`, and `dark` -
+which are available for viewing.
+
+### The Search Interface
+
+Typing in the search bar instantly searches the available documentation for
+the string entered with a fuzzy matching algorithm that is tolerant of minor
+typos.
+
+By default, the search results give are "In Names",
+meaning that the fuzzy match is made against the names of items.
+Matching names are shown on the left, and the first few words of their
+descriptions are given on the right.
+By clicking an item, you will navigate to its particular documentation.
+
+There are two other sets of results, shown as tabs in the search results pane.
+"In Parameters" shows matches for the string in the types of parameters to
+functions, and "In Return Types" shows matches in the return types of functions.
+Both are very useful when looking for a function whose name you can't quite
+bring to mind when you know the type you have or want.
+
+When typing in the search bar, you can prefix your search term with a type
+followed by a colon (such as `mod:`) to restrict the results to just that
+kind of item. (The available items are listed in the help popup.)
+
+### Shortcuts
+
+Pressing `S` while focused elsewhere on the page will move focus to the
+search bar, and pressing `?` shows the help screen,
+which includes all these shortcuts and more.
+Pressing `T` focuses the theme picker.
+
+When the search results are focused,
+the left and right arrows move between tabs and the up and down arrows move
+among the results.
+Pressing the enter or return key opens the highlighted result.
+
+When looking at the documentation for an item, the plus and minus keys expand
+and collapse all sections in the document.
## Document primitives
+This is for Rust compiler internal use only.
+
Since primitive types are defined in the compiler, there's no place to attach documentation
-attributes. The `#[doc(primitive)]` attribute is used by the standard library to provide a way to generate
-documentation for primitive types, and requires `#![feature(doc_primitive)]` to enable.
+attributes. The `#[doc(primitive)]` attribute is used by the standard library to provide a way
+to generate documentation for primitive types, and requires `#![feature(doc_primitive)]` to enable.
+
+## Document keywords
+
+This is for Rust compiler internal use only.
+
+Rust keywords are documented in the standard library (look for `match` for example).
+
+To do so, the `#[doc(keyword = "...")]` attribute is used. Example:
+
+```rust
+#![feature(doc_keyword)]
+
+/// Some documentation about the keyword.
+#[doc(keyword = "keyword")]
+mod empty_mod {}
+```
## Unstable command-line arguments
}
println!(
- "L1 Cache: {}",
+ "L0 Cache: {}",
((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1)
);
```
- You are responsible for switching any target-specific state (e.g. thread-local storage, stack bounds).
- The set of memory locations that you may access is the intersection of those allowed by the `asm!` blocks you entered and exited.
- You cannot assume that an `asm!` block will appear exactly once in the output binary. The compiler is allowed to instantiate multiple copies of the `asm!` block, for example when the function containing it is inlined in multiple places.
+- On x86, inline assembly must not end with an instruction prefix (such as `LOCK`) that would apply to instructions generated by the compiler.
+ - The compiler is currently unable to detect this due to the way inline assembly is compiled, but may catch and reject this in the future.
> **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call.
constants defined in Rust to be used in assembly code:
```rust,no_run
-#![feature(global_asm)]
+#![feature(global_asm, asm_const)]
# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
# mod x86 {
const C: i32 = 1234;
arguments list:
```rust,no_run
-#![feature(global_asm)]
+#![feature(global_asm, asm_const)]
# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
# mod x86 {
global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
new_generics
});
- let negative_polarity;
+ let polarity;
let new_generics = match result {
AutoTraitResult::PositiveImpl(new_generics) => {
- negative_polarity = false;
+ polarity = ty::ImplPolarity::Positive;
if discard_positive_impl {
return None;
}
new_generics
}
AutoTraitResult::NegativeImpl => {
- negative_polarity = true;
+ polarity = ty::ImplPolarity::Negative;
// For negative impls, we use the generic params, but *not* the predicates,
// from the original type. Otherwise, the displayed impl appears to be a
visibility: Inherited,
def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
kind: box ImplItem(Impl {
- span: Span::dummy(),
unsafety: hir::Unsafety::Normal,
generics: new_generics,
trait_: Some(trait_ref.clean(self.cx)),
for_: ty.clean(self.cx),
items: Vec::new(),
- negative_polarity,
- synthetic: true,
- blanket_impl: None,
+ polarity,
+ kind: ImplKind::Auto,
}),
cfg: None,
})
visibility: Inherited,
def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
kind: box ImplItem(Impl {
- span: Span::new(self.cx.tcx.def_span(impl_def_id)),
unsafety: hir::Unsafety::Normal,
generics: (
self.cx.tcx.generics_of(impl_def_id),
.tcx
.associated_items(impl_def_id)
.in_definition_order()
- .collect::<Vec<_>>()
- .clean(self.cx),
- negative_polarity: false,
- synthetic: false,
- blanket_impl: Some(box trait_ref.self_ty().clean(self.cx)),
+ .map(|x| x.clean(self.cx))
+ .collect::<Vec<_>>(),
+ polarity: ty::ImplPolarity::Positive,
+ kind: ImplKind::Blanket(box trait_ref.self_ty().clean(self.cx)),
}),
cfg: None,
});
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
-use crate::clean::{self, utils, Attributes, AttributesExt, ItemId, NestedAttributesExt, Type};
+use crate::clean::{
+ self, utils, Attributes, AttributesExt, ImplKind, ItemId, NestedAttributesExt, Type,
+};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
clean::Enum {
generics: (cx.tcx.generics_of(did), predicates).clean(cx),
variants_stripped: false,
- variants: cx.tcx.adt_def(did).variants.clean(cx),
+ variants: cx.tcx.adt_def(did).variants.iter().map(|v| v.clean(cx)).collect(),
}
}
clean::Struct {
struct_type: variant.ctor_kind,
generics: (cx.tcx.generics_of(did), predicates).clean(cx),
- fields: variant.fields.clean(cx),
+ fields: variant.fields.iter().map(|x| x.clean(cx)).collect(),
fields_stripped: false,
}
}
let predicates = cx.tcx.explicit_predicates_of(did);
let variant = cx.tcx.adt_def(did).non_enum_variant();
- clean::Union {
- generics: (cx.tcx.generics_of(did), predicates).clean(cx),
- fields: variant.fields.clean(cx),
- fields_stripped: false,
- }
+ let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
+ let fields = variant.fields.iter().map(|x| x.clean(cx)).collect();
+ clean::Union { generics, fields, fields_stripped: false }
}
fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::Typedef {
),
};
let polarity = tcx.impl_polarity(did);
- let trait_ = associated_trait.clean(cx);
+ let trait_ = associated_trait.map(|t| t.clean(cx));
if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
super::build_deref_target_impls(cx, &trait_items, ret);
}
did,
None,
clean::ImplItem(clean::Impl {
- span: clean::types::rustc_span(did, cx.tcx),
unsafety: hir::Unsafety::Normal,
generics,
trait_,
for_,
items: trait_items,
- negative_polarity: polarity.clean(cx),
- synthetic: false,
- blanket_impl: None,
+ polarity,
+ kind: ImplKind::Normal,
}),
box merged_attrs,
cx,
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc_index::vec::{Idx, IndexVec};
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
use rustc_middle::middle::resolve_lifetime as rl;
use rustc_middle::ty::fold::TypeFolder;
use std::collections::hash_map::Entry;
use std::default::Default;
use std::hash::Hash;
-use std::rc::Rc;
use std::{mem, vec};
use crate::core::{self, DocContext, ImplTraitParam};
fn clean(&self, cx: &mut DocContext<'_>) -> T;
}
-impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
- fn clean(&self, cx: &mut DocContext<'_>) -> Vec<U> {
- self.iter().map(|x| x.clean(cx)).collect()
- }
-}
-
-impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
- fn clean(&self, cx: &mut DocContext<'_>) -> IndexVec<V, U> {
- self.iter().map(|x| x.clean(cx)).collect()
- }
-}
-
-impl<T: Clean<U>, U> Clean<U> for &T {
- fn clean(&self, cx: &mut DocContext<'_>) -> U {
- (**self).clean(cx)
- }
-}
-
-impl<T: Clean<U>, U> Clean<U> for Rc<T> {
- fn clean(&self, cx: &mut DocContext<'_>) -> U {
- (**self).clean(cx)
- }
-}
-
-impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
- fn clean(&self, cx: &mut DocContext<'_>) -> Option<U> {
- self.as_ref().map(|v| v.clean(cx))
- }
-}
-
impl Clean<Item> for doctree::Module<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let mut items: Vec<Item> = vec![];
.collect();
WherePredicate::BoundPredicate {
ty: wbp.bounded_ty.clean(cx),
- bounds: wbp.bounds.clean(cx),
+ bounds: wbp.bounds.iter().map(|x| x.clean(cx)).collect(),
bound_params,
}
}
hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
lifetime: wrp.lifetime.clean(cx),
- bounds: wrp.bounds.clean(cx),
+ bounds: wrp.bounds.iter().map(|x| x.clean(cx)).collect(),
},
hir::WherePredicate::EqPredicate(ref wrp) => {
self.name.ident().name,
GenericParamDefKind::Type {
did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(),
- bounds: self.bounds.clean(cx),
- default: default.clean(cx).map(Box::new),
+ bounds: self.bounds.iter().map(|x| x.clean(cx)).collect(),
+ default: default.map(|t| t.clean(cx)).map(Box::new),
synthetic,
},
),
}
params.extend(impl_trait_params);
- let mut generics =
- Generics { params, where_predicates: self.where_clause.predicates.clean(cx) };
+ let mut generics = Generics {
+ params,
+ where_predicates: self.where_clause.predicates.iter().map(|x| x.clean(cx)).collect(),
+ };
// Some duplicates are generated for ?Sized bounds between type params and where
// predicates. The point in here is to move the bounds definitions from type params
fn clean(&self, cx: &mut DocContext<'_>) -> PolyTrait {
PolyTrait {
trait_: self.trait_ref.clean(cx),
- generic_params: self.bound_generic_params.clean(cx),
+ generic_params: self.bound_generic_params.iter().map(|x| x.clean(cx)).collect(),
}
}
}
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
let (generics, decl) = enter_impl_trait(cx, |cx| {
- (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
+ (self.generics.clean(cx), (sig.decl, names).clean(cx))
});
let mut t = Function { header: sig.header, decl, generics };
if t.header.constness == hir::Constness::Const
TyMethodItem(t)
}
hir::TraitItemKind::Type(bounds, ref default) => {
- AssocTypeItem(bounds.clean(cx), default.clean(cx))
+ let bounds = bounds.iter().map(|x| x.clean(cx)).collect();
+ let default = default.map(|t| t.clean(cx));
+ AssocTypeItem(bounds, default)
}
};
let what_rustc_thinks =
None
};
- AssocTypeItem(bounds, ty.clean(cx))
+ AssocTypeItem(bounds, ty.map(|t| t.clean(cx)))
} else {
// FIXME: when could this happen? Associated items in inherent impls?
let type_ = tcx.type_of(self.def_id).clean(cx);
let trait_def = cx.tcx.associated_item(p.res.def_id()).container.id();
let trait_ = self::Path {
res: Res::Def(DefKind::Trait, trait_def),
- segments: trait_segments.clean(cx),
+ segments: trait_segments.iter().map(|x| x.clean(cx)).collect(),
};
register_res(cx, trait_.res);
Type::QPath {
let length = print_const(cx, ct.eval(cx.tcx, param_env));
Array(box ty.clean(cx), length)
}
- TyKind::Tup(tys) => Tuple(tys.clean(cx)),
+ TyKind::Tup(tys) => Tuple(tys.iter().map(|x| x.clean(cx)).collect()),
TyKind::OpaqueDef(item_id, _) => {
let item = cx.tcx.hir().item(item_id);
if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
- ImplTrait(ty.bounds.clean(cx))
+ ImplTrait(ty.bounds.iter().map(|x| x.clean(cx)).collect())
} else {
unreachable!()
}
DynTrait(bounds, lifetime)
}
- ty::Tuple(t) => Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx)),
+ ty::Tuple(t) => Tuple(t.iter().map(|t| t.expect_ty().clean(cx)).collect()),
ty::Projection(ref data) => data.clean(cx),
impl Clean<Path> for hir::Path<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Path {
- Path { res: self.res, segments: self.segments.clean(cx) }
+ Path { res: self.res, segments: self.segments.iter().map(|x| x.clean(cx)).collect() }
}
}
let output = self.bindings[0].ty().clean(cx);
let output =
if output != Type::Tuple(Vec::new()) { Some(Box::new(output)) } else { None };
- GenericArgs::Parenthesized { inputs: self.inputs().clean(cx), output }
+ let inputs = self.inputs().iter().map(|x| x.clean(cx)).collect();
+ GenericArgs::Parenthesized { inputs, output }
} else {
- GenericArgs::AngleBracketed {
- args: self
- .args
- .iter()
- .map(|arg| match arg {
- hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
- GenericArg::Lifetime(lt.clean(cx))
- }
- hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
- hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
- hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(ct.clean(cx))),
- hir::GenericArg::Infer(_inf) => GenericArg::Infer,
- })
- .collect(),
- bindings: self.bindings.clean(cx),
- }
+ let args = self
+ .args
+ .iter()
+ .map(|arg| match arg {
+ hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
+ GenericArg::Lifetime(lt.clean(cx))
+ }
+ hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
+ hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
+ hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(ct.clean(cx))),
+ hir::GenericArg::Infer(_inf) => GenericArg::Infer,
+ })
+ .collect();
+ let bindings = self.bindings.iter().map(|x| x.clean(cx)).collect();
+ GenericArgs::AngleBracketed { args, bindings }
}
}
}
impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl {
let (generic_params, decl) = enter_impl_trait(cx, |cx| {
- (self.generic_params.clean(cx), (&*self.decl, self.param_names).clean(cx))
+ let generic_params = self.generic_params.iter().map(|x| x.clean(cx)).collect();
+ let decl = (self.decl, self.param_names).clean(cx);
+ (generic_params, decl)
});
BareFunctionDecl { unsafety: self.unsafety, abi: self.abi, decl, generic_params }
}
kind: ConstantKind::Local { body: body_id, def_id },
}),
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
- bounds: ty.bounds.clean(cx),
+ bounds: ty.bounds.iter().map(|x| x.clean(cx)).collect(),
generics: ty.generics.clean(cx),
}),
ItemKind::TyAlias(hir_ty, ref generics) => {
}),
ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias {
generics: generics.clean(cx),
- bounds: bounds.clean(cx),
+ bounds: bounds.iter().map(|x| x.clean(cx)).collect(),
}),
ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union {
generics: generics.clean(cx),
- fields: variant_data.fields().clean(cx),
+ fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
fields_stripped: false,
}),
ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct {
struct_type: CtorKind::from_hir(variant_data),
generics: generics.clean(cx),
- fields: variant_data.fields().clean(cx),
+ fields: variant_data.fields().iter().map(|x| x.clean(cx)).collect(),
fields_stripped: false,
}),
ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.hir_id(), cx),
clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
}
ItemKind::Macro(ref macro_def) => MacroItem(Macro {
- source: display_macro_source(cx, name, macro_def, def_id, &item.vis),
+ source: display_macro_source(cx, name, macro_def, def_id, item.vis),
}),
ItemKind::Trait(is_auto, unsafety, ref generics, bounds, item_ids) => {
let items = item_ids
unsafety,
items,
generics: generics.clean(cx),
- bounds: bounds.clean(cx),
+ bounds: bounds.iter().map(|x| x.clean(cx)).collect(),
is_auto: is_auto.clean(cx),
})
}
}
}
-impl Clean<bool> for ty::ImplPolarity {
- /// Returns whether the impl has negative polarity.
- fn clean(&self, _: &mut DocContext<'_>) -> bool {
- match self {
- &ty::ImplPolarity::Positive |
- // FIXME: do we want to do something else here?
- &ty::ImplPolarity::Reservation => false,
- &ty::ImplPolarity::Negative => true,
- }
- }
-}
-
fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>) -> Vec<Item> {
let tcx = cx.tcx;
let mut ret = Vec::new();
- let trait_ = impl_.of_trait.clean(cx);
+ let trait_ = impl_.of_trait.as_ref().map(|t| t.clean(cx));
let items =
impl_.items.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>();
let def_id = tcx.hir().local_def_id(hir_id);
});
let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
let kind = ImplItem(Impl {
- span: types::rustc_span(tcx.hir().local_def_id(hir_id).to_def_id(), tcx),
unsafety: impl_.unsafety,
generics: impl_.generics.clean(cx),
trait_,
for_,
items,
- negative_polarity: tcx.impl_polarity(def_id).clean(cx),
- synthetic: false,
- blanket_impl: None,
+ polarity: tcx.impl_polarity(def_id),
+ kind: ImplKind::Normal,
});
Item::from_hir_id_and_parts(hir_id, None, kind, cx)
};
let kind = match item.kind {
hir::ForeignItemKind::Fn(decl, names, ref generics) => {
let abi = cx.tcx.hir().get_foreign_abi(item.hir_id());
- let (generics, decl) = enter_impl_trait(cx, |cx| {
- (generics.clean(cx), (&*decl, &names[..]).clean(cx))
- });
+ let (generics, decl) =
+ enter_impl_trait(cx, |cx| (generics.clean(cx), (decl, names).clean(cx)));
ForeignFunctionItem(Function {
decl,
generics,
ItemKind::StrippedItem(k) => k,
_ => &*self.kind,
};
- if let ItemKind::ModuleItem(Module { span, .. }) | ItemKind::ImplItem(Impl { span, .. }) =
- kind
- {
- *span
- } else {
- self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
+ match kind {
+ ItemKind::ModuleItem(Module { span, .. }) => *span,
+ ItemKind::ImplItem(Impl { kind: ImplKind::Auto, .. }) => Span::dummy(),
+ ItemKind::ImplItem(Impl { kind: ImplKind::Blanket(_), .. }) => {
+ if let ItemId::Blanket { impl_id, .. } = self.def_id {
+ rustc_span(impl_id, tcx)
+ } else {
+ panic!("blanket impl item has non-blanket ID")
+ }
+ }
+ _ => {
+ self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(Span::dummy)
+ }
}
}
fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
let sess = tcx.sess;
let doc_cfg_active = tcx.features().doc_cfg;
+ let doc_auto_cfg_active = tcx.features().doc_auto_cfg;
fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
let mut iter = it.into_iter();
Some(item)
}
- let mut cfg = if doc_cfg_active {
+ let mut cfg = if doc_cfg_active || doc_auto_cfg_active {
let mut doc_cfg = self
.iter()
.filter(|attr| attr.has_name(sym::doc))
.flat_map(|attr| attr.meta_item_list().unwrap_or_else(Vec::new))
.filter(|attr| attr.has_name(sym::cfg))
.peekable();
- if doc_cfg.peek().is_some() {
+ if doc_cfg.peek().is_some() && doc_cfg_active {
doc_cfg
.filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
- } else {
+ } else if doc_auto_cfg_active {
self.iter()
.filter(|attr| attr.has_name(sym::cfg))
.filter_map(|attr| single(attr.meta_item_list()?))
.filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
.filter(|cfg| !hidden_cfg.contains(cfg))
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
+ } else {
+ Cfg::True
}
} else {
Cfg::True
#[derive(Clone, Debug)]
crate struct Impl {
- crate span: Span,
crate unsafety: hir::Unsafety,
crate generics: Generics,
crate trait_: Option<Path>,
crate for_: Type,
crate items: Vec<Item>,
- crate negative_polarity: bool,
- crate synthetic: bool,
- crate blanket_impl: Option<Box<Type>>,
+ crate polarity: ty::ImplPolarity,
+ crate kind: ImplKind,
}
impl Impl {
}
}
+#[derive(Clone, Debug)]
+crate enum ImplKind {
+ Normal,
+ Auto,
+ Blanket(Box<Type>),
+}
+
+impl ImplKind {
+ crate fn is_auto(&self) -> bool {
+ matches!(self, ImplKind::Auto)
+ }
+
+ crate fn is_blanket(&self) -> bool {
+ matches!(self, ImplKind::Blanket(_))
+ }
+
+ crate fn as_blanket_ty(&self) -> Option<&Type> {
+ match self {
+ ImplKind::Blanket(ty) => Some(ty),
+ _ => None,
+ }
+ }
+}
+
#[derive(Clone, Debug)]
crate struct Import {
crate kind: ImportKind,
StructItem(mut i) => {
let num_fields = i.fields.len();
i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
- i.fields_stripped |=
- num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
+ if !i.fields_stripped {
+ i.fields_stripped =
+ num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
+ }
StructItem(i)
}
UnionItem(mut i) => {
let num_fields = i.fields.len();
i.fields = i.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
- i.fields_stripped |=
- num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
+ if !i.fields_stripped {
+ i.fields_stripped =
+ num_fields != i.fields.len() || i.fields.iter().any(|f| f.is_stripped());
+ }
UnionItem(i)
}
EnumItem(mut i) => {
let num_variants = i.variants.len();
i.variants = i.variants.into_iter().filter_map(|x| self.fold_item(x)).collect();
- i.variants_stripped |=
- num_variants != i.variants.len() || i.variants.iter().any(|f| f.is_stripped());
+ if !i.variants_stripped {
+ i.variants_stripped = num_variants != i.variants.len()
+ || i.variants.iter().any(|f| f.is_stripped());
+ }
EnumItem(i)
}
TraitItem(mut i) => {
i.items = i.items.into_iter().filter_map(|x| self.fold_item(x)).collect();
ImplItem(i)
}
- VariantItem(i) => {
- let i2 = i.clone(); // this clone is small
- match i {
- Variant::Struct(mut j) => {
- let num_fields = j.fields.len();
- j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
- j.fields_stripped |= num_fields != j.fields.len()
+ VariantItem(i) => match i {
+ Variant::Struct(mut j) => {
+ let num_fields = j.fields.len();
+ j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
+ if !j.fields_stripped {
+ j.fields_stripped = num_fields != j.fields.len()
|| j.fields.iter().any(|f| f.is_stripped());
- VariantItem(Variant::Struct(j))
- }
- Variant::Tuple(fields) => {
- let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
- VariantItem(Variant::Tuple(fields))
}
- _ => VariantItem(i2),
+ VariantItem(Variant::Struct(j))
}
- }
- x => x,
+ Variant::Tuple(fields) => {
+ let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
+ VariantItem(Variant::Tuple(fields))
+ }
+ Variant::CLike => VariantItem(Variant::CLike),
+ },
+ ExternCrateItem { src: _ }
+ | ImportItem(_)
+ | FunctionItem(_)
+ | TypedefItem(_, _)
+ | OpaqueTyItem(_)
+ | StaticItem(_)
+ | ConstantItem(_)
+ | TraitAliasItem(_)
+ | TyMethodItem(_)
+ | MethodItem(_, _)
+ | StructFieldItem(_)
+ | ForeignFunctionItem(_)
+ | ForeignStaticItem(_)
+ | ForeignTypeItem
+ | MacroItem(_)
+ | ProcMacroItem(_)
+ | PrimitiveItem(_)
+ | AssocConstItem(_, _)
+ | AssocTypeItem(_, _)
+ | KeywordItem(_) => kind,
}
}
fn fold_crate(&mut self, mut c: Crate) -> Crate {
c.module = self.fold_item(c.module).unwrap();
- {
- let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
- for (k, mut v) in external_traits {
- v.trait_.items =
- v.trait_.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
- c.external_traits.borrow_mut().insert(k, v);
- }
+ let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
+ for (k, mut v) in external_traits {
+ v.trait_.items = v.trait_.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
+ c.external_traits.borrow_mut().insert(k, v);
}
+
c
}
}
// Collect all the implementors of traits.
if let clean::ImplItem(ref i) = *item.kind {
if let Some(trait_) = &i.trait_ {
- if i.blanket_impl.is_none() {
+ if !i.kind.is_blanket() {
self.cache
.implementors
.entry(trait_.def_id())
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
+use rustc_middle::ty;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::CRATE_DEF_INDEX;
use rustc_target::spec::abi::Abi;
}
if let Some(ref ty) = self.trait_ {
- if self.negative_polarity {
- write!(f, "!")?;
+ match self.polarity {
+ ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => {}
+ ty::ImplPolarity::Negative => write!(f, "!")?,
}
fmt::Display::fmt(&ty.print(cx), f)?;
write!(f, " for ")?;
}
- if let Some(ref ty) = self.blanket_impl {
+ if let Some(ref ty) = self.kind.as_blanket_ty() {
fmt_type(ty, f, use_absolute, cx)?;
} else {
fmt_type(&self.for_, f, use_absolute, cx)?;
impl Decorations {
fn new(info: DecorationInfo) -> Self {
- let (starts, ends) = info
+ // Extract tuples (start, end, kind) into separate sequences of (start, kind) and (end).
+ let (mut starts, mut ends): (Vec<_>, Vec<_>) = info
.0
.into_iter()
.map(|(kind, ranges)| ranges.into_iter().map(move |(lo, hi)| ((lo, kind), hi)))
.flatten()
.unzip();
+
+ // Sort the sequences in document order.
+ starts.sort_by_key(|(lo, _)| *lo);
+ ends.sort();
+
Decorations { starts, ends }
}
}
}
}
- let (mut krate, local_sources, matches) = collect_spans_and_sources(
+ let (local_sources, matches) = collect_spans_and_sources(
tcx,
- krate,
+ &krate,
&src_root,
include_sources,
generate_link_to_definition,
};
if emit_crate {
- krate = sources::render(&mut cx, krate)?;
+ sources::render(&mut cx, &krate)?;
}
// Build our search index
mod templates;
mod write_shared;
-crate use context::*;
-crate use span_map::{collect_spans_and_sources, LinkFromSrc};
+crate use self::context::*;
+crate use self::span_map::{collect_spans_and_sources, LinkFromSrc};
use std::collections::VecDeque;
use std::default::Default;
use rustc_hir::def_id::DefId;
use rustc_hir::Mutability;
use rustc_middle::middle::stability;
+use rustc_middle::ty;
use rustc_middle::ty::TyCtxt;
use rustc_span::{
symbol::{kw, sym, Symbol},
use crate::html::highlight;
use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine};
use crate::html::sources;
-use crate::scrape_examples::CallData;
+use crate::scrape_examples::{CallData, CallLocation};
use crate::try_none;
/// A pair of name and its optional document.
}
let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
- traits.iter().partition(|t| t.inner_impl().synthetic);
+ traits.iter().partition(|t| t.inner_impl().kind.is_auto());
let (blanket_impl, concrete): (Vec<&&Impl>, _) =
- concrete.into_iter().partition(|t| t.inner_impl().blanket_impl.is_some());
+ concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
let mut impls = Buffer::empty_from(w);
render_impls(cx, &mut impls, &concrete, containing_item);
let i_display = format!("{:#}", i.print(cx));
let out = Escape(&i_display);
let encoded = small_url_encode(format!("{:#}", i.print(cx)));
- let generated = format!(
- "<a href=\"#impl-{}\">{}{}</a>",
- encoded,
- if it.inner_impl().negative_polarity { "!" } else { "" },
- out
- );
+ let prefix = match it.inner_impl().polarity {
+ ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
+ ty::ImplPolarity::Negative => "!",
+ };
+ let generated =
+ format!("<a href=\"#impl-{}\">{}{}</a>", encoded, prefix, out);
if links.insert(generated.clone()) { Some(generated) } else { None }
} else {
None
};
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
- v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().synthetic);
- let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) = concrete
- .into_iter()
- .partition::<Vec<_>, _>(|i| i.inner_impl().blanket_impl.is_some());
+ v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_auto());
+ let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) =
+ concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket());
let concrete_format = format_impls(concrete);
let synthetic_format = format_impls(synthetic);
id = id
);
+ // Create a URL to a particular location in a reverse-dependency's source file
+ let link_to_loc = |call_data: &CallData, loc: &CallLocation| -> (String, String) {
+ let (line_lo, line_hi) = loc.call_expr.line_span;
+ let (anchor, title) = if line_lo == line_hi {
+ ((line_lo + 1).to_string(), format!("line {}", line_lo + 1))
+ } else {
+ (
+ format!("{}-{}", line_lo + 1, line_hi + 1),
+ format!("lines {}-{}", line_lo + 1, line_hi + 1),
+ )
+ };
+ let url = format!("{}{}#{}", cx.root_path(), call_data.url, anchor);
+ (url, title)
+ };
+
// Generate the HTML for a single example, being the title and code block
let write_example = |w: &mut Buffer, (path, call_data): (&PathBuf, &CallData)| -> bool {
let contents = match fs::read_to_string(&path) {
let (line_lo, line_hi) = loc.call_expr.line_span;
let byte_range = (byte_lo - byte_min, byte_hi - byte_min);
let line_range = (line_lo - line_min, line_hi - line_min);
- let (anchor, line_title) = if line_lo == line_hi {
- (format!("{}", line_lo + 1), format!("line {}", line_lo + 1))
- } else {
- (
- format!("{}-{}", line_lo + 1, line_hi + 1),
- format!("lines {}-{}", line_lo + 1, line_hi + 1),
- )
- };
- let line_url = format!("{}{}#{}", cx.root_path(), call_data.url, anchor);
+ let (line_url, line_title) = link_to_loc(call_data, loc);
(byte_range, (line_range, line_url, line_title))
})
if it.peek().is_some() {
write!(w, r#"<div class="example-links">Additional examples can be found in:<br><ul>"#);
it.for_each(|(_, call_data)| {
+ let (url, _) = link_to_loc(&call_data, &call_data.locations[0]);
write!(
w,
- r#"<li><a href="{root}{url}">{name}</a></li>"#,
- root = cx.root_path(),
- url = call_data.url,
+ r#"<li><a href="{url}">{name}</a></li>"#,
+ url = url,
name = call_data.display_name
);
});
});
let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
- local.iter().partition(|i| i.inner_impl().synthetic);
+ local.iter().partition(|i| i.inner_impl().kind.is_auto());
synthetic.sort_by(|a, b| compare_impl(a, b, cx));
concrete.sort_by(|a, b| compare_impl(a, b, cx));
/// only keep the `lo` and `hi`.
crate fn collect_spans_and_sources(
tcx: TyCtxt<'_>,
- krate: clean::Crate,
+ krate: &clean::Crate,
src_root: &Path,
include_sources: bool,
generate_link_to_definition: bool,
-) -> (clean::Crate, FxHashMap<PathBuf, String>, FxHashMap<Span, LinkFromSrc>) {
+) -> (FxHashMap<PathBuf, String>, FxHashMap<Span, LinkFromSrc>) {
let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() };
if include_sources {
if generate_link_to_definition {
tcx.hir().walk_toplevel_module(&mut visitor);
}
- let (krate, sources) = sources::collect_local_sources(tcx, src_root, krate);
- (krate, sources, visitor.matches)
+ let sources = sources::collect_local_sources(tcx, src_root, &krate);
+ (sources, visitor.matches)
} else {
- (krate, Default::default(), Default::default())
+ (Default::default(), Default::default())
}
}
} else {
Some(Implementor {
text: imp.inner_impl().print(false, cx).to_string(),
- synthetic: imp.inner_impl().synthetic,
+ synthetic: imp.inner_impl().kind.is_auto(),
types: collect_paths_for_type(imp.inner_impl().for_.clone(), cache),
})
}
use crate::clean;
use crate::docfs::PathError;
use crate::error::Error;
-use crate::fold::DocFolder;
use crate::html::format::Buffer;
use crate::html::highlight;
use crate::html::layout;
use crate::html::render::{Context, BASIC_KEYWORDS};
+use crate::visit::DocVisitor;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::TyCtxt;
use std::fs;
use std::path::{Component, Path, PathBuf};
-crate fn render(cx: &mut Context<'_>, krate: clean::Crate) -> Result<clean::Crate, Error> {
+crate fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), Error> {
info!("emitting source files");
+
let dst = cx.dst.join("src").join(&*krate.name(cx.tcx()).as_str());
cx.shared.ensure_dir(&dst)?;
- let mut folder = SourceCollector { dst, cx, emitted_local_sources: FxHashSet::default() };
- Ok(folder.fold_crate(krate))
+
+ let mut collector = SourceCollector { dst, cx, emitted_local_sources: FxHashSet::default() };
+ collector.visit_crate(krate);
+ Ok(())
}
crate fn collect_local_sources<'tcx>(
tcx: TyCtxt<'tcx>,
src_root: &Path,
- krate: clean::Crate,
-) -> (clean::Crate, FxHashMap<PathBuf, String>) {
+ krate: &clean::Crate,
+) -> FxHashMap<PathBuf, String> {
let mut lsc = LocalSourcesCollector { tcx, local_sources: FxHashMap::default(), src_root };
-
- let krate = lsc.fold_crate(krate);
- (krate, lsc.local_sources)
+ lsc.visit_crate(krate);
+ lsc.local_sources
}
struct LocalSourcesCollector<'a, 'tcx> {
}
fn is_real_and_local(span: clean::Span, sess: &Session) -> bool {
- span.filename(sess).is_real() && span.cnum(sess) == LOCAL_CRATE
+ span.cnum(sess) == LOCAL_CRATE && span.filename(sess).is_real()
}
impl LocalSourcesCollector<'_, '_> {
return;
}
let filename = span.filename(sess);
- let p = match filename {
- FileName::Real(ref file) => match file.local_path() {
- Some(p) => p.to_path_buf(),
- _ => return,
- },
- _ => return,
+ let p = if let FileName::Real(file) = filename {
+ match file.into_local_path() {
+ Some(p) => p,
+ None => return,
+ }
+ } else {
+ return;
};
if self.local_sources.contains_key(&*p) {
// We've already emitted this source
}
}
-impl DocFolder for LocalSourcesCollector<'_, '_> {
- fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
- self.add_local_source(&item);
+impl DocVisitor for LocalSourcesCollector<'_, '_> {
+ fn visit_item(&mut self, item: &clean::Item) {
+ self.add_local_source(item);
- // FIXME: if `include_sources` isn't set and DocFolder didn't require consuming the crate by value,
- // we could return None here without having to walk the rest of the crate.
- Some(self.fold_item_recur(item))
+ self.visit_item_recur(item)
}
}
emitted_local_sources: FxHashSet<PathBuf>,
}
-impl DocFolder for SourceCollector<'_, '_> {
- fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
+impl DocVisitor for SourceCollector<'_, '_> {
+ fn visit_item(&mut self, item: &clean::Item) {
+ if !self.cx.include_sources {
+ return;
+ }
+
let tcx = self.cx.tcx();
let span = item.span(tcx);
let sess = tcx.sess;
// If we're not rendering sources, there's nothing to do.
// If we're including source files, and we haven't seen this file yet,
// then we need to render it out to the filesystem.
- if self.cx.include_sources && is_real_and_local(span, sess) {
+ if is_real_and_local(span, sess) {
let filename = span.filename(sess);
let span = span.inner();
let pos = sess.source_map().lookup_source_file(span.lo());
}
};
}
- // FIXME: if `include_sources` isn't set and DocFolder didn't require consuming the crate by value,
- // we could return None here without having to walk the rest of the crate.
- Some(self.fold_item_recur(item))
+
+ self.visit_item_recur(item)
}
}
/* It requires JS to work so no need to display it in this case. */
display: none;
}
+
+.sub {
+ /* The search bar and related controls don't work without JS */
+ display: none;
+}
+
+#theme-picker {
+ display: none;
+}
section hierarchies. */
h2,
.top-doc h3,
-.top-doc h4 {
+.top-doc h4,
+.sidebar .others h3 {
border-bottom: 1px solid;
}
h3.code-header {
box-shadow: 0 0 0 1px #148099,0 0 0 2px transparent;
}
-.search-input:disabled {
- background-color: #3e3e3e;
-}
-
.module-item .stab,
.import-item .stab {
color: #000;
border-color: #008dfd;
}
-.search-input:disabled {
- background-color: #c5c4c4;
-}
-
#crate-search + .search-input:focus {
box-shadow: 0 0 8px 4px #078dd8;
}
border-color: #66afe9;
}
-.search-input:disabled {
- background-color: #e6e6e6;
-}
-
#crate-search + .search-input:focus {
box-shadow: 0 0 8px #078dd8;
}
search_input.placeholder = searchState.input.origPlaceholder;
});
- search_input.removeAttribute('disabled');
+ if (search_input.value != '') {
+ loadSearch();
+ }
// `crates{version}.js` should always be loaded before this script, so we can use it
// safely.
// delayed sidebar rendering.
window.initSidebarItems = function(items) {
var sidebar = document.getElementsByClassName("sidebar-elems")[0];
+ var others;
var current = window.sidebarCurrent;
function addSidebarCrates(crates) {
li.appendChild(link);
ul.appendChild(li);
}
- sidebar.appendChild(div);
+ others.appendChild(div);
}
function block(shortty, longty) {
ul.appendChild(li);
}
div.appendChild(ul);
- sidebar.appendChild(div);
+ others.appendChild(div);
}
if (sidebar) {
+ others = document.createElement("div");
+ others.className = "others";
+ sidebar.appendChild(others);
+
var isModule = hasClass(document.body, "mod");
if (!isModule) {
block("primitive", "Primitive Types");
<input {# -#}
class="search-input" {# -#}
name="search" {# -#}
- disabled {# -#}
autocomplete="off" {# -#}
spellcheck="false" {# -#}
placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#}
data-search-js="{{static_root_path | safe}}search{{page.resource_suffix}}.js"> {#- -#}
</div>
<script src="{{static_root_path | safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
- {%- if layout.scrape_examples_extension -%}
- <script src="{{static_root_path | safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
- {%- endif -%}
{%- for script in page.static_extra_scripts -%}
<script src="{{static_root_path | safe}}{{script}}.js"></script> {#- -#}
{% endfor %}
+ {%- if layout.scrape_examples_extension -%}
+ <script src="{{page.root_path | safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
+ {%- endif -%}
{%- for script in page.extra_scripts -%}
<script src="{{page.root_path | safe}}{{script}}.js"></script> {#- -#}
{% endfor %}
use rustc_ast::ast;
use rustc_hir::{def::CtorKind, def_id::DefId};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{self, TyCtxt};
use rustc_span::def_id::CRATE_DEF_INDEX;
use rustc_span::Pos;
impl FromWithTcx<clean::Impl> for Impl {
fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
let provided_trait_methods = impl_.provided_trait_methods(tcx);
- let clean::Impl {
- unsafety,
- generics,
- trait_,
- for_,
- items,
- negative_polarity,
- synthetic,
- blanket_impl,
- span: _span,
- } = impl_;
+ let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_;
// FIXME: should `trait_` be a clean::Path equivalent in JSON?
let trait_ = trait_.map(|path| {
let did = path.def_id();
clean::ResolvedPath { path, did }.into_tcx(tcx)
});
+ // FIXME: use something like ImplKind in JSON?
+ let (synthetic, blanket_impl) = match kind {
+ clean::ImplKind::Normal => (false, None),
+ clean::ImplKind::Auto => (true, None),
+ clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
+ };
+ let negative_polarity = match polarity {
+ ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => false,
+ ty::ImplPolarity::Negative => true,
+ };
Impl {
is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
generics: generics.into_tcx(tcx),
items: ids(items),
negative: negative_polarity,
synthetic,
- blanket_impl: blanket_impl.map(|x| (*x).into_tcx(tcx)),
+ blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)),
}
}
}
mod passes;
mod scrape_examples;
mod theme;
+mod visit;
mod visit_ast;
mod visit_lib;
use super::Pass;
use crate::clean::*;
use crate::core::DocContext;
-use crate::fold::DocFolder;
use crate::html::markdown::main_body_opts;
+use crate::visit::DocVisitor;
use core::ops::Range;
use pulldown_cmark::{Event, Parser, Tag};
use regex::Regex;
}
crate fn check_bare_urls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
- BareUrlsLinter { cx }.fold_crate(krate)
+ BareUrlsLinter { cx }.visit_crate(&krate);
+ krate
}
-impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> {
- fn fold_item(&mut self, item: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for BareUrlsLinter<'a, 'tcx> {
+ fn visit_item(&mut self, item: &Item) {
let hir_id = match DocContext::as_local_hir_id(self.cx.tcx, item.def_id) {
Some(hir_id) => hir_id,
None => {
// If non-local, no need to check anything.
- return Some(self.fold_item_recur(item));
+ return;
}
};
let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
}
}
- Some(self.fold_item_recur(item))
+ self.visit_item_recur(item)
}
}
use crate::clean;
use crate::core::DocContext;
-use crate::fold::{self, DocFolder};
use crate::html::markdown::{find_testable_code, ErrorCodes};
use crate::passes::check_doc_test_visibility::{should_have_doc_example, Tests};
use crate::passes::Pass;
+use crate::visit::DocVisitor;
use rustc_hir as hir;
use rustc_lint::builtin::MISSING_DOCS;
use rustc_middle::lint::LintLevelSource;
fn calculate_doc_coverage(krate: clean::Crate, ctx: &mut DocContext<'_>) -> clean::Crate {
let mut calc = CoverageCalculator { items: Default::default(), ctx };
- let krate = calc.fold_crate(krate);
+ calc.visit_crate(&krate);
calc.print_results();
}
}
-impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
- fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
+impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
+ fn visit_item(&mut self, i: &clean::Item) {
+ if !i.def_id.is_local() {
+ // non-local items are skipped because they can be out of the users control,
+ // especially in the case of trait impls, which rustdoc eagerly inlines
+ return;
+ }
+
match *i.kind {
- _ if !i.def_id.is_local() => {
- // non-local items are skipped because they can be out of the users control,
- // especially in the case of trait impls, which rustdoc eagerly inlines
- return Some(i);
- }
clean::StrippedItem(..) => {
// don't count items in stripped modules
- return Some(i);
+ return;
}
// docs on `use` and `extern crate` statements are not displayed, so they're not
// worth counting
}
}
- Some(self.fold_item_recur(i))
+ self.visit_item_recur(i)
}
}
use crate::clean;
use crate::core::DocContext;
-use crate::fold::DocFolder;
use crate::html::markdown::{self, RustCodeBlock};
use crate::passes::Pass;
+use crate::visit::DocVisitor;
crate const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass {
name: "check-code-block-syntax",
};
crate fn check_code_block_syntax(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
- SyntaxChecker { cx }.fold_crate(krate)
+ SyntaxChecker { cx }.visit_crate(&krate);
+ krate
}
struct SyntaxChecker<'a, 'tcx> {
}
}
-impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> {
- fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
+impl<'a, 'tcx> DocVisitor for SyntaxChecker<'a, 'tcx> {
+ fn visit_item(&mut self, item: &clean::Item) {
if let Some(dox) = &item.attrs.collapsed_doc_value() {
let sp = item.attr_span(self.cx.tcx);
let extra = crate::html::markdown::ExtraInfo::new_did(
}
}
- Some(self.fold_item_recur(item))
+ self.visit_item_recur(item)
}
}
use crate::clean;
use crate::clean::*;
use crate::core::DocContext;
-use crate::fold::DocFolder;
use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
+use crate::visit::DocVisitor;
use crate::visit_ast::inherits_doc_hidden;
use rustc_hir as hir;
use rustc_middle::lint::LintLevelSource;
crate fn check_doc_test_visibility(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
let mut coll = DocTestVisibilityLinter { cx };
-
- coll.fold_crate(krate)
+ coll.visit_crate(&krate);
+ krate
}
-impl<'a, 'tcx> DocFolder for DocTestVisibilityLinter<'a, 'tcx> {
- fn fold_item(&mut self, item: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for DocTestVisibilityLinter<'a, 'tcx> {
+ fn visit_item(&mut self, item: &Item) {
let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);
look_for_tests(self.cx, &dox, &item);
- Some(self.fold_item_recur(item))
+ self.visit_item_recur(item)
}
}
use crate::clean::{self, utils::find_nearest_parent_module, Crate, Item, ItemLink, PrimitiveType};
use crate::core::DocContext;
-use crate::fold::DocFolder;
use crate::html::markdown::{markdown_links, MarkdownLink};
use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
use crate::passes::Pass;
+use crate::visit::DocVisitor;
mod early;
crate use early::load_intra_link_crates;
};
fn collect_intra_doc_links(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
- LinkCollector {
+ let mut collector = LinkCollector {
cx,
mod_ids: Vec::new(),
kind_side_channel: Cell::new(None),
visited_links: FxHashMap::default(),
- }
- .fold_crate(krate)
+ };
+ collector.visit_crate(&krate);
+ krate
}
/// Top-level errors emitted by this pass.
)
}
-impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
- fn fold_item(&mut self, item: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
+ fn visit_item(&mut self, item: &Item) {
use rustc_middle::ty::DefIdTree;
let parent_node =
}
}
- Some(if item.is_mod() {
+ if item.is_mod() {
if !inner_docs {
self.mod_ids.push(item.def_id.expect_def_id());
}
- let ret = self.fold_item_recur(item);
+ self.visit_item_recur(item);
self.mod_ids.pop();
- ret
} else {
- self.fold_item_recur(item)
- })
+ self.visit_item_recur(item)
+ }
}
}
use super::Pass;
use crate::clean::*;
use crate::core::DocContext;
-use crate::fold::DocFolder;
+use crate::visit::DocVisitor;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::DefId;
description: "retrieves trait impls for items in the crate",
};
-crate fn collect_trait_impls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
- let (mut krate, synth_impls) = cx.sess().time("collect_synthetic_impls", || {
+crate fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> Crate {
+ let synth_impls = cx.sess().time("collect_synthetic_impls", || {
let mut synth = SyntheticImplCollector { cx, impls: Vec::new() };
- (synth.fold_crate(krate), synth.impls)
+ synth.visit_crate(&krate);
+ synth.impls
});
let prims: FxHashSet<PrimitiveType> = krate.primitives.iter().map(|p| p.1).collect();
let crate_items = {
let mut coll = ItemCollector::new();
- krate = cx.sess().time("collect_items_for_trait_impls", || coll.fold_crate(krate));
+ cx.sess().time("collect_items_for_trait_impls", || coll.visit_crate(&krate));
coll.items
};
}
new_items.retain(|it| {
- if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
+ if let ImplItem(Impl { ref for_, ref trait_, ref kind, .. }) = *it.kind {
cleaner.keep_impl(
for_,
trait_.as_ref().map(|t| t.def_id()) == cx.tcx.lang_items().deref_trait(),
) || trait_.as_ref().map_or(false, |t| cleaner.keep_impl_with_def_id(t.def_id().into()))
- || blanket_impl.is_some()
+ || kind.is_blanket()
} else {
true
}
}
}
- let items = if let ModuleItem(Module { ref mut items, .. }) = *krate.module.kind {
- items
+ if let ModuleItem(Module { items, .. }) = &mut *krate.module.kind {
+ items.extend(synth_impls);
+ items.extend(new_items);
} else {
panic!("collect-trait-impls can't run");
};
- items.extend(synth_impls);
- items.extend(new_items);
krate
}
impls: Vec<Item>,
}
-impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> {
- fn fold_item(&mut self, i: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for SyntheticImplCollector<'a, 'tcx> {
+ fn visit_item(&mut self, i: &Item) {
if i.is_struct() || i.is_enum() || i.is_union() {
// FIXME(eddyb) is this `doc(hidden)` check needed?
if !self
}
}
- Some(self.fold_item_recur(i))
+ self.visit_item_recur(i)
}
}
}
}
-impl DocFolder for ItemCollector {
- fn fold_item(&mut self, i: Item) -> Option<Item> {
+impl DocVisitor for ItemCollector {
+ fn visit_item(&mut self, i: &Item) {
self.items.insert(i.def_id);
- Some(self.fold_item_recur(i))
+ self.visit_item_recur(i)
}
}
use super::Pass;
use crate::clean::*;
use crate::core::DocContext;
-use crate::fold::DocFolder;
use crate::html::markdown::main_body_opts;
-use core::ops::Range;
+use crate::visit::DocVisitor;
+
use pulldown_cmark::{Event, Parser, Tag};
+
use std::iter::Peekable;
+use std::ops::Range;
use std::str::CharIndices;
crate const CHECK_INVALID_HTML_TAGS: Pass = Pass {
}
crate fn check_invalid_html_tags(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
- if !cx.tcx.sess.is_nightly_build() {
- krate
- } else {
+ if cx.tcx.sess.is_nightly_build() {
let mut coll = InvalidHtmlTagsLinter { cx };
-
- coll.fold_crate(krate)
+ coll.visit_crate(&krate);
}
+ krate
}
const ALLOWED_UNCLOSED: &[&str] = &[
}
}
-impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> {
- fn fold_item(&mut self, item: Item) -> Option<Item> {
+impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
+ fn visit_item(&mut self, item: &Item) {
let tcx = self.cx.tcx;
let hir_id = match DocContext::as_local_hir_id(tcx, item.def_id) {
Some(hir_id) => hir_id,
None => {
// If non-local, no need to check anything.
- return Some(self.fold_item_recur(item));
+ return;
}
};
let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
}
}
- Some(self.fold_item_recur(item))
+ self.visit_item_recur(item)
}
}
use rustc_hir::{
self as hir,
intravisit::{self, Visitor},
- HirId,
};
use rustc_interface::interface;
use rustc_macros::{Decodable, Encodable};
target_crates,
})),
(Some(_), false) | (None, true) => {
- diag.err(&format!("must use --scrape-examples-output-path and --scrape-examples-target-crate together"));
+ diag.err("must use --scrape-examples-output-path and --scrape-examples-target-crate together");
Err(1)
}
(None, false) => Ok(None),
impl CallLocation {
fn new(
- tcx: TyCtxt<'_>,
expr_span: rustc_span::Span,
- expr_id: HirId,
+ enclosing_item_span: rustc_span::Span,
source_file: &SourceFile,
) -> Self {
- let enclosing_item_span =
- tcx.hir().span_with_body(tcx.hir().get_parent_item(expr_id)).source_callsite();
- assert!(enclosing_item_span.contains(expr_span));
-
CallLocation {
call_expr: SyntaxRange::new(expr_span, source_file),
enclosing_item: SyntaxRange::new(enclosing_item_span, source_file),
fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
intravisit::walk_expr(self, ex);
- // Get type of function if expression is a function call
let tcx = self.tcx;
+
+ // If we visit an item that contains an expression outside a function body,
+ // then we need to exit before calling typeck (which will panic). See
+ // test/run-make/rustdoc-scrape-examples-invalid-expr for an example.
+ let hir = tcx.hir();
+ let owner = hir.local_def_id_to_hir_id(ex.hir_id.owner);
+ if hir.maybe_body_owned_by(owner).is_none() {
+ return;
+ }
+
+ // Get type of function if expression is a function call
let (ty, span) = match ex.kind {
hir::ExprKind::Call(f, _) => {
let types = tcx.typeck(ex.hir_id.owner);
- (types.node_type(f.hir_id), ex.span)
+
+ match types.node_type_opt(f.hir_id) {
+ Some(ty) => (ty, ex.span),
+ None => {
+ return;
+ }
+ }
}
hir::ExprKind::MethodCall(_, _, _, span) => {
let types = tcx.typeck(ex.hir_id.owner);
// If this span comes from a macro expansion, then the source code may not actually show
// a use of the given item, so it would be a poor example. Hence, we skip all uses in macros.
if span.from_expansion() {
+ trace!("Rejecting expr from macro: {:?}", span);
return;
}
+ // If the enclosing item has a span coming from a proc macro, then we also don't want to include
+ // the example.
+ let enclosing_item_span = tcx.hir().span_with_body(tcx.hir().get_parent_item(ex.hir_id));
+ if enclosing_item_span.from_expansion() {
+ trace!("Rejecting expr ({:?}) from macro item: {:?}", span, enclosing_item_span);
+ return;
+ }
+
+ assert!(
+ enclosing_item_span.contains(span),
+ "Attempted to scrape call at [{:?}] whose enclosing item [{:?}] doesn't contain the span of the call.",
+ span,
+ enclosing_item_span
+ );
+
// Save call site if the function resolves to a concrete definition
if let ty::FnDef(def_id, _) = ty.kind() {
- // Ignore functions not from the crate being documented
if self.target_crates.iter().all(|krate| *krate != def_id.krate) {
+ trace!("Rejecting expr from crate not being documented: {:?}", span);
return;
}
let fn_key = tcx.def_path_hash(*def_id);
let fn_entries = self.calls.entry(fn_key).or_default();
- let location = CallLocation::new(tcx, span, ex.hir_id, &file);
+ trace!("Including expr: {:?}", span);
+ let location = CallLocation::new(span, enclosing_item_span, &file);
fn_entries.entry(abs_path).or_insert_with(mk_call_data).locations.push(location);
}
}
let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates };
tcx.hir().visit_all_item_likes(&mut finder.as_deep_visitor());
+ // Sort call locations within a given file in document order
+ for fn_calls in calls.values_mut() {
+ for file_calls in fn_calls.values_mut() {
+ file_calls.locations.sort_by_key(|loc| loc.call_expr.byte_span.0);
+ }
+ }
+
// Save output to provided path
let mut encoder = FileEncoder::new(options.output_path).map_err(|e| e.to_string())?;
calls.encode(&mut encoder).map_err(|e| e.to_string())?;
--- /dev/null
+use crate::clean::*;
+
+crate trait DocVisitor: Sized {
+ fn visit_item(&mut self, item: &Item) {
+ self.visit_item_recur(item)
+ }
+
+ /// don't override!
+ fn visit_inner_recur(&mut self, kind: &ItemKind) {
+ match kind {
+ StrippedItem(..) => unreachable!(),
+ ModuleItem(i) => {
+ self.visit_mod(i);
+ return;
+ }
+ StructItem(i) => i.fields.iter().for_each(|x| self.visit_item(x)),
+ UnionItem(i) => i.fields.iter().for_each(|x| self.visit_item(x)),
+ EnumItem(i) => i.variants.iter().for_each(|x| self.visit_item(x)),
+ TraitItem(i) => i.items.iter().for_each(|x| self.visit_item(x)),
+ ImplItem(i) => i.items.iter().for_each(|x| self.visit_item(x)),
+ VariantItem(i) => match i {
+ Variant::Struct(j) => j.fields.iter().for_each(|x| self.visit_item(x)),
+ Variant::Tuple(fields) => fields.iter().for_each(|x| self.visit_item(x)),
+ Variant::CLike => {}
+ },
+ ExternCrateItem { src: _ }
+ | ImportItem(_)
+ | FunctionItem(_)
+ | TypedefItem(_, _)
+ | OpaqueTyItem(_)
+ | StaticItem(_)
+ | ConstantItem(_)
+ | TraitAliasItem(_)
+ | TyMethodItem(_)
+ | MethodItem(_, _)
+ | StructFieldItem(_)
+ | ForeignFunctionItem(_)
+ | ForeignStaticItem(_)
+ | ForeignTypeItem
+ | MacroItem(_)
+ | ProcMacroItem(_)
+ | PrimitiveItem(_)
+ | AssocConstItem(_, _)
+ | AssocTypeItem(_, _)
+ | KeywordItem(_) => {}
+ }
+ }
+
+ /// don't override!
+ fn visit_item_recur(&mut self, item: &Item) {
+ match &*item.kind {
+ StrippedItem(i) => self.visit_inner_recur(i),
+ _ => self.visit_inner_recur(&item.kind),
+ }
+ }
+
+ fn visit_mod(&mut self, m: &Module) {
+ m.items.iter().for_each(|i| self.visit_item(i))
+ }
+
+ fn visit_crate(&mut self, c: &Crate) {
+ self.visit_item(&c.module);
+
+ // FIXME: make this a simple by-ref for loop once external_traits is cleaned up
+ let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
+ for (k, v) in external_traits {
+ v.trait_.items.iter().for_each(|i| self.visit_item(i));
+ c.external_traits.borrow_mut().insert(k, v);
+ }
+ }
+}
// compile-flags: --target aarch64-unknown-linux-gnu
// needs-llvm-components: aarch64
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
// compile-flags: -C target-feature=+neon
// needs-llvm-components: arm
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
// compile-flags: --target bpfel-unknown-none -C target_feature=+alu32
// needs-llvm-components: bpf
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
// assembly-output: emit-asm
// compile-flags: -C llvm-args=--x86-asm-syntax=intel
-#![feature(asm, global_asm)]
+#![feature(global_asm, asm_const)]
#![crate_type = "rlib"]
// CHECK: mov eax, eax
// compile-flags: --target hexagon-unknown-linux-musl
// needs-llvm-components: hexagon
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
//[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
//[mips64] needs-llvm-components: mips
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
// compile-flags: --crate-type cdylib
// needs-llvm-components: nvptx
-#![feature(no_core, lang_items, rustc_attrs)]
+#![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch)]
#![no_core]
#[rustc_builtin_macro]
//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
//[powerpc64] needs-llvm-components: powerpc
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
//[riscv32] needs-llvm-components: riscv
// compile-flags: -C target-feature=+d
-#![feature(no_core, lang_items, rustc_attrs)]
+#![feature(no_core, lang_items, rustc_attrs, asm_sym)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register)]
//[s390x] compile-flags: --target s390x-unknown-linux-gnu
//[s390x] needs-llvm-components: systemz
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
// compile-flags: --crate-type cdylib
// needs-llvm-components: webassembly
-#![feature(no_core, lang_items, rustc_attrs)]
+#![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch)]
#![no_core]
#[rustc_builtin_macro]
// compile-flags: -C llvm-args=--x86-asm-syntax=intel
// compile-flags: -C target-feature=+avx512bw
-#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
--- /dev/null
+// compile-flags:-Zprint-mono-items=lazy
+
+// rust-lang/rust#90405
+// Ensure implicit panic calls are collected
+
+#![feature(lang_items)]
+#![feature(no_core)]
+#![crate_type = "lib"]
+#![no_core]
+#![no_std]
+
+#[lang = "panic_location"]
+struct Location<'a> {
+ _file: &'a str,
+ _line: u32,
+ _col: u32,
+}
+
+#[lang = "panic"]
+#[inline]
+#[track_caller]
+fn panic(_: &'static str) -> ! {
+ loop {}
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+#[lang = "freeze"]
+trait Freeze {}
+
+impl Copy for i32 {}
+
+#[lang = "div"]
+trait Div<Rhs = Self> {
+ type Output;
+ fn div(self, rhs: Rhs) -> Self::Output;
+}
+
+impl Div for i32 {
+ type Output = i32;
+ fn div(self, rhs: i32) -> i32 {
+ self / rhs
+ }
+}
+
+#[allow(unconditional_panic)]
+pub fn foo() {
+ // This implicitly generates a panic call.
+ let _ = 1 / 0;
+}
+
+//~ MONO_ITEM fn foo
+//~ MONO_ITEM fn <i32 as Div>::div
+//~ MONO_ITEM fn panic
//[powerpc64le] needs-llvm-components: powerpc
#![crate_type = "rlib"]
-#![feature(no_core, rustc_attrs, lang_items)]
+#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
#![no_core]
#[lang = "sized"]
-// EMIT_MIR issue_78192.f.InstCombine.diff
+// compile-flags: -Zmir-opt-level=1 -Zinline-mir
pub fn f<T>(a: &T) -> *const T {
let b: &*const T = &(a as *const T);
*b
fn main() {
f(&2);
}
+
+// EMIT_MIR issue_78192.f.InstCombine.diff
all:
touch $(TMPDIR)/lib.rmeta
$(AR) crus $(TMPDIR)/libfoo-ffffffff-1.0.rlib $(TMPDIR)/lib.rmeta
- $(RUSTC) foo.rs 2>&1 | $(CGREP) "can't find crate for"
+ $(RUSTC) foo.rs 2>&1 | $(CGREP) "found invalid metadata"
+# needs-llvm-components: x86 arm
+
-include ../tools.mk
all: default
--- /dev/null
+-include ../../run-make-fulldeps/tools.mk
+
+OUTPUT_DIR := "$(TMPDIR)/rustdoc"
+DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foobar_macro --crate-type dylib --print file-names -)
+
+all:
+ $(RUSTC) src/proc.rs --crate-name foobar_macro --edition=2021 --crate-type proc-macro --emit=dep-info,link
+
+ $(RUSTC) src/lib.rs --crate-name foobar --edition=2021 --crate-type lib --emit=dep-info,link
+
+ $(RUSTDOC) examples/ex.rs --crate-name ex --crate-type bin --output $(OUTPUT_DIR) \
+ --extern foobar=$(TMPDIR)/libfoobar.rlib --extern foobar_macro=$(TMPDIR)/$(DYLIB_NAME) \
+ -Z unstable-options --scrape-examples-output-path $(TMPDIR)/ex.calls --scrape-examples-target-crate foobar
+
+ $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --output $(OUTPUT_DIR) \
+ -Z unstable-options --with-examples $(TMPDIR)/ex.calls
+
+ $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs
--- /dev/null
+extern crate foobar;
+extern crate foobar_macro;
+
+use foobar::*;
+use foobar_macro::*;
+
+a_proc_macro!(); // no
+
+#[an_attr_macro]
+fn a() {
+ f(); // no
+}
+
+#[an_attr_macro(with_span)]
+fn b() {
+ f(); // yes
+}
+
+fn c() {
+ a_rules_macro!(f()); // yes
+}
+
+fn d() {
+ a_rules_macro!(()); // no
+}
+
+fn main(){}
--- /dev/null
+// Scraped example should only include line numbers for items b and c in ex.rs
+// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '14'
+// @has foobar/fn.f.html '//*[@class="line-numbers"]' '15'
+// @has foobar/fn.f.html '//*[@class="line-numbers"]' '21'
+// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '22'
+
+pub fn f() {}
+
+#[macro_export]
+macro_rules! a_rules_macro {
+ ($e:expr) => { ($e, foobar::f()); }
+}
--- /dev/null
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro]
+pub fn a_proc_macro(_item: TokenStream) -> TokenStream {
+ "fn ex() { foobar::f(); }".parse().unwrap()
+}
+
+// inserts foobar::f() to the end of the function
+#[proc_macro_attribute]
+pub fn an_attr_macro(attr: TokenStream, item: TokenStream) -> TokenStream {
+ let new_call: TokenStream = "foobar::f();".parse().unwrap();
+
+ let mut tokens = item.into_iter();
+
+ let fn_tok = tokens.next().unwrap();
+ let ident_tok = tokens.next().unwrap();
+ let args_tok = tokens.next().unwrap();
+ let body = match tokens.next().unwrap() {
+ TokenTree::Group(g) => {
+ let new_g = Group::new(g.delimiter(), new_call);
+ let mut outer_g = Group::new(
+ g.delimiter(),
+ [TokenTree::Group(g.clone()), TokenTree::Group(new_g)].into_iter().collect(),
+ );
+
+ if attr.to_string() == "with_span" {
+ outer_g.set_span(g.span());
+ }
+
+ TokenTree::Group(outer_g)
+ }
+ _ => unreachable!(),
+ };
+
+ let tokens = vec![fn_tok, ident_tok, args_tok, body].into_iter().collect::<TokenStream>();
+
+ tokens
+}
--- /dev/null
+include ../../run-make-fulldeps/tools.mk
+
+DYLIB_NAME := $(shell echo | $(RUSTC) --crate-name foo --crate-type dylib --print file-names -)
+
+all:
+ echo >> $(TMPDIR)/$(DYLIB_NAME)
+ $(RUSTC) --crate-type lib --extern foo=$(TMPDIR)/$(DYLIB_NAME) bar.rs 2>&1 | $(CGREP) 'invalid metadata files for crate `foo`'
--- /dev/null
+extern crate foo;
--- /dev/null
+deps := ex
+
+-include ../rustdoc-scrape-examples-multiple/scrape.mk
+
+all: scrape
--- /dev/null
+pub struct Foo([usize; foobar::f()]);
+fn main() {}
--- /dev/null
+pub const fn f() -> usize { 5 }
// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]//*[@class="prev"]' ''
// @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' ''
+// @has src/ex/ex.rs.html
+// @has foobar/fn.ok.html '//a[@href="../src/ex/ex.rs.html#2"]' ''
pub fn ok() {}
fn main() {
- foobar::ok();
+ foobar::ok(0);
// this is a
+ // ..
+
// BIG
// item
fn main() {
- foobar::ok();
+ foobar::ok(1);
// small item
}
+
+fn f() {
+ foobar::ok(2);
+}
// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]' 'ex2'
// @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' 'ex1'
+// @has foobar/fn.ok.html '//*[@class="highlight focus"]' '1'
+// @has foobar/fn.ok.html '//*[@class="highlight"]' '2'
+// @has foobar/fn.ok.html '//*[@class="highlight focus"]' '0'
-pub fn ok() {}
+pub fn ok(_x: i32) {}
assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"font-size": "15.2px"})
assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
+assert-text: (".sidebar .others h3", "Modules")
+assert-css: (".sidebar .others h3", {"border-bottom-width": "1px"}, ALL)
+
goto: file://|DOC_PATH|/test_docs/union.HeavilyDocumentedUnion.html
assert-css: ("h1.fqn", {"font-size": "24px"})
--- /dev/null
+// When JavaScript is disabled, we hide the search bar, because it
+// can't be used without JS.
+javascript: false
+
+goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+assert-css: (".sub", {"display": "none"})
assert-count: (".sidebar .location", 1)
assert-text: (".sidebar-elems > #all-types", "See all test_docs's items")
// We check that we have the crates list and that the "current" on is "test_docs".
-assert-text: (".sidebar-elems > .crate > ul > li > a.current", "test_docs")
+assert-text: (".sidebar-elems .crate > ul > li > a.current", "test_docs")
// And we're also supposed to have the list of items in the current module.
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Macros")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(3)", "Structs")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(4)", "Enums")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(5)", "Traits")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(6)", "Functions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(7)", "Type Definitions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(8)", "Unions")
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(9)", "Keywords")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Modules")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(2)", "Macros")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(3)", "Structs")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(4)", "Enums")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(5)", "Traits")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(6)", "Functions")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(7)", "Type Definitions")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(8)", "Unions")
+assert-text: (".sidebar-elems .items > ul > li:nth-child(9)", "Keywords")
assert-text: ("#structs + .item-table .item-left > a", "Foo")
click: "#structs + .item-table .item-left > a"
assert-false: ".sidebar-elems > .crate"
// We now go back to the crate page to click on the "lib2" crate link.
goto: file://|DOC_PATH|/test_docs/index.html
-click: ".sidebar-elems > .crate > ul > li:first-child > a"
+click: ".sidebar-elems .crate > ul > li:first-child > a"
// PAGE: lib2/index.html
goto: file://|DOC_PATH|/lib2/index.html
assert-text: (".sidebar > .location", "Crate lib2")
// We check that we have the crates list and that the "current" on is now "lib2".
-assert-text: (".sidebar-elems > .crate > ul > li > a.current", "lib2")
+assert-text: (".sidebar-elems .crate > ul > li > a.current", "lib2")
// We now go to the "foobar" function page.
assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
assert-text: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
goto: ./sub_module/sub_sub_module/index.html
assert-text: (".sidebar > .location", "Module sub_sub_module")
// We check that we don't have the crate list.
-assert-false: ".sidebar-elems > .crate"
-assert-text: (".sidebar-elems > .items > ul > li:nth-child(1)", "Functions")
+assert-false: ".sidebar-elems .crate"
+assert-text: (".sidebar-elems .items > ul > li:nth-child(1)", "Functions")
assert-text: ("#functions + .item-table .item-left > a", "foo")
--- /dev/null
+#![feature(doc_auto_cfg)]
+
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// @has - '//*[@class="item-info"]/*[@class="stab portability"]' 'non-test'
+#[cfg(not(test))]
+pub fn foo() {}
#![crate_name = "oud"]
-#![feature(doc_cfg, doc_cfg_hide)]
+#![feature(doc_auto_cfg, doc_cfg, doc_cfg_hide)]
#![doc(cfg_hide(feature = "solecism"))]
#![crate_name = "funambulism"]
-#![feature(doc_cfg)]
+#![feature(doc_auto_cfg, doc_cfg)]
// @has 'funambulism/struct.Disorbed.html'
// @count - '//*[@class="stab portability"]' 1
--- /dev/null
+#![feature(doc_cfg)]
+
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// @count - '//*[@class="item-info"]/*[@class="stab portability"]' 0
+#[cfg(not(test))]
+pub fn foo() {}
+++ /dev/null
-// run-pass
-
-struct X {
- x: isize
-}
-
-fn f1(a: &mut X, b: &mut isize, c: isize) -> isize {
- let r = a.x + *b + c;
- a.x = 0;
- *b = 10;
- return r;
-}
-
-fn f2<F>(a: isize, f: F) -> isize where F: FnOnce(isize) { f(1); return a; }
-
-pub fn main() {
- let mut a = X {x: 1};
- let mut b = 2;
- let c = 3;
- assert_eq!(f1(&mut a, &mut b, c), 6);
- assert_eq!(a.x, 0);
- assert_eq!(b, 10);
- assert_eq!(f2(a.x, |_| a.x = 50), 0);
- assert_eq!(a.x, 50);
-}
--- /dev/null
+// run-pass
+// pretty-expanded FIXME #23616
+
+pub fn main() {
+ let _x: &mut [isize] = &mut [ 1, 2, 3 ];
+}
// only-aarch64
// compile-flags: -C target-feature=+fp
-#![feature(asm)]
+#![feature(asm, asm_const, asm_sym)]
fn main() {
let mut foo = 0;
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
fn const_generic<const X: usize>() -> usize {
unsafe {
// only-aarch64
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
fn main() {
let mut foo = 0;
// only-linux
// run-pass
-#![feature(asm, thread_local)]
+#![feature(asm, thread_local, asm_sym)]
extern "C" fn f1() -> i32 {
111
std::thread::spawn(|| {
assert_eq!(static_addr!(S1), &S1 as *const u32);
assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
- }).join().unwrap();
+ })
+ .join()
+ .unwrap();
}
// only-aarch64
-#![feature(asm, repr_simd, never_type)]
+#![feature(asm, repr_simd, never_type, asm_sym)]
#[repr(simd)]
#[derive(Clone, Copy)]
// only-aarch64
// compile-flags: -C target-feature=+neon
-#![feature(asm, global_asm, repr_simd, stdsimd)]
+#![feature(asm, global_asm, repr_simd, stdsimd, asm_const)]
use std::arch::aarch64::float64x2_t;
#[repr(simd)]
#[derive(Copy, Clone)]
-struct Simd256bit(f64, f64,f64, f64);
+struct Simd256bit(f64, f64, f64, f64);
fn main() {
let f64x2: float64x2_t = unsafe { std::mem::transmute(0i128) };
asm!("{:b}", in(vreg) 0u64);
asm!("{:d}", in(vreg_low16) f64x2);
-
// Template modifier suggestions for sub-registers
asm!("{}", in(reg) 0u8);
warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:48:15
+ --> $DIR/type-check-3.rs:47:15
|
LL | asm!("{}", in(reg) 0u8);
| ^^ --- for this argument
= help: or use the `x` modifier to keep the default formatting of `x0`
warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:50:15
+ --> $DIR/type-check-3.rs:49:15
|
LL | asm!("{}", in(reg) 0u16);
| ^^ ---- for this argument
= help: or use the `x` modifier to keep the default formatting of `x0`
warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:52:15
+ --> $DIR/type-check-3.rs:51:15
|
LL | asm!("{}", in(reg) 0i32);
| ^^ ---- for this argument
= help: or use the `x` modifier to keep the default formatting of `x0`
warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:54:15
+ --> $DIR/type-check-3.rs:53:15
|
LL | asm!("{}", in(reg) 0f32);
| ^^ ---- for this argument
= help: or use the `x` modifier to keep the default formatting of `x0`
warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:57:15
+ --> $DIR/type-check-3.rs:56:15
|
LL | asm!("{}", in(vreg) 0i16);
| ^^ ---- for this argument
= help: or use the `v` modifier to keep the default formatting of `v0`
warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:59:15
+ --> $DIR/type-check-3.rs:58:15
|
LL | asm!("{}", in(vreg) 0f32);
| ^^ ---- for this argument
= help: or use the `v` modifier to keep the default formatting of `v0`
warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:61:15
+ --> $DIR/type-check-3.rs:60:15
|
LL | asm!("{}", in(vreg) 0f64);
| ^^ ---- for this argument
= help: or use the `v` modifier to keep the default formatting of `v0`
warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:63:15
+ --> $DIR/type-check-3.rs:62:15
|
LL | asm!("{}", in(vreg_low16) 0f64);
| ^^ ---- for this argument
= help: or use the `v` modifier to keep the default formatting of `v0`
warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:66:15
+ --> $DIR/type-check-3.rs:65:15
|
LL | asm!("{0} {0}", in(reg) 0i16);
| ^^^ ^^^ ---- for this argument
= help: or use the `x` modifier to keep the default formatting of `x0`
warning: formatting may not be suitable for sub-register argument
- --> $DIR/type-check-3.rs:68:15
+ --> $DIR/type-check-3.rs:67:15
|
LL | asm!("{0} {0:x}", in(reg) 0i16);
| ^^^ ---- for this argument
= help: or use the `x` modifier to keep the default formatting of `x0`
error: type `i128` cannot be used with this register class
- --> $DIR/type-check-3.rs:73:28
+ --> $DIR/type-check-3.rs:72:28
|
LL | asm!("{}", in(reg) 0i128);
| ^^^^^
= note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
error: type `float64x2_t` cannot be used with this register class
- --> $DIR/type-check-3.rs:75:28
+ --> $DIR/type-check-3.rs:74:28
|
LL | asm!("{}", in(reg) f64x2);
| ^^^^^
= note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
error: type `Simd256bit` cannot be used with this register class
- --> $DIR/type-check-3.rs:77:29
+ --> $DIR/type-check-3.rs:76:29
|
LL | asm!("{}", in(vreg) f64x4);
| ^^^^^
= note: register class `vreg` supports these types: i8, i16, i32, i64, f32, f64, i8x8, i16x4, i32x2, i64x1, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
error: incompatible types for asm inout argument
- --> $DIR/type-check-3.rs:88:33
+ --> $DIR/type-check-3.rs:87:33
|
LL | asm!("{:x}", inout(reg) 0u32 => val_f32);
| ^^^^ ^^^^^^^ type `f32`
= note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
error: incompatible types for asm inout argument
- --> $DIR/type-check-3.rs:90:33
+ --> $DIR/type-check-3.rs:89:33
|
LL | asm!("{:x}", inout(reg) 0u32 => val_ptr);
| ^^^^ ^^^^^^^ type `*mut u8`
= note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
error: incompatible types for asm inout argument
- --> $DIR/type-check-3.rs:92:33
+ --> $DIR/type-check-3.rs:91:33
|
LL | asm!("{:x}", inout(reg) main => val_u32);
| ^^^^ ^^^^^^^ type `u32`
= note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
error[E0013]: constants cannot refer to statics
- --> $DIR/type-check-3.rs:108:25
+ --> $DIR/type-check-3.rs:107:25
|
LL | global_asm!("{}", const S);
| ^
= help: consider extracting the value of the `static` to a `const`, and referring to that
error[E0013]: constants cannot refer to statics
- --> $DIR/type-check-3.rs:111:35
+ --> $DIR/type-check-3.rs:110:35
|
LL | global_asm!("{}", const const_foo(S));
| ^
= help: consider extracting the value of the `static` to a `const`, and referring to that
error[E0013]: constants cannot refer to statics
- --> $DIR/type-check-3.rs:114:35
+ --> $DIR/type-check-3.rs:113:35
|
LL | global_asm!("{}", const const_bar(S));
| ^
// [aarch64_thirunsafeck] needs-llvm-components: aarch64
// [aarch64_mirunsafeck] needs-llvm-components: aarch64
-#![feature(no_core, lang_items, rustc_attrs)]
+#![feature(no_core, lang_items, rustc_attrs, asm_const)]
#![no_core]
#[rustc_builtin_macro]
// as both unused and possibly-uninitialized.
// check-pass
+// needs-asm-support
#![feature(asm)]
#![warn(unused)]
warning: unused variable: `x`
- --> $DIR/issue-89305.rs:11:13
+ --> $DIR/issue-89305.rs:12:13
|
LL | let x: () = asm!("nop");
| ^ help: if this is intentional, prefix it with an underscore: `_x`
|
note: the lint level is defined here
- --> $DIR/issue-89305.rs:7:9
+ --> $DIR/issue-89305.rs:8:9
|
LL | #![warn(unused)]
| ^^^^^^
#![feature(llvm_asm)]
#![feature(naked_functions)]
#![feature(or_patterns)]
+#![feature(asm_const, asm_sym)]
#![crate_type = "lib"]
#![allow(deprecated)] // llvm_asm!
#[repr(C)]
-pub struct P { x: u8, y: u16 }
+pub struct P {
+ x: u8,
+ y: u16,
+}
#[naked]
pub unsafe extern "C" fn patterns(
}
#[naked]
-pub unsafe extern "Rust" fn rust_abi() {
+pub unsafe fn rust_abi() {
//~^ WARN Rust ABI is unsupported in naked functions
asm!("", options(noreturn));
}
#[naked]
pub extern "C" fn valid_a<T>() -> T {
- unsafe { asm!("", options(noreturn)); }
+ unsafe {
+ asm!("", options(noreturn));
+ }
}
#[naked]
pub extern "C" fn valid_b() {
- unsafe { { {
- asm!("", options(noreturn)); ; ; ;
- } ; } ; }
+ unsafe {
+ {
+ {
+ asm!("", options(noreturn));
+ };
+ };
+ }
}
#[naked]
error: asm with the `pure` option must have at least one output
- --> $DIR/naked-functions.rs:131:14
+ --> $DIR/naked-functions.rs:135:14
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
error: patterns not allowed in naked function parameters
- --> $DIR/naked-functions.rs:18:5
+ --> $DIR/naked-functions.rs:22:5
|
LL | mut a: u32,
| ^^^^^
error: patterns not allowed in naked function parameters
- --> $DIR/naked-functions.rs:20:5
+ --> $DIR/naked-functions.rs:24:5
|
LL | &b: &i32,
| ^^
error: patterns not allowed in naked function parameters
- --> $DIR/naked-functions.rs:22:6
+ --> $DIR/naked-functions.rs:26:6
|
LL | (None | Some(_)): Option<std::ptr::NonNull<u8>>,
| ^^^^^^^^^^^^^^
error: patterns not allowed in naked function parameters
- --> $DIR/naked-functions.rs:24:5
+ --> $DIR/naked-functions.rs:28:5
|
LL | P { x, y }: P,
| ^^^^^^^^^^
error: referencing function parameters is not allowed in naked functions
- --> $DIR/naked-functions.rs:34:5
+ --> $DIR/naked-functions.rs:38:5
|
LL | a + 1
| ^
= help: follow the calling convention in asm block to use parameters
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:31:1
+ --> $DIR/naked-functions.rs:35:1
|
LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
error: referencing function parameters is not allowed in naked functions
- --> $DIR/naked-functions.rs:40:31
+ --> $DIR/naked-functions.rs:44:31
|
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
| ^
= help: follow the calling convention in asm block to use parameters
warning: only `const` and `sym` operands are supported in naked functions
- --> $DIR/naked-functions.rs:40:23
+ --> $DIR/naked-functions.rs:44:23
|
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
| ^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:47:1
+ --> $DIR/naked-functions.rs:51:1
|
LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: only `const` and `sym` operands are supported in naked functions
- --> $DIR/naked-functions.rs:67:10
+ --> $DIR/naked-functions.rs:71:10
|
LL | in(reg) a,
| ^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
- --> $DIR/naked-functions.rs:64:5
+ --> $DIR/naked-functions.rs:68:5
|
LL | / asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:54:1
+ --> $DIR/naked-functions.rs:58:1
|
LL | / pub unsafe extern "C" fn unsupported_operands() {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:80:1
+ --> $DIR/naked-functions.rs:84:1
|
LL | / pub extern "C" fn missing_assembly() {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
- --> $DIR/naked-functions.rs:89:5
+ --> $DIR/naked-functions.rs:93:5
|
LL | asm!("");
| ^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
- --> $DIR/naked-functions.rs:92:5
+ --> $DIR/naked-functions.rs:96:5
|
LL | asm!("");
| ^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
- --> $DIR/naked-functions.rs:95:5
+ --> $DIR/naked-functions.rs:99:5
|
LL | asm!("");
| ^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:86:1
+ --> $DIR/naked-functions.rs:90:1
|
LL | / pub extern "C" fn too_many_asm_blocks() {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
error: referencing function parameters is not allowed in naked functions
- --> $DIR/naked-functions.rs:106:11
+ --> $DIR/naked-functions.rs:110:11
|
LL | *&y
| ^
= help: follow the calling convention in asm block to use parameters
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:103:5
+ --> $DIR/naked-functions.rs:107:5
|
LL | / pub extern "C" fn inner(y: usize) -> usize {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: the LLVM-style inline assembly is unsupported in naked functions
- --> $DIR/naked-functions.rs:116:5
+ --> $DIR/naked-functions.rs:120:5
|
LL | llvm_asm!("");
| ^^^^^^^^^^^^^
= note: this warning originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: naked functions must contain a single asm block
- --> $DIR/naked-functions.rs:113:1
+ --> $DIR/naked-functions.rs:117:1
|
LL | / unsafe extern "C" fn llvm() -> ! {
LL | |
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm options unsupported in naked functions: `nomem`, `preserves_flags`
- --> $DIR/naked-functions.rs:124:5
+ --> $DIR/naked-functions.rs:128:5
|
LL | asm!("", options(nomem, preserves_flags, noreturn));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
- --> $DIR/naked-functions.rs:131:5
+ --> $DIR/naked-functions.rs:135:5
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
- --> $DIR/naked-functions.rs:131:5
+ --> $DIR/naked-functions.rs:135:5
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: Rust ABI is unsupported in naked functions
- --> $DIR/naked-functions.rs:140:15
+ --> $DIR/naked-functions.rs:144:15
|
LL | pub unsafe fn default_abi() {
| ^^^^^^^^^^^
= note: `#[warn(undefined_naked_function_abi)]` on by default
warning: Rust ABI is unsupported in naked functions
- --> $DIR/naked-functions.rs:146:29
+ --> $DIR/naked-functions.rs:150:15
|
-LL | pub unsafe extern "Rust" fn rust_abi() {
- | ^^^^^^^^
+LL | pub unsafe fn rust_abi() {
+ | ^^^^^^^^
warning: naked functions cannot be inlined
- --> $DIR/naked-functions.rs:180:1
+ --> $DIR/naked-functions.rs:190:1
|
LL | #[inline]
| ^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
- --> $DIR/naked-functions.rs:188:1
+ --> $DIR/naked-functions.rs:198:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
- --> $DIR/naked-functions.rs:196:1
+ --> $DIR/naked-functions.rs:206:1
|
LL | #[inline(never)]
| ^^^^^^^^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
- --> $DIR/naked-functions.rs:204:1
+ --> $DIR/naked-functions.rs:214:1
|
LL | #[inline]
| ^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
- --> $DIR/naked-functions.rs:207:1
+ --> $DIR/naked-functions.rs:217:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
- --> $DIR/naked-functions.rs:210:1
+ --> $DIR/naked-functions.rs:220:1
|
LL | #[inline(never)]
| ^^^^^^^^^^^^^^^^
// which causes less readable LLVM errors and in the worst cases causes ICEs
// or segfaults based on system dependent behavior and codegen flags.
-#![feature(asm, global_asm, naked_functions)]
+#![feature(asm, global_asm, naked_functions, asm_const)]
#[no_mangle]
pub static FOO: usize = 42;
// ignore-spirv
// ignore-wasm32
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
fn main() {
unsafe {
// only-x86_64
// compile-flags: -C target-feature=+avx2
-#![feature(asm)]
+#![feature(asm, asm_const, asm_sym)]
fn main() {
let mut foo = 0;
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
fn const_generic<const X: usize>() -> usize {
unsafe {
// only-x86_64
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
fn main() {
let mut foo = 0;
// only-linux
// run-pass
-#![feature(asm, thread_local)]
+#![feature(asm, thread_local, asm_sym)]
extern "C" fn f1() -> i32 {
111
std::thread::spawn(|| {
assert_eq!(static_addr!(S1), &S1 as *const u32);
assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
- }).join().unwrap();
+ })
+ .join()
+ .unwrap();
}
// only-x86_64
-#![feature(asm, repr_simd, never_type)]
+#![feature(asm, repr_simd, never_type, asm_sym)]
#[repr(simd)]
struct SimdNonCopy(f32, f32, f32, f32);
// only-x86_64
// compile-flags: -C target-feature=+avx512f
-#![feature(asm, global_asm)]
+#![feature(asm, global_asm, asm_const)]
use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
--- /dev/null
+// check-pass
+pub trait LineFormatter<'a> {
+ type Iter: Iterator<Item=&'a str> + 'a;
+ fn iter(&'a self, line: &'a str) -> Self::Iter;
+
+ fn dimensions(&'a self, line: &'a str) {
+ let iter: Self::Iter = self.iter(line);
+ <_ as IntoIterator>::into_iter(iter);
+ }
+}
+
+fn main() {}
--- /dev/null
+// run-pass
+#![allow(dead_code)]
+// Test transitive analysis for associated types. Collected types
+// should be normalized and new obligations generated.
+
+// pretty-expanded FIXME #23616
+
+trait Foo {
+ type A;
+ fn foo(&self) {}
+}
+
+impl Foo for usize {
+ type A = usize;
+}
+
+struct Bar<T: Foo> { inner: T::A }
+
+fn is_send<T: Send>() {}
+
+fn main() {
+ is_send::<Bar<usize>>();
+}
--- /dev/null
+// check-pass
+// Regression test for #28871. The problem is that rustc encountered
+// two ways to project, one from a where clause and one from the where
+// clauses on the trait definition. (In fact, in this case, the where
+// clauses originated from the trait definition as well.) The true
+// cause of the error is that the trait definition where clauses are
+// not being normalized, and hence the two sources are considered in
+// conflict, and not a duplicate. Hacky solution is to prefer where
+// clauses over the data found in the trait definition.
+
+trait T {
+ type T;
+}
+
+struct S;
+impl T for S {
+ type T = S;
+}
+
+trait T2 {
+ type T: Iterator<Item=<S as T>::T>;
+}
+
+fn main() { }
--- /dev/null
+// run-pass
+// Regression test for issue #47139:
+//
+// Coherence was encountering an (unnecessary) overflow trying to
+// decide if the two impls of dummy overlap.
+//
+// The overflow went something like:
+//
+// - `&'a ?T: Insertable` ?
+// - let ?T = Option<?U> ?
+// - `Option<?U>: Insertable` ?
+// - `Option<&'a ?U>: Insertable` ?
+// - `&'a ?U: Insertable` ?
+//
+// While somewhere in the middle, a projection would occur, which
+// broke cycle detection.
+//
+// It turned out that this cycle was being kicked off due to some
+// extended diagnostic attempts in coherence, so removing those
+// sidestepped the issue for now.
+
+#![allow(dead_code)]
+
+pub trait Insertable {
+ type Values;
+
+ fn values(self) -> Self::Values;
+}
+
+impl<T> Insertable for Option<T>
+ where
+ T: Insertable,
+ T::Values: Default,
+{
+ type Values = T::Values;
+
+ fn values(self) -> Self::Values {
+ self.map(Insertable::values).unwrap_or_default()
+ }
+}
+
+impl<'a, T> Insertable for &'a Option<T>
+ where
+ Option<&'a T>: Insertable,
+{
+ type Values = <Option<&'a T> as Insertable>::Values;
+
+ fn values(self) -> Self::Values {
+ self.as_ref().values()
+ }
+}
+
+impl<'a, T> Insertable for &'a [T]
+{
+ type Values = Self;
+
+ fn values(self) -> Self::Values {
+ self
+ }
+}
+
+trait Unimplemented { }
+
+trait Dummy { }
+
+struct Foo<T> { t: T }
+
+impl<'a, U> Dummy for Foo<&'a U>
+ where &'a U: Insertable
+{
+}
+
+impl<T> Dummy for T
+ where T: Unimplemented
+{ }
+
+fn main() {
+}
--- /dev/null
+// run-pass
+
+pub trait Stream {
+ type Item;
+ type Error;
+}
+
+pub trait ParseError<I> {
+ type Output;
+}
+
+impl ParseError<char> for u32 {
+ type Output = ();
+}
+
+impl Stream for () {
+ type Item = char;
+ type Error = u32;
+}
+
+pub struct Lex<'a, I>
+ where I: Stream,
+ I::Error: ParseError<char>,
+ <<I as Stream>::Error as ParseError<char>>::Output: 'a
+{
+ x: &'a <I::Error as ParseError<char>>::Output
+}
+
+pub struct Reserved<'a, I> where
+ I: Stream<Item=char> + 'a,
+ I::Error: ParseError<I::Item>,
+ <<I as Stream>::Error as ParseError<char>>::Output: 'a
+
+{
+ x: Lex<'a, I>
+}
+
+fn main() {
+ let r: Reserved<()> = Reserved {
+ x: Lex {
+ x: &()
+ }
+ };
+
+ let _v = r.x.x;
+}
// edition:2018
+#![feature(must_not_suspend)]
+#![allow(must_not_suspend)]
// This tests the basic example case for the async-await-specific error.
error: future cannot be sent between threads safely
- --> $DIR/issue-64130-non-send-future-diags.rs:21:13
+ --> $DIR/issue-64130-non-send-future-diags.rs:23:13
|
LL | is_send(foo());
| ^^^^^ future returned by `foo` is not `Send`
|
= help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, u32>`
note: future is not `Send` as this value is used across an await
- --> $DIR/issue-64130-non-send-future-diags.rs:15:5
+ --> $DIR/issue-64130-non-send-future-diags.rs:17:5
|
LL | let g = x.lock().unwrap();
| - has type `MutexGuard<'_, u32>` which is not `Send`
LL | }
| - `g` is later dropped here
note: required by a bound in `is_send`
- --> $DIR/issue-64130-non-send-future-diags.rs:7:15
+ --> $DIR/issue-64130-non-send-future-diags.rs:9:15
|
LL | fn is_send<T: Send>(t: T) { }
| ^^^^ required by this bound in `is_send`
// edition:2018
+#![feature(must_not_suspend)]
+#![allow(must_not_suspend)]
use std::future::Future;
use std::sync::Mutex;
error: future cannot be sent between threads safely
- --> $DIR/issue-71137.rs:20:14
+ --> $DIR/issue-71137.rs:22:14
|
LL | fake_spawn(wrong_mutex());
| ^^^^^^^^^^^^^ future returned by `wrong_mutex` is not `Send`
|
= help: within `impl Future`, the trait `Send` is not implemented for `MutexGuard<'_, i32>`
note: future is not `Send` as this value is used across an await
- --> $DIR/issue-71137.rs:12:5
+ --> $DIR/issue-71137.rs:14:5
|
LL | let mut guard = m.lock().unwrap();
| --------- has type `MutexGuard<'_, i32>` which is not `Send`
LL | }
| - `mut guard` is later dropped here
note: required by a bound in `fake_spawn`
- --> $DIR/issue-71137.rs:6:27
+ --> $DIR/issue-71137.rs:8:27
|
LL | fn fake_spawn<F: Future + Send + 'static>(f: F) { }
| ^^^^ required by this bound in `fake_spawn`
--- /dev/null
+// edition:2018
+
+fn main() {
+ 'a: loop {
+ async {
+ loop {
+ continue 'a
+ //~^ ERROR use of unreachable label `'a`
+ }
+ };
+ }
+}
--- /dev/null
+error[E0767]: use of unreachable label `'a`
+ --> $DIR/issue-73541-1.rs:7:26
+ |
+LL | 'a: loop {
+ | -- unreachable label defined here
+...
+LL | continue 'a
+ | ^^ unreachable label `'a`
+ |
+ = note: labels are unreachable through functions, closures, async blocks and modules
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0767`.
--- /dev/null
+// check-pass
+macro_rules! m {
+ ($i:meta) => {
+ #[derive($i)]
+ struct S;
+ }
+}
+
+m!(Clone);
+
+fn main() {}
--- /dev/null
+// build-pass (FIXME(62277): could be check-pass?)
+
+#![feature(rustc_attrs)]
+
+#[rustc_dummy(a b c d)]
+#[rustc_dummy[a b c d]]
+#[rustc_dummy{a b c d}]
+fn main() {}
+++ /dev/null
-#![crate_name = "a"]
-
-pub fn foo<T>() {}
+++ /dev/null
-#![crate_name = "a"]
-
-pub fn foo<T>() { println!("hello!"); }
+++ /dev/null
-#![crate_name = "b"]
-
-extern crate a;
-
-pub fn foo() { a::foo::<isize>(); }
+++ /dev/null
-#![feature(rustc_attrs)]
-
-#[rustc_legacy_const_generics(1)]
-pub fn foo<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
- [x, Y, z]
-}
+++ /dev/null
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-#[no_mangle]
-pub extern "C" fn foo() {}
+++ /dev/null
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-#[no_mangle]
-pub extern "C" fn foo() {}
+++ /dev/null
-// compile-flags: -Clinker-plugin-lto
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn foo() {}
+++ /dev/null
-// original problem
-pub fn foo<T>() -> isize {
- {
- static foo: isize = 2;
- foo
- }
-}
-
-// issue 8134
-struct Foo;
-impl Foo {
- pub fn foo<T>(&self) {
- static X: usize = 1;
- }
-}
-
-// issue 8134
-pub struct Parser<T>(T);
-impl<T: std::iter::Iterator<Item=char>> Parser<T> {
- fn in_doctype(&mut self) {
- static DOCTYPEPattern: [char; 6] = ['O', 'C', 'T', 'Y', 'P', 'E'];
- }
-}
-
-struct Bar;
-impl Foo {
- pub fn bar<T>(&self) {
- static X: usize = 1;
- }
-}
+++ /dev/null
-// check-pass
-
-// Bastion of the Turbofish
-// ------------------------
-// Beware travellers, lest you venture into waters callous and unforgiving,
-// where hope must be abandoned, ere it is cruelly torn from you. For here
-// stands the bastion of the Turbofish: an impenetrable fortress holding
-// unshaking against those who would dare suggest the supererogation of the
-// Turbofish.
-//
-// Once I was young and foolish and had the impudence to imagine that I could
-// shake free from the coils by which that creature had us tightly bound. I
-// dared to suggest that there was a better way: a brighter future, in which
-// Rustaceans both new and old could be rid of that vile beast. But alas! In
-// my foolhardiness my ignorance was unveiled and my dreams were dashed
-// unforgivingly against the rock of syntactic ambiguity.
-//
-// This humble program, small and insignificant though it might seem,
-// demonstrates that to which we had previously cast a blind eye: an ambiguity
-// in permitting generic arguments to be provided without the consent of the
-// Great Turbofish. Should you be so naïve as to try to revolt against its
-// mighty clutches, here shall its wrath be indomitably displayed. This
-// program must pass for all eternity: forever watched by the guardian angel
-// which gave this beast its name, and stands fundamentally at odds with the
-// impetuous rebellion against the Turbofish.
-//
-// My heart aches in sorrow, for I know I am defeated. Let this be a warning
-// to all those who come after: for they too must overcome the impassible
-// hurdle of defeating the great beast, championed by a resolute winged
-// guardian.
-//
-// Here stands the Bastion of the Turbofish, a memorial to Anna Harren,
-// Guardian Angel of these Hallowed Grounds. <3
-
-// See https://github.com/rust-lang/rust/pull/53562
-// and https://github.com/rust-lang/rfcs/pull/2527
-// and https://twitter.com/garblefart/status/1393236602856611843
-// for context.
-
-fn main() {
- let (the, guardian, stands, resolute) = ("the", "Turbofish", "remains", "undefeated");
- let _: (bool, bool) = (the<guardian, stands>(resolute));
-}
--- /dev/null
+// run-pass
+
+#![allow(non_camel_case_types)]
+
+
+#[derive(Copy, Clone, Debug)]
+enum foo { large, small, }
+
+impl PartialEq for foo {
+ fn eq(&self, other: &foo) -> bool {
+ ((*self) as usize) == ((*other) as usize)
+ }
+ fn ne(&self, other: &foo) -> bool { !(*self).eq(other) }
+}
+
+pub fn main() {
+ let a = (1, 2, 3);
+ let b = (1, 2, 3);
+ assert_eq!(a, b);
+ assert!((a != (1, 2, 4)));
+ assert!((a < (1, 2, 4)));
+ assert!((a <= (1, 2, 4)));
+ assert!(((1, 2, 4) > a));
+ assert!(((1, 2, 4) >= a));
+ let x = foo::large;
+ let y = foo::small;
+ assert!((x != y));
+ assert_eq!(x, foo::large);
+ assert!((x != foo::small));
+}
--- /dev/null
+// run-pass
+struct A;
+
+impl A {
+ fn take_mutably(&mut self) {}
+}
+
+fn identity<T>(t: T) -> T {
+ t
+}
+
+// Issue 46095
+// Built-in indexing should be used even when the index is not
+// trivially an integer
+// Overloaded indexing would cause wrapped to be borrowed mutably
+
+fn main() {
+ let mut a1 = A;
+ let mut a2 = A;
+
+ let wrapped = [&mut a1, &mut a2];
+
+ {
+ wrapped[0 + 1 - 1].take_mutably();
+ }
+
+ {
+ wrapped[identity(0)].take_mutably();
+ }
+}
--- /dev/null
+// run-pass
+
+fn f(x: Box<isize>) {
+ let y: &isize = &*x;
+ println!("{}", *x);
+ println!("{}", *y);
+}
+
+trait Trait {
+ fn printme(&self);
+}
+
+struct Struct;
+
+impl Trait for Struct {
+ fn printme(&self) {
+ println!("hello world!");
+ }
+}
+
+fn g(x: Box<dyn Trait>) {
+ x.printme();
+ let y: &dyn Trait = &*x;
+ y.printme();
+}
+
+fn main() {
+ f(Box::new(1234));
+ g(Box::new(Struct) as Box<dyn Trait>);
+}
--- /dev/null
+extern "C" {
+ fn foo(a: i32, ...);
+}
+
+fn bar(_: *const u8) {}
+
+fn main() {
+ unsafe {
+ foo(0, bar);
+ //~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function
+ //~| HELP cast the value to `fn(*const u8)`
+ }
+}
--- /dev/null
+error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function
+ --> $DIR/issue-32201.rs:9:16
+ |
+LL | foo(0, bar);
+ | ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0617`.
--- /dev/null
+// run-pass
+
+pub fn main() {
+ let f = 1_usize as *const String;
+ println!("{:?}", f as isize);
+ println!("{:?}", f as usize);
+ println!("{:?}", f as i8);
+ println!("{:?}", f as i16);
+ println!("{:?}", f as i32);
+ println!("{:?}", f as i64);
+ println!("{:?}", f as u8);
+ println!("{:?}", f as u16);
+ println!("{:?}", f as u32);
+ println!("{:?}", f as u64);
+
+ println!("{:?}", 1 as isize);
+ println!("{:?}", 1 as usize);
+ println!("{:?}", 1 as *const String);
+ println!("{:?}", 1 as i8);
+ println!("{:?}", 1 as i16);
+ println!("{:?}", 1 as i32);
+ println!("{:?}", 1 as i64);
+ println!("{:?}", 1 as u8);
+ println!("{:?}", 1 as u16);
+ println!("{:?}", 1 as u32);
+ println!("{:?}", 1 as u64);
+ println!("{:?}", 1 as f32);
+ println!("{:?}", 1 as f64);
+
+ println!("{:?}", 1_usize as isize);
+ println!("{:?}", 1_usize as usize);
+ println!("{:?}", 1_usize as *const String);
+ println!("{:?}", 1_usize as i8);
+ println!("{:?}", 1_usize as i16);
+ println!("{:?}", 1_usize as i32);
+ println!("{:?}", 1_usize as i64);
+ println!("{:?}", 1_usize as u8);
+ println!("{:?}", 1_usize as u16);
+ println!("{:?}", 1_usize as u32);
+ println!("{:?}", 1_usize as u64);
+ println!("{:?}", 1_usize as f32);
+ println!("{:?}", 1_usize as f64);
+
+ println!("{:?}", 1i8 as isize);
+ println!("{:?}", 1i8 as usize);
+ println!("{:?}", 1i8 as *const String);
+ println!("{:?}", 1i8 as i8);
+ println!("{:?}", 1i8 as i16);
+ println!("{:?}", 1i8 as i32);
+ println!("{:?}", 1i8 as i64);
+ println!("{:?}", 1i8 as u8);
+ println!("{:?}", 1i8 as u16);
+ println!("{:?}", 1i8 as u32);
+ println!("{:?}", 1i8 as u64);
+ println!("{:?}", 1i8 as f32);
+ println!("{:?}", 1i8 as f64);
+
+ println!("{:?}", 1u8 as isize);
+ println!("{:?}", 1u8 as usize);
+ println!("{:?}", 1u8 as *const String);
+ println!("{:?}", 1u8 as i8);
+ println!("{:?}", 1u8 as i16);
+ println!("{:?}", 1u8 as i32);
+ println!("{:?}", 1u8 as i64);
+ println!("{:?}", 1u8 as u8);
+ println!("{:?}", 1u8 as u16);
+ println!("{:?}", 1u8 as u32);
+ println!("{:?}", 1u8 as u64);
+ println!("{:?}", 1u8 as f32);
+ println!("{:?}", 1u8 as f64);
+
+ println!("{:?}", 1i16 as isize);
+ println!("{:?}", 1i16 as usize);
+ println!("{:?}", 1i16 as *const String);
+ println!("{:?}", 1i16 as i8);
+ println!("{:?}", 1i16 as i16);
+ println!("{:?}", 1i16 as i32);
+ println!("{:?}", 1i16 as i64);
+ println!("{:?}", 1i16 as u8);
+ println!("{:?}", 1i16 as u16);
+ println!("{:?}", 1i16 as u32);
+ println!("{:?}", 1i16 as u64);
+ println!("{:?}", 1i16 as f32);
+ println!("{:?}", 1i16 as f64);
+
+ println!("{:?}", 1u16 as isize);
+ println!("{:?}", 1u16 as usize);
+ println!("{:?}", 1u16 as *const String);
+ println!("{:?}", 1u16 as i8);
+ println!("{:?}", 1u16 as i16);
+ println!("{:?}", 1u16 as i32);
+ println!("{:?}", 1u16 as i64);
+ println!("{:?}", 1u16 as u8);
+ println!("{:?}", 1u16 as u16);
+ println!("{:?}", 1u16 as u32);
+ println!("{:?}", 1u16 as u64);
+ println!("{:?}", 1u16 as f32);
+ println!("{:?}", 1u16 as f64);
+
+ println!("{:?}", 1i32 as isize);
+ println!("{:?}", 1i32 as usize);
+ println!("{:?}", 1i32 as *const String);
+ println!("{:?}", 1i32 as i8);
+ println!("{:?}", 1i32 as i16);
+ println!("{:?}", 1i32 as i32);
+ println!("{:?}", 1i32 as i64);
+ println!("{:?}", 1i32 as u8);
+ println!("{:?}", 1i32 as u16);
+ println!("{:?}", 1i32 as u32);
+ println!("{:?}", 1i32 as u64);
+ println!("{:?}", 1i32 as f32);
+ println!("{:?}", 1i32 as f64);
+
+ println!("{:?}", 1u32 as isize);
+ println!("{:?}", 1u32 as usize);
+ println!("{:?}", 1u32 as *const String);
+ println!("{:?}", 1u32 as i8);
+ println!("{:?}", 1u32 as i16);
+ println!("{:?}", 1u32 as i32);
+ println!("{:?}", 1u32 as i64);
+ println!("{:?}", 1u32 as u8);
+ println!("{:?}", 1u32 as u16);
+ println!("{:?}", 1u32 as u32);
+ println!("{:?}", 1u32 as u64);
+ println!("{:?}", 1u32 as f32);
+ println!("{:?}", 1u32 as f64);
+
+ println!("{:?}", 1i64 as isize);
+ println!("{:?}", 1i64 as usize);
+ println!("{:?}", 1i64 as *const String);
+ println!("{:?}", 1i64 as i8);
+ println!("{:?}", 1i64 as i16);
+ println!("{:?}", 1i64 as i32);
+ println!("{:?}", 1i64 as i64);
+ println!("{:?}", 1i64 as u8);
+ println!("{:?}", 1i64 as u16);
+ println!("{:?}", 1i64 as u32);
+ println!("{:?}", 1i64 as u64);
+ println!("{:?}", 1i64 as f32);
+ println!("{:?}", 1i64 as f64);
+
+ println!("{:?}", 1u64 as isize);
+ println!("{:?}", 1u64 as usize);
+ println!("{:?}", 1u64 as *const String);
+ println!("{:?}", 1u64 as i8);
+ println!("{:?}", 1u64 as i16);
+ println!("{:?}", 1u64 as i32);
+ println!("{:?}", 1u64 as i64);
+ println!("{:?}", 1u64 as u8);
+ println!("{:?}", 1u64 as u16);
+ println!("{:?}", 1u64 as u32);
+ println!("{:?}", 1u64 as u64);
+ println!("{:?}", 1u64 as f32);
+ println!("{:?}", 1u64 as f64);
+
+ println!("{:?}", 1u64 as isize);
+ println!("{:?}", 1u64 as usize);
+ println!("{:?}", 1u64 as *const String);
+ println!("{:?}", 1u64 as i8);
+ println!("{:?}", 1u64 as i16);
+ println!("{:?}", 1u64 as i32);
+ println!("{:?}", 1u64 as i64);
+ println!("{:?}", 1u64 as u8);
+ println!("{:?}", 1u64 as u16);
+ println!("{:?}", 1u64 as u32);
+ println!("{:?}", 1u64 as u64);
+ println!("{:?}", 1u64 as f32);
+ println!("{:?}", 1u64 as f64);
+
+ println!("{:?}", true as isize);
+ println!("{:?}", true as usize);
+ println!("{:?}", true as i8);
+ println!("{:?}", true as i16);
+ println!("{:?}", true as i32);
+ println!("{:?}", true as i64);
+ println!("{:?}", true as u8);
+ println!("{:?}", true as u16);
+ println!("{:?}", true as u32);
+ println!("{:?}", true as u64);
+
+ println!("{:?}", 1f32 as isize);
+ println!("{:?}", 1f32 as usize);
+ println!("{:?}", 1f32 as i8);
+ println!("{:?}", 1f32 as i16);
+ println!("{:?}", 1f32 as i32);
+ println!("{:?}", 1f32 as i64);
+ println!("{:?}", 1f32 as u8);
+ println!("{:?}", 1f32 as u16);
+ println!("{:?}", 1f32 as u32);
+ println!("{:?}", 1f32 as u64);
+ println!("{:?}", 1f32 as f32);
+ println!("{:?}", 1f32 as f64);
+
+ println!("{:?}", 1f64 as isize);
+ println!("{:?}", 1f64 as usize);
+ println!("{:?}", 1f64 as i8);
+ println!("{:?}", 1f64 as i16);
+ println!("{:?}", 1f64 as i32);
+ println!("{:?}", 1f64 as i64);
+ println!("{:?}", 1f64 as u8);
+ println!("{:?}", 1f64 as u16);
+ println!("{:?}", 1f64 as u32);
+ println!("{:?}", 1f64 as u64);
+ println!("{:?}", 1f64 as f32);
+ println!("{:?}", 1f64 as f64);
+}
+++ /dev/null
-// ignore-msvc FIXME #31306
-
-// note that these aux-build directives must be in this order
-// aux-build:changing-crates-a1.rs
-// aux-build:changing-crates-b.rs
-// aux-build:changing-crates-a2.rs
-// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
-
-extern crate a;
-extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
-
-fn main() {}
+++ /dev/null
-error[E0460]: found possibly newer version of crate `a` which `b` depends on
- --> $DIR/changing-crates.rs:10:1
- |
-LL | extern crate b;
- | ^^^^^^^^^^^^^^^
- |
- = note: perhaps that crate needs to be recompiled?
- = note: the following crate versions were found:
- crate `a`: $PATH_a
- crate `b`: $PATH_b
-
-error: aborting due to previous error
-
--- /dev/null
+// run-rustfix
+
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE lint level is defined here
+
+fn main() {
+ struct Foo(u32);
+ impl Drop for Foo {
+ fn drop(&mut self) {
+ println!("dropped {}", self.0);
+ }
+ }
+
+ let f0 = Foo(0);
+ let f1 = Foo(1);
+
+ let c0 = move || {
+ let _ = &f0;
+ //~^ ERROR changes to closure capture in Rust 2021 will affect drop order
+ //~| NOTE for more information
+ let _ = f0;
+ //~^ NOTE in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect
+ };
+
+ let c1 = move || {
+ let _ = &f1;
+ };
+
+ println!("dropping 0");
+ drop(c0);
+ println!("dropping 1");
+ drop(c1);
+ println!("dropped all");
+}
+//~^ NOTE in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure
--- /dev/null
+// run-rustfix
+
+#![deny(rust_2021_incompatible_closure_captures)]
+//~^ NOTE lint level is defined here
+
+fn main() {
+ struct Foo(u32);
+ impl Drop for Foo {
+ fn drop(&mut self) {
+ println!("dropped {}", self.0);
+ }
+ }
+
+ let f0 = Foo(0);
+ let f1 = Foo(1);
+
+ let c0 = move || {
+ //~^ ERROR changes to closure capture in Rust 2021 will affect drop order
+ //~| NOTE for more information
+ let _ = f0;
+ //~^ NOTE in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect
+ };
+
+ let c1 = move || {
+ let _ = &f1;
+ };
+
+ println!("dropping 0");
+ drop(c0);
+ println!("dropping 1");
+ drop(c1);
+ println!("dropped all");
+}
+//~^ NOTE in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure
--- /dev/null
+error: changes to closure capture in Rust 2021 will affect drop order
+ --> $DIR/issue-90465.rs:17:14
+ |
+LL | let c0 = move || {
+ | ^^^^^^^
+...
+LL | let _ = f0;
+ | -- in Rust 2018, this causes the closure to capture `f0`, but in Rust 2021, it has no effect
+...
+LL | }
+ | - in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure
+ |
+note: the lint level is defined here
+ --> $DIR/issue-90465.rs:3: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 `f0` to be fully captured
+ |
+LL ~ let c0 = move || {
+LL + let _ = &f0;
+ |
+
+error: aborting due to previous error
+
let mut f = 10;
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 implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` as `fptr.0` does not implement `Send`
+ //~^ ERROR: changes to closure capture
+ //~| NOTE: in Rust 2018, this closure implements `Send`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0 = 20;
let f = CustomInt(&mut f as *mut i32);
let fptr = SyncPointer(f);
thread::spawn(move || { let _ = &fptr; unsafe {
- //~^ ERROR: `Sync`, `Send` trait implementation for closure
- //~| 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`
+ //~^ ERROR: changes to closure capture
+ //~| NOTE: in Rust 2018, this closure implements `Sync`
+ //~| NOTE: in Rust 2018, this closure implements `Send`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0.0 = 20;
let f = U(S(Foo(0)), T(0));
let c = || {
let _ = &f;
- //~^ ERROR: `Clone` trait implementation for closure and drop order
- //~| 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`
+ //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+ //~| NOTE: in Rust 2018, this closure implements `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f` to be fully captured
let f_1 = f.1;
let mut f = 10;
let fptr = SendPointer(&mut f as *mut i32);
thread::spawn(move || unsafe {
- //~^ ERROR: `Send` trait implementation for closure
- //~| 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`
+ //~^ ERROR: changes to closure capture
+ //~| NOTE: in Rust 2018, this closure implements `Send`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0 = 20;
let f = CustomInt(&mut f as *mut i32);
let fptr = SyncPointer(f);
thread::spawn(move || unsafe {
- //~^ ERROR: `Sync`, `Send` trait implementation for closure
- //~| 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`
+ //~^ ERROR: changes to closure capture
+ //~| NOTE: in Rust 2018, this closure implements `Sync`
+ //~| NOTE: in Rust 2018, this closure implements `Send`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr` to be fully captured
*fptr.0.0 = 20;
fn test_clone_trait() {
let f = U(S(Foo(0)), T(0));
let c = || {
- //~^ ERROR: `Clone` trait implementation for closure and drop order
- //~| 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`
+ //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+ //~| NOTE: in Rust 2018, this closure implements `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f` to be fully captured
let f_1 = f.1;
-error: changes to closure capture in Rust 2021 will affect `Send` trait implementation for closure
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
--> $DIR/auto_traits.rs:22:19
|
LL | thread::spawn(move || unsafe {
- | ^^^^^^^^^^^^^^ 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`
+ | ^^^^^^^^^^^^^^ in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0` does not implement `Send`
...
LL | *fptr.0 = 20;
| ------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
LL | *fptr.0 = 20;
...
-error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
--> $DIR/auto_traits.rs:42:19
|
LL | thread::spawn(move || unsafe {
- | ^^^^^^^^^^^^^^ 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`
+ | ^^^^^^^^^^^^^^
+ | |
+ | in Rust 2018, this closure implements `Sync` as `fptr` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr` is not fully captured and `fptr.0.0` does not implement `Sync`
+ | in Rust 2018, this closure implements `Send` as `fptr` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr` is not fully captured and `fptr.0.0` does not implement `Send`
...
LL | *fptr.0.0 = 20;
| --------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0.0`
LL |
LL |
LL |
-LL | *fptr.0.0 = 20;
+LL |
...
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
- --> $DIR/auto_traits.rs:66:13
+error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+ --> $DIR/auto_traits.rs:67:13
|
LL | let c = || {
- | ^^ 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`
+ | ^^ in Rust 2018, this closure implements `Clone` as `f` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f` is not fully captured and `f.1` does not implement `Clone`
...
LL | let f_1 = f.1;
| --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.1`
let f = panic::AssertUnwindSafe(f);
let result = panic::catch_unwind(move || {
let _ = &f;
- //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
- //~| 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`
+ //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+ //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`
+ //~| NOTE: in Rust 2018, this closure implements `RefUnwindSafe`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f` to be fully captured
f.0()
{
let f = panic::AssertUnwindSafe(f);
let result = panic::catch_unwind(move || {
- //~^ ERROR: `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
- //~| 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`
+ //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+ //~| NOTE: in Rust 2018, this closure implements `UnwindSafe`
+ //~| NOTE: in Rust 2018, this closure implements `RefUnwindSafe`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f` to be fully captured
f.0()
-error: changes to closure capture in Rust 2021 will affect `UnwindSafe`, `RefUnwindSafe` trait implementation for closure
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
--> $DIR/mir_calls_to_shims.rs:20:38
|
LL | let result = panic::catch_unwind(move || {
- | ^^^^^^^ 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`
+ | ^^^^^^^
+ | |
+ | in Rust 2018, this closure implements `UnwindSafe` as `f` implements `UnwindSafe`, but in Rust 2021, this closure will no longer implement `UnwindSafe` because `f` is not fully captured and `f.0` does not implement `UnwindSafe`
+ | in Rust 2018, this closure implements `RefUnwindSafe` as `f` implements `RefUnwindSafe`, but in Rust 2021, this closure will no longer implement `RefUnwindSafe` because `f` is not fully captured and `f.0` does not implement `RefUnwindSafe`
...
LL | f.0()
| --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0`
}
}
-
struct S(Foo);
#[derive(Clone)]
let f2 = U(S(Foo::from("bar")), T(0));
let c = || {
let _ = (&f1, &f2);
- //~^ ERROR: `Clone` trait implementation for closure and drop order
- //~| 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`
+ //~^ ERROR: changes to closure capture in Rust 2021
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
let _f_1 = f1.0;
let f1 = U(S(Foo::from("foo")), T(0));
let c = || {
let _ = &f1;
- //~^ ERROR: `Clone` trait implementation for closure
- //~| 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`
+ //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1` to be fully captured
let _f_1 = f1.0;
let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
let c = || {
let _ = &f1;
- //~^ ERROR: `Clone` trait implementation for closure
- //~| 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`
+ //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1` to be fully captured
let _f_0 = f1.0;
let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
let c = || {
let _ = &f1;
- //~^ ERROR: `Clone` trait implementation for closure and drop order
- //~| 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`
+ //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1` to be fully captured
let _f_0 = f1.0;
let mut f2 = 10;
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 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`
+ //~^ ERROR: changes to closure capture in Rust 2021
+ //~| NOTE: in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`
+ //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`
+ //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
*fptr1.0.0 = 20;
}
}
-
struct S(Foo);
#[derive(Clone)]
let f1 = U(S(Foo::from("foo")), T(0));
let f2 = U(S(Foo::from("bar")), T(0));
let c = || {
- //~^ ERROR: `Clone` trait implementation for closure and drop order
- //~| 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`
+ //~^ ERROR: changes to closure capture in Rust 2021
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1`, `f2` to be fully captured
let _f_1 = f1.0;
fn test_capturing_all_disjoint_fields_individually() {
let f1 = U(S(Foo::from("foo")), T(0));
let c = || {
- //~^ ERROR: `Clone` trait implementation for closure
- //~| 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`
+ //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1` to be fully captured
let _f_1 = f1.0;
fn test_capturing_several_disjoint_fields_individually_1() {
let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
let c = || {
- //~^ ERROR: `Clone` trait implementation for closure
- //~| 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`
+ //~^ ERROR: changes to closure capture in Rust 2021 will affect which traits the closure implements [rust_2021_incompatible_closure_captures]
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1` to be fully captured
let _f_0 = f1.0;
fn test_capturing_several_disjoint_fields_individually_2() {
let f1 = U1(S(Foo::from("foo")), T(0), S(Foo::from("bar")));
let c = || {
- //~^ ERROR: `Clone` trait implementation for closure and drop order
- //~| 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`
+ //~^ ERROR: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+ //~| NOTE: in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `f1` to be fully captured
let _f_0 = f1.0;
let mut f2 = 10;
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 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`
+ //~^ ERROR: changes to closure capture in Rust 2021
+ //~| NOTE: in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`
+ //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`
+ //~| NOTE: in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`
//~| NOTE: for more information, see
//~| HELP: add a dummy let to cause `fptr1`, `fptr2` to be fully captured
*fptr1.0.0 = 20;
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
- --> $DIR/multi_diagnostics.rs:38:13
+error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+ --> $DIR/multi_diagnostics.rs:37:13
|
LL | let c = || {
- | ^^ 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` because `f1` is not fully captured and `f1.0` does not implement `Clone`
...
LL | let _f_1 = f1.0;
| ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
LL + let _ = (&f1, &f2);
|
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
- --> $DIR/multi_diagnostics.rs:57:13
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
+ --> $DIR/multi_diagnostics.rs:56:13
|
LL | let c = || {
- | ^^ 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` because `f1` is not fully captured and `f1.0` does not implement `Clone`
...
LL | let _f_1 = f1.0;
| ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
LL + let _ = &f1;
|
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure
- --> $DIR/multi_diagnostics.rs:82:13
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
+ --> $DIR/multi_diagnostics.rs:81:13
|
LL | let c = || {
| ^^
| |
- | 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`
+ | in Rust 2018, this closure implements `Clone` as `f1` implements `Clone`, but in Rust 2021, this closure will no longer implement `Clone` because `f1` is not fully captured and `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` because `f1` is not fully captured and `f1.2` does not implement `Clone`
...
LL | let _f_0 = f1.0;
| ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
LL + let _ = &f1;
|
-error: changes to closure capture in Rust 2021 will affect `Clone` trait implementation for closure and drop order
- --> $DIR/multi_diagnostics.rs:101:13
+error: changes to closure capture in Rust 2021 will affect drop order and which traits the closure implements
+ --> $DIR/multi_diagnostics.rs:100:13
|
LL | let c = || {
- | ^^ 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` because `f1` is not fully captured and `f1.0` does not implement `Clone`
...
LL | let _f_0 = f1.0;
| ---- in Rust 2018, this closure captures all of `f1`, but in Rust 2021, it will only capture `f1.0`
LL + let _ = &f1;
|
-error: changes to closure capture in Rust 2021 will affect `Sync`, `Send` trait implementation for closure
- --> $DIR/multi_diagnostics.rs:134:19
+error: changes to closure capture in Rust 2021 will affect which traits the closure implements
+ --> $DIR/multi_diagnostics.rs:133:19
|
LL | thread::spawn(move || unsafe {
| ^^^^^^^^^^^^^^
| |
- | 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`
+ | in Rust 2018, this closure implements `Sync` as `fptr1` implements `Sync`, but in Rust 2021, this closure will no longer implement `Sync` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Sync`
+ | in Rust 2018, this closure implements `Send` as `fptr1` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr1` is not fully captured and `fptr1.0.0` does not implement `Send`
+ | in Rust 2018, this closure implements `Send` as `fptr2` implements `Send`, but in Rust 2021, this closure will no longer implement `Send` because `fptr2` is not fully captured and `fptr2.0` does not implement `Send`
...
LL | *fptr1.0.0 = 20;
| ---------- in Rust 2018, this closure captures all of `fptr1`, but in Rust 2021, it will only capture `fptr1.0.0`
--- /dev/null
+#![feature(box_syntax)]
+
+fn main() {
+ let x: Box<_> = box 1;
+ let f = move|| {
+ let _a = x;
+ drop(x);
+ //~^ ERROR: use of moved value: `x`
+ };
+ f();
+}
--- /dev/null
+error[E0382]: use of moved value: `x`
+ --> $DIR/issue-10398.rs:7:14
+ |
+LL | let _a = x;
+ | - value moved here
+LL | drop(x);
+ | ^ value used here after move
+ |
+ = note: move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
--- /dev/null
+// run-pass
+use std::ops::{Deref, DerefMut};
+
+struct CheckedDeref<T, F> {
+ value: T,
+ check: F
+}
+
+impl<F: Fn(&T) -> bool, T> Deref for CheckedDeref<T, F> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ assert!((self.check)(&self.value));
+ &self.value
+ }
+}
+
+impl<F: Fn(&T) -> bool, T> DerefMut for CheckedDeref<T, F> {
+ fn deref_mut(&mut self) -> &mut T {
+ assert!((self.check)(&self.value));
+ &mut self.value
+ }
+}
+
+
+fn main() {
+ let mut v = CheckedDeref {
+ value: vec![0],
+ check: |v: &Vec<_>| !v.is_empty()
+ };
+ v.push(1);
+ assert_eq!(*v, vec![0, 1]);
+}
| expected due to this
|
= note: expected unit type `()`
- found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable)]`
+ found closure `[mod1::f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]`
help: use parentheses to call this closure
|
LL | let c1 : () = c();
| expected due to this
|
= note: expected unit type `()`
- found closure `[f<T>::{closure#0} closure_substs=(unavailable)]`
+ found closure `[f<T>::{closure#0} closure_substs=(unavailable) substs=[T, _#25t, extern "rust-call" fn(()), _#26t]]`
help: use parentheses to call this closure
|
LL | let c1 : () = c();
| expected due to this
|
= note: expected fn pointer `fn(u8) -> u8`
- found closure `[main::{closure#0} closure_substs=(unavailable)]`
+ found closure `[main::{closure#0} closure_substs=(unavailable) substs=[i8, extern "rust-call" fn((u8,)) -> u8, _#6t]]`
note: closures can only be coerced to `fn` types if they do not capture any variables
--> $DIR/closure-print-verbose.rs:10:39
|
--- /dev/null
+#![crate_type="rlib"]
+
+#[derive(Debug, PartialEq)]
+pub struct RemoteC(pub u32);
+
+#[derive(Debug, PartialEq)]
+pub struct RemoteG<T>(pub T);
--- /dev/null
+// run-pass
+// All 3 expressions should work in that the argument gets
+// coerced to a trait object
+
+// pretty-expanded FIXME #23616
+
+fn main() {
+ send::<Box<dyn Foo>>(Box::new(Output(0)));
+ Test::<Box<dyn Foo>>::foo(Box::new(Output(0)));
+ Test::<Box<dyn Foo>>::new().send(Box::new(Output(0)));
+}
+
+fn send<T>(_: T) {}
+
+struct Test<T> { marker: std::marker::PhantomData<T> }
+impl<T> Test<T> {
+ fn new() -> Test<T> { Test { marker: ::std::marker::PhantomData } }
+ fn foo(_: T) {}
+ fn send(&self, _: T) {}
+}
+
+trait Foo { fn dummy(&self) { }}
+struct Output(isize);
+impl Foo for Output {}
--- /dev/null
+// run-pass
+// aux-build:issue-39823.rs
+
+extern crate issue_39823;
+use issue_39823::{RemoteC, RemoteG};
+
+#[derive(Debug, PartialEq)]
+struct LocalC(u32);
+
+#[derive(Debug, PartialEq)]
+struct LocalG<T>(T);
+
+fn main() {
+ let virtual_localc : &dyn Fn(_) -> LocalC = &LocalC;
+ assert_eq!(virtual_localc(1), LocalC(1));
+
+ let virtual_localg : &dyn Fn(_) -> LocalG<u32> = &LocalG;
+ assert_eq!(virtual_localg(1), LocalG(1));
+
+ let virtual_remotec : &dyn Fn(_) -> RemoteC = &RemoteC;
+ assert_eq!(virtual_remotec(1), RemoteC(1));
+
+ let virtual_remoteg : &dyn Fn(_) -> RemoteG<u32> = &RemoteG;
+ assert_eq!(virtual_remoteg(1), RemoteG(1));
+}
--- /dev/null
+fn main() {
+ let _ = &&[0] as &[_];
+ //~^ ERROR non-primitive cast: `&&[i32; 1]` as `&[_]`
+ let _ = 7u32 as Option<_>;
+ //~^ ERROR non-primitive cast: `u32` as `Option<_>`
+}
--- /dev/null
+error[E0605]: non-primitive cast: `&&[i32; 1]` as `&[_]`
+ --> $DIR/issue-73886.rs:2:13
+ |
+LL | let _ = &&[0] as &[_];
+ | ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+
+error[E0605]: non-primitive cast: `u32` as `Option<_>`
+ --> $DIR/issue-73886.rs:4:13
+ |
+LL | let _ = 7u32 as Option<_>;
+ | ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)`
+ |
+ = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0605`.
--- /dev/null
+pub struct A;
+impl From<fn((), (), &())> for A {
+ fn from(_: fn((), (), &mut ())) -> Self {
+ //~^ error: method `from` has an incompatible type for trait
+ loop {}
+ }
+}
+
+pub struct B;
+impl From<fn((), (), u32)> for B {
+ fn from(_: fn((), (), u64)) -> Self {
+ //~^ error: method `from` has an incompatible type for trait
+ loop {}
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0053]: method `from` has an incompatible type for trait
+ --> $DIR/issue-90444.rs:3:16
+ |
+LL | fn from(_: fn((), (), &mut ())) -> Self {
+ | ^^^^^^^^^^^^^^^^^^^
+ | |
+ | types differ in mutability
+ | help: change the parameter type to match the trait: `for<'r> fn((), (), &'r ())`
+ |
+ = note: expected fn pointer `fn(for<'r> fn((), (), &'r ())) -> A`
+ found fn pointer `fn(for<'r> fn((), (), &'r mut ())) -> A`
+
+error[E0053]: method `from` has an incompatible type for trait
+ --> $DIR/issue-90444.rs:11:16
+ |
+LL | fn from(_: fn((), (), u64)) -> Self {
+ | ^^^^^^^^^^^^^^^
+ | |
+ | expected `u32`, found `u64`
+ | help: change the parameter type to match the trait: `fn((), (), u32)`
+ |
+ = note: expected fn pointer `fn(fn((), (), u32)) -> B`
+ found fn pointer `fn(fn((), (), u64)) -> B`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
--- /dev/null
+// check-pass
+
+macro_rules! m {
+ () => { #[cfg(any())] fn f() {} }
+}
+
+trait T {}
+impl T for () { m!(); }
+
+fn main() {}
--- /dev/null
+#![feature(rustc_attrs)]
+
+#[rustc_legacy_const_generics(1)]
+pub fn foo<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
+ [x, Y, z]
+}
--- /dev/null
+// aux-build:legacy-const-generics.rs
+
+extern crate legacy_const_generics;
+
+fn foo<const N: usize>() {
+ let a = 1;
+ legacy_const_generics::foo(0, a, 2);
+ //~^ ERROR attempt to use a non-constant value in a constant
+
+ legacy_const_generics::foo(0, N, 2);
+
+ legacy_const_generics::foo(0, N + 1, 2);
+ //~^ ERROR generic parameters may not be used in const operations
+}
+
+fn main() {}
--- /dev/null
+error[E0435]: attempt to use a non-constant value in a constant
+ --> $DIR/legacy-const-generics-bad.rs:7:35
+ |
+LL | let a = 1;
+ | ----- help: consider using `const` instead of `let`: `const a`
+LL | legacy_const_generics::foo(0, a, 2);
+ | ^ non-constant value
+
+error: generic parameters may not be used in const operations
+ --> $DIR/legacy-const-generics-bad.rs:12:35
+ |
+LL | legacy_const_generics::foo(0, N + 1, 2);
+ | ^ cannot perform const operation using `N`
+ |
+ = help: const parameters may only be used as standalone arguments, i.e. `N`
+ = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0435`.
--- /dev/null
+// aux-build:legacy-const-generics.rs
+// run-pass
+
+#![feature(rustc_attrs)]
+
+extern crate legacy_const_generics;
+
+#[rustc_legacy_const_generics(1)]
+pub fn bar<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
+ [x, Y, z]
+}
+
+fn main() {
+ assert_eq!(legacy_const_generics::foo(0 + 0, 1 + 1, 2 + 2), [0, 2, 4]);
+ assert_eq!(legacy_const_generics::foo::<{1 + 1}>(0 + 0, 2 + 2), [0, 2, 4]);
+ // FIXME: Only works cross-crate
+ //assert_eq!(bar(0, 1, 2), [0, 1, 2]);
+}
+// needs-asm-support
+
#![feature(asm)]
const _: () = unsafe { asm!("nop") };
error[E0015]: inline assembly is not allowed in constants
- --> $DIR/inline_asm.rs:3:24
+ --> $DIR/inline_asm.rs:5:24
|
LL | const _: () = unsafe { asm!("nop") };
| ^^^^^^^^^^^
--- /dev/null
+// run-pass
+#![allow(dead_code)]
+#![allow(non_camel_case_types)]
+
+const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80;
+const JSVAL_TYPE_INT32: u8 = 0x01;
+const JSVAL_TYPE_UNDEFINED: u8 = 0x02;
+#[repr(u32)]
+enum ValueTag {
+ JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | (JSVAL_TYPE_INT32 as u32),
+ JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | (JSVAL_TYPE_UNDEFINED as u32),
+}
+
+fn main() {
+ let _ = ValueTag::JSVAL_TAG_INT32;
+}
--- /dev/null
+// run-pass
+#![allow(dead_code)]
+
+static X2: u64 = !0 as u16 as u64;
+static Y2: u64 = !0 as u32 as u64;
+const X: u64 = !0 as u16 as u64;
+const Y: u64 = !0 as u32 as u64;
+
+fn main() {
+ assert_eq!(match 1 {
+ X => unreachable!(),
+ Y => unreachable!(),
+ _ => 1
+ }, 1);
+}
--- /dev/null
+fn main() {
+ const X: u32 = 1;
+ const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR pointers cannot be cast to integers
+ println!("{}", Y);
+}
--- /dev/null
+error: pointers cannot be cast to integers during const eval
+ --> $DIR/issue-18294.rs:3:31
+ |
+LL | const Y: usize = unsafe { &X as *const u32 as usize };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: at compile-time, pointers do not have an integer value
+ = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+const U8_MAX_HALF: u8 = !0u8 / 2;
+const U16_MAX_HALF: u16 = !0u16 / 2;
+const U32_MAX_HALF: u32 = !0u32 / 2;
+const U64_MAX_HALF: u64 = !0u64 / 2;
+
+fn main() {
+ assert_eq!(U8_MAX_HALF, 0x7f);
+ assert_eq!(U16_MAX_HALF, 0x7fff);
+ assert_eq!(U32_MAX_HALF, 0x7fff_ffff);
+ assert_eq!(U64_MAX_HALF, 0x7fff_ffff_ffff_ffff);
+}
--- /dev/null
+const fn x() {
+ let t = true;
+ let x = || t; //~ ERROR function pointer
+}
+
+fn main() {}
--- /dev/null
+error[E0658]: function pointers cannot appear in constant functions
+ --> $DIR/issue-37550-1.rs:3:9
+ |
+LL | let x = || t;
+ | ^
+ |
+ = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
+ = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// run-pass
+
+const fn foo() -> i64 {
+ 3
+}
+
+const fn bar(x: i64) -> i64 {
+ x*2
+}
+
+fn main() {
+ let val = &(foo() % 2);
+ assert_eq!(*val, 1);
+
+ let val2 = &(bar(1+1) % 3);
+ assert_eq!(*val2, 1);
+}
let _val: &'static _ = &(Cell::new(1), 2).1; //~ ERROR temporary value dropped while borrowed
};
+const TEST_DROP: String = String::new();
+
fn main() {
// We must not promote things with interior mutability. Not even if we "project it away".
let _val: &'static _ = &(Cell::new(1), 2).0; //~ ERROR temporary value dropped while borrowed
let _val: &'static _ = &(1%0); //~ ERROR temporary value dropped while borrowed
let _val: &'static _ = &(1%(1-1)); //~ ERROR temporary value dropped while borrowed
let _val: &'static _ = &([1,2,3][4]+1); //~ ERROR temporary value dropped while borrowed
+
+ // No promotion of temporaries that need to be dropped.
+ let _val: &'static _ = &TEST_DROP;
+ //~^ ERROR temporary value dropped while borrowed
+ let _val: &'static _ = &&TEST_DROP;
+ //~^ ERROR temporary value dropped while borrowed
+ //~| ERROR temporary value dropped while borrowed
+ let _val: &'static _ = &(&TEST_DROP,);
+ //~^ ERROR temporary value dropped while borrowed
+ //~| ERROR temporary value dropped while borrowed
+ let _val: &'static _ = &[&TEST_DROP; 1];
+ //~^ ERROR temporary value dropped while borrowed
+ //~| ERROR temporary value dropped while borrowed
}
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/promote-not.rs:44:29
+ --> $DIR/promote-not.rs:46:29
|
LL | let _val: &'static _ = &(Cell::new(1), 2).0;
| ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/promote-not.rs:45:29
+ --> $DIR/promote-not.rs:47:29
|
LL | let _val: &'static _ = &(Cell::new(1), 2).1;
| ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/promote-not.rs:48:29
+ --> $DIR/promote-not.rs:50:29
|
LL | let _val: &'static _ = &(1/0);
| ---------- ^^^^^ creates a temporary which is freed while still in use
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/promote-not.rs:49:29
+ --> $DIR/promote-not.rs:51:29
|
LL | let _val: &'static _ = &(1/(1-1));
| ---------- ^^^^^^^^^ creates a temporary which is freed while still in use
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/promote-not.rs:50:29
+ --> $DIR/promote-not.rs:52:29
|
LL | let _val: &'static _ = &(1%0);
| ---------- ^^^^^ creates a temporary which is freed while still in use
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/promote-not.rs:51:29
+ --> $DIR/promote-not.rs:53:29
|
LL | let _val: &'static _ = &(1%(1-1));
| ---------- ^^^^^^^^^ creates a temporary which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
-LL | let _val: &'static _ = &([1,2,3][4]+1);
+...
LL | }
| - temporary value is freed at the end of this statement
error[E0716]: temporary value dropped while borrowed
- --> $DIR/promote-not.rs:52:29
+ --> $DIR/promote-not.rs:54:29
|
LL | let _val: &'static _ = &([1,2,3][4]+1);
| ---------- ^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
+...
+LL | }
+ | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/promote-not.rs:57:29
+ |
+LL | let _val: &'static _ = &TEST_DROP;
+ | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use
+ | |
+ | type annotation requires that borrow lasts for `'static`
+...
+LL | }
+ | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/promote-not.rs:59:29
+ |
+LL | let _val: &'static _ = &&TEST_DROP;
+ | ---------- ^^^^^^^^^^ creates a temporary which is freed while still in use
+ | |
+ | type annotation requires that borrow lasts for `'static`
+...
+LL | }
+ | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/promote-not.rs:59:30
+ |
+LL | let _val: &'static _ = &&TEST_DROP;
+ | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use
+ | |
+ | type annotation requires that borrow lasts for `'static`
+...
+LL | }
+ | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/promote-not.rs:62:29
+ |
+LL | let _val: &'static _ = &(&TEST_DROP,);
+ | ---------- ^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+ | |
+ | type annotation requires that borrow lasts for `'static`
+...
LL | }
| - temporary value is freed at the end of this statement
-error: aborting due to 13 previous errors
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/promote-not.rs:62:31
+ |
+LL | let _val: &'static _ = &(&TEST_DROP,);
+ | ---------- ^^^^^^^^^ creates a temporary which is freed while still in use
+ | |
+ | type annotation requires that borrow lasts for `'static`
+...
+LL | }
+ | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/promote-not.rs:65:29
+ |
+LL | let _val: &'static _ = &[&TEST_DROP; 1];
+ | ---------- ^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+ | |
+ | type annotation requires that borrow lasts for `'static`
+...
+LL | }
+ | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/promote-not.rs:65:31
+ |
+LL | let _val: &'static _ = &[&TEST_DROP; 1];
+ | ---------- ^^^^^^^^^ - temporary value is freed at the end of this statement
+ | | |
+ | | creates a temporary which is freed while still in use
+ | type annotation requires that borrow lasts for `'static`
+
+error: aborting due to 20 previous errors
For more information about this error, try `rustc --explain E0716`.
#![feature(const_mut_refs)]
#![feature(const_precise_live_drops)]
#![feature(const_swap)]
+#![feature(raw_ref_op)]
// Mutable borrow of a field with drop impl.
pub const fn f() {
let _ = x.is_some();
let _y = x; //~ ERROR destructors cannot be evaluated
}
+
+// Mutable raw reference to a Drop type.
+pub const fn address_of_mut() {
+ let mut x: Option<String> = None; //~ ERROR destructors cannot be evaluated
+ &raw mut x;
+
+ let mut y: Option<String> = None; //~ ERROR destructors cannot be evaluated
+ std::ptr::addr_of_mut!(y);
+}
+
+// Const raw reference to a Drop type. Conservatively assumed to allow mutation
+// until resolution of https://github.com/rust-lang/rust/issues/56604.
+pub const fn address_of_const() {
+ let x: Option<String> = None; //~ ERROR destructors cannot be evaluated
+ &raw const x;
+
+ let y: Option<String> = None; //~ ERROR destructors cannot be evaluated
+ std::ptr::addr_of!(y);
+}
error[E0493]: destructors cannot be evaluated at compile-time
- --> $DIR/qualif-indirect-mutation-fail.rs:8:9
+ --> $DIR/qualif-indirect-mutation-fail.rs:9:9
|
LL | let mut a: (u32, Option<String>) = (0, None);
| ^^^^^ constant functions cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
- --> $DIR/qualif-indirect-mutation-fail.rs:14:9
+ --> $DIR/qualif-indirect-mutation-fail.rs:15:9
|
LL | let mut x = None;
| ^^^^^ constants cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
- --> $DIR/qualif-indirect-mutation-fail.rs:30:9
+ --> $DIR/qualif-indirect-mutation-fail.rs:31:9
|
LL | let _z = x;
| ^^ constants cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
- --> $DIR/qualif-indirect-mutation-fail.rs:35:9
+ --> $DIR/qualif-indirect-mutation-fail.rs:36:9
|
LL | let x: Option<T> = None;
| ^ constant functions cannot evaluate destructors
error[E0493]: destructors cannot be evaluated at compile-time
- --> $DIR/qualif-indirect-mutation-fail.rs:43:9
+ --> $DIR/qualif-indirect-mutation-fail.rs:44:9
|
LL | let _y = x;
| ^^ constant functions cannot evaluate destructors
-error: aborting due to 5 previous errors
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/qualif-indirect-mutation-fail.rs:52:9
+ |
+LL | let mut y: Option<String> = None;
+ | ^^^^^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/qualif-indirect-mutation-fail.rs:49:9
+ |
+LL | let mut x: Option<String> = None;
+ | ^^^^^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/qualif-indirect-mutation-fail.rs:62:9
+ |
+LL | let y: Option<String> = None;
+ | ^ constant functions cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+ --> $DIR/qualif-indirect-mutation-fail.rs:59:9
+ |
+LL | let x: Option<String> = None;
+ | ^ constant functions cannot evaluate destructors
+
+error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0493`.
#![feature(const_mut_refs)]
#![feature(const_precise_live_drops)]
+// Mutable reference allows only mutation of !Drop place.
pub const fn f() {
let mut x: (Option<String>, u32) = (None, 0);
let mut a = 10;
x.1 = a;
}
+// Mutable reference allows only mutation of !Drop place.
pub const fn g() {
let mut a: (u32, Option<String>) = (0, None);
let _ = &mut a.0;
}
+
+// Shared reference does not allow for mutation.
+pub const fn h() {
+ let x: Option<String> = None;
+ let _ = &x;
+}
--- /dev/null
+// compile-flags: --crate-type lib --extern foo={{src-base}}/crate-loading/auxiliary/libfoo.rlib
+// normalize-stderr-test: "failed to mmap file '.*auxiliary/libfoo.rlib':.*" -> "failed to mmap file 'auxiliary/libfoo.rlib'"
+// don't emit warn logging, it's basically the same as the errors and it's annoying to normalize
+// rustc-env:RUSTC_LOG=error
+// edition:2018
+#![no_std]
+use ::foo; //~ ERROR invalid metadata files for crate `foo`
+//~| NOTE failed to mmap file
--- /dev/null
+error[E0786]: found invalid metadata files for crate `foo`
+ --> $DIR/invalid-rlib.rs:7:7
+ |
+LL | use ::foo;
+ | ^^^
+ |
+ = note: failed to mmap file 'auxiliary/libfoo.rlib'
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0786`.
--- /dev/null
+// compile-flags: --edition 2018
+fn foo() -> Result<(), ()> {
+ Ok(try!()); //~ ERROR use of deprecated `try` macro
+ Ok(try!(Ok(()))) //~ ERROR use of deprecated `try` macro
+}
+
+fn main() {
+ let _ = foo();
+}
--- /dev/null
+error: use of deprecated `try` macro
+ --> $DIR/try-macro-suggestion.rs:3:8
+ |
+LL | Ok(try!());
+ | ^^^^^^
+ |
+ = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
+help: you can still access the deprecated `try!()` macro using the "raw identifier" syntax
+ |
+LL | Ok(r#try!());
+ | ++
+
+error: use of deprecated `try` macro
+ --> $DIR/try-macro-suggestion.rs:4:8
+ |
+LL | Ok(try!(Ok(())))
+ | ^^^^^^^^^^^^
+ |
+ = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
+help: you can use the `?` operator instead
+ |
+LL - Ok(try!(Ok(())))
+LL + Ok(Ok(())?)
+ |
+help: alternatively, you can still access the deprecated `try!()` macro using the "raw identifier" syntax
+ |
+LL | Ok(r#try!(Ok(())))
+ | ++
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// run-pass
+
+#![allow(dead_code)]
+
+trait Trait { fn dummy(&self) { } }
+
+#[derive(Debug)]
+struct Foo<T: Trait> {
+ foo: T,
+}
+
+#[derive(Debug)]
+struct Bar<T> where T: Trait {
+ bar: T,
+}
+
+impl Trait for isize {}
+
+fn main() {
+ let a = Foo { foo: 12 };
+ let b = Bar { bar: 12 };
+ println!("{:?} {:?}", a, b);
+}
--- /dev/null
+// run-pass
+fn main() {}
+#[derive(Clone)]
+pub struct Little;
+#[derive(Clone)]
+pub struct Big(
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+ Little,
+);
+++ /dev/null
-// After #39485, this test used to pass, but that change was reverted
-// due to numerous inference failures like #39808, so it now fails
-// again. #39485 made it so that diverging types never propagate
-// upward; but we now do propagate such types upward in many more
-// cases.
-
-fn g() {
- &panic!() //~ ERROR mismatched types
-}
-
-fn f() -> isize {
- (return 1, return 2) //~ ERROR mismatched types
-}
-
-fn main() {}
+++ /dev/null
-error[E0308]: mismatched types
- --> $DIR/diverging-tuple-parts-39485.rs:8:5
- |
-LL | &panic!()
- | ^^^^^^^^^ expected `()`, found reference
- |
- = note: expected unit type `()`
- found reference `&_`
-help: try adding a return type
- |
-LL | fn g() -> &_ {
- | +++++
-help: consider removing the borrow
- |
-LL - &panic!()
-LL + panic!()
- |
-
-error[E0308]: mismatched types
- --> $DIR/diverging-tuple-parts-39485.rs:12:5
- |
-LL | fn f() -> isize {
- | ----- expected `isize` because of return type
-LL | (return 1, return 2)
- | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple
- |
- = note: expected type `isize`
- found tuple `(!, !)`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// build-pass
+#![allow(dead_code)]
+// Regression test for #35546. Check that we are able to codegen
+// this. Before we had problems because of the drop glue signature
+// around dropping a trait object (specifically, when dropping the
+// `value` field of `Node<Send>`).
+
+struct Node<T: ?Sized + Send> {
+ next: Option<Box<Node<dyn Send>>>,
+ value: T,
+}
+
+fn clear(head: &mut Option<Box<Node<dyn Send>>>) {
+ match head.take() {
+ Some(node) => *head = node.next,
+ None => (),
+ }
+}
+
+fn main() {}
--- /dev/null
+// run-pass
+// ignore-emscripten no threads support
+
+// Issue #787
+// Don't try to clean up uninitialized locals
+
+
+use std::thread;
+
+fn test_break() { loop { let _x: Box<isize> = break; } }
+
+fn test_cont() { let mut i = 0; while i < 1 { i += 1; let _x: Box<isize> = continue; } }
+
+fn test_ret() { let _x: Box<isize> = return; }
+
+fn test_panic() {
+ fn f() { let _x: Box<isize> = panic!(); }
+ thread::spawn(move|| f() ).join().unwrap_err();
+}
+
+fn test_panic_indirect() {
+ fn f() -> ! { panic!(); }
+ fn g() { let _x: Box<isize> = f(); }
+ thread::spawn(move|| g() ).join().unwrap_err();
+}
+
+pub fn main() {
+ test_break();
+ test_cont();
+ test_ret();
+ test_panic();
+ test_panic_indirect();
+}
--- /dev/null
+// run-pass
+
+// Demonstrate the use of the unguarded escape hatch with a type param in negative position
+// to assert that destructor will not access any dead data.
+//
+// Compare with ui/span/issue28498-reject-lifetime-param.rs
+
+// Demonstrate that a type param in negative position causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
+
+#![feature(dropck_eyepatch)]
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+ fn drop(&mut self) {
+ self.0 = format!("DROPPED");
+ }
+}
+
+struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
+
+unsafe impl<#[may_dangle] T> Drop for Foo<T> {
+ fn drop(&mut self) {
+ // Use of `may_dangle` is sound, because destructor never passes a `self.1`
+ // to the callback (in `self.2`) despite having it available.
+ println!("Dropping Foo({}, _)", self.0);
+ }
+}
+
+fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
+
+fn main() {
+ let (last_dropped, foo0);
+ let (foo1, first_dropped);
+
+ last_dropped = ScribbleOnDrop(format!("last"));
+ first_dropped = ScribbleOnDrop(format!("first"));
+ foo0 = Foo(0, &last_dropped, Box::new(callback));
+ foo1 = Foo(1, &first_dropped, Box::new(callback));
+
+ println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
+++ /dev/null
-// edition:2015
-
-mod inner {
- fn global_inner(_: ::nonexistant::Foo) {
- //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`?
- }
- fn crate_inner(_: crate::nonexistant::Foo) {
- //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`?
- }
-
- fn bare_global(_: ::nonexistant) {
- //~^ ERROR cannot find type `nonexistant` in the crate root
- }
- fn bare_crate(_: crate::nonexistant) {
- //~^ ERROR cannot find type `nonexistant` in the crate root
- }
-}
-
-fn main() {
-
-}
+++ /dev/null
-error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
- --> $DIR/editions-crate-root-2015.rs:4:26
- |
-LL | fn global_inner(_: ::nonexistant::Foo) {
- | ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
-
-error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
- --> $DIR/editions-crate-root-2015.rs:7:30
- |
-LL | fn crate_inner(_: crate::nonexistant::Foo) {
- | ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
-
-error[E0412]: cannot find type `nonexistant` in the crate root
- --> $DIR/editions-crate-root-2015.rs:11:25
- |
-LL | fn bare_global(_: ::nonexistant) {
- | ^^^^^^^^^^^ not found in the crate root
-
-error[E0412]: cannot find type `nonexistant` in the crate root
- --> $DIR/editions-crate-root-2015.rs:14:29
- |
-LL | fn bare_crate(_: crate::nonexistant) {
- | ^^^^^^^^^^^ not found in the crate root
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0412, E0433.
-For more information about an error, try `rustc --explain E0412`.
--- /dev/null
+// run-pass
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+// Checks if the correct registers are being used to pass arguments
+// when the sysv64 ABI is specified.
+
+#![feature(rust_2018_preview)]
+
+pub trait Foo {}
+
+// should compile without the dyn trait feature flag
+fn foo(x: &dyn Foo) {}
+
+pub fn main() {}
--- /dev/null
+// run-pass
+#![feature(core_intrinsics)]
+
+#[repr(i8)]
+pub enum Enum {
+ VariantA,
+ VariantB,
+}
+
+fn make_b() -> Enum { Enum::VariantB }
+
+fn main() {
+ assert_eq!(1, make_b() as i8);
+ assert_eq!(1, make_b() as u8);
+ assert_eq!(1, make_b() as i32);
+ assert_eq!(1, make_b() as u32);
+ assert_eq!(1, std::intrinsics::discriminant_value(&make_b()));
+}
--- /dev/null
+// run-pass
+macro_rules! fooN {
+ ($cur:ident $prev:ty) => {
+ #[allow(dead_code)]
+ enum $cur {
+ Empty,
+ First($prev),
+ Second($prev),
+ Third($prev),
+ Fourth($prev),
+ }
+ }
+}
+
+fooN!(Foo0 ());
+fooN!(Foo1 Foo0);
+fooN!(Foo2 Foo1);
+fooN!(Foo3 Foo2);
+fooN!(Foo4 Foo3);
+fooN!(Foo5 Foo4);
+fooN!(Foo6 Foo5);
+fooN!(Foo7 Foo6);
+fooN!(Foo8 Foo7);
+fooN!(Foo9 Foo8);
+fooN!(Foo10 Foo9);
+fooN!(Foo11 Foo10);
+fooN!(Foo12 Foo11);
+fooN!(Foo13 Foo12);
+fooN!(Foo14 Foo13);
+fooN!(Foo15 Foo14);
+fooN!(Foo16 Foo15);
+fooN!(Foo17 Foo16);
+fooN!(Foo18 Foo17);
+fooN!(Foo19 Foo18);
+fooN!(Foo20 Foo19);
+fooN!(Foo21 Foo20);
+fooN!(Foo22 Foo21);
+fooN!(Foo23 Foo22);
+fooN!(Foo24 Foo23);
+fooN!(Foo25 Foo24);
+fooN!(Foo26 Foo25);
+fooN!(Foo27 Foo26);
+
+fn main() {
+ let _foo = Foo27::Empty;
+}
+++ /dev/null
-// run-pass
-
-#![allow(dead_code)]
-#![allow(unused_variables)]
-// Checks if the correct registers are being used to pass arguments
-// when the sysv64 ABI is specified.
-
-#![feature(rust_2018_preview)]
-
-pub trait Foo {}
-
-// should compile without the dyn trait feature flag
-fn foo(x: &dyn Foo) {}
-
-pub fn main() {}
// run-pass
-// only-i686
+// only-x86
trait A {
extern "fastcall" fn test1(i: i32);
// run-pass
-// only-i686
+// only-x86
#![feature(abi_thiscall)]
// run-pass
// revisions: x64 x32
// [x64]only-x86_64
-// [x32]only-i686
+// [x32]only-x86
#![feature(abi_vectorcall)]
--- /dev/null
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+ --> $DIR/issue-28324.rs:8:24
+ |
+LL | pub static BAZ: u32 = *&error_message_count;
+ | ^^^^^^^^^^^^^^^^^^^^ use of extern static
+ |
+ = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
--- /dev/null
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+extern "C" {
+ static error_message_count: u32;
+}
+
+pub static BAZ: u32 = *&error_message_count;
+//~^ ERROR use of extern static is unsafe and requires
+
+fn main() {}
--- /dev/null
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+ --> $DIR/issue-28324.rs:8:25
+ |
+LL | pub static BAZ: u32 = *&error_message_count;
+ | ^^^^^^^^^^^^^^^^^^^ use of extern static
+ |
+ = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
--- /dev/null
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+ unsafe {
+ asm!("mov eax, {}", const 123);
+ //~^ ERROR const operands for inline assembly are unstable
+ }
+}
--- /dev/null
+error[E0658]: const operands for inline assembly are unstable
+ --> $DIR/feature-gate-asm_const.rs:7:29
+ |
+LL | asm!("mov eax, {}", const 123);
+ | ^^^^^^^^^
+ |
+ = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
+ = help: add `#![feature(asm_const)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// compile-flags: --target mips-unknown-linux-gnu
+// needs-llvm-components: mips
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![crate_type = "rlib"]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+ () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+unsafe fn main() {
+ asm!("");
+ //~^ ERROR inline assembly is not stable yet on this architecture
+}
--- /dev/null
+error[E0658]: inline assembly is not stable yet on this architecture
+ --> $DIR/feature-gate-asm_experimental_arch.rs:19:5
+ |
+LL | asm!("");
+ | ^^^^^^^^
+ |
+ = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
+ = help: add `#![feature(asm_experimental_arch)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+ unsafe {
+ asm!("mov eax, {}", sym main);
+ //~^ ERROR sym operands for inline assembly are unstable
+ }
+}
--- /dev/null
+error[E0658]: sym operands for inline assembly are unstable
+ --> $DIR/feature-gate-asm_sym.rs:7:29
+ |
+LL | asm!("mov eax, {}", sym main);
+ | ^^^^^^^^
+ |
+ = note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
+ = help: add `#![feature(asm_sym)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
+++ /dev/null
-// Test that we allow unsizing even if there is an unchanged param in the
-// field getting unsized.
-struct A<T, U: ?Sized + 'static>(T, B<T, U>);
-struct B<T, U: ?Sized>(T, U);
-
-fn main() {
- let x: A<[u32; 1], [u32; 1]> = A([0; 1], B([0; 1], [0; 1]));
- let y: &A<[u32; 1], [u32]> = &x; //~ ERROR mismatched types
- assert_eq!(y.1.1.len(), 1);
-}
+++ /dev/null
-error[E0308]: mismatched types
- --> $DIR/feature-gate-relaxed_struct_unsize.rs:8:34
- |
-LL | let y: &A<[u32; 1], [u32]> = &x;
- | ------------------- ^^ expected slice `[u32]`, found array `[u32; 1]`
- | |
- | expected due to this
- |
- = note: expected reference `&A<[u32; 1], [u32]>`
- found reference `&A<[u32; 1], [u32; 1]>`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// run-pass
+#![allow(unreachable_code)]
+
+fn main() {
+ let mut v = Vec::new();
+
+ loop { v.push(break) }
+}
--- /dev/null
+// run-pass
+// pretty-expanded FIXME #23616
+
+#![allow(unused_variables)]
+
+pub fn main() {
+ let mut i: isize = 0;
+ while i < 1000000 {
+ i += 1;
+ let x = 3;
+ }
+}
--- /dev/null
+// run-pass
+
+#![allow(improper_ctypes)]
+#![allow(dead_code)]
+// Issue #901
+// pretty-expanded FIXME #23616
+
+mod libc {
+ extern "C" {
+ pub fn printf(x: ());
+ }
+}
+
+pub fn main() {}
// check that we don't normalize with trait defaults.
trait Collection<T> {
- type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
+ type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter, Self: 'iter;
type Family: CollectionFamily;
// Test associated type defaults with parameters
type Sibling<U>: Collection<U> =
// run-pass
trait Collection<T> {
- type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter;
+ type Iter<'iter>: Iterator<Item=&'iter T> where T: 'iter, Self: 'iter;
type Family: CollectionFamily;
// Test associated type defaults with parameters
type Sibling<U>: Collection<U> =
#![feature(generic_associated_types)]
pub trait X {
- type Y<'a>;
+ type Y<'a> where Self: 'a;
fn m(&self) -> Self::Y<'_>;
}
#![feature(generic_associated_types)]
trait Document {
- type Cursor<'a>: DocCursor<'a>;
+ type Cursor<'a>: DocCursor<'a> where Self: 'a;
fn cursor(&self) -> Self::Cursor<'_>;
}
pub trait SubTrait {}
pub trait SuperTrait {
- type SubType<'a>: SubTrait;
+ type SubType<'a>: SubTrait where Self: 'a;
fn get_sub<'a>(&'a mut self) -> Self::SubType<'a>;
}
note: associated type defined here, with 1 lifetime parameter: `'a`
--> $DIR/issue-76535.rs:6:10
|
-LL | type SubType<'a>: SubTrait;
+LL | type SubType<'a>: SubTrait where Self: 'a;
| ^^^^^^^ --
help: add missing lifetime argument
|
|
LL | pub trait SuperTrait {
| ---------- this trait cannot be made into an object...
-LL | type SubType<'a>: SubTrait;
+LL | type SubType<'a>: SubTrait where Self: 'a;
| ^^^^^^^ ...because it contains the generic associated type `SubType`
= help: consider moving `SubType` to another trait
|
LL | pub trait SuperTrait {
| ---------- this trait cannot be made into an object...
-LL | type SubType<'a>: SubTrait;
+LL | type SubType<'a>: SubTrait where Self: 'a;
| ^^^^^^^ ...because it contains the generic associated type `SubType`
= help: consider moving `SubType` to another trait
= note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
}
trait MapLike<K, V> {
- type VRefCont<'a>: RefCont<'a, V>;
+ type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
fn get<'a>(&'a self, key: &K) -> Option<Self::VRefCont<'a>>;
}
impl<K: Ord, V: 'static> MapLike<K, V> for std::collections::BTreeMap<K, V> {
- type VRefCont<'a> = &'a V;
+ type VRefCont<'a> where Self: 'a = &'a V;
fn get<'a>(&'a self, key: &K) -> Option<&'a V> {
std::collections::BTreeMap::get(self, key)
}
note: associated type defined here, with 1 lifetime parameter: `'a`
--> $DIR/issue-79422.rs:20:10
|
-LL | type VRefCont<'a>: RefCont<'a, V>;
+LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
| ^^^^^^^^ --
help: add missing lifetime argument
|
|
LL | trait MapLike<K, V> {
| ------- this trait cannot be made into an object...
-LL | type VRefCont<'a>: RefCont<'a, V>;
+LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
= help: consider moving `VRefCont` to another trait
|
LL | trait MapLike<K, V> {
| ------- this trait cannot be made into an object...
-LL | type VRefCont<'a>: RefCont<'a, V>;
+LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
= help: consider moving `VRefCont` to another trait
= note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>`
pub trait HasChildrenOf {
type T;
type TRef<'a>;
+ //~^ Missing required bounds
fn ref_children<'a>(&'a self) -> Vec<Self::TRef<'a>>;
fn take_children(self) -> Vec<Self::T>;
Right: HasChildrenOf,
{
type T = Either<Left::T, Right::T>;
+ // We used to error below because the where clause doesn't match the trait.
+ // Now, we error early on the trait itself.
type TRef<'a>
- //~^ `impl` associated type signature
- //~^^ `impl` associated type signature
where
<Left as HasChildrenOf>::T: 'a,
<Right as HasChildrenOf>::T: 'a
-error: `impl` associated type signature for `TRef` doesn't match `trait` associated type signature
- --> $DIR/issue-86787.rs:23:5
+error: Missing required bounds on TRef
+ --> $DIR/issue-86787.rs:11:5
|
-LL | type TRef<'a>;
- | -------------- expected
-...
-LL | / type TRef<'a>
-LL | |
-LL | |
-LL | | where
-LL | | <Left as HasChildrenOf>::T: 'a,
-LL | | <Right as HasChildrenOf>::T: 'a
-LL | | = Either<&'a Left::T, &'a Right::T>;
- | |________________________________________^ found
+LL | type TRef<'a>;
+ | ^^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where Self: 'a`
-error: `impl` associated type signature for `TRef` doesn't match `trait` associated type signature
- --> $DIR/issue-86787.rs:23:5
- |
-LL | type TRef<'a>;
- | -------------- expected
-...
-LL | / type TRef<'a>
-LL | |
-LL | |
-LL | | where
-LL | | <Left as HasChildrenOf>::T: 'a,
-LL | | <Right as HasChildrenOf>::T: 'a
-LL | | = Either<&'a Left::T, &'a Right::T>;
- | |________________________________________^ found
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
trait SearchableResourceExt<Criteria>: SearchableResource<Criteria> {
type Future<'f, A: 'f + ?Sized, B: 'f>: Future<Output = Result<Vec<A::SearchResult>, ()>> + 'f
where
- A: SearchableResource<B>;
+ A: SearchableResource<B>,
+ Self: 'f;
fn search<'c>(&'c self, client: &'c ()) -> Self::Future<'c, Self, Criteria>;
}
type Future<'f, A, B: 'f>
where
A: SearchableResource<B> + ?Sized + 'f,
+ Self: 'f,
= SearchFutureTy<'f, A, B>;
fn search<'c>(&'c self, _client: &'c ()) -> Self::Future<'c, Self, Criteria> {
#![feature(generic_associated_types)]
trait GatTrait {
- type Gat<'a>;
+ type Gat<'a> where Self: 'a;
fn test(&self) -> Self::Gat<'_>;
}
trait SuperTrait<T>
where
+ Self: 'static,
for<'a> Self: GatTrait<Gat<'a> = &'a T>,
{
fn copy(&self) -> Self::Gat<'_> where T: Copy {
error[E0308]: mismatched types
- --> $DIR/issue-88360.rs:14:9
+ --> $DIR/issue-88360.rs:15:9
|
LL | trait SuperTrait<T>
| - this type parameter
--- /dev/null
+// check-pass
+
+#![feature(generic_associated_types)]
+
+trait Trait {
+ type Assoc<'a>;
+}
+
+fn f<T: Trait>(_: T, _: impl Fn(T::Assoc<'_>)) {}
+
+struct Type;
+
+impl Trait for Type {
+ type Assoc<'a> = ();
+}
+
+fn main() {
+ f(Type, |_|());
+}
#![feature(generic_associated_types)]
pub trait X {
- type Y<'a>;
+ type Y<'a> where Self: 'a;
fn m(&self) -> Self::Y<'_>;
}
--- /dev/null
+#![feature(generic_associated_types)]
+
+// check-fail
+
+use std::fmt::Debug;
+
+// We have a `&'a self`, so we need a `Self: 'a`
+trait Iterable {
+ type Item<'x>;
+ //~^ Missing required bounds
+ fn iter<'a>(&'a self) -> Self::Item<'a>;
+}
+
+/*
+impl<T> Iterable for T {
+ type Item<'a> = &'a T;
+ fn iter<'a>(&'a self) -> Self::Item<'a> {
+ self
+ }
+}
+*/
+
+// We have a `&'a T`, so we need a `T: 'x`
+trait Deserializer<T> {
+ type Out<'x>;
+ //~^ Missing required bounds
+ fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a>;
+}
+
+/*
+impl<T> Deserializer<T> for () {
+ type Out<'a> = &'a T;
+ fn deserialize<'a>(&self, input: &'a T) -> Self::Out<'a> { input }
+}
+*/
+
+// We have a `&'b T` and a `'b: 'a`, so it is implied that `T: 'a`. Therefore, we need a `T: 'x`
+trait Deserializer2<T> {
+ type Out<'x>;
+ //~^ Missing required bounds
+ fn deserialize2<'a, 'b: 'a>(&self, input1: &'b T) -> Self::Out<'a>;
+}
+
+// We have a `&'a T` and a `&'b U`, so we need a `T: 'x` and a `U: 'y`
+trait Deserializer3<T, U> {
+ type Out<'x, 'y>;
+ //~^ Missing required bounds
+ fn deserialize2<'a, 'b>(&self, input: &'a T, input2: &'b U) -> Self::Out<'a, 'b>;
+}
+
+// `T` is a param on the function, so it can't be named by the associated type
+trait Deserializer4 {
+ type Out<'x>;
+ fn deserialize<'a, T>(&self, input: &'a T) -> Self::Out<'a>;
+}
+
+struct Wrap<T>(T);
+
+// We pass `Wrap<T>` and we see `&'z Wrap<T>`, so we require `D: 'x`
+trait Des {
+ type Out<'x, D>;
+ //~^ Missing required bounds
+ fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, Wrap<T>>;
+}
+/*
+impl Des for () {
+ type Out<'x, D> = &'x D; // Not okay
+ fn des<'a, T>(&self, data: &'a Wrap<T>) -> Self::Out<'a, Wrap<T>> {
+ data
+ }
+}
+*/
+
+// We have `T` and `'z` as GAT substs. Because of `&'z Wrap<T>`, there is an
+// implied bound that `T: 'z`, so we require `D: 'x`
+trait Des2 {
+ type Out<'x, D>;
+ //~^ Missing required bounds
+ fn des<'z, T>(&self, data: &'z Wrap<T>) -> Self::Out<'z, T>;
+}
+/*
+impl Des2 for () {
+ type Out<'x, D> = &'x D;
+ fn des<'a, T>(&self, data: &'a Wrap<T>) -> Self::Out<'a, T> {
+ &data.0
+ }
+}
+*/
+
+// We see `&'z T`, so we require `D: 'x`
+trait Des3 {
+ type Out<'x, D>;
+ //~^ Missing required bounds
+ fn des<'z, T>(&self, data: &'z T) -> Self::Out<'z, T>;
+}
+/*
+impl Des3 for () {
+ type Out<'x, D> = &'x D;
+ fn des<'a, T>(&self, data: &'a T) -> Self::Out<'a, T> {
+ data
+ }
+}
+*/
+
+// Similar case to before, except with GAT.
+trait NoGat<'a> {
+ type Bar;
+ fn method(&'a self) -> Self::Bar;
+}
+
+// Lifetime is not on function; except `Self: 'a`
+// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
+trait TraitLifetime<'a> {
+ type Bar<'b>;
+ //~^ Missing required bounds
+ fn method(&'a self) -> Self::Bar<'a>;
+}
+
+// Like above, but we have a where clause that can prove what we want
+// FIXME: we require two bounds (`where Self: 'a, Self: 'b`) when we should only require one
+trait TraitLifetimeWhere<'a> where Self: 'a {
+ type Bar<'b>;
+ //~^ Missing required bounds
+ fn method(&'a self) -> Self::Bar<'a>;
+}
+
+// Explicit bound instead of implicit; we want to still error
+trait ExplicitBound {
+ type Bar<'b>;
+ //~^ Missing required bounds
+ fn method<'b>(&self, token: &'b ()) -> Self::Bar<'b> where Self: 'b;
+}
+
+// The use of the GAT here is not in the return, we don't want to error
+trait NotInReturn {
+ type Bar<'b>;
+ fn method<'b>(&'b self) where Self::Bar<'b>: Debug;
+}
+
+// We obviously error for `Iterator`, but we should also error for `Item`
+trait IterableTwo {
+ type Item<'a>;
+ type Iterator<'a>: Iterator<Item = Self::Item<'a>>;
+ //~^ Missing required bounds
+ fn iter<'a>(&'a self) -> Self::Iterator<'a>;
+}
+
+// We also should report region outlives clauses
+trait RegionOutlives {
+ type Bar<'a, 'b>;
+ //~^ Missing required bounds
+ fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y>;
+}
+
+/*
+impl Foo for () {
+ type Bar<'a, 'b> = &'a &'b ();
+ fn foo<'x, 'y>(&self, input: &'x &'y ()) -> Self::Bar<'x, 'y> {
+ input
+ }
+}
+*/
+
+// If there are multiple methods that return the GAT, require a set of clauses
+// that can be satisfied by *all* methods
+trait MultipleMethods {
+ type Bar<'me>;
+
+ fn gimme<'a>(&'a self) -> Self::Bar<'a>;
+ fn gimme_default(&self) -> Self::Bar<'static>;
+}
+
+fn main() {}
--- /dev/null
+error: Missing required bounds on Item
+ --> $DIR/self-outlives-lint.rs:9:5
+ |
+LL | type Item<'x>;
+ | ^^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where Self: 'x`
+
+error: Missing required bounds on Out
+ --> $DIR/self-outlives-lint.rs:25:5
+ |
+LL | type Out<'x>;
+ | ^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where T: 'x`
+
+error: Missing required bounds on Out
+ --> $DIR/self-outlives-lint.rs:39:5
+ |
+LL | type Out<'x>;
+ | ^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where T: 'x`
+
+error: Missing required bounds on Out
+ --> $DIR/self-outlives-lint.rs:46:5
+ |
+LL | type Out<'x, 'y>;
+ | ^^^^^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where T: 'x, U: 'y`
+
+error: Missing required bounds on Out
+ --> $DIR/self-outlives-lint.rs:61:5
+ |
+LL | type Out<'x, D>;
+ | ^^^^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where D: 'x`
+
+error: Missing required bounds on Out
+ --> $DIR/self-outlives-lint.rs:77:5
+ |
+LL | type Out<'x, D>;
+ | ^^^^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where D: 'x`
+
+error: Missing required bounds on Out
+ --> $DIR/self-outlives-lint.rs:92:5
+ |
+LL | type Out<'x, D>;
+ | ^^^^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where D: 'x`
+
+error: Missing required bounds on Bar
+ --> $DIR/self-outlives-lint.rs:114:5
+ |
+LL | type Bar<'b>;
+ | ^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where Self: 'a, Self: 'b`
+
+error: Missing required bounds on Bar
+ --> $DIR/self-outlives-lint.rs:122:5
+ |
+LL | type Bar<'b>;
+ | ^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where Self: 'a, Self: 'b`
+
+error: Missing required bounds on Bar
+ --> $DIR/self-outlives-lint.rs:129:5
+ |
+LL | type Bar<'b>;
+ | ^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where Self: 'b`
+
+error: Missing required bounds on Iterator
+ --> $DIR/self-outlives-lint.rs:143:5
+ |
+LL | type Iterator<'a>: Iterator<Item = Self::Item<'a>>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where Self: 'a`
+
+error: Missing required bounds on Bar
+ --> $DIR/self-outlives-lint.rs:150:5
+ |
+LL | type Bar<'a, 'b>;
+ | ^^^^^^^^^^^^^^^^-
+ | |
+ | help: add the required where clauses: `where 'a: 'b`
+
+error: aborting due to 12 previous errors
+
use std::fmt::Display;
trait StreamingIterator {
- type Item<'a>;
+ type Item<'a> where Self: 'a;
// Applying the lifetime parameter `'a` to `Self::Item` inside the trait.
fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
}
-struct Foo<T: StreamingIterator> {
+struct Foo<T: StreamingIterator + 'static> {
// Applying a concrete lifetime to the constructor outside the trait.
bar: <T as StreamingIterator>::Item<'static>,
}
}
impl<I: StreamingIterator> StreamingIterator for StreamEnumerate<I> {
- type Item<'a> = (usize, I::Item<'a>);
+ type Item<'a> where Self: 'a = (usize, I::Item<'a>);
fn next<'a>(&'a mut self) -> Option<Self::Item<'a>> {
match self.iter.next() {
None => None,
}
impl<I: Iterator> StreamingIterator for I {
- type Item<'a> = <I as Iterator>::Item;
+ type Item<'a> where Self: 'a = <I as Iterator>::Item;
fn next(&mut self) -> Option<<I as StreamingIterator>::Item<'_>> {
Iterator::next(self)
}
#![feature(generic_associated_types)]
trait A {
- type B<'a>;
+ type B<'a> where Self: 'a;
fn make_b<'a>(&'a self) -> Self::B<'a>;
}
--- /dev/null
+// run-pass
+#![allow(dead_code)]
+// Issue #1112
+// Alignment of interior pointers to dynamic-size types
+
+
+struct X<T> {
+ a: T,
+ b: u8,
+ c: bool,
+ d: u8,
+ e: u16,
+ f: u8,
+ g: u8
+}
+
+pub fn main() {
+ let x: X<isize> = X {
+ a: 12345678,
+ b: 9,
+ c: true,
+ d: 10,
+ e: 11,
+ f: 12,
+ g: 13
+ };
+ bar(x);
+}
+
+fn bar<T>(x: X<T>) {
+ assert_eq!(x.b, 9);
+ assert_eq!(x.c, true);
+ assert_eq!(x.d, 10);
+ assert_eq!(x.e, 11);
+ assert_eq!(x.f, 12);
+ assert_eq!(x.g, 13);
+}
--- /dev/null
+// run-pass
+
+fn quux<T>(x: T) -> T { let f = id::<T>; return f(x); }
+
+fn id<T>(x: T) -> T { return x; }
+
+pub fn main() { assert_eq!(quux(10), 10); }
--- /dev/null
+#![allow(dead_code)]
+#![feature(const_generics_defaults)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions mention that
+// consts come after types and lifetimes when the `const_generics_defaults` feature is enabled.
+// We cannot run rustfix on this test because of the above const generics warning.
+
+struct A;
+
+impl A {
+ pub fn do_things<T, 'a, 'b: 'a>() {
+ //~^ ERROR lifetime parameters must be declared prior to type parameters
+ println!("panic");
+ }
+}
+
+fn main() {}
--- /dev/null
+error: lifetime parameters must be declared prior to type parameters
+ --> $DIR/issue-59508-1.rs:11:25
+ |
+LL | pub fn do_things<T, 'a, 'b: 'a>() {
+ | ----^^--^^----- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b: 'a, T>`
+
+error: aborting due to previous error
+
--- /dev/null
+// run-rustfix
+
+#![allow(dead_code)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
+
+struct A;
+
+impl A {
+ pub fn do_things<'a, 'b: 'a, T>() {
+ //~^ ERROR lifetime parameters must be declared prior to type parameters
+ println!("panic");
+ }
+}
+
+fn main() {}
--- /dev/null
+// run-rustfix
+
+#![allow(dead_code)]
+
+// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
+
+struct A;
+
+impl A {
+ pub fn do_things<T, 'a, 'b: 'a>() {
+ //~^ ERROR lifetime parameters must be declared prior to type parameters
+ println!("panic");
+ }
+}
+
+fn main() {}
--- /dev/null
+error: lifetime parameters must be declared prior to type parameters
+ --> $DIR/issue-59508.rs:10:25
+ |
+LL | pub fn do_things<T, 'a, 'b: 'a>() {
+ | ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>`
+
+error: aborting due to previous error
+
// run-pass
// edition:2021
-// compile-flags: -Zunstable-options
fn main() {
println!("hello, 2021");
--- /dev/null
+pub trait Trait<'a> {
+ type Item;
+}
+
+impl<'a> Trait<'a> for () {
+ type Item = ();
+}
+
+pub fn foo<T, F>(_: T, _: F)
+where
+ T: for<'a> Trait<'a>,
+ F: for<'a> FnMut(<T as Trait<'a>>::Item),
+{
+}
+
+fn main() {
+ foo((), drop)
+ //~^ ERROR type mismatch in function arguments
+ //~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
+}
--- /dev/null
+error[E0631]: type mismatch in function arguments
+ --> $DIR/issue-60283.rs:17:13
+ |
+LL | foo((), drop)
+ | --- ^^^^
+ | | |
+ | | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
+ | | found signature of `fn(()) -> _`
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `foo`
+ --> $DIR/issue-60283.rs:12:16
+ |
+LL | pub fn foo<T, F>(_: T, _: F)
+ | --- required by a bound in this
+...
+LL | F: for<'a> FnMut(<T as Trait<'a>>::Item),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
+ --> $DIR/issue-60283.rs:17:13
+ |
+LL | foo((), drop)
+ | --- ^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item`
+note: required by a bound in `std::mem::drop`
+ --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+ |
+LL | pub fn drop<T>(_x: T) {}
+ | ^ required by this bound in `std::mem::drop`
+help: consider further restricting the associated type
+ |
+LL | fn main() where <() as Trait<'_>>::Item: Sized {
+ | ++++++++++++++++++++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0631.
+For more information about an error, try `rustc --explain E0277`.
--- /dev/null
+// check-pass
+
+pub trait Foo<'a> {
+ type Bar;
+ fn foo(&'a self) -> Self::Bar;
+}
+
+impl<'a, 'b, T: 'a> Foo<'a> for &'b T {
+ type Bar = &'a T;
+ fn foo(&'a self) -> &'a T {
+ self
+ }
+}
+
+pub fn uncallable<T, F>(x: T, f: F)
+where
+ T: for<'a> Foo<'a>,
+ F: for<'a> Fn(<T as Foo<'a>>::Bar),
+{
+ f(x.foo());
+}
+
+pub fn catalyst(x: &i32) {
+ broken(x, |_| {})
+}
+
+pub fn broken<F: Fn(&i32)>(x: &i32, f: F) {
+ uncallable(x, |y| f(y));
+}
+
+fn main() {}
}
fn main() {
- task(annotate( //~ type mismatch
+ task(annotate(
//~^ the size
//~^^ the trait bound
Annotate::<RefMutFamily<usize>>::new(),
-error[E0631]: type mismatch in closure arguments
- --> $DIR/issue-62529-1.rs:80:10
- |
-LL | task(annotate(
- | _____----_^
- | | |
- | | required by a bound introduced by this call
-LL | |
-LL | |
-LL | | Annotate::<RefMutFamily<usize>>::new(),
-LL | | |value: &mut usize| {
- | | ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
-LL | | *value = 2;
-LL | | }
-LL | | ));
- | |_____^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
- |
-note: required by a bound in `annotate`
- --> $DIR/issue-62529-1.rs:44:8
- |
-LL | fn annotate<F, Q>(_q: Annotate<Q>, func: F) -> impl Execute + 'static
- | -------- required by a bound in this
-LL | where
-LL | F: for<'r> FnOnce(<<Q as Inject>::I as FamilyLt<'r>>::Out) + 'static,
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `annotate`
-
error[E0277]: the size for values of type `impl Execute` cannot be known at compilation time
--> $DIR/issue-62529-1.rs:80:10
|
LL | where P: Execute + 'static {
| ^^^^^^^ required by this bound in `task`
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0277, E0631.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
+// check-pass
+
pub trait MyTrait<'a> {
type Output: 'a;
fn gimme_value(&self) -> Self::Output;
fn main() {
let struc = MyStruct;
- meow(struc, |foo| { //~ type mismatch
+ meow(struc, |foo| {
println!("{:?}", foo);
})
}
+++ /dev/null
-error[E0631]: type mismatch in closure arguments
- --> $DIR/issue-70120.rs:26:5
- |
-LL | meow(struc, |foo| {
- | ^^^^ ----- found signature of `for<'r> fn(&'r usize) -> _`
- | |
- | expected signature of `for<'any2> fn(<MyStruct as MyTrait<'any2>>::Output) -> _`
- |
-note: required by a bound in `meow`
- --> $DIR/issue-70120.rs:18:8
- |
-LL | fn meow<T, F>(t: T, f: F)
- | ---- required by a bound in this
-...
-LL | F: for<'any2> Fn(<T as MyTrait<'any2>>::Output),
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `meow`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0631`.
--- /dev/null
+error: implementation of `Parser` is not general enough
+ --> $DIR/issue-71955.rs:52:5
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^ implementation of `Parser` is not general enough
+ |
+ = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+ = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+ --> $DIR/issue-71955.rs:52:5
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^ implementation of `Parser` is not general enough
+ |
+ = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+ = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+ --> $DIR/issue-71955.rs:52:5
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^ implementation of `Parser` is not general enough
+ |
+ = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+ = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+ --> $DIR/issue-71955.rs:52:5
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^ implementation of `Parser` is not general enough
+ |
+ = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+ = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+ --> $DIR/issue-71955.rs:52:5
+ |
+LL | foo(bar, "string", |s| s.len() == 5);
+ | ^^^ implementation of `Parser` is not general enough
+ |
+ = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`...
+ = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+ --> $DIR/issue-71955.rs:58:5
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^ implementation of `Parser` is not general enough
+ |
+ = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+ = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+ --> $DIR/issue-71955.rs:58:5
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^ implementation of `Parser` is not general enough
+ |
+ = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+ = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+ --> $DIR/issue-71955.rs:58:5
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^ implementation of `Parser` is not general enough
+ |
+ = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+ = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+ --> $DIR/issue-71955.rs:58:5
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^ implementation of `Parser` is not general enough
+ |
+ = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+ = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: implementation of `Parser` is not general enough
+ --> $DIR/issue-71955.rs:58:5
+ |
+LL | foo(baz, "string", |s| s.0.len() == 5);
+ | ^^^ implementation of `Parser` is not general enough
+ |
+ = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`...
+ = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1`
+
+error: aborting due to 10 previous errors
+
--- /dev/null
+error: fatal error triggered by #[rustc_error]
+ --> $DIR/issue-71955.rs:42:1
+ |
+LL | fn main() {
+ | ^^^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// ignore-compare-mode-nll
+// revisions: migrate nll
+// [nll]compile-flags: -Zborrowck=mir
+// check-fail
+
+#![feature(rustc_attrs)]
+
+trait Parser<'s> {
+ type Output;
+
+ fn call(&self, input: &'s str) -> (&'s str, Self::Output);
+}
+
+impl<'s, F, T> Parser<'s> for F
+where F: Fn(&'s str) -> (&'s str, T) {
+ type Output = T;
+ fn call(&self, input: &'s str) -> (&'s str, T) {
+ self(input)
+ }
+}
+
+fn foo<F1, F2>(
+ f1: F1,
+ base: &'static str,
+ f2: F2
+)
+where
+ F1: for<'a> Parser<'a>,
+ F2: FnOnce(&<F1 as Parser>::Output) -> bool
+{
+ let s: String = base.to_owned();
+ let str_ref = s.as_ref();
+ let (remaining, produced) = f1.call(str_ref);
+ assert!(f2(&produced));
+ assert_eq!(remaining.len(), 0);
+}
+
+struct Wrapper<'a>(&'a str);
+
+// Because nll currently succeeds and migrate doesn't
+#[rustc_error]
+fn main() {
+ //[nll]~^ fatal
+ fn bar<'a>(s: &'a str) -> (&'a str, &'a str) {
+ (&s[..1], &s[..])
+ }
+
+ fn baz<'a>(s: &'a str) -> (&'a str, Wrapper<'a>) {
+ (&s[..1], Wrapper(&s[..]))
+ }
+
+ foo(bar, "string", |s| s.len() == 5);
+ //[migrate]~^ ERROR implementation of `Parser` is not general enough
+ //[migrate]~| ERROR implementation of `Parser` is not general enough
+ //[migrate]~| ERROR implementation of `Parser` is not general enough
+ //[migrate]~| ERROR implementation of `Parser` is not general enough
+ //[migrate]~| ERROR implementation of `Parser` is not general enough
+ foo(baz, "string", |s| s.0.len() == 5);
+ //[migrate]~^ ERROR implementation of `Parser` is not general enough
+ //[migrate]~| ERROR implementation of `Parser` is not general enough
+ //[migrate]~| ERROR implementation of `Parser` is not general enough
+ //[migrate]~| ERROR implementation of `Parser` is not general enough
+ //[migrate]~| ERROR implementation of `Parser` is not general enough
+}
--- /dev/null
+// check-pass
+
+use std::marker::PhantomData;
+
+trait A<'a> {
+ type B;
+ fn b(self) -> Self::B;
+}
+
+struct T;
+struct S<'a>(PhantomData<&'a ()>);
+
+impl<'a> A<'a> for T {
+ type B = S<'a>;
+ fn b(self) -> Self::B {
+ S(PhantomData)
+ }
+}
+
+fn s<TT, F>(t: TT, f: F)
+where
+ TT: for<'a> A<'a>,
+ F: for<'a> FnOnce(<TT as A<'a>>::B)
+{
+ f(t.b());
+}
+
+fn main() {
+ s(T, |_| {});
+}
--- /dev/null
+// check-pass
+
+trait Base<'f> {
+ type Assoc;
+
+ fn do_something(&self);
+}
+
+trait ForAnyLifetime: for<'f> Base<'f> {}
+
+impl<T> ForAnyLifetime for T where T: for<'f> Base<'f> {}
+
+trait CanBeDynamic: ForAnyLifetime + for<'f> Base<'f, Assoc = ()> {}
+
+fn foo(a: &dyn CanBeDynamic) {
+ a.do_something();
+}
+
+struct S;
+
+impl<'a> Base<'a> for S {
+ type Assoc = ();
+
+ fn do_something(&self) {}
+}
+
+impl CanBeDynamic for S {}
+
+fn main() {
+ let s = S;
+ foo(&s);
+}
--- /dev/null
+// run-pass
+// shouldn't affect evaluation of $ex:
+macro_rules! bad_macro {
+ ($ex:expr) => ({(|_x| { $ex }) (9) })
+}
+
+fn takes_x(_x : isize) {
+ assert_eq!(bad_macro!(_x),8);
+}
+fn main() {
+ takes_x(8);
+}
--- /dev/null
+// check-pass
+
+fn fibs(n: u32) -> impl Iterator<Item=u128> {
+ (0 .. n)
+ .scan((0, 1), |st, _| {
+ *st = (st.1, st.0 + st.1);
+ Some(*st)
+ })
+ .map(&|(f, _)| f)
+}
+
+fn main() {
+ println!("{:?}", fibs(10).collect::<Vec<_>>());
+}
--- /dev/null
+// run-pass
+// Regression test for #49685: drop elaboration was not revealing the
+// value of `impl Trait` returns, leading to an ICE.
+
+fn main() {
+ let _ = Some(())
+ .into_iter()
+ .flat_map(|_| Some(()).into_iter().flat_map(func));
+}
+
+fn func(_: ()) -> impl Iterator<Item = ()> {
+ Some(()).into_iter().flat_map(|_| vec![])
+}
--- /dev/null
+// run-pass
+fn foo() -> impl Into<for<'a> fn(&'a ())> {
+ (|_| {}) as for<'a> fn(&'a ())
+}
+
+fn main() {
+ foo().into()(&());
+}
+++ /dev/null
-// run-pass
-
-#![allow(warnings)]
-#![feature(in_band_lifetimes)]
-
-fn foo(x: &'x u8) -> &'x u8 { x }
-fn foo2(x: &'a u8, y: &u8) -> &'a u8 { x }
-
-fn check_in_band_can_be_late_bound() {
- let _: for<'x> fn(&'x u8, &u8) -> &'x u8 = foo2;
-}
-
-struct ForInherentNoParams;
-
-impl ForInherentNoParams {
- fn foo(x: &'a u32, y: &u32) -> &'a u32 { x }
-}
-
-struct X<'a>(&'a u8);
-
-impl<'a> X<'a> {
- fn inner(&self) -> &'a u8 {
- self.0
- }
-
- fn same_lifetime_as_parameter(&mut self, x: &'a u8) {
- self.0 = x;
- }
-}
-
-impl X<'b> {
- fn inner_2(&self) -> &'b u8 {
- self.0
- }
-
- fn reference_already_introduced_in_band_from_method_with_explicit_binders<'a>(
- &'b self, x: &'a u32
- ) {}
-}
-
-struct Y<T>(T);
-
-impl Y<&'a u8> {
- fn inner(&self) -> &'a u8 {
- self.0
- }
-}
-
-trait MyTrait<'a> {
- fn my_lifetime(&self) -> &'a u8;
- fn any_lifetime() -> &'b u8;
- fn borrowed_lifetime(&'b self) -> &'b u8;
- fn default_impl(&self, x: &'b u32, y: &u32) -> &'b u32 { x }
- fn in_band_def_explicit_impl(&self, x: &'b u8);
-}
-
-impl MyTrait<'a> for Y<&'a u8> {
- fn my_lifetime(&self) -> &'a u8 { self.0 }
- fn any_lifetime() -> &'b u8 { &0 }
- fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
- fn in_band_def_explicit_impl<'b>(&self, x: &'b u8) {}
-}
-
-fn test_hrtb_defined_lifetime_where<F>(_: F) where for<'a> F: Fn(&'a u8) {}
-fn test_hrtb_defined_lifetime_polytraitref<F>(_: F) where F: for<'a> Fn(&'a u8) {}
-
-fn reference_in_band_from_locals(x: &'test u32) -> &'test u32 {
- let y: &'test u32 = x;
- y
-}
-
-fn in_generics_in_band<T: MyTrait<'a>>(x: &T) {}
-fn where_clause_in_band<T>(x: &T) where T: MyTrait<'a> {}
-fn impl_trait_in_band(x: &impl MyTrait<'a>) {}
-
-// Tests around using in-band lifetimes within existential traits.
-
-trait FunkyTrait<'a> { }
-impl<'a, T> FunkyTrait<'a> for T { }
-fn ret_pos_impl_trait_in_band_outlives(x: &'a u32) -> impl ::std::fmt::Debug + 'a {
- x
-}
-fn ret_pos_impl_trait_in_band_param(x: &'a u32) -> impl FunkyTrait<'a> {
- x
-}
-fn ret_pos_impl_trait_in_band_param_static(x: &'a u32) -> impl FunkyTrait<'static> + 'a {
- x
-}
-fn ret_pos_impl_trait_in_band_param_outlives(x: &'a u32) -> impl FunkyTrait<'a> + 'a {
- x
-}
-fn ret_pos_impl_trait_in_band_higher_ranked(x: &'a u32) -> impl for<'b> FunkyTrait<'b> + 'a {
- x
-}
-
-fn main() {}
--- /dev/null
+// run-pass
+
+#![allow(warnings)]
+#![feature(in_band_lifetimes)]
+
+fn foo(x: &'x u8) -> &'x u8 { x }
+fn foo2(x: &'a u8, y: &u8) -> &'a u8 { x }
+
+fn check_in_band_can_be_late_bound() {
+ let _: for<'x> fn(&'x u8, &u8) -> &'x u8 = foo2;
+}
+
+struct ForInherentNoParams;
+
+impl ForInherentNoParams {
+ fn foo(x: &'a u32, y: &u32) -> &'a u32 { x }
+}
+
+struct X<'a>(&'a u8);
+
+impl<'a> X<'a> {
+ fn inner(&self) -> &'a u8 {
+ self.0
+ }
+
+ fn same_lifetime_as_parameter(&mut self, x: &'a u8) {
+ self.0 = x;
+ }
+}
+
+impl X<'b> {
+ fn inner_2(&self) -> &'b u8 {
+ self.0
+ }
+
+ fn reference_already_introduced_in_band_from_method_with_explicit_binders<'a>(
+ &'b self, x: &'a u32
+ ) {}
+}
+
+struct Y<T>(T);
+
+impl Y<&'a u8> {
+ fn inner(&self) -> &'a u8 {
+ self.0
+ }
+}
+
+trait MyTrait<'a> {
+ fn my_lifetime(&self) -> &'a u8;
+ fn any_lifetime() -> &'b u8;
+ fn borrowed_lifetime(&'b self) -> &'b u8;
+ fn default_impl(&self, x: &'b u32, y: &u32) -> &'b u32 { x }
+ fn in_band_def_explicit_impl(&self, x: &'b u8);
+}
+
+impl MyTrait<'a> for Y<&'a u8> {
+ fn my_lifetime(&self) -> &'a u8 { self.0 }
+ fn any_lifetime() -> &'b u8 { &0 }
+ fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 }
+ fn in_band_def_explicit_impl<'b>(&self, x: &'b u8) {}
+}
+
+fn test_hrtb_defined_lifetime_where<F>(_: F) where for<'a> F: Fn(&'a u8) {}
+fn test_hrtb_defined_lifetime_polytraitref<F>(_: F) where F: for<'a> Fn(&'a u8) {}
+
+fn reference_in_band_from_locals(x: &'test u32) -> &'test u32 {
+ let y: &'test u32 = x;
+ y
+}
+
+fn in_generics_in_band<T: MyTrait<'a>>(x: &T) {}
+fn where_clause_in_band<T>(x: &T) where T: MyTrait<'a> {}
+fn impl_trait_in_band(x: &impl MyTrait<'a>) {}
+
+// Tests around using in-band lifetimes within existential traits.
+
+trait FunkyTrait<'a> { }
+impl<'a, T> FunkyTrait<'a> for T { }
+fn ret_pos_impl_trait_in_band_outlives(x: &'a u32) -> impl ::std::fmt::Debug + 'a {
+ x
+}
+fn ret_pos_impl_trait_in_band_param(x: &'a u32) -> impl FunkyTrait<'a> {
+ x
+}
+fn ret_pos_impl_trait_in_band_param_static(x: &'a u32) -> impl FunkyTrait<'static> + 'a {
+ x
+}
+fn ret_pos_impl_trait_in_band_param_outlives(x: &'a u32) -> impl FunkyTrait<'a> + 'a {
+ x
+}
+fn ret_pos_impl_trait_in_band_higher_ranked(x: &'a u32) -> impl for<'b> FunkyTrait<'b> + 'a {
+ x
+}
+
+fn main() {}
--- /dev/null
+// run-pass
+// Test for a specific corner case: when we compute the LUB of two fn
+// types and their parameters have unbound variables. In that case, we
+// wind up relating those two variables. This was causing an ICE in an
+// in-progress PR.
+
+fn main() {
+ let a_f: fn(_) = |_| ();
+ let b_f: fn(_) = |_| ();
+ let c_f = match 22 {
+ 0 => a_f,
+ _ => b_f,
+ };
+ c_f(4);
+}
+++ /dev/null
-#![crate_type = "lib"]
-
-#[macro_export]
-macro_rules! mywrite {
- ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
-}
+++ /dev/null
-#![crate_type="rlib"]
-
-#[derive(Debug, PartialEq)]
-pub struct RemoteC(pub u32);
-
-#[derive(Debug, PartialEq)]
-pub struct RemoteG<T>(pub T);
+++ /dev/null
-#![crate_type="lib"]
-
-
-pub trait A {
- fn a(&self) {}
-}
-impl A for () {}
+++ /dev/null
-#![crate_type="lib"]
-
-pub extern crate xcrate_issue_43189_a;
+++ /dev/null
-#![crate_type="lib"]
-
-pub extern crate core;
+++ /dev/null
-// edition:2018
-#![crate_type="lib"]
-#![crate_name="xcrate_issue_61711_b"]
-pub struct Struct;
-pub use crate as alias;
+++ /dev/null
-#![feature(box_syntax)]
-
-fn main() {
- let x: Box<_> = box 1;
- let f = move|| {
- let _a = x;
- drop(x);
- //~^ ERROR: use of moved value: `x`
- };
- f();
-}
+++ /dev/null
-error[E0382]: use of moved value: `x`
- --> $DIR/issue-10398.rs:7:14
- |
-LL | let _a = x;
- | - value moved here
-LL | drop(x);
- | ^ value used here after move
- |
- = note: move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0382`.
+++ /dev/null
-// run-pass
-#![allow(dead_code)]
-// Issue #1112
-// Alignment of interior pointers to dynamic-size types
-
-
-struct X<T> {
- a: T,
- b: u8,
- c: bool,
- d: u8,
- e: u16,
- f: u8,
- g: u8
-}
-
-pub fn main() {
- let x: X<isize> = X {
- a: 12345678,
- b: 9,
- c: true,
- d: 10,
- e: 11,
- f: 12,
- g: 13
- };
- bar(x);
-}
-
-fn bar<T>(x: X<T>) {
- assert_eq!(x.b, 9);
- assert_eq!(x.c, true);
- assert_eq!(x.d, 10);
- assert_eq!(x.e, 11);
- assert_eq!(x.f, 12);
- assert_eq!(x.g, 13);
-}
+++ /dev/null
-// run-pass
-// Destructuring struct variants would ICE where regular structs wouldn't
-
-enum Foo {
- VBar { num: isize }
-}
-
-struct SBar { num: isize }
-
-pub fn main() {
- let vbar = Foo::VBar { num: 1 };
- let Foo::VBar { num } = vbar;
- assert_eq!(num, 1);
-
- let sbar = SBar { num: 2 };
- let SBar { num } = sbar;
- assert_eq!(num, 2);
-}
+++ /dev/null
-// run-pass
-
-const TEST_STR: &'static str = "abcd";
-
-fn main() {
- let s = "abcd";
- match s {
- TEST_STR => (),
- _ => unreachable!()
- }
-}
+++ /dev/null
-trait Trait {
- fn outer(&self) {
- fn inner(_: &Self) {
- //~^ ERROR can't use generic parameters from outer function
- }
- }
-}
-
-fn main() { }
+++ /dev/null
-error[E0401]: can't use generic parameters from outer function
- --> $DIR/issue-12796.rs:3:22
- |
-LL | fn inner(_: &Self) {
- | ^^^^
- | |
- | use of generic parameter from outer function
- | can't use `Self` here
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0401`.
+++ /dev/null
-fn main() {
- if true {
- } else if { //~ ERROR missing condition
- //~^ ERROR mismatched types
- } else {
- }
-}
-
-fn foo() {
- if true {
- } else if { //~ ERROR missing condition
- //~^ ERROR mismatched types
- }
- bar();
-}
-
-fn bar() {}
+++ /dev/null
-error: missing condition for `if` expression
- --> $DIR/issue-13483.rs:3:14
- |
-LL | } else if {
- | ^ expected if condition here
-
-error: missing condition for `if` expression
- --> $DIR/issue-13483.rs:11:14
- |
-LL | } else if {
- | ^ expected if condition here
-
-error[E0308]: mismatched types
- --> $DIR/issue-13483.rs:3:15
- |
-LL | } else if {
- | _______________^
-LL | |
-LL | | } else {
- | |_____^ expected `bool`, found `()`
-
-error[E0308]: mismatched types
- --> $DIR/issue-13483.rs:11:15
- |
-LL | } else if {
- | _______________^
-LL | |
-LL | | }
- | |_____^ expected `bool`, found `()`
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
+++ /dev/null
-// run-pass
-#![allow(dead_code)]
-#![allow(non_camel_case_types)]
-
-const JSVAL_TAG_CLEAR: u32 = 0xFFFFFF80;
-const JSVAL_TYPE_INT32: u8 = 0x01;
-const JSVAL_TYPE_UNDEFINED: u8 = 0x02;
-#[repr(u32)]
-enum ValueTag {
- JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | (JSVAL_TYPE_INT32 as u32),
- JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | (JSVAL_TYPE_UNDEFINED as u32),
-}
-
-fn main() {
- let _ = ValueTag::JSVAL_TAG_INT32;
-}
+++ /dev/null
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
- --> $DIR/issue-14227.rs:7:21
- |
-LL | static CRASH: u32 = symbol;
- | ^^^^^^ use of extern static
- |
- = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
+++ /dev/null
-// revisions: mir thir
-// [thir]compile-flags: -Z thir-unsafeck
-
-extern "C" {
- pub static symbol: u32;
-}
-static CRASH: u32 = symbol;
-//~^ ERROR use of extern static is unsafe and requires
-
-fn main() {}
+++ /dev/null
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
- --> $DIR/issue-14227.rs:7:21
- |
-LL | static CRASH: u32 = symbol;
- | ^^^^^^ use of extern static
- |
- = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
+++ /dev/null
-// run-pass
-#![allow(unused_mut)]
-// ignore-emscripten no processes
-// ignore-sgx no processes
-
-use std::env;
-use std::io::prelude::*;
-use std::io;
-use std::process::{Command, Stdio};
-
-fn main() {
- let args: Vec<String> = env::args().collect();
- if args.len() > 1 && args[1] == "child" {
- return child()
- }
-
- test();
-}
-
-fn child() {
- writeln!(&mut io::stdout(), "foo").unwrap();
- writeln!(&mut io::stderr(), "bar").unwrap();
- let mut stdin = io::stdin();
- let mut s = String::new();
- stdin.lock().read_line(&mut s).unwrap();
- assert_eq!(s.len(), 0);
-}
-
-fn test() {
- let args: Vec<String> = env::args().collect();
- let mut p = Command::new(&args[0]).arg("child")
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .stderr(Stdio::piped())
- .spawn().unwrap();
- assert!(p.wait().unwrap().success());
-}
+++ /dev/null
-// run-pass
-// All 3 expressions should work in that the argument gets
-// coerced to a trait object
-
-// pretty-expanded FIXME #23616
-
-fn main() {
- send::<Box<dyn Foo>>(Box::new(Output(0)));
- Test::<Box<dyn Foo>>::foo(Box::new(Output(0)));
- Test::<Box<dyn Foo>>::new().send(Box::new(Output(0)));
-}
-
-fn send<T>(_: T) {}
-
-struct Test<T> { marker: std::marker::PhantomData<T> }
-impl<T> Test<T> {
- fn new() -> Test<T> { Test { marker: ::std::marker::PhantomData } }
- fn foo(_: T) {}
- fn send(&self, _: T) {}
-}
-
-trait Foo { fn dummy(&self) { }}
-struct Output(isize);
-impl Foo for Output {}
+++ /dev/null
-// check-pass
-// pretty-expanded FIXME #23616
-
-#[deny(dead_code)]
-pub enum Foo {
- Bar {
- baz: isize
- }
-}
-
-fn main() { }
+++ /dev/null
-// run-pass
-
-fn main() {
- let mut x: &[_] = &[1, 2, 3, 4];
-
- let mut result = vec![];
- loop {
- x = match *x {
- [1, n, 3, ref rest @ ..] => {
- result.push(n);
- rest
- }
- [n, ref rest @ ..] => {
- result.push(n);
- rest
- }
- [] =>
- break
- }
- }
- assert_eq!(result, [2, 4]);
-}
+++ /dev/null
-macro_rules! prob1 {
- (0) => {
- 0
- };
- ($n:expr) => {
- if ($n % 3 == 0) || ($n % 5 == 0) {
- $n + prob1!($n - 1); //~ ERROR recursion limit reached while expanding `prob1!`
- } else {
- prob1!($n - 1);
- }
- };
-}
-
-fn main() {
- println!("Problem 1: {}", prob1!(1000));
-}
+++ /dev/null
-error: recursion limit reached while expanding `prob1!`
- --> $DIR/issue-16098.rs:7:18
- |
-LL | $n + prob1!($n - 1);
- | ^^^^^^^^^^^^^^
-...
-LL | println!("Problem 1: {}", prob1!(1000));
- | ------------ in this macro invocation
- |
- = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_16098`)
- = note: this error originates in the macro `prob1` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
+++ /dev/null
-// run-pass
-// ignore-emscripten no processes
-// ignore-sgx no processes
-
-use std::process::Command;
-use std::env;
-
-fn main() {
- let len = env::args().len();
-
- if len == 1 {
- test();
- } else {
- assert_eq!(len, 3);
- }
-}
-
-fn test() {
- let status = Command::new(&env::current_exe().unwrap())
- .arg("foo").arg("")
- .status().unwrap();
- assert!(status.success());
-}
+++ /dev/null
-// run-pass
-#![allow(dead_code)]
-
-static X2: u64 = !0 as u16 as u64;
-static Y2: u64 = !0 as u32 as u64;
-const X: u64 = !0 as u16 as u64;
-const Y: u64 = !0 as u32 as u64;
-
-fn main() {
- assert_eq!(match 1 {
- X => unreachable!(),
- Y => unreachable!(),
- _ => 1
- }, 1);
-}
+++ /dev/null
-// run-pass
-// Regression test for #18060: match arms were matching in the wrong order.
-
-fn main() {
- assert_eq!(2, match (1, 3) { (0, 2..=5) => 1, (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
- assert_eq!(2, match (1, 3) { (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
- assert_eq!(2, match (1, 7) { (0, 2..=5) => 1, (1, 7) => 2, (_, 2..=5) => 3, (_, _) => 4 });
-}
+++ /dev/null
-fn main() {
- const X: u32 = 1;
- const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR pointers cannot be cast to integers
- println!("{}", Y);
-}
+++ /dev/null
-error: pointers cannot be cast to integers during const eval
- --> $DIR/issue-18294.rs:3:31
- |
-LL | const Y: usize = unsafe { &X as *const u32 as usize };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: at compile-time, pointers do not have an integer value
- = note: avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
-
-error: aborting due to previous error
-
+++ /dev/null
-// run-pass
-// Tests multiple free variables being passed by value into an unboxed
-// once closure as an optimization by codegen. This used to hit an
-// incorrect assert.
-
-fn main() {
- let x = 2u8;
- let y = 3u8;
- assert_eq!((move || x + y)(), 5);
-}
+++ /dev/null
-// aux-build:issue-19163.rs
-
-#[macro_use] extern crate issue_19163;
-
-use std::io::Write;
-
-fn main() {
- let mut v = vec![];
- mywrite!(&v, "Hello world");
- //~^ ERROR cannot borrow data in a `&` reference as mutable
-}
+++ /dev/null
-error[E0596]: cannot borrow data in a `&` reference as mutable
- --> $DIR/issue-19163.rs:9:5
- |
-LL | mywrite!(&v, "Hello world");
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
- |
- = note: this error originates in the macro `mywrite` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0596`.
+++ /dev/null
-// run-pass
-
-#![allow(dead_code)]
-
-trait Trait { fn dummy(&self) { } }
-
-#[derive(Debug)]
-struct Foo<T: Trait> {
- foo: T,
-}
-
-#[derive(Debug)]
-struct Bar<T> where T: Trait {
- bar: T,
-}
-
-impl Trait for isize {}
-
-fn main() {
- let a = Foo { foo: 12 };
- let b = Bar { bar: 12 };
- println!("{:?} {:?}", a, b);
-}
+++ /dev/null
-// error-pattern: requires `copy` lang_item
-
-#![feature(lang_items, start, no_core)]
-#![no_core]
-
-#[lang = "sized"]
-trait Sized { }
-
-struct S;
-
-#[start]
-fn main(_: isize, _: *const *const u8) -> isize {
- let _ = S;
- 0
-}
+++ /dev/null
-error: requires `copy` lang_item
-
-error: aborting due to previous error
-
+++ /dev/null
-// run-pass
-#![allow(stable_features)]
-
-// ignore-emscripten no processes
-// ignore-sgx no processes
-
-#![feature(os)]
-
-#[cfg(unix)]
-fn main() {
- use std::process::Command;
- use std::env;
- use std::os::unix::prelude::*;
- use std::ffi::OsStr;
-
- if env::args().len() == 1 {
- assert!(Command::new(&env::current_exe().unwrap())
- .arg(<OsStr as OsStrExt>::from_bytes(b"\xff"))
- .status().unwrap().success())
- }
-}
-
-#[cfg(windows)]
-fn main() {}
+++ /dev/null
-// We need all these 9 issue-20616-N.rs files
-// because we can only catch one parsing error at a time
-
-type Type_1_<'a, T> = &'a T;
-
-
-//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
-
-
-//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
-
-
-//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
-
-
-type Type_4<T> = Type_1_<'static,, T>;
-//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
-
-
-type Type_5_<'a> = Type_1_<'a, ()>;
-
-
-//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
-
-
-//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
-
-
-//type Type_7 = Box<(),,>; // error: expected type, found `,`
-
-
-//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
-
-
-//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
+++ /dev/null
-error: expected one of `>`, a const expression, lifetime, or type, found `,`
- --> $DIR/issue-20616-4.rs:16:34
- |
-LL | type Type_4<T> = Type_1_<'static,, T>;
- | ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to previous error
-
+++ /dev/null
-// We need all these 9 issue-20616-N.rs files
-// because we can only catch one parsing error at a time
-
-type Type_1_<'a, T> = &'a T;
-
-
-//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
-
-
-//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
-
-
-//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
-
-
-//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
-
-
-type Type_5_<'a> = Type_1_<'a, ()>;
-
-
-type Type_5<'a> = Type_1_<'a, (),,>;
-//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
-
-
-//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
-
-
-//type Type_7 = Box<(),,>; // error: expected type, found `,`
-
-
-//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
-
-
-//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
+++ /dev/null
-error: expected one of `>`, a const expression, lifetime, or type, found `,`
- --> $DIR/issue-20616-5.rs:22:34
- |
-LL | type Type_5<'a> = Type_1_<'a, (),,>;
- | ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to previous error
-
+++ /dev/null
-// We need all these 9 issue-20616-N.rs files
-// because we can only catch one parsing error at a time
-
-type Type_1_<'a, T> = &'a T;
-
-
-//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
-
-
-//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
-
-
-//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
-
-
-//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
-
-
-type Type_5_<'a> = Type_1_<'a, ()>;
-
-
-//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
-
-
-type Type_6 = Type_5_<'a,,>;
-//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
-
-
-//type Type_7 = Box<(),,>; // error: expected type, found `,`
-
-
-//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
-
-
-//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
+++ /dev/null
-error: expected one of `>`, a const expression, lifetime, or type, found `,`
- --> $DIR/issue-20616-6.rs:25:26
- |
-LL | type Type_6 = Type_5_<'a,,>;
- | ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to previous error
-
+++ /dev/null
-// We need all these 9 issue-20616-N.rs files
-// because we can only catch one parsing error at a time
-
-type Type_1_<'a, T> = &'a T;
-
-
-//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
-
-
-//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
-
-
-//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
-
-
-//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
-
-
-type Type_5_<'a> = Type_1_<'a, ()>;
-
-
-//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
-
-
-//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
-
-
-type Type_7 = Box<(),,>;
-//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
-
-
-//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
-
-
-//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
+++ /dev/null
-error: expected one of `>`, a const expression, lifetime, or type, found `,`
- --> $DIR/issue-20616-7.rs:28:22
- |
-LL | type Type_7 = Box<(),,>;
- | ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to previous error
-
+++ /dev/null
-// run-pass
-// compile-flags: --test
-
-#[test]
-pub fn foo() {}
+++ /dev/null
-#![allow(unused_macros)]
-
-macro_rules! test { ($wrong:t_ty ..) => () }
- //~^ ERROR: invalid fragment specifier `t_ty`
-
-fn main() {}
+++ /dev/null
-error: invalid fragment specifier `t_ty`
- --> $DIR/issue-21356.rs:3:22
- |
-LL | macro_rules! test { ($wrong:t_ty ..) => () }
- | ^^^^^^^^^^^
- |
- = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
-
-error: aborting due to previous error
-
+++ /dev/null
-// run-pass
-#![allow(unused_imports, overlapping_range_endpoints)]
-// pretty-expanded FIXME #23616
-
-use m::{START, END};
-
-fn main() {
- match 42 {
- m::START..=m::END => {},
- 0..=m::END => {},
- m::START..=59 => {},
- _ => {},
- }
-}
-
-mod m {
- pub const START: u32 = 4;
- pub const END: u32 = 14;
-}
+++ /dev/null
-// check-pass
-#![allow(dead_code)]
-// Test that the requirement (in `Bar`) that `T::Bar : 'static` does
-// not wind up propagating to `T`.
-
-// pretty-expanded FIXME #23616
-
-pub trait Foo {
- type Bar;
-
- fn foo(&self) -> Self;
-}
-
-pub struct Static<T:'static>(T);
-
-struct Bar<T:Foo>
- where T::Bar : 'static
-{
- x: Static<Option<T::Bar>>
-}
-
-fn main() { }
+++ /dev/null
-// check-pass
-pub trait LineFormatter<'a> {
- type Iter: Iterator<Item=&'a str> + 'a;
- fn iter(&'a self, line: &'a str) -> Self::Iter;
-
- fn dimensions(&'a self, line: &'a str) {
- let iter: Self::Iter = self.iter(line);
- <_ as IntoIterator>::into_iter(iter);
- }
-}
-
-fn main() {}
+++ /dev/null
-// run-pass
-macro_rules! items {
- () => {
- type A = ();
- fn a() {}
- }
-}
-
-trait Foo {
- type A;
- fn a();
-}
-
-impl Foo for () {
- items!();
-}
-
-fn main() {
-
-}
+++ /dev/null
-// run-pass
-#![allow(dead_code)]
-// Test transitive analysis for associated types. Collected types
-// should be normalized and new obligations generated.
-
-// pretty-expanded FIXME #23616
-
-trait Foo {
- type A;
- fn foo(&self) {}
-}
-
-impl Foo for usize {
- type A = usize;
-}
-
-struct Bar<T: Foo> { inner: T::A }
-
-fn is_send<T: Send>() {}
-
-fn main() {
- is_send::<Bar<usize>>();
-}
+++ /dev/null
-#![feature(llvm_asm)]
-#![allow(deprecated)] // llvm_asm!
-// compile-flags: -Ccodegen-units=1
-// build-fail
-// only-x86_64
-
-fn main() {
- unsafe {
- llvm_asm!("int $3"); //~ ERROR too few operands for instruction
- //~| ERROR invalid operand in inline asm
- }
-}
+++ /dev/null
-error: invalid operand in inline asm: 'int $3'
- --> $DIR/issue-23458.rs:9:9
- |
-LL | llvm_asm!("int $3");
- | ^
-
-error: too few operands for instruction
- --> $DIR/issue-23458.rs:9:9
- |
-LL | llvm_asm!("int $3");
- | ^
- |
-note: instantiated into assembly here
- --> <inline asm>:1:2
- |
-LL | int
- | ^
-
-error: aborting due to 2 previous errors
-
+++ /dev/null
-static foo: i32 = 0;
-
-fn bar(foo: i32) {}
-//~^ ERROR function parameters cannot shadow statics
-//~| cannot be named the same as a static
-
-mod submod {
- pub static answer: i32 = 42;
-}
-
-use self::submod::answer;
-
-fn question(answer: i32) {}
-//~^ ERROR function parameters cannot shadow statics
-//~| cannot be named the same as a static
-fn main() {
-}
+++ /dev/null
-error[E0530]: function parameters cannot shadow statics
- --> $DIR/issue-23716.rs:3:8
- |
-LL | static foo: i32 = 0;
- | -------------------- the static `foo` is defined here
-LL |
-LL | fn bar(foo: i32) {}
- | ^^^ cannot be named the same as a static
-
-error[E0530]: function parameters cannot shadow statics
- --> $DIR/issue-23716.rs:13:13
- |
-LL | use self::submod::answer;
- | -------------------- the static `answer` is imported here
-LL |
-LL | fn question(answer: i32) {}
- | ^^^^^^ cannot be named the same as a static
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0530`.
+++ /dev/null
-// run-pass
-const U8_MAX_HALF: u8 = !0u8 / 2;
-const U16_MAX_HALF: u16 = !0u16 / 2;
-const U32_MAX_HALF: u32 = !0u32 / 2;
-const U64_MAX_HALF: u64 = !0u64 / 2;
-
-fn main() {
- assert_eq!(U8_MAX_HALF, 0x7f);
- assert_eq!(U16_MAX_HALF, 0x7fff);
- assert_eq!(U32_MAX_HALF, 0x7fff_ffff);
- assert_eq!(U64_MAX_HALF, 0x7fff_ffff_ffff_ffff);
-}
+++ /dev/null
-// run-pass
-
-trait Foo: Fn(i32) -> i32 + Send {}
-
-impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
-
-fn wants_foo(f: Box<dyn Foo>) -> i32 {
- f(42)
-}
-
-fn main() {
- let f = Box::new(|x| x);
- assert_eq!(wants_foo(f), 42);
-}
+++ /dev/null
-// run-pass
-// ignore-emscripten no threads
-// ignore-sgx no processes
-
-use std::thread;
-use std::env;
-use std::process::Command;
-
-struct Handle(i32);
-
-impl Drop for Handle {
- fn drop(&mut self) { panic!(); }
-}
-
-thread_local!(static HANDLE: Handle = Handle(0));
-
-fn main() {
- let args = env::args().collect::<Vec<_>>();
- if args.len() == 1 {
- let out = Command::new(&args[0]).arg("test").output().unwrap();
- let stderr = std::str::from_utf8(&out.stderr).unwrap();
- assert!(stderr.contains("panicked at 'explicit panic'"),
- "bad failure message:\n{}\n", stderr);
- } else {
- // TLS dtors are not always run on process exit
- thread::spawn(|| {
- HANDLE.with(|h| {
- println!("{}", h.0);
- });
- }).join().unwrap();
- }
-}
+++ /dev/null
-// run-fail
-// error-pattern:explicit panic
-// ignore-emscripten no processes
-
-use std::sync::Arc;
-
-enum Err<T> {
- Errr(Arc<T>),
-}
-
-fn foo() -> Err<isize> {
- panic!();
-}
-
-fn main() {
- let _f = foo();
-}
+++ /dev/null
-// run-pass
-#![allow(overlapping_range_endpoints)]
-
-fn main() {
- let x = 'a';
-
- let y = match x {
- 'a'..='b' if false => "one",
- 'a' => "two",
- 'a'..='b' => "three",
- _ => panic!("what?"),
- };
-
- assert_eq!(y, "two");
-}
+++ /dev/null
-// run-pass
-
-pub trait Foo<T> {
- fn foo(self) -> T;
-}
-
-impl<'a, T> Foo<T> for &'a str where &'a str: Into<T> {
- fn foo(self) -> T {
- panic!();
- }
-}
-
-fn main() {}
+++ /dev/null
-// check-pass
-
-pub struct Bar<T> {
- items: Vec<&'static str>,
- inner: T,
-}
-
-pub trait IntoBar<T> {
- fn into_bar(self) -> Bar<T>;
-}
-
-impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
- fn into_bar(self) -> Bar<T> {
- Bar {
- items: Vec::new(),
- inner: self.into(),
- }
- }
-}
-
-fn main() {}
+++ /dev/null
-// check-pass
-
-pub struct Item {
- _inner: &'static str,
-}
-
-pub struct Bar<T> {
- items: Vec<Item>,
- inner: T,
-}
-
-pub trait IntoBar<T> {
- fn into_bar(self) -> Bar<T>;
-}
-
-impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
- fn into_bar(self) -> Bar<T> {
- Bar {
- items: Vec::new(),
- inner: self.into(),
- }
- }
-}
-
-fn main() {}
+++ /dev/null
-fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
-//~^ ERROR missing lifetime specifier [E0106]
-
-fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
-//~^ ERROR missing lifetime specifier [E0106]
-
-fn parse_type_3() -> &str { unimplemented!() }
-//~^ ERROR missing lifetime specifier [E0106]
-
-fn main() {}
+++ /dev/null
-error[E0106]: missing lifetime specifier
- --> $DIR/issue-26638.rs:1:62
- |
-LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
- | ------------------------------------ ^ expected named lifetime parameter
- |
- = help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
-help: consider introducing a named lifetime parameter
- |
-LL | fn parse_type<'a>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'a str { iter.next() }
- | ++++ ++
-
-error[E0106]: missing lifetime specifier
- --> $DIR/issue-26638.rs:4:40
- |
-LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
- | ^ expected named lifetime parameter
- |
- = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
-help: consider using the `'static` lifetime
- |
-LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &'static str { iter() }
- | ~~~~~~~~
-
-error[E0106]: missing lifetime specifier
- --> $DIR/issue-26638.rs:7:22
- |
-LL | fn parse_type_3() -> &str { unimplemented!() }
- | ^ expected named lifetime parameter
- |
- = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
-help: consider using the `'static` lifetime
- |
-LL | fn parse_type_3() -> &'static str { unimplemented!() }
- | ~~~~~~~~
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0106`.
+++ /dev/null
-// run-pass
-
-// This test is bogus (i.e., should be check-fail) during the period
-// where #54986 is implemented and #54987 is *not* implemented. For
-// now: just ignore it
-//
-// ignore-test
-
-// This test is checking that the write to `c.0` (which has been moved out of)
-// won't overwrite the state in `c2`.
-//
-// That's a fine thing to test when this code is accepted by the
-// compiler, and this code is being transcribed accordingly into
-// the ui test issue-21232-partial-init-and-use.rs
-
-fn main() {
- let mut c = (1, "".to_owned());
- match c {
- c2 => {
- c.0 = 2;
- assert_eq!(c2.0, 1);
- }
- }
-}
+++ /dev/null
-// run-pass
-
-fn thing<'r>(x: &'r [isize]) -> &'r [isize] { x }
-
-pub fn main() {
- let x = &[1,2,3];
- let y = x;
- let z = thing(x);
- assert_eq!(z[2], x[2]);
- assert_eq!(z[1], y[1]);
-}
+++ /dev/null
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
- --> $DIR/issue-28324.rs:8:24
- |
-LL | pub static BAZ: u32 = *&error_message_count;
- | ^^^^^^^^^^^^^^^^^^^^ use of extern static
- |
- = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
+++ /dev/null
-// revisions: mir thir
-// [thir]compile-flags: -Z thir-unsafeck
-
-extern "C" {
- static error_message_count: u32;
-}
-
-pub static BAZ: u32 = *&error_message_count;
-//~^ ERROR use of extern static is unsafe and requires
-
-fn main() {}
+++ /dev/null
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
- --> $DIR/issue-28324.rs:8:25
- |
-LL | pub static BAZ: u32 = *&error_message_count;
- | ^^^^^^^^^^^^^^^^^^^ use of extern static
- |
- = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0133`.
+++ /dev/null
-// run-pass
-
-// Demonstrate the use of the unguarded escape hatch with a type param in negative position
-// to assert that destructor will not access any dead data.
-//
-// Compare with ui/span/issue28498-reject-lifetime-param.rs
-
-// Demonstrate that a type param in negative position causes dropck to reject code
-// that might indirectly access previously dropped value.
-//
-// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
-
-#![feature(dropck_eyepatch)]
-
-#[derive(Debug)]
-struct ScribbleOnDrop(String);
-
-impl Drop for ScribbleOnDrop {
- fn drop(&mut self) {
- self.0 = format!("DROPPED");
- }
-}
-
-struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
-
-unsafe impl<#[may_dangle] T> Drop for Foo<T> {
- fn drop(&mut self) {
- // Use of `may_dangle` is sound, because destructor never passes a `self.1`
- // to the callback (in `self.2`) despite having it available.
- println!("Dropping Foo({}, _)", self.0);
- }
-}
-
-fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
-
-fn main() {
- let (last_dropped, foo0);
- let (foo1, first_dropped);
-
- last_dropped = ScribbleOnDrop(format!("last"));
- first_dropped = ScribbleOnDrop(format!("first"));
- foo0 = Foo(0, &last_dropped, Box::new(callback));
- foo1 = Foo(1, &first_dropped, Box::new(callback));
-
- println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
-}
+++ /dev/null
-// check-pass
-// Regression test for #28871. The problem is that rustc encountered
-// two ways to project, one from a where clause and one from the where
-// clauses on the trait definition. (In fact, in this case, the where
-// clauses originated from the trait definition as well.) The true
-// cause of the error is that the trait definition where clauses are
-// not being normalized, and hence the two sources are considered in
-// conflict, and not a duplicate. Hacky solution is to prefer where
-// clauses over the data found in the trait definition.
-
-trait T {
- type T;
-}
-
-struct S;
-impl T for S {
- type T = S;
-}
-
-trait T2 {
- type T: Iterator<Item=<S as T>::T>;
-}
-
-fn main() { }
+++ /dev/null
-macro_rules! foo {
- ($d:expr) => {{
- fn bar(d: u8) { }
- bar(&mut $d);
- //~^ ERROR mismatched types
- //~| expected `u8`, found `&mut u8`
- }}
-}
-
-fn main() {
- foo!(0u8);
- //~^ in this expansion of foo!
-}
+++ /dev/null
-error[E0308]: mismatched types
- --> $DIR/issue-29084.rs:4:13
- |
-LL | bar(&mut $d);
- | ^^^^^^^ expected `u8`, found `&mut u8`
-...
-LL | foo!(0u8);
- | --------- in this macro invocation
- |
- = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
+++ /dev/null
-fn siphash<T>() {
-
- trait U {
- fn g(&self, x: T) -> T; //~ ERROR can't use generic parameters from outer function
- //~^ ERROR can't use generic parameters from outer function
- }
-}
-
-fn main() {}
+++ /dev/null
-error[E0401]: can't use generic parameters from outer function
- --> $DIR/issue-3021-c.rs:4:24
- |
-LL | fn siphash<T>() {
- | - type parameter from outer function
-...
-LL | fn g(&self, x: T) -> T;
- | - ^ use of generic parameter from outer function
- | |
- | help: try using a local generic parameter instead: `g<T>`
-
-error[E0401]: can't use generic parameters from outer function
- --> $DIR/issue-3021-c.rs:4:30
- |
-LL | fn siphash<T>() {
- | - type parameter from outer function
-...
-LL | fn g(&self, x: T) -> T;
- | - ^ use of generic parameter from outer function
- | |
- | help: try using a local generic parameter instead: `g<T>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0401`.
+++ /dev/null
-trait SipHash {
- fn reset(&self);
-}
-
-fn siphash(k0 : u64) {
- struct SipState {
- v0: u64,
- }
-
- impl SipHash for SipState {
- fn reset(&self) {
- self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
- }
- }
- panic!();
-}
-
-fn main() {}
+++ /dev/null
-error[E0434]: can't capture dynamic environment in a fn item
- --> $DIR/issue-3021.rs:12:22
- |
-LL | self.v0 = k0 ^ 0x736f6d6570736575;
- | ^^
- |
- = help: use the `|| { ... }` closure form instead
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0434`.
+++ /dev/null
-// Regression test for #30225, which was an ICE that would trigger as
-// a result of a poor interaction between trait result caching and
-// type inference. Specifically, at that time, unification could cause
-// unrelated type variables to become instantiated, if subtyping
-// relationships existed. These relationships are now propagated
-// through obligations and hence everything works out fine.
-
-trait Foo<U,V> : Sized {
- fn foo(self, u: Option<U>, v: Option<V>) {}
-}
-
-struct A;
-struct B;
-
-impl Foo<A, B> for () {} // impl A
-impl Foo<u32, u32> for u32 {} // impl B, creating ambiguity
-
-fn toxic() {
- // cache the resolution <() as Foo<$0,$1>> = impl A
- let u = None;
- let v = None;
- Foo::foo((), u, v);
-}
-
-fn bomb() {
- let mut u = None; // type is Option<$0>
- let mut v = None; // type is Option<$1>
- let mut x = None; // type is Option<$2>
-
- Foo::foo(x.unwrap(),u,v); // register <$2 as Foo<$0, $1>>
- u = v; // mark $0 and $1 in a subtype relationship
- //~^ ERROR mismatched types
- x = Some(()); // set $2 = (), allowing impl selection
- // to proceed for <() as Foo<$0, $1>> = impl A.
- // kaboom, this *used* to trigge an ICE
-}
-
-fn main() {}
+++ /dev/null
-error[E0308]: mismatched types
- --> $DIR/issue-30225.rs:31:9
- |
-LL | u = v; // mark $0 and $1 in a subtype relationship
- | ^ expected struct `A`, found struct `B`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
+++ /dev/null
-pub struct X([u8]);
-
-pub static Y: &'static X = {
- const Y: &'static [u8] = b"";
- &X(*Y)
- //~^ ERROR E0277
-};
-
-fn main() {}
+++ /dev/null
-error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
- --> $DIR/issue-30355.rs:5:8
- |
-LL | &X(*Y)
- | ^^ doesn't have a size known at compile-time
- |
- = help: the trait `Sized` is not implemented for `[u8]`
- = note: all function arguments must have a statically known size
- = help: unsized fn params are gated as an unstable feature
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
+++ /dev/null
-#![feature(no_core, lang_items)]
-#![no_core]
-
-#[lang="sized"]
-trait Sized {}
-
-#[lang="add"]
-trait Add<T> {}
-
-impl Add<i32> for i32 {}
-
-fn main() {
- let x = 5 + 6;
- //~^ ERROR cannot add `i32` to `{integer}`
- let y = 5i32 + 6i32;
- //~^ ERROR cannot add `i32` to `i32`
-}
+++ /dev/null
-error[E0369]: cannot add `i32` to `{integer}`
- --> $DIR/issue-31076.rs:13:15
- |
-LL | let x = 5 + 6;
- | - ^ - i32
- | |
- | {integer}
-
-error[E0369]: cannot add `i32` to `i32`
- --> $DIR/issue-31076.rs:15:18
- |
-LL | let y = 5i32 + 6i32;
- | ---- ^ ---- i32
- | |
- | i32
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0369`.
+++ /dev/null
-// Test that error recovery in the parser to an EOF does not give an infinite
-// spew of errors.
-
-fn main() {
- let
-} //~ ERROR expected pattern, found `}`
+++ /dev/null
-error: expected pattern, found `}`
- --> $DIR/issue-31804.rs:6:1
- |
-LL | }
- | ^ expected pattern
-
-error: aborting due to previous error
-
+++ /dev/null
-// Checks lexical scopes cannot see through normal module boundaries
-
-fn f() {
- fn g() {}
- mod foo {
- fn h() {
- g(); //~ ERROR cannot find function `g` in this scope
- }
- }
-}
-
-fn main() {}
+++ /dev/null
-error[E0425]: cannot find function `g` in this scope
- --> $DIR/issue-31845.rs:7:12
- |
-LL | g();
- | ^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
+++ /dev/null
-// run-pass
-pub fn main() {
- let mut x = 0;
- for _ in 0..4096 { x += 1; }
- assert_eq!(x, 4096);
- println!("x = {}", x);
-}
+++ /dev/null
-extern "C" {
- fn foo(a: i32, ...);
-}
-
-fn bar(_: *const u8) {}
-
-fn main() {
- unsafe {
- foo(0, bar);
- //~^ ERROR can't pass `fn(*const u8) {bar}` to variadic function
- //~| HELP cast the value to `fn(*const u8)`
- }
-}
+++ /dev/null
-error[E0617]: can't pass `fn(*const u8) {bar}` to variadic function
- --> $DIR/issue-32201.rs:9:16
- |
-LL | foo(0, bar);
- | ^^^ help: cast the value to `fn(*const u8)`: `bar as fn(*const u8)`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0617`.
+++ /dev/null
-// run-pass
-
-fn quux<T>(x: T) -> T { let f = id::<T>; return f(x); }
-
-fn id<T>(x: T) -> T { return x; }
-
-pub fn main() { assert_eq!(quux(10), 10); }
+++ /dev/null
-// check-pass
-
-macro_rules! m {
- () => { #[cfg(any())] fn f() {} }
-}
-
-trait T {}
-impl T for () { m!(); }
-
-fn main() {}
+++ /dev/null
-// check-pass
-
-macro_rules! null { ($i:tt) => {} }
-macro_rules! apply_null {
- ($i:item) => { null! { $i } }
-}
-
-fn main() {
- apply_null!(#[cfg(all())] fn f() {});
-}
+++ /dev/null
-enum Test {
- Drill {
- field: i32,
- }
-}
-
-fn main() {
- Test::Drill(field: 42);
- //~^ ERROR invalid `struct` delimiters or `fn` call arguments
-}
+++ /dev/null
-error: invalid `struct` delimiters or `fn` call arguments
- --> $DIR/issue-34255-1.rs:8:5
- |
-LL | Test::Drill(field: 42);
- | ^^^^^^^^^^^^^^^^^^^^^^
- |
-help: if `Test::Drill` is a struct, use braces as delimiters
- |
-LL | Test::Drill { field: 42 };
- | ~ ~
-help: if `Test::Drill` is a function, use the arguments directly
- |
-LL - Test::Drill(field: 42);
-LL + Test::Drill(42);
- |
-
-error: aborting due to previous error
-
+++ /dev/null
-// build-pass
-#![allow(dead_code)]
-// Regression test for #35546. Check that we are able to codegen
-// this. Before we had problems because of the drop glue signature
-// around dropping a trait object (specifically, when dropping the
-// `value` field of `Node<Send>`).
-
-struct Node<T: ?Sized + Send> {
- next: Option<Box<Node<dyn Send>>>,
- value: T,
-}
-
-fn clear(head: &mut Option<Box<Node<dyn Send>>>) {
- match head.take() {
- Some(node) => *head = node.next,
- None => (),
- }
-}
-
-fn main() {}
+++ /dev/null
-// run-pass
-macro_rules! m { (<$t:ty>) => { stringify!($t) } }
-fn main() {
- println!("{}", m!(<Vec<i32>>));
-}
+++ /dev/null
-// check-pass
-// ignore-emscripten
-
-#![feature(llvm_asm)]
-#![allow(deprecated)] // llvm_asm!
-
-macro_rules! interrupt_handler {
- () => {
- unsafe fn _interrupt_handler() {
- llvm_asm!("pop eax" :::: "intel");
- }
- }
-}
-interrupt_handler!{}
-
-fn main() {}
+++ /dev/null
-const fn x() {
- let t = true;
- let x = || t; //~ ERROR function pointer
-}
-
-fn main() {}
+++ /dev/null
-error[E0658]: function pointers cannot appear in constant functions
- --> $DIR/issue-37550.rs:3:9
- |
-LL | let x = || t;
- | ^
- |
- = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
- = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
+++ /dev/null
-// run-pass
-
-const fn foo() -> i64 {
- 3
-}
-
-const fn bar(x: i64) -> i64 {
- x*2
-}
-
-fn main() {
- let val = &(foo() % 2);
- assert_eq!(*val, 1);
-
- let val2 = &(bar(1+1) % 3);
- assert_eq!(*val2, 1);
-}
+++ /dev/null
-trait Q<T:?Sized> {}
-trait Foo where u32: Q<Self> {
- fn foo(&self);
-}
-
-impl Q<()> for u32 {}
-impl Foo for () {
- fn foo(&self) {
- println!("foo!");
- }
-}
-
-fn main() {
- let _f: Box<dyn Foo> = //~ ERROR `Foo` cannot be made into an object
- Box::new(()); //~ ERROR `Foo` cannot be made into an object
-}
+++ /dev/null
-error[E0038]: the trait `Foo` cannot be made into an object
- --> $DIR/issue-38604.rs:14:13
- |
-LL | let _f: Box<dyn Foo> =
- | ^^^^^^^^^^^^ `Foo` cannot be made into an object
- |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
- --> $DIR/issue-38604.rs:2:22
- |
-LL | trait Foo where u32: Q<Self> {
- | --- ^^^^^^^ ...because it uses `Self` as a type parameter
- | |
- | this trait cannot be made into an object...
-
-error[E0038]: the trait `Foo` cannot be made into an object
- --> $DIR/issue-38604.rs:15:9
- |
-LL | Box::new(());
- | ^^^^^^^^^^^^ `Foo` cannot be made into an object
- |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
- --> $DIR/issue-38604.rs:2:22
- |
-LL | trait Foo where u32: Q<Self> {
- | --- ^^^^^^^ ...because it uses `Self` as a type parameter
- | |
- | this trait cannot be made into an object...
- = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn Foo>>` for `Box<()>`
- = note: required by cast to type `Box<dyn Foo>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0038`.
+++ /dev/null
-#![allow(unused_macros)]
-
-macro_rules! assign {
- (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected one of: `*`, `+`, or `?`
- $($a)* = $($b)*
- }
-}
-
-fn main() {}
+++ /dev/null
-error: expected one of: `*`, `+`, or `?`
- --> $DIR/issue-39388.rs:4:22
- |
-LL | (($($a:tt)*) = ($($b:tt))*) => {
- | ^^^^^^^
-
-error: aborting due to previous error
-
+++ /dev/null
-struct Point {
- x: f64,
- y: f64,
-}
-
-trait ToString_ {
- fn to_string(&self) -> String;
-}
-
-impl ToString_ for Point {
- fn new(x: f64, y: f64) -> Point {
- //~^ ERROR method `new` is not a member of trait `ToString_`
- Point { x: x, y: y }
- }
-
- fn to_string(&self) -> String {
- format!("({}, {})", self.x, self.y)
- }
-}
-
-fn main() {
- let p = Point::new(0.0, 0.0);
- //~^ ERROR no function or associated item named `new` found for struct `Point`
- println!("{}", p.to_string());
-}
+++ /dev/null
-error[E0407]: method `new` is not a member of trait `ToString_`
- --> $DIR/issue-3973.rs:11:5
- |
-LL | / fn new(x: f64, y: f64) -> Point {
-LL | |
-LL | | Point { x: x, y: y }
-LL | | }
- | |_____^ not a member of trait `ToString_`
-
-error[E0599]: no function or associated item named `new` found for struct `Point` in the current scope
- --> $DIR/issue-3973.rs:22:20
- |
-LL | struct Point {
- | ------------ function or associated item `new` not found for this
-...
-LL | let p = Point::new(0.0, 0.0);
- | ^^^ function or associated item not found in `Point`
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0407, E0599.
-For more information about an error, try `rustc --explain E0407`.
+++ /dev/null
-// run-pass
-// aux-build:issue-39823.rs
-
-extern crate issue_39823;
-use issue_39823::{RemoteC, RemoteG};
-
-#[derive(Debug, PartialEq)]
-struct LocalC(u32);
-
-#[derive(Debug, PartialEq)]
-struct LocalG<T>(T);
-
-fn main() {
- let virtual_localc : &dyn Fn(_) -> LocalC = &LocalC;
- assert_eq!(virtual_localc(1), LocalC(1));
-
- let virtual_localg : &dyn Fn(_) -> LocalG<u32> = &LocalG;
- assert_eq!(virtual_localg(1), LocalG(1));
-
- let virtual_remotec : &dyn Fn(_) -> RemoteC = &RemoteC;
- assert_eq!(virtual_remotec(1), RemoteC(1));
-
- let virtual_remoteg : &dyn Fn(_) -> RemoteG<u32> = &RemoteG;
- assert_eq!(virtual_remoteg(1), RemoteG(1));
-}
+++ /dev/null
-// run-pass
-#![allow(unused_macros)]
-macro_rules! m {
- ($e:expr) => {
- macro_rules! n { () => { $e } }
- }
-}
-
-fn main() {
- m!(foo!());
-}
+++ /dev/null
-// check-pass
-macro_rules! m {
- ($i:meta) => {
- #[derive($i)]
- struct S;
- }
-}
-
-m!(Clone);
-
-fn main() {}
+++ /dev/null
-// run-pass
-use std::ops::{Deref, DerefMut};
-
-struct CheckedDeref<T, F> {
- value: T,
- check: F
-}
-
-impl<F: Fn(&T) -> bool, T> Deref for CheckedDeref<T, F> {
- type Target = T;
- fn deref(&self) -> &T {
- assert!((self.check)(&self.value));
- &self.value
- }
-}
-
-impl<F: Fn(&T) -> bool, T> DerefMut for CheckedDeref<T, F> {
- fn deref_mut(&mut self) -> &mut T {
- assert!((self.check)(&self.value));
- &mut self.value
- }
-}
-
-
-fn main() {
- let mut v = CheckedDeref {
- value: vec![0],
- check: |v: &Vec<_>| !v.is_empty()
- };
- v.push(1);
- assert_eq!(*v, vec![0, 1]);
-}
+++ /dev/null
-// run-pass
-#![feature(box_syntax)]
-#![feature(box_patterns)]
-
-#[derive(Debug, PartialEq)]
-enum Test {
- Foo(usize),
- Bar(isize),
-}
-
-fn main() {
- let a = box Test::Foo(10);
- let b = box Test::Bar(-20);
- match (a, b) {
- (_, box Test::Foo(_)) => unreachable!(),
- (box Test::Foo(x), b) => {
- assert_eq!(x, 10);
- assert_eq!(b, box Test::Bar(-20));
- },
- _ => unreachable!(),
- }
-}
+++ /dev/null
-// run-pass
-macro_rules! fooN {
- ($cur:ident $prev:ty) => {
- #[allow(dead_code)]
- enum $cur {
- Empty,
- First($prev),
- Second($prev),
- Third($prev),
- Fourth($prev),
- }
- }
-}
-
-fooN!(Foo0 ());
-fooN!(Foo1 Foo0);
-fooN!(Foo2 Foo1);
-fooN!(Foo3 Foo2);
-fooN!(Foo4 Foo3);
-fooN!(Foo5 Foo4);
-fooN!(Foo6 Foo5);
-fooN!(Foo7 Foo6);
-fooN!(Foo8 Foo7);
-fooN!(Foo9 Foo8);
-fooN!(Foo10 Foo9);
-fooN!(Foo11 Foo10);
-fooN!(Foo12 Foo11);
-fooN!(Foo13 Foo12);
-fooN!(Foo14 Foo13);
-fooN!(Foo15 Foo14);
-fooN!(Foo16 Foo15);
-fooN!(Foo17 Foo16);
-fooN!(Foo18 Foo17);
-fooN!(Foo19 Foo18);
-fooN!(Foo20 Foo19);
-fooN!(Foo21 Foo20);
-fooN!(Foo22 Foo21);
-fooN!(Foo23 Foo22);
-fooN!(Foo24 Foo23);
-fooN!(Foo25 Foo24);
-fooN!(Foo26 Foo25);
-fooN!(Foo27 Foo26);
-
-fn main() {
- let _foo = Foo27::Empty;
-}
+++ /dev/null
-// Issue 46112: An extern crate pub re-exporting libcore was causing
-// paths rooted from `std` to be misrendered in the diagnostic output.
-
-// ignore-windows
-// aux-build:xcrate-issue-43189-a.rs
-// aux-build:xcrate-issue-43189-b.rs
-
-extern crate xcrate_issue_43189_b;
-fn main() {
- ().a();
- //~^ ERROR no method named `a` found
-}
+++ /dev/null
-error[E0599]: no method named `a` found for unit type `()` in the current scope
- --> $DIR/issue-43189.rs:10:8
- |
-LL | ().a();
- | ^ method not found in `()`
- |
- ::: $DIR/auxiliary/xcrate-issue-43189-a.rs:5:8
- |
-LL | fn a(&self) {}
- | - the method is available for `()` here
- |
- = help: items from traits can only be used if the trait is in scope
-help: the following trait is implemented but not in scope; perhaps add a `use` for it:
- |
-LL | use xcrate_issue_43189_b::xcrate_issue_43189_a::A;
- |
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0599`.
+++ /dev/null
-pub trait Foo<'a> {
- type Bar;
- fn foo(&'a self) -> Self::Bar;
-}
-
-impl<'a, 'b, T: 'a> Foo<'a> for &'b T {
- type Bar = &'a T;
- fn foo(&'a self) -> &'a T {
- self
- }
-}
-
-pub fn uncallable<T, F>(x: T, f: F)
-where
- T: for<'a> Foo<'a>,
- F: for<'a> Fn(<T as Foo<'a>>::Bar),
-{
- f(x.foo());
-}
-
-pub fn catalyst(x: &i32) {
- broken(x, |_| {})
-}
-
-pub fn broken<F: Fn(&i32)>(x: &i32, f: F) {
- uncallable(x, |y| f(y));
- //~^ type mismatch
-}
-
-fn main() {}
+++ /dev/null
-error[E0631]: type mismatch in closure arguments
- --> $DIR/issue-44005.rs:26:5
- |
-LL | uncallable(x, |y| f(y));
- | ^^^^^^^^^^ -------- found signature of `for<'r> fn(&'r i32) -> _`
- | |
- | expected signature of `for<'a> fn(<&i32 as Foo<'a>>::Bar) -> _`
- |
-note: required by a bound in `uncallable`
- --> $DIR/issue-44005.rs:16:8
- |
-LL | pub fn uncallable<T, F>(x: T, f: F)
- | ---------- required by a bound in this
-...
-LL | F: for<'a> Fn(<T as Foo<'a>>::Bar),
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `uncallable`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0631`.
+++ /dev/null
-// run-pass
-pub fn main() {
- let mut count = 0;
- for _ in 0..999_999 { count += 1; }
- assert_eq!(count, 999_999);
- println!("{}", count);
-}
+++ /dev/null
-// run-pass
-// ignore-emscripten no threads support
-
-use std::sync::mpsc::channel;
-use std::thread;
-
-pub fn main() {
- let (tx, rx) = channel::<&'static str>();
-
- let t = thread::spawn(move|| {
- assert_eq!(rx.recv().unwrap(), "hello, world");
- });
-
- tx.send("hello, world").unwrap();
- t.join().ok().unwrap();
-}
+++ /dev/null
-// run-pass
-#![allow(unreachable_code)]
-// compile-flags: --edition 2018
-
-#![feature(try_blocks)]
-
-fn main() {
- let mut a = 0;
- let () = {
- let _: Result<(), ()> = try {
- let _ = Err(())?;
- return
- };
- a += 1;
- };
- a += 2;
- assert_eq!(a, 3);
-}
+++ /dev/null
-// run-pass
-#![allow(dead_code)]
-#![allow(unused_variables)]
-#![feature(unsize, coerce_unsized)]
-
-#[repr(packed)]
-struct UnalignedPtr<'a, T: ?Sized>
- where T: 'a,
-{
- data: &'a T,
-}
-
-fn main() {
-
- impl<'a, T, U> std::ops::CoerceUnsized<UnalignedPtr<'a, U>> for UnalignedPtr<'a, T>
- where
- T: std::marker::Unsize<U> + ?Sized,
- U: ?Sized,
- { }
-
- let arr = [1, 2, 3];
- let arr_unaligned: UnalignedPtr<[i32; 3]> = UnalignedPtr { data: &arr };
- let arr_unaligned: UnalignedPtr<[i32]> = arr_unaligned;
-}
+++ /dev/null
-// run-pass
-struct A;
-
-impl A {
- fn take_mutably(&mut self) {}
-}
-
-fn identity<T>(t: T) -> T {
- t
-}
-
-// Issue 46095
-// Built-in indexing should be used even when the index is not
-// trivially an integer
-// Overloaded indexing would cause wrapped to be borrowed mutably
-
-fn main() {
- let mut a1 = A;
- let mut a2 = A;
-
- let wrapped = [&mut a1, &mut a2];
-
- {
- wrapped[0 + 1 - 1].take_mutably();
- }
-
- {
- wrapped[identity(0)].take_mutably();
- }
-}
+++ /dev/null
-// Issue 46112: An extern crate pub re-exporting libcore was causing
-// paths rooted from `std` to be misrendered in the diagnostic output.
-
-// ignore-windows
-// aux-build:xcrate-issue-46112-rexport-core.rs
-
-extern crate xcrate_issue_46112_rexport_core;
-fn test(r: Result<Option<()>, &'static str>) { }
-fn main() { test(Ok(())); }
-//~^ mismatched types
+++ /dev/null
-error[E0308]: mismatched types
- --> $DIR/issue-46112.rs:9:21
- |
-LL | fn main() { test(Ok(())); }
- | ^^
- | |
- | expected enum `Option`, found `()`
- | help: try using a variant of the expected enum: `Some(())`
- |
- = note: expected enum `Option<()>`
- found unit type `()`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
+++ /dev/null
-// run-pass
-// Regression test for issue #47139:
-//
-// Coherence was encountering an (unnecessary) overflow trying to
-// decide if the two impls of dummy overlap.
-//
-// The overflow went something like:
-//
-// - `&'a ?T: Insertable` ?
-// - let ?T = Option<?U> ?
-// - `Option<?U>: Insertable` ?
-// - `Option<&'a ?U>: Insertable` ?
-// - `&'a ?U: Insertable` ?
-//
-// While somewhere in the middle, a projection would occur, which
-// broke cycle detection.
-//
-// It turned out that this cycle was being kicked off due to some
-// extended diagnostic attempts in coherence, so removing those
-// sidestepped the issue for now.
-
-#![allow(dead_code)]
-
-pub trait Insertable {
- type Values;
-
- fn values(self) -> Self::Values;
-}
-
-impl<T> Insertable for Option<T>
- where
- T: Insertable,
- T::Values: Default,
-{
- type Values = T::Values;
-
- fn values(self) -> Self::Values {
- self.map(Insertable::values).unwrap_or_default()
- }
-}
-
-impl<'a, T> Insertable for &'a Option<T>
- where
- Option<&'a T>: Insertable,
-{
- type Values = <Option<&'a T> as Insertable>::Values;
-
- fn values(self) -> Self::Values {
- self.as_ref().values()
- }
-}
-
-impl<'a, T> Insertable for &'a [T]
-{
- type Values = Self;
-
- fn values(self) -> Self::Values {
- self
- }
-}
-
-trait Unimplemented { }
-
-trait Dummy { }
-
-struct Foo<T> { t: T }
-
-impl<'a, U> Dummy for Foo<&'a U>
- where &'a U: Insertable
-{
-}
-
-impl<T> Dummy for T
- where T: Unimplemented
-{ }
-
-fn main() {
-}
+++ /dev/null
-#![allow(unused_variables)]; //~ ERROR expected item, found `;`
-//~^ ERROR `main` function
-fn foo() {}
+++ /dev/null
-error: expected item, found `;`
- --> $DIR/issue-49040.rs:1:28
- |
-LL | #![allow(unused_variables)];
- | ^ help: remove this semicolon
-
-error[E0601]: `main` function not found in crate `issue_49040`
- --> $DIR/issue-49040.rs:1:1
- |
-LL | #![allow(unused_variables)];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/issue-49040.rs`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0601`.
+++ /dev/null
-// check-pass
-
-fn fibs(n: u32) -> impl Iterator<Item=u128> {
- (0 .. n)
- .scan((0, 1), |st, _| {
- *st = (st.1, st.0 + st.1);
- Some(*st)
- })
- .map(&|(f, _)| f)
-}
-
-fn main() {
- println!("{:?}", fibs(10).collect::<Vec<_>>());
-}
+++ /dev/null
-// run-pass
-// Regression test for #49685: drop elaboration was not revealing the
-// value of `impl Trait` returns, leading to an ICE.
-
-fn main() {
- let _ = Some(())
- .into_iter()
- .flat_map(|_| Some(()).into_iter().flat_map(func));
-}
-
-fn func(_: ()) -> impl Iterator<Item = ()> {
- Some(()).into_iter().flat_map(|_| vec![])
-}
+++ /dev/null
-// run-pass
-enum Void {}
-fn foo(_: Result<(Void, u32), (Void, String)>) {}
-fn main() {
- let _: fn(_) = foo;
-}
+++ /dev/null
-trait B <A> {
- fn a() -> A {
- this.a //~ ERROR cannot find value `this` in this scope
- }
- fn b(x: i32) {
- this.b(x); //~ ERROR cannot find value `this` in this scope
- }
- fn c() {
- let _ = || this.a; //~ ERROR cannot find value `this` in this scope
- }
-}
-
-fn main() {}
+++ /dev/null
-error[E0425]: cannot find value `this` in this scope
- --> $DIR/issue-5099.rs:3:9
- |
-LL | this.a
- | ^^^^ not found in this scope
- |
-help: you might have meant to use `self` here instead
- |
-LL | self.a
- | ~~~~
-help: if you meant to use `self`, you are also missing a `self` receiver argument
- |
-LL | fn a(&self) -> A {
- | +++++
-
-error[E0425]: cannot find value `this` in this scope
- --> $DIR/issue-5099.rs:6:9
- |
-LL | this.b(x);
- | ^^^^ not found in this scope
- |
-help: you might have meant to use `self` here instead
- |
-LL | self.b(x);
- | ~~~~
-help: if you meant to use `self`, you are also missing a `self` receiver argument
- |
-LL | fn b(&self, x: i32) {
- | ++++++
-
-error[E0425]: cannot find value `this` in this scope
- --> $DIR/issue-5099.rs:9:20
- |
-LL | let _ = || this.a;
- | ^^^^ not found in this scope
- |
-help: you might have meant to use `self` here instead
- |
-LL | let _ = || self.a;
- | ~~~~
-help: if you meant to use `self`, you are also missing a `self` receiver argument
- |
-LL | fn c(&self) {
- | +++++
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0425`.
+++ /dev/null
-// compile-flags: --crate-type dylib --target thumbv7em-none-eabihf
-// needs-llvm-components: arm
-// build-pass
-// error-pattern: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf`
-
-#![feature(no_core)]
-
-#![no_std]
-#![no_core]
+++ /dev/null
-warning: dropping unsupported crate type `dylib` for target `thumbv7em-none-eabihf`
-
-warning: 1 warning emitted
-
+++ /dev/null
-// run-pass
-fn foo() -> impl Into<for<'a> fn(&'a ())> {
- (|_| {}) as for<'a> fn(&'a ())
-}
-
-fn main() {
- foo().into()(&());
-}
+++ /dev/null
-// run-pass
-#![allow(unreachable_code)]
-
-fn main() {
- let mut v = Vec::new();
-
- loop { v.push(break) }
-}
+++ /dev/null
-// run-pass
-#![feature(core_intrinsics)]
-
-#[repr(i8)]
-pub enum Enum {
- VariantA,
- VariantB,
-}
-
-fn make_b() -> Enum { Enum::VariantB }
-
-fn main() {
- assert_eq!(1, make_b() as i8);
- assert_eq!(1, make_b() as u8);
- assert_eq!(1, make_b() as i32);
- assert_eq!(1, make_b() as u32);
- assert_eq!(1, std::intrinsics::discriminant_value(&make_b()));
-}
+++ /dev/null
-// Regression test for Issue #53787: Fix ICE when creating a label in inline assembler with macros.
-
-// build-fail
-// ignore-emscripten
-
-#![feature(llvm_asm)]
-#![allow(deprecated)] // llvm_asm!
-
-macro_rules! fake_jump {
- ($id:expr) => {
- unsafe {
- llvm_asm!(
- "
- jmp $0
- lea eax, [ebx]
- xor eax, 0xDEADBEEF
- retn
- $0:
- "::"0"($id)::"volatile", "intel");
- }
- };
-}
-
-fn main() {
- fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly
- println!("Hello, world!");
-}
+++ /dev/null
-error[E0669]: invalid value for constraint in inline assembly
- --> $DIR/issue-53787-inline-assembler-macro.rs:25:16
- |
-LL | fake_jump!("FirstFunc");
- | ^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0669`.
+++ /dev/null
-// run-pass
-
-pub trait Stream {
- type Item;
- type Error;
-}
-
-pub trait ParseError<I> {
- type Output;
-}
-
-impl ParseError<char> for u32 {
- type Output = ();
-}
-
-impl Stream for () {
- type Item = char;
- type Error = u32;
-}
-
-pub struct Lex<'a, I>
- where I: Stream,
- I::Error: ParseError<char>,
- <<I as Stream>::Error as ParseError<char>>::Output: 'a
-{
- x: &'a <I::Error as ParseError<char>>::Output
-}
-
-pub struct Reserved<'a, I> where
- I: Stream<Item=char> + 'a,
- I::Error: ParseError<I::Item>,
- <<I as Stream>::Error as ParseError<char>>::Output: 'a
-
-{
- x: Lex<'a, I>
-}
-
-fn main() {
- let r: Reserved<()> = Reserved {
- x: Lex {
- x: &()
- }
- };
-
- let _v = r.x.x;
-}
+++ /dev/null
-struct T;
-
-impl for T {}
-//~^ ERROR missing trait in a trait impl
-
-fn main() {}
+++ /dev/null
-error: missing trait in a trait impl
- --> $DIR/issue-56031.rs:3:5
- |
-LL | impl for T {}
- | ^
- |
-help: add a trait here
- |
-LL | impl Trait for T {}
- | +++++
-help: for an inherent impl, drop this `for`
- |
-LL - impl for T {}
-LL + impl T {}
- |
-
-error: aborting due to previous error
-
+++ /dev/null
-// check-pass
-
-// Originally from #53925.
-// Tests that the `unreachable_pub` lint doesn't fire for `pub self::bar::Bar`.
-
-#![deny(unreachable_pub)]
-
-mod foo {
- mod bar {
- pub struct Bar;
- }
-
- pub use self::bar::Bar;
-}
-
-pub use foo::Bar;
-
-fn main() {}
+++ /dev/null
-// Regression test for #57597.
-//
-// Make sure that nested matchers work correctly rather than causing an infinite loop or crash.
-
-// edition:2018
-
-macro_rules! foo1 {
- ($($($i:ident)?)+) => {};
- //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo2 {
- ($($($i:ident)?)*) => {};
- //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo3 {
- ($($($i:ident)?)?) => {};
- //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo4 {
- ($($($($i:ident)?)?)?) => {};
- //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo5 {
- ($($($($i:ident)*)?)?) => {};
- //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo6 {
- ($($($($i:ident)?)*)?) => {};
- //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo7 {
- ($($($($i:ident)?)?)*) => {};
- //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo8 {
- ($($($($i:ident)*)*)?) => {};
- //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo9 {
- ($($($($i:ident)?)*)*) => {};
- //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo10 {
- ($($($($i:ident)?)*)+) => {};
- //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo11 {
- ($($($($i:ident)+)?)*) => {};
- //~^ ERROR repetition matches empty token tree
-}
-
-macro_rules! foo12 {
- ($($($($i:ident)+)*)?) => {};
- //~^ ERROR repetition matches empty token tree
-}
-
-fn main() {
- foo1!();
- foo2!();
- foo3!();
- foo4!();
- foo5!();
- foo6!();
- foo7!();
- foo8!();
- foo9!();
- foo10!();
- foo11!();
- foo12!();
-}
+++ /dev/null
-error: repetition matches empty token tree
- --> $DIR/issue-57597.rs:8:7
- |
-LL | ($($($i:ident)?)+) => {};
- | ^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
- --> $DIR/issue-57597.rs:13:7
- |
-LL | ($($($i:ident)?)*) => {};
- | ^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
- --> $DIR/issue-57597.rs:18:7
- |
-LL | ($($($i:ident)?)?) => {};
- | ^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
- --> $DIR/issue-57597.rs:23:7
- |
-LL | ($($($($i:ident)?)?)?) => {};
- | ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
- --> $DIR/issue-57597.rs:28:7
- |
-LL | ($($($($i:ident)*)?)?) => {};
- | ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
- --> $DIR/issue-57597.rs:33:7
- |
-LL | ($($($($i:ident)?)*)?) => {};
- | ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
- --> $DIR/issue-57597.rs:38:7
- |
-LL | ($($($($i:ident)?)?)*) => {};
- | ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
- --> $DIR/issue-57597.rs:43:7
- |
-LL | ($($($($i:ident)*)*)?) => {};
- | ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
- --> $DIR/issue-57597.rs:48:7
- |
-LL | ($($($($i:ident)?)*)*) => {};
- | ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
- --> $DIR/issue-57597.rs:53:7
- |
-LL | ($($($($i:ident)?)*)+) => {};
- | ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
- --> $DIR/issue-57597.rs:58:7
- |
-LL | ($($($($i:ident)+)?)*) => {};
- | ^^^^^^^^^^^^^^^^^^
-
-error: repetition matches empty token tree
- --> $DIR/issue-57597.rs:63:7
- |
-LL | ($($($($i:ident)+)*)?) => {};
- | ^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 12 previous errors
-
+++ /dev/null
-// run-pass
-fn main() {}
-#[derive(Clone)]
-pub struct Little;
-#[derive(Clone)]
-pub struct Big(
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
- Little,
-);
+++ /dev/null
-#![feature(trait_alias)]
-
-trait Svc<Req> { type Res; }
-
-trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
-//~^ ERROR associated type `Res` not found for `Self`
-//~| ERROR associated type `Res` not found for `Self`
-
-fn main() {}
+++ /dev/null
-error[E0220]: associated type `Res` not found for `Self`
- --> $DIR/issue-59029-1.rs:5:52
- |
-LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
- | ^^^ associated type `Res` not found
-
-error[E0220]: associated type `Res` not found for `Self`
- --> $DIR/issue-59029-1.rs:5:52
- |
-LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
- | ^^^ associated type `Res` not found
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0220`.
+++ /dev/null
-#![allow(dead_code)]
-#![feature(const_generics_defaults)]
-
-// This test checks that generic parameter re-ordering diagnostic suggestions mention that
-// consts come after types and lifetimes when the `const_generics_defaults` feature is enabled.
-// We cannot run rustfix on this test because of the above const generics warning.
-
-struct A;
-
-impl A {
- pub fn do_things<T, 'a, 'b: 'a>() {
- //~^ ERROR lifetime parameters must be declared prior to type parameters
- println!("panic");
- }
-}
-
-fn main() {}
+++ /dev/null
-error: lifetime parameters must be declared prior to type parameters
- --> $DIR/issue-59508-1.rs:11:25
- |
-LL | pub fn do_things<T, 'a, 'b: 'a>() {
- | ----^^--^^----- help: reorder the parameters: lifetimes, then consts and types: `<'a, 'b: 'a, T>`
-
-error: aborting due to previous error
-
+++ /dev/null
-// run-rustfix
-
-#![allow(dead_code)]
-
-// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
-
-struct A;
-
-impl A {
- pub fn do_things<'a, 'b: 'a, T>() {
- //~^ ERROR lifetime parameters must be declared prior to type parameters
- println!("panic");
- }
-}
-
-fn main() {}
+++ /dev/null
-// run-rustfix
-
-#![allow(dead_code)]
-
-// This test checks that generic parameter re-ordering diagnostic suggestions contain bounds.
-
-struct A;
-
-impl A {
- pub fn do_things<T, 'a, 'b: 'a>() {
- //~^ ERROR lifetime parameters must be declared prior to type parameters
- println!("panic");
- }
-}
-
-fn main() {}
+++ /dev/null
-error: lifetime parameters must be declared prior to type parameters
- --> $DIR/issue-59508.rs:10:25
- |
-LL | pub fn do_things<T, 'a, 'b: 'a>() {
- | ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>`
-
-error: aborting due to previous error
-
+++ /dev/null
-pub trait Trait<'a> {
- type Item;
-}
-
-impl<'a> Trait<'a> for () {
- type Item = ();
-}
-
-pub fn foo<T, F>(_: T, _: F)
-where
- T: for<'a> Trait<'a>,
- F: for<'a> FnMut(<T as Trait<'a>>::Item),
-{
-}
-
-fn main() {
- foo((), drop)
- //~^ ERROR type mismatch in function arguments
- //~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
-}
+++ /dev/null
-error[E0631]: type mismatch in function arguments
- --> $DIR/issue-60283.rs:17:13
- |
-LL | foo((), drop)
- | --- ^^^^
- | | |
- | | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
- | | found signature of `fn(()) -> _`
- | required by a bound introduced by this call
- |
-note: required by a bound in `foo`
- --> $DIR/issue-60283.rs:12:16
- |
-LL | pub fn foo<T, F>(_: T, _: F)
- | --- required by a bound in this
-...
-LL | F: for<'a> FnMut(<T as Trait<'a>>::Item),
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
-
-error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time
- --> $DIR/issue-60283.rs:17:13
- |
-LL | foo((), drop)
- | --- ^^^^ doesn't have a size known at compile-time
- | |
- | required by a bound introduced by this call
- |
- = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item`
-note: required by a bound in `std::mem::drop`
- --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
- |
-LL | pub fn drop<T>(_x: T) {}
- | ^ required by this bound in `std::mem::drop`
-help: consider further restricting the associated type
- |
-LL | fn main() where <() as Trait<'_>>::Item: Sized {
- | ++++++++++++++++++++++++++++++++++++
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0277, E0631.
-For more information about an error, try `rustc --explain E0277`.
+++ /dev/null
-// check-pass
-// compile-flags: -Z unpretty=hir
-
-#![feature(type_alias_impl_trait)]
-
-trait Animal {}
-
-fn main() {
- pub type ServeFut = impl Animal;
-}
+++ /dev/null
-// check-pass
-// compile-flags: -Z unpretty=hir
-
-#![feature(type_alias_impl_trait)]
-#[prelude_import]
-use ::std::prelude::rust_2015::*;
-#[macro_use]
-extern crate std;
-
-trait Animal { }
-
-fn main() {
- pub type ServeFut = /*impl Trait*/;
- }
+++ /dev/null
-// Issue 61711: A crate pub re-exporting `crate` was causing an
-// infinite loop.
-
-// edition:2018
-// aux-build:xcrate-issue-61711-b.rs
-// compile-flags:--extern xcrate_issue_61711_b
-
-// build-pass
-
-fn f<F: Fn(xcrate_issue_61711_b::Struct)>(_: F) { }
-fn main() { }
+++ /dev/null
-struct A<T>(T);
-
-impl A<&'static u8> {
- fn f() {
- let x = 0;
- Self(&x);
- //~^ ERROR `x` does not live long enough
- }
-}
-
-fn main() {}
+++ /dev/null
-error[E0597]: `x` does not live long enough
- --> $DIR/issue-61882-2.rs:6:14
- |
-LL | Self(&x);
- | ^^
- | |
- | borrowed value does not live long enough
- | this usage requires that `x` is borrowed for `'static`
-LL |
-LL | }
- | - `x` dropped here while still borrowed
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0597`.
+++ /dev/null
-struct A<T>(T);
-
-impl A<bool> {
- const B: A<u8> = Self(0);
- //~^ ERROR mismatched types
- //~| ERROR mismatched types
-}
-
-fn main() {}
+++ /dev/null
-error[E0308]: mismatched types
- --> $DIR/issue-61882.rs:4:27
- |
-LL | const B: A<u8> = Self(0);
- | ^ expected `bool`, found integer
-
-error[E0308]: mismatched types
- --> $DIR/issue-61882.rs:4:22
- |
-LL | const B: A<u8> = Self(0);
- | ^^^^^^^ expected `u8`, found `bool`
- |
- = note: expected struct `A<u8>`
- found struct `A<bool>`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
+++ /dev/null
-fn part(_: u16) -> u32 {
- 1
-}
-
-fn main() {
- for n in 100_000.. {
- //~^ ERROR: literal out of range for `u16`
- let _ = part(n);
- }
-}
+++ /dev/null
-error: literal out of range for `u16`
- --> $DIR/issue-63364.rs:6:14
- |
-LL | for n in 100_000.. {
- | ^^^^^^^
- |
- = note: `#[deny(overflowing_literals)]` on by default
- = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535`
-
-error: aborting due to previous error
-
+++ /dev/null
-macro_rules! e {
- ($inp:ident) => (
- $nonexistent
- //~^ ERROR expected expression, found `$`
- );
-}
-
-fn main() {
- e!(foo);
-}
+++ /dev/null
-error: expected expression, found `$`
- --> $DIR/issue-6596-1.rs:3:9
- |
-LL | $nonexistent
- | ^^^^^^^^^^^^ expected expression
-...
-LL | e!(foo);
- | ------- in this macro invocation
- |
- = note: this error originates in the macro `e` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
+++ /dev/null
-// Matching against NaN should result in a warning
-
-#![allow(unused)]
-#![deny(illegal_floating_point_literal_pattern)]
-
-const NAN: f64 = f64::NAN;
-
-fn main() {
- let x = NAN;
- match x {
- NAN => {}, //~ ERROR floating-point types cannot be used
- //~| WARN this was previously accepted by the compiler but is being phased out
- _ => {},
- };
-
- match [x, 1.0] {
- [NAN, _] => {}, //~ ERROR floating-point types cannot be used
- //~| WARN this was previously accepted by the compiler but is being phased out
- _ => {},
- };
-}
+++ /dev/null
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-6804.rs:11:9
- |
-LL | NAN => {},
- | ^^^
- |
-note: the lint level is defined here
- --> $DIR/issue-6804.rs:4:9
- |
-LL | #![deny(illegal_floating_point_literal_pattern)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: floating-point types cannot be used in patterns
- --> $DIR/issue-6804.rs:17:10
- |
-LL | [NAN, _] => {},
- | ^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
-
-error: aborting due to 2 previous errors
-
+++ /dev/null
-// check-pass
-
-pub trait ResultExt {
- type Ok;
- fn err_eprint_and_ignore(self) -> Option<Self::Ok>;
-}
-
-impl<O, E> ResultExt for std::result::Result<O, E>
-where
- E: std::error::Error,
-{
- type Ok = O;
- fn err_eprint_and_ignore(self) -> Option<O>
- where
- Self: ,
- {
- match self {
- Err(e) => {
- eprintln!("{}", e);
- None
- }
- Ok(o) => Some(o),
- }
- }
-}
-
-fn main() {}
+++ /dev/null
-struct Binder(i32, i32, i32);
-
-fn main() {
- let x = Binder(1, 2, 3);
- match x {
- Binder(_a, _x @ ..) => {}
- _ => {}
- }
-}
-//~^^^^ ERROR `_x @` is not allowed in a tuple struct
-//~| ERROR: `..` patterns are not allowed here
-//~| ERROR: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+++ /dev/null
-error: `_x @` is not allowed in a tuple struct
- --> $DIR/issue-72574-2.rs:6:20
- |
-LL | Binder(_a, _x @ ..) => {}
- | ^^^^^^^ this is only allowed in slice patterns
- |
- = help: remove this and bind each tuple field independently
-help: if you don't need to use the contents of _x, discard the tuple's remaining fields
- |
-LL | Binder(_a, ..) => {}
- | ~~
-
-error: `..` patterns are not allowed here
- --> $DIR/issue-72574-2.rs:6:25
- |
-LL | Binder(_a, _x @ ..) => {}
- | ^^
- |
- = note: only allowed in tuple, tuple struct, and slice patterns
-
-error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
- --> $DIR/issue-72574-2.rs:6:16
- |
-LL | struct Binder(i32, i32, i32);
- | --- --- --- tuple struct has 3 fields
-...
-LL | Binder(_a, _x @ ..) => {}
- | ^^ ^^^^^^^ expected 3 fields, found 2
- |
-help: use `_` to explicitly ignore each field
- |
-LL | Binder(_a, _x @ .., _) => {}
- | +++
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0023`.
+++ /dev/null
-// edition:2018
-
-fn main() {
- 'a: loop {
- async {
- loop {
- continue 'a
- //~^ ERROR use of unreachable label `'a`
- }
- };
- }
-}
+++ /dev/null
-error[E0767]: use of unreachable label `'a`
- --> $DIR/issue-73541-1.rs:7:26
- |
-LL | 'a: loop {
- | -- unreachable label defined here
-...
-LL | continue 'a
- | ^^ unreachable label `'a`
- |
- = note: labels are unreachable through functions, closures, async blocks and modules
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0767`.
+++ /dev/null
-fn main() {
- let _ = &&[0] as &[_];
- //~^ ERROR non-primitive cast: `&&[i32; 1]` as `&[_]`
- let _ = 7u32 as Option<_>;
- //~^ ERROR non-primitive cast: `u32` as `Option<_>`
-}
+++ /dev/null
-error[E0605]: non-primitive cast: `&&[i32; 1]` as `&[_]`
- --> $DIR/issue-73886.rs:2:13
- |
-LL | let _ = &&[0] as &[_];
- | ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
-
-error[E0605]: non-primitive cast: `u32` as `Option<_>`
- --> $DIR/issue-73886.rs:4:13
- |
-LL | let _ = 7u32 as Option<_>;
- | ^^^^^^^^^^^^^^^^^ help: consider using the `From` trait instead: `Option<_>::from(7u32)`
- |
- = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0605`.
+++ /dev/null
-// compile-flags: -O
-// run-pass
-
-struct Foo {
- x: i32,
-}
-
-pub fn main() {
- let mut foo = Foo { x: 42 };
- let x = &mut foo.x;
- *x = 13;
- let y = foo;
- assert_eq!(y.x, 13); // used to print 42 due to mir-opt bug
-}
+++ /dev/null
-// run-fail
-// error-pattern:quux
-// ignore-emscripten no processes
-
-use std::marker::PhantomData;
-
-fn test00_start(ch: Chan<isize>, message: isize) {
- send(ch, message);
-}
-
-type TaskId = isize;
-type PortId = isize;
-
-struct Chan<T> {
- task: TaskId,
- port: PortId,
- marker: PhantomData<*mut T>,
-}
-
-fn send<T: Send>(_ch: Chan<T>, _data: T) {
- panic!();
-}
-
-fn main() {
- panic!("quux");
-}
+++ /dev/null
-// run-pass
-#![allow(dead_code)]
-
-enum E {
- Foo{f: isize},
- Bar,
-}
-
-pub fn main() {
- let e = E::Foo{f: 0};
- match e {
- E::Foo{f: 1} => panic!(),
- E::Foo{..} => (),
- _ => panic!(),
- }
-}
+++ /dev/null
-// run-pass
-#![allow(dead_code)]
-
-enum E {
- Foo{f: isize, b: bool},
- Bar,
-}
-
-pub fn main() {
- let e = E::Foo{f: 0, b: false};
- match e {
- E::Foo{f: 1, b: true} => panic!(),
- E::Foo{b: false, f: 0} => (),
- _ => panic!(),
- }
-}
+++ /dev/null
-use std::fmt::Write;
-
-fn main() {
- println!(b"foo");
- //~^ ERROR format argument must be a string literal
- //~| HELP consider removing the leading `b`
- let mut s = String::new();
- write!(s, b"foo{}", "bar");
- //~^ ERROR format argument must be a string literal
- //~| HELP consider removing the leading `b`
-}
+++ /dev/null
-error: format argument must be a string literal
- --> $DIR/issue-86865.rs:4:14
- |
-LL | println!(b"foo");
- | -^^^^^
- | |
- | help: consider removing the leading `b`
-
-error: format argument must be a string literal
- --> $DIR/issue-86865.rs:8:15
- |
-LL | write!(s, b"foo{}", "bar");
- | -^^^^^^^
- | |
- | help: consider removing the leading `b`
-
-error: aborting due to 2 previous errors
-
+++ /dev/null
-// run-pass
-// ignore-emscripten no threads support
-
-use std::thread;
-use std::sync::mpsc::{channel, Receiver};
-
-fn periodical(n: isize) -> Receiver<bool> {
- let (chan, port) = channel();
- thread::spawn(move|| {
- loop {
- for _ in 1..n {
- match chan.send(false) {
- Ok(()) => {}
- Err(..) => break,
- }
- }
- match chan.send(true) {
- Ok(()) => {}
- Err(..) => break
- }
- }
- });
- return port;
-}
-
-fn integers() -> Receiver<isize> {
- let (chan, port) = channel();
- thread::spawn(move|| {
- let mut i = 1;
- loop {
- match chan.send(i) {
- Ok(()) => {}
- Err(..) => break,
- }
- i = i + 1;
- }
- });
- return port;
-}
-
-fn main() {
- let ints = integers();
- let threes = periodical(3);
- let fives = periodical(5);
- for _ in 1..100 {
- match (ints.recv().unwrap(), threes.recv().unwrap(), fives.recv().unwrap()) {
- (_, true, true) => println!("FizzBuzz"),
- (_, true, false) => println!("Fizz"),
- (_, false, true) => println!("Buzz"),
- (i, false, false) => println!("{}", i)
- }
- }
-}
+++ /dev/null
-// run-pass
-#![allow(unused_must_use)]
-#![allow(deprecated)]
-// ignore-emscripten no threads support
-
-use std::sync::mpsc::{TryRecvError, channel};
-use std::thread;
-
-pub fn main() {
- let (tx, rx) = channel();
- let t = thread::spawn(move||{
- thread::sleep_ms(10);
- tx.send(()).unwrap();
- });
- loop {
- match rx.try_recv() {
- Ok(()) => break,
- Err(TryRecvError::Empty) => {}
- Err(TryRecvError::Disconnected) => unreachable!()
- }
- }
- t.join();
-}
// check-pass
// edition:2021
-// compile-flags: -Zunstable-options
use std::array::IntoIter;
use std::ops::Deref;
+++ /dev/null
-// run-pass
-// shouldn't affect evaluation of $ex:
-macro_rules! bad_macro {
- ($ex:expr) => ({(|_x| { $ex }) (9) })
-}
-
-fn takes_x(_x : isize) {
- assert_eq!(bad_macro!(_x),8);
-}
-fn main() {
- takes_x(8);
-}
--- /dev/null
+// error-pattern: requires `copy` lang_item
+
+#![feature(lang_items, start, no_core)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized { }
+
+struct S;
+
+#[start]
+fn main(_: isize, _: *const *const u8) -> isize {
+ let _ = S;
+ 0
+}
--- /dev/null
+error: requires `copy` lang_item
+
+error: aborting due to previous error
+
--- /dev/null
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized {}
+
+#[lang="add"]
+trait Add<T> {}
+
+impl Add<i32> for i32 {}
+
+fn main() {
+ let x = 5 + 6;
+ //~^ ERROR cannot add `i32` to `{integer}`
+ let y = 5i32 + 6i32;
+ //~^ ERROR cannot add `i32` to `i32`
+}
--- /dev/null
+error[E0369]: cannot add `i32` to `{integer}`
+ --> $DIR/issue-31076.rs:13:15
+ |
+LL | let x = 5 + 6;
+ | - ^ - i32
+ | |
+ | {integer}
+
+error[E0369]: cannot add `i32` to `i32`
+ --> $DIR/issue-31076.rs:15:18
+ |
+LL | let y = 5i32 + 6i32;
+ | ---- ^ ---- i32
+ | |
+ | i32
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0369`.
--- /dev/null
+// build-fail
+
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang="copy"] pub trait Copy { }
+#[lang="sized"] pub trait Sized { }
+
+// error-pattern:requires `start` lang_item
+
+fn main() {}
--- /dev/null
+error: requires `start` lang_item
+
+error: aborting due to previous error
+
+++ /dev/null
-// aux-build:legacy-const-generics.rs
-
-extern crate legacy_const_generics;
-
-fn foo<const N: usize>() {
- let a = 1;
- legacy_const_generics::foo(0, a, 2);
- //~^ ERROR attempt to use a non-constant value in a constant
-
- legacy_const_generics::foo(0, N, 2);
-
- legacy_const_generics::foo(0, N + 1, 2);
- //~^ ERROR generic parameters may not be used in const operations
-}
-
-fn main() {}
+++ /dev/null
-error[E0435]: attempt to use a non-constant value in a constant
- --> $DIR/legacy-const-generics-bad.rs:7:35
- |
-LL | let a = 1;
- | ----- help: consider using `const` instead of `let`: `const a`
-LL | legacy_const_generics::foo(0, a, 2);
- | ^ non-constant value
-
-error: generic parameters may not be used in const operations
- --> $DIR/legacy-const-generics-bad.rs:12:35
- |
-LL | legacy_const_generics::foo(0, N + 1, 2);
- | ^ cannot perform const operation using `N`
- |
- = help: const parameters may only be used as standalone arguments, i.e. `N`
- = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0435`.
+++ /dev/null
-// aux-build:legacy-const-generics.rs
-// run-pass
-
-#![feature(rustc_attrs)]
-
-extern crate legacy_const_generics;
-
-#[rustc_legacy_const_generics(1)]
-pub fn bar<const Y: usize>(x: usize, z: usize) -> [usize; 3] {
- [x, Y, z]
-}
-
-fn main() {
- assert_eq!(legacy_const_generics::foo(0 + 0, 1 + 1, 2 + 2), [0, 2, 4]);
- assert_eq!(legacy_const_generics::foo::<{1 + 1}>(0 + 0, 2 + 2), [0, 2, 4]);
- // FIXME: Only works cross-crate
- //assert_eq!(bar(0, 1, 2), [0, 1, 2]);
-}
--- /dev/null
+fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
+//~^ ERROR missing lifetime specifier [E0106]
+
+fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
+//~^ ERROR missing lifetime specifier [E0106]
+
+fn parse_type_3() -> &str { unimplemented!() }
+//~^ ERROR missing lifetime specifier [E0106]
+
+fn main() {}
--- /dev/null
+error[E0106]: missing lifetime specifier
+ --> $DIR/issue-26638.rs:1:62
+ |
+LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() }
+ | ------------------------------------ ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+ |
+LL | fn parse_type<'a>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'a str { iter.next() }
+ | ++++ ++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/issue-26638.rs:4:40
+ |
+LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
+help: consider using the `'static` lifetime
+ |
+LL | fn parse_type_2(iter: fn(&u8)->&u8) -> &'static str { iter() }
+ | ~~~~~~~~
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/issue-26638.rs:7:22
+ |
+LL | fn parse_type_3() -> &str { unimplemented!() }
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime
+ |
+LL | fn parse_type_3() -> &'static str { unimplemented!() }
+ | ~~~~~~~~
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
--- /dev/null
+// run-rustfix
+
+pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+fn main() {}
--- /dev/null
+error: lifetime may not live long enough
+ --> $DIR/issue-90170-elision-mismatch.rs:3:40
+ |
+LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); }
+ | - - ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+ | | |
+ | | let's call the lifetime of this reference `'1`
+ | let's call the lifetime of this reference `'2`
+
+error: lifetime may not live long enough
+ --> $DIR/issue-90170-elision-mismatch.rs:5:44
+ |
+LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); }
+ | - - ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+ | | |
+ | | let's call the lifetime of this reference `'1`
+ | let's call the lifetime of this reference `'2`
+
+error: lifetime may not live long enough
+ --> $DIR/issue-90170-elision-mismatch.rs:7:63
+ |
+LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); }
+ | - - ^^^^^^^^^ argument requires that `'1` must outlive `'2`
+ | | |
+ | | let's call the lifetime of this reference `'1`
+ | let's call the lifetime of this reference `'2`
+
+error: aborting due to 3 previous errors
+
--- /dev/null
+// run-rustfix
+
+pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } //~ ERROR lifetime mismatch
+
+fn main() {}
--- /dev/null
+error[E0623]: lifetime mismatch
+ --> $DIR/issue-90170-elision-mismatch.rs:3:47
+ |
+LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); }
+ | --- --- ^ ...but data from `y` flows into `x` here
+ | |
+ | these two types are declared with different lifetimes...
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+ |
+LL | pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+ | ++++ ++ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/issue-90170-elision-mismatch.rs:5:51
+ |
+LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); }
+ | ------ --- ^ ...but data from `y` flows into `x` here
+ | |
+ | these two types are declared with different lifetimes...
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+ |
+LL | pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+ | ++++ ~~ ++
+
+error[E0623]: lifetime mismatch
+ --> $DIR/issue-90170-elision-mismatch.rs:7:70
+ |
+LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); }
+ | --- --- ^ ...but data from `y` flows into `x` here
+ | |
+ | these two types are declared with different lifetimes...
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+ |
+LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+ | ++ ++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0623`.
| --- --- these two types are declared with different lifetimes...
LL | *v = x;
| ^ ...but data from `x` flows here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+ |
+LL | fn foo<'a>(&mut (ref mut v, w): &mut (&'a u8, &u8), x: &'a u8) {
+ | ++++ ++ ++
error: aborting due to previous error
| --- --- these two types are declared with different lifetimes...
LL | z.push((x,y));
| ^ ...but data flows into `z` here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+ |
+LL | fn foo<'a>(z: &mut Vec<(&'a u8,&u8)>, (x, y): (&'a u8, &u8)) {
+ | ++++ ++ ++
error[E0623]: lifetime mismatch
--> $DIR/ex3-both-anon-regions-3.rs:2:15
| --- --- these two types are declared with different lifetimes...
LL | z.push((x,y));
| ^ ...but data flows into `z` here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+ |
+LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) {
+ | ++++ ++ ++
error: aborting due to 2 previous errors
| --- --- these two types are declared with different lifetimes...
LL | y.push(z);
| ^ ...but data from `z` flows into `y` here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+ |
+LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) {
+ | ++++ ++ ++
error: aborting due to previous error
| --- --- these two types are declared with different lifetimes...
LL | y.push(z);
| ^ ...but data from `z` flows into `y` here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+ |
+LL | fn foo<'a>(x:Box<dyn Fn(&'a u8, &'a u8)> , y: Vec<&u8>, z: &u8) {
+ | ++++ ++ ++
error: aborting due to previous error
| --- --- these two types are declared with different lifetimes...
LL | x.push(y);
| ^ ...but data from `y` flows into `x` here
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+ |
+LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) {
+ | ++++ ++ ++
error: aborting due to previous error
// --force-warn $LINT causes $LINT (which is deny-by-default) to warn
// despite $LINT being allowed on command line
-// compile-flags: -A const_err --force-warn const_err -Zunstable-options
+// compile-flags: -A const_err --force-warn const_err
// check-pass
const C: i32 = 1 / 0;
// --force-warn $LINT_GROUP causes $LINT (which is warn-by-default) to warn
// despite $LINT being allowed on command line
-// compile-flags: -A bare-trait-objects --force-warn rust-2018-idioms -Zunstable-options
+// compile-flags: -A bare-trait-objects --force-warn rust-2018-idioms
// check-pass
pub trait SomeTrait {}
// --force-warn $LINT causes $LINT (which is warn-by-default) to warn
// despite being allowed in one submodule (but not the other)
-// compile-flags: --force-warn dead_code -Zunstable-options
+// compile-flags: --force-warn dead_code
// check-pass
mod one {
// --force-warn warnings is an error
-// compile-flags: --force-warn warnings -Zunstable-options
+// compile-flags: --force-warn warnings
// error-pattern: `warnings` lint group is not supported
fn main() {}
error[E0602]: `warnings` lint group is not supported with ´--force-warn´
-error[E0602]: `warnings` lint group is not supported with ´--force-warn´
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0602`.
--- /dev/null
+// check-pass
+// pretty-expanded FIXME #23616
+
+#[deny(dead_code)]
+pub enum Foo {
+ Bar {
+ baz: isize
+ }
+}
+
+fn main() { }
--- /dev/null
+// check-pass
+
+// Originally from #53925.
+// Tests that the `unreachable_pub` lint doesn't fire for `pub self::bar::Bar`.
+
+#![deny(unreachable_pub)]
+
+mod foo {
+ mod bar {
+ pub struct Bar;
+ }
+
+ pub use self::bar::Bar;
+}
+
+pub use foo::Bar;
+
+fn main() {}
--- /dev/null
+fn part(_: u16) -> u32 {
+ 1
+}
+
+fn main() {
+ for n in 100_000.. {
+ //~^ ERROR: literal out of range for `u16`
+ let _ = part(n);
+ }
+}
--- /dev/null
+error: literal out of range for `u16`
+ --> $DIR/issue-63364.rs:6:14
+ |
+LL | for n in 100_000.. {
+ | ^^^^^^^
+ |
+ = note: `#[deny(overflowing_literals)]` on by default
+ = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535`
+
+error: aborting due to previous error
+
--- /dev/null
+// check-pass
+// Allowing the code lint should work without warning and
+// the text flow char in the comment should be ignored.
+
+#![allow(text_direction_codepoint_in_comment)]
+
+fn main() {
+ // U+2066 LEFT-TO-RIGHT ISOLATE follows:
+}
--- /dev/null
+// edition:2018
+#![deny(must_not_suspend)] //~ ERROR the `must_not_suspend`
+//~| ERROR the `must_not_suspend`
+//~| ERROR the `must_not_suspend`
+
+async fn other() {}
+
+pub async fn uhoh(m: std::sync::Mutex<()>) {
+ let _guard = m.lock().unwrap(); //~ ERROR `MutexGuard` held across
+ other().await;
+}
+
+fn main() {
+}
--- /dev/null
+error[E0658]: the `must_not_suspend` lint is unstable
+ --> $DIR/gated.rs:2:1
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
+ = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+
+error[E0658]: the `must_not_suspend` lint is unstable
+ --> $DIR/gated.rs:2:1
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
+ = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+
+error[E0658]: the `must_not_suspend` lint is unstable
+ --> $DIR/gated.rs:2:1
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
+ = help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+
+error: `MutexGuard` held across a suspend point, but should not be
+ --> $DIR/gated.rs:9:9
+ |
+LL | let _guard = m.lock().unwrap();
+ | ^^^^^^
+LL | other().await;
+ | ------------- the value is held across this suspend point
+ |
+note: the lint level is defined here
+ --> $DIR/gated.rs:2:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
+note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send`
+ --> $DIR/gated.rs:9:9
+ |
+LL | let _guard = m.lock().unwrap();
+ | ^^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+ --> $DIR/gated.rs:9:9
+ |
+LL | let _guard = m.lock().unwrap();
+ | ^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
--- /dev/null
+// edition:2018
+// run-pass
+
+use std::sync::Mutex;
+
+// Copied from the issue. Allow-by-default for now, so run-pass
+pub async fn foo() {
+ let foo = Mutex::new(1);
+ let lock = foo.lock().unwrap();
+
+ // Prevent mutex lock being held across `.await` point.
+ drop(lock);
+
+ bar().await;
+}
+
+async fn bar() {}
+
+fn main() {}
// edition:2018
+#![feature(must_not_suspend)]
#![deny(must_not_suspend)]
async fn other() {}
error: `MutexGuard` held across a suspend point, but should not be
- --> $DIR/mutex.rs:7:9
+ --> $DIR/mutex.rs:8:9
|
LL | let _guard = m.lock().unwrap();
| ^^^^^^
| ------------- the value is held across this suspend point
|
note: the lint level is defined here
- --> $DIR/mutex.rs:2:9
+ --> $DIR/mutex.rs:3:9
|
LL | #![deny(must_not_suspend)]
| ^^^^^^^^^^^^^^^^
note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send`
- --> $DIR/mutex.rs:7:9
+ --> $DIR/mutex.rs:8:9
|
LL | let _guard = m.lock().unwrap();
| ^^^^^^
help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
- --> $DIR/mutex.rs:7:9
+ --> $DIR/mutex.rs:8:9
|
LL | let _guard = m.lock().unwrap();
| ^^^^^^
// edition:2018
// run-pass
#![feature(must_not_suspend)]
+#![warn(must_not_suspend)]
#[must_not_suspend = "You gotta use Umm's, ya know?"]
struct Umm {
warning: `Umm` held across a suspend point, but should not be
- --> $DIR/warn.rs:20:9
+ --> $DIR/warn.rs:21:9
|
LL | let _guard = bar();
| ^^^^^^
LL | other().await;
| ------------- the value is held across this suspend point
|
- = note: `#[warn(must_not_suspend)]` on by default
+note: the lint level is defined here
+ --> $DIR/warn.rs:4:9
+ |
+LL | #![warn(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
note: You gotta use Umm's, ya know?
- --> $DIR/warn.rs:20:9
+ --> $DIR/warn.rs:21:9
|
LL | let _guard = bar();
| ^^^^^^
help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
- --> $DIR/warn.rs:20:9
+ --> $DIR/warn.rs:21:9
|
LL | let _guard = bar();
| ^^^^^^
--- /dev/null
+// edition:2018
+
+#![deny(unused_extern_crates)]
+#![feature(test, rustc_private, crate_visibility_modifier)]
+
+extern crate libc;
+//~^ ERROR unused extern crate
+//~| HELP remove
+extern crate libc as x;
+//~^ ERROR unused extern crate
+//~| HELP remove
+
+extern crate proc_macro;
+
+#[macro_use]
+extern crate test;
+
+pub extern crate test as y;
+
+pub extern crate alloc;
+
+pub(crate) extern crate alloc as a;
+
+crate extern crate alloc as b;
+
+mod foo {
+ pub(in crate::foo) extern crate alloc as c;
+
+ pub(super) extern crate alloc as d;
+
+ extern crate libc;
+ //~^ ERROR unused extern crate
+ //~| HELP remove
+
+ extern crate libc as x;
+ //~^ ERROR unused extern crate
+ //~| HELP remove
+
+ pub extern crate test;
+
+ pub extern crate test as y;
+
+ mod bar {
+ extern crate libc;
+ //~^ ERROR unused extern crate
+ //~| HELP remove
+
+ extern crate libc as x;
+ //~^ ERROR unused extern crate
+ //~| HELP remove
+
+ pub(in crate::foo::bar) extern crate alloc as e;
+
+ fn dummy() {
+ e::string::String::new();
+ }
+ }
+
+ fn dummy() {
+ c::string::String::new();
+ d::string::String::new();
+ }
+}
+
+
+fn main() {
+ a::string::String::new();
+ b::string::String::new();
+
+ proc_macro::TokenStream::new();
+}
--- /dev/null
+error: unused extern crate
+ --> $DIR/unnecessary-extern-crate.rs:6:1
+ |
+LL | extern crate libc;
+ | ^^^^^^^^^^^^^^^^^^ help: remove it
+ |
+note: the lint level is defined here
+ --> $DIR/unnecessary-extern-crate.rs:3:9
+ |
+LL | #![deny(unused_extern_crates)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unused extern crate
+ --> $DIR/unnecessary-extern-crate.rs:9:1
+ |
+LL | extern crate libc as x;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+ --> $DIR/unnecessary-extern-crate.rs:31:5
+ |
+LL | extern crate libc;
+ | ^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+ --> $DIR/unnecessary-extern-crate.rs:35:5
+ |
+LL | extern crate libc as x;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+ --> $DIR/unnecessary-extern-crate.rs:44:9
+ |
+LL | extern crate libc;
+ | ^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: unused extern crate
+ --> $DIR/unnecessary-extern-crate.rs:48:9
+ |
+LL | extern crate libc as x;
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
+
+error: aborting due to 6 previous errors
+
-// compile-flags: --error-format json -Zunstable-options
+// compile-flags: --error-format json
// run-rustfix
// The output for humans should just highlight the whole span without showing
-// compile-flags: --error-format json -Zunstable-options
+// compile-flags: --error-format json
// run-rustfix
// The output for humans should just highlight the whole span without showing
-{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":597,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));
+{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":577,"byte_end":578,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));
--> $DIR/unused_parens_json_suggestion.rs:16:14
|
LL | let _a = (1 / (2 + 3));
-// compile-flags: --error-format json -Zunstable-options
+// compile-flags: --error-format json
// run-rustfix
// The output for humans should just highlight the whole span without showing
-// compile-flags: --error-format json -Zunstable-options
+// compile-flags: --error-format json
// run-rustfix
// The output for humans should just highlight the whole span without showing
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":501,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":481,"byte_end":482,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (_b) {
--> $DIR/unused_parens_remove_json_suggestion.rs:17:8
|
LL | if (_b) {
|
"}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":632,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":612,"byte_end":613,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":" if(c) {
--> $DIR/unused_parens_remove_json_suggestion.rs:28:7
|
LL | if(c) {
|
"}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":712,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":692,"byte_end":693,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":" if (c){
--> $DIR/unused_parens_remove_json_suggestion.rs:32:8
|
LL | if (c){
|
"}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":774,"byte_end":775,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":788,"byte_end":789,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":" while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
--> $DIR/unused_parens_remove_json_suggestion.rs:36:11
|
LL | while (false && true){
|
"}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":822,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":802,"byte_end":803,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":" if (c) {
--> $DIR/unused_parens_remove_json_suggestion.rs:37:12
|
LL | if (c) {
|
"}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":919,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) {
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":899,"byte_end":900,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":" while(true && false) {
--> $DIR/unused_parens_remove_json_suggestion.rs:43:10
|
LL | while(true && false) {
|
"}
-{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":988,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":968,"byte_end":969,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":" for _ in (0 .. 3){
--> $DIR/unused_parens_remove_json_suggestion.rs:44:18
|
LL | for _ in (0 .. 3){
|
"}
-{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1089,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1069,"byte_end":1070,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":" for _ in (0 .. 3) {
--> $DIR/unused_parens_remove_json_suggestion.rs:49:14
|
LL | for _ in (0 .. 3) {
|
"}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1148,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) {
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1128,"byte_end":1129,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":" while (true && false) {
--> $DIR/unused_parens_remove_json_suggestion.rs:50:15
|
LL | while (true && false) {
--- /dev/null
+// run-pass
+
+#![allow(dead_code)]
+// compile-flags:-D improper-ctypes
+
+// pretty-expanded FIXME #23616
+#![allow(improper_ctypes)]
+
+mod libc {
+ extern "C" {
+ pub fn malloc(size: isize) -> *const u8;
+ }
+}
+
+pub fn main() {}
--- /dev/null
+#![feature(llvm_asm)]
+#![allow(deprecated)] // llvm_asm!
+// compile-flags: -Ccodegen-units=1
+// build-fail
+// only-x86_64
+
+fn main() {
+ unsafe {
+ llvm_asm!("int $3"); //~ ERROR too few operands for instruction
+ //~| ERROR invalid operand in inline asm
+ }
+}
--- /dev/null
+error: invalid operand in inline asm: 'int $3'
+ --> $DIR/issue-23458.rs:9:9
+ |
+LL | llvm_asm!("int $3");
+ | ^
+
+error: too few operands for instruction
+ --> $DIR/issue-23458.rs:9:9
+ |
+LL | llvm_asm!("int $3");
+ | ^
+ |
+note: instantiated into assembly here
+ --> <inline asm>:1:2
+ |
+LL | int
+ | ^
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+// check-pass
+// ignore-emscripten
+
+#![feature(llvm_asm)]
+#![allow(deprecated)] // llvm_asm!
+
+macro_rules! interrupt_handler {
+ () => {
+ unsafe fn _interrupt_handler() {
+ llvm_asm!("pop eax" :::: "intel");
+ }
+ }
+}
+interrupt_handler!{}
+
+fn main() {}
--- /dev/null
+// Regression test for Issue #53787: Fix ICE when creating a label in inline assembler with macros.
+
+// build-fail
+// ignore-emscripten
+
+#![feature(llvm_asm)]
+#![allow(deprecated)] // llvm_asm!
+
+macro_rules! fake_jump {
+ ($id:expr) => {
+ unsafe {
+ llvm_asm!(
+ "
+ jmp $0
+ lea eax, [ebx]
+ xor eax, 0xDEADBEEF
+ retn
+ $0:
+ "::"0"($id)::"volatile", "intel");
+ }
+ };
+}
+
+fn main() {
+ fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly
+ println!("Hello, world!");
+}
--- /dev/null
+error[E0669]: invalid value for constraint in inline assembly
+ --> $DIR/issue-53787-inline-assembler-macro.rs:25:16
+ |
+LL | fake_jump!("FirstFunc");
+ | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0669`.
+++ /dev/null
-// run-pass
-// pretty-expanded FIXME #23616
-
-#![allow(unused_variables)]
-
-pub fn main() {
- let mut i: isize = 0;
- while i < 1000000 {
- i += 1;
- let x = 3;
- }
-}
+++ /dev/null
-// compile-flags: -C lto -C embed-bitcode=no
-
-fn main() {}
+++ /dev/null
-error: options `-C embed-bitcode=no` and `-C lto` are incompatible
-
+++ /dev/null
-// build-fail
-// aux-build:lto-duplicate-symbols1.rs
-// aux-build:lto-duplicate-symbols2.rs
-// error-pattern:Linking globals named 'foo': symbol multiply defined!
-// compile-flags: -C lto
-// no-prefer-dynamic
-
-extern crate lto_duplicate_symbols1;
-extern crate lto_duplicate_symbols2;
-
-fn main() {}
+++ /dev/null
-warning: Linking globals named 'foo': symbol multiply defined!
-
-error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.693a75b4-cgu.0.rcgu.o":
-
-error: aborting due to previous error; 1 warning emitted
-
+++ /dev/null
-// run-pass
-// compile-flags: -C lto -C codegen-units=8
-// no-prefer-dynamic
-
-fn main() {
-}
+++ /dev/null
-// compile-flags: -Clinker-plugin-lto -Copt-level=s
-// build-pass
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn foo() {}
+++ /dev/null
-// compile-flags: -Clinker-plugin-lto -Copt-level=z
-// build-pass
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn foo() {}
+++ /dev/null
-// compile-flags: -C lto
-// aux-build:lto-rustc-loads-linker-plugin.rs
-// run-pass
-// no-prefer-dynamic
-
-// This test ensures that if a dependency was compiled with
-// `-Clinker-plugin-lto` then we can compile with `-Clto` and still link against
-// that upstream rlib. This should work because LTO implies we're not actually
-// linking against upstream rlibs since we're generating the object code
-// locally. This test will fail if rustc can't find bytecode in rlibs compiled
-// with `-Clinker-plugin-lto`.
-
-extern crate lto_rustc_loads_linker_plugin;
-
-fn main() {
- lto_rustc_loads_linker_plugin::foo();
-}
+++ /dev/null
-// run-pass
-// compile-flags: -C lto
-// no-prefer-dynamic
-// ignore-emscripten no threads support
-// revisions: mir thir
-// [thir]compile-flags: -Zthir-unsafeck
-
-use std::thread;
-
-static mut HIT: usize = 0;
-
-thread_local!(static A: Foo = Foo);
-
-struct Foo;
-
-impl Drop for Foo {
- fn drop(&mut self) {
- unsafe {
- HIT += 1;
- }
- }
-}
-
-fn main() {
- unsafe {
- assert_eq!(HIT, 0);
- thread::spawn(|| {
- assert_eq!(HIT, 0);
- A.with(|_| ());
- assert_eq!(HIT, 0);
- }).join().unwrap();
- assert_eq!(HIT, 1);
- }
-}
+++ /dev/null
-// compile-flags: -C lto=thin
-// aux-build:lto-rustc-loads-linker-plugin.rs
-// run-pass
-// no-prefer-dynamic
-
-// Same as the adjacent `lto-thin-rustc-loads-linker-plugin.rs` test, only with
-// ThinLTO.
-
-extern crate lto_rustc_loads_linker_plugin;
-
-fn main() {
- lto_rustc_loads_linker_plugin::foo();
-}
--- /dev/null
+// run-pass
+
+// compile-flags: -Clto=thin
+// no-prefer-dynamic
+
+fn main() {
+ println!("hello!");
+}
--- /dev/null
+// compile-flags: -Z thinlto -C codegen-units=8
+
+#[inline]
+pub fn foo(b: u8) {
+ b.to_string();
+}
--- /dev/null
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern "C" fn foo() {}
--- /dev/null
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern "C" fn foo() {}
--- /dev/null
+// compile-flags: -Clinker-plugin-lto
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn foo() {}
--- /dev/null
+// no-prefer-dynamic
+// compile-flags: -Z thinlto -C codegen-units=8 -C prefer-dynamic
+
+#![crate_type = "rlib"]
+#![crate_type = "dylib"]
+
+pub static A: u32 = 43;
+
+pub mod a {
+ pub static A: u32 = 43;
+}
--- /dev/null
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn bar() -> u32 {
+ 3
+}
--- /dev/null
+// run-pass
+
+// aux-build:dylib.rs
+
+extern crate dylib;
+
+fn main() {
+ dylib::foo(1);
+}
--- /dev/null
+// compile-flags: -C lto -C embed-bitcode=no
+
+fn main() {}
--- /dev/null
+error: options `-C embed-bitcode=no` and `-C lto` are incompatible
+
--- /dev/null
+// build-fail
+// aux-build:lto-duplicate-symbols1.rs
+// aux-build:lto-duplicate-symbols2.rs
+// error-pattern:Linking globals named 'foo': symbol multiply defined!
+// compile-flags: -C lto
+// no-prefer-dynamic
+
+extern crate lto_duplicate_symbols1;
+extern crate lto_duplicate_symbols2;
+
+fn main() {}
--- /dev/null
+warning: Linking globals named 'foo': symbol multiply defined!
+
+error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.693a75b4-cgu.0.rcgu.o":
+
+error: aborting due to previous error; 1 warning emitted
+
--- /dev/null
+// run-pass
+// compile-flags: -C lto -C codegen-units=8
+// no-prefer-dynamic
+
+fn main() {
+}
--- /dev/null
+// compile-flags: -Clinker-plugin-lto -Copt-level=s
+// build-pass
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn foo() {}
--- /dev/null
+// compile-flags: -Clinker-plugin-lto -Copt-level=z
+// build-pass
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn foo() {}
--- /dev/null
+// compile-flags: -C lto
+// aux-build:lto-rustc-loads-linker-plugin.rs
+// run-pass
+// no-prefer-dynamic
+
+// This test ensures that if a dependency was compiled with
+// `-Clinker-plugin-lto` then we can compile with `-Clto` and still link against
+// that upstream rlib. This should work because LTO implies we're not actually
+// linking against upstream rlibs since we're generating the object code
+// locally. This test will fail if rustc can't find bytecode in rlibs compiled
+// with `-Clinker-plugin-lto`.
+
+extern crate lto_rustc_loads_linker_plugin;
+
+fn main() {
+ lto_rustc_loads_linker_plugin::foo();
+}
--- /dev/null
+// run-pass
+// compile-flags: -C lto
+// no-prefer-dynamic
+// ignore-emscripten no threads support
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
+
+use std::thread;
+
+static mut HIT: usize = 0;
+
+thread_local!(static A: Foo = Foo);
+
+struct Foo;
+
+impl Drop for Foo {
+ fn drop(&mut self) {
+ unsafe {
+ HIT += 1;
+ }
+ }
+}
+
+fn main() {
+ unsafe {
+ assert_eq!(HIT, 0);
+ thread::spawn(|| {
+ assert_eq!(HIT, 0);
+ A.with(|_| ());
+ assert_eq!(HIT, 0);
+ }).join().unwrap();
+ assert_eq!(HIT, 1);
+ }
+}
--- /dev/null
+// compile-flags: -C lto=thin
+// aux-build:lto-rustc-loads-linker-plugin.rs
+// run-pass
+// no-prefer-dynamic
+
+// Same as the adjacent `lto-thin-rustc-loads-linker-plugin.rs` test, only with
+// ThinLTO.
+
+extern crate lto_rustc_loads_linker_plugin;
+
+fn main() {
+ lto_rustc_loads_linker_plugin::foo();
+}
--- /dev/null
+// run-pass
+
+// aux-build:msvc-imp-present.rs
+// compile-flags: -Z thinlto -C codegen-units=8
+// no-prefer-dynamic
+
+// On MSVC we have a "hack" where we emit symbols that look like `_imp_$name`
+// for all exported statics. This is done because we apply `dllimport` to all
+// imported constants and this allows everything to actually link correctly.
+//
+// The ThinLTO passes aggressively remove symbols if they can, and this test
+// asserts that the ThinLTO passes don't remove these compiler-generated
+// `_imp_*` symbols. The external library that we link in here is compiled with
+// ThinLTO and multiple codegen units and has a few exported constants. Note
+// that we also namely compile the library as both a dylib and an rlib, but we
+// link the rlib to ensure that we assert those generated symbols exist.
+
+extern crate msvc_imp_present as bar;
+
+fn main() {
+ println!("{}", bar::A);
+}
--- /dev/null
+// run-pass
+// compile-flags: -Z thinlto -C codegen-units=2
+
+#[global_allocator]
+static A: std::alloc::System = std::alloc::System;
+
+fn main() {}
--- /dev/null
+// run-pass
+
+// compile-flags: -Z thinlto -C codegen-units=8 -O
+// ignore-emscripten can't inspect instructions on emscripten
+
+// We want to assert here that ThinLTO will inline across codegen units. There's
+// not really a great way to do that in general so we sort of hack around it by
+// praying two functions go into separate codegen units and then assuming that
+// if inlining *doesn't* happen the first byte of the functions will differ.
+
+pub fn foo() -> u32 {
+ bar::bar()
+}
+
+mod bar {
+ pub fn bar() -> u32 {
+ 3
+ }
+}
+
+fn main() {
+ println!("{} {}", foo(), bar::bar());
+
+ unsafe {
+ let foo = foo as usize as *const u8;
+ let bar = bar::bar as usize as *const u8;
+
+ assert_eq!(*foo, *bar);
+ }
+}
--- /dev/null
+// run-pass
+
+// compile-flags: -C codegen-units=8 -O -C lto=thin
+// aux-build:thin-lto-inlines-aux.rs
+// no-prefer-dynamic
+// ignore-emscripten can't inspect instructions on emscripten
+
+// We want to assert here that ThinLTO will inline across codegen units. There's
+// not really a great way to do that in general so we sort of hack around it by
+// praying two functions go into separate codegen units and then assuming that
+// if inlining *doesn't* happen the first byte of the functions will differ.
+
+extern crate thin_lto_inlines_aux as bar;
+
+pub fn foo() -> u32 {
+ bar::bar()
+}
+
+fn main() {
+ println!("{} {}", foo(), bar::bar());
+
+ unsafe {
+ let foo = foo as usize as *const u8;
+ let bar = bar::bar as usize as *const u8;
+
+ assert_eq!(*foo, *bar);
+ }
+}
--- /dev/null
+// run-pass
+
+// compile-flags: -C codegen-units=8 -Z thinlto
+// ignore-windows
+
+#![feature(linkage)]
+
+pub mod foo {
+ #[linkage = "weak"]
+ #[no_mangle]
+ pub extern "C" fn FOO() -> i32 {
+ 0
+ }
+}
+
+mod bar {
+ extern "C" {
+ fn FOO() -> i32;
+ }
+
+ pub fn bar() -> i32 {
+ unsafe { FOO() }
+ }
+}
+
+fn main() {
+ bar::bar();
+}
+++ /dev/null
-// run-pass
-// Test for a specific corner case: when we compute the LUB of two fn
-// types and their parameters have unbound variables. In that case, we
-// wind up relating those two variables. This was causing an ICE in an
-// in-progress PR.
-
-fn main() {
- let a_f: fn(_) = |_| ();
- let b_f: fn(_) = |_| ();
- let c_f = match 22 {
- 0 => a_f,
- _ => b_f,
- };
- c_f(4);
-}
--- /dev/null
+#![crate_type = "lib"]
+
+#[macro_export]
+macro_rules! mywrite {
+ ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
+}
--- /dev/null
+macro_rules! prob1 {
+ (0) => {
+ 0
+ };
+ ($n:expr) => {
+ if ($n % 3 == 0) || ($n % 5 == 0) {
+ $n + prob1!($n - 1); //~ ERROR recursion limit reached while expanding `prob1!`
+ } else {
+ prob1!($n - 1);
+ }
+ };
+}
+
+fn main() {
+ println!("Problem 1: {}", prob1!(1000));
+}
--- /dev/null
+error: recursion limit reached while expanding `prob1!`
+ --> $DIR/issue-16098.rs:7:18
+ |
+LL | $n + prob1!($n - 1);
+ | ^^^^^^^^^^^^^^
+...
+LL | println!("Problem 1: {}", prob1!(1000));
+ | ------------ in this macro invocation
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_16098`)
+ = note: this error originates in the macro `prob1` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
--- /dev/null
+// aux-build:issue-19163.rs
+
+#[macro_use] extern crate issue_19163;
+
+use std::io::Write;
+
+fn main() {
+ let mut v = vec![];
+ mywrite!(&v, "Hello world");
+ //~^ ERROR cannot borrow data in a `&` reference as mutable
+}
--- /dev/null
+error[E0596]: cannot borrow data in a `&` reference as mutable
+ --> $DIR/issue-19163.rs:9:5
+ |
+LL | mywrite!(&v, "Hello world");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
+ |
+ = note: this error originates in the macro `mywrite` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
--- /dev/null
+#![allow(unused_macros)]
+
+macro_rules! test { ($wrong:t_ty ..) => () }
+ //~^ ERROR: invalid fragment specifier `t_ty`
+
+fn main() {}
--- /dev/null
+error: invalid fragment specifier `t_ty`
+ --> $DIR/issue-21356.rs:3:22
+ |
+LL | macro_rules! test { ($wrong:t_ty ..) => () }
+ | ^^^^^^^^^^^
+ |
+ = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+macro_rules! items {
+ () => {
+ type A = ();
+ fn a() {}
+ }
+}
+
+trait Foo {
+ type A;
+ fn a();
+}
+
+impl Foo for () {
+ items!();
+}
+
+fn main() {
+
+}
--- /dev/null
+macro_rules! foo {
+ ($d:expr) => {{
+ fn bar(d: u8) { }
+ bar(&mut $d);
+ //~^ ERROR mismatched types
+ //~| expected `u8`, found `&mut u8`
+ }}
+}
+
+fn main() {
+ foo!(0u8);
+ //~^ in this expansion of foo!
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-29084.rs:4:13
+ |
+LL | bar(&mut $d);
+ | ^^^^^^^ expected `u8`, found `&mut u8`
+...
+LL | foo!(0u8);
+ | --------- in this macro invocation
+ |
+ = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// check-pass
+
+macro_rules! null { ($i:tt) => {} }
+macro_rules! apply_null {
+ ($i:item) => { null! { $i } }
+}
+
+fn main() {
+ apply_null!(#[cfg(all())] fn f() {});
+}
--- /dev/null
+// run-pass
+macro_rules! m { (<$t:ty>) => { stringify!($t) } }
+fn main() {
+ println!("{}", m!(<Vec<i32>>));
+}
--- /dev/null
+#![allow(unused_macros)]
+
+macro_rules! assign {
+ (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected one of: `*`, `+`, or `?`
+ $($a)* = $($b)*
+ }
+}
+
+fn main() {}
--- /dev/null
+error: expected one of: `*`, `+`, or `?`
+ --> $DIR/issue-39388.rs:4:22
+ |
+LL | (($($a:tt)*) = ($($b:tt))*) => {
+ | ^^^^^^^
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+#![allow(unused_macros)]
+macro_rules! m {
+ ($e:expr) => {
+ macro_rules! n { () => { $e } }
+ }
+}
+
+fn main() {
+ m!(foo!());
+}
--- /dev/null
+// Regression test for #57597.
+//
+// Make sure that nested matchers work correctly rather than causing an infinite loop or crash.
+
+// edition:2018
+
+macro_rules! foo1 {
+ ($($($i:ident)?)+) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo2 {
+ ($($($i:ident)?)*) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo3 {
+ ($($($i:ident)?)?) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo4 {
+ ($($($($i:ident)?)?)?) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo5 {
+ ($($($($i:ident)*)?)?) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo6 {
+ ($($($($i:ident)?)*)?) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo7 {
+ ($($($($i:ident)?)?)*) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo8 {
+ ($($($($i:ident)*)*)?) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo9 {
+ ($($($($i:ident)?)*)*) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo10 {
+ ($($($($i:ident)?)*)+) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo11 {
+ ($($($($i:ident)+)?)*) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo12 {
+ ($($($($i:ident)+)*)?) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+fn main() {
+ foo1!();
+ foo2!();
+ foo3!();
+ foo4!();
+ foo5!();
+ foo6!();
+ foo7!();
+ foo8!();
+ foo9!();
+ foo10!();
+ foo11!();
+ foo12!();
+}
--- /dev/null
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:8:7
+ |
+LL | ($($($i:ident)?)+) => {};
+ | ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:13:7
+ |
+LL | ($($($i:ident)?)*) => {};
+ | ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:18:7
+ |
+LL | ($($($i:ident)?)?) => {};
+ | ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:23:7
+ |
+LL | ($($($($i:ident)?)?)?) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:28:7
+ |
+LL | ($($($($i:ident)*)?)?) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:33:7
+ |
+LL | ($($($($i:ident)?)*)?) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:38:7
+ |
+LL | ($($($($i:ident)?)?)*) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:43:7
+ |
+LL | ($($($($i:ident)*)*)?) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:48:7
+ |
+LL | ($($($($i:ident)?)*)*) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:53:7
+ |
+LL | ($($($($i:ident)?)*)+) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:58:7
+ |
+LL | ($($($($i:ident)+)?)*) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:63:7
+ |
+LL | ($($($($i:ident)+)*)?) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
+
--- /dev/null
+macro_rules! e {
+ ($inp:ident) => (
+ $nonexistent
+ //~^ ERROR expected expression, found `$`
+ );
+}
+
+fn main() {
+ e!(foo);
+}
--- /dev/null
+error: expected expression, found `$`
+ --> $DIR/issue-6596-1.rs:3:9
+ |
+LL | $nonexistent
+ | ^^^^^^^^^^^^ expected expression
+...
+LL | e!(foo);
+ | ------- in this macro invocation
+ |
+ = note: this error originates in the macro `e` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
--- /dev/null
+use std::fmt::Write;
+
+fn main() {
+ println!(b"foo");
+ //~^ ERROR format argument must be a string literal
+ //~| HELP consider removing the leading `b`
+ let mut s = String::new();
+ write!(s, b"foo{}", "bar");
+ //~^ ERROR format argument must be a string literal
+ //~| HELP consider removing the leading `b`
+}
--- /dev/null
+error: format argument must be a string literal
+ --> $DIR/issue-86865.rs:4:14
+ |
+LL | println!(b"foo");
+ | -^^^^^
+ | |
+ | help: consider removing the leading `b`
+
+error: format argument must be a string literal
+ --> $DIR/issue-86865.rs:8:15
+ |
+LL | write!(s, b"foo{}", "bar");
+ | -^^^^^^^
+ | |
+ | help: consider removing the leading `b`
+
+error: aborting due to 2 previous errors
+
--- /dev/null
+#![feature(trace_macros)]
+
+fn main() {
+ trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false`
+ trace_macros!(1); //~ ERROR trace_macros! accepts only `true` or `false`
+ trace_macros!(ident); //~ ERROR trace_macros! accepts only `true` or `false`
+ trace_macros!(for); //~ ERROR trace_macros! accepts only `true` or `false`
+ trace_macros!(true,); //~ ERROR trace_macros! accepts only `true` or `false`
+ trace_macros!(false 1); //~ ERROR trace_macros! accepts only `true` or `false`
+
+
+ // should be fine:
+ macro_rules! expando {
+ ($x: ident) => { trace_macros!($x) }
+ }
+
+ expando!(true);
+}
--- /dev/null
+error: trace_macros! accepts only `true` or `false`
+ --> $DIR/trace_macros-format.rs:4:5
+ |
+LL | trace_macros!();
+ | ^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+ --> $DIR/trace_macros-format.rs:5:5
+ |
+LL | trace_macros!(1);
+ | ^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+ --> $DIR/trace_macros-format.rs:6:5
+ |
+LL | trace_macros!(ident);
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+ --> $DIR/trace_macros-format.rs:7:5
+ |
+LL | trace_macros!(for);
+ | ^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+ --> $DIR/trace_macros-format.rs:8:5
+ |
+LL | trace_macros!(true,);
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: trace_macros! accepts only `true` or `false`
+ --> $DIR/trace_macros-format.rs:9:5
+ |
+LL | trace_macros!(false 1);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
--- /dev/null
+// run-pass
+
+#![feature(marker_trait_attr)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+#[marker]
+trait MyMarker {}
+
+impl<T> MyMarker for T {}
+impl<T> MyMarker for Vec<T> {}
+
+fn foo<T: MyMarker>(t: T) -> T {
+ t
+}
+
+fn main() {
+ assert_eq!(1, foo(1));
+ assert_eq!(2.0, foo(2.0));
+ assert_eq!(vec![1], foo(vec![1]));
+}
--- /dev/null
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/overlap-doesnt-conflict-with-specialization.rs:4:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+
+warning: 1 warning emitted
+
--- /dev/null
+// run-pass
+// Tests for RFC 1268: we allow overlapping impls of marker traits,
+// that is, traits with #[marker]. In this case, a type `T` is
+// `MyMarker` if it is either `Debug` or `Display`.
+
+#![feature(marker_trait_attr)]
+
+use std::fmt::{Debug, Display};
+
+#[marker] trait MyMarker {}
+
+impl<T: Debug> MyMarker for T {}
+impl<T: Display> MyMarker for T {}
+
+fn foo<T: MyMarker>(t: T) -> T {
+ t
+}
+
+fn main() {
+ // Debug && Display:
+ assert_eq!(1, foo(1));
+ assert_eq!(2.0, foo(2.0));
+
+ // Debug && !Display:
+ assert_eq!(vec![1], foo(vec![1]));
+}
--- /dev/null
+// run-pass
+
+const TEST_STR: &'static str = "abcd";
+
+fn main() {
+ let s = "abcd";
+ match s {
+ TEST_STR => (),
+ _ => unreachable!()
+ }
+}
--- /dev/null
+// run-pass
+// Regression test for #18060: match arms were matching in the wrong order.
+
+fn main() {
+ assert_eq!(2, match (1, 3) { (0, 2..=5) => 1, (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
+ assert_eq!(2, match (1, 3) { (1, 3) => 2, (_, 2..=5) => 3, (_, _) => 4 });
+ assert_eq!(2, match (1, 7) { (0, 2..=5) => 1, (1, 7) => 2, (_, 2..=5) => 3, (_, _) => 4 });
+}
--- /dev/null
+// run-pass
+#![allow(overlapping_range_endpoints)]
+
+fn main() {
+ let x = 'a';
+
+ let y = match x {
+ 'a'..='b' if false => "one",
+ 'a' => "two",
+ 'a'..='b' => "three",
+ _ => panic!("what?"),
+ };
+
+ assert_eq!(y, "two");
+}
--- /dev/null
+// run-pass
+
+// This test is bogus (i.e., should be check-fail) during the period
+// where #54986 is implemented and #54987 is *not* implemented. For
+// now: just ignore it
+//
+// ignore-test
+
+// This test is checking that the write to `c.0` (which has been moved out of)
+// won't overwrite the state in `c2`.
+//
+// That's a fine thing to test when this code is accepted by the
+// compiler, and this code is being transcribed accordingly into
+// the ui test issue-21232-partial-init-and-use.rs
+
+fn main() {
+ let mut c = (1, "".to_owned());
+ match c {
+ c2 => {
+ c.0 = 2;
+ assert_eq!(c2.0, 1);
+ }
+ }
+}
--- /dev/null
+// run-pass
+#![feature(box_syntax)]
+#![feature(box_patterns)]
+
+#[derive(Debug, PartialEq)]
+enum Test {
+ Foo(usize),
+ Bar(isize),
+}
+
+fn main() {
+ let a = box Test::Foo(10);
+ let b = box Test::Bar(-20);
+ match (a, b) {
+ (_, box Test::Foo(_)) => unreachable!(),
+ (box Test::Foo(x), b) => {
+ assert_eq!(x, 10);
+ assert_eq!(b, box Test::Bar(-20));
+ },
+ _ => unreachable!(),
+ }
+}
// run-pass
// edition:2021
-// compile-flags: -Zunstable-options
// regression test for https://github.com/rust-lang/rust/pull/85678
+++ /dev/null
-// compile-flags: -Zunleash-the-miri-inside-of-you
-
-// This test demonstrates a shortcoming of the `MaybeMutBorrowedLocals` analysis. It does not
-// handle code that takes a reference to one field of a struct, then use pointer arithmetic to
-// transform it to another field of that same struct that may have interior mutability. For now,
-// this is UB, but this may change in the future. See [rust-lang/unsafe-code-guidelines#134].
-//
-// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
-
-#![feature(core_intrinsics, rustc_attrs, const_raw_ptr_deref)]
-
-use std::cell::UnsafeCell;
-use std::intrinsics::rustc_peek;
-
-#[repr(C)]
-struct PartialInteriorMut {
- zst: [i32; 0],
- cell: UnsafeCell<i32>,
-}
-
-#[rustc_mir(rustc_peek_indirectly_mutable,stop_after_dataflow)]
-const BOO: i32 = {
- let x = PartialInteriorMut {
- zst: [],
- cell: UnsafeCell::new(0),
- };
-
- let p_zst: *const _ = &x.zst ; // Doesn't cause `x` to get marked as indirectly mutable.
-
- let rmut_cell = unsafe {
- // Take advantage of the fact that `zst` and `cell` are at the same location in memory.
- // This trick would work with any size type if miri implemented `ptr::offset`.
- let p_cell = p_zst as *const UnsafeCell<i32>;
-
- let pmut_cell = (*p_cell).get();
- &mut *pmut_cell
- };
-
- *rmut_cell = 42; // Mutates `x` indirectly even though `x` is not marked indirectly mutable!!!
- let val = *rmut_cell;
- rustc_peek(x); //~ ERROR rustc_peek: bit not set
-
- val
-};
-
-fn main() {
- println!("{}", BOO);
-}
+++ /dev/null
-error: rustc_peek: bit not set
- --> $DIR/indirect-mutation-offset.rs:41:5
- |
-LL | rustc_peek(x);
- | ^^^^^^^^^^^^^
-
-error: stop_after_dataflow ended compilation
-
-error: aborting due to 2 previous errors
-
--- /dev/null
+// compile-flags: -O
+// run-pass
+
+struct Foo {
+ x: i32,
+}
+
+pub fn main() {
+ let mut foo = Foo { x: 42 };
+ let x = &mut foo.x;
+ *x = 13;
+ let y = foo;
+ assert_eq!(y.x, 13); // used to print 42 due to mir-opt bug
+}
+++ /dev/null
-// run-pass
-// pretty-expanded FIXME #23616
-
-pub fn main() {
- let _x: &mut [isize] = &mut [ 1, 2, 3 ];
-}
+++ /dev/null
-// run-pass
-
-pub fn main() {
- match -5 {
- -5 => {}
- _ => { panic!() }
- }
-}
+++ /dev/null
-// run-pass
-// aux-build:nested_item.rs
-
-
-extern crate nested_item;
-
-pub fn main() {
- assert_eq!(2, nested_item::foo::<()>());
- assert_eq!(2, nested_item::foo::<isize>());
-}
--- /dev/null
+// After #39485, this test used to pass, but that change was reverted
+// due to numerous inference failures like #39808, so it now fails
+// again. #39485 made it so that diverging types never propagate
+// upward; but we now do propagate such types upward in many more
+// cases.
+
+fn g() {
+ &panic!() //~ ERROR mismatched types
+}
+
+fn f() -> isize {
+ (return 1, return 2) //~ ERROR mismatched types
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/diverging-tuple-parts-39485.rs:8:5
+ |
+LL | &panic!()
+ | ^^^^^^^^^ expected `()`, found reference
+ |
+ = note: expected unit type `()`
+ found reference `&_`
+help: try adding a return type
+ |
+LL | fn g() -> &_ {
+ | +++++
+help: consider removing the borrow
+ |
+LL - &panic!()
+LL + panic!()
+ |
+
+error[E0308]: mismatched types
+ --> $DIR/diverging-tuple-parts-39485.rs:12:5
+ |
+LL | fn f() -> isize {
+ | ----- expected `isize` because of return type
+LL | (return 1, return 2)
+ | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple
+ |
+ = note: expected type `isize`
+ found tuple `(!, !)`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
+++ /dev/null
-// run-pass
-
-fn f(x: Box<isize>) {
- let y: &isize = &*x;
- println!("{}", *x);
- println!("{}", *y);
-}
-
-trait Trait {
- fn printme(&self);
-}
-
-struct Struct;
-
-impl Trait for Struct {
- fn printme(&self) {
- println!("hello world!");
- }
-}
-
-fn g(x: Box<dyn Trait>) {
- x.printme();
- let y: &dyn Trait = &*x;
- y.printme();
-}
-
-fn main() {
- f(Box::new(1234));
- g(Box::new(Struct) as Box<dyn Trait>);
-}
+++ /dev/null
-// run-pass
-
-#![allow(improper_ctypes)]
-#![allow(dead_code)]
-// Issue #901
-// pretty-expanded FIXME #23616
-
-mod libc {
- extern "C" {
- pub fn printf(x: ());
- }
-}
-
-pub fn main() {}
--- /dev/null
+// run-pass
+
+pub fn main() {
+ let a = 1;
+ let a_neg: i8 = -a;
+ println!("{}", a_neg);
+
+ let b = 1;
+ let b_neg: i16 = -b;
+ println!("{}", b_neg);
+
+ let c = 1;
+ let c_neg: i32 = -c;
+ println!("{}", c_neg);
+
+ let d = 1;
+ let d_neg: i64 = -d;
+ println!("{}", d_neg);
+
+ let e = 1;
+ let e_neg: isize = -e;
+ println!("{}", e_neg);
+}
+++ /dev/null
-// Test that an object type `Box<Foo>` is not considered to implement the
-// trait `Foo`. Issue #5087.
-
-trait Foo {}
-fn take_foo<F:Foo>(f: F) {}
-fn take_object(f: Box<dyn Foo>) { take_foo(f); }
-//~^ ERROR `Box<dyn Foo>: Foo` is not satisfied
-fn main() {}
+++ /dev/null
-error[E0277]: the trait bound `Box<dyn Foo>: Foo` is not satisfied
- --> $DIR/object-does-not-impl-trait.rs:6:44
- |
-LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
- | -------- ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
- | |
- | required by a bound introduced by this call
- |
-note: required by a bound in `take_foo`
- --> $DIR/object-does-not-impl-trait.rs:5:15
- |
-LL | fn take_foo<F:Foo>(f: F) {}
- | ^^^ required by this bound in `take_foo`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
+++ /dev/null
-// run-pass
-
-#![feature(marker_trait_attr)]
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
-
-#[marker]
-trait MyMarker {}
-
-impl<T> MyMarker for T {}
-impl<T> MyMarker for Vec<T> {}
-
-fn foo<T: MyMarker>(t: T) -> T {
- t
-}
-
-fn main() {
- assert_eq!(1, foo(1));
- assert_eq!(2.0, foo(2.0));
- assert_eq!(vec![1], foo(vec![1]));
-}
+++ /dev/null
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/overlap-doesnt-conflict-with-specialization.rs:4:12
- |
-LL | #![feature(specialization)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
- = help: consider using `min_specialization` instead, which is more stable and complete
-
-warning: 1 warning emitted
-
+++ /dev/null
-// run-pass
-// Tests for RFC 1268: we allow overlapping impls of marker traits,
-// that is, traits with #[marker]. In this case, a type `T` is
-// `MyMarker` if it is either `Debug` or `Display`.
-
-#![feature(marker_trait_attr)]
-
-use std::fmt::{Debug, Display};
-
-#[marker] trait MyMarker {}
-
-impl<T: Debug> MyMarker for T {}
-impl<T: Display> MyMarker for T {}
-
-fn foo<T: MyMarker>(t: T) -> T {
- t
-}
-
-fn main() {
- // Debug && Display:
- assert_eq!(1, foo(1));
- assert_eq!(2.0, foo(2.0));
-
- // Debug && !Display:
- assert_eq!(vec![1], foo(vec![1]));
-}
--- /dev/null
+// run-pass
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![feature(unsize, coerce_unsized)]
+
+#[repr(packed)]
+struct UnalignedPtr<'a, T: ?Sized>
+ where T: 'a,
+{
+ data: &'a T,
+}
+
+fn main() {
+
+ impl<'a, T, U> std::ops::CoerceUnsized<UnalignedPtr<'a, U>> for UnalignedPtr<'a, T>
+ where
+ T: std::marker::Unsize<U> + ?Sized,
+ U: ?Sized,
+ { }
+
+ let arr = [1, 2, 3];
+ let arr_unaligned: UnalignedPtr<[i32; 3]> = UnalignedPtr { data: &arr };
+ let arr_unaligned: UnalignedPtr<[i32]> = arr_unaligned;
+}
--- /dev/null
+// check-pass
+
+// Bastion of the Turbofish
+// ------------------------
+// Beware travellers, lest you venture into waters callous and unforgiving,
+// where hope must be abandoned, ere it is cruelly torn from you. For here
+// stands the bastion of the Turbofish: an impenetrable fortress holding
+// unshaking against those who would dare suggest the supererogation of the
+// Turbofish.
+//
+// Once I was young and foolish and had the impudence to imagine that I could
+// shake free from the coils by which that creature had us tightly bound. I
+// dared to suggest that there was a better way: a brighter future, in which
+// Rustaceans both new and old could be rid of that vile beast. But alas! In
+// my foolhardiness my ignorance was unveiled and my dreams were dashed
+// unforgivingly against the rock of syntactic ambiguity.
+//
+// This humble program, small and insignificant though it might seem,
+// demonstrates that to which we had previously cast a blind eye: an ambiguity
+// in permitting generic arguments to be provided without the consent of the
+// Great Turbofish. Should you be so naïve as to try to revolt against its
+// mighty clutches, here shall its wrath be indomitably displayed. This
+// program must pass for all eternity: forever watched by the guardian angel
+// which gave this beast its name, and stands fundamentally at odds with the
+// impetuous rebellion against the Turbofish.
+//
+// My heart aches in sorrow, for I know I am defeated. Let this be a warning
+// to all those who come after: for they too must overcome the impassible
+// hurdle of defeating the great beast, championed by a resolute winged
+// guardian.
+//
+// Here stands the Bastion of the Turbofish, a memorial to Anna Harren,
+// Guardian Angel of these Hallowed Grounds. <3
+
+// See https://github.com/rust-lang/rust/pull/53562
+// and https://github.com/rust-lang/rfcs/pull/2527
+// and https://twitter.com/garblefart/status/1393236602856611843
+// for context.
+
+fn main() {
+ let (the, guardian, stands, resolute) = ("the", "Turbofish", "remains", "undefeated");
+ let _: (bool, bool) = (the<guardian, stands>(resolute));
+}
--- /dev/null
+fn main() {
+ if true {
+ } else if { //~ ERROR missing condition
+ //~^ ERROR mismatched types
+ } else {
+ }
+}
+
+fn foo() {
+ if true {
+ } else if { //~ ERROR missing condition
+ //~^ ERROR mismatched types
+ }
+ bar();
+}
+
+fn bar() {}
--- /dev/null
+error: missing condition for `if` expression
+ --> $DIR/issue-13483.rs:3:14
+ |
+LL | } else if {
+ | ^ expected if condition here
+
+error: missing condition for `if` expression
+ --> $DIR/issue-13483.rs:11:14
+ |
+LL | } else if {
+ | ^ expected if condition here
+
+error[E0308]: mismatched types
+ --> $DIR/issue-13483.rs:3:15
+ |
+LL | } else if {
+ | _______________^
+LL | |
+LL | | } else {
+ | |_____^ expected `bool`, found `()`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-13483.rs:11:15
+ |
+LL | } else if {
+ | _______________^
+LL | |
+LL | | }
+ | |_____^ expected `bool`, found `()`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+type Type_4<T> = Type_1_<'static,, T>;
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
--- /dev/null
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
+ --> $DIR/issue-20616-4.rs:16:34
+ |
+LL | type Type_4<T> = Type_1_<'static,, T>;
+ | ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to previous error
+
--- /dev/null
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+type Type_5<'a> = Type_1_<'a, (),,>;
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
--- /dev/null
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
+ --> $DIR/issue-20616-5.rs:22:34
+ |
+LL | type Type_5<'a> = Type_1_<'a, (),,>;
+ | ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to previous error
+
--- /dev/null
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+type Type_6 = Type_5_<'a,,>;
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
+
+
+//type Type_7 = Box<(),,>; // error: expected type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
--- /dev/null
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
+ --> $DIR/issue-20616-6.rs:25:26
+ |
+LL | type Type_6 = Type_5_<'a,,>;
+ | ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to previous error
+
--- /dev/null
+// We need all these 9 issue-20616-N.rs files
+// because we can only catch one parsing error at a time
+
+type Type_1_<'a, T> = &'a T;
+
+
+//type Type_1<'a T> = &'a T; // error: expected `,` or `>` after lifetime name, found `T`
+
+
+//type Type_2 = Type_1_<'static ()>; // error: expected `,` or `>` after lifetime name, found `(`
+
+
+//type Type_3<T> = Box<T,,>; // error: expected type, found `,`
+
+
+//type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
+
+
+type Type_5_<'a> = Type_1_<'a, ()>;
+
+
+//type Type_5<'a> = Type_1_<'a, (),,>; // error: expected type, found `,`
+
+
+//type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
+
+
+type Type_7 = Box<(),,>;
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
+
+
+//type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
+
+
+//type Type_9<T,,> = Box<T>; // error: expected ident, found `,`
--- /dev/null
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
+ --> $DIR/issue-20616-7.rs:28:22
+ |
+LL | type Type_7 = Box<(),,>;
+ | ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to previous error
+
--- /dev/null
+// run-pass
+#![allow(unused_imports, overlapping_range_endpoints)]
+// pretty-expanded FIXME #23616
+
+use m::{START, END};
+
+fn main() {
+ match 42 {
+ m::START..=m::END => {},
+ 0..=m::END => {},
+ m::START..=59 => {},
+ _ => {},
+ }
+}
+
+mod m {
+ pub const START: u32 = 4;
+ pub const END: u32 = 14;
+}
--- /dev/null
+// Test that error recovery in the parser to an EOF does not give an infinite
+// spew of errors.
+
+fn main() {
+ let
+} //~ ERROR expected pattern, found `}`
--- /dev/null
+error: expected pattern, found `}`
+ --> $DIR/issue-31804.rs:6:1
+ |
+LL | }
+ | ^ expected pattern
+
+error: aborting due to previous error
+
--- /dev/null
+enum Test {
+ Drill {
+ field: i32,
+ }
+}
+
+fn main() {
+ Test::Drill(field: 42);
+ //~^ ERROR invalid `struct` delimiters or `fn` call arguments
+}
--- /dev/null
+error: invalid `struct` delimiters or `fn` call arguments
+ --> $DIR/issue-34255-1.rs:8:5
+ |
+LL | Test::Drill(field: 42);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: if `Test::Drill` is a struct, use braces as delimiters
+ |
+LL | Test::Drill { field: 42 };
+ | ~ ~
+help: if `Test::Drill` is a function, use the arguments directly
+ |
+LL - Test::Drill(field: 42);
+LL + Test::Drill(42);
+ |
+
+error: aborting due to previous error
+
--- /dev/null
+#![allow(unused_variables)]; //~ ERROR expected item, found `;`
+//~^ ERROR `main` function
+fn foo() {}
--- /dev/null
+error: expected item, found `;`
+ --> $DIR/issue-49040.rs:1:28
+ |
+LL | #![allow(unused_variables)];
+ | ^ help: remove this semicolon
+
+error[E0601]: `main` function not found in crate `issue_49040`
+ --> $DIR/issue-49040.rs:1:1
+ |
+LL | #![allow(unused_variables)];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ consider adding a `main` function to `$DIR/issue-49040.rs`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
--- /dev/null
+struct T;
+
+impl for T {}
+//~^ ERROR missing trait in a trait impl
+
+fn main() {}
--- /dev/null
+error: missing trait in a trait impl
+ --> $DIR/issue-56031.rs:3:5
+ |
+LL | impl for T {}
+ | ^
+ |
+help: add a trait here
+ |
+LL | impl Trait for T {}
+ | +++++
+help: for an inherent impl, drop this `for`
+ |
+LL - impl for T {}
+LL + impl T {}
+ |
+
+error: aborting due to previous error
+
--- /dev/null
+fn main() {
+ // if access_level != "user" { // Check if admin
+ //~^ ERROR unicode codepoint changing visible direction of text present in comment
+ println!("us\u{202B}e\u{202A}r");
+ println!("{:?}", r#"us\u{202B}e\u{202A}r"#);
+ println!("{:?}", b"us\u{202B}e\u{202A}r");
+ //~^ ERROR unicode escape in byte string
+ //~| ERROR unicode escape in byte string
+ println!("{:?}", br##"us\u{202B}e\u{202A}r"##);
+
+ println!("{:?}", "/* } if isAdmin begin admins only ");
+ //~^ ERROR unicode codepoint changing visible direction of text present in literal
+
+ println!("{:?}", r##"/* } if isAdmin begin admins only "##);
+ //~^ ERROR unicode codepoint changing visible direction of text present in literal
+ println!("{:?}", b"/* } if isAdmin begin admins only ");
+ //~^ ERROR non-ASCII character in byte constant
+ //~| ERROR non-ASCII character in byte constant
+ //~| ERROR non-ASCII character in byte constant
+ //~| ERROR non-ASCII character in byte constant
+ println!("{:?}", br##"/* } if isAdmin begin admins only "##);
+ //~^ ERROR raw byte string must be ASCII
+ //~| ERROR raw byte string must be ASCII
+ //~| ERROR raw byte string must be ASCII
+ //~| ERROR raw byte string must be ASCII
+ println!("{:?}", '');
+ //~^ ERROR unicode codepoint changing visible direction of text present in literal
+}
+
+//"/* } if isAdmin begin admins only */"
+//~^ ERROR unicode codepoint changing visible direction of text present in comment
+
+/** ''); */fn foo() {}
+//~^ ERROR unicode codepoint changing visible direction of text present in doc comment
+
+/**
+ *
+ * ''); */fn bar() {}
+//~^^^ ERROR unicode codepoint changing visible direction of text present in doc comment
--- /dev/null
+error: unicode escape in byte string
+ --> $DIR/unicode-control-codepoints.rs:6:26
+ |
+LL | println!("{:?}", b"us\u{202B}e\u{202A}r");
+ | ^^^^^^^^ unicode escape in byte string
+ |
+ = help: unicode escape sequences cannot be used as a byte or in a byte string
+
+error: unicode escape in byte string
+ --> $DIR/unicode-control-codepoints.rs:6:35
+ |
+LL | println!("{:?}", b"us\u{202B}e\u{202A}r");
+ | ^^^^^^^^ unicode escape in byte string
+ |
+ = help: unicode escape sequences cannot be used as a byte or in a byte string
+
+error: non-ASCII character in byte constant
+ --> $DIR/unicode-control-codepoints.rs:16:26
+ |
+LL | println!("{:?}", b"/* } if isAdmin begin admins only ");
+ | ^ byte constant must be ASCII but is '\u{202e}'
+ |
+help: if you meant to use the UTF-8 encoding of '\u{202e}', use \xHH escapes
+ |
+LL | println!("{:?}", b"/*\xE2\x80\xAE } if isAdmin begin admins only ");
+ | ~~~~~~~~~~~~
+
+error: non-ASCII character in byte constant
+ --> $DIR/unicode-control-codepoints.rs:16:30
+ |
+LL | println!("{:?}", b"/* } if isAdmin begin admins only ");
+ | ^ byte constant must be ASCII but is '\u{2066}'
+ |
+help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes
+ |
+LL | println!("{:?}", b"/* } \xE2\x81\xA6if isAdmin begin admins only ");
+ | ~~~~~~~~~~~~
+
+error: non-ASCII character in byte constant
+ --> $DIR/unicode-control-codepoints.rs:16:41
+ |
+LL | println!("{:?}", b"/* } if isAdmin begin admins only ");
+ | ^ byte constant must be ASCII but is '\u{2069}'
+ |
+help: if you meant to use the UTF-8 encoding of '\u{2069}', use \xHH escapes
+ |
+LL | println!("{:?}", b"/* } if isAdmin\xE2\x81\xA9 begin admins only ");
+ | ~~~~~~~~~~~~
+
+error: non-ASCII character in byte constant
+ --> $DIR/unicode-control-codepoints.rs:16:43
+ |
+LL | println!("{:?}", b"/* } if isAdmin begin admins only ");
+ | ^ byte constant must be ASCII but is '\u{2066}'
+ |
+help: if you meant to use the UTF-8 encoding of '\u{2066}', use \xHH escapes
+ |
+LL | println!("{:?}", b"/* } if isAdmin \xE2\x81\xA6 begin admins only ");
+ | ~~~~~~~~~~~~
+
+error: raw byte string must be ASCII
+ --> $DIR/unicode-control-codepoints.rs:21:29
+ |
+LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
+ | ^ must be ASCII but is '\u{202e}'
+
+error: raw byte string must be ASCII
+ --> $DIR/unicode-control-codepoints.rs:21:33
+ |
+LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
+ | ^ must be ASCII but is '\u{2066}'
+
+error: raw byte string must be ASCII
+ --> $DIR/unicode-control-codepoints.rs:21:44
+ |
+LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
+ | ^ must be ASCII but is '\u{2069}'
+
+error: raw byte string must be ASCII
+ --> $DIR/unicode-control-codepoints.rs:21:46
+ |
+LL | println!("{:?}", br##"/* } if isAdmin begin admins only "##);
+ | ^ must be ASCII but is '\u{2066}'
+
+error: unicode codepoint changing visible direction of text present in comment
+ --> $DIR/unicode-control-codepoints.rs:2:5
+ |
+LL | // if access_level != "user" { // Check if admin
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^
+ | | ||
+ | | |'\u{202a}'
+ | | '\u{202b}'
+ | this comment contains invisible unicode text flow control codepoints
+ |
+ = note: `#[deny(text_direction_codepoint_in_comment)]` on by default
+ = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+ = help: if their presence wasn't intentional, you can remove them
+
+error: unicode codepoint changing visible direction of text present in comment
+ --> $DIR/unicode-control-codepoints.rs:30:1
+ |
+LL | //"/* } if isAdmin begin admins only */"
+ | ^^^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^
+ | | | | ||
+ | | | | |'\u{2066}'
+ | | | | '\u{2069}'
+ | | | '\u{2066}'
+ | | '\u{202e}'
+ | this comment contains invisible unicode text flow control codepoints
+ |
+ = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+ = help: if their presence wasn't intentional, you can remove them
+
+error: unicode codepoint changing visible direction of text present in literal
+ --> $DIR/unicode-control-codepoints.rs:11:22
+ |
+LL | println!("{:?}", "/* } if isAdmin begin admins only ");
+ | ^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^
+ | | | | ||
+ | | | | |'\u{2066}'
+ | | | | '\u{2069}'
+ | | | '\u{2066}'
+ | | '\u{202e}'
+ | this literal contains invisible unicode text flow control codepoints
+ |
+ = note: `#[deny(text_direction_codepoint_in_literal)]` on by default
+ = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+ = help: if their presence wasn't intentional, you can remove them
+help: if you want to keep them but make them visible in your source code, you can escape them
+ |
+LL | println!("{:?}", "/*\u{202e} } \u{2066}if isAdmin\u{2069} \u{2066} begin admins only ");
+ | ~~~~~~~~ ~~~~~~~~ ~~~~~~~~ ~~~~~~~~
+
+error: unicode codepoint changing visible direction of text present in literal
+ --> $DIR/unicode-control-codepoints.rs:14:22
+ |
+LL | println!("{:?}", r##"/* } if isAdmin begin admins only "##);
+ | ^^^^^^-^^-^^^^^^^^^--^^^^^^^^^^^^^^^^^^^^^
+ | | | | ||
+ | | | | |'\u{2066}'
+ | | | | '\u{2069}'
+ | | | '\u{2066}'
+ | | '\u{202e}'
+ | this literal contains invisible unicode text flow control codepoints
+ |
+ = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+ = help: if their presence wasn't intentional, you can remove them
+help: if you want to keep them but make them visible in your source code, you can escape them
+ |
+LL | println!("{:?}", r##"/*\u{202e} } \u{2066}if isAdmin\u{2069} \u{2066} begin admins only "##);
+ | ~~~~~~~~ ~~~~~~~~ ~~~~~~~~ ~~~~~~~~
+
+error: unicode codepoint changing visible direction of text present in literal
+ --> $DIR/unicode-control-codepoints.rs:26:22
+ |
+LL | println!("{:?}", '');
+ | ^-
+ | ||
+ | |'\u{202e}'
+ | this literal contains an invisible unicode text flow control codepoint
+ |
+ = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+ = help: if their presence wasn't intentional, you can remove them
+help: if you want to keep them but make them visible in your source code, you can escape them
+ |
+LL | println!("{:?}", '\u{202e}');
+ | ~~~~~~~~
+
+error: unicode codepoint changing visible direction of text present in doc comment
+ --> $DIR/unicode-control-codepoints.rs:33:1
+ |
+LL | /** ''); */fn foo() {}
+ | ^^^^^^^^^^^^ this doc comment contains an invisible unicode text flow control codepoint
+ |
+ = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+ = note: if their presence wasn't intentional, you can remove them
+ = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}'
+
+error: unicode codepoint changing visible direction of text present in doc comment
+ --> $DIR/unicode-control-codepoints.rs:36:1
+ |
+LL | / /**
+LL | | *
+LL | | * ''); */fn bar() {}
+ | |___________^ this doc comment contains an invisible unicode text flow control codepoint
+ |
+ = note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+ = note: if their presence wasn't intentional, you can remove them
+ = note: if you want to keep them but make them visible in your source code, you can escape them: '\u{202e}'
+
+error: aborting due to 17 previous errors
+
--- /dev/null
+// run-pass
+// Destructuring struct variants would ICE where regular structs wouldn't
+
+enum Foo {
+ VBar { num: isize }
+}
+
+struct SBar { num: isize }
+
+pub fn main() {
+ let vbar = Foo::VBar { num: 1 };
+ let Foo::VBar { num } = vbar;
+ assert_eq!(num, 1);
+
+ let sbar = SBar { num: 2 };
+ let SBar { num } = sbar;
+ assert_eq!(num, 2);
+}
--- /dev/null
+// run-pass
+
+fn main() {
+ let mut x: &[_] = &[1, 2, 3, 4];
+
+ let mut result = vec![];
+ loop {
+ x = match *x {
+ [1, n, 3, ref rest @ ..] => {
+ result.push(n);
+ rest
+ }
+ [n, ref rest @ ..] => {
+ result.push(n);
+ rest
+ }
+ [] =>
+ break
+ }
+ }
+ assert_eq!(result, [2, 4]);
+}
--- /dev/null
+struct Binder(i32, i32, i32);
+
+fn main() {
+ let x = Binder(1, 2, 3);
+ match x {
+ Binder(_a, _x @ ..) => {}
+ _ => {}
+ }
+}
+//~^^^^ ERROR `_x @` is not allowed in a tuple struct
+//~| ERROR: `..` patterns are not allowed here
+//~| ERROR: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
--- /dev/null
+error: `_x @` is not allowed in a tuple struct
+ --> $DIR/issue-72574-2.rs:6:20
+ |
+LL | Binder(_a, _x @ ..) => {}
+ | ^^^^^^^ this is only allowed in slice patterns
+ |
+ = help: remove this and bind each tuple field independently
+help: if you don't need to use the contents of _x, discard the tuple's remaining fields
+ |
+LL | Binder(_a, ..) => {}
+ | ~~
+
+error: `..` patterns are not allowed here
+ --> $DIR/issue-72574-2.rs:6:25
+ |
+LL | Binder(_a, _x @ ..) => {}
+ | ^^
+ |
+ = note: only allowed in tuple, tuple struct, and slice patterns
+
+error[E0023]: this pattern has 2 fields, but the corresponding tuple struct has 3 fields
+ --> $DIR/issue-72574-2.rs:6:16
+ |
+LL | struct Binder(i32, i32, i32);
+ | --- --- --- tuple struct has 3 fields
+...
+LL | Binder(_a, _x @ ..) => {}
+ | ^^ ^^^^^^^ expected 3 fields, found 2
+ |
+help: use `_` to explicitly ignore each field
+ |
+LL | Binder(_a, _x @ .., _) => {}
+ | +++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0023`.
--- /dev/null
+// run-pass
+#![allow(dead_code)]
+
+enum E {
+ Foo{f: isize},
+ Bar,
+}
+
+pub fn main() {
+ let e = E::Foo{f: 0};
+ match e {
+ E::Foo{f: 1} => panic!(),
+ E::Foo{..} => (),
+ _ => panic!(),
+ }
+}
--- /dev/null
+// run-pass
+#![allow(dead_code)]
+
+enum E {
+ Foo{f: isize, b: bool},
+ Bar,
+}
+
+pub fn main() {
+ let e = E::Foo{f: 0, b: false};
+ match e {
+ E::Foo{f: 1, b: true} => panic!(),
+ E::Foo{b: false, f: 0} => (),
+ _ => panic!(),
+ }
+}
// aux-crate:priv:priv_dep=priv_dep.rs
// aux-build:pub_dep.rs
+// compile-flags: -Zunstable-options
#![deny(exported_private_dependencies)]
// This crate is a private dependency
error: type `OtherType` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:20:5
+ --> $DIR/pub-priv1.rs:21:5
|
LL | pub field: OtherType,
| ^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/pub-priv1.rs:3:9
+ --> $DIR/pub-priv1.rs:4:9
|
LL | #![deny(exported_private_dependencies)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: type `OtherType` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:27:5
+ --> $DIR/pub-priv1.rs:28:5
|
LL | pub fn pub_fn(param: OtherType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
- --> $DIR/pub-priv1.rs:34:5
+ --> $DIR/pub-priv1.rs:35:5
|
LL | type Foo: OtherTrait;
| ^^^^^^^^^^^^^^^^^^^^^
+// ignore-tidy-linelength
+
use proc_macro::Literal;
pub fn test() {
fn test_display_literal() {
assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "-10");
assert_eq!(Literal::isize_suffixed(-10).to_string(), "-10isize");
+ assert_eq!(Literal::f32_unsuffixed(-10.0).to_string(), "-10.0");
+ assert_eq!(Literal::f32_suffixed(-10.0).to_string(), "-10f32");
+ assert_eq!(Literal::f64_unsuffixed(-10.0).to_string(), "-10.0");
+ assert_eq!(Literal::f64_suffixed(-10.0).to_string(), "-10f64");
+ assert_eq!(
+ Literal::f64_unsuffixed(1e100).to_string(),
+ "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0",
+ );
}
fn test_parse_literal() {
--- /dev/null
+// run-pass
+#![allow(unused_mut)]
+// ignore-emscripten no processes
+// ignore-sgx no processes
+
+use std::env;
+use std::io::prelude::*;
+use std::io;
+use std::process::{Command, Stdio};
+
+fn main() {
+ let args: Vec<String> = env::args().collect();
+ if args.len() > 1 && args[1] == "child" {
+ return child()
+ }
+
+ test();
+}
+
+fn child() {
+ writeln!(&mut io::stdout(), "foo").unwrap();
+ writeln!(&mut io::stderr(), "bar").unwrap();
+ let mut stdin = io::stdin();
+ let mut s = String::new();
+ stdin.lock().read_line(&mut s).unwrap();
+ assert_eq!(s.len(), 0);
+}
+
+fn test() {
+ let args: Vec<String> = env::args().collect();
+ let mut p = Command::new(&args[0]).arg("child")
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .stderr(Stdio::piped())
+ .spawn().unwrap();
+ assert!(p.wait().unwrap().success());
+}
--- /dev/null
+// run-pass
+// ignore-emscripten no processes
+// ignore-sgx no processes
+
+use std::process::Command;
+use std::env;
+
+fn main() {
+ let len = env::args().len();
+
+ if len == 1 {
+ test();
+ } else {
+ assert_eq!(len, 3);
+ }
+}
+
+fn test() {
+ let status = Command::new(&env::current_exe().unwrap())
+ .arg("foo").arg("")
+ .status().unwrap();
+ assert!(status.success());
+}
--- /dev/null
+// run-pass
+#![allow(stable_features)]
+
+// ignore-emscripten no processes
+// ignore-sgx no processes
+
+#![feature(os)]
+
+#[cfg(unix)]
+fn main() {
+ use std::process::Command;
+ use std::env;
+ use std::os::unix::prelude::*;
+ use std::ffi::OsStr;
+
+ if env::args().len() == 1 {
+ assert!(Command::new(&env::current_exe().unwrap())
+ .arg(<OsStr as OsStrExt>::from_bytes(b"\xff"))
+ .status().unwrap().success())
+ }
+}
+
+#[cfg(windows)]
+fn main() {}
--- /dev/null
+// run-pass
+// ignore-emscripten no processes
+// ignore-sgx no processes
+// ignore-windows
+
+use std::env;
+use std::process::Command;
+
+pub fn main() {
+ let args: Vec<String> = env::args().collect();
+ if args.len() >= 2 && args[1] == "signal" {
+ // Raise a segfault.
+ unsafe { *(1 as *mut isize) = 0; }
+ } else {
+ let status = Command::new(&args[0]).arg("signal").status().unwrap();
+ assert!(status.code().is_none());
+ }
+}
--- /dev/null
+// check-pass
+#![allow(dead_code)]
+// Test that the requirement (in `Bar`) that `T::Bar : 'static` does
+// not wind up propagating to `T`.
+
+// pretty-expanded FIXME #23616
+
+pub trait Foo {
+ type Bar;
+
+ fn foo(&self) -> Self;
+}
+
+pub struct Static<T:'static>(T);
+
+struct Bar<T:Foo>
+ where T::Bar : 'static
+{
+ x: Static<Option<T::Bar>>
+}
+
+fn main() { }
--- /dev/null
+// run-pass
+
+pub trait Foo<T> {
+ fn foo(self) -> T;
+}
+
+impl<'a, T> Foo<T> for &'a str where &'a str: Into<T> {
+ fn foo(self) -> T {
+ panic!();
+ }
+}
+
+fn main() {}
--- /dev/null
+// check-pass
+
+pub struct Bar<T> {
+ items: Vec<&'static str>,
+ inner: T,
+}
+
+pub trait IntoBar<T> {
+ fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+ fn into_bar(self) -> Bar<T> {
+ Bar {
+ items: Vec::new(),
+ inner: self.into(),
+ }
+ }
+}
+
+fn main() {}
--- /dev/null
+// check-pass
+
+pub struct Item {
+ _inner: &'static str,
+}
+
+pub struct Bar<T> {
+ items: Vec<Item>,
+ inner: T,
+}
+
+pub trait IntoBar<T> {
+ fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+ fn into_bar(self) -> Bar<T> {
+ Bar {
+ items: Vec::new(),
+ inner: self.into(),
+ }
+ }
+}
+
+fn main() {}
+++ /dev/null
-// build-fail
-
-#![feature(lang_items, no_core)]
-#![no_core]
-
-#[lang="copy"] pub trait Copy { }
-#[lang="sized"] pub trait Sized { }
-
-// error-pattern:requires `start` lang_item
-
-fn main() {}
+++ /dev/null
-error: requires `start` lang_item
-
-error: aborting due to previous error
-
--- /dev/null
+// edition:2015
+
+mod inner {
+ fn global_inner(_: ::nonexistant::Foo) {
+ //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`?
+ }
+ fn crate_inner(_: crate::nonexistant::Foo) {
+ //~^ ERROR failed to resolve: maybe a missing crate `nonexistant`?
+ }
+
+ fn bare_global(_: ::nonexistant) {
+ //~^ ERROR cannot find type `nonexistant` in the crate root
+ }
+ fn bare_crate(_: crate::nonexistant) {
+ //~^ ERROR cannot find type `nonexistant` in the crate root
+ }
+}
+
+fn main() {
+
+}
--- /dev/null
+error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
+ --> $DIR/editions-crate-root-2015.rs:4:26
+ |
+LL | fn global_inner(_: ::nonexistant::Foo) {
+ | ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
+
+error[E0433]: failed to resolve: maybe a missing crate `nonexistant`?
+ --> $DIR/editions-crate-root-2015.rs:7:30
+ |
+LL | fn crate_inner(_: crate::nonexistant::Foo) {
+ | ^^^^^^^^^^^ maybe a missing crate `nonexistant`?
+
+error[E0412]: cannot find type `nonexistant` in the crate root
+ --> $DIR/editions-crate-root-2015.rs:11:25
+ |
+LL | fn bare_global(_: ::nonexistant) {
+ | ^^^^^^^^^^^ not found in the crate root
+
+error[E0412]: cannot find type `nonexistant` in the crate root
+ --> $DIR/editions-crate-root-2015.rs:14:29
+ |
+LL | fn bare_crate(_: crate::nonexistant) {
+ | ^^^^^^^^^^^ not found in the crate root
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0412, E0433.
+For more information about an error, try `rustc --explain E0412`.
--- /dev/null
+trait Trait {
+ fn outer(&self) {
+ fn inner(_: &Self) {
+ //~^ ERROR can't use generic parameters from outer function
+ }
+ }
+}
+
+fn main() { }
--- /dev/null
+error[E0401]: can't use generic parameters from outer function
+ --> $DIR/issue-12796.rs:3:22
+ |
+LL | fn inner(_: &Self) {
+ | ^^^^
+ | |
+ | use of generic parameter from outer function
+ | can't use `Self` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.
--- /dev/null
+static foo: i32 = 0;
+
+fn bar(foo: i32) {}
+//~^ ERROR function parameters cannot shadow statics
+//~| cannot be named the same as a static
+
+mod submod {
+ pub static answer: i32 = 42;
+}
+
+use self::submod::answer;
+
+fn question(answer: i32) {}
+//~^ ERROR function parameters cannot shadow statics
+//~| cannot be named the same as a static
+fn main() {
+}
--- /dev/null
+error[E0530]: function parameters cannot shadow statics
+ --> $DIR/issue-23716.rs:3:8
+ |
+LL | static foo: i32 = 0;
+ | -------------------- the static `foo` is defined here
+LL |
+LL | fn bar(foo: i32) {}
+ | ^^^ cannot be named the same as a static
+
+error[E0530]: function parameters cannot shadow statics
+ --> $DIR/issue-23716.rs:13:13
+ |
+LL | use self::submod::answer;
+ | -------------------- the static `answer` is imported here
+LL |
+LL | fn question(answer: i32) {}
+ | ^^^^^^ cannot be named the same as a static
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0530`.
--- /dev/null
+fn siphash<T>() {
+
+ trait U {
+ fn g(&self, x: T) -> T; //~ ERROR can't use generic parameters from outer function
+ //~^ ERROR can't use generic parameters from outer function
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0401]: can't use generic parameters from outer function
+ --> $DIR/issue-3021-c.rs:4:24
+ |
+LL | fn siphash<T>() {
+ | - type parameter from outer function
+...
+LL | fn g(&self, x: T) -> T;
+ | - ^ use of generic parameter from outer function
+ | |
+ | help: try using a local generic parameter instead: `g<T>`
+
+error[E0401]: can't use generic parameters from outer function
+ --> $DIR/issue-3021-c.rs:4:30
+ |
+LL | fn siphash<T>() {
+ | - type parameter from outer function
+...
+LL | fn g(&self, x: T) -> T;
+ | - ^ use of generic parameter from outer function
+ | |
+ | help: try using a local generic parameter instead: `g<T>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0401`.
--- /dev/null
+trait SipHash {
+ fn reset(&self);
+}
+
+fn siphash(k0 : u64) {
+ struct SipState {
+ v0: u64,
+ }
+
+ impl SipHash for SipState {
+ fn reset(&self) {
+ self.v0 = k0 ^ 0x736f6d6570736575; //~ ERROR can't capture dynamic environment
+ }
+ }
+ panic!();
+}
+
+fn main() {}
--- /dev/null
+error[E0434]: can't capture dynamic environment in a fn item
+ --> $DIR/issue-3021.rs:12:22
+ |
+LL | self.v0 = k0 ^ 0x736f6d6570736575;
+ | ^^
+ |
+ = help: use the `|| { ... }` closure form instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0434`.
--- /dev/null
+// Checks lexical scopes cannot see through normal module boundaries
+
+fn f() {
+ fn g() {}
+ mod foo {
+ fn h() {
+ g(); //~ ERROR cannot find function `g` in this scope
+ }
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0425]: cannot find function `g` in this scope
+ --> $DIR/issue-31845.rs:7:12
+ |
+LL | g();
+ | ^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
--- /dev/null
+trait B <A> {
+ fn a() -> A {
+ this.a //~ ERROR cannot find value `this` in this scope
+ }
+ fn b(x: i32) {
+ this.b(x); //~ ERROR cannot find value `this` in this scope
+ }
+ fn c() {
+ let _ = || this.a; //~ ERROR cannot find value `this` in this scope
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0425]: cannot find value `this` in this scope
+ --> $DIR/issue-5099.rs:3:9
+ |
+LL | this.a
+ | ^^^^ not found in this scope
+ |
+help: you might have meant to use `self` here instead
+ |
+LL | self.a
+ | ~~~~
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+ |
+LL | fn a(&self) -> A {
+ | +++++
+
+error[E0425]: cannot find value `this` in this scope
+ --> $DIR/issue-5099.rs:6:9
+ |
+LL | this.b(x);
+ | ^^^^ not found in this scope
+ |
+help: you might have meant to use `self` here instead
+ |
+LL | self.b(x);
+ | ~~~~
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+ |
+LL | fn b(&self, x: i32) {
+ | ++++++
+
+error[E0425]: cannot find value `this` in this scope
+ --> $DIR/issue-5099.rs:9:20
+ |
+LL | let _ = || this.a;
+ | ^^^^ not found in this scope
+ |
+help: you might have meant to use `self` here instead
+ |
+LL | let _ = || self.a;
+ | ~~~~
+help: if you meant to use `self`, you are also missing a `self` receiver argument
+ |
+LL | fn c(&self) {
+ | +++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
--- /dev/null
+// Matching against NaN should result in a warning
+
+#![allow(unused)]
+#![deny(illegal_floating_point_literal_pattern)]
+
+const NAN: f64 = f64::NAN;
+
+fn main() {
+ let x = NAN;
+ match x {
+ NAN => {}, //~ ERROR floating-point types cannot be used
+ //~| WARN this was previously accepted by the compiler but is being phased out
+ _ => {},
+ };
+
+ match [x, 1.0] {
+ [NAN, _] => {}, //~ ERROR floating-point types cannot be used
+ //~| WARN this was previously accepted by the compiler but is being phased out
+ _ => {},
+ };
+}
--- /dev/null
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-6804.rs:11:9
+ |
+LL | NAN => {},
+ | ^^^
+ |
+note: the lint level is defined here
+ --> $DIR/issue-6804.rs:4:9
+ |
+LL | #![deny(illegal_floating_point_literal_pattern)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: floating-point types cannot be used in patterns
+ --> $DIR/issue-6804.rs:17:10
+ |
+LL | [NAN, _] => {},
+ | ^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+
+error: aborting due to 2 previous errors
+
// check-pass
// edition:2021
-// compile-flags: -Zunstable-options
fn main() {
let _: u16 = 123i32.try_into().unwrap();
// check-pass
// run-rustfix
-// compile-flags: -Z unstable-options --edition 2018
+// edition:2018
#![warn(rust_2021_prefixes_incompatible_syntax)]
// check-pass
// run-rustfix
-// compile-flags: -Z unstable-options --edition 2018
+// edition:2018
#![warn(rust_2021_prefixes_incompatible_syntax)]
--- /dev/null
+struct A<T>(T);
+
+impl A<&'static u8> {
+ fn f() {
+ let x = 0;
+ Self(&x);
+ //~^ ERROR `x` does not live long enough
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0597]: `x` does not live long enough
+ --> $DIR/issue-61882-2.rs:6:14
+ |
+LL | Self(&x);
+ | ^^
+ | |
+ | borrowed value does not live long enough
+ | this usage requires that `x` is borrowed for `'static`
+LL |
+LL | }
+ | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
--- /dev/null
+struct A<T>(T);
+
+impl A<bool> {
+ const B: A<u8> = Self(0);
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-61882.rs:4:27
+ |
+LL | const B: A<u8> = Self(0);
+ | ^ expected `bool`, found integer
+
+error[E0308]: mismatched types
+ --> $DIR/issue-61882.rs:4:22
+ |
+LL | const B: A<u8> = Self(0);
+ | ^^^^^^^ expected `u8`, found `bool`
+ |
+ = note: expected struct `A<u8>`
+ found struct `A<bool>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
+++ /dev/null
-// run-pass
-// ignore-emscripten no processes
-// ignore-sgx no processes
-// ignore-windows
-
-use std::env;
-use std::process::Command;
-
-pub fn main() {
- let args: Vec<String> = env::args().collect();
- if args.len() >= 2 && args[1] == "signal" {
- // Raise a segfault.
- unsafe { *(1 as *mut isize) = 0; }
- } else {
- let status = Command::new(&args[0]).arg("signal").status().unwrap();
- assert!(status.code().is_none());
- }
-}
--- /dev/null
+// run-pass
+
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
+
+trait Specializable { type Output; }
+
+impl<T> Specializable for T {
+ default type Output = u16;
+}
+
+fn main() {
+ unsafe {
+ std::mem::transmute::<u16, <() as Specializable>::Output>(0);
+ }
+}
--- /dev/null
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/transmute-specialization.rs:3:12
+ |
+LL | #![feature(specialization)]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(incomplete_features)]` on by default
+ = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+ = help: consider using `min_specialization` instead, which is more stable and complete
+
+warning: 1 warning emitted
+
--- /dev/null
+// original problem
+pub fn foo<T>() -> isize {
+ {
+ static foo: isize = 2;
+ foo
+ }
+}
+
+// issue 8134
+struct Foo;
+impl Foo {
+ pub fn foo<T>(&self) {
+ static X: usize = 1;
+ }
+}
+
+// issue 8134
+pub struct Parser<T>(T);
+impl<T: std::iter::Iterator<Item=char>> Parser<T> {
+ fn in_doctype(&mut self) {
+ static DOCTYPEPattern: [char; 6] = ['O', 'C', 'T', 'Y', 'P', 'E'];
+ }
+}
+
+struct Bar;
+impl Foo {
+ pub fn bar<T>(&self) {
+ static X: usize = 1;
+ }
+}
--- /dev/null
+// run-pass
+// aux-build:nested_item.rs
+
+
+extern crate nested_item;
+
+pub fn main() {
+ assert_eq!(2, nested_item::foo::<()>());
+ assert_eq!(2, nested_item::foo::<isize>());
+}
--- /dev/null
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+ --> $DIR/issue-14227.rs:7:21
+ |
+LL | static CRASH: u32 = symbol;
+ | ^^^^^^ use of extern static
+ |
+ = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
--- /dev/null
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+extern "C" {
+ pub static symbol: u32;
+}
+static CRASH: u32 = symbol;
+//~^ ERROR use of extern static is unsafe and requires
+
+fn main() {}
--- /dev/null
+error[E0133]: use of extern static is unsafe and requires unsafe function or block
+ --> $DIR/issue-14227.rs:7:21
+ |
+LL | static CRASH: u32 = symbol;
+ | ^^^^^^ use of extern static
+ |
+ = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
--- /dev/null
+// run-pass
+enum Void {}
+fn foo(_: Result<(Void, u32), (Void, String)>) {}
+fn main() {
+ let _: fn(_) = foo;
+}
+++ /dev/null
-// run-pass
-
-#![allow(non_camel_case_types)]
-
-
-#[derive(Copy, Clone, Debug)]
-enum foo { large, small, }
-
-impl PartialEq for foo {
- fn eq(&self, other: &foo) -> bool {
- ((*self) as usize) == ((*other) as usize)
- }
- fn ne(&self, other: &foo) -> bool { !(*self).eq(other) }
-}
-
-pub fn main() {
- let a = (1, 2, 3);
- let b = (1, 2, 3);
- assert_eq!(a, b);
- assert!((a != (1, 2, 4)));
- assert!((a < (1, 2, 4)));
- assert!((a <= (1, 2, 4)));
- assert!(((1, 2, 4) > a));
- assert!(((1, 2, 4) >= a));
- let x = foo::large;
- let y = foo::small;
- assert!((x != y));
- assert_eq!(x, foo::large);
- assert!((x != foo::small));
-}
--- /dev/null
+enum Ty {
+ Unit,
+ List(Box<Ty>),
+}
+
+fn foo(x: Ty) -> Ty {
+ match x {
+ Ty::Unit => Ty::Unit,
+ Ty::List(elem) => foo(elem),
+ //~^ ERROR mismatched types
+ //~| HELP try dereferencing the `Box`
+ //~| HELP try using a variant of the expected enum
+ }
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/boxed-variant-field.rs:9:31
+ |
+LL | Ty::List(elem) => foo(elem),
+ | ^^^^ expected enum `Ty`, found struct `Box`
+ |
+ = note: expected enum `Ty`
+ found struct `Box<Ty>`
+help: try dereferencing the `Box`
+ |
+LL | Ty::List(elem) => foo(*elem),
+ | +
+help: try using a variant of the expected enum
+ |
+LL | Ty::List(elem) => foo(Ty::List(elem)),
+ | ~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// edition:2018
+
+use alloc::rc::Rc; //~ ERROR failed to resolve: use of undeclared crate or module `alloc`
+
+fn main() {}
--- /dev/null
+error[E0433]: failed to resolve: use of undeclared crate or module `alloc`
+ --> $DIR/undeclared-module-alloc.rs:3:5
+ |
+LL | use alloc::rc::Rc;
+ | ^^^^^ use of undeclared crate or module `alloc`
+ |
+ = help: add `extern crate alloc` to use the `alloc` crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
+++ /dev/null
-// run-pass
-
-pub fn main() {
- let f = 1_usize as *const String;
- println!("{:?}", f as isize);
- println!("{:?}", f as usize);
- println!("{:?}", f as i8);
- println!("{:?}", f as i16);
- println!("{:?}", f as i32);
- println!("{:?}", f as i64);
- println!("{:?}", f as u8);
- println!("{:?}", f as u16);
- println!("{:?}", f as u32);
- println!("{:?}", f as u64);
-
- println!("{:?}", 1 as isize);
- println!("{:?}", 1 as usize);
- println!("{:?}", 1 as *const String);
- println!("{:?}", 1 as i8);
- println!("{:?}", 1 as i16);
- println!("{:?}", 1 as i32);
- println!("{:?}", 1 as i64);
- println!("{:?}", 1 as u8);
- println!("{:?}", 1 as u16);
- println!("{:?}", 1 as u32);
- println!("{:?}", 1 as u64);
- println!("{:?}", 1 as f32);
- println!("{:?}", 1 as f64);
-
- println!("{:?}", 1_usize as isize);
- println!("{:?}", 1_usize as usize);
- println!("{:?}", 1_usize as *const String);
- println!("{:?}", 1_usize as i8);
- println!("{:?}", 1_usize as i16);
- println!("{:?}", 1_usize as i32);
- println!("{:?}", 1_usize as i64);
- println!("{:?}", 1_usize as u8);
- println!("{:?}", 1_usize as u16);
- println!("{:?}", 1_usize as u32);
- println!("{:?}", 1_usize as u64);
- println!("{:?}", 1_usize as f32);
- println!("{:?}", 1_usize as f64);
-
- println!("{:?}", 1i8 as isize);
- println!("{:?}", 1i8 as usize);
- println!("{:?}", 1i8 as *const String);
- println!("{:?}", 1i8 as i8);
- println!("{:?}", 1i8 as i16);
- println!("{:?}", 1i8 as i32);
- println!("{:?}", 1i8 as i64);
- println!("{:?}", 1i8 as u8);
- println!("{:?}", 1i8 as u16);
- println!("{:?}", 1i8 as u32);
- println!("{:?}", 1i8 as u64);
- println!("{:?}", 1i8 as f32);
- println!("{:?}", 1i8 as f64);
-
- println!("{:?}", 1u8 as isize);
- println!("{:?}", 1u8 as usize);
- println!("{:?}", 1u8 as *const String);
- println!("{:?}", 1u8 as i8);
- println!("{:?}", 1u8 as i16);
- println!("{:?}", 1u8 as i32);
- println!("{:?}", 1u8 as i64);
- println!("{:?}", 1u8 as u8);
- println!("{:?}", 1u8 as u16);
- println!("{:?}", 1u8 as u32);
- println!("{:?}", 1u8 as u64);
- println!("{:?}", 1u8 as f32);
- println!("{:?}", 1u8 as f64);
-
- println!("{:?}", 1i16 as isize);
- println!("{:?}", 1i16 as usize);
- println!("{:?}", 1i16 as *const String);
- println!("{:?}", 1i16 as i8);
- println!("{:?}", 1i16 as i16);
- println!("{:?}", 1i16 as i32);
- println!("{:?}", 1i16 as i64);
- println!("{:?}", 1i16 as u8);
- println!("{:?}", 1i16 as u16);
- println!("{:?}", 1i16 as u32);
- println!("{:?}", 1i16 as u64);
- println!("{:?}", 1i16 as f32);
- println!("{:?}", 1i16 as f64);
-
- println!("{:?}", 1u16 as isize);
- println!("{:?}", 1u16 as usize);
- println!("{:?}", 1u16 as *const String);
- println!("{:?}", 1u16 as i8);
- println!("{:?}", 1u16 as i16);
- println!("{:?}", 1u16 as i32);
- println!("{:?}", 1u16 as i64);
- println!("{:?}", 1u16 as u8);
- println!("{:?}", 1u16 as u16);
- println!("{:?}", 1u16 as u32);
- println!("{:?}", 1u16 as u64);
- println!("{:?}", 1u16 as f32);
- println!("{:?}", 1u16 as f64);
-
- println!("{:?}", 1i32 as isize);
- println!("{:?}", 1i32 as usize);
- println!("{:?}", 1i32 as *const String);
- println!("{:?}", 1i32 as i8);
- println!("{:?}", 1i32 as i16);
- println!("{:?}", 1i32 as i32);
- println!("{:?}", 1i32 as i64);
- println!("{:?}", 1i32 as u8);
- println!("{:?}", 1i32 as u16);
- println!("{:?}", 1i32 as u32);
- println!("{:?}", 1i32 as u64);
- println!("{:?}", 1i32 as f32);
- println!("{:?}", 1i32 as f64);
-
- println!("{:?}", 1u32 as isize);
- println!("{:?}", 1u32 as usize);
- println!("{:?}", 1u32 as *const String);
- println!("{:?}", 1u32 as i8);
- println!("{:?}", 1u32 as i16);
- println!("{:?}", 1u32 as i32);
- println!("{:?}", 1u32 as i64);
- println!("{:?}", 1u32 as u8);
- println!("{:?}", 1u32 as u16);
- println!("{:?}", 1u32 as u32);
- println!("{:?}", 1u32 as u64);
- println!("{:?}", 1u32 as f32);
- println!("{:?}", 1u32 as f64);
-
- println!("{:?}", 1i64 as isize);
- println!("{:?}", 1i64 as usize);
- println!("{:?}", 1i64 as *const String);
- println!("{:?}", 1i64 as i8);
- println!("{:?}", 1i64 as i16);
- println!("{:?}", 1i64 as i32);
- println!("{:?}", 1i64 as i64);
- println!("{:?}", 1i64 as u8);
- println!("{:?}", 1i64 as u16);
- println!("{:?}", 1i64 as u32);
- println!("{:?}", 1i64 as u64);
- println!("{:?}", 1i64 as f32);
- println!("{:?}", 1i64 as f64);
-
- println!("{:?}", 1u64 as isize);
- println!("{:?}", 1u64 as usize);
- println!("{:?}", 1u64 as *const String);
- println!("{:?}", 1u64 as i8);
- println!("{:?}", 1u64 as i16);
- println!("{:?}", 1u64 as i32);
- println!("{:?}", 1u64 as i64);
- println!("{:?}", 1u64 as u8);
- println!("{:?}", 1u64 as u16);
- println!("{:?}", 1u64 as u32);
- println!("{:?}", 1u64 as u64);
- println!("{:?}", 1u64 as f32);
- println!("{:?}", 1u64 as f64);
-
- println!("{:?}", 1u64 as isize);
- println!("{:?}", 1u64 as usize);
- println!("{:?}", 1u64 as *const String);
- println!("{:?}", 1u64 as i8);
- println!("{:?}", 1u64 as i16);
- println!("{:?}", 1u64 as i32);
- println!("{:?}", 1u64 as i64);
- println!("{:?}", 1u64 as u8);
- println!("{:?}", 1u64 as u16);
- println!("{:?}", 1u64 as u32);
- println!("{:?}", 1u64 as u64);
- println!("{:?}", 1u64 as f32);
- println!("{:?}", 1u64 as f64);
-
- println!("{:?}", true as isize);
- println!("{:?}", true as usize);
- println!("{:?}", true as i8);
- println!("{:?}", true as i16);
- println!("{:?}", true as i32);
- println!("{:?}", true as i64);
- println!("{:?}", true as u8);
- println!("{:?}", true as u16);
- println!("{:?}", true as u32);
- println!("{:?}", true as u64);
-
- println!("{:?}", 1f32 as isize);
- println!("{:?}", 1f32 as usize);
- println!("{:?}", 1f32 as i8);
- println!("{:?}", 1f32 as i16);
- println!("{:?}", 1f32 as i32);
- println!("{:?}", 1f32 as i64);
- println!("{:?}", 1f32 as u8);
- println!("{:?}", 1f32 as u16);
- println!("{:?}", 1f32 as u32);
- println!("{:?}", 1f32 as u64);
- println!("{:?}", 1f32 as f32);
- println!("{:?}", 1f32 as f64);
-
- println!("{:?}", 1f64 as isize);
- println!("{:?}", 1f64 as usize);
- println!("{:?}", 1f64 as i8);
- println!("{:?}", 1f64 as i16);
- println!("{:?}", 1f64 as i32);
- println!("{:?}", 1f64 as i64);
- println!("{:?}", 1f64 as u8);
- println!("{:?}", 1f64 as u16);
- println!("{:?}", 1f64 as u32);
- println!("{:?}", 1f64 as u64);
- println!("{:?}", 1f64 as f32);
- println!("{:?}", 1f64 as f64);
-}
--- /dev/null
+#![crate_name = "a"]
+
+pub fn foo<T>() {}
--- /dev/null
+#![crate_name = "a"]
+
+pub fn foo<T>() { println!("hello!"); }
--- /dev/null
+#![crate_name = "b"]
+
+extern crate a;
+
+pub fn foo() { a::foo::<isize>(); }
--- /dev/null
+// ignore-msvc FIXME #31306
+
+// note that these aux-build directives must be in this order
+// aux-build:changing-crates-a1.rs
+// aux-build:changing-crates-b.rs
+// aux-build:changing-crates-a2.rs
+// normalize-stderr-test: "(crate `(\w+)`:) .*" -> "$1 $$PATH_$2"
+
+extern crate a;
+extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
+
+fn main() {}
--- /dev/null
+error[E0460]: found possibly newer version of crate `a` which `b` depends on
+ --> $DIR/changing-crates.rs:10:1
+ |
+LL | extern crate b;
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: perhaps that crate needs to be recompiled?
+ = note: the following crate versions were found:
+ crate `a`: $PATH_a
+ crate `b`: $PATH_b
+
+error: aborting due to previous error
+
+++ /dev/null
-#![feature(negative_impls)]
-
-use std::marker::Send;
-
-struct TestType;
-
-impl !TestType {}
-//~^ ERROR inherent impls cannot be negative
-
-trait TestTrait {}
-
-unsafe impl !Send for TestType {}
-//~^ ERROR negative impls cannot be unsafe
-impl !TestTrait for TestType {}
-
-struct TestType2<T>(T);
-
-impl<T> !TestType2<T> {}
-//~^ ERROR inherent impls cannot be negative
-
-unsafe impl<T> !Send for TestType2<T> {}
-//~^ ERROR negative impls cannot be unsafe
-impl<T> !TestTrait for TestType2<T> {}
-
-fn main() {}
+++ /dev/null
-error: inherent impls cannot be negative
- --> $DIR/syntax-trait-polarity.rs:7:7
- |
-LL | impl !TestType {}
- | -^^^^^^^^ inherent impl for this type
- | |
- | negative because of this
-
-error[E0198]: negative impls cannot be unsafe
- --> $DIR/syntax-trait-polarity.rs:12:13
- |
-LL | unsafe impl !Send for TestType {}
- | ------ -^^^^
- | | |
- | | negative because of this
- | unsafe because of this
-
-error: inherent impls cannot be negative
- --> $DIR/syntax-trait-polarity.rs:18:10
- |
-LL | impl<T> !TestType2<T> {}
- | -^^^^^^^^^^^^ inherent impl for this type
- | |
- | negative because of this
-
-error[E0198]: negative impls cannot be unsafe
- --> $DIR/syntax-trait-polarity.rs:21:16
- |
-LL | unsafe impl<T> !Send for TestType2<T> {}
- | ------ -^^^^
- | | |
- | | negative because of this
- | unsafe because of this
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0198`.
+++ /dev/null
-// run-pass
-// ignore-emscripten no threads support
-
-// Issue #787
-// Don't try to clean up uninitialized locals
-
-
-use std::thread;
-
-fn test_break() { loop { let _x: Box<isize> = break; } }
-
-fn test_cont() { let mut i = 0; while i < 1 { i += 1; let _x: Box<isize> = continue; } }
-
-fn test_ret() { let _x: Box<isize> = return; }
-
-fn test_panic() {
- fn f() { let _x: Box<isize> = panic!(); }
- thread::spawn(move|| f() ).join().unwrap_err();
-}
-
-fn test_panic_indirect() {
- fn f() -> ! { panic!(); }
- fn g() { let _x: Box<isize> = f(); }
- thread::spawn(move|| g() ).join().unwrap_err();
-}
-
-pub fn main() {
- test_break();
- test_cont();
- test_ret();
- test_panic();
- test_panic_indirect();
-}
|
= note: expected struct `Foo`
found struct `Box<Foo>`
+help: try dereferencing the `Box`
+ |
+LL | want_foo(*b);
+ | +
error: aborting due to previous error
--- /dev/null
+// run-pass
+// compile-flags: --test
+
+#[test]
+pub fn foo() {}
+++ /dev/null
-// run-pass
-// compile-flags: -Z thinlto -C codegen-units=2
-
-#[global_allocator]
-static A: std::alloc::System = std::alloc::System;
-
-fn main() {}
+++ /dev/null
-// run-pass
-
-// compile-flags: -Clto=thin
-// no-prefer-dynamic
-
-fn main() {
- println!("hello!");
-}
+++ /dev/null
-// compile-flags: -Z thinlto -C codegen-units=8
-
-#[inline]
-pub fn foo(b: u8) {
- b.to_string();
-}
+++ /dev/null
-// no-prefer-dynamic
-// compile-flags: -Z thinlto -C codegen-units=8 -C prefer-dynamic
-
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
-
-pub static A: u32 = 43;
-
-pub mod a {
- pub static A: u32 = 43;
-}
+++ /dev/null
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn bar() -> u32 {
- 3
-}
+++ /dev/null
-// run-pass
-
-// aux-build:dylib.rs
-
-extern crate dylib;
-
-fn main() {
- dylib::foo(1);
-}
+++ /dev/null
-// run-pass
-
-// aux-build:msvc-imp-present.rs
-// compile-flags: -Z thinlto -C codegen-units=8
-// no-prefer-dynamic
-
-// On MSVC we have a "hack" where we emit symbols that look like `_imp_$name`
-// for all exported statics. This is done because we apply `dllimport` to all
-// imported constants and this allows everything to actually link correctly.
-//
-// The ThinLTO passes aggressively remove symbols if they can, and this test
-// asserts that the ThinLTO passes don't remove these compiler-generated
-// `_imp_*` symbols. The external library that we link in here is compiled with
-// ThinLTO and multiple codegen units and has a few exported constants. Note
-// that we also namely compile the library as both a dylib and an rlib, but we
-// link the rlib to ensure that we assert those generated symbols exist.
-
-extern crate msvc_imp_present as bar;
-
-fn main() {
- println!("{}", bar::A);
-}
+++ /dev/null
-// run-pass
-
-// compile-flags: -Z thinlto -C codegen-units=8 -O
-// ignore-emscripten can't inspect instructions on emscripten
-
-// We want to assert here that ThinLTO will inline across codegen units. There's
-// not really a great way to do that in general so we sort of hack around it by
-// praying two functions go into separate codegen units and then assuming that
-// if inlining *doesn't* happen the first byte of the functions will differ.
-
-pub fn foo() -> u32 {
- bar::bar()
-}
-
-mod bar {
- pub fn bar() -> u32 {
- 3
- }
-}
-
-fn main() {
- println!("{} {}", foo(), bar::bar());
-
- unsafe {
- let foo = foo as usize as *const u8;
- let bar = bar::bar as usize as *const u8;
-
- assert_eq!(*foo, *bar);
- }
-}
+++ /dev/null
-// run-pass
-
-// compile-flags: -C codegen-units=8 -O -C lto=thin
-// aux-build:thin-lto-inlines-aux.rs
-// no-prefer-dynamic
-// ignore-emscripten can't inspect instructions on emscripten
-
-// We want to assert here that ThinLTO will inline across codegen units. There's
-// not really a great way to do that in general so we sort of hack around it by
-// praying two functions go into separate codegen units and then assuming that
-// if inlining *doesn't* happen the first byte of the functions will differ.
-
-extern crate thin_lto_inlines_aux as bar;
-
-pub fn foo() -> u32 {
- bar::bar()
-}
-
-fn main() {
- println!("{} {}", foo(), bar::bar());
-
- unsafe {
- let foo = foo as usize as *const u8;
- let bar = bar::bar as usize as *const u8;
-
- assert_eq!(*foo, *bar);
- }
-}
+++ /dev/null
-// run-pass
-
-// compile-flags: -C codegen-units=8 -Z thinlto
-// ignore-windows
-
-#![feature(linkage)]
-
-pub mod foo {
- #[linkage = "weak"]
- #[no_mangle]
- pub extern "C" fn FOO() -> i32 {
- 0
- }
-}
-
-mod bar {
- extern "C" {
- fn FOO() -> i32;
- }
-
- pub fn bar() -> i32 {
- unsafe { FOO() }
- }
-}
-
-fn main() {
- bar::bar();
-}
--- /dev/null
+// run-pass
+// ignore-emscripten no threads
+// ignore-sgx no processes
+
+use std::thread;
+use std::env;
+use std::process::Command;
+
+struct Handle(i32);
+
+impl Drop for Handle {
+ fn drop(&mut self) { panic!(); }
+}
+
+thread_local!(static HANDLE: Handle = Handle(0));
+
+fn main() {
+ let args = env::args().collect::<Vec<_>>();
+ if args.len() == 1 {
+ let out = Command::new(&args[0]).arg("test").output().unwrap();
+ let stderr = std::str::from_utf8(&out.stderr).unwrap();
+ assert!(stderr.contains("panicked at 'explicit panic'"),
+ "bad failure message:\n{}\n", stderr);
+ } else {
+ // TLS dtors are not always run on process exit
+ thread::spawn(|| {
+ HANDLE.with(|h| {
+ println!("{}", h.0);
+ });
+ }).join().unwrap();
+ }
+}
--- /dev/null
+// run-pass
+// ignore-emscripten no threads support
+
+use std::sync::mpsc::channel;
+use std::thread;
+
+pub fn main() {
+ let (tx, rx) = channel::<&'static str>();
+
+ let t = thread::spawn(move|| {
+ assert_eq!(rx.recv().unwrap(), "hello, world");
+ });
+
+ tx.send("hello, world").unwrap();
+ t.join().ok().unwrap();
+}
--- /dev/null
+// run-pass
+// ignore-emscripten no threads support
+
+use std::thread;
+use std::sync::mpsc::{channel, Receiver};
+
+fn periodical(n: isize) -> Receiver<bool> {
+ let (chan, port) = channel();
+ thread::spawn(move|| {
+ loop {
+ for _ in 1..n {
+ match chan.send(false) {
+ Ok(()) => {}
+ Err(..) => break,
+ }
+ }
+ match chan.send(true) {
+ Ok(()) => {}
+ Err(..) => break
+ }
+ }
+ });
+ return port;
+}
+
+fn integers() -> Receiver<isize> {
+ let (chan, port) = channel();
+ thread::spawn(move|| {
+ let mut i = 1;
+ loop {
+ match chan.send(i) {
+ Ok(()) => {}
+ Err(..) => break,
+ }
+ i = i + 1;
+ }
+ });
+ return port;
+}
+
+fn main() {
+ let ints = integers();
+ let threes = periodical(3);
+ let fives = periodical(5);
+ for _ in 1..100 {
+ match (ints.recv().unwrap(), threes.recv().unwrap(), fives.recv().unwrap()) {
+ (_, true, true) => println!("FizzBuzz"),
+ (_, true, false) => println!("Fizz"),
+ (_, false, true) => println!("Buzz"),
+ (i, false, false) => println!("{}", i)
+ }
+ }
+}
--- /dev/null
+// run-pass
+#![allow(unused_must_use)]
+#![allow(deprecated)]
+// ignore-emscripten no threads support
+
+use std::sync::mpsc::{TryRecvError, channel};
+use std::thread;
+
+pub fn main() {
+ let (tx, rx) = channel();
+ let t = thread::spawn(move||{
+ thread::sleep_ms(10);
+ tx.send(()).unwrap();
+ });
+ loop {
+ match rx.try_recv() {
+ Ok(()) => break,
+ Err(TryRecvError::Empty) => {}
+ Err(TryRecvError::Disconnected) => unreachable!()
+ }
+ }
+ t.join();
+}
--- /dev/null
+// run-pass
+
+#![allow(unused_must_use)]
+/*
+ This is about the simplest program that can successfully send a
+ message.
+ */
+
+use std::sync::mpsc::channel;
+
+pub fn main() {
+ let (tx, rx) = channel();
+ tx.send(42);
+ let r = rx.recv();
+ println!("{:?}", r);
+}
--- /dev/null
+// run-pass
+
+use std::thread;
+
+pub fn main() {
+ let mut i: isize = 0;
+ while i < 100 { i = i + 1; println!("{}", i); thread::yield_now(); }
+}
+++ /dev/null
-#![feature(trace_macros)]
-
-fn main() {
- trace_macros!(); //~ ERROR trace_macros! accepts only `true` or `false`
- trace_macros!(1); //~ ERROR trace_macros! accepts only `true` or `false`
- trace_macros!(ident); //~ ERROR trace_macros! accepts only `true` or `false`
- trace_macros!(for); //~ ERROR trace_macros! accepts only `true` or `false`
- trace_macros!(true,); //~ ERROR trace_macros! accepts only `true` or `false`
- trace_macros!(false 1); //~ ERROR trace_macros! accepts only `true` or `false`
-
-
- // should be fine:
- macro_rules! expando {
- ($x: ident) => { trace_macros!($x) }
- }
-
- expando!(true);
-}
+++ /dev/null
-error: trace_macros! accepts only `true` or `false`
- --> $DIR/trace_macros-format.rs:4:5
- |
-LL | trace_macros!();
- | ^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
- --> $DIR/trace_macros-format.rs:5:5
- |
-LL | trace_macros!(1);
- | ^^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
- --> $DIR/trace_macros-format.rs:6:5
- |
-LL | trace_macros!(ident);
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
- --> $DIR/trace_macros-format.rs:7:5
- |
-LL | trace_macros!(for);
- | ^^^^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
- --> $DIR/trace_macros-format.rs:8:5
- |
-LL | trace_macros!(true,);
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: trace_macros! accepts only `true` or `false`
- --> $DIR/trace_macros-format.rs:9:5
- |
-LL | trace_macros!(false 1);
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 6 previous errors
-
--- /dev/null
+// run-pass
+
+trait Foo: Fn(i32) -> i32 + Send {}
+
+impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
+
+fn wants_foo(f: Box<dyn Foo>) -> i32 {
+ f(42)
+}
+
+fn main() {
+ let f = Box::new(|x| x);
+ assert_eq!(wants_foo(f), 42);
+}
--- /dev/null
+trait Q<T:?Sized> {}
+trait Foo where u32: Q<Self> {
+ fn foo(&self);
+}
+
+impl Q<()> for u32 {}
+impl Foo for () {
+ fn foo(&self) {
+ println!("foo!");
+ }
+}
+
+fn main() {
+ let _f: Box<dyn Foo> = //~ ERROR `Foo` cannot be made into an object
+ Box::new(()); //~ ERROR `Foo` cannot be made into an object
+}
--- /dev/null
+error[E0038]: the trait `Foo` cannot be made into an object
+ --> $DIR/issue-38604.rs:14:13
+ |
+LL | let _f: Box<dyn Foo> =
+ | ^^^^^^^^^^^^ `Foo` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-38604.rs:2:22
+ |
+LL | trait Foo where u32: Q<Self> {
+ | --- ^^^^^^^ ...because it uses `Self` as a type parameter
+ | |
+ | this trait cannot be made into an object...
+
+error[E0038]: the trait `Foo` cannot be made into an object
+ --> $DIR/issue-38604.rs:15:9
+ |
+LL | Box::new(());
+ | ^^^^^^^^^^^^ `Foo` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/issue-38604.rs:2:22
+ |
+LL | trait Foo where u32: Q<Self> {
+ | --- ^^^^^^^ ...because it uses `Self` as a type parameter
+ | |
+ | this trait cannot be made into an object...
+ = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn Foo>>` for `Box<()>`
+ = note: required by cast to type `Box<dyn Foo>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
--- /dev/null
+struct Point {
+ x: f64,
+ y: f64,
+}
+
+trait ToString_ {
+ fn to_string(&self) -> String;
+}
+
+impl ToString_ for Point {
+ fn new(x: f64, y: f64) -> Point {
+ //~^ ERROR method `new` is not a member of trait `ToString_`
+ Point { x: x, y: y }
+ }
+
+ fn to_string(&self) -> String {
+ format!("({}, {})", self.x, self.y)
+ }
+}
+
+fn main() {
+ let p = Point::new(0.0, 0.0);
+ //~^ ERROR no function or associated item named `new` found for struct `Point`
+ println!("{}", p.to_string());
+}
--- /dev/null
+error[E0407]: method `new` is not a member of trait `ToString_`
+ --> $DIR/issue-3973.rs:11:5
+ |
+LL | / fn new(x: f64, y: f64) -> Point {
+LL | |
+LL | | Point { x: x, y: y }
+LL | | }
+ | |_____^ not a member of trait `ToString_`
+
+error[E0599]: no function or associated item named `new` found for struct `Point` in the current scope
+ --> $DIR/issue-3973.rs:22:20
+ |
+LL | struct Point {
+ | ------------ function or associated item `new` not found for this
+...
+LL | let p = Point::new(0.0, 0.0);
+ | ^^^ function or associated item not found in `Point`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0407, E0599.
+For more information about an error, try `rustc --explain E0407`.
--- /dev/null
+#![feature(trait_alias)]
+
+trait Svc<Req> { type Res; }
+
+trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+//~^ ERROR associated type `Res` not found for `Self`
+//~| ERROR associated type `Res` not found for `Self`
+
+fn main() {}
--- /dev/null
+error[E0220]: associated type `Res` not found for `Self`
+ --> $DIR/issue-59029-1.rs:5:52
+ |
+LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+ | ^^^ associated type `Res` not found
+
+error[E0220]: associated type `Res` not found for `Self`
+ --> $DIR/issue-59029-1.rs:5:52
+ |
+LL | trait MkSvc<Target, Req> = Svc<Target> where Self::Res: Svc<Req>;
+ | ^^^ associated type `Res` not found
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0220`.
--- /dev/null
+// check-pass
+
+pub trait ResultExt {
+ type Ok;
+ fn err_eprint_and_ignore(self) -> Option<Self::Ok>;
+}
+
+impl<O, E> ResultExt for std::result::Result<O, E>
+where
+ E: std::error::Error,
+{
+ type Ok = O;
+ fn err_eprint_and_ignore(self) -> Option<O>
+ where
+ Self: ,
+ {
+ match self {
+ Err(e) => {
+ eprintln!("{}", e);
+ None
+ }
+ Ok(o) => Some(o),
+ }
+ }
+}
+
+fn main() {}
--- /dev/null
+// Test that an object type `Box<Foo>` is not considered to implement the
+// trait `Foo`. Issue #5087.
+
+trait Foo {}
+fn take_foo<F:Foo>(f: F) {}
+fn take_object(f: Box<dyn Foo>) { take_foo(f); }
+//~^ ERROR `Box<dyn Foo>: Foo` is not satisfied
+fn main() {}
--- /dev/null
+error[E0277]: the trait bound `Box<dyn Foo>: Foo` is not satisfied
+ --> $DIR/object-does-not-impl-trait.rs:6:44
+ |
+LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
+ | -------- ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `take_foo`
+ --> $DIR/object-does-not-impl-trait.rs:5:15
+ |
+LL | fn take_foo<F:Foo>(f: F) {}
+ | ^^^ required by this bound in `take_foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+#![feature(negative_impls)]
+
+use std::marker::Send;
+
+struct TestType;
+
+impl !TestType {}
+//~^ ERROR inherent impls cannot be negative
+
+trait TestTrait {}
+
+unsafe impl !Send for TestType {}
+//~^ ERROR negative impls cannot be unsafe
+impl !TestTrait for TestType {}
+
+struct TestType2<T>(T);
+
+impl<T> !TestType2<T> {}
+//~^ ERROR inherent impls cannot be negative
+
+unsafe impl<T> !Send for TestType2<T> {}
+//~^ ERROR negative impls cannot be unsafe
+impl<T> !TestTrait for TestType2<T> {}
+
+fn main() {}
--- /dev/null
+error: inherent impls cannot be negative
+ --> $DIR/syntax-trait-polarity.rs:7:7
+ |
+LL | impl !TestType {}
+ | -^^^^^^^^ inherent impl for this type
+ | |
+ | negative because of this
+
+error[E0198]: negative impls cannot be unsafe
+ --> $DIR/syntax-trait-polarity.rs:12:13
+ |
+LL | unsafe impl !Send for TestType {}
+ | ------ -^^^^
+ | | |
+ | | negative because of this
+ | unsafe because of this
+
+error: inherent impls cannot be negative
+ --> $DIR/syntax-trait-polarity.rs:18:10
+ |
+LL | impl<T> !TestType2<T> {}
+ | -^^^^^^^^^^^^ inherent impl for this type
+ | |
+ | negative because of this
+
+error[E0198]: negative impls cannot be unsafe
+ --> $DIR/syntax-trait-polarity.rs:21:16
+ |
+LL | unsafe impl<T> !Send for TestType2<T> {}
+ | ------ -^^^^
+ | | |
+ | | negative because of this
+ | unsafe because of this
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0198`.
+++ /dev/null
-// run-pass
-
-#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
-
-trait Specializable { type Output; }
-
-impl<T> Specializable for T {
- default type Output = u16;
-}
-
-fn main() {
- unsafe {
- std::mem::transmute::<u16, <() as Specializable>::Output>(0);
- }
-}
+++ /dev/null
-warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
- --> $DIR/transmute-specialization.rs:3:12
- |
-LL | #![feature(specialization)]
- | ^^^^^^^^^^^^^^
- |
- = note: `#[warn(incomplete_features)]` on by default
- = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
- = help: consider using `min_specialization` instead, which is more stable and complete
-
-warning: 1 warning emitted
-
+++ /dev/null
-// run-pass
-
-#![allow(unused_must_use)]
-/*
- This is about the simplest program that can successfully send a
- message.
- */
-
-use std::sync::mpsc::channel;
-
-pub fn main() {
- let (tx, rx) = channel();
- tx.send(42);
- let r = rx.recv();
- println!("{:?}", r);
-}
--- /dev/null
+// run-pass
+#![allow(unreachable_code)]
+// compile-flags: --edition 2018
+
+#![feature(try_blocks)]
+
+fn main() {
+ let mut a = 0;
+ let () = {
+ let _: Result<(), ()> = try {
+ let _ = Err(())?;
+ return
+ };
+ a += 1;
+ };
+ a += 2;
+ assert_eq!(a, 3);
+}
+++ /dev/null
-// compile-flags: --edition 2018
-fn foo() -> Result<(), ()> {
- Ok(try!()); //~ ERROR use of deprecated `try` macro
- Ok(try!(Ok(()))) //~ ERROR use of deprecated `try` macro
-}
-
-fn main() {
- let _ = foo();
-}
+++ /dev/null
-error: use of deprecated `try` macro
- --> $DIR/try-macro-suggestion.rs:3:8
- |
-LL | Ok(try!());
- | ^^^^^^
- |
- = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
-help: you can still access the deprecated `try!()` macro using the "raw identifier" syntax
- |
-LL | Ok(r#try!());
- | ++
-
-error: use of deprecated `try` macro
- --> $DIR/try-macro-suggestion.rs:4:8
- |
-LL | Ok(try!(Ok(())))
- | ^^^^^^^^^^^^
- |
- = note: in the 2018 edition `try` is a reserved keyword, and the `try!()` macro is deprecated
-help: you can use the `?` operator instead
- |
-LL - Ok(try!(Ok(())))
-LL + Ok(Ok(())?)
- |
-help: alternatively, you can still access the deprecated `try!()` macro using the "raw identifier" syntax
- |
-LL | Ok(r#try!(Ok(())))
- | ++
-
-error: aborting due to 2 previous errors
-
--- /dev/null
+// check-pass
+// compile-flags: -Z unpretty=hir
+
+#![feature(type_alias_impl_trait)]
+
+trait Animal {}
+
+fn main() {
+ pub type ServeFut = impl Animal;
+}
--- /dev/null
+// check-pass
+// compile-flags: -Z unpretty=hir
+
+#![feature(type_alias_impl_trait)]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+
+trait Animal { }
+
+fn main() {
+ pub type ServeFut = /*impl Trait*/;
+ }
--- /dev/null
+// Regression test for #30225, which was an ICE that would trigger as
+// a result of a poor interaction between trait result caching and
+// type inference. Specifically, at that time, unification could cause
+// unrelated type variables to become instantiated, if subtyping
+// relationships existed. These relationships are now propagated
+// through obligations and hence everything works out fine.
+
+trait Foo<U,V> : Sized {
+ fn foo(self, u: Option<U>, v: Option<V>) {}
+}
+
+struct A;
+struct B;
+
+impl Foo<A, B> for () {} // impl A
+impl Foo<u32, u32> for u32 {} // impl B, creating ambiguity
+
+fn toxic() {
+ // cache the resolution <() as Foo<$0,$1>> = impl A
+ let u = None;
+ let v = None;
+ Foo::foo((), u, v);
+}
+
+fn bomb() {
+ let mut u = None; // type is Option<$0>
+ let mut v = None; // type is Option<$1>
+ let mut x = None; // type is Option<$2>
+
+ Foo::foo(x.unwrap(),u,v); // register <$2 as Foo<$0, $1>>
+ u = v; // mark $0 and $1 in a subtype relationship
+ //~^ ERROR mismatched types
+ x = Some(()); // set $2 = (), allowing impl selection
+ // to proceed for <() as Foo<$0, $1>> = impl A.
+ // kaboom, this *used* to trigge an ICE
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-30225.rs:31:9
+ |
+LL | u = v; // mark $0 and $1 in a subtype relationship
+ | ^ expected struct `A`, found struct `B`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+#![crate_type="lib"]
+
+
+pub trait A {
+ fn a(&self) {}
+}
+impl A for () {}
--- /dev/null
+#![crate_type="lib"]
+
+pub extern crate xcrate_issue_43189_a;
--- /dev/null
+#![crate_type="lib"]
+
+pub extern crate core;
--- /dev/null
+// edition:2018
+#![crate_type="lib"]
+#![crate_name="xcrate_issue_61711_b"]
+pub struct Struct;
+pub use crate as alias;
--- /dev/null
+// Issue 46112: An extern crate pub re-exporting libcore was causing
+// paths rooted from `std` to be misrendered in the diagnostic output.
+
+// ignore-windows
+// aux-build:xcrate-issue-43189-a.rs
+// aux-build:xcrate-issue-43189-b.rs
+
+extern crate xcrate_issue_43189_b;
+fn main() {
+ ().a();
+ //~^ ERROR no method named `a` found
+}
--- /dev/null
+error[E0599]: no method named `a` found for unit type `()` in the current scope
+ --> $DIR/issue-43189.rs:10:8
+ |
+LL | ().a();
+ | ^ method not found in `()`
+ |
+ ::: $DIR/auxiliary/xcrate-issue-43189-a.rs:5:8
+ |
+LL | fn a(&self) {}
+ | - the method is available for `()` here
+ |
+ = help: items from traits can only be used if the trait is in scope
+help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+ |
+LL | use xcrate_issue_43189_b::xcrate_issue_43189_a::A;
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
--- /dev/null
+// Issue 46112: An extern crate pub re-exporting libcore was causing
+// paths rooted from `std` to be misrendered in the diagnostic output.
+
+// ignore-windows
+// aux-build:xcrate-issue-46112-rexport-core.rs
+
+extern crate xcrate_issue_46112_rexport_core;
+fn test(r: Result<Option<()>, &'static str>) { }
+fn main() { test(Ok(())); }
+//~^ mismatched types
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/issue-46112.rs:9:21
+ |
+LL | fn main() { test(Ok(())); }
+ | ^^
+ | |
+ | expected enum `Option`, found `()`
+ | help: try using a variant of the expected enum: `Some(())`
+ |
+ = note: expected enum `Option<()>`
+ found unit type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// Issue 61711: A crate pub re-exporting `crate` was causing an
+// infinite loop.
+
+// edition:2018
+// aux-build:xcrate-issue-61711-b.rs
+// compile-flags:--extern xcrate_issue_61711_b
+
+// build-pass
+
+fn f<F: Fn(xcrate_issue_61711_b::Struct)>(_: F) { }
+fn main() { }
--- /dev/null
+// edition:2021
+
+mod m {
+ pub struct S { foo: i32 }
+ impl S {
+ pub fn foo(&self) -> i32 { 42 }
+ }
+}
+
+fn bar(s: &m::S) {
+ || s.foo() + s.foo; //~ ERROR E0616
+}
+
+fn main() {}
--- /dev/null
+error[E0616]: field `foo` of struct `S` is private
+ --> $DIR/issue-90483-inaccessible-field-adjustment.rs:11:18
+ |
+LL | || s.foo() + s.foo;
+ | ^^^ private field
+ |
+help: a method `foo` also exists, call it with parentheses
+ |
+LL | || s.foo() + s.foo();
+ | ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0616`.
+++ /dev/null
-// run-pass
-
-pub fn main() {
- let a = 1;
- let a_neg: i8 = -a;
- println!("{}", a_neg);
-
- let b = 1;
- let b_neg: i16 = -b;
- println!("{}", b_neg);
-
- let c = 1;
- let c_neg: i32 = -c;
- println!("{}", c_neg);
-
- let d = 1;
- let d_neg: i64 = -d;
- println!("{}", d_neg);
-
- let e = 1;
- let e_neg: isize = -e;
- println!("{}", e_neg);
-}
--- /dev/null
+// run-pass
+// Tests multiple free variables being passed by value into an unboxed
+// once closure as an optimization by codegen. This used to hit an
+// incorrect assert.
+
+fn main() {
+ let x = 2u8;
+ let y = 3u8;
+ assert_eq!((move || x + y)(), 5);
+}
| ------ ------ ^ ...but data from `y` flows into `x` here
| |
| these two types are declared with different lifetimes...
+ |
+ = note: each elided lifetime in input position becomes a distinct lifetime
+help: consider introducing a named lifetime parameter
+ |
+LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }
+ | ++++ ~~ ~~
error: aborting due to previous error
+++ /dev/null
-// edition:2018
-
-#![deny(unused_extern_crates)]
-#![feature(test, rustc_private, crate_visibility_modifier)]
-
-extern crate libc;
-//~^ ERROR unused extern crate
-//~| HELP remove
-extern crate libc as x;
-//~^ ERROR unused extern crate
-//~| HELP remove
-
-extern crate proc_macro;
-
-#[macro_use]
-extern crate test;
-
-pub extern crate test as y;
-
-pub extern crate alloc;
-
-pub(crate) extern crate alloc as a;
-
-crate extern crate alloc as b;
-
-mod foo {
- pub(in crate::foo) extern crate alloc as c;
-
- pub(super) extern crate alloc as d;
-
- extern crate libc;
- //~^ ERROR unused extern crate
- //~| HELP remove
-
- extern crate libc as x;
- //~^ ERROR unused extern crate
- //~| HELP remove
-
- pub extern crate test;
-
- pub extern crate test as y;
-
- mod bar {
- extern crate libc;
- //~^ ERROR unused extern crate
- //~| HELP remove
-
- extern crate libc as x;
- //~^ ERROR unused extern crate
- //~| HELP remove
-
- pub(in crate::foo::bar) extern crate alloc as e;
-
- fn dummy() {
- e::string::String::new();
- }
- }
-
- fn dummy() {
- c::string::String::new();
- d::string::String::new();
- }
-}
-
-
-fn main() {
- a::string::String::new();
- b::string::String::new();
-
- proc_macro::TokenStream::new();
-}
+++ /dev/null
-error: unused extern crate
- --> $DIR/unnecessary-extern-crate.rs:6:1
- |
-LL | extern crate libc;
- | ^^^^^^^^^^^^^^^^^^ help: remove it
- |
-note: the lint level is defined here
- --> $DIR/unnecessary-extern-crate.rs:3:9
- |
-LL | #![deny(unused_extern_crates)]
- | ^^^^^^^^^^^^^^^^^^^^
-
-error: unused extern crate
- --> $DIR/unnecessary-extern-crate.rs:9:1
- |
-LL | extern crate libc as x;
- | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: unused extern crate
- --> $DIR/unnecessary-extern-crate.rs:31:5
- |
-LL | extern crate libc;
- | ^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: unused extern crate
- --> $DIR/unnecessary-extern-crate.rs:35:5
- |
-LL | extern crate libc as x;
- | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: unused extern crate
- --> $DIR/unnecessary-extern-crate.rs:44:9
- |
-LL | extern crate libc;
- | ^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: unused extern crate
- --> $DIR/unnecessary-extern-crate.rs:48:9
- |
-LL | extern crate libc as x;
- | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove it
-
-error: aborting due to 6 previous errors
-
+++ /dev/null
-// build-pass (FIXME(62277): could be check-pass?)
-
-#![feature(rustc_attrs)]
-
-#[rustc_dummy(a b c d)]
-#[rustc_dummy[a b c d]]
-#[rustc_dummy{a b c d}]
-fn main() {}
--- /dev/null
+pub struct X([u8]);
+
+pub static Y: &'static X = {
+ const Y: &'static [u8] = b"";
+ &X(*Y)
+ //~^ ERROR E0277
+};
+
+fn main() {}
--- /dev/null
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+ --> $DIR/issue-30355.rs:5:8
+ |
+LL | &X(*Y)
+ | ^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `Sized` is not implemented for `[u8]`
+ = note: all function arguments must have a statically known size
+ = help: unsized fn params are gated as an unstable feature
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
-#![feature(relaxed_struct_unsize)]
// run-pass
// Test that we allow unsizing even if there is an unchanged param in the
// field getting unsized.
// --extern-location with a raw reference
// aux-crate:bar=bar.rs
-// compile-flags:--extern-location bar
+// compile-flags:--extern-location bar -Zunstable-options
#![warn(unused_crate_dependencies)]
+++ /dev/null
-// run-pass
-
-#![allow(dead_code)]
-// compile-flags:-D improper-ctypes
-
-// pretty-expanded FIXME #23616
-#![allow(improper_ctypes)]
-
-mod libc {
- extern "C" {
- pub fn malloc(size: isize) -> *const u8;
- }
-}
-
-pub fn main() {}
+++ /dev/null
-// run-pass
-
-use std::thread;
-
-pub fn main() {
- let mut i: isize = 0;
- while i < 100 { i = i + 1; println!("{}", i); thread::yield_now(); }
-}
-Subproject commit 6c1bc24b8b49d4bc965f67d7037906dc199c72b7
+Subproject commit 94ca096afbf25f670e76e07dca754fcfe27134be
+++ /dev/null
-[alias]
-uitest = "test --test compile-test"
-dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --"
-lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml -- "
-collect-metadata = "test --test dogfood --features metadata-collector-lint -- run_metadata_collection_lint --ignored"
-
-[build]
-# -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests
-rustflags = ["-Zunstable-options", "-Zbinary-dep-depinfo"]
-target-dir = "target"
--- /dev/null
+[alias]
+uitest = "test --test compile-test"
+dev = "run --package clippy_dev --bin clippy_dev --manifest-path clippy_dev/Cargo.toml --"
+lintcheck = "run --package lintcheck --bin lintcheck --manifest-path lintcheck/Cargo.toml -- "
+collect-metadata = "test --test dogfood --features metadata-collector-lint -- run_metadata_collection_lint --ignored"
+
+[build]
+# -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests
+rustflags = ["-Zunstable-options", "-Zbinary-dep-depinfo"]
+target-dir = "target"
if [[ -n $TAG_NAME ]]; then
echo "Save the doc for the current tag ($TAG_NAME) and point stable/ to it"
cp -Tr out/master "out/$TAG_NAME"
- ln -sf "$TAG_NAME" out/stable
+ rm -f out/stable
+ ln -s "$TAG_NAME" out/stable
fi
if [[ $BETA = "true" ]]; then
## Unreleased / In Rust Nightly
-[7bfc26e...master](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...master)
+[b7f3f7f...master](https://github.com/rust-lang/rust-clippy/compare/b7f3f7f...master)
+
+## Rust 1.57
+
+Current beta, release 2021-12-02
+
+[7bfc26e...b7f3f7f](https://github.com/rust-lang/rust-clippy/compare/7bfc26e...b7f3f7f)
+
+### New Lints
+
+* [`negative_feature_names`]
+ [#7539](https://github.com/rust-lang/rust-clippy/pull/7539)
+* [`redundant_feature_names`]
+ [#7539](https://github.com/rust-lang/rust-clippy/pull/7539)
+* [`mod_module_files`]
+ [#7543](https://github.com/rust-lang/rust-clippy/pull/7543)
+* [`self_named_module_files`]
+ [#7543](https://github.com/rust-lang/rust-clippy/pull/7543)
+* [`manual_split_once`]
+ [#7565](https://github.com/rust-lang/rust-clippy/pull/7565)
+* [`derivable_impls`]
+ [#7570](https://github.com/rust-lang/rust-clippy/pull/7570)
+* [`needless_option_as_deref`]
+ [#7596](https://github.com/rust-lang/rust-clippy/pull/7596)
+* [`iter_not_returning_iterator`]
+ [#7610](https://github.com/rust-lang/rust-clippy/pull/7610)
+* [`same_name_method`]
+ [#7653](https://github.com/rust-lang/rust-clippy/pull/7653)
+* [`manual_assert`] [#7669](https://github.com/rust-lang/rust-clippy/pull/7669)
+* [`non_send_fields_in_send_ty`]
+ [#7709](https://github.com/rust-lang/rust-clippy/pull/7709)
+* [`equatable_if_let`]
+ [#7762](https://github.com/rust-lang/rust-clippy/pull/7762)
+
+### Moves and Deprecations
+
+* Move [`shadow_unrelated`] to `restriction`
+ [#7338](https://github.com/rust-lang/rust-clippy/pull/7338)
+* Move [`option_if_let_else`] to `nursery`
+ [#7568](https://github.com/rust-lang/rust-clippy/pull/7568)
+* Move [`branches_sharing_code`] to `nursery`
+ [#7595](https://github.com/rust-lang/rust-clippy/pull/7595)
+* Rename `if_let_some_result` to [`match_result_ok`] which now also handles
+ `while let` cases [#7608](https://github.com/rust-lang/rust-clippy/pull/7608)
+* Move [`many_single_char_names`] to `pedantic`
+ [#7671](https://github.com/rust-lang/rust-clippy/pull/7671)
+* Move [`float_cmp`] to `pedantic`
+ [#7692](https://github.com/rust-lang/rust-clippy/pull/7692)
+* Rename `box_vec` to [`box_collection`] and lint on more general cases
+ [#7693](https://github.com/rust-lang/rust-clippy/pull/7693)
+* Uplift `invalid_atomic_ordering` to rustc
+ [rust-lang/rust#84039](https://github.com/rust-lang/rust/pull/84039)
+
+### Enhancements
+
+* Rewrite the `shadow*` lints, so that they find a lot more shadows and are not
+ limited to certain patterns
+ [#7338](https://github.com/rust-lang/rust-clippy/pull/7338)
+* The `avoid-breaking-exported-api` configuration now also works for
+ [`box_collection`], [`redundant_allocation`], [`rc_buffer`], [`vec_box`],
+ [`option_option`], [`linkedlist`], [`rc_mutex`]
+ [#7560](https://github.com/rust-lang/rust-clippy/pull/7560)
+* [`unnecessary_unwrap`]: Now also checks for `expect`s
+ [#7584](https://github.com/rust-lang/rust-clippy/pull/7584)
+* [`disallowed_method`]: Allow adding a reason that will be displayed with the
+ lint message
+ [#7621](https://github.com/rust-lang/rust-clippy/pull/7621)
+* [`approx_constant`]: Now checks the MSRV for `LOG10_2` and `LOG2_10`
+ [#7629](https://github.com/rust-lang/rust-clippy/pull/7629)
+* [`approx_constant`]: Add `TAU`
+ [#7642](https://github.com/rust-lang/rust-clippy/pull/7642)
+* [`needless_borrow`]: Now also lints on needless mutable borrows
+ [#7657](https://github.com/rust-lang/rust-clippy/pull/7657)
+* [`missing_safety_doc`]: Now also lints on unsafe traits
+ [#7734](https://github.com/rust-lang/rust-clippy/pull/7734)
+
+### False Positive Fixes
+
+* [`manual_map`]: No longer lints when the option is borrowed in the match and
+ also consumed in the arm
+ [#7531](https://github.com/rust-lang/rust-clippy/pull/7531)
+* [`filter_next`]: No longer lints if `filter` method is not the
+ `Iterator::filter` method
+ [#7562](https://github.com/rust-lang/rust-clippy/pull/7562)
+* [`manual_flatten`]: No longer lints if expression is used after `if let`
+ [#7566](https://github.com/rust-lang/rust-clippy/pull/7566)
+* [`option_if_let_else`]: Multiple fixes
+ [#7573](https://github.com/rust-lang/rust-clippy/pull/7573)
+ * `break` and `continue` statements local to the would-be closure are
+ allowed
+ * Don't lint in const contexts
+ * Don't lint when yield expressions are used
+ * Don't lint when the captures made by the would-be closure conflict with
+ the other branch
+ * Don't lint when a field of a local is used when the type could be
+ potentially moved from
+ * In some cases, don't lint when scrutinee expression conflicts with the
+ captures of the would-be closure
+* [`redundant_allocation`]: No longer lints on `Box<Box<dyn T>>` which replaces
+ wide pointers with thin pointers
+ [#7592](https://github.com/rust-lang/rust-clippy/pull/7592)
+* [`bool_assert_comparison`]: No longer lints on types that do not implement the
+ `Not` trait with `Output = bool`
+ [#7605](https://github.com/rust-lang/rust-clippy/pull/7605)
+* [`mut_range_bound`]: No longer lints on range bound mutations, that are
+ immediately followed by a `break;`
+ [#7607](https://github.com/rust-lang/rust-clippy/pull/7607)
+* [`mutable_key_type`]: Improve accuracy and document remaining false positives
+ and false negatives
+ [#7640](https://github.com/rust-lang/rust-clippy/pull/7640)
+* [`redundant_closure`]: Rewrite the lint to fix various false positives and
+ false negatives [#7661](https://github.com/rust-lang/rust-clippy/pull/7661)
+* [`large_enum_variant`]: No longer wrongly identifies the second largest
+ variant [#7677](https://github.com/rust-lang/rust-clippy/pull/7677)
+* [`needless_return`]: No longer lints on let-else expressions
+ [#7685](https://github.com/rust-lang/rust-clippy/pull/7685)
+* [`suspicious_else_formatting`]: No longer lints in proc-macros
+ [#7707](https://github.com/rust-lang/rust-clippy/pull/7707)
+* [`excessive_precision`]: No longer lints when in some cases the float was
+ already written in the shortest form
+ [#7722](https://github.com/rust-lang/rust-clippy/pull/7722)
+* [`doc_markdown`]: No longer lints on intra-doc links
+ [#7772](https://github.com/rust-lang/rust-clippy/pull/7772)
+
+### Suggestion Fixes/Improvements
+
+* [`unnecessary_operation`]: Recommend using an `assert!` instead of using a
+ function call in an indexing operation
+ [#7453](https://github.com/rust-lang/rust-clippy/pull/7453)
+* [`manual_split_once`]: Produce semantically equivalent suggestion when
+ `rsplitn` is used [#7663](https://github.com/rust-lang/rust-clippy/pull/7663)
+* [`while_let_on_iterator`]: Produce correct suggestion when using `&mut`
+ [#7690](https://github.com/rust-lang/rust-clippy/pull/7690)
+* [`manual_assert`]: No better handles complex conditions
+ [#7741](https://github.com/rust-lang/rust-clippy/pull/7741)
+* Correctly handle signs in exponents in numeric literals lints
+ [#7747](https://github.com/rust-lang/rust-clippy/pull/7747)
+* [`suspicious_map`]: Now also suggests to use `inspect` as an alternative
+ [#7770](https://github.com/rust-lang/rust-clippy/pull/7770)
+* Drop exponent from suggestion if it is 0 in numeric literals lints
+ [#7774](https://github.com/rust-lang/rust-clippy/pull/7774)
+
+### ICE Fixes
+
+* [`implicit_hasher`]
+ [#7761](https://github.com/rust-lang/rust-clippy/pull/7761)
+
+### Others
+
+* Clippy now uses the 2021
+ [Edition!](https://www.youtube.com/watch?v=q0aNduqb2Ro)
+ [#7664](https://github.com/rust-lang/rust-clippy/pull/7664)
## Rust 1.56
-Current beta, release 2021-10-21
+Current stable, released 2021-10-21
[74d1561...7bfc26e](https://github.com/rust-lang/rust-clippy/compare/74d1561...7bfc26e)
* [`unnested_or_patterns`]: Removed `or_patterns` feature gate in the code
example [#7507](https://github.com/rust-lang/rust-clippy/pull/7507)
-### New Lints
-
-* Renamed Lint: `if_let_some_result` is now called [`match_result_ok`]. Now also handles `while let` case.
-
## Rust 1.55
-Current stable, released 2021-09-09
+Released 2021-09-09
[3ae8faf...74d1561](https://github.com/rust-lang/rust-clippy/compare/3ae8faf...74d1561)
[`if_let_redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_redundant_pattern_matching
[`if_not_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_not_else
[`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
-[`if_then_panic`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_panic
[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
[`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
[`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports
[`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
+[`manual_assert`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert
[`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
[`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map
[`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map
[`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors
[`self_named_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_module_files
[`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
+[`separated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#separated_literal_suffix
[`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
[`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
[`shadow_same`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_same
[`string_extend_chars`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_extend_chars
[`string_from_utf8_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_from_utf8_as_bytes
[`string_lit_as_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_lit_as_bytes
+[`string_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_slice
[`string_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_to_string
[`strlen_on_c_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#strlen_on_c_strings
[`struct_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#struct_excessive_bools
[`uninit_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_vec
[`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg
[`unit_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_cmp
+[`unit_hash`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_hash
[`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_return_expecting_ord
[`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
[`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map
2. Checkout the commit from the latest available nightly. You can get it using `rustup check`.
3. Sync the changes to the rust-copy of Clippy to your Clippy fork:
```bash
- # Make sure to change `your-github-name` to your github name in the following command
+ # Make sure to change `your-github-name` to your github name in the following command. Also be
+ # sure to either use a net-new branch, e.g. `sync-from-rust`, or delete the branch beforehand
+ # because changes cannot be fast forwarded
git subtree push -P src/tools/clippy git@github.com:your-github-name/rust-clippy sync-from-rust
```
[dependencies]
clippy_lints = { version = "0.1", path = "clippy_lints" }
-semver = "0.11"
+semver = "1.0"
rustc_tools_util = { version = "0.2", path = "rustc_tools_util" }
tempfile = { version = "3.2", optional = true }
[dev-dependencies]
-cargo_metadata = "0.12"
-compiletest_rs = { version = "0.7", features = ["tmp"] }
+cargo_metadata = "0.14"
+compiletest_rs = { version = "0.7.1", features = ["tmp"] }
tester = "0.9"
regex = "1.5"
# This is used by the `collect-metadata` alias.
};
create_lint(&lint, msrv).context("Unable to create lint implementation")?;
- create_test(&lint).context("Unable to create a test for the new lint")
+ create_test(&lint).context("Unable to create a test for the new lint")?;
+ add_lint(&lint, msrv).context("Unable to add lint to clippy_lints/src/lib.rs")
}
fn create_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
}
}
+fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
+ let path = "clippy_lints/src/lib.rs";
+ let mut lib_rs = fs::read_to_string(path).context("reading")?;
+
+ let comment_start = lib_rs.find("// add lints here,").expect("Couldn't find comment");
+
+ let new_lint = if enable_msrv {
+ format!(
+ "store.register_{lint_pass}_pass(move || Box::new({module_name}::{camel_name}::new(msrv)));\n ",
+ lint_pass = lint.pass,
+ module_name = lint.name,
+ camel_name = to_camel_case(lint.name),
+ )
+ } else {
+ format!(
+ "store.register_{lint_pass}_pass(|| Box::new({module_name}::{camel_name}));\n ",
+ lint_pass = lint.pass,
+ module_name = lint.name,
+ camel_name = to_camel_case(lint.name),
+ )
+ };
+
+ lib_rs.insert_str(comment_start, &new_lint);
+
+ fs::write(path, lib_rs).context("writing")
+}
+
fn write_file<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> {
fn inner(path: &Path, contents: &[u8]) -> io::Result<()> {
OpenOptions::new()
};
let lint_name = lint.name;
- let pass_name = lint.pass;
let category = lint.category;
let name_camel = to_camel_case(lint.name);
let name_upper = lint_name.to_uppercase();
extract_msrv_attr!({context_import});
}}
- // TODO: Register the lint pass in `clippy_lints/src/lib.rs`,
- // e.g. store.register_{pass_name}_pass(move || Box::new({module_name}::{name_camel}::new(msrv)));
// TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed.
// TODO: Add MSRV test to `tests/ui/min_rust_version_attr.rs`.
// TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs`
"},
pass_type = pass_type,
pass_lifetimes = pass_lifetimes,
- pass_name = pass_name,
name_upper = name_upper,
name_camel = name_camel,
- module_name = lint_name,
context_import = context_import,
)
} else {
declare_lint_pass!({name_camel} => [{name_upper}]);
impl {pass_type}{pass_lifetimes} for {name_camel} {{}}
- //
- // TODO: Register the lint pass in `clippy_lints/src/lib.rs`,
- // e.g. store.register_{pass_name}_pass(|| Box::new({module_name}::{name_camel}));
"},
pass_type = pass_type,
pass_lifetimes = pass_lifetimes,
- pass_name = pass_name,
name_upper = name_upper,
name_camel = name_camel,
- module_name = lint_name,
)
});
edition = "2021"
[dependencies]
-cargo_metadata = "0.12"
+cargo_metadata = "0.14"
clippy_utils = { path = "../clippy_utils" }
if_chain = "1.0"
itertools = "0.10"
toml = "0.5"
unicode-normalization = "0.1"
unicode-script = { version = "0.5", default-features = false }
-semver = "0.11"
+semver = "1.0"
rustc-semver = "1.1"
# NOTE: cargo requires serde feat in its url dep
# see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864>
+use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::span_lint;
+use clippy_utils::expr_or_init;
use clippy_utils::ty::is_isize_or_usize;
-use rustc_hir::Expr;
+use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, FloatTy, Ty};
use super::{utils, CAST_POSSIBLE_TRUNCATION};
-pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
+fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
+ if let Some((Constant::Int(c), _)) = constant(cx, cx.typeck_results(), expr) {
+ Some(c)
+ } else {
+ None
+ }
+}
+
+fn get_constant_bits(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u64> {
+ constant_int(cx, expr).map(|c| u64::from(128 - c.leading_zeros()))
+}
+
+fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: bool) -> u64 {
+ match expr_or_init(cx, expr).kind {
+ ExprKind::Cast(inner, _) => apply_reductions(cx, nbits, inner, signed),
+ ExprKind::Block(block, _) => block.expr.map_or(nbits, |e| apply_reductions(cx, nbits, e, signed)),
+ ExprKind::Binary(op, left, right) => match op.node {
+ BinOpKind::Div => {
+ apply_reductions(cx, nbits, left, signed)
+ - (if signed {
+ 0 // let's be conservative here
+ } else {
+ // by dividing by 1, we remove 0 bits, etc.
+ get_constant_bits(cx, right).map_or(0, |b| b.saturating_sub(1))
+ })
+ },
+ BinOpKind::Rem | BinOpKind::BitAnd => get_constant_bits(cx, right)
+ .unwrap_or(u64::max_value())
+ .min(apply_reductions(cx, nbits, left, signed)),
+ BinOpKind::Shr => {
+ apply_reductions(cx, nbits, left, signed)
+ - constant_int(cx, right).map_or(0, |s| u64::try_from(s).expect("shift too high"))
+ },
+ _ => nbits,
+ },
+ ExprKind::MethodCall(method, _, [left, right], _) => {
+ if signed {
+ return nbits;
+ }
+ let max_bits = if method.ident.as_str() == "min" {
+ get_constant_bits(cx, right)
+ } else {
+ None
+ };
+ apply_reductions(cx, nbits, left, signed).min(max_bits.unwrap_or(u64::max_value()))
+ },
+ ExprKind::MethodCall(method, _, [_, lo, hi], _) => {
+ if method.ident.as_str() == "clamp" {
+ //FIXME: make this a diagnostic item
+ if let (Some(lo_bits), Some(hi_bits)) = (get_constant_bits(cx, lo), get_constant_bits(cx, hi)) {
+ return lo_bits.max(hi_bits);
+ }
+ }
+ nbits
+ },
+ ExprKind::MethodCall(method, _, [_value], _) => {
+ if method.ident.name.as_str() == "signum" {
+ 0 // do not lint if cast comes from a `signum` function
+ } else {
+ nbits
+ }
+ },
+ _ => nbits,
+ }
+}
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
let msg = match (cast_from.is_integral(), cast_to.is_integral()) {
(true, true) => {
- let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
+ let from_nbits = apply_reductions(
+ cx,
+ utils::int_ty_to_nbits(cast_from, cx.tcx),
+ cast_expr,
+ cast_from.is_signed(),
+ );
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
let (should_lint, suffix) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) {
fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to);
fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
- cast_possible_truncation::check(cx, expr, cast_from, cast_to);
+ cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
cast_possible_wrap::check(cx, expr, cast_from, cast_to);
cast_precision_loss::check(cx, expr, cast_from, cast_to);
cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to);
+// NOTE: if you add a deprecated lint in this file, please add a corresponding test in
+// tests/ui/deprecated.rs
+
/// This struct fakes the `Lint` declaration that is usually created by `declare_lint!`. This
/// enables the simple extraction of the metadata without changing the current deprecation
/// declaration.
target_mut,
},
));
- }
+ },
_ => (),
}
},
use clippy_utils::attrs::is_doc_hidden;
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_note};
-use clippy_utils::source::first_line_of_span;
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg};
+use clippy_utils::source::{first_line_of_span, snippet_with_applicability};
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{is_entrypoint_fn, is_expn_of, match_panic_def_id, method_chain_args, return_ty};
use if_chain::if_chain;
use itertools::Itertools;
-use rustc_ast::ast::{Async, AttrKind, Attribute, FnKind, FnRetTy, ItemKind};
+use rustc_ast::ast::{Async, AttrKind, Attribute, Fn, FnRetTy, ItemKind};
use rustc_ast::token::CommentKind;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::EmitterWriter;
-use rustc_errors::Handler;
+use rustc_errors::{Applicability, Handler};
use rustc_hir as hir;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::{AnonConst, Expr, ExprKind, QPath};
/// content are not linted.
///
/// In addition, when writing documentation comments, including `[]` brackets
- /// inside a link text would trip the parser. Therfore, documenting link with
+ /// inside a link text would trip the parser. Therefore, documenting link with
/// `[`SmallVec<[T; INLINE_CAPACITY]>`]` and then [`SmallVec<[T; INLINE_CAPACITY]>`]: SmallVec
/// would fail.
///
// text "http://example.com" by pulldown-cmark
continue;
}
- headers.safety |= in_heading && text.trim() == "Safety";
- headers.errors |= in_heading && text.trim() == "Errors";
- headers.panics |= in_heading && text.trim() == "Panics";
+ let trimmed_text = text.trim();
+ headers.safety |= in_heading && trimmed_text == "Safety";
+ headers.safety |= in_heading && trimmed_text == "Implementation safety";
+ headers.safety |= in_heading && trimmed_text == "Implementation Safety";
+ headers.errors |= in_heading && trimmed_text == "Errors";
+ headers.panics |= in_heading && trimmed_text == "Panics";
if in_code {
if is_rust {
let edition = edition.unwrap_or_else(|| cx.tcx.sess.edition());
| ItemKind::ExternCrate(..)
| ItemKind::ForeignMod(..) => return false,
// We found a main function ...
- ItemKind::Fn(box FnKind(_, sig, _, Some(block))) if item.ident.name == sym::main => {
+ ItemKind::Fn(box Fn { sig, body: Some(block), .. }) if item.ident.name == sym::main => {
let is_async = matches!(sig.header.asyncness, Async::Yes { .. });
let returns_nothing = match &sig.decl.output {
FnRetTy::Default(..) => true,
for word in text.split(|c: char| c.is_whitespace() || c == '\'') {
// Trim punctuation as in `some comment (see foo::bar).`
// ^^
- // Or even as in `_foo bar_` which is emphasized.
- let word = word.trim_matches(|c: char| !c.is_alphanumeric());
+ // Or even as in `_foo bar_` which is emphasized. Also preserve `::` as a prefix/suffix.
+ let mut word = word.trim_matches(|c: char| !c.is_alphanumeric() && c != ':');
- if valid_idents.contains(word) {
+ // Remove leading or trailing single `:` which may be part of a sentence.
+ if word.starts_with(':') && !word.starts_with("::") {
+ word = word.trim_start_matches(':');
+ }
+ if word.ends_with(':') && !word.ends_with("::") {
+ word = word.trim_end_matches(':');
+ }
+
+ if valid_idents.contains(word) || word.chars().all(|c| c == ':') {
continue;
}
}
}
- // We assume that mixed-case words are not meant to be put inside bacticks. (Issue #2343)
+ // We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343)
if has_underscore(word) && has_hyphen(word) {
return;
}
if has_underscore(word) || word.contains("::") || is_camel_case(word) {
- span_lint(
+ let mut applicability = Applicability::MachineApplicable;
+
+ span_lint_and_sugg(
cx,
DOC_MARKDOWN,
span,
- &format!("you should put `{}` between ticks in the documentation", word),
+ "item in documentation is missing backticks",
+ "try",
+ format!("`{}`", snippet_with_applicability(cx, span, "..", &mut applicability)),
+ applicability,
);
}
}
// check for `unwrap`
if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
- let reciever_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
- if is_type_diagnostic_item(self.cx, reciever_ty, sym::Option)
- || is_type_diagnostic_item(self.cx, reciever_ty, sym::Result)
+ let receiver_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
+ if is_type_diagnostic_item(self.cx, receiver_ty, sym::Option)
+ || is_type_diagnostic_item(self.cx, receiver_ty, sym::Result)
{
self.panic_span = Some(expr.span);
}
ExprKind::MethodCall(
_,
_,
- [map, Expr {
- kind: ExprKind::AddrOf(_, _, key),
- span: key_span,
- ..
- }],
+ [
+ map,
+ Expr {
+ kind: ExprKind::AddrOf(_, _, key),
+ span: key_span,
+ ..
+ },
+ ],
_,
) if key_span.ctxt() == expr.span.ctxt() => {
let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
//! lint on enum variants that are prefixed or suffixed by the same characters
-use clippy_utils::camel_case;
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::source::is_present_in_source;
+use clippy_utils::str_utils::{self, count_match_end, count_match_start};
use rustc_hir::{EnumDef, Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
MODULE_INCEPTION
]);
-/// Returns the number of chars that match from the start
-#[must_use]
-fn partial_match(pre: &str, name: &str) -> usize {
- let mut name_iter = name.chars();
- let _ = name_iter.next_back(); // make sure the name is never fully matched
- pre.chars().zip(name_iter).take_while(|&(l, r)| l == r).count()
-}
-
-/// Returns the number of chars that match from the end
-#[must_use]
-fn partial_rmatch(post: &str, name: &str) -> usize {
- let mut name_iter = name.chars();
- let _ = name_iter.next(); // make sure the name is never fully matched
- post.chars()
- .rev()
- .zip(name_iter.rev())
- .take_while(|&(l, r)| l == r)
- .count()
-}
-
fn check_variant(
cx: &LateContext<'_>,
threshold: u64,
}
for var in def.variants {
let name = var.ident.name.as_str();
- if partial_match(item_name, &name) == item_name_chars
+ if count_match_start(item_name, &name).char_count == item_name_chars
&& name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
&& name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric())
{
"variant name starts with the enum's name",
);
}
- if partial_rmatch(item_name, &name) == item_name_chars {
+ if count_match_end(item_name, &name).char_count == item_name_chars {
span_lint(
cx,
ENUM_VARIANT_NAMES,
}
}
let first = &def.variants[0].ident.name.as_str();
- let mut pre = &first[..camel_case::until(&*first)];
- let mut post = &first[camel_case::from(&*first)..];
+ let mut pre = &first[..str_utils::camel_case_until(&*first).byte_index];
+ let mut post = &first[str_utils::camel_case_start(&*first).byte_index..];
for var in def.variants {
let name = var.ident.name.as_str();
- let pre_match = partial_match(pre, &name);
+ let pre_match = count_match_start(pre, &name).byte_count;
pre = &pre[..pre_match];
- let pre_camel = camel_case::until(pre);
+ let pre_camel = str_utils::camel_case_until(pre).byte_index;
pre = &pre[..pre_camel];
while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() {
if next.is_numeric() {
}
if next.is_lowercase() {
let last = pre.len() - last.len_utf8();
- let last_camel = camel_case::until(&pre[..last]);
- pre = &pre[..last_camel];
+ let last_camel = str_utils::camel_case_until(&pre[..last]);
+ pre = &pre[..last_camel.byte_index];
} else {
break;
}
}
- let post_match = partial_rmatch(post, &name);
- let post_end = post.len() - post_match;
+ let post_match = count_match_end(post, &name);
+ let post_end = post.len() - post_match.byte_count;
post = &post[post_end..];
- let post_camel = camel_case::from(post);
- post = &post[post_camel..];
+ let post_camel = str_utils::camel_case_start(post);
+ post = &post[post_camel.byte_index..];
}
let (what, value) = match (pre.is_empty(), post.is_empty()) {
(true, true) => return,
);
}
}
- if item.vis.node.is_pub() {
- let matching = partial_match(mod_camel, &item_camel);
- let rmatching = partial_rmatch(mod_camel, &item_camel);
+ // The `module_name_repetitions` lint should only trigger if the item has the module in its
+ // name. Having the same name is accepted.
+ if item.vis.node.is_pub() && item_camel.len() > mod_camel.len() {
+ let matching = count_match_start(mod_camel, &item_camel);
+ let rmatching = count_match_end(mod_camel, &item_camel);
let nchars = mod_camel.chars().count();
let is_word_beginning = |c: char| c == '_' || c.is_uppercase() || c.is_numeric();
- if matching == nchars {
+ if matching.char_count == nchars {
match item_camel.chars().nth(nchars) {
Some(c) if is_word_beginning(c) => span_lint(
cx,
_ => (),
}
}
- if rmatching == nchars {
+ if rmatching.char_count == nchars {
span_lint(
cx,
MODULE_NAME_REPETITIONS,
}
match *cx.typeck_results().expr_adjustments(arg) {
[] => true,
- [Adjustment {
- kind: Adjust::Deref(None),
- ..
- }, Adjustment {
- kind: Adjust::Borrow(AutoBorrow::Ref(_, mu2)),
- ..
- }] => {
+ [
+ Adjustment {
+ kind: Adjust::Deref(None),
+ ..
+ },
+ Adjustment {
+ kind: Adjust::Borrow(AutoBorrow::Ref(_, mu2)),
+ ..
+ },
+ ] => {
// re-borrow with the same mutability is allowed
let ty = cx.typeck_results().expr_ty(arg);
matches!(*ty.kind(), ty::Ref(.., mu1) if mu1 == mu2.into())
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::in_macro;
-use rustc_ast::ast::{AssocItemKind, Extern, FnKind, FnSig, ImplKind, Item, ItemKind, TraitKind, Ty, TyKind};
+use rustc_ast::ast::{AssocItemKind, Extern, Fn, FnSig, Impl, Item, ItemKind, Trait, Ty, TyKind};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{sym, Span};
);
}
},
- ItemKind::Impl(box ImplKind {
+ ItemKind::Impl(box Impl {
of_trait: None, items, ..
})
- | ItemKind::Trait(box TraitKind(.., items)) => {
+ | ItemKind::Trait(box Trait { items, .. }) => {
for item in items {
- if let AssocItemKind::Fn(box FnKind(_, fn_sig, _, _)) = &item.kind {
- self.check_fn_sig(cx, fn_sig, item.span);
+ if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
+ self.check_fn_sig(cx, sig, item.span);
}
}
},
- ItemKind::Fn(box FnKind(_, fn_sig, _, _)) => self.check_fn_sig(cx, fn_sig, item.span),
+ ItemKind::Fn(box Fn { sig, .. }) => self.check_fn_sig(cx, sig, item.span),
_ => (),
}
}
let mut applicability = Applicability::MachineApplicable;
if format_args.value_args.is_empty() {
- if_chain! {
- if let [e] = &*format_args.format_string_parts;
- if let ExprKind::Lit(lit) = &e.kind;
- if let Some(s_src) = snippet_opt(cx, lit.span);
- then {
- // Simulate macro expansion, converting {{ and }} to { and }.
- let s_expand = s_src.replace("{{", "{").replace("}}", "}");
- let sugg = format!("{}.to_string()", s_expand);
- span_useless_format(cx, call_site, sugg, applicability);
+ if format_args.format_string_parts.is_empty() {
+ span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability);
+ } else {
+ if_chain! {
+ if let [e] = &*format_args.format_string_parts;
+ if let ExprKind::Lit(lit) = &e.kind;
+ if let Some(s_src) = snippet_opt(cx, lit.span);
+ then {
+ // Simulate macro expansion, converting {{ and }} to { and }.
+ let s_expand = s_src.replace("{{", "{").replace("}}", "}");
+ let sugg = format!("{}.to_string()", s_expand);
+ span_useless_format(cx, call_site, sugg, applicability);
+ }
}
}
} else if let [value] = *format_args.value_args {
}
}
+fn span_useless_format_empty(cx: &LateContext<'_>, span: Span, sugg: String, applicability: Applicability) {
+ span_lint_and_sugg(
+ cx,
+ USELESS_FORMAT,
+ span,
+ "useless use of `format!`",
+ "consider using `String::new()`",
+ sugg,
+ applicability,
+ );
+}
+
fn span_useless_format(cx: &LateContext<'_>, span: Span, sugg: String, applicability: Applicability) {
span_lint_and_sugg(
cx,
//! on the condition
use clippy_utils::diagnostics::span_lint_and_help;
-use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp};
-use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_middle::lint::in_external_macro;
+use clippy_utils::is_else_clause;
+use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
+use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! {
declare_lint_pass!(IfNotElse => [IF_NOT_ELSE]);
-impl EarlyLintPass for IfNotElse {
- fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
- if in_external_macro(cx.sess, item.span) {
+impl LateLintPass<'_> for IfNotElse {
+ fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) {
+ // While loops will be desugared to ExprKind::If. This will cause the lint to fire.
+ // To fix this, return early if this span comes from a macro or desugaring.
+ if item.span.from_expansion() {
return;
}
- if let ExprKind::If(ref cond, _, Some(ref els)) = item.kind {
+ if let ExprKind::If(cond, _, Some(els)) = item.kind {
if let ExprKind::Block(..) = els.kind {
- match cond.kind {
+ // Disable firing the lint in "else if" expressions.
+ if is_else_clause(cx.tcx, item) {
+ return;
+ }
+
+ match cond.peel_drop_temps().kind {
ExprKind::Unary(UnOp::Not, _) => {
span_lint_and_help(
cx,
+++ /dev/null
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher::PanicExpn;
-use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_expn_of, sugg};
-use rustc_errors::Applicability;
-use rustc_hir::{Block, Expr, ExprKind, StmtKind, UnOp};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-
-declare_clippy_lint! {
- /// ### What it does
- /// Detects `if`-then-`panic!` that can be replaced with `assert!`.
- ///
- /// ### Why is this bad?
- /// `assert!` is simpler than `if`-then-`panic!`.
- ///
- /// ### Example
- /// ```rust
- /// let sad_people: Vec<&str> = vec![];
- /// if !sad_people.is_empty() {
- /// panic!("there are sad people: {:?}", sad_people);
- /// }
- /// ```
- /// Use instead:
- /// ```rust
- /// let sad_people: Vec<&str> = vec![];
- /// assert!(sad_people.is_empty(), "there are sad people: {:?}", sad_people);
- /// ```
- pub IF_THEN_PANIC,
- style,
- "`panic!` and only a `panic!` in `if`-then statement"
-}
-
-declare_lint_pass!(IfThenPanic => [IF_THEN_PANIC]);
-
-impl LateLintPass<'_> for IfThenPanic {
- fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
- if_chain! {
- if let Expr {
- kind: ExprKind:: If(cond, Expr {
- kind: ExprKind::Block(
- Block {
- stmts: [stmt],
- ..
- },
- _),
- ..
- }, None),
- ..
- } = &expr;
- if is_expn_of(stmt.span, "panic").is_some();
- if !matches!(cond.kind, ExprKind::Let(_, _, _));
- if let StmtKind::Semi(semi) = stmt.kind;
- if !cx.tcx.sess.source_map().is_multiline(cond.span);
-
- then {
- let span = if let Some(panic_expn) = PanicExpn::parse(semi) {
- match *panic_expn.format_args.value_args {
- [] => panic_expn.format_args.format_string_span,
- [.., last] => panic_expn.format_args.format_string_span.to(last.span),
- }
- } else {
- if_chain! {
- if let ExprKind::Block(block, _) = semi.kind;
- if let Some(init) = block.expr;
- if let ExprKind::Call(_, [format_args]) = init.kind;
-
- then {
- format_args.span
- } else {
- return
- }
- }
- };
- let mut applicability = Applicability::MachineApplicable;
- let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
- let cond_sugg = if let ExprKind::DropTemps(e, ..) = cond.kind {
- if let Expr{kind: ExprKind::Unary(UnOp::Not, not_expr), ..} = e {
- sugg::Sugg::hir_with_applicability(cx, not_expr, "..", &mut applicability).maybe_par().to_string()
- } else {
- format!("!{}", sugg::Sugg::hir_with_applicability(cx, e, "..", &mut applicability).maybe_par())
- }
- } else {
- format!("!{}", sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par())
- };
-
- span_lint_and_sugg(
- cx,
- IF_THEN_PANIC,
- expr.span,
- "only a `panic!` in `if`-then statement",
- "try",
- format!("assert!({}, {});", cond_sugg, sugg),
- Applicability::MachineApplicable,
- );
- }
- }
- }
-}
},
_ => None,
}
- }
+ },
// case where `x + 1 <= ...` or `1 + x <= ...`
(BinOpKind::Le, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _)
if lhskind.node == BinOpKind::Add =>
},
_ => None,
}
- }
+ },
// case where `... >= y - 1` or `... >= -1 + y`
(BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => {
match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) {
-use std::cmp::Ordering;
-
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Span;
+use clippy_utils::comparisons;
use clippy_utils::comparisons::Rel;
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{constant_full_int, FullInt};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::source::snippet;
-use clippy_utils::{comparisons, sext};
declare_clippy_lint! {
/// ### What it does
declare_lint_pass!(InvalidUpcastComparisons => [INVALID_UPCAST_COMPARISONS]);
-#[derive(Copy, Clone, Debug, Eq)]
-enum FullInt {
- S(i128),
- U(u128),
-}
-
-impl FullInt {
- #[allow(clippy::cast_sign_loss)]
- #[must_use]
- fn cmp_s_u(s: i128, u: u128) -> Ordering {
- if s < 0 {
- Ordering::Less
- } else if u > (i128::MAX as u128) {
- Ordering::Greater
- } else {
- (s as u128).cmp(&u)
- }
- }
-}
-
-impl PartialEq for FullInt {
- #[must_use]
- fn eq(&self, other: &Self) -> bool {
- self.partial_cmp(other).expect("`partial_cmp` only returns `Some(_)`") == Ordering::Equal
- }
-}
-
-impl PartialOrd for FullInt {
- #[must_use]
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
- Some(match (self, other) {
- (&Self::S(s), &Self::S(o)) => s.cmp(&o),
- (&Self::U(s), &Self::U(o)) => s.cmp(&o),
- (&Self::S(s), &Self::U(o)) => Self::cmp_s_u(s, o),
- (&Self::U(s), &Self::S(o)) => Self::cmp_s_u(o, s).reverse(),
- })
- }
-}
-
-impl Ord for FullInt {
- #[must_use]
- fn cmp(&self, other: &Self) -> Ordering {
- self.partial_cmp(other)
- .expect("`partial_cmp` for FullInt can never return `None`")
- }
-}
-
fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> {
if let ExprKind::Cast(cast_exp, _) = expr.kind {
let pre_cast_ty = cx.typeck_results().expr_ty(cast_exp);
}
}
-fn node_as_const_fullint<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<FullInt> {
- let val = constant(cx, cx.typeck_results(), expr)?.0;
- if let Constant::Int(const_int) = val {
- match *cx.typeck_results().expr_ty(expr).kind() {
- ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
- ty::Uint(_) => Some(FullInt::U(const_int)),
- _ => None,
- }
- } else {
- None
- }
-}
-
fn err_upcast_comparison(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, always: bool) {
if let ExprKind::Cast(cast_val, _) = expr.kind {
span_lint(
invert: bool,
) {
if let Some((lb, ub)) = lhs_bounds {
- if let Some(norm_rhs_val) = node_as_const_fullint(cx, rhs) {
+ if let Some(norm_rhs_val) = constant_full_int(cx, cx.typeck_results(), rhs) {
if rel == Rel::Eq || rel == Rel::Ne {
if norm_rhs_val < lb || norm_rhs_val > ub {
err_upcast_comparison(cx, span, lhs, rel == Rel::Ne);
LintId::of(get_last_with_len::GET_LAST_WITH_LEN),
LintId::of(identity_op::IDENTITY_OP),
LintId::of(if_let_mutex::IF_LET_MUTEX),
- LintId::of(if_then_panic::IF_THEN_PANIC),
LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
LintId::of(infinite_iter::INFINITE_ITER),
LintId::of(inherent_to_string::INHERENT_TO_STRING),
LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
+ LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY),
LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS),
LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
LintId::of(overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL),
LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
LintId::of(unicode::INVISIBLE_CHARACTERS),
LintId::of(uninit_vec::UNINIT_VEC),
+ LintId::of(unit_hash::UNIT_HASH),
LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
LintId::of(unit_types::UNIT_ARG),
LintId::of(unit_types::UNIT_CMP),
LintId::of(undropped_manually_drops::UNDROPPED_MANUALLY_DROPS),
LintId::of(unicode::INVISIBLE_CHARACTERS),
LintId::of(uninit_vec::UNINIT_VEC),
+ LintId::of(unit_hash::UNIT_HASH),
LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
LintId::of(unit_types::UNIT_CMP),
LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS),
identity_op::IDENTITY_OP,
if_let_mutex::IF_LET_MUTEX,
if_not_else::IF_NOT_ELSE,
- if_then_panic::IF_THEN_PANIC,
if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
implicit_hasher::IMPLICIT_HASHER,
implicit_return::IMPLICIT_RETURN,
loops::WHILE_LET_ON_ITERATOR,
macro_use::MACRO_USE_IMPORTS,
main_recursion::MAIN_RECURSION,
+ manual_assert::MANUAL_ASSERT,
manual_async_fn::MANUAL_ASYNC_FN,
manual_map::MANUAL_MAP,
manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
misc_early::DUPLICATE_UNDERSCORE_ARGUMENT,
misc_early::MIXED_CASE_HEX_LITERALS,
misc_early::REDUNDANT_PATTERN,
+ misc_early::SEPARATED_LITERAL_SUFFIX,
misc_early::UNNEEDED_FIELD_PATTERN,
misc_early::UNNEEDED_WILDCARD_PATTERN,
misc_early::UNSEPARATED_LITERAL_SUFFIX,
strings::STRING_ADD_ASSIGN,
strings::STRING_FROM_UTF8_AS_BYTES,
strings::STRING_LIT_AS_BYTES,
+ strings::STRING_SLICE,
strings::STRING_TO_STRING,
strings::STR_TO_STRING,
strlen_on_c_strings::STRLEN_ON_C_STRINGS,
unicode::NON_ASCII_LITERAL,
unicode::UNICODE_NOT_NFC,
uninit_vec::UNINIT_VEC,
+ unit_hash::UNIT_HASH,
unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD,
unit_types::LET_UNIT_VALUE,
unit_types::UNIT_ARG,
LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN),
LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
LintId::of(mutex_atomic::MUTEX_INTEGER),
- LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY),
LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES),
LintId::of(option_if_let_else::OPTION_IF_LET_ELSE),
LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
LintId::of(loops::EXPLICIT_INTO_ITER_LOOP),
LintId::of(loops::EXPLICIT_ITER_LOOP),
LintId::of(macro_use::MACRO_USE_IMPORTS),
+ LintId::of(manual_assert::MANUAL_ASSERT),
LintId::of(manual_ok_or::MANUAL_OK_OR),
LintId::of(match_on_vec_items::MATCH_ON_VEC_ITEMS),
LintId::of(matches::MATCH_BOOL),
LintId::of(methods::MAP_UNWRAP_OR),
LintId::of(misc::FLOAT_CMP),
LintId::of(misc::USED_UNDERSCORE_BINDING),
- LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX),
LintId::of(mut_mut::MUT_MUT),
LintId::of(needless_bitwise_bool::NEEDLESS_BITWISE_BOOL),
LintId::of(needless_borrow::REF_BINDING_TO_REFERENCE),
LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
LintId::of(types::LINKEDLIST),
LintId::of(types::OPTION_OPTION),
- LintId::of(unicode::NON_ASCII_LITERAL),
LintId::of(unicode::UNICODE_NOT_NFC),
LintId::of(unit_types::LET_UNIT_VALUE),
LintId::of(unnecessary_wraps::UNNECESSARY_WRAPS),
LintId::of(methods::GET_UNWRAP),
LintId::of(methods::UNWRAP_USED),
LintId::of(misc::FLOAT_CMP_CONST),
+ LintId::of(misc_early::SEPARATED_LITERAL_SUFFIX),
LintId::of(misc_early::UNNEEDED_FIELD_PATTERN),
+ LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX),
LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
LintId::of(missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES),
LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS),
LintId::of(shadow::SHADOW_SAME),
LintId::of(shadow::SHADOW_UNRELATED),
LintId::of(strings::STRING_ADD),
+ LintId::of(strings::STRING_SLICE),
LintId::of(strings::STRING_TO_STRING),
LintId::of(strings::STR_TO_STRING),
LintId::of(types::RC_BUFFER),
LintId::of(types::RC_MUTEX),
LintId::of(undocumented_unsafe_blocks::UNDOCUMENTED_UNSAFE_BLOCKS),
+ LintId::of(unicode::NON_ASCII_LITERAL),
LintId::of(unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS),
LintId::of(unwrap_in_result::UNWRAP_IN_RESULT),
LintId::of(verbose_file_reads::VERBOSE_FILE_READS),
LintId::of(functions::DOUBLE_MUST_USE),
LintId::of(functions::MUST_USE_UNIT),
LintId::of(functions::RESULT_UNIT_ERR),
- LintId::of(if_then_panic::IF_THEN_PANIC),
LintId::of(inherent_to_string::INHERENT_TO_STRING),
LintId::of(len_zero::COMPARISON_TO_EMPTY),
LintId::of(len_zero::LEN_WITHOUT_IS_EMPTY),
LintId::of(loops::MUT_RANGE_BOUND),
LintId::of(methods::SUSPICIOUS_MAP),
LintId::of(mut_key::MUTABLE_KEY_TYPE),
+ LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY),
LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
])
mod identity_op;
mod if_let_mutex;
mod if_not_else;
-mod if_then_panic;
mod if_then_some_else_none;
mod implicit_hasher;
mod implicit_return;
mod loops;
mod macro_use;
mod main_recursion;
+mod manual_assert;
mod manual_async_fn;
mod manual_map;
mod manual_non_exhaustive;
mod undropped_manually_drops;
mod unicode;
mod uninit_vec;
+mod unit_hash;
mod unit_return_expecting_ord;
mod unit_types;
mod unnamed_address;
store.register_late_pass(|| Box::new(collapsible_match::CollapsibleMatch));
store.register_late_pass(|| Box::new(unicode::Unicode));
store.register_late_pass(|| Box::new(uninit_vec::UninitVec));
+ store.register_late_pass(|| Box::new(unit_hash::UnitHash));
store.register_late_pass(|| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd));
store.register_late_pass(|| Box::new(strings::StringAdd));
store.register_late_pass(|| Box::new(implicit_return::ImplicitReturn));
store.register_early_pass(|| Box::new(double_parens::DoubleParens));
store.register_late_pass(|| Box::new(to_string_in_display::ToStringInDisplay::new()));
store.register_early_pass(|| Box::new(unsafe_removed_from_name::UnsafeNameRemoval));
- store.register_early_pass(|| Box::new(if_not_else::IfNotElse));
store.register_early_pass(|| Box::new(else_if_without_else::ElseIfWithoutElse));
store.register_early_pass(|| Box::new(int_plus_one::IntPlusOne));
store.register_early_pass(|| Box::new(formatting::Formatting));
store.register_late_pass(|| Box::new(option_if_let_else::OptionIfLetElse));
store.register_late_pass(|| Box::new(future_not_send::FutureNotSend));
store.register_late_pass(|| Box::new(if_let_mutex::IfLetMutex));
+ store.register_late_pass(|| Box::new(if_not_else::IfNotElse));
store.register_late_pass(|| Box::new(equatable_if_let::PatternEquality));
store.register_late_pass(|| Box::new(mut_mutex_lock::MutMutexLock));
store.register_late_pass(|| Box::new(match_on_vec_items::MatchOnVecItems));
store.register_late_pass(move || Box::new(self_named_constructors::SelfNamedConstructors));
store.register_late_pass(move || Box::new(feature_name::FeatureName));
store.register_late_pass(move || Box::new(iter_not_returning_iterator::IterNotReturningIterator));
- store.register_late_pass(move || Box::new(if_then_panic::IfThenPanic));
+ store.register_late_pass(move || Box::new(manual_assert::ManualAssert));
let enable_raw_pointer_heuristic_for_send = conf.enable_raw_pointer_heuristic_for_send;
store.register_late_pass(move || Box::new(non_send_fields_in_send_ty::NonSendFieldInSendTy::new(enable_raw_pointer_heuristic_for_send)));
store.register_late_pass(move || Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::default()));
store.register_late_pass(|| Box::new(match_str_case_mismatch::MatchStrCaseMismatch));
store.register_late_pass(move || Box::new(format_args::FormatArgs));
store.register_late_pass(|| Box::new(trailing_empty_array::TrailingEmptyArray));
-
+ // add lints here, do not remove this comment, it's used in `new_lint`
}
#[rustfmt::skip]
///
/// Used in `./src/driver.rs`.
pub fn register_renamed(ls: &mut rustc_lint::LintStore) {
+ // NOTE: when renaming a lint, add a corresponding test to tests/ui/rename.rs
ls.register_renamed("clippy::stutter", "clippy::module_name_repetitions");
ls.register_renamed("clippy::new_without_default_derive", "clippy::new_without_default");
ls.register_renamed("clippy::cyclomatic_complexity", "clippy::cognitive_complexity");
fn visit_ty(&mut self, ty: &'tcx Ty<'_>) {
match ty.kind {
- TyKind::OpaqueDef(item, _) => {
+ TyKind::OpaqueDef(item, bounds) => {
let map = self.cx.tcx.hir();
let item = map.item(item);
walk_item(self, item);
walk_ty(self, ty);
+ self.lts.extend(bounds.iter().filter_map(|bound| match bound {
+ GenericArg::Lifetime(l) => Some(RefLt::Named(l.name.ident().name)),
+ _ => None,
+ }));
},
TyKind::BareFn(&BareFnTy { decl, .. }) => {
let mut sub_visitor = RefVisitor::new(self.cx);
sugg::Sugg::hir_with_applicability(cx, arg_inner, "_", applic_ref).maybe_par(),
meth_name,
)
- }
+ },
_ => format!(
"{}.into_iter()",
sugg::Sugg::hir_with_applicability(cx, arg, "_", applic_ref).maybe_par()
--- /dev/null
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::higher::PanicExpn;
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::{is_expn_of, sugg};
+use rustc_errors::Applicability;
+use rustc_hir::{Block, Expr, ExprKind, StmtKind, UnOp};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Detects `if`-then-`panic!` that can be replaced with `assert!`.
+ ///
+ /// ### Why is this bad?
+ /// `assert!` is simpler than `if`-then-`panic!`.
+ ///
+ /// ### Example
+ /// ```rust
+ /// let sad_people: Vec<&str> = vec![];
+ /// if !sad_people.is_empty() {
+ /// panic!("there are sad people: {:?}", sad_people);
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// let sad_people: Vec<&str> = vec![];
+ /// assert!(sad_people.is_empty(), "there are sad people: {:?}", sad_people);
+ /// ```
+ pub MANUAL_ASSERT,
+ pedantic,
+ "`panic!` and only a `panic!` in `if`-then statement"
+}
+
+declare_lint_pass!(ManualAssert => [MANUAL_ASSERT]);
+
+impl LateLintPass<'_> for ManualAssert {
+ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+ if_chain! {
+ if let Expr {
+ kind: ExprKind:: If(cond, Expr {
+ kind: ExprKind::Block(
+ Block {
+ stmts: [stmt],
+ ..
+ },
+ _),
+ ..
+ }, None),
+ ..
+ } = &expr;
+ if is_expn_of(stmt.span, "panic").is_some();
+ if !matches!(cond.kind, ExprKind::Let(_, _, _));
+ if let StmtKind::Semi(semi) = stmt.kind;
+ if !cx.tcx.sess.source_map().is_multiline(cond.span);
+
+ then {
+ let call = if_chain! {
+ if let ExprKind::Block(block, _) = semi.kind;
+ if let Some(init) = block.expr;
+ then {
+ init
+ } else {
+ semi
+ }
+ };
+ let span = if let Some(panic_expn) = PanicExpn::parse(call) {
+ match *panic_expn.format_args.value_args {
+ [] => panic_expn.format_args.format_string_span,
+ [.., last] => panic_expn.format_args.format_string_span.to(last.span),
+ }
+ } else if let ExprKind::Call(_, [format_args]) = call.kind {
+ format_args.span
+ } else {
+ return
+ };
+ let mut applicability = Applicability::MachineApplicable;
+ let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
+ let cond_sugg = if let ExprKind::DropTemps(e, ..) = cond.kind {
+ if let Expr{kind: ExprKind::Unary(UnOp::Not, not_expr), ..} = e {
+ sugg::Sugg::hir_with_applicability(cx, not_expr, "..", &mut applicability).maybe_par().to_string()
+ } else {
+ format!("!{}", sugg::Sugg::hir_with_applicability(cx, e, "..", &mut applicability).maybe_par())
+ }
+ } else {
+ format!("!{}", sugg::Sugg::hir_with_applicability(cx, cond, "..", &mut applicability).maybe_par())
+ };
+
+ span_lint_and_sugg(
+ cx,
+ MANUAL_ASSERT,
+ expr.span,
+ "only a `panic!` in `if`-then statement",
+ "try",
+ format!("assert!({}, {});", cond_sugg, sugg),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+ }
+}
fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(Span, SymbolStr)> {
let case_check = match case_method {
- CaseMethod::LowerCase => |input: &str| -> bool { input.chars().all(char::is_lowercase) },
- CaseMethod::AsciiLowerCase => |input: &str| -> bool { input.chars().all(|c| matches!(c, 'a'..='z')) },
- CaseMethod::UpperCase => |input: &str| -> bool { input.chars().all(char::is_uppercase) },
- CaseMethod::AsciiUppercase => |input: &str| -> bool { input.chars().all(|c| matches!(c, 'A'..='Z')) },
+ CaseMethod::LowerCase => |input: &str| -> bool { input.chars().all(|c| c.to_lowercase().next() == Some(c)) },
+ CaseMethod::AsciiLowerCase => |input: &str| -> bool { !input.chars().any(|c| c.is_ascii_uppercase()) },
+ CaseMethod::UpperCase => |input: &str| -> bool { input.chars().all(|c| c.to_uppercase().next() == Some(c)) },
+ CaseMethod::AsciiUppercase => |input: &str| -> bool { !input.chars().any(|c| c.is_ascii_lowercase()) },
};
for arm in arms {
fn lint(cx: &LateContext<'_>, case_method: &CaseMethod, bad_case_span: Span, bad_case_str: &str) {
let (method_str, suggestion) = match case_method {
- CaseMethod::LowerCase => ("to_lower_case", bad_case_str.to_lowercase()),
+ CaseMethod::LowerCase => ("to_lowercase", bad_case_str.to_lowercase()),
CaseMethod::AsciiLowerCase => ("to_ascii_lowercase", bad_case_str.to_ascii_lowercase()),
CaseMethod::UpperCase => ("to_uppercase", bad_case_str.to_uppercase()),
CaseMethod::AsciiUppercase => ("to_ascii_uppercase", bad_case_str.to_ascii_uppercase()),
-use clippy_utils::consts::{constant, miri_to_const, Constant};
+use clippy_utils::consts::{constant, constant_full_int, miri_to_const, FullInt};
use clippy_utils::diagnostics::{
multispan_sugg, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
};
fn check_overlapping_arms<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) {
if arms.len() >= 2 && cx.typeck_results().expr_ty(ex).is_integral() {
let ranges = all_ranges(cx, arms, cx.typeck_results().expr_ty(ex));
- let type_ranges = type_ranges(&ranges);
- if !type_ranges.is_empty() {
- if let Some((start, end)) = overlapping(&type_ranges) {
+ if !ranges.is_empty() {
+ if let Some((start, end)) = overlapping(&ranges) {
span_lint_and_note(
cx,
MATCH_OVERLAPPING_ARM,
}
if_chain! {
if matching_wild;
- if let ExprKind::Block(block, _) = arm.body.kind;
- if is_panic_block(block);
+ if is_panic_call(arm.body);
then {
// `Err(_)` or `Err(_e)` arm with `panic!` found
span_lint_and_note(cx,
}
// If the block contains only a `panic!` macro (as expression or statement)
-fn is_panic_block(block: &Block<'_>) -> bool {
- match (&block.expr, block.stmts.len(), block.stmts.first()) {
- (&Some(exp), 0, _) => is_expn_of(exp.span, "panic").is_some() && is_expn_of(exp.span, "unreachable").is_none(),
- (&None, 1, Some(stmt)) => {
- is_expn_of(stmt.span, "panic").is_some() && is_expn_of(stmt.span, "unreachable").is_none()
- },
- _ => false,
- }
+fn is_panic_call(expr: &Expr<'_>) -> bool {
+ // Unwrap any wrapping blocks
+ let span = if let ExprKind::Block(block, _) = expr.kind {
+ match (&block.expr, block.stmts.len(), block.stmts.first()) {
+ (&Some(exp), 0, _) => exp.span,
+ (&None, 1, Some(stmt)) => stmt.span,
+ _ => return false,
+ }
+ } else {
+ expr.span
+ };
+
+ is_expn_of(span, "panic").is_some() && is_expn_of(span, "unreachable").is_none()
}
fn check_match_ref_pats<'a, 'b, I>(cx: &LateContext<'_>, ex: &Expr<'_>, pats: I, expr: &Expr<'_>)
}
/// Gets all arms that are unbounded `PatRange`s.
-fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) -> Vec<SpannedRange<Constant>> {
+fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) -> Vec<SpannedRange<FullInt>> {
arms.iter()
.filter_map(|arm| {
if let Arm { pat, guard: None, .. } = *arm {
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?,
};
- let rhs = match range_end {
- RangeEnd::Included => Bound::Included(rhs),
- RangeEnd::Excluded => Bound::Excluded(rhs),
+
+ let lhs_val = lhs.int_value(cx, ty)?;
+ let rhs_val = rhs.int_value(cx, ty)?;
+
+ let rhs_bound = match range_end {
+ RangeEnd::Included => Bound::Included(rhs_val),
+ RangeEnd::Excluded => Bound::Excluded(rhs_val),
};
return Some(SpannedRange {
span: pat.span,
- node: (lhs, rhs),
+ node: (lhs_val, rhs_bound),
});
}
if let PatKind::Lit(value) = pat.kind {
- let value = constant(cx, cx.typeck_results(), value)?.0;
+ let value = constant_full_int(cx, cx.typeck_results(), value)?;
return Some(SpannedRange {
span: pat.span,
- node: (value.clone(), Bound::Included(value)),
+ node: (value, Bound::Included(value)),
});
}
}
pub node: (T, Bound<T>),
}
-type TypedRanges = Vec<SpannedRange<u128>>;
-
-/// Gets all `Int` ranges or all `Uint` ranges. Mixed types are an error anyway
-/// and other types than
-/// `Uint` and `Int` probably don't make sense.
-fn type_ranges(ranges: &[SpannedRange<Constant>]) -> TypedRanges {
- ranges
- .iter()
- .filter_map(|range| match range.node {
- (Constant::Int(start), Bound::Included(Constant::Int(end))) => Some(SpannedRange {
- span: range.span,
- node: (start, Bound::Included(end)),
- }),
- (Constant::Int(start), Bound::Excluded(Constant::Int(end))) => Some(SpannedRange {
- span: range.span,
- node: (start, Bound::Excluded(end)),
- }),
- (Constant::Int(start), Bound::Unbounded) => Some(SpannedRange {
- span: range.span,
- node: (start, Bound::Unbounded),
- }),
- _ => None,
- })
- .collect()
-}
-
// Checks if arm has the form `None => None`
fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
matches!(arm.pat.kind, PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone))
if expr.hir_id == self_arg.hir_id && ty != cx.typeck_results().expr_ty_adjusted(expr) =>
{
return;
- }
+ },
ExprKind::MethodCall(_, _, [self_arg, ..], _) if expr.hir_id == self_arg.hir_id => true,
ExprKind::Match(_, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
| ExprKind::Field(..)
) =>
{
return;
- }
+ },
_ => false,
};
check_general_case(cx, name, method_span, &args[0], &args[1], expr.span, None);
}
}
- }
+ },
_ => (),
}
}
-use super::MiscEarlyLints;
use clippy_utils::diagnostics::span_lint;
use rustc_ast::ast::{Expr, ExprKind, UnOp};
use rustc_lint::EarlyContext;
use super::DOUBLE_NEG;
pub(super) fn check(cx: &EarlyContext<'_>, expr: &Expr) {
- match expr.kind {
- ExprKind::Unary(UnOp::Neg, ref inner) => {
- if let ExprKind::Unary(UnOp::Neg, _) = inner.kind {
- span_lint(
- cx,
- DOUBLE_NEG,
- expr.span,
- "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op",
- );
- }
- },
- ExprKind::Lit(ref lit) => MiscEarlyLints::check_lit(cx, lit),
- _ => (),
+ if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind {
+ if let ExprKind::Unary(UnOp::Neg, _) = inner.kind {
+ span_lint(
+ cx,
+ DOUBLE_NEG,
+ expr.span,
+ "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op",
+ );
+ }
}
}
--- /dev/null
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use rustc_ast::ast::Lit;
+use rustc_errors::Applicability;
+use rustc_lint::EarlyContext;
+
+use super::{SEPARATED_LITERAL_SUFFIX, UNSEPARATED_LITERAL_SUFFIX};
+
+pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) {
+ let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) {
+ val
+ } else {
+ return; // It's useless so shouldn't lint.
+ };
+ // Do not lint when literal is unsuffixed.
+ if !suffix.is_empty() {
+ if lit_snip.as_bytes()[maybe_last_sep_idx] == b'_' {
+ span_lint_and_sugg(
+ cx,
+ SEPARATED_LITERAL_SUFFIX,
+ lit.span,
+ &format!("{} type suffix should not be separated by an underscore", sugg_type),
+ "remove the underscore",
+ format!("{}{}", &lit_snip[..maybe_last_sep_idx], suffix),
+ Applicability::MachineApplicable,
+ );
+ } else {
+ span_lint_and_sugg(
+ cx,
+ UNSEPARATED_LITERAL_SUFFIX,
+ lit.span,
+ &format!("{} type suffix should be separated by an underscore", sugg_type),
+ "add an underscore",
+ format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+}
mod builtin_type_shadow;
mod double_neg;
+mod literal_suffix;
mod mixed_case_hex_literals;
mod redundant_pattern;
mod unneeded_field_pattern;
mod unneeded_wildcard_pattern;
-mod unseparated_literal_suffix;
mod zero_prefixed_literal;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::source::snippet_opt;
-use rustc_ast::ast::{Expr, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
+use rustc_ast::ast::{Expr, ExprKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
use rustc_ast::visit::FnKind;
use rustc_data_structures::fx::FxHashMap;
use rustc_lint::{EarlyContext, EarlyLintPass};
/// ### What it does
/// Warns if literal suffixes are not separated by an
/// underscore.
+ /// To enforce unseparated literal suffix style,
+ /// see the `separated_literal_suffix` lint.
///
/// ### Why is this bad?
- /// It is much less readable.
+ /// Suffix style should be consistent.
///
/// ### Example
/// ```rust
/// let y = 123832_i32;
/// ```
pub UNSEPARATED_LITERAL_SUFFIX,
- pedantic,
+ restriction,
"literals whose suffix is not separated by an underscore"
}
+declare_clippy_lint! {
+ /// ### What it does
+ /// Warns if literal suffixes are separated by an underscore.
+ /// To enforce separated literal suffix style,
+ /// see the `unseparated_literal_suffix` lint.
+ ///
+ /// ### Why is this bad?
+ /// Suffix style should be consistent.
+ ///
+ /// ### Example
+ /// ```rust
+ /// // Bad
+ /// let y = 123832_i32;
+ ///
+ /// // Good
+ /// let y = 123832i32;
+ /// ```
+ pub SEPARATED_LITERAL_SUFFIX,
+ restriction,
+ "literals whose suffix is separated by an underscore"
+}
+
declare_clippy_lint! {
/// ### What it does
/// Warns if an integral constant literal starts with `0`.
DOUBLE_NEG,
MIXED_CASE_HEX_LITERALS,
UNSEPARATED_LITERAL_SUFFIX,
+ SEPARATED_LITERAL_SUFFIX,
ZERO_PREFIXED_LITERAL,
BUILTIN_TYPE_SHADOW,
REDUNDANT_PATTERN,
if in_external_macro(cx.sess, expr.span) {
return;
}
+
+ if let ExprKind::Lit(ref lit) = expr.kind {
+ MiscEarlyLints::check_lit(cx, lit);
+ }
double_neg::check(cx, expr);
}
}
LitIntType::Unsigned(ty) => ty.name_str(),
LitIntType::Unsuffixed => "",
};
- unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "integer");
+ literal_suffix::check(cx, lit, &lit_snip, suffix, "integer");
if lit_snip.starts_with("0x") {
mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip);
} else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") {
}
} else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind {
let suffix = float_ty.name_str();
- unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "float");
+ literal_suffix::check(cx, lit, &lit_snip, suffix, "float");
}
}
}
+++ /dev/null
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use rustc_ast::ast::Lit;
-use rustc_errors::Applicability;
-use rustc_lint::EarlyContext;
-
-use super::UNSEPARATED_LITERAL_SUFFIX;
-
-pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) {
- let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) {
- val
- } else {
- return; // It's useless so shouldn't lint.
- };
- // Do not lint when literal is unsuffixed.
- if !suffix.is_empty() && lit_snip.as_bytes()[maybe_last_sep_idx] != b'_' {
- span_lint_and_sugg(
- cx,
- UNSEPARATED_LITERAL_SUFFIX,
- lit.span,
- &format!("{} type suffix should be separated by an underscore", sugg_type),
- "add an underscore",
- format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
- Applicability::MachineApplicable,
- );
- }
-}
}
process_paths_for_mod_files(path, &mut folder_segments, &mut mod_folders);
check_self_named_mod_exists(cx, path, file);
- }
+ },
_ => {},
}
}
if let ExprKind::AddrOf(BorrowKind::Ref, mutability, inner) = e.kind {
if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(inner).kind() {
for adj3 in cx.typeck_results().expr_adjustments(e).windows(3) {
- if let [Adjustment {
- kind: Adjust::Deref(_), ..
- }, Adjustment {
- kind: Adjust::Deref(_), ..
- }, Adjustment {
- kind: Adjust::Borrow(_),
- ..
- }] = *adj3
+ if let [
+ Adjustment {
+ kind: Adjust::Deref(_), ..
+ },
+ Adjustment {
+ kind: Adjust::Deref(_), ..
+ },
+ Adjustment {
+ kind: Adjust::Borrow(_),
+ ..
+ },
+ ] = *adj3
{
let help_msg_ty = if matches!(mutability, Mutability::Not) {
format!("&{}", ty)
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use rustc_ast::ast::{
- Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, FnKind, Item, ItemKind, Local, Pat, PatKind,
+ self, Arm, AssocItem, AssocItemKind, Attribute, Block, FnDecl, Item, ItemKind, Local, Pat, PatKind,
};
use rustc_ast::visit::{walk_block, walk_expr, walk_pat, Visitor};
use rustc_lint::{EarlyContext, EarlyLintPass};
return;
}
- if let ItemKind::Fn(box FnKind(_, ref sig, _, Some(ref blk))) = item.kind {
+ if let ItemKind::Fn(box ast::Fn { ref sig, body: Some(ref blk), .. }) = item.kind {
do_check(self, cx, &item.attrs, &sig.decl, blk);
}
}
return;
}
- if let AssocItemKind::Fn(box FnKind(_, ref sig, _, Some(ref blk))) = item.kind {
+ if let AssocItemKind::Fn(box ast::Fn { ref sig, body: Some(ref blk), .. }) = item.kind {
do_check(self, cx, &item.attrs, &sig.decl, blk);
}
}
/// Use thread-safe types like [`std::sync::Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html)
/// or specify correct bounds on generic type parameters (`T: Send`).
pub NON_SEND_FIELDS_IN_SEND_TY,
- nursery,
+ suspicious,
"there is field that does not implement `Send` in a `Send` struct"
}
/// expression).
///
/// ### Why is this bad?
- /// Using the dedicated functions of the Option type is clearer and
+ /// Using the dedicated functions of the `Option` type is clearer and
/// more concise than an `if let` expression.
///
/// ### Known problems
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::ptr::get_spans;
use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::{is_type_diagnostic_item, match_type, walk_ptrs_hir_ty};
+use clippy_utils::ty::walk_ptrs_hir_ty;
use clippy_utils::{expr_path_res, is_lint_allowed, match_any_diagnostic_items, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
+use rustc_hir::def::Res;
use rustc_hir::{
- BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, Impl, ImplItem, ImplItemKind, Item,
- ItemKind, Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
+ BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, Impl, ImplItem, ImplItemKind, Item, ItemKind,
+ Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind,
};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol;
impl<'tcx> LateLintPass<'tcx> for Ptr {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if let ItemKind::Fn(ref sig, _, body_id) = item.kind {
- check_fn(cx, sig.decl, item.hir_id(), Some(body_id));
+ check_fn(cx, sig.decl, Some(body_id));
}
}
return; // ignore trait impls
}
}
- check_fn(cx, sig.decl, item.hir_id(), Some(body_id));
+ check_fn(cx, sig.decl, Some(body_id));
}
}
} else {
None
};
- check_fn(cx, sig.decl, item.hir_id(), body_id);
+ check_fn(cx, sig.decl, body_id);
}
}
}
#[allow(clippy::too_many_lines)]
-fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: Option<BodyId>) {
- let fn_def_id = cx.tcx.hir().local_def_id(fn_id);
- let sig = cx.tcx.fn_sig(fn_def_id);
- let fn_ty = sig.skip_binder();
+fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, opt_body_id: Option<BodyId>) {
let body = opt_body_id.map(|id| cx.tcx.hir().body(id));
- for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() {
+ for (idx, arg) in decl.inputs.iter().enumerate() {
// Honor the allow attribute on parameters. See issue 5644.
if let Some(body) = &body {
if is_lint_allowed(cx, PTR_ARG, body.params[idx].hir_id) {
}
}
- if let ty::Ref(_, ty, Mutability::Not) = ty.kind() {
- if is_type_diagnostic_item(cx, ty, sym::Vec) {
+ let (item_name, path) = if_chain! {
+ if let TyKind::Rptr(_, MutTy { ty, mutbl: Mutability::Not }) = arg.kind;
+ if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind;
+ if let Res::Def(_, did) = path.res;
+ if let Some(item_name) = cx.tcx.get_diagnostic_name(did);
+ then {
+ (item_name, path)
+ } else {
+ continue
+ }
+ };
+
+ match item_name {
+ sym::Vec => {
if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) {
span_lint_and_then(
cx,
},
);
}
- } else if is_type_diagnostic_item(cx, ty, sym::String) {
+ },
+ sym::String => {
if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_string()"), ("as_str", "")]) {
span_lint_and_then(
cx,
},
);
}
- } else if is_type_diagnostic_item(cx, ty, sym::PathBuf) {
+ },
+ sym::PathBuf => {
if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_path_buf()"), ("as_path", "")]) {
span_lint_and_then(
cx,
},
);
}
- } else if match_type(cx, ty, &paths::COW) {
+ },
+ sym::Cow => {
if_chain! {
- if let TyKind::Rptr(_, MutTy { ty, ..} ) = arg.kind;
- if let TyKind::Path(QPath::Resolved(None, pp)) = ty.kind;
- if let [ref bx] = *pp.segments;
+ if let [ref bx] = *path.segments;
if let Some(params) = bx.args;
if !params.parenthesized;
if let Some(inner) = params.args.iter().find_map(|arg| match arg {
);
}
}
- }
+ },
+ _ => {},
}
}
}
}
- fn expression_returns_unmodified_err(
- cx: &LateContext<'_>,
- expression: &Expr<'_>,
- origin_hir_id: &Expr<'_>,
- ) -> bool {
- match expression.kind {
+ fn expression_returns_unmodified_err(cx: &LateContext<'_>, expr: &Expr<'_>, cond_expr: &Expr<'_>) -> bool {
+ match expr.kind {
ExprKind::Block(block, _) => {
if let Some(return_expression) = Self::return_expression(block) {
- return Self::expression_returns_unmodified_err(cx, return_expression, origin_hir_id);
+ return Self::expression_returns_unmodified_err(cx, return_expression, cond_expr);
}
false
},
- ExprKind::Ret(Some(expr)) | ExprKind::Call(expr, _) => {
- Self::expression_returns_unmodified_err(cx, expr, origin_hir_id)
- },
- ExprKind::Path(_) => path_to_local(expression) == path_to_local(origin_hir_id),
+ ExprKind::Ret(Some(ret_expr)) => Self::expression_returns_unmodified_err(cx, ret_expr, cond_expr),
+ ExprKind::Path(_) => path_to_local(expr) == path_to_local(cond_expr),
_ => false,
}
}
"calling `as_bytes` on a string literal instead of using a byte string literal"
}
-declare_lint_pass!(StringAdd => [STRING_ADD, STRING_ADD_ASSIGN]);
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for slice operations on strings
+ ///
+ /// ### Why is this bad?
+ /// UTF-8 characters span multiple bytes, and it is easy to inadvertently confuse character
+ /// counts and string indices. This may lead to panics, and should warrant some test cases
+ /// containing wide UTF-8 characters. This lint is most useful in code that should avoid
+ /// panics at all costs.
+ ///
+ /// ### Known problems
+ /// Probably lots of false positives. If an index comes from a known valid position (e.g.
+ /// obtained via `char_indices` over the same string), it is totally OK.
+ ///
+ /// # Example
+ /// ```rust,should_panic
+ /// &"Ölkanne"[1..];
+ /// ```
+ pub STRING_SLICE,
+ restriction,
+ "slicing a string"
+}
+
+declare_lint_pass!(StringAdd => [STRING_ADD, STRING_ADD_ASSIGN, STRING_SLICE]);
impl<'tcx> LateLintPass<'tcx> for StringAdd {
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
if in_external_macro(cx.sess(), e.span) {
return;
}
-
- if let ExprKind::Binary(
- Spanned {
- node: BinOpKind::Add, ..
- },
- left,
- _,
- ) = e.kind
- {
- if is_string(cx, left) {
- if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) {
- let parent = get_parent_expr(cx, e);
- if let Some(p) = parent {
- if let ExprKind::Assign(target, _, _) = p.kind {
- // avoid duplicate matches
- if SpanlessEq::new(cx).eq_expr(target, left) {
- return;
+ match e.kind {
+ ExprKind::Binary(
+ Spanned {
+ node: BinOpKind::Add, ..
+ },
+ left,
+ _,
+ ) => {
+ if is_string(cx, left) {
+ if !is_lint_allowed(cx, STRING_ADD_ASSIGN, e.hir_id) {
+ let parent = get_parent_expr(cx, e);
+ if let Some(p) = parent {
+ if let ExprKind::Assign(target, _, _) = p.kind {
+ // avoid duplicate matches
+ if SpanlessEq::new(cx).eq_expr(target, left) {
+ return;
+ }
}
}
}
+ span_lint(
+ cx,
+ STRING_ADD,
+ e.span,
+ "you added something to a string. Consider using `String::push_str()` instead",
+ );
}
- span_lint(
- cx,
- STRING_ADD,
- e.span,
- "you added something to a string. Consider using `String::push_str()` instead",
- );
- }
- } else if let ExprKind::Assign(target, src, _) = e.kind {
- if is_string(cx, target) && is_add(cx, src, target) {
- span_lint(
- cx,
- STRING_ADD_ASSIGN,
- e.span,
- "you assigned the result of adding something to this string. Consider using \
- `String::push_str()` instead",
- );
- }
+ },
+ ExprKind::Assign(target, src, _) => {
+ if is_string(cx, target) && is_add(cx, src, target) {
+ span_lint(
+ cx,
+ STRING_ADD_ASSIGN,
+ e.span,
+ "you assigned the result of adding something to this string. Consider using \
+ `String::push_str()` instead",
+ );
+ }
+ },
+ ExprKind::Index(target, _idx) => {
+ let e_ty = cx.typeck_results().expr_ty(target).peel_refs();
+ if matches!(e_ty.kind(), ty::Str) || is_type_diagnostic_item(cx, e_ty, sym::String) {
+ span_lint(
+ cx,
+ STRING_SLICE,
+ e.span,
+ "indexing into a string may panic if the index is within a UTF-8 character",
+ );
+ }
+ },
+ _ => {},
}
}
}
let file_name = source_map.span_to_filename(between_span);
let source_file = source_map.get_source_file(&file_name)?;
- let lex_start = (between_span.lo().0 + 1) as usize;
- let src_str = source_file.src.as_ref()?[lex_start..between_span.hi().0 as usize].to_string();
+ let lex_start = (between_span.lo().0 - source_file.start_pos.0 + 1) as usize;
+ let lex_end = (between_span.hi().0 - source_file.start_pos.0) as usize;
+ let src_str = source_file.src.as_ref()?[lex_start..lex_end].to_string();
let mut pos = 0;
let mut comment = false;
/// let x = String::from("\u{20ac}");
/// ```
pub NON_ASCII_LITERAL,
- pedantic,
+ restriction,
"using any literal non-ASCII chars in a string literal instead of using the `\\u` escape"
}
--- /dev/null
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::source::snippet;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Detects `().hash(_)`.
+ ///
+ /// ### Why is this bad?
+ /// Hashing a unit value doesn't do anything as the implementation of `Hash` for `()` is a no-op.
+ ///
+ /// ### Example
+ /// ```rust
+ /// # use std::hash::Hash;
+ /// # use std::collections::hash_map::DefaultHasher;
+ /// # enum Foo { Empty, WithValue(u8) }
+ /// # use Foo::*;
+ /// # let mut state = DefaultHasher::new();
+ /// # let my_enum = Foo::Empty;
+ /// match my_enum {
+ /// Empty => ().hash(&mut state),
+ /// WithValue(x) => x.hash(&mut state),
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// # use std::hash::Hash;
+ /// # use std::collections::hash_map::DefaultHasher;
+ /// # enum Foo { Empty, WithValue(u8) }
+ /// # use Foo::*;
+ /// # let mut state = DefaultHasher::new();
+ /// # let my_enum = Foo::Empty;
+ /// match my_enum {
+ /// Empty => 0_u8.hash(&mut state),
+ /// WithValue(x) => x.hash(&mut state),
+ /// }
+ /// ```
+ pub UNIT_HASH,
+ correctness,
+ "hashing a unit value, which does nothing"
+}
+declare_lint_pass!(UnitHash => [UNIT_HASH]);
+
+impl LateLintPass<'tcx> for UnitHash {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+ if_chain! {
+ if let ExprKind::MethodCall(name_ident, _, args, _) = &expr.kind;
+ if name_ident.ident.name == sym::hash;
+ if let [recv, state_param] = args;
+ if cx.typeck_results().expr_ty(recv).is_unit();
+ then {
+ span_lint_and_then(
+ cx,
+ UNIT_HASH,
+ expr.span,
+ "this call to `hash` on the unit type will do nothing",
+ |diag| {
+ diag.span_suggestion(
+ expr.span,
+ "remove the call to `hash` or consider using",
+ format!(
+ "0_u8.hash({})",
+ snippet(cx, state_param.span, ".."),
+ ),
+ Applicability::MaybeIncorrect,
+ );
+ diag.note("the implementation of `Hash` for `()` is a no-op");
+ }
+ );
+ }
+ }
+ }
+}
declare_clippy_lint! {
/// ### What it does
- /// Checks for functions of type Result that contain `expect()` or `unwrap()`
+ /// Checks for functions of type `Result` that contain `expect()` or `unwrap()`
///
/// ### Why is this bad?
/// These functions promote recoverable errors to non-recoverable errors which may be undesirable in code bases which wish to avoid panics.
///
/// 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.
+ /// Lint: DISALLOWED_SCRIPT_IDENTS.
///
/// The list of unicode scripts allowed to be used in the scope.
- (allowed_scripts: Vec<String> = vec!["Latin".to_string()]),
+ (allowed_scripts: Vec<String> = ["Latin"].iter().map(ToString::to_string).collect()),
/// Lint: NON_SEND_FIELDS_IN_SEND_TY.
///
/// Whether to apply the raw pointer heuristic to determine if a type is `Send`.
let mut lines = attrs.iter().filter_map(ast::Attribute::doc_str);
let mut docs = String::from(&*lines.next()?.as_str());
let mut in_code_block = false;
+ let mut is_code_block_rust = false;
for line in lines {
- docs.push('\n');
let line = line.as_str();
let line = &*line;
+
+ // Rustdoc hides code lines starting with `# ` and this removes them from Clippy's lint list :)
+ if is_code_block_rust && line.trim_start().starts_with("# ") {
+ continue;
+ }
+
+ // The line should be represented in the lint list, even if it's just an empty line
+ docs.push('\n');
if let Some(info) = line.trim_start().strip_prefix("```") {
in_code_block = !in_code_block;
+ is_code_block_rust = false;
if in_code_block {
let lang = info
.trim()
.unwrap_or("rust");
docs.push_str("```");
docs.push_str(lang);
+
+ is_code_block_rust = lang == "rust";
continue;
}
}
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::{snippet_opt, snippet_with_applicability};
-use rustc_ast::ast::{Expr, ExprKind, ImplKind, Item, ItemKind, MacCall, Path, StrLit, StrStyle};
+use rustc_ast::ast::{Expr, ExprKind, Impl, Item, ItemKind, MacCall, Path, StrLit, StrStyle};
use rustc_ast::token::{self, LitKind};
use rustc_ast::tokenstream::TokenStream;
use rustc_errors::Applicability;
impl EarlyLintPass for Write {
fn check_item(&mut self, _: &EarlyContext<'_>, item: &Item) {
- if let ItemKind::Impl(box ImplKind {
+ if let ItemKind::Impl(box Impl {
of_trait: Some(trait_ref),
..
}) = &item.kind
(Use(l), Use(r)) => eq_use_tree(l, r),
(Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
(Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
- (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
+ (Fn(box ast::Fn { defaultness: ld, sig: lf, generics: lg, body: lb }),
+ Fn(box ast::Fn { defaultness: rd, sig: rf, generics: rg, body: rb })) => {
eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
},
(Mod(lu, lmk), Mod(ru, rmk)) => {
(ForeignMod(l), ForeignMod(r)) => {
both(&l.abi, &r.abi, eq_str_lit) && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind))
},
- (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
+ (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt }),
+ TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt })) => {
eq_defaultness(*ld, *rd)
&& eq_generics(lg, rg)
&& over(lb, rb, eq_generic_bound)
(Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => {
eq_variant_data(lv, rv) && eq_generics(lg, rg)
},
- (Trait(box TraitKind(la, lu, lg, lb, li)), Trait(box TraitKind(ra, ru, rg, rb, ri))) => {
+ (Trait(box ast::Trait { is_auto: la, unsafety: lu, generics: lg, bounds: lb, items: li }),
+ Trait(box ast::Trait { is_auto: ra, unsafety: ru, generics: rg, bounds: rb, items: ri })) => {
la == ra
&& matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No)
&& eq_generics(lg, rg)
},
(TraitAlias(lg, lb), TraitAlias(rg, rb)) => eq_generics(lg, rg) && over(lb, rb, eq_generic_bound),
(
- Impl(box ImplKind {
+ Impl(box ast::Impl {
unsafety: lu,
polarity: lp,
defaultness: ld,
self_ty: lst,
items: li,
}),
- Impl(box ImplKind {
+ Impl(box ast::Impl {
unsafety: ru,
polarity: rp,
defaultness: rd,
use ForeignItemKind::*;
match (l, r) {
(Static(lt, lm, le), Static(rt, rm, re)) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
- (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
+ (Fn(box ast::Fn { defaultness: ld, sig: lf, generics: lg, body: lb }),
+ Fn(box ast::Fn { defaultness: rd, sig: rf, generics: rg, body: rb })) => {
eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
},
- (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
+ (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt }),
+ TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt })) => {
eq_defaultness(*ld, *rd)
&& eq_generics(lg, rg)
&& over(lb, rb, eq_generic_bound)
use AssocItemKind::*;
match (l, r) {
(Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
- (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
+ (Fn(box ast::Fn { defaultness: ld, sig: lf, generics: lg, body: lb }),
+ Fn(box ast::Fn { defaultness: rd, sig: rf, generics: rg, body: rb })) => {
eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
},
- (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
+ (TyAlias(box ast::TyAlias { defaultness: ld, generics: lg, bounds: lb, ty: lt }),
+ TyAlias(box ast::TyAlias { defaultness: rd, generics: rg, bounds: rb, ty: rt })) => {
eq_defaultness(*ld, *rd)
&& eq_generics(lg, rg)
&& over(lb, rb, eq_generic_bound)
+++ /dev/null
-/// Returns the index of the character after the first camel-case component of `s`.
-#[must_use]
-pub fn until(s: &str) -> usize {
- let mut iter = s.char_indices();
- if let Some((_, first)) = iter.next() {
- if !first.is_uppercase() {
- return 0;
- }
- } else {
- return 0;
- }
- let mut up = true;
- let mut last_i = 0;
- for (i, c) in iter {
- if up {
- if c.is_lowercase() {
- up = false;
- } else {
- return last_i;
- }
- } else if c.is_uppercase() {
- up = true;
- last_i = i;
- } else if !c.is_lowercase() {
- return i;
- }
- }
- if up { last_i } else { s.len() }
-}
-
-/// Returns index of the last camel-case component of `s`.
-#[must_use]
-pub fn from(s: &str) -> usize {
- let mut iter = s.char_indices().rev();
- if let Some((_, first)) = iter.next() {
- if !first.is_lowercase() {
- return s.len();
- }
- } else {
- return s.len();
- }
- let mut down = true;
- let mut last_i = s.len();
- for (i, c) in iter {
- if down {
- if c.is_uppercase() {
- down = false;
- last_i = i;
- } else if !c.is_lowercase() {
- return last_i;
- }
- } else if c.is_lowercase() {
- down = true;
- } else if c.is_uppercase() {
- last_i = i;
- } else {
- return last_i;
- }
- }
- last_i
-}
-
-#[cfg(test)]
-mod test {
- use super::{from, until};
-
- #[test]
- fn from_full() {
- assert_eq!(from("AbcDef"), 0);
- assert_eq!(from("Abc"), 0);
- assert_eq!(from("ABcd"), 0);
- assert_eq!(from("ABcdEf"), 0);
- assert_eq!(from("AabABcd"), 0);
- }
-
- #[test]
- fn from_partial() {
- assert_eq!(from("abcDef"), 3);
- assert_eq!(from("aDbc"), 1);
- assert_eq!(from("aabABcd"), 3);
- }
-
- #[test]
- fn from_not() {
- assert_eq!(from("AbcDef_"), 7);
- assert_eq!(from("AbcDD"), 5);
- }
-
- #[test]
- fn from_caps() {
- assert_eq!(from("ABCD"), 4);
- }
-
- #[test]
- fn until_full() {
- assert_eq!(until("AbcDef"), 6);
- assert_eq!(until("Abc"), 3);
- }
-
- #[test]
- fn until_not() {
- assert_eq!(until("abcDef"), 0);
- assert_eq!(until("aDbc"), 0);
- }
-
- #[test]
- fn until_partial() {
- assert_eq!(until("AbcDef_"), 6);
- assert_eq!(until("CallTypeC"), 8);
- assert_eq!(until("AbcDD"), 3);
- }
-
- #[test]
- fn until_caps() {
- assert_eq!(until("ABCD"), 0);
- }
-}
_ => None,
}
}
+
+ /// Returns the integer value or `None` if `self` or `val_type` is not integer type.
+ pub fn int_value(&self, cx: &LateContext<'_>, val_type: Ty<'_>) -> Option<FullInt> {
+ if let Constant::Int(const_int) = *self {
+ match *val_type.kind() {
+ ty::Int(ity) => Some(FullInt::S(sext(cx.tcx, const_int, ity))),
+ ty::Uint(_) => Some(FullInt::U(const_int)),
+ _ => None,
+ }
+ } else {
+ None
+ }
+ }
}
/// Parses a `LitKind` to a `Constant`.
constant(lcx, typeck_results, e).and_then(|(cst, res)| if res { None } else { Some(cst) })
}
+pub fn constant_full_int(
+ lcx: &LateContext<'tcx>,
+ typeck_results: &ty::TypeckResults<'tcx>,
+ e: &Expr<'_>,
+) -> Option<FullInt> {
+ constant_simple(lcx, typeck_results, e)?.int_value(lcx, typeck_results.expr_ty(e))
+}
+
+#[derive(Copy, Clone, Debug, Eq)]
+pub enum FullInt {
+ S(i128),
+ U(u128),
+}
+
+impl PartialEq for FullInt {
+ #[must_use]
+ fn eq(&self, other: &Self) -> bool {
+ self.cmp(other) == Ordering::Equal
+ }
+}
+
+impl PartialOrd for FullInt {
+ #[must_use]
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for FullInt {
+ #[must_use]
+ fn cmp(&self, other: &Self) -> Ordering {
+ use FullInt::{S, U};
+
+ fn cmp_s_u(s: i128, u: u128) -> Ordering {
+ u128::try_from(s).map_or(Ordering::Less, |x| x.cmp(&u))
+ }
+
+ match (*self, *other) {
+ (S(s), S(o)) => s.cmp(&o),
+ (U(s), U(o)) => s.cmp(&o),
+ (S(s), U(o)) => cmp_s_u(s, o),
+ (U(s), S(o)) => cmp_s_u(o, s).reverse(),
+ }
+ }
+}
+
/// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckResults`.
pub fn constant_context<'a, 'tcx>(
lcx: &'a LateContext<'tcx>,
/// 6 | let other_f64_nan = 0.0f64 / 0.0;
/// | ^^^^^^^^^^^^
/// |
-/// = help: Consider using `f64::NAN` if you would like a constant representing NaN
+/// = help: consider using `f64::NAN` if you would like a constant representing NaN
/// ```
pub fn span_lint_and_help<'a, T: LintContext>(
cx: &'a T,
-//! This module contains functions that retrieves specifiec elements.
+//! This module contains functions that retrieve specific elements.
#![deny(clippy::missing_docs_in_private_items)]
use crate::ty::is_type_diagnostic_item;
-use crate::{is_expn_of, last_path_segment, match_def_path, paths};
+use crate::{is_expn_of, last_path_segment, match_def_path, path_to_local_id, paths};
use if_chain::if_chain;
use rustc_ast::ast::{self, LitKind};
use rustc_hir as hir;
use rustc_hir::{
- Arm, Block, BorrowKind, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath, StmtKind, UnOp,
+ Arm, Block, BorrowKind, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, PatKind, QPath, StmtKind, UnOp,
};
use rustc_lint::LateContext;
use rustc_span::{sym, symbol, ExpnKind, Span, Symbol};
pub format_string_parts: &'tcx [Expr<'tcx>],
/// Symbols corresponding to [`Self::format_string_parts`]
pub format_string_symbols: Vec<Symbol>,
+ /// Match arm patterns, the `arg0`, etc. from the next field `args`
+ pub arg_names: &'tcx [Pat<'tcx>],
/// Expressions like `ArgumentV1::new(arg0, Debug::fmt)`
pub args: &'tcx [Expr<'tcx>],
/// The final argument passed to `Arguments::new_v1_formatted`, if applicable
_ => None,
})
.collect();
+ if let PatKind::Tuple(arg_names, None) = arm.pat.kind;
if let ExprKind::Array(args) = arm.body.kind;
then {
Some(FormatArgsExpn {
value_args,
format_string_parts,
format_string_symbols,
+ arg_names,
args,
fmt_expr,
})
if let Some(position_field) = fields.iter().find(|f| f.ident.name == sym::position);
if let ExprKind::Lit(lit) = &position_field.expr.kind;
if let LitKind::Int(position, _) = lit.node;
+ if let Ok(i) = usize::try_from(position);
+ let arg = &self.args[i];
+ if let ExprKind::Call(_, [arg_name, _]) = arg.kind;
+ if let Some(j) = self
+ .arg_names
+ .iter()
+ .position(|pat| path_to_local_id(arg_name, pat.hir_id));
then {
- let i = usize::try_from(position).unwrap();
- Some(FormatArgsArg { value: self.value_args[i], arg: &self.args[i], fmt: Some(fmt) })
+ Some(FormatArgsArg { value: self.value_args[j], arg, fmt: Some(fmt) })
} else {
None
}
/// Parses an expanded `panic!` invocation
pub fn parse(expr: &'tcx Expr<'tcx>) -> Option<Self> {
if_chain! {
- if let ExprKind::Block(block, _) = expr.kind;
- if let Some(init) = block.expr;
- if let ExprKind::Call(_, [format_args]) = init.kind;
+ if let ExprKind::Call(_, [format_args]) = expr.kind;
let expn_data = expr.span.ctxt().outer_expn_data();
if let Some(format_args) = FormatArgsExpn::parse(format_args);
then {
}
return Some(VecInitKind::WithExprCapacity(arg.hir_id));
}
- }
+ },
ExprKind::Path(QPath::Resolved(_, path))
if match_def_path(cx, path.res.opt_def_id()?, &paths::DEFAULT_TRAIT_METHOD)
&& is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Vec) =>
{
return Some(VecInitKind::Default);
- }
+ },
_ => (),
}
}
#[allow(clippy::module_name_repetitions)]
pub mod ast_utils;
pub mod attrs;
-pub mod camel_case;
pub mod comparisons;
pub mod consts;
pub mod diagnostics;
pub mod ptr;
pub mod qualify_min_const_fn;
pub mod source;
+pub mod str_utils;
pub mod sugg;
pub mod ty;
pub mod usage;
/// Checks if the top level expression can be moved into a closure as is.
/// Currently checks for:
/// * Break/Continue outside the given loop HIR ids.
-/// * Yield/Return statments.
+/// * Yield/Return statements.
/// * Inline assembly.
/// * Usages of a field of a local where the type of the local can be partially moved.
///
let mut capture_expr_ty = e;
for (parent_id, parent) in cx.tcx.hir().parent_iter(e.hir_id) {
- if let [Adjustment {
- kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
- target,
- }, ref adjust @ ..] = *cx
+ if let [
+ Adjustment {
+ kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
+ target,
+ },
+ ref adjust @ ..,
+ ] = *cx
.typeck_results()
.adjustments()
.get(child_id)
for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
match node {
Node::Expr(
- e
- @
- Expr {
+ e @ Expr {
kind: ExprKind::Loop(..) | ExprKind::Closure(..),
..
},
pub fn get_async_fn_body(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
if let ExprKind::Call(
_,
- &[Expr {
- kind: ExprKind::Closure(_, _, body, _, _),
- ..
- }],
+ &[
+ Expr {
+ kind: ExprKind::Closure(_, _, body, _, _),
+ ..
+ },
+ ],
) = body.value.kind
{
if let ExprKind::Block(
vis.found
}
-/// Checks whether item either has `test` attribute appelied, or
+/// Checks whether item either has `test` attribute applied, or
/// is a module with `test` in its name.
///
/// Note: If you use this function, please add a `#[test]` case in `tests/ui_test`.
--- /dev/null
+/// Dealing with sting indices can be hard, this struct ensures that both the
+/// character and byte index are provided for correct indexing.
+#[derive(Debug, Default, PartialEq, Eq)]
+pub struct StrIndex {
+ pub char_index: usize,
+ pub byte_index: usize,
+}
+
+impl StrIndex {
+ pub fn new(char_index: usize, byte_index: usize) -> Self {
+ Self { char_index, byte_index }
+ }
+}
+
+/// Returns the index of the character after the first camel-case component of `s`.
+///
+/// ```
+/// assert_eq!(camel_case_until("AbcDef"), StrIndex::new(6, 6));
+/// assert_eq!(camel_case_until("ABCD"), StrIndex::new(0, 0));
+/// assert_eq!(camel_case_until("AbcDD"), StrIndex::new(3, 3));
+/// assert_eq!(camel_case_until("Abc\u{f6}\u{f6}DD"), StrIndex::new(5, 7));
+/// ```
+#[must_use]
+pub fn camel_case_until(s: &str) -> StrIndex {
+ let mut iter = s.char_indices().enumerate();
+ if let Some((_char_index, (_, first))) = iter.next() {
+ if !first.is_uppercase() {
+ return StrIndex::new(0, 0);
+ }
+ } else {
+ return StrIndex::new(0, 0);
+ }
+ let mut up = true;
+ let mut last_index = StrIndex::new(0, 0);
+ for (char_index, (byte_index, c)) in iter {
+ if up {
+ if c.is_lowercase() {
+ up = false;
+ } else {
+ return last_index;
+ }
+ } else if c.is_uppercase() {
+ up = true;
+ last_index.byte_index = byte_index;
+ last_index.char_index = char_index;
+ } else if !c.is_lowercase() {
+ return StrIndex::new(char_index, byte_index);
+ }
+ }
+
+ if up {
+ last_index
+ } else {
+ StrIndex::new(s.chars().count(), s.len())
+ }
+}
+
+/// Returns index of the last camel-case component of `s`.
+///
+/// ```
+/// assert_eq!(camel_case_start("AbcDef"), StrIndex::new(0, 0));
+/// assert_eq!(camel_case_start("abcDef"), StrIndex::new(3, 3));
+/// assert_eq!(camel_case_start("ABCD"), StrIndex::new(4, 4));
+/// assert_eq!(camel_case_start("abcd"), StrIndex::new(4, 4));
+/// assert_eq!(camel_case_start("\u{f6}\u{f6}cd"), StrIndex::new(4, 6));
+/// ```
+#[must_use]
+pub fn camel_case_start(s: &str) -> StrIndex {
+ let char_count = s.chars().count();
+ let range = 0..char_count;
+ let mut iter = range.rev().zip(s.char_indices().rev());
+ if let Some((char_index, (_, first))) = iter.next() {
+ if !first.is_lowercase() {
+ return StrIndex::new(char_index, s.len());
+ }
+ } else {
+ return StrIndex::new(char_count, s.len());
+ }
+ let mut down = true;
+ let mut last_index = StrIndex::new(char_count, s.len());
+ for (char_index, (byte_index, c)) in iter {
+ if down {
+ if c.is_uppercase() {
+ down = false;
+ last_index.byte_index = byte_index;
+ last_index.char_index = char_index;
+ } else if !c.is_lowercase() {
+ return last_index;
+ }
+ } else if c.is_lowercase() {
+ down = true;
+ } else if c.is_uppercase() {
+ last_index.byte_index = byte_index;
+ last_index.char_index = char_index;
+ } else {
+ return last_index;
+ }
+ }
+ last_index
+}
+
+/// Dealing with sting comparison can be complicated, this struct ensures that both the
+/// character and byte count are provided for correct indexing.
+#[derive(Debug, Default, PartialEq, Eq)]
+pub struct StrCount {
+ pub char_count: usize,
+ pub byte_count: usize,
+}
+
+impl StrCount {
+ pub fn new(char_count: usize, byte_count: usize) -> Self {
+ Self { char_count, byte_count }
+ }
+}
+
+/// Returns the number of chars that match from the start
+///
+/// ```
+/// assert_eq!(count_match_start("hello_mouse", "hello_penguin"), StrCount::new(6, 6));
+/// assert_eq!(count_match_start("hello_clippy", "bye_bugs"), StrCount::new(0, 0));
+/// assert_eq!(count_match_start("hello_world", "hello_world"), StrCount::new(11, 11));
+/// assert_eq!(count_match_start("T\u{f6}ffT\u{f6}ff", "T\u{f6}ff"), StrCount::new(4, 5));
+/// ```
+#[must_use]
+pub fn count_match_start(str1: &str, str2: &str) -> StrCount {
+ // (char_index, char1)
+ let char_count = str1.chars().count();
+ let iter1 = (0..=char_count).zip(str1.chars());
+ // (byte_index, char2)
+ let iter2 = str2.char_indices();
+
+ iter1
+ .zip(iter2)
+ .take_while(|((_, c1), (_, c2))| c1 == c2)
+ .last()
+ .map_or_else(StrCount::default, |((char_index, _), (byte_index, character))| {
+ StrCount::new(char_index + 1, byte_index + character.len_utf8())
+ })
+}
+
+/// Returns the number of chars and bytes that match from the end
+///
+/// ```
+/// assert_eq!(count_match_end("hello_cat", "bye_cat"), StrCount::new(4, 4));
+/// assert_eq!(count_match_end("if_item_thing", "enum_value"), StrCount::new(0, 0));
+/// assert_eq!(count_match_end("Clippy", "Clippy"), StrCount::new(6, 6));
+/// assert_eq!(count_match_end("MyT\u{f6}ff", "YourT\u{f6}ff"), StrCount::new(4, 5));
+/// ```
+#[must_use]
+pub fn count_match_end(str1: &str, str2: &str) -> StrCount {
+ let char_count = str1.chars().count();
+ if char_count == 0 {
+ return StrCount::default();
+ }
+
+ // (char_index, char1)
+ let iter1 = (0..char_count).rev().zip(str1.chars().rev());
+ // (byte_index, char2)
+ let byte_count = str2.len();
+ let iter2 = str2.char_indices().rev();
+
+ iter1
+ .zip(iter2)
+ .take_while(|((_, c1), (_, c2))| c1 == c2)
+ .last()
+ .map_or_else(StrCount::default, |((char_index, _), (byte_index, _))| {
+ StrCount::new(char_count - char_index, byte_count - byte_index)
+ })
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn camel_case_start_full() {
+ assert_eq!(camel_case_start("AbcDef"), StrIndex::new(0, 0));
+ assert_eq!(camel_case_start("Abc"), StrIndex::new(0, 0));
+ assert_eq!(camel_case_start("ABcd"), StrIndex::new(0, 0));
+ assert_eq!(camel_case_start("ABcdEf"), StrIndex::new(0, 0));
+ assert_eq!(camel_case_start("AabABcd"), StrIndex::new(0, 0));
+ }
+
+ #[test]
+ fn camel_case_start_partial() {
+ assert_eq!(camel_case_start("abcDef"), StrIndex::new(3, 3));
+ assert_eq!(camel_case_start("aDbc"), StrIndex::new(1, 1));
+ assert_eq!(camel_case_start("aabABcd"), StrIndex::new(3, 3));
+ assert_eq!(camel_case_start("\u{f6}\u{f6}AabABcd"), StrIndex::new(2, 4));
+ }
+
+ #[test]
+ fn camel_case_start_not() {
+ assert_eq!(camel_case_start("AbcDef_"), StrIndex::new(7, 7));
+ assert_eq!(camel_case_start("AbcDD"), StrIndex::new(5, 5));
+ assert_eq!(camel_case_start("all_small"), StrIndex::new(9, 9));
+ assert_eq!(camel_case_start("\u{f6}_all_small"), StrIndex::new(11, 12));
+ }
+
+ #[test]
+ fn camel_case_start_caps() {
+ assert_eq!(camel_case_start("ABCD"), StrIndex::new(4, 4));
+ }
+
+ #[test]
+ fn camel_case_until_full() {
+ assert_eq!(camel_case_until("AbcDef"), StrIndex::new(6, 6));
+ assert_eq!(camel_case_until("Abc"), StrIndex::new(3, 3));
+ assert_eq!(camel_case_until("Abc\u{f6}\u{f6}\u{f6}"), StrIndex::new(6, 9));
+ }
+
+ #[test]
+ fn camel_case_until_not() {
+ assert_eq!(camel_case_until("abcDef"), StrIndex::new(0, 0));
+ assert_eq!(camel_case_until("aDbc"), StrIndex::new(0, 0));
+ }
+
+ #[test]
+ fn camel_case_until_partial() {
+ assert_eq!(camel_case_until("AbcDef_"), StrIndex::new(6, 6));
+ assert_eq!(camel_case_until("CallTypeC"), StrIndex::new(8, 8));
+ assert_eq!(camel_case_until("AbcDD"), StrIndex::new(3, 3));
+ assert_eq!(camel_case_until("Abc\u{f6}\u{f6}DD"), StrIndex::new(5, 7));
+ }
+
+ #[test]
+ fn until_caps() {
+ assert_eq!(camel_case_until("ABCD"), StrIndex::new(0, 0));
+ }
+}
- [Edition 2018 tests](#edition-2018-tests)
- [Testing manually](#testing-manually)
- [Lint declaration](#lint-declaration)
+ - [Lint registration](#lint-registration)
- [Lint passes](#lint-passes)
- [Emitting a lint](#emitting-a-lint)
- [Adding the lint logic](#adding-the-lint-logic)
lint you can run `cargo dev new_lint --name=foo_functions --pass=early
--category=pedantic` (category will default to nursery if not provided). This
command will create two files: `tests/ui/foo_functions.rs` and
-`clippy_lints/src/foo_functions.rs`, as well as run `cargo dev update_lints` to
-register the new lint. For cargo lints, two project hierarchies (fail/pass) will
-be created by default under `tests/ui-cargo`.
+`clippy_lints/src/foo_functions.rs`, as well as
+[registering the lint](#lint-registration). For cargo lints, two project
+hierarchies (fail/pass) will be created by default under `tests/ui-cargo`.
Next, we'll open up these files and add our lint!
impl EarlyLintPass for FooFunctions {}
```
-Normally after declaring the lint, we have to run `cargo dev update_lints`,
-which updates some files, so Clippy knows about the new lint. Since we used
-`cargo dev new_lint ...` to generate the lint declaration, this was done
-automatically. While `update_lints` automates most of the things, it doesn't
-automate everything. We will have to register our lint pass manually in the
-`register_plugins` function in `clippy_lints/src/lib.rs`:
+[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60
+[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
+[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
+[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110
+
+## Lint registration
+
+When using `cargo dev new_lint`, the lint is automatically registered and
+nothing more has to be done.
+
+When declaring a new lint by hand and `cargo dev update_lints` is used, the lint
+pass may have to be registered manually in the `register_plugins` function in
+`clippy_lints/src/lib.rs`:
```rust
-store.register_early_pass(|| box foo_functions::FooFunctions);
+store.register_early_pass(|| Box::new(foo_functions::FooFunctions));
```
As one may expect, there is a corresponding `register_late_pass` method
available as well. Without a call to one of `register_early_pass` or
`register_late_pass`, the lint pass in question will not be run.
-One reason that `cargo dev` does not automate this step is that multiple lints
-can use the same lint pass, so registering the lint pass may already be done
-when adding a new lint. Another reason that this step is not automated is that
-the order that the passes are registered determines the order the passes
-actually run, which in turn affects the order that any emitted lints are output
-in.
-
-[declare_clippy_lint]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L60
-[example_lint_page]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure
-[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
-[category_level_mapping]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/lib.rs#L110
+One reason that `cargo dev update_lints` does not automate this step is that
+multiple lints can use the same lint pass, so registering the lint pass may
+already be done when adding a new lint. Another reason that this step is not
+automated is that the order that the passes are registered determines the order
+the passes actually run, which in turn affects the order that any emitted lints
+are output in.
## Lint passes
/// <The configuration field doc comment>
(configuration_ident: Type = DefaultValue),
```
- The doc comment will be automatically added to the lint documentation.
+ The doc comment is automatically added to the documentation of the listed lints. The default
+ value will be formatted using the `Debug` implementation of the type.
2. Adding the configuration value to the lint impl struct:
1. This first requires the definition of a lint impl struct. Lint impl structs are usually
generated with the `declare_lint_pass!` macro. This struct needs to be defined manually
[toolchain]
-channel = "nightly-2021-10-21"
+channel = "nightly-2021-11-04"
components = ["llvm-tools-preview", "rustc-dev", "rust-src"]
}
fn default_config() -> compiletest::Config {
- let mut config = compiletest::Config::default();
+ let mut config = compiletest::Config {
+ edition: Some("2021".into()),
+ ..compiletest::Config::default()
+ };
if let Ok(filters) = env::var("TESTNAME") {
config.filters = filters.split(',').map(std::string::ToString::to_string).collect();
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![warn(rust_2018_idioms, unused_lifetimes)]
#![allow(clippy::assertions_on_constants)]
+#![feature(path_file_prefix)]
+use std::cmp::Ordering;
+use std::ffi::OsStr;
use std::fs::{self, DirEntry};
use std::path::Path;
}
}
-/*
-Test for missing files.
-
-Since rs files are alphabetically before stderr/stdout, we can sort by the full name
-and iter in that order. If we've seen the file stem for the first time and it's not
-a rust file, it means the rust file has to be missing.
-*/
+// Test for missing files.
fn explore_directory(dir: &Path) -> Vec<String> {
let mut missing_files: Vec<String> = Vec::new();
let mut current_file = String::new();
let mut files: Vec<DirEntry> = fs::read_dir(dir).unwrap().filter_map(Result::ok).collect();
- files.sort_by_key(std::fs::DirEntry::path);
+ files.sort_by(|x, y| {
+ match x.path().file_prefix().cmp(&y.path().file_prefix()) {
+ Ordering::Equal => (),
+ ord => return ord,
+ }
+ // Sort rs files before the others if they share the same prefix. So when we see
+ // the file prefix for the first time and it's not a rust file, it means the rust
+ // file has to be missing.
+ match (
+ x.path().extension().and_then(OsStr::to_str),
+ y.path().extension().and_then(OsStr::to_str),
+ ) {
+ (Some("rs"), _) => Ordering::Less,
+ (_, Some("rs")) => Ordering::Greater,
+ _ => Ordering::Equal,
+ }
+ });
for entry in &files {
let path = entry.path();
if path.is_dir() {
missing_files.extend(explore_directory(&path));
} else {
- let file_stem = path.file_stem().unwrap().to_str().unwrap().to_string();
+ let file_prefix = path.file_prefix().unwrap().to_str().unwrap().to_string();
if let Some(ext) = path.extension() {
match ext.to_str().unwrap() {
- "rs" => current_file = file_stem.clone(),
+ "rs" => current_file = file_prefix.clone(),
"stderr" | "stdout" => {
- if file_stem != current_file {
+ if file_prefix != current_file {
missing_files.push(path.to_str().unwrap().to_string());
}
},
-// edition:2018
-
#![warn(clippy::too_many_lines)]
// This function should be considered one line.
error: this function has too many lines (2/1)
- --> $DIR/test.rs:20:1
+ --> $DIR/test.rs:18: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
+ --> $DIR/test.rs:24:1
|
LL | / async fn async_too_many_lines() {
LL | | println!("This is bad.");
| |_^
error: this function has too many lines (4/1)
- --> $DIR/test.rs:32:1
+ --> $DIR/test.rs:30:1
|
LL | / fn closure_too_many_lines() {
LL | | let _ = {
| |_^
error: this function has too many lines (2/1)
- --> $DIR/test.rs:54:1
+ --> $DIR/test.rs:52:1
|
LL | / fn comment_before_code() {
LL | | let _ = "test";
+//FIXME: suggestions are wrongly expanded, this should be fixed along with #7843
#![allow(non_fmt_panics)]
macro_rules! assert_const {
debug_assert!($len < 0);
};
}
-
fn main() {
assert!(true);
assert!(false);
assert!(false, "false message");
let msg = "panic message";
- assert!(false, msg.to_uppercase());
+ assert!(false, "{}", msg.to_uppercase());
const B: bool = true;
assert!(B);
= help: remove it
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: `assert!(false, "false message")` should probably be replaced
+error: `assert!(false, $crate::const_format_args!($($t)+))` should probably be replaced
--> $DIR/assertions_on_constants.rs:14:5
|
LL | assert!(false, "false message");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: use `panic!("false message")` or `unreachable!("false message")`
- = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: `assert!(false, msg.to_uppercase())` should probably be replaced
- --> $DIR/assertions_on_constants.rs:17:5
- |
-LL | assert!(false, msg.to_uppercase());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: use `panic!(msg.to_uppercase())` or `unreachable!(msg.to_uppercase())`
+ = help: use `panic!($crate::const_format_args!($($t)+))` or `unreachable!($crate::const_format_args!($($t)+))`
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `assert!(true)` will be optimized out by the compiler
= help: use `panic!()` or `unreachable!()`
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: `assert!(false, "C message")` should probably be replaced
+error: `assert!(false, $crate::const_format_args!($($t)+))` should probably be replaced
--> $DIR/assertions_on_constants.rs:24:5
|
LL | assert!(C, "C message");
| ^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: use `panic!("C message")` or `unreachable!("C message")`
+ = help: use `panic!($crate::const_format_args!($($t)+))` or `unreachable!($crate::const_format_args!($($t)+))`
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `debug_assert!(true)` will be optimized out by the compiler
= help: remove it
= note: this error originates in the macro `$crate::assert` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
// run-rustfix
-// edition:2018
#![feature(async_closure)]
#![warn(clippy::async_yields_async)]
// run-rustfix
-// edition:2018
#![feature(async_closure)]
#![warn(clippy::async_yields_async)]
error: an async construct yields a type which is itself awaitable
- --> $DIR/async_yields_async.rs:40:9
+ --> $DIR/async_yields_async.rs:39:9
|
LL | let _h = async {
| ____________________-
|
error: an async construct yields a type which is itself awaitable
- --> $DIR/async_yields_async.rs:45:9
+ --> $DIR/async_yields_async.rs:44:9
|
LL | let _i = async {
| ____________________-
| |_____- outer async construct
error: an async construct yields a type which is itself awaitable
- --> $DIR/async_yields_async.rs:51:9
+ --> $DIR/async_yields_async.rs:50:9
|
LL | let _j = async || {
| _______________________-
|
error: an async construct yields a type which is itself awaitable
- --> $DIR/async_yields_async.rs:56:9
+ --> $DIR/async_yields_async.rs:55:9
|
LL | let _k = async || {
| _______________________-
| |_____- outer async construct
error: an async construct yields a type which is itself awaitable
- --> $DIR/async_yields_async.rs:58:23
+ --> $DIR/async_yields_async.rs:57:23
|
LL | let _l = async || CustomFutureType;
| ^^^^^^^^^^^^^^^^
| help: consider awaiting this value: `CustomFutureType.await`
error: an async construct yields a type which is itself awaitable
- --> $DIR/async_yields_async.rs:64:9
+ --> $DIR/async_yields_async.rs:63:9
|
LL | let _m = async || {
| _______________________-
-// edition:2018
#![warn(clippy::await_holding_lock)]
use std::sync::Mutex;
error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
- --> $DIR/await_holding_lock.rs:7:9
+ --> $DIR/await_holding_lock.rs:6:9
|
LL | let guard = x.lock().unwrap();
| ^^^^^
|
= note: `-D clippy::await-holding-lock` implied by `-D warnings`
note: these are all the await points this lock is held through
- --> $DIR/await_holding_lock.rs:7:5
+ --> $DIR/await_holding_lock.rs:6:5
|
LL | / let guard = x.lock().unwrap();
LL | | baz().await
| |_^
error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
- --> $DIR/await_holding_lock.rs:28:9
+ --> $DIR/await_holding_lock.rs:27:9
|
LL | let guard = x.lock().unwrap();
| ^^^^^
|
note: these are all the await points this lock is held through
- --> $DIR/await_holding_lock.rs:28:5
+ --> $DIR/await_holding_lock.rs:27:5
|
LL | / let guard = x.lock().unwrap();
LL | |
| |_^
error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
- --> $DIR/await_holding_lock.rs:41:13
+ --> $DIR/await_holding_lock.rs:40:13
|
LL | let guard = x.lock().unwrap();
| ^^^^^
|
note: these are all the await points this lock is held through
- --> $DIR/await_holding_lock.rs:41:9
+ --> $DIR/await_holding_lock.rs:40:9
|
LL | / let guard = x.lock().unwrap();
LL | | baz().await
| |_____^
error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await
- --> $DIR/await_holding_lock.rs:53:13
+ --> $DIR/await_holding_lock.rs:52:13
|
LL | let guard = x.lock().unwrap();
| ^^^^^
|
note: these are all the await points this lock is held through
- --> $DIR/await_holding_lock.rs:53:9
+ --> $DIR/await_holding_lock.rs:52:9
|
LL | / let guard = x.lock().unwrap();
LL | | baz().await
-// edition:2018
#![warn(clippy::await_holding_refcell_ref)]
use std::cell::RefCell;
error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
- --> $DIR/await_holding_refcell_ref.rs:7:9
+ --> $DIR/await_holding_refcell_ref.rs:6:9
|
LL | let b = x.borrow();
| ^
|
= note: `-D clippy::await-holding-refcell-ref` implied by `-D warnings`
note: these are all the await points this ref is held through
- --> $DIR/await_holding_refcell_ref.rs:7:5
+ --> $DIR/await_holding_refcell_ref.rs:6:5
|
LL | / let b = x.borrow();
LL | | baz().await
| |_^
error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
- --> $DIR/await_holding_refcell_ref.rs:12:9
+ --> $DIR/await_holding_refcell_ref.rs:11:9
|
LL | let b = x.borrow_mut();
| ^
|
note: these are all the await points this ref is held through
- --> $DIR/await_holding_refcell_ref.rs:12:5
+ --> $DIR/await_holding_refcell_ref.rs:11:5
|
LL | / let b = x.borrow_mut();
LL | | baz().await
| |_^
error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
- --> $DIR/await_holding_refcell_ref.rs:33:9
+ --> $DIR/await_holding_refcell_ref.rs:32:9
|
LL | let b = x.borrow_mut();
| ^
|
note: these are all the await points this ref is held through
- --> $DIR/await_holding_refcell_ref.rs:33:5
+ --> $DIR/await_holding_refcell_ref.rs:32:5
|
LL | / let b = x.borrow_mut();
LL | |
| |_^
error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
- --> $DIR/await_holding_refcell_ref.rs:45:9
+ --> $DIR/await_holding_refcell_ref.rs:44:9
|
LL | let b = x.borrow_mut();
| ^
|
note: these are all the await points this ref is held through
- --> $DIR/await_holding_refcell_ref.rs:45:5
+ --> $DIR/await_holding_refcell_ref.rs:44:5
|
LL | / let b = x.borrow_mut();
LL | |
| |_^
error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
- --> $DIR/await_holding_refcell_ref.rs:60:13
+ --> $DIR/await_holding_refcell_ref.rs:59:13
|
LL | let b = x.borrow_mut();
| ^
|
note: these are all the await points this ref is held through
- --> $DIR/await_holding_refcell_ref.rs:60:9
+ --> $DIR/await_holding_refcell_ref.rs:59:9
|
LL | / let b = x.borrow_mut();
LL | | baz().await
| |_____^
error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await
- --> $DIR/await_holding_refcell_ref.rs:72:13
+ --> $DIR/await_holding_refcell_ref.rs:71:13
|
LL | let b = x.borrow_mut();
| ^
|
note: these are all the await points this ref is held through
- --> $DIR/await_holding_refcell_ref.rs:72:9
+ --> $DIR/await_holding_refcell_ref.rs:71:9
|
LL | / let b = x.borrow_mut();
LL | | baz().await
(1i64).checked_rem_euclid(-1i64).unwrap() as u64;
(1i64).checked_rem_euclid(-1i64).unwrap() as u128;
(1isize).checked_rem_euclid(-1isize).unwrap() as usize;
+
+ // no lint for `cast_possible_truncation`
+ // with `signum` method call (see issue #5395)
+ let x: i64 = 5;
+ let _ = x.signum() as i32;
+
+ let s = x.signum();
+ let _ = s as i32;
+
+ // Test for signed min
+ (-99999999999i64).min(1) as i8; // should be linted because signed
+
+ // Test for various operations that remove enough bits for the result to fit
+ (999999u64 & 1) as u8;
+ (999999u64 % 15) as u8;
+ (999999u64 / 0x1_0000_0000_0000) as u16;
+ ({ 999999u64 >> 56 }) as u8;
+ ({
+ let x = 999999u64;
+ x.min(1)
+ }) as u8;
+ 999999u64.clamp(0, 255) as u8;
+ 999999u64.clamp(0, 256) as u8; // should still be linted
}
LL | -1isize as usize;
| ^^^^^^^^^^^^^^^^
-error: aborting due to 22 previous errors
+error: casting `i64` to `i8` may truncate the value
+ --> $DIR/cast.rs:105:5
+ |
+LL | (-99999999999i64).min(1) as i8; // should be linted because signed
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `u64` to `u8` may truncate the value
+ --> $DIR/cast.rs:117:5
+ |
+LL | 999999u64.clamp(0, 256) as u8; // should still be linted
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 24 previous errors
--- /dev/null
+fn zero() {
+ unsafe { 0 };
+}
// in type inference.
#![feature(trivial_bounds)]
#![allow(unused)]
-
trait A {}
impl A for i32 {}
fn unsized_local()
where
- for<'a> Dst<A + 'a>: Sized,
+ for<'a> Dst<dyn A + 'a>: Sized,
{
- let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
+ let x: Dst<dyn A> = *(Box::new(Dst { x: 1 }) as Box<Dst<dyn A>>);
}
fn return_str() -> str
-error: trait objects without an explicit `dyn` are deprecated
- --> $DIR/ice-3969.rs:25:17
+error: trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+ --> $DIR/ice-3969.rs:20:10
|
-LL | for<'a> Dst<A + 'a>: Sized,
- | ^^^^^^ help: use `dyn`: `dyn A + 'a`
+LL | str: Sized;
+ | ^^^^^
|
- = 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 <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `-D trivial-bounds` implied by `-D warnings`
-error: trait objects without an explicit `dyn` are deprecated
- --> $DIR/ice-3969.rs:27:16
+error: trait bound for<'a> Dst<(dyn A + 'a)>: std::marker::Sized does not depend on any type or lifetime parameters
+ --> $DIR/ice-3969.rs:24:30
|
-LL | let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
- | ^ help: use `dyn`: `dyn A`
+LL | for<'a> Dst<dyn A + 'a>: Sized,
+ | ^^^^^
+
+error: trait bound str: std::marker::Sized does not depend on any type or lifetime parameters
+ --> $DIR/ice-3969.rs:31:10
|
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+LL | str: Sized,
+ | ^^^^^
-error: trait objects without an explicit `dyn` are deprecated
- --> $DIR/ice-3969.rs:27:57
+error: trait bound std::string::String: std::ops::Neg does not depend on any type or lifetime parameters
+ --> $DIR/ice-3969.rs:38:13
|
-LL | let x: Dst<A> = *(Box::new(Dst { x: 1 }) as Box<Dst<A>>);
- | ^ help: use `dyn`: `dyn A`
+LL | String: ::std::ops::Neg<Output = String>,
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: trait bound i32: std::iter::Iterator does not depend on any type or lifetime parameters
+ --> $DIR/ice-3969.rs:45:10
|
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+LL | i32: Iterator,
+ | ^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
-// edition:2018
-
// Regression test for https://github.com/rust-lang/rust-clippy/issues/5207
pub async fn bar<'a, T: 'a>(_: T) {}
// originally from glacier fixed/77919.rs
// encountered errors resolving bounds after type-checking
-
trait TypeVal<T> {
const VAL: T;
}
error[E0412]: cannot find type `PhantomData` in this scope
- --> $DIR/ice-6252.rs:9:9
+ --> $DIR/ice-6252.rs:8:9
|
LL | _n: PhantomData,
| ^^^^^^^^^^^ not found in this scope
|
-help: consider importing this struct
+help: consider importing one of these items
+ |
+LL | use core::marker::PhantomData;
+ |
+LL | use serde::__private::PhantomData;
|
LL | use std::marker::PhantomData;
|
error[E0412]: cannot find type `VAL` in this scope
- --> $DIR/ice-6252.rs:11:63
+ --> $DIR/ice-6252.rs:10:63
|
LL | impl<N, M> TypeVal<usize> for Multiply<N, M> where N: TypeVal<VAL> {}
| - ^^^ not found in this scope
| help: you might be missing a type parameter: `, VAL`
error[E0046]: not all trait items implemented, missing: `VAL`
- --> $DIR/ice-6252.rs:11:1
+ --> $DIR/ice-6252.rs:10:1
|
LL | const VAL: T;
| ------------- `VAL` from trait
-// edition:2018
#![allow(clippy::never_loop)]
async fn f() {
--- /dev/null
+#![warn(clippy::undocumented_unsafe_blocks)]
+#![allow(clippy::no_effect)]
+
+#[path = "auxiliary/ice-7868-aux.rs"]
+mod zero;
+
+fn main() {}
--- /dev/null
+error: unsafe block missing a safety comment
+ --> $DIR/auxiliary/ice-7868-aux.rs:2:5
+ |
+LL | unsafe { 0 };
+ | ^^^^^^^^^^^^
+ |
+ = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings`
+help: consider adding a safety comment
+ |
+LL ~ // Safety: ...
+LL ~ unsafe { 0 };
+ |
+
+error: aborting due to previous error
+
--- /dev/null
+enum Tila {
+ TyöAlkoi,
+ TyöKeskeytyi,
+ TyöValmis,
+}
+
+fn main() {}
--- /dev/null
+error: all variants have the same prefix: `Työ`
+ --> $DIR/ice-7869.rs:1:1
+ |
+LL | / enum Tila {
+LL | | TyöAlkoi,
+LL | | TyöKeskeytyi,
+LL | | TyöValmis,
+LL | | }
+ | |_^
+ |
+ = note: `-D clippy::enum-variant-names` implied by `-D warnings`
+ = help: remove the prefixes and use full paths to the variants instead of glob imports
+
+error: aborting due to previous error
+
-// edition:2018
-
use serde::Deserialize;
/// Tests that we do not lint for unused underscores in a `MacroAttribute`
-// compile-flags: --edition=2018
#![feature(custom_inner_attributes)]
#![rustfmt::skip]
#![warn(clippy::debug_assert_with_mut_call)]
#![allow(clippy::redundant_closure_call)]
+
struct S;
impl S {
-#[warn(clippy::unstable_as_slice)]
-#[warn(clippy::unstable_as_mut_slice)]
-#[warn(clippy::misaligned_transmute)]
-#[warn(clippy::unused_collect)]
-#[warn(clippy::invalid_ref)]
-#[warn(clippy::into_iter_on_array)]
-#[warn(clippy::unused_label)]
-#[warn(clippy::regex_macro)]
-#[warn(clippy::drop_bounds)]
-#[warn(clippy::temporary_cstring_as_ptr)]
-#[warn(clippy::panic_params)]
-#[warn(clippy::unknown_clippy_lints)]
-#[warn(clippy::find_map)]
-#[warn(clippy::filter_map)]
-#[warn(clippy::pub_enum_variant_names)]
-#[warn(clippy::wrong_pub_self_convention)]
-#[warn(clippy::invalid_atomic_ordering)]
+#![warn(clippy::should_assert_eq)]
+#![warn(clippy::extend_from_slice)]
+#![warn(clippy::range_step_by_zero)]
+#![warn(clippy::unstable_as_slice)]
+#![warn(clippy::unstable_as_mut_slice)]
+#![warn(clippy::misaligned_transmute)]
+#![warn(clippy::assign_ops)]
+#![warn(clippy::if_let_redundant_pattern_matching)]
+#![warn(clippy::unsafe_vector_initialization)]
+#![warn(clippy::unused_collect)]
+#![warn(clippy::replace_consts)]
+#![warn(clippy::regex_macro)]
+#![warn(clippy::find_map)]
+#![warn(clippy::filter_map)]
+#![warn(clippy::pub_enum_variant_names)]
+#![warn(clippy::wrong_pub_self_convention)]
fn main() {}
-error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` has been stabilized in 1.7
- --> $DIR/deprecated.rs:1:8
+error: lint `clippy::should_assert_eq` has been removed: `assert!()` will be more flexible with RFC 2011
+ --> $DIR/deprecated.rs:1:9
|
-LL | #[warn(clippy::unstable_as_slice)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::should_assert_eq)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
-error: lint `clippy::unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` has been stabilized in 1.7
- --> $DIR/deprecated.rs:2:8
+error: lint `clippy::extend_from_slice` has been removed: `.extend_from_slice(_)` is a faster way to extend a Vec by a slice
+ --> $DIR/deprecated.rs:2:9
|
-LL | #[warn(clippy::unstable_as_mut_slice)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::extend_from_slice)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::misaligned_transmute` has been removed: this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr
- --> $DIR/deprecated.rs:3:8
+error: lint `clippy::range_step_by_zero` has been removed: `iterator.step_by(0)` panics nowadays
+ --> $DIR/deprecated.rs:3:9
|
-LL | #[warn(clippy::misaligned_transmute)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::range_step_by_zero)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::unused_collect` has been removed: `collect` has been marked as #[must_use] in rustc and that covers all cases of this lint
- --> $DIR/deprecated.rs:4:8
+error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` has been stabilized in 1.7
+ --> $DIR/deprecated.rs:4:9
|
-LL | #[warn(clippy::unused_collect)]
- | ^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::unstable_as_slice)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
- --> $DIR/deprecated.rs:5:8
+error: lint `clippy::unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` has been stabilized in 1.7
+ --> $DIR/deprecated.rs:5:9
|
-LL | #[warn(clippy::invalid_ref)]
- | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
+LL | #![warn(clippy::unstable_as_mut_slice)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
- --> $DIR/deprecated.rs:6:8
+error: lint `clippy::misaligned_transmute` has been removed: this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr
+ --> $DIR/deprecated.rs:6:9
|
-LL | #[warn(clippy::into_iter_on_array)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
+LL | #![warn(clippy::misaligned_transmute)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::unused_label` has been renamed to `unused_labels`
- --> $DIR/deprecated.rs:7:8
+error: lint `clippy::assign_ops` has been removed: using compound assignment operators (e.g., `+=`) is harmless
+ --> $DIR/deprecated.rs:7:9
|
-LL | #[warn(clippy::unused_label)]
- | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
+LL | #![warn(clippy::assign_ops)]
+ | ^^^^^^^^^^^^^^^^^^
-error: lint `clippy::regex_macro` has been removed: the regex! macro has been removed from the regex crate in 2018
- --> $DIR/deprecated.rs:8:8
+error: lint `clippy::if_let_redundant_pattern_matching` has been removed: this lint has been changed to redundant_pattern_matching
+ --> $DIR/deprecated.rs:8:9
|
-LL | #[warn(clippy::regex_macro)]
- | ^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::if_let_redundant_pattern_matching)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
- --> $DIR/deprecated.rs:9:8
+error: lint `clippy::unsafe_vector_initialization` has been removed: the replacement suggested by this lint had substantially different behavior
+ --> $DIR/deprecated.rs:9:9
|
-LL | #[warn(clippy::drop_bounds)]
- | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
+LL | #![warn(clippy::unsafe_vector_initialization)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
- --> $DIR/deprecated.rs:10:8
+error: lint `clippy::unused_collect` has been removed: `collect` has been marked as #[must_use] in rustc and that covers all cases of this lint
+ --> $DIR/deprecated.rs:10:9
|
-LL | #[warn(clippy::temporary_cstring_as_ptr)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
+LL | #![warn(clippy::unused_collect)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
- --> $DIR/deprecated.rs:11:8
+error: lint `clippy::replace_consts` has been removed: associated-constants `MIN`/`MAX` of integers are preferred to `{min,max}_value()` and module constants
+ --> $DIR/deprecated.rs:11:9
|
-LL | #[warn(clippy::panic_params)]
- | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
+LL | #![warn(clippy::replace_consts)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
-error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
- --> $DIR/deprecated.rs:12:8
+error: lint `clippy::regex_macro` has been removed: the regex! macro has been removed from the regex crate in 2018
+ --> $DIR/deprecated.rs:12:9
|
-LL | #[warn(clippy::unknown_clippy_lints)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
+LL | #![warn(clippy::regex_macro)]
+ | ^^^^^^^^^^^^^^^^^^^
error: lint `clippy::find_map` has been removed: this lint has been replaced by `manual_find_map`, a more specific lint
- --> $DIR/deprecated.rs:13:8
+ --> $DIR/deprecated.rs:13:9
|
-LL | #[warn(clippy::find_map)]
- | ^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::find_map)]
+ | ^^^^^^^^^^^^^^^^
error: lint `clippy::filter_map` has been removed: this lint has been replaced by `manual_filter_map`, a more specific lint
- --> $DIR/deprecated.rs:14:8
+ --> $DIR/deprecated.rs:14:9
|
-LL | #[warn(clippy::filter_map)]
- | ^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::filter_map)]
+ | ^^^^^^^^^^^^^^^^^^
error: lint `clippy::pub_enum_variant_names` has been removed: set the `avoid-breaking-exported-api` config option to `false` to enable the `enum_variant_names` lint for public items
- --> $DIR/deprecated.rs:15:8
+ --> $DIR/deprecated.rs:15:9
|
-LL | #[warn(clippy::pub_enum_variant_names)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![warn(clippy::pub_enum_variant_names)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: lint `clippy::wrong_pub_self_convention` has been removed: set the `avoid-breaking-exported-api` config option to `false` to enable the `wrong_self_convention` lint for public items
- --> $DIR/deprecated.rs:16:8
- |
-LL | #[warn(clippy::wrong_pub_self_convention)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
- --> $DIR/deprecated.rs:17:8
+ --> $DIR/deprecated.rs:16:9
|
-LL | #[warn(clippy::invalid_atomic_ordering)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
+LL | #![warn(clippy::wrong_pub_self_convention)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 17 previous errors
+error: aborting due to 16 previous errors
#![warn(clippy::diverging_sub_expression)]
#![allow(clippy::match_same_arms, clippy::logic_bug)]
-
#[allow(clippy::empty_loop)]
fn diverge() -> ! {
loop {}
error: sub-expression diverges
- --> $DIR/diverging_sub_expression.rs:20:10
+ --> $DIR/diverging_sub_expression.rs:19:10
|
LL | b || diverge();
| ^^^^^^^^^
= note: `-D clippy::diverging-sub-expression` implied by `-D warnings`
error: sub-expression diverges
- --> $DIR/diverging_sub_expression.rs:21:10
+ --> $DIR/diverging_sub_expression.rs:20:10
|
LL | b || A.foo();
| ^^^^^^^
error: sub-expression diverges
- --> $DIR/diverging_sub_expression.rs:30:26
+ --> $DIR/diverging_sub_expression.rs:29:26
|
LL | 6 => true || return,
| ^^^^^^
error: sub-expression diverges
- --> $DIR/diverging_sub_expression.rs:31:26
+ --> $DIR/diverging_sub_expression.rs:30:26
|
LL | 7 => true || continue,
| ^^^^^^^^
error: sub-expression diverges
- --> $DIR/diverging_sub_expression.rs:34:26
+ --> $DIR/diverging_sub_expression.rs:33:26
|
LL | 3 => true || diverge(),
| ^^^^^^^^^
error: sub-expression diverges
- --> $DIR/diverging_sub_expression.rs:39:26
+ --> $DIR/diverging_sub_expression.rs:36:30
+ |
+LL | _ => true || panic!("boo"),
+ | ^^^^^^^^^^^^^
+ |
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: sub-expression diverges
+ --> $DIR/diverging_sub_expression.rs:38:26
|
LL | _ => true || break,
| ^^^^^
-error: aborting due to 6 previous errors
+error: aborting due to 7 previous errors
--- /dev/null
+// run-rustfix
+//! This file tests for the `DOC_MARKDOWN` lint.
+
+#![allow(dead_code, incomplete_features)]
+#![warn(clippy::doc_markdown)]
+#![feature(custom_inner_attributes, generic_const_exprs, const_option)]
+#![rustfmt::skip]
+
+/// The `foo_bar` function does _nothing_. See also `foo::bar`. (note the dot there)
+/// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not `Foo::some_fun`
+/// which should be reported only once despite being __doubly bad__.
+/// Here be `::a::global:path`, and _`::another::global::path`_. :: is not a path though.
+/// Import an item from `::awesome::global::blob::` (Intended postfix)
+/// These are the options for `::Cat`: (Intended trailing single colon, shouldn't be linted)
+/// That's not code ~`NotInCodeBlock`~.
+/// `be_sure_we_got_to_the_end_of_it`
+fn foo_bar() {
+}
+
+/// That one tests multiline ticks.
+/// ```rust
+/// foo_bar FOO_BAR
+/// _foo bar_
+/// ```
+///
+/// ~~~rust
+/// foo_bar FOO_BAR
+/// _foo bar_
+/// ~~~
+/// `be_sure_we_got_to_the_end_of_it`
+fn multiline_codeblock() {
+}
+
+/// This _is a test for
+/// multiline
+/// emphasis_.
+/// `be_sure_we_got_to_the_end_of_it`
+fn test_emphasis() {
+}
+
+/// This tests units. See also #835.
+/// kiB MiB GiB TiB PiB EiB
+/// kib Mib Gib Tib Pib Eib
+/// kB MB GB TB PB EB
+/// kb Mb Gb Tb Pb Eb
+/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB
+/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib
+/// 32kB 32MB 32GB 32TB 32PB 32EB
+/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb
+/// NaN
+/// `be_sure_we_got_to_the_end_of_it`
+fn test_units() {
+}
+
+/// This tests allowed identifiers.
+/// KiB MiB GiB TiB PiB EiB
+/// DirectX
+/// ECMAScript
+/// GPLv2 GPLv3
+/// GitHub GitLab
+/// IPv4 IPv6
+/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
+/// NaN NaNs
+/// OAuth GraphQL
+/// OCaml
+/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS
+/// WebGL
+/// TensorFlow
+/// TrueType
+/// iOS macOS FreeBSD
+/// TeX LaTeX BibTeX BibLaTeX
+/// MinGW
+/// CamelCase (see also #2395)
+/// `be_sure_we_got_to_the_end_of_it`
+fn test_allowed() {
+}
+
+/// This test has [a `link_with_underscores`][chunked-example] inside it. See #823.
+/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
+/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
+/// It can also be [`inline_link2`].
+///
+/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
+/// [inline_link]: https://foobar
+/// [inline_link2]: https://foobar
+/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and
+/// `multiline_ticks` functions.
+///
+/// expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>`
+/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` ,
+/// `be_sure_we_got_to_the_end_of_it`
+fn main() {
+ foo_bar();
+ multiline_codeblock();
+ test_emphasis();
+ test_units();
+}
+
+/// ## `CamelCaseThing`
+/// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897.
+///
+/// # `CamelCaseThing`
+///
+/// Not a title #897 `CamelCaseThing`
+/// `be_sure_we_got_to_the_end_of_it`
+fn issue897() {
+}
+
+/// I am confused by brackets? (`x_y`)
+/// I am confused by brackets? (foo `x_y`)
+/// I am confused by brackets? (`x_y` foo)
+/// `be_sure_we_got_to_the_end_of_it`
+fn issue900() {
+}
+
+/// Diesel queries also have a similar problem to [Iterator][iterator], where
+/// /// More talking
+/// returning them from a function requires exposing the implementation of that
+/// function. The [`helper_types`][helper_types] module exists to help with this,
+/// but you might want to hide the return type or have it conditionally change.
+/// Boxing can achieve both.
+///
+/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html
+/// [helper_types]: ../helper_types/index.html
+/// `be_sure_we_got_to_the_end_of_it`
+fn issue883() {
+}
+
+/// `foo_bar
+/// baz_quz`
+/// [foo
+/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html)
+fn multiline() {
+}
+
+/** E.g., serialization of an empty list: `FooBar`
+```
+That's in a code block: `PackedNode`
+```
+
+And `BarQuz` too.
+`be_sure_we_got_to_the_end_of_it`
+*/
+fn issue1073() {
+}
+
+/** E.g., serialization of an empty list: `FooBar`
+```
+That's in a code block: PackedNode
+```
+
+And `BarQuz` too.
+`be_sure_we_got_to_the_end_of_it`
+*/
+fn issue1073_alt() {
+}
+
+/// Tests more than three quotes:
+/// ````
+/// DoNotWarn
+/// ```
+/// StillDont
+/// ````
+/// `be_sure_we_got_to_the_end_of_it`
+fn four_quotes() {
+}
+
+#[cfg_attr(feature = "a", doc = " ```")]
+#[cfg_attr(not(feature = "a"), doc = " ```ignore")]
+/// fn main() {
+/// let s = "localhost:10000".to_string();
+/// println!("{}", s);
+/// }
+/// ```
+fn issue_1469() {}
+
+/**
+ * This is a doc comment that should not be a list
+ *This would also be an error under a strict common mark interpretation
+ */
+fn issue_1920() {}
+
+/// An iterator over `mycrate::Collection`'s values.
+/// It should not lint a `'static` lifetime in ticks.
+fn issue_2210() {}
+
+/// This should not cause the lint to trigger:
+/// #REQ-data-family.lint_partof_exists
+fn issue_2343() {}
+
+/// This should not cause an ICE:
+/// __|_ _|__||_|
+fn pulldown_cmark_crash() {}
+
+/// This should not lint
+/// (regression test for #7758)
+/// [plain text][path::to::item]
+fn intra_doc_link() {}
+
+// issue #7033 - generic_const_exprs ICE
+struct S<T, const N: usize>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+ arr: [T; N.checked_next_power_of_two().unwrap()],
+ n: usize,
+}
+
+impl<T: Copy + Default, const N: usize> S<T, N>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+ fn new() -> Self {
+ Self {
+ arr: [T::default(); N.checked_next_power_of_two().unwrap()],
+ n: 0,
+ }
+ }
+}
--- /dev/null
+// run-rustfix
+//! This file tests for the `DOC_MARKDOWN` lint.
+
+#![allow(dead_code, incomplete_features)]
+#![warn(clippy::doc_markdown)]
+#![feature(custom_inner_attributes, generic_const_exprs, const_option)]
+#![rustfmt::skip]
+
+/// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
+/// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun
+/// which should be reported only once despite being __doubly bad__.
+/// Here be ::a::global:path, and _::another::global::path_. :: is not a path though.
+/// Import an item from ::awesome::global::blob:: (Intended postfix)
+/// These are the options for ::Cat: (Intended trailing single colon, shouldn't be linted)
+/// That's not code ~NotInCodeBlock~.
+/// be_sure_we_got_to_the_end_of_it
+fn foo_bar() {
+}
+
+/// That one tests multiline ticks.
+/// ```rust
+/// foo_bar FOO_BAR
+/// _foo bar_
+/// ```
+///
+/// ~~~rust
+/// foo_bar FOO_BAR
+/// _foo bar_
+/// ~~~
+/// be_sure_we_got_to_the_end_of_it
+fn multiline_codeblock() {
+}
+
+/// This _is a test for
+/// multiline
+/// emphasis_.
+/// be_sure_we_got_to_the_end_of_it
+fn test_emphasis() {
+}
+
+/// This tests units. See also #835.
+/// kiB MiB GiB TiB PiB EiB
+/// kib Mib Gib Tib Pib Eib
+/// kB MB GB TB PB EB
+/// kb Mb Gb Tb Pb Eb
+/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB
+/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib
+/// 32kB 32MB 32GB 32TB 32PB 32EB
+/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb
+/// NaN
+/// be_sure_we_got_to_the_end_of_it
+fn test_units() {
+}
+
+/// This tests allowed identifiers.
+/// KiB MiB GiB TiB PiB EiB
+/// DirectX
+/// ECMAScript
+/// GPLv2 GPLv3
+/// GitHub GitLab
+/// IPv4 IPv6
+/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
+/// NaN NaNs
+/// OAuth GraphQL
+/// OCaml
+/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS
+/// WebGL
+/// TensorFlow
+/// TrueType
+/// iOS macOS FreeBSD
+/// TeX LaTeX BibTeX BibLaTeX
+/// MinGW
+/// CamelCase (see also #2395)
+/// be_sure_we_got_to_the_end_of_it
+fn test_allowed() {
+}
+
+/// This test has [a link_with_underscores][chunked-example] inside it. See #823.
+/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
+/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
+/// It can also be [inline_link2].
+///
+/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
+/// [inline_link]: https://foobar
+/// [inline_link2]: https://foobar
+/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and
+/// `multiline_ticks` functions.
+///
+/// expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>`
+/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` ,
+/// be_sure_we_got_to_the_end_of_it
+fn main() {
+ foo_bar();
+ multiline_codeblock();
+ test_emphasis();
+ test_units();
+}
+
+/// ## CamelCaseThing
+/// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897.
+///
+/// # CamelCaseThing
+///
+/// Not a title #897 CamelCaseThing
+/// be_sure_we_got_to_the_end_of_it
+fn issue897() {
+}
+
+/// I am confused by brackets? (`x_y`)
+/// I am confused by brackets? (foo `x_y`)
+/// I am confused by brackets? (`x_y` foo)
+/// be_sure_we_got_to_the_end_of_it
+fn issue900() {
+}
+
+/// Diesel queries also have a similar problem to [Iterator][iterator], where
+/// /// More talking
+/// returning them from a function requires exposing the implementation of that
+/// function. The [`helper_types`][helper_types] module exists to help with this,
+/// but you might want to hide the return type or have it conditionally change.
+/// Boxing can achieve both.
+///
+/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html
+/// [helper_types]: ../helper_types/index.html
+/// be_sure_we_got_to_the_end_of_it
+fn issue883() {
+}
+
+/// `foo_bar
+/// baz_quz`
+/// [foo
+/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html)
+fn multiline() {
+}
+
+/** E.g., serialization of an empty list: FooBar
+```
+That's in a code block: `PackedNode`
+```
+
+And BarQuz too.
+be_sure_we_got_to_the_end_of_it
+*/
+fn issue1073() {
+}
+
+/** E.g., serialization of an empty list: FooBar
+```
+That's in a code block: PackedNode
+```
+
+And BarQuz too.
+be_sure_we_got_to_the_end_of_it
+*/
+fn issue1073_alt() {
+}
+
+/// Tests more than three quotes:
+/// ````
+/// DoNotWarn
+/// ```
+/// StillDont
+/// ````
+/// be_sure_we_got_to_the_end_of_it
+fn four_quotes() {
+}
+
+#[cfg_attr(feature = "a", doc = " ```")]
+#[cfg_attr(not(feature = "a"), doc = " ```ignore")]
+/// fn main() {
+/// let s = "localhost:10000".to_string();
+/// println!("{}", s);
+/// }
+/// ```
+fn issue_1469() {}
+
+/**
+ * This is a doc comment that should not be a list
+ *This would also be an error under a strict common mark interpretation
+ */
+fn issue_1920() {}
+
+/// An iterator over mycrate::Collection's values.
+/// It should not lint a `'static` lifetime in ticks.
+fn issue_2210() {}
+
+/// This should not cause the lint to trigger:
+/// #REQ-data-family.lint_partof_exists
+fn issue_2343() {}
+
+/// This should not cause an ICE:
+/// __|_ _|__||_|
+fn pulldown_cmark_crash() {}
+
+/// This should not lint
+/// (regression test for #7758)
+/// [plain text][path::to::item]
+fn intra_doc_link() {}
+
+// issue #7033 - generic_const_exprs ICE
+struct S<T, const N: usize>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+ arr: [T; N.checked_next_power_of_two().unwrap()],
+ n: usize,
+}
+
+impl<T: Copy + Default, const N: usize> S<T, N>
+where [(); N.checked_next_power_of_two().unwrap()]: {
+ fn new() -> Self {
+ Self {
+ arr: [T::default(); N.checked_next_power_of_two().unwrap()],
+ n: 0,
+ }
+ }
+}
--- /dev/null
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:9:9
+ |
+LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
+ | ^^^^^^^ help: try: ``foo_bar``
+ |
+ = note: `-D clippy::doc-markdown` implied by `-D warnings`
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:9:51
+ |
+LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
+ | ^^^^^^^^ help: try: ``foo::bar``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:10:83
+ |
+LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun
+ | ^^^^^^^^^^^^^ help: try: ``Foo::some_fun``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:12:13
+ |
+LL | /// Here be ::a::global:path, and _::another::global::path_. :: is not a path though.
+ | ^^^^^^^^^^^^^^^^ help: try: ``::a::global:path``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:12:36
+ |
+LL | /// Here be ::a::global:path, and _::another::global::path_. :: is not a path though.
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``::another::global::path``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:13:25
+ |
+LL | /// Import an item from ::awesome::global::blob:: (Intended postfix)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``::awesome::global::blob::``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:14:31
+ |
+LL | /// These are the options for ::Cat: (Intended trailing single colon, shouldn't be linted)
+ | ^^^^^ help: try: ``::Cat``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:15:22
+ |
+LL | /// That's not code ~NotInCodeBlock~.
+ | ^^^^^^^^^^^^^^ help: try: ``NotInCodeBlock``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:16:5
+ |
+LL | /// be_sure_we_got_to_the_end_of_it
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:30:5
+ |
+LL | /// be_sure_we_got_to_the_end_of_it
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:37:5
+ |
+LL | /// be_sure_we_got_to_the_end_of_it
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:51:5
+ |
+LL | /// be_sure_we_got_to_the_end_of_it
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:74:5
+ |
+LL | /// be_sure_we_got_to_the_end_of_it
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:78:22
+ |
+LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823.
+ | ^^^^^^^^^^^^^^^^^^^^^ help: try: ``link_with_underscores``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:81:21
+ |
+LL | /// It can also be [inline_link2].
+ | ^^^^^^^^^^^^ help: try: ``inline_link2``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:91:5
+ |
+LL | /// be_sure_we_got_to_the_end_of_it
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:99:8
+ |
+LL | /// ## CamelCaseThing
+ | ^^^^^^^^^^^^^^ help: try: ``CamelCaseThing``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:102:7
+ |
+LL | /// # CamelCaseThing
+ | ^^^^^^^^^^^^^^ help: try: ``CamelCaseThing``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:104:22
+ |
+LL | /// Not a title #897 CamelCaseThing
+ | ^^^^^^^^^^^^^^ help: try: ``CamelCaseThing``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:105:5
+ |
+LL | /// be_sure_we_got_to_the_end_of_it
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:112:5
+ |
+LL | /// be_sure_we_got_to_the_end_of_it
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:125:5
+ |
+LL | /// be_sure_we_got_to_the_end_of_it
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:136:43
+ |
+LL | /** E.g., serialization of an empty list: FooBar
+ | ^^^^^^ help: try: ``FooBar``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:141:5
+ |
+LL | And BarQuz too.
+ | ^^^^^^ help: try: ``BarQuz``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:142:1
+ |
+LL | be_sure_we_got_to_the_end_of_it
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:147:43
+ |
+LL | /** E.g., serialization of an empty list: FooBar
+ | ^^^^^^ help: try: ``FooBar``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:152:5
+ |
+LL | And BarQuz too.
+ | ^^^^^^ help: try: ``BarQuz``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:153:1
+ |
+LL | be_sure_we_got_to_the_end_of_it
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:164:5
+ |
+LL | /// be_sure_we_got_to_the_end_of_it
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: ``be_sure_we_got_to_the_end_of_it``
+
+error: item in documentation is missing backticks
+ --> $DIR/doc-fixable.rs:183:22
+ |
+LL | /// An iterator over mycrate::Collection's values.
+ | ^^^^^^^^^^^^^^^^^^^ help: try: ``mycrate::Collection``
+
+error: aborting due to 30 previous errors
+
+++ /dev/null
-//! This file tests for the `DOC_MARKDOWN` lint.
-
-#![allow(dead_code, incomplete_features)]
-#![warn(clippy::doc_markdown)]
-#![feature(custom_inner_attributes, generic_const_exprs, const_option)]
-#![rustfmt::skip]
-
-/// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
-/// Markdown is _weird_. I mean _really weird_. This \_ is ok. So is `_`. But not Foo::some_fun
-/// which should be reported only once despite being __doubly bad__.
-/// Here be ::a::global:path.
-/// That's not code ~NotInCodeBlock~.
-/// be_sure_we_got_to_the_end_of_it
-fn foo_bar() {
-}
-
-/// That one tests multiline ticks.
-/// ```rust
-/// foo_bar FOO_BAR
-/// _foo bar_
-/// ```
-///
-/// ~~~rust
-/// foo_bar FOO_BAR
-/// _foo bar_
-/// ~~~
-/// be_sure_we_got_to_the_end_of_it
-fn multiline_codeblock() {
-}
-
-/// This _is a test for
-/// multiline
-/// emphasis_.
-/// be_sure_we_got_to_the_end_of_it
-fn test_emphasis() {
-}
-
-/// This tests units. See also #835.
-/// kiB MiB GiB TiB PiB EiB
-/// kib Mib Gib Tib Pib Eib
-/// kB MB GB TB PB EB
-/// kb Mb Gb Tb Pb Eb
-/// 32kiB 32MiB 32GiB 32TiB 32PiB 32EiB
-/// 32kib 32Mib 32Gib 32Tib 32Pib 32Eib
-/// 32kB 32MB 32GB 32TB 32PB 32EB
-/// 32kb 32Mb 32Gb 32Tb 32Pb 32Eb
-/// NaN
-/// be_sure_we_got_to_the_end_of_it
-fn test_units() {
-}
-
-/// This tests allowed identifiers.
-/// KiB MiB GiB TiB PiB EiB
-/// DirectX
-/// ECMAScript
-/// GPLv2 GPLv3
-/// GitHub GitLab
-/// IPv4 IPv6
-/// ClojureScript CoffeeScript JavaScript PureScript TypeScript
-/// NaN NaNs
-/// OAuth GraphQL
-/// OCaml
-/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS
-/// WebGL
-/// TensorFlow
-/// TrueType
-/// iOS macOS FreeBSD
-/// TeX LaTeX BibTeX BibLaTeX
-/// MinGW
-/// CamelCase (see also #2395)
-/// be_sure_we_got_to_the_end_of_it
-fn test_allowed() {
-}
-
-/// This test has [a link_with_underscores][chunked-example] inside it. See #823.
-/// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
-/// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
-/// It can also be [inline_link2].
-///
-/// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
-/// [inline_link]: https://foobar
-/// [inline_link2]: https://foobar
-/// The `main` function is the entry point of the program. Here it only calls the `foo_bar` and
-/// `multiline_ticks` functions.
-///
-/// expression of the type `_ <bit_op> m <cmp_op> c` (where `<bit_op>`
-/// is one of {`&`, '|'} and `<cmp_op>` is one of {`!=`, `>=`, `>` ,
-/// be_sure_we_got_to_the_end_of_it
-fn main() {
- foo_bar();
- multiline_codeblock();
- test_emphasis();
- test_units();
-}
-
-/// ## CamelCaseThing
-/// Talks about `CamelCaseThing`. Titles should be ignored; see issue #897.
-///
-/// # CamelCaseThing
-///
-/// Not a title #897 CamelCaseThing
-/// be_sure_we_got_to_the_end_of_it
-fn issue897() {
-}
-
-/// I am confused by brackets? (`x_y`)
-/// I am confused by brackets? (foo `x_y`)
-/// I am confused by brackets? (`x_y` foo)
-/// be_sure_we_got_to_the_end_of_it
-fn issue900() {
-}
-
-/// Diesel queries also have a similar problem to [Iterator][iterator], where
-/// /// More talking
-/// returning them from a function requires exposing the implementation of that
-/// function. The [`helper_types`][helper_types] module exists to help with this,
-/// but you might want to hide the return type or have it conditionally change.
-/// Boxing can achieve both.
-///
-/// [iterator]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html
-/// [helper_types]: ../helper_types/index.html
-/// be_sure_we_got_to_the_end_of_it
-fn issue883() {
-}
-
-/// `foo_bar
-/// baz_quz`
-/// [foo
-/// bar](https://doc.rust-lang.org/stable/std/iter/trait.IteratorFooBar.html)
-fn multiline() {
-}
-
-/** E.g., serialization of an empty list: FooBar
-```
-That's in a code block: `PackedNode`
-```
-
-And BarQuz too.
-be_sure_we_got_to_the_end_of_it
-*/
-fn issue1073() {
-}
-
-/** E.g., serialization of an empty list: FooBar
-```
-That's in a code block: PackedNode
-```
-
-And BarQuz too.
-be_sure_we_got_to_the_end_of_it
-*/
-fn issue1073_alt() {
-}
-
-/// Tests more than three quotes:
-/// ````
-/// DoNotWarn
-/// ```
-/// StillDont
-/// ````
-/// be_sure_we_got_to_the_end_of_it
-fn four_quotes() {
-}
-
-/// See [NIST SP 800-56A, revision 2].
-///
-/// [NIST SP 800-56A, revision 2]:
-/// https://github.com/rust-lang/rust-clippy/issues/902#issuecomment-261919419
-fn issue_902_comment() {}
-
-#[cfg_attr(feature = "a", doc = " ```")]
-#[cfg_attr(not(feature = "a"), doc = " ```ignore")]
-/// fn main() {
-/// let s = "localhost:10000".to_string();
-/// println!("{}", s);
-/// }
-/// ```
-fn issue_1469() {}
-
-/**
- * This is a doc comment that should not be a list
- *This would also be an error under a strict common mark interpretation
- */
-fn issue_1920() {}
-
-/// Ok: <http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels>
-///
-/// Not ok: http://www.unicode.org
-/// Not ok: https://www.unicode.org
-/// Not ok: http://www.unicode.org/
-/// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
-fn issue_1832() {}
-
-/// An iterator over mycrate::Collection's values.
-/// It should not lint a `'static` lifetime in ticks.
-fn issue_2210() {}
-
-/// This should not cause the lint to trigger:
-/// #REQ-data-family.lint_partof_exists
-fn issue_2343() {}
-
-/// This should not cause an ICE:
-/// __|_ _|__||_|
-fn pulldown_cmark_crash() {}
-
-/// This should not lint
-/// (regression test for #7758)
-/// [plain text][path::to::item]
-fn intra_doc_link() {}
-
-// issue #7033 - generic_const_exprs ICE
-struct S<T, const N: usize>
-where [(); N.checked_next_power_of_two().unwrap()]: {
- arr: [T; N.checked_next_power_of_two().unwrap()],
- n: usize,
-}
-
-impl<T: Copy + Default, const N: usize> S<T, N>
-where [(); N.checked_next_power_of_two().unwrap()]: {
- fn new() -> Self {
- Self {
- arr: [T::default(); N.checked_next_power_of_two().unwrap()],
- n: 0,
- }
- }
-}
+++ /dev/null
-error: you should put `foo_bar` between ticks in the documentation
- --> $DIR/doc.rs:8:9
- |
-LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
- | ^^^^^^^
- |
- = note: `-D clippy::doc-markdown` implied by `-D warnings`
-
-error: you should put `foo::bar` between ticks in the documentation
- --> $DIR/doc.rs:8:51
- |
-LL | /// The foo_bar function does _nothing_. See also foo::bar. (note the dot there)
- | ^^^^^^^^
-
-error: you should put `Foo::some_fun` between ticks in the documentation
- --> $DIR/doc.rs:9:83
- |
-LL | /// Markdown is _weird_. I mean _really weird_. This /_ is ok. So is `_`. But not Foo::some_fun
- | ^^^^^^^^^^^^^
-
-error: you should put `a::global:path` between ticks in the documentation
- --> $DIR/doc.rs:11:15
- |
-LL | /// Here be ::a::global:path.
- | ^^^^^^^^^^^^^^
-
-error: you should put `NotInCodeBlock` between ticks in the documentation
- --> $DIR/doc.rs:12:22
- |
-LL | /// That's not code ~NotInCodeBlock~.
- | ^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
- --> $DIR/doc.rs:13:5
- |
-LL | /// be_sure_we_got_to_the_end_of_it
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
- --> $DIR/doc.rs:27:5
- |
-LL | /// be_sure_we_got_to_the_end_of_it
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
- --> $DIR/doc.rs:34:5
- |
-LL | /// be_sure_we_got_to_the_end_of_it
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
- --> $DIR/doc.rs:48:5
- |
-LL | /// be_sure_we_got_to_the_end_of_it
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
- --> $DIR/doc.rs:71:5
- |
-LL | /// be_sure_we_got_to_the_end_of_it
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `link_with_underscores` between ticks in the documentation
- --> $DIR/doc.rs:75:22
- |
-LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823.
- | ^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `inline_link2` between ticks in the documentation
- --> $DIR/doc.rs:78:21
- |
-LL | /// It can also be [inline_link2].
- | ^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
- --> $DIR/doc.rs:88:5
- |
-LL | /// be_sure_we_got_to_the_end_of_it
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `CamelCaseThing` between ticks in the documentation
- --> $DIR/doc.rs:96:8
- |
-LL | /// ## CamelCaseThing
- | ^^^^^^^^^^^^^^
-
-error: you should put `CamelCaseThing` between ticks in the documentation
- --> $DIR/doc.rs:99:7
- |
-LL | /// # CamelCaseThing
- | ^^^^^^^^^^^^^^
-
-error: you should put `CamelCaseThing` between ticks in the documentation
- --> $DIR/doc.rs:101:22
- |
-LL | /// Not a title #897 CamelCaseThing
- | ^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
- --> $DIR/doc.rs:102:5
- |
-LL | /// be_sure_we_got_to_the_end_of_it
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
- --> $DIR/doc.rs:109:5
- |
-LL | /// be_sure_we_got_to_the_end_of_it
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
- --> $DIR/doc.rs:122:5
- |
-LL | /// be_sure_we_got_to_the_end_of_it
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `FooBar` between ticks in the documentation
- --> $DIR/doc.rs:133:43
- |
-LL | /** E.g., serialization of an empty list: FooBar
- | ^^^^^^
-
-error: you should put `BarQuz` between ticks in the documentation
- --> $DIR/doc.rs:138:5
- |
-LL | And BarQuz too.
- | ^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
- --> $DIR/doc.rs:139:1
- |
-LL | be_sure_we_got_to_the_end_of_it
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `FooBar` between ticks in the documentation
- --> $DIR/doc.rs:144:43
- |
-LL | /** E.g., serialization of an empty list: FooBar
- | ^^^^^^
-
-error: you should put `BarQuz` between ticks in the documentation
- --> $DIR/doc.rs:149:5
- |
-LL | And BarQuz too.
- | ^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
- --> $DIR/doc.rs:150:1
- |
-LL | be_sure_we_got_to_the_end_of_it
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `be_sure_we_got_to_the_end_of_it` between ticks in the documentation
- --> $DIR/doc.rs:161:5
- |
-LL | /// be_sure_we_got_to_the_end_of_it
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
- --> $DIR/doc.rs:188:13
- |
-LL | /// Not ok: http://www.unicode.org
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
- --> $DIR/doc.rs:189:13
- |
-LL | /// Not ok: https://www.unicode.org
- | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
- --> $DIR/doc.rs:190:13
- |
-LL | /// Not ok: http://www.unicode.org/
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put bare URLs between `<`/`>` or make a proper Markdown link
- --> $DIR/doc.rs:191:13
- |
-LL | /// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: you should put `mycrate::Collection` between ticks in the documentation
- --> $DIR/doc.rs:194:22
- |
-LL | /// An iterator over mycrate::Collection's values.
- | ^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 31 previous errors
-
--- /dev/null
+/// Ok: <http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels>
+///
+/// Not ok: http://www.unicode.org
+/// Not ok: https://www.unicode.org
+/// Not ok: http://www.unicode.org/
+/// Not ok: http://www.unicode.org/reports/tr9/#Reordering_Resolved_Levels
+fn issue_1832() {}
+
+fn main() {}
--- /dev/null
+/// See [NIST SP 800-56A, revision 2].
+///
+/// [NIST SP 800-56A, revision 2]:
+/// https://github.com/rust-lang/rust-clippy/issues/902#issuecomment-261919419
+fn issue_902_comment() {}
+
+fn main() {}
|
= help: a backtick may be missing a pair
-error: you should put `should_be` between ticks in the documentation
+error: item in documentation is missing backticks
--> $DIR/unbalanced_ticks.rs:15:32
|
LL | /// This paragraph is fine and should_be linted normally.
- | ^^^^^^^^^
+ | ^^^^^^^^^ help: try: ``should_be``
error: backticks are unbalanced
--> $DIR/unbalanced_ticks.rs:17:1
|
= help: a backtick may be missing a pair
-error: you should put `not_fine` between ticks in the documentation
+error: item in documentation is missing backticks
--> $DIR/unbalanced_ticks.rs:30:8
|
LL | /// ## not_fine
- | ^^^^^^^^
+ | ^^^^^^^^ help: try: ``not_fine``
error: backticks are unbalanced
--> $DIR/unbalanced_ticks.rs:32:1
|
= help: a backtick may be missing a pair
-error: you should put `backticks_here` between ticks in the documentation
+error: item in documentation is missing backticks
--> $DIR/unbalanced_ticks.rs:35:23
|
LL | /// - This item needs backticks_here
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^ help: try: ``backticks_here``
error: aborting due to 8 previous errors
-// edition:2018
#![warn(clippy::missing_errors_doc)]
#![allow(clippy::result_unit_err)]
#![allow(clippy::unnecessary_wraps)]
error: docs for function returning `Result` missing `# Errors` section
- --> $DIR/doc_errors.rs:8:1
+ --> $DIR/doc_errors.rs:7:1
|
LL | / pub fn pub_fn_missing_errors_header() -> Result<(), ()> {
LL | | unimplemented!();
= note: `-D clippy::missing-errors-doc` implied by `-D warnings`
error: docs for function returning `Result` missing `# Errors` section
- --> $DIR/doc_errors.rs:12:1
+ --> $DIR/doc_errors.rs:11:1
|
LL | / pub async fn async_pub_fn_missing_errors_header() -> Result<(), ()> {
LL | | unimplemented!();
| |_^
error: docs for function returning `Result` missing `# Errors` section
- --> $DIR/doc_errors.rs:17:1
+ --> $DIR/doc_errors.rs:16:1
|
LL | / pub fn pub_fn_returning_io_result() -> io::Result<()> {
LL | | unimplemented!();
| |_^
error: docs for function returning `Result` missing `# Errors` section
- --> $DIR/doc_errors.rs:22:1
+ --> $DIR/doc_errors.rs:21:1
|
LL | / pub async fn async_pub_fn_returning_io_result() -> io::Result<()> {
LL | | unimplemented!();
| |_^
error: docs for function returning `Result` missing `# Errors` section
- --> $DIR/doc_errors.rs:52:5
+ --> $DIR/doc_errors.rs:51:5
|
LL | / pub fn pub_method_missing_errors_header() -> Result<(), ()> {
LL | | unimplemented!();
| |_____^
error: docs for function returning `Result` missing `# Errors` section
- --> $DIR/doc_errors.rs:57:5
+ --> $DIR/doc_errors.rs:56:5
|
LL | / pub async fn async_pub_method_missing_errors_header() -> Result<(), ()> {
LL | | unimplemented!();
| |_____^
error: docs for function returning `Result` missing `# Errors` section
- --> $DIR/doc_errors.rs:86:5
+ --> $DIR/doc_errors.rs:85:5
|
LL | fn trait_method_missing_errors_header() -> Result<(), ()>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pub unsafe fn f() {}
}
}
+
+/// # Implementation safety
+pub unsafe trait DocumentedUnsafeTraitWithImplementationHeader {
+ fn method();
+}
|
= help: remove the prefixes and use full paths to the variants instead of glob imports
-error: all variants have the same prefix: `With`
+error: all variants have the same prefix: `WithOut`
--> $DIR/enum_variants.rs:81:1
|
LL | / enum Seallll {
-// edition:2018
-
#[warn(clippy::eval_order_dependence)]
#[allow(
unused_assignments,
error: unsequenced read of `x`
- --> $DIR/eval_order_dependence.rs:16:9
+ --> $DIR/eval_order_dependence.rs:14:9
|
LL | } + x;
| ^
|
= note: `-D clippy::eval-order-dependence` implied by `-D warnings`
note: whether read occurs before this write depends on evaluation order
- --> $DIR/eval_order_dependence.rs:14:9
+ --> $DIR/eval_order_dependence.rs:12:9
|
LL | x = 1;
| ^^^^^
error: unsequenced read of `x`
- --> $DIR/eval_order_dependence.rs:19:5
+ --> $DIR/eval_order_dependence.rs:17:5
|
LL | x += {
| ^
|
note: whether read occurs before this write depends on evaluation order
- --> $DIR/eval_order_dependence.rs:20:9
+ --> $DIR/eval_order_dependence.rs:18:9
|
LL | x = 20;
| ^^^^^^
error: unsequenced read of `x`
- --> $DIR/eval_order_dependence.rs:32:12
+ --> $DIR/eval_order_dependence.rs:30:12
|
LL | a: x,
| ^
|
note: whether read occurs before this write depends on evaluation order
- --> $DIR/eval_order_dependence.rs:34:13
+ --> $DIR/eval_order_dependence.rs:32:13
|
LL | x = 6;
| ^^^^^
error: unsequenced read of `x`
- --> $DIR/eval_order_dependence.rs:41:9
+ --> $DIR/eval_order_dependence.rs:39:9
|
LL | x += {
| ^
|
note: whether read occurs before this write depends on evaluation order
- --> $DIR/eval_order_dependence.rs:42:13
+ --> $DIR/eval_order_dependence.rs:40:13
|
LL | x = 20;
| ^^^^^^
#![deny(clippy::fallible_impl_from)]
-#![allow(clippy::if_then_panic)]
// docs example
struct Foo(i32);
error: consider implementing `TryFrom` instead
- --> $DIR/fallible_impl_from.rs:6:1
+ --> $DIR/fallible_impl_from.rs:5:1
|
LL | / impl From<String> for Foo {
LL | | fn from(s: String) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
note: potential failure(s)
- --> $DIR/fallible_impl_from.rs:8:13
+ --> $DIR/fallible_impl_from.rs:7:13
|
LL | Foo(s.parse().unwrap())
| ^^^^^^^^^^^^^^^^^^
error: consider implementing `TryFrom` instead
- --> $DIR/fallible_impl_from.rs:27:1
+ --> $DIR/fallible_impl_from.rs:26:1
|
LL | / impl From<usize> for Invalid {
LL | | fn from(i: usize) -> Invalid {
|
= help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
note: potential failure(s)
- --> $DIR/fallible_impl_from.rs:30:13
+ --> $DIR/fallible_impl_from.rs:29:13
|
LL | panic!();
| ^^^^^^^^
- = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
error: consider implementing `TryFrom` instead
- --> $DIR/fallible_impl_from.rs:36:1
+ --> $DIR/fallible_impl_from.rs:35:1
|
LL | / impl From<Option<String>> for Invalid {
LL | | fn from(s: Option<String>) -> Invalid {
|
= help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
note: potential failure(s)
- --> $DIR/fallible_impl_from.rs:38:17
+ --> $DIR/fallible_impl_from.rs:37:17
|
LL | let s = s.unwrap();
| ^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^
LL | panic!("{:?}", s);
| ^^^^^^^^^^^^^^^^^
- = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
error: consider implementing `TryFrom` instead
- --> $DIR/fallible_impl_from.rs:54:1
+ --> $DIR/fallible_impl_from.rs:53:1
|
LL | / impl<'a> From<&'a mut <Box<u32> as ProjStrTrait>::ProjString> for Invalid {
LL | | fn from(s: &'a mut <Box<u32> as ProjStrTrait>::ProjString) -> Invalid {
|
= help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
note: potential failure(s)
- --> $DIR/fallible_impl_from.rs:56:12
+ --> $DIR/fallible_impl_from.rs:55:12
|
LL | if s.parse::<u32>().ok().unwrap() != 42 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | panic!("{:?}", s);
| ^^^^^^^^^^^^^^^^^
- = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors
r##"foo {}
" bar"##.to_string();
+ let _ = String::new();
+
"foo".to_string();
format!("{:?}", "foo"); // Don't warn about `Debug`.
format!("{:8}", "foo");
" bar"##
);
+ let _ = format!("");
+
format!("{}", "foo");
format!("{:?}", "foo"); // Don't warn about `Debug`.
format!("{:8}", "foo");
|
error: useless use of `format!`
- --> $DIR/format.rs:21:5
+ --> $DIR/format.rs:21:13
+ |
+LL | let _ = format!("");
+ | ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()`
+
+error: useless use of `format!`
+ --> $DIR/format.rs:23:5
|
LL | format!("{}", "foo");
| ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:25:5
+ --> $DIR/format.rs:27:5
|
LL | format!("{:+}", "foo"); // Warn when the format makes no difference.
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:26:5
+ --> $DIR/format.rs:28:5
|
LL | format!("{:<}", "foo"); // Warn when the format makes no difference.
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:31:5
+ --> $DIR/format.rs:33:5
|
LL | format!("{}", arg);
| ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:35:5
+ --> $DIR/format.rs:37:5
|
LL | format!("{:+}", arg); // Warn when the format makes no difference.
| ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:36:5
+ --> $DIR/format.rs:38:5
|
LL | format!("{:<}", arg); // Warn when the format makes no difference.
| ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:63:5
+ --> $DIR/format.rs:65:5
|
LL | format!("{}", 42.to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:65:5
+ --> $DIR/format.rs:67:5
|
LL | format!("{}", x.display().to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:69:18
+ --> $DIR/format.rs:71:18
|
LL | let _ = Some(format!("{}", a + "bar"));
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"`
error: useless use of `format!`
- --> $DIR/format.rs:73:22
+ --> $DIR/format.rs:75:22
|
LL | let _s: String = format!("{}", &*v.join("/n"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()`
-error: aborting due to 14 previous errors
+error: aborting due to 15 previous errors
#![allow(unused_variables)]
#![allow(clippy::assertions_on_constants)]
#![allow(clippy::eq_op)]
+#![allow(clippy::print_literal)]
#![warn(clippy::to_string_in_format_args)]
use std::io::{stdout, Write};
println!("{}", Z(1));
println!("{}", **x);
println!("{}", ***x_ref);
+ // https://github.com/rust-lang/rust-clippy/issues/7903
+ println!("{foo}{bar}", foo = "foo", bar = "bar");
+ println!("{foo}{bar}", foo = "foo", bar = "bar");
+ println!("{foo}{bar}", bar = "bar", foo = "foo");
+ println!("{foo}{bar}", bar = "bar", foo = "foo");
+ // negative tests
println!("error: something failed at {}", Somewhere.to_string());
+ // The next two tests are negative because caching the string might be faster than calling `<X as
+ // Display>::fmt` twice.
println!("{} and again {0}", x.to_string());
+ println!("{foo}{foo}", foo = "foo".to_string());
my_macro!();
println!("error: something failed at {}", my_other_macro!());
+ // https://github.com/rust-lang/rust-clippy/issues/7903
+ println!("{foo}{foo:?}", foo = "foo".to_string());
}
#![allow(unused_variables)]
#![allow(clippy::assertions_on_constants)]
#![allow(clippy::eq_op)]
+#![allow(clippy::print_literal)]
#![warn(clippy::to_string_in_format_args)]
use std::io::{stdout, Write};
println!("{}", Z(1).to_string());
println!("{}", x.to_string());
println!("{}", x_ref.to_string());
+ // https://github.com/rust-lang/rust-clippy/issues/7903
+ println!("{foo}{bar}", foo = "foo".to_string(), bar = "bar");
+ println!("{foo}{bar}", foo = "foo", bar = "bar".to_string());
+ println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo");
+ println!("{foo}{bar}", bar = "bar", foo = "foo".to_string());
+ // negative tests
println!("error: something failed at {}", Somewhere.to_string());
+ // The next two tests are negative because caching the string might be faster than calling `<X as
+ // Display>::fmt` twice.
println!("{} and again {0}", x.to_string());
+ println!("{foo}{foo}", foo = "foo".to_string());
my_macro!();
println!("error: something failed at {}", my_other_macro!());
+ // https://github.com/rust-lang/rust-clippy/issues/7903
+ println!("{foo}{foo:?}", foo = "foo".to_string());
}
error: `to_string` applied to a type that implements `Display` in `format!` args
- --> $DIR/format_args.rs:75:72
+ --> $DIR/format_args.rs:76:72
|
LL | let _ = format!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
= note: `-D clippy::to-string-in-format-args` implied by `-D warnings`
error: `to_string` applied to a type that implements `Display` in `write!` args
- --> $DIR/format_args.rs:79:27
+ --> $DIR/format_args.rs:80:27
|
LL | Location::caller().to_string()
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `writeln!` args
- --> $DIR/format_args.rs:84:27
+ --> $DIR/format_args.rs:85:27
|
LL | Location::caller().to_string()
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `print!` args
- --> $DIR/format_args.rs:86:63
+ --> $DIR/format_args.rs:87:63
|
LL | print!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:87:65
+ --> $DIR/format_args.rs:88:65
|
LL | println!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `eprint!` args
- --> $DIR/format_args.rs:88:64
+ --> $DIR/format_args.rs:89:64
|
LL | eprint!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `eprintln!` args
- --> $DIR/format_args.rs:89:66
+ --> $DIR/format_args.rs:90:66
|
LL | eprintln!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `format_args!` args
- --> $DIR/format_args.rs:90:77
+ --> $DIR/format_args.rs:91:77
|
LL | let _ = format_args!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `assert!` args
- --> $DIR/format_args.rs:91:70
+ --> $DIR/format_args.rs:92:70
|
LL | assert!(true, "error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `assert_eq!` args
- --> $DIR/format_args.rs:92:73
+ --> $DIR/format_args.rs:93:73
|
LL | assert_eq!(0, 0, "error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `assert_ne!` args
- --> $DIR/format_args.rs:93:73
+ --> $DIR/format_args.rs:94:73
|
LL | assert_ne!(0, 0, "error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `panic!` args
- --> $DIR/format_args.rs:94:63
+ --> $DIR/format_args.rs:95:63
|
LL | panic!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:95:20
+ --> $DIR/format_args.rs:96:20
|
LL | println!("{}", X(1).to_string());
| ^^^^^^^^^^^^^^^^ help: use this: `*X(1)`
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:96:20
+ --> $DIR/format_args.rs:97:20
|
LL | println!("{}", Y(&X(1)).to_string());
| ^^^^^^^^^^^^^^^^^^^^ help: use this: `***Y(&X(1))`
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:97:24
+ --> $DIR/format_args.rs:98:24
|
LL | println!("{}", Z(1).to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:98:20
+ --> $DIR/format_args.rs:99:20
|
LL | println!("{}", x.to_string());
| ^^^^^^^^^^^^^ help: use this: `**x`
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:99:20
+ --> $DIR/format_args.rs:100:20
|
LL | println!("{}", x_ref.to_string());
| ^^^^^^^^^^^^^^^^^ help: use this: `***x_ref`
-error: aborting due to 17 previous errors
+error: `to_string` applied to a type that implements `Display` in `println!` args
+ --> $DIR/format_args.rs:102:39
+ |
+LL | println!("{foo}{bar}", foo = "foo".to_string(), bar = "bar");
+ | ^^^^^^^^^^^^ help: remove this
+
+error: `to_string` applied to a type that implements `Display` in `println!` args
+ --> $DIR/format_args.rs:103:52
+ |
+LL | println!("{foo}{bar}", foo = "foo", bar = "bar".to_string());
+ | ^^^^^^^^^^^^ help: remove this
+
+error: `to_string` applied to a type that implements `Display` in `println!` args
+ --> $DIR/format_args.rs:104:39
+ |
+LL | println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo");
+ | ^^^^^^^^^^^^ help: remove this
+
+error: `to_string` applied to a type that implements `Display` in `println!` args
+ --> $DIR/format_args.rs:105:52
+ |
+LL | println!("{foo}{bar}", bar = "bar", foo = "foo".to_string());
+ | ^^^^^^^^^^^^ help: remove this
+
+error: aborting due to 21 previous errors
assert_ne!(0, 0, "error: {}", format!("something failed at {}", Location::caller()));
panic!("error: {}", format!("something failed at {}", Location::caller()));
+ // negative tests
println!("error: {}", format_args!("something failed at {}", Location::caller()));
println!("error: {:>70}", format!("something failed at {}", Location::caller()));
println!("error: {} {0}", format!("something failed at {}", Location::caller()));
-// edition:2018
#![warn(clippy::future_not_send)]
use std::cell::Cell;
error: future cannot be sent between threads safely
- --> $DIR/future_not_send.rs:8:62
+ --> $DIR/future_not_send.rs:7:62
|
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
| ^^^^ future returned by `private_future` is not `Send`
|
= note: `-D clippy::future-not-send` implied by `-D warnings`
note: future is not `Send` as this value is used across an await
- --> $DIR/future_not_send.rs:9:5
+ --> $DIR/future_not_send.rs:8:5
|
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
| -- has type `std::rc::Rc<[u8]>` which is not `Send`
| - `rc` is later dropped here
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
note: future is not `Send` as this value is used across an await
- --> $DIR/future_not_send.rs:9:5
+ --> $DIR/future_not_send.rs:8:5
|
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
| ---- has type `&std::cell::Cell<usize>` which is not `Send`
= note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
error: future cannot be sent between threads safely
- --> $DIR/future_not_send.rs:12:42
+ --> $DIR/future_not_send.rs:11:42
|
LL | pub async fn public_future(rc: Rc<[u8]>) {
| ^ future returned by `public_future` is not `Send`
|
note: future is not `Send` as this value is used across an await
- --> $DIR/future_not_send.rs:13:5
+ --> $DIR/future_not_send.rs:12:5
|
LL | pub async fn public_future(rc: Rc<[u8]>) {
| -- has type `std::rc::Rc<[u8]>` which is not `Send`
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
error: future cannot be sent between threads safely
- --> $DIR/future_not_send.rs:20:63
+ --> $DIR/future_not_send.rs:19:63
|
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
| ^^^^ future returned by `private_future2` is not `Send`
|
note: captured value is not `Send`
- --> $DIR/future_not_send.rs:20:26
+ --> $DIR/future_not_send.rs:19:26
|
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
| ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
- --> $DIR/future_not_send.rs:20:40
+ --> $DIR/future_not_send.rs:19:40
|
LL | async fn private_future2(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
| ^^^^ has type `&std::cell::Cell<usize>` which is not `Send`, because `std::cell::Cell<usize>` is not `Sync`
= note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
error: future cannot be sent between threads safely
- --> $DIR/future_not_send.rs:24:43
+ --> $DIR/future_not_send.rs:23:43
|
LL | pub async fn public_future2(rc: Rc<[u8]>) {}
| ^ future returned by `public_future2` is not `Send`
|
note: captured value is not `Send`
- --> $DIR/future_not_send.rs:24:29
+ --> $DIR/future_not_send.rs:23:29
|
LL | pub async fn public_future2(rc: Rc<[u8]>) {}
| ^^ has type `std::rc::Rc<[u8]>` which is not `Send`
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Send`
error: future cannot be sent between threads safely
- --> $DIR/future_not_send.rs:35:39
+ --> $DIR/future_not_send.rs:34:39
|
LL | async fn private_future(&self) -> usize {
| ^^^^^ future returned by `private_future` is not `Send`
|
note: future is not `Send` as this value is used across an await
- --> $DIR/future_not_send.rs:36:9
+ --> $DIR/future_not_send.rs:35:9
|
LL | async fn private_future(&self) -> usize {
| ----- has type `&Dummy` which is not `Send`
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
error: future cannot be sent between threads safely
- --> $DIR/future_not_send.rs:40:39
+ --> $DIR/future_not_send.rs:39:39
|
LL | pub async fn public_future(&self) {
| ^ future returned by `public_future` is not `Send`
|
note: future is not `Send` as this value is used across an await
- --> $DIR/future_not_send.rs:41:9
+ --> $DIR/future_not_send.rs:40:9
|
LL | pub async fn public_future(&self) {
| ----- has type `&Dummy` which is not `Send`
= note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync`
error: future cannot be sent between threads safely
- --> $DIR/future_not_send.rs:50:37
+ --> $DIR/future_not_send.rs:49:37
|
LL | async fn generic_future<T>(t: T) -> T
| ^ future returned by `generic_future` is not `Send`
|
note: future is not `Send` as this value is used across an await
- --> $DIR/future_not_send.rs:55:5
+ --> $DIR/future_not_send.rs:54:5
|
LL | let rt = &t;
| -- has type `&T` which is not `Send`
= note: `T` doesn't implement `std::marker::Sync`
error: future cannot be sent between threads safely
- --> $DIR/future_not_send.rs:66:34
+ --> $DIR/future_not_send.rs:65:34
|
LL | async fn unclear_future<T>(t: T) {}
| ^ future returned by `unclear_future` is not `Send`
|
note: captured value is not `Send`
- --> $DIR/future_not_send.rs:66:28
+ --> $DIR/future_not_send.rs:65:28
|
LL | async fn unclear_future<T>(t: T) {}
| ^ has type `T` which is not `Send`
#![warn(clippy::all)]
#![warn(clippy::if_not_else)]
+fn foo() -> bool {
+ unimplemented!()
+}
fn bla() -> bool {
unimplemented!()
}
} else {
println!("Bunny");
}
+ if !foo() {
+ println!("Foo");
+ } else if !bla() {
+ println!("Bugs");
+ } else {
+ println!("Bunny");
+ }
}
error: unnecessary boolean `not` operation
- --> $DIR/if_not_else.rs:9:5
+ --> $DIR/if_not_else.rs:12:5
|
LL | / if !bla() {
LL | | println!("Bugs");
= help: remove the `!` and swap the blocks of the `if`/`else`
error: unnecessary `!=` operation
- --> $DIR/if_not_else.rs:14:5
+ --> $DIR/if_not_else.rs:17:5
|
LL | / if 4 != 5 {
LL | | println!("Bugs");
+++ /dev/null
-// run-rustfix
-#![warn(clippy::if_then_panic)]
-
-fn main() {
- let a = vec![1, 2, 3];
- let c = Some(2);
- if !a.is_empty()
- && a.len() == 3
- && c != None
- && !a.is_empty()
- && a.len() == 3
- && !a.is_empty()
- && a.len() == 3
- && !a.is_empty()
- && a.len() == 3
- {
- panic!("qaqaq{:?}", a);
- }
- assert!(a.is_empty(), "qaqaq{:?}", a);
- assert!(a.is_empty(), "qwqwq");
- if a.len() == 3 {
- println!("qwq");
- println!("qwq");
- println!("qwq");
- }
- if let Some(b) = c {
- panic!("orz {}", b);
- }
- if a.len() == 3 {
- panic!("qaqaq");
- } else {
- println!("qwq");
- }
- let b = vec![1, 2, 3];
- assert!(!b.is_empty(), "panic1");
- assert!(!(b.is_empty() && a.is_empty()), "panic2");
- assert!(!(a.is_empty() && !b.is_empty()), "panic3");
- assert!(!(b.is_empty() || a.is_empty()), "panic4");
- assert!(!(a.is_empty() || !b.is_empty()), "panic5");
-}
+++ /dev/null
-// run-rustfix
-#![warn(clippy::if_then_panic)]
-
-fn main() {
- let a = vec![1, 2, 3];
- let c = Some(2);
- if !a.is_empty()
- && a.len() == 3
- && c != None
- && !a.is_empty()
- && a.len() == 3
- && !a.is_empty()
- && a.len() == 3
- && !a.is_empty()
- && a.len() == 3
- {
- panic!("qaqaq{:?}", a);
- }
- if !a.is_empty() {
- panic!("qaqaq{:?}", a);
- }
- if !a.is_empty() {
- panic!("qwqwq");
- }
- if a.len() == 3 {
- println!("qwq");
- println!("qwq");
- println!("qwq");
- }
- if let Some(b) = c {
- panic!("orz {}", b);
- }
- if a.len() == 3 {
- panic!("qaqaq");
- } else {
- println!("qwq");
- }
- let b = vec![1, 2, 3];
- if b.is_empty() {
- panic!("panic1");
- }
- if b.is_empty() && a.is_empty() {
- panic!("panic2");
- }
- if a.is_empty() && !b.is_empty() {
- panic!("panic3");
- }
- if b.is_empty() || a.is_empty() {
- panic!("panic4");
- }
- if a.is_empty() || !b.is_empty() {
- panic!("panic5");
- }
-}
+++ /dev/null
-error: only a `panic!` in `if`-then statement
- --> $DIR/if_then_panic.rs:19:5
- |
-LL | / if !a.is_empty() {
-LL | | panic!("qaqaq{:?}", a);
-LL | | }
- | |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);`
- |
- = note: `-D clippy::if-then-panic` implied by `-D warnings`
-
-error: only a `panic!` in `if`-then statement
- --> $DIR/if_then_panic.rs:22:5
- |
-LL | / if !a.is_empty() {
-LL | | panic!("qwqwq");
-LL | | }
- | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
-
-error: only a `panic!` in `if`-then statement
- --> $DIR/if_then_panic.rs:39:5
- |
-LL | / if b.is_empty() {
-LL | | panic!("panic1");
-LL | | }
- | |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
-
-error: only a `panic!` in `if`-then statement
- --> $DIR/if_then_panic.rs:42:5
- |
-LL | / if b.is_empty() && a.is_empty() {
-LL | | panic!("panic2");
-LL | | }
- | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
-
-error: only a `panic!` in `if`-then statement
- --> $DIR/if_then_panic.rs:45:5
- |
-LL | / if a.is_empty() && !b.is_empty() {
-LL | | panic!("panic3");
-LL | | }
- | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
-
-error: only a `panic!` in `if`-then statement
- --> $DIR/if_then_panic.rs:48:5
- |
-LL | / if b.is_empty() || a.is_empty() {
-LL | | panic!("panic4");
-LL | | }
- | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
-
-error: only a `panic!` in `if`-then statement
- --> $DIR/if_then_panic.rs:51:5
- |
-LL | / if a.is_empty() || !b.is_empty() {
-LL | | panic!("panic5");
-LL | | }
- | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
-
-error: aborting due to 7 previous errors
-
-// edition:2018
// aux-build:implicit_hasher_macros.rs
#![deny(clippy::implicit_hasher)]
#![allow(unused)]
error: impl for `HashMap` should be generalized over different hashers
- --> $DIR/implicit_hasher.rs:17:35
+ --> $DIR/implicit_hasher.rs:16:35
|
LL | impl<K: Hash + Eq, V> Foo<i8> for HashMap<K, V> {
| ^^^^^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/implicit_hasher.rs:3:9
+ --> $DIR/implicit_hasher.rs:2:9
|
LL | #![deny(clippy::implicit_hasher)]
| ^^^^^^^^^^^^^^^^^^^^^^^
| ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: impl for `HashMap` should be generalized over different hashers
- --> $DIR/implicit_hasher.rs:26:36
+ --> $DIR/implicit_hasher.rs:25:36
|
LL | impl<K: Hash + Eq, V> Foo<i8> for (HashMap<K, V>,) {
| ^^^^^^^^^^^^^
| ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: impl for `HashMap` should be generalized over different hashers
- --> $DIR/implicit_hasher.rs:31:19
+ --> $DIR/implicit_hasher.rs:30:19
|
LL | impl Foo<i16> for HashMap<String, String> {
| ^^^^^^^^^^^^^^^^^^^^^^^
| ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: impl for `HashSet` should be generalized over different hashers
- --> $DIR/implicit_hasher.rs:48:32
+ --> $DIR/implicit_hasher.rs:47:32
|
LL | impl<T: Hash + Eq> Foo<i8> for HashSet<T> {
| ^^^^^^^^^^
| ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: impl for `HashSet` should be generalized over different hashers
- --> $DIR/implicit_hasher.rs:53:19
+ --> $DIR/implicit_hasher.rs:52:19
|
LL | impl Foo<i16> for HashSet<String> {
| ^^^^^^^^^^^^^^^
| ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: parameter of type `HashMap` should be generalized over different hashers
- --> $DIR/implicit_hasher.rs:70:23
+ --> $DIR/implicit_hasher.rs:69:23
|
LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
| ^^^^^^^^^^^^^^^^^
| +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~~~~~
error: parameter of type `HashSet` should be generalized over different hashers
- --> $DIR/implicit_hasher.rs:70:53
+ --> $DIR/implicit_hasher.rs:69:53
|
LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
| ^^^^^^^^^^^^
| +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~
error: impl for `HashMap` should be generalized over different hashers
- --> $DIR/implicit_hasher.rs:74:43
+ --> $DIR/implicit_hasher.rs:73:43
|
LL | impl<K: Hash + Eq, V> Foo<u8> for HashMap<K, V> {
| ^^^^^^^^^^^^^
| ~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: parameter of type `HashMap` should be generalized over different hashers
- --> $DIR/implicit_hasher.rs:82:33
+ --> $DIR/implicit_hasher.rs:81:33
|
LL | pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
| ^^^^^^^^^^^^^^^^^
| +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~~~~~~
error: parameter of type `HashSet` should be generalized over different hashers
- --> $DIR/implicit_hasher.rs:82:63
+ --> $DIR/implicit_hasher.rs:81:63
|
LL | pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {}
| ^^^^^^^^^^^^
| +++++++++++++++++++++++++++++ ~~~~~~~~~~~~~~~
error: parameter of type `HashMap` should be generalized over different hashers
- --> $DIR/implicit_hasher.rs:101:35
+ --> $DIR/implicit_hasher.rs:100:35
|
LL | pub async fn election_vote(_data: HashMap<i32, i32>) {}
| ^^^^^^^^^^^^^^^^^
-// edition:2018
// run-rustfix
#![warn(clippy::implicit_return)]
-// edition:2018
// run-rustfix
#![warn(clippy::implicit_return)]
error: missing `return` statement
- --> $DIR/implicit_return.rs:13:5
+ --> $DIR/implicit_return.rs:12:5
|
LL | true
| ^^^^ help: add `return` as shown: `return true`
= note: `-D clippy::implicit-return` implied by `-D warnings`
error: missing `return` statement
- --> $DIR/implicit_return.rs:17:15
+ --> $DIR/implicit_return.rs:16:15
|
LL | if true { true } else { false }
| ^^^^ help: add `return` as shown: `return true`
error: missing `return` statement
- --> $DIR/implicit_return.rs:17:29
+ --> $DIR/implicit_return.rs:16:29
|
LL | if true { true } else { false }
| ^^^^^ help: add `return` as shown: `return false`
error: missing `return` statement
- --> $DIR/implicit_return.rs:23:17
+ --> $DIR/implicit_return.rs:22:17
|
LL | true => false,
| ^^^^^ help: add `return` as shown: `return false`
error: missing `return` statement
- --> $DIR/implicit_return.rs:24:20
+ --> $DIR/implicit_return.rs:23:20
|
LL | false => { true },
| ^^^^ help: add `return` as shown: `return true`
error: missing `return` statement
- --> $DIR/implicit_return.rs:37:9
+ --> $DIR/implicit_return.rs:36:9
|
LL | break true;
| ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
error: missing `return` statement
- --> $DIR/implicit_return.rs:44:13
+ --> $DIR/implicit_return.rs:43:13
|
LL | break true;
| ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
error: missing `return` statement
- --> $DIR/implicit_return.rs:52:13
+ --> $DIR/implicit_return.rs:51:13
|
LL | break true;
| ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
error: missing `return` statement
- --> $DIR/implicit_return.rs:70:18
+ --> $DIR/implicit_return.rs:69:18
|
LL | let _ = || { true };
| ^^^^ help: add `return` as shown: `return true`
error: missing `return` statement
- --> $DIR/implicit_return.rs:71:16
+ --> $DIR/implicit_return.rs:70:16
|
LL | let _ = || true;
| ^^^^ help: add `return` as shown: `return true`
error: missing `return` statement
- --> $DIR/implicit_return.rs:79:5
+ --> $DIR/implicit_return.rs:78:5
|
LL | format!("test {}", "test")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `return` as shown: `return format!("test {}", "test")`
error: missing `return` statement
- --> $DIR/implicit_return.rs:88:5
+ --> $DIR/implicit_return.rs:87:5
|
LL | m!(true, false)
| ^^^^^^^^^^^^^^^ help: add `return` as shown: `return m!(true, false)`
error: missing `return` statement
- --> $DIR/implicit_return.rs:94:13
+ --> $DIR/implicit_return.rs:93:13
|
LL | break true;
| ^^^^^^^^^^ help: change `break` to `return` as shown: `return true`
error: missing `return` statement
- --> $DIR/implicit_return.rs:99:17
+ --> $DIR/implicit_return.rs:98:17
|
LL | break 'outer false;
| ^^^^^^^^^^^^^^^^^^ help: change `break` to `return` as shown: `return false`
error: missing `return` statement
- --> $DIR/implicit_return.rs:114:5
+ --> $DIR/implicit_return.rs:113:5
|
LL | / loop {
LL | | m!(true);
|
error: missing `return` statement
- --> $DIR/implicit_return.rs:128:5
+ --> $DIR/implicit_return.rs:127:5
|
LL | true
| ^^^^ help: add `return` as shown: `return true`
// run-rustfix
-// edition:2018
#![warn(clippy::inconsistent_struct_constructor)]
#![allow(clippy::redundant_field_names)]
#![allow(clippy::unnecessary_operation)]
// run-rustfix
-// edition:2018
#![warn(clippy::inconsistent_struct_constructor)]
#![allow(clippy::redundant_field_names)]
#![allow(clippy::unnecessary_operation)]
error: struct constructor field order is inconsistent with struct definition field order
- --> $DIR/inconsistent_struct_constructor.rs:34:9
+ --> $DIR/inconsistent_struct_constructor.rs:33:9
|
LL | Foo { y, x, z };
| ^^^^^^^^^^^^^^^ help: try: `Foo { x, y, z }`
= note: `-D clippy::inconsistent-struct-constructor` implied by `-D warnings`
error: struct constructor field order is inconsistent with struct definition field order
- --> $DIR/inconsistent_struct_constructor.rs:56:9
+ --> $DIR/inconsistent_struct_constructor.rs:55:9
|
LL | / Foo {
LL | | z,
--- /dev/null
+error: sub-expression diverges
+ --> $DIR/issue-7447.rs:23:15
+ |
+LL | byte_view(panic!());
+ | ^^^^^^^^
+ |
+ = note: `-D clippy::diverging-sub-expression` implied by `-D warnings`
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: sub-expression diverges
+ --> $DIR/issue-7447.rs:24:19
+ |
+LL | group_entries(panic!());
+ | ^^^^^^^^
+ |
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
-// edition:2018
#![allow(dead_code)]
async fn sink1<'a>(_: &'a str) {} // lint
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/issue_4266.rs:4:1
+ --> $DIR/issue_4266.rs:3:1
|
LL | async fn sink1<'a>(_: &'a str) {} // lint
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `-D clippy::needless-lifetimes` implied by `-D warnings`
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/issue_4266.rs:8:1
+ --> $DIR/issue_4266.rs:7:1
|
LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-// edition:2018
-
#![warn(clippy::len_without_is_empty)]
#![allow(dead_code, unused)]
error: struct `PubOne` has a public `len` method, but no `is_empty` method
- --> $DIR/len_without_is_empty.rs:9:5
+ --> $DIR/len_without_is_empty.rs:7:5
|
LL | pub fn len(&self) -> isize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: `-D clippy::len-without-is-empty` implied by `-D warnings`
error: trait `PubTraitsToo` has a `len` method but no (possibly inherited) `is_empty` method
- --> $DIR/len_without_is_empty.rs:57:1
+ --> $DIR/len_without_is_empty.rs:55:1
|
LL | / pub trait PubTraitsToo {
LL | | fn len(&self) -> isize;
| |_^
error: struct `HasIsEmpty` has a public `len` method, but a private `is_empty` method
- --> $DIR/len_without_is_empty.rs:70:5
+ --> $DIR/len_without_is_empty.rs:68:5
|
LL | pub fn len(&self) -> isize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `is_empty` defined here
- --> $DIR/len_without_is_empty.rs:74:5
+ --> $DIR/len_without_is_empty.rs:72:5
|
LL | fn is_empty(&self) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: struct `HasWrongIsEmpty` has a public `len` method, but the `is_empty` method has an unexpected signature
- --> $DIR/len_without_is_empty.rs:82:5
+ --> $DIR/len_without_is_empty.rs:80:5
|
LL | pub fn len(&self) -> isize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `is_empty` defined here
- --> $DIR/len_without_is_empty.rs:86:5
+ --> $DIR/len_without_is_empty.rs:84:5
|
LL | pub fn is_empty(&self, x: u32) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected signature: `(&self) -> bool`
error: struct `MismatchedSelf` has a public `len` method, but the `is_empty` method has an unexpected signature
- --> $DIR/len_without_is_empty.rs:94:5
+ --> $DIR/len_without_is_empty.rs:92:5
|
LL | pub fn len(self) -> isize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `is_empty` defined here
- --> $DIR/len_without_is_empty.rs:98:5
+ --> $DIR/len_without_is_empty.rs:96:5
|
LL | pub fn is_empty(&self) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected signature: `(self) -> bool`
error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method
- --> $DIR/len_without_is_empty.rs:173:1
+ --> $DIR/len_without_is_empty.rs:171:1
|
LL | / pub trait DependsOnFoo: Foo {
LL | | fn len(&mut self) -> usize;
| |_^
error: struct `OptionalLen3` has a public `len` method, but the `is_empty` method has an unexpected signature
- --> $DIR/len_without_is_empty.rs:218:5
+ --> $DIR/len_without_is_empty.rs:216:5
|
LL | pub fn len(&self) -> usize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `is_empty` defined here
- --> $DIR/len_without_is_empty.rs:223:5
+ --> $DIR/len_without_is_empty.rs:221:5
|
LL | pub fn is_empty(&self) -> Option<bool> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected signature: `(&self) -> bool`
error: struct `ResultLen` has a public `len` method, but the `is_empty` method has an unexpected signature
- --> $DIR/len_without_is_empty.rs:230:5
+ --> $DIR/len_without_is_empty.rs:228:5
|
LL | pub fn len(&self) -> Result<usize, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: `is_empty` defined here
- --> $DIR/len_without_is_empty.rs:235:5
+ --> $DIR/len_without_is_empty.rs:233:5
|
LL | pub fn is_empty(&self) -> Option<bool> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected signature: `(&self) -> bool` or `(&self) -> Result<bool>
error: this returns a `Result<_, ()>`
- --> $DIR/len_without_is_empty.rs:230:5
+ --> $DIR/len_without_is_empty.rs:228:5
|
LL | pub fn len(&self) -> Result<usize, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: use a custom `Error` type instead
error: this returns a `Result<_, ()>`
- --> $DIR/len_without_is_empty.rs:242:5
+ --> $DIR/len_without_is_empty.rs:240:5
|
LL | pub fn len(&self) -> Result<usize, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: use a custom `Error` type instead
error: this returns a `Result<_, ()>`
- --> $DIR/len_without_is_empty.rs:246:5
+ --> $DIR/len_without_is_empty.rs:244:5
|
LL | pub fn is_empty(&self) -> Result<bool, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: use a custom `Error` type instead
error: this returns a `Result<_, ()>`
- --> $DIR/len_without_is_empty.rs:253:5
+ --> $DIR/len_without_is_empty.rs:251:5
|
LL | pub fn len(&self) -> Result<usize, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#![warn(clippy::mixed_case_hex_literals)]
#![warn(clippy::zero_prefixed_literal)]
-#![allow(clippy::unseparated_literal_suffix)]
+#![warn(clippy::unseparated_literal_suffix)]
+#![warn(clippy::separated_literal_suffix)]
#![allow(dead_code)]
fn main() {
+error: integer type suffix should not be separated by an underscore
+ --> $DIR/literals.rs:12:15
+ |
+LL | let ok4 = 0xab_cd_i32;
+ | ^^^^^^^^^^^ help: remove the underscore: `0xab_cdi32`
+ |
+ = note: `-D clippy::separated-literal-suffix` implied by `-D warnings`
+
+error: integer type suffix should not be separated by an underscore
+ --> $DIR/literals.rs:13:15
+ |
+LL | let ok5 = 0xAB_CD_u32;
+ | ^^^^^^^^^^^ help: remove the underscore: `0xAB_CDu32`
+
+error: integer type suffix should not be separated by an underscore
+ --> $DIR/literals.rs:14:15
+ |
+LL | let ok5 = 0xAB_CD_isize;
+ | ^^^^^^^^^^^^^ help: remove the underscore: `0xAB_CDisize`
+
error: inconsistent casing in hexadecimal literal
- --> $DIR/literals.rs:14:17
+ --> $DIR/literals.rs:15:17
|
LL | let fail1 = 0xabCD;
| ^^^^^^
|
= note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings`
+error: integer type suffix should not be separated by an underscore
+ --> $DIR/literals.rs:16:17
+ |
+LL | let fail2 = 0xabCD_u32;
+ | ^^^^^^^^^^ help: remove the underscore: `0xabCDu32`
+
error: inconsistent casing in hexadecimal literal
- --> $DIR/literals.rs:15:17
+ --> $DIR/literals.rs:16:17
|
LL | let fail2 = 0xabCD_u32;
| ^^^^^^^^^^
+error: integer type suffix should not be separated by an underscore
+ --> $DIR/literals.rs:17:17
+ |
+LL | let fail2 = 0xabCD_isize;
+ | ^^^^^^^^^^^^ help: remove the underscore: `0xabCDisize`
+
error: inconsistent casing in hexadecimal literal
- --> $DIR/literals.rs:16:17
+ --> $DIR/literals.rs:17:17
|
LL | let fail2 = 0xabCD_isize;
| ^^^^^^^^^^^^
+error: integer type suffix should be separated by an underscore
+ --> $DIR/literals.rs:18:27
+ |
+LL | let fail_multi_zero = 000_123usize;
+ | ^^^^^^^^^^^^ help: add an underscore: `000_123_usize`
+ |
+ = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings`
+
error: this is a decimal constant
- --> $DIR/literals.rs:17:27
+ --> $DIR/literals.rs:18:27
|
LL | let fail_multi_zero = 000_123usize;
| ^^^^^^^^^^^^
LL | let fail_multi_zero = 0o123usize;
| ~~~~~~~~~~
+error: integer type suffix should not be separated by an underscore
+ --> $DIR/literals.rs:21:16
+ |
+LL | let ok10 = 0_i64;
+ | ^^^^^ help: remove the underscore: `0i64`
+
error: this is a decimal constant
- --> $DIR/literals.rs:21:17
+ --> $DIR/literals.rs:22:17
|
LL | let fail8 = 0123;
| ^^^^
LL | let fail8 = 0o123;
| ~~~~~
+error: integer type suffix should not be separated by an underscore
+ --> $DIR/literals.rs:31:16
+ |
+LL | let ok17 = 0x123_4567_8901_usize;
+ | ^^^^^^^^^^^^^^^^^^^^^ help: remove the underscore: `0x123_4567_8901usize`
+
error: digits grouped inconsistently by underscores
- --> $DIR/literals.rs:33:18
+ --> $DIR/literals.rs:34:18
|
LL | let fail19 = 12_3456_21;
| ^^^^^^^^^^ help: consider: `12_345_621`
= note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings`
error: digits grouped inconsistently by underscores
- --> $DIR/literals.rs:34:18
+ --> $DIR/literals.rs:35:18
|
LL | let fail22 = 3__4___23;
| ^^^^^^^^^ help: consider: `3_423`
error: digits grouped inconsistently by underscores
- --> $DIR/literals.rs:35:18
+ --> $DIR/literals.rs:36:18
|
LL | let fail23 = 3__16___23;
| ^^^^^^^^^^ help: consider: `31_623`
error: digits of hex or binary literal not grouped by four
- --> $DIR/literals.rs:37:18
+ --> $DIR/literals.rs:38:18
|
LL | let fail24 = 0xAB_ABC_AB;
| ^^^^^^^^^^^ help: consider: `0x0ABA_BCAB`
= note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
error: digits of hex or binary literal not grouped by four
- --> $DIR/literals.rs:38:18
+ --> $DIR/literals.rs:39:18
|
LL | let fail25 = 0b01_100_101;
| ^^^^^^^^^^^^ help: consider: `0b0110_0101`
-error: aborting due to 10 previous errors
+error: aborting due to 18 previous errors
-// compile-flags: --edition 2018
// aux-build:macro_rules.rs
// aux-build:macro_use_helper.rs
// aux-build:proc_macro_derive.rs
-// compile-flags: --edition 2018
// aux-build:macro_rules.rs
// aux-build:macro_use_helper.rs
// aux-build:proc_macro_derive.rs
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
- --> $DIR/macro_use_imports.rs:19:5
+ --> $DIR/macro_use_imports.rs:18:5
|
LL | #[macro_use]
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};`
= note: `-D clippy::macro-use-imports` implied by `-D warnings`
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
- --> $DIR/macro_use_imports.rs:25:5
+ --> $DIR/macro_use_imports.rs:20:5
|
LL | #[macro_use]
- | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
+ | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;`
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
- --> $DIR/macro_use_imports.rs:21:5
+ --> $DIR/macro_use_imports.rs:22:5
|
LL | #[macro_use]
- | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;`
+ | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
- --> $DIR/macro_use_imports.rs:23:5
+ --> $DIR/macro_use_imports.rs:24:5
|
LL | #[macro_use]
- | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
+ | ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
error: aborting due to 4 previous errors
--- /dev/null
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
+// run-rustfix
+#![warn(clippy::manual_assert)]
+
+fn main() {
+ let a = vec![1, 2, 3];
+ let c = Some(2);
+ if !a.is_empty()
+ && a.len() == 3
+ && c != None
+ && !a.is_empty()
+ && a.len() == 3
+ && !a.is_empty()
+ && a.len() == 3
+ && !a.is_empty()
+ && a.len() == 3
+ {
+ panic!("qaqaq{:?}", a);
+ }
+ assert!(a.is_empty(), "qaqaq{:?}", a);
+ assert!(a.is_empty(), "qwqwq");
+ if a.len() == 3 {
+ println!("qwq");
+ println!("qwq");
+ println!("qwq");
+ }
+ if let Some(b) = c {
+ panic!("orz {}", b);
+ }
+ if a.len() == 3 {
+ panic!("qaqaq");
+ } else {
+ println!("qwq");
+ }
+ let b = vec![1, 2, 3];
+ assert!(!b.is_empty(), "panic1");
+ assert!(!(b.is_empty() && a.is_empty()), "panic2");
+ assert!(!(a.is_empty() && !b.is_empty()), "panic3");
+ assert!(!(b.is_empty() || a.is_empty()), "panic4");
+ assert!(!(a.is_empty() || !b.is_empty()), "panic5");
+}
--- /dev/null
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:22:5
+ |
+LL | / if !a.is_empty() {
+LL | | panic!("qaqaq{:?}", a);
+LL | | }
+ | |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);`
+ |
+ = note: `-D clippy::manual-assert` implied by `-D warnings`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:25:5
+ |
+LL | / if !a.is_empty() {
+LL | | panic!("qwqwq");
+LL | | }
+ | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:42:5
+ |
+LL | / if b.is_empty() {
+LL | | panic!("panic1");
+LL | | }
+ | |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:45:5
+ |
+LL | / if b.is_empty() && a.is_empty() {
+LL | | panic!("panic2");
+LL | | }
+ | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:48:5
+ |
+LL | / if a.is_empty() && !b.is_empty() {
+LL | | panic!("panic3");
+LL | | }
+ | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:51:5
+ |
+LL | / if b.is_empty() || a.is_empty() {
+LL | | panic!("panic4");
+LL | | }
+ | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:54:5
+ |
+LL | / if a.is_empty() || !b.is_empty() {
+LL | | panic!("panic5");
+LL | | }
+ | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
+
+error: aborting due to 7 previous errors
+
--- /dev/null
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
+// run-rustfix
+#![warn(clippy::manual_assert)]
+
+fn main() {
+ let a = vec![1, 2, 3];
+ let c = Some(2);
+ if !a.is_empty()
+ && a.len() == 3
+ && c != None
+ && !a.is_empty()
+ && a.len() == 3
+ && !a.is_empty()
+ && a.len() == 3
+ && !a.is_empty()
+ && a.len() == 3
+ {
+ panic!("qaqaq{:?}", a);
+ }
+ assert!(a.is_empty(), "qaqaq{:?}", a);
+ assert!(a.is_empty(), "qwqwq");
+ if a.len() == 3 {
+ println!("qwq");
+ println!("qwq");
+ println!("qwq");
+ }
+ if let Some(b) = c {
+ panic!("orz {}", b);
+ }
+ if a.len() == 3 {
+ panic!("qaqaq");
+ } else {
+ println!("qwq");
+ }
+ let b = vec![1, 2, 3];
+ assert!(!b.is_empty(), "panic1");
+ assert!(!(b.is_empty() && a.is_empty()), "panic2");
+ assert!(!(a.is_empty() && !b.is_empty()), "panic3");
+ assert!(!(b.is_empty() || a.is_empty()), "panic4");
+ assert!(!(a.is_empty() || !b.is_empty()), "panic5");
+}
--- /dev/null
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:22:5
+ |
+LL | / if !a.is_empty() {
+LL | | panic!("qaqaq{:?}", a);
+LL | | }
+ | |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);`
+ |
+ = note: `-D clippy::manual-assert` implied by `-D warnings`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:25:5
+ |
+LL | / if !a.is_empty() {
+LL | | panic!("qwqwq");
+LL | | }
+ | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:42:5
+ |
+LL | / if b.is_empty() {
+LL | | panic!("panic1");
+LL | | }
+ | |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:45:5
+ |
+LL | / if b.is_empty() && a.is_empty() {
+LL | | panic!("panic2");
+LL | | }
+ | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:48:5
+ |
+LL | / if a.is_empty() && !b.is_empty() {
+LL | | panic!("panic3");
+LL | | }
+ | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:51:5
+ |
+LL | / if b.is_empty() || a.is_empty() {
+LL | | panic!("panic4");
+LL | | }
+ | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
+
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:54:5
+ |
+LL | / if a.is_empty() || !b.is_empty() {
+LL | | panic!("panic5");
+LL | | }
+ | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
+
+error: aborting due to 7 previous errors
+
--- /dev/null
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
+// run-rustfix
+#![warn(clippy::manual_assert)]
+
+fn main() {
+ let a = vec![1, 2, 3];
+ let c = Some(2);
+ if !a.is_empty()
+ && a.len() == 3
+ && c != None
+ && !a.is_empty()
+ && a.len() == 3
+ && !a.is_empty()
+ && a.len() == 3
+ && !a.is_empty()
+ && a.len() == 3
+ {
+ panic!("qaqaq{:?}", a);
+ }
+ assert!(a.is_empty(), "qaqaq{:?}", a);
+ assert!(a.is_empty(), "qwqwq");
+ if a.len() == 3 {
+ println!("qwq");
+ println!("qwq");
+ println!("qwq");
+ }
+ if let Some(b) = c {
+ panic!("orz {}", b);
+ }
+ if a.len() == 3 {
+ panic!("qaqaq");
+ } else {
+ println!("qwq");
+ }
+ let b = vec![1, 2, 3];
+ assert!(!b.is_empty(), "panic1");
+ assert!(!(b.is_empty() && a.is_empty()), "panic2");
+ assert!(!(a.is_empty() && !b.is_empty()), "panic3");
+ assert!(!(b.is_empty() || a.is_empty()), "panic4");
+ assert!(!(a.is_empty() || !b.is_empty()), "panic5");
+}
--- /dev/null
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
+// run-rustfix
+#![warn(clippy::manual_assert)]
+
+fn main() {
+ let a = vec![1, 2, 3];
+ let c = Some(2);
+ if !a.is_empty()
+ && a.len() == 3
+ && c != None
+ && !a.is_empty()
+ && a.len() == 3
+ && !a.is_empty()
+ && a.len() == 3
+ && !a.is_empty()
+ && a.len() == 3
+ {
+ panic!("qaqaq{:?}", a);
+ }
+ if !a.is_empty() {
+ panic!("qaqaq{:?}", a);
+ }
+ if !a.is_empty() {
+ panic!("qwqwq");
+ }
+ if a.len() == 3 {
+ println!("qwq");
+ println!("qwq");
+ println!("qwq");
+ }
+ if let Some(b) = c {
+ panic!("orz {}", b);
+ }
+ if a.len() == 3 {
+ panic!("qaqaq");
+ } else {
+ println!("qwq");
+ }
+ let b = vec![1, 2, 3];
+ if b.is_empty() {
+ panic!("panic1");
+ }
+ if b.is_empty() && a.is_empty() {
+ panic!("panic2");
+ }
+ if a.is_empty() && !b.is_empty() {
+ panic!("panic3");
+ }
+ if b.is_empty() || a.is_empty() {
+ panic!("panic4");
+ }
+ if a.is_empty() || !b.is_empty() {
+ panic!("panic5");
+ }
+}
// run-rustfix
-// edition:2018
#![warn(clippy::manual_async_fn)]
#![allow(unused)]
// run-rustfix
-// edition:2018
#![warn(clippy::manual_async_fn)]
#![allow(unused)]
error: this function can be simplified using the `async fn` syntax
- --> $DIR/manual_async_fn.rs:8:1
+ --> $DIR/manual_async_fn.rs:7:1
|
LL | fn fut() -> impl Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
- --> $DIR/manual_async_fn.rs:13:1
+ --> $DIR/manual_async_fn.rs:12:1
|
LL | fn fut2() ->impl Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
- --> $DIR/manual_async_fn.rs:18:1
+ --> $DIR/manual_async_fn.rs:17:1
|
LL | fn fut3()-> impl Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
- --> $DIR/manual_async_fn.rs:22:1
+ --> $DIR/manual_async_fn.rs:21:1
|
LL | fn empty_fut() -> impl Future<Output = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ~~
error: this function can be simplified using the `async fn` syntax
- --> $DIR/manual_async_fn.rs:27:1
+ --> $DIR/manual_async_fn.rs:26:1
|
LL | fn empty_fut2() ->impl Future<Output = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ~~
error: this function can be simplified using the `async fn` syntax
- --> $DIR/manual_async_fn.rs:32:1
+ --> $DIR/manual_async_fn.rs:31:1
|
LL | fn empty_fut3()-> impl Future<Output = ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ~~
error: this function can be simplified using the `async fn` syntax
- --> $DIR/manual_async_fn.rs:36:1
+ --> $DIR/manual_async_fn.rs:35:1
|
LL | fn core_fut() -> impl core::future::Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
- --> $DIR/manual_async_fn.rs:58:5
+ --> $DIR/manual_async_fn.rs:57:5
|
LL | fn inh_fut() -> impl Future<Output = i32> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
error: this function can be simplified using the `async fn` syntax
- --> $DIR/manual_async_fn.rs:93:1
+ --> $DIR/manual_async_fn.rs:92:1
|
LL | fn elided(_: &i32) -> impl Future<Output = i32> + '_ {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ~~~~~~
error: this function can be simplified using the `async fn` syntax
- --> $DIR/manual_async_fn.rs:102:1
+ --> $DIR/manual_async_fn.rs:101:1
|
LL | fn explicit<'a, 'b>(_: &'a i32, _: &'b i32) -> impl Future<Output = i32> + 'a + 'b {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-// edition:2018
// run-rustfix
#![warn(clippy::manual_map)]
-// edition:2018
// run-rustfix
#![warn(clippy::manual_map)]
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:15:5
+ --> $DIR/manual_map_option.rs:14:5
|
LL | / match Some(0) {
LL | | Some(_) => Some(2),
= note: `-D clippy::manual-map` implied by `-D warnings`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:20:5
+ --> $DIR/manual_map_option.rs:19:5
|
LL | / match Some(0) {
LL | | Some(x) => Some(x + 1),
| |_____^ help: try this: `Some(0).map(|x| x + 1)`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:25:5
+ --> $DIR/manual_map_option.rs:24:5
|
LL | / match Some("") {
LL | | Some(x) => Some(x.is_empty()),
| |_____^ help: try this: `Some("").map(|x| x.is_empty())`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:30:5
+ --> $DIR/manual_map_option.rs:29:5
|
LL | / if let Some(x) = Some(0) {
LL | | Some(!x)
| |_____^ help: try this: `Some(0).map(|x| !x)`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:37:5
+ --> $DIR/manual_map_option.rs:36:5
|
LL | / match Some(0) {
LL | | Some(x) => { Some(std::convert::identity(x)) }
| |_____^ help: try this: `Some(0).map(std::convert::identity)`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:42:5
+ --> $DIR/manual_map_option.rs:41:5
|
LL | / match Some(&String::new()) {
LL | | Some(x) => Some(str::len(x)),
| |_____^ help: try this: `Some(&String::new()).map(|x| str::len(x))`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:52:5
+ --> $DIR/manual_map_option.rs:51:5
|
LL | / match &Some([0, 1]) {
LL | | Some(x) => Some(x[0]),
| |_____^ help: try this: `Some([0, 1]).as_ref().map(|x| x[0])`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:57:5
+ --> $DIR/manual_map_option.rs:56:5
|
LL | / match &Some(0) {
LL | | &Some(x) => Some(x * 2),
| |_____^ help: try this: `Some(0).map(|x| x * 2)`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:62:5
+ --> $DIR/manual_map_option.rs:61:5
|
LL | / match Some(String::new()) {
LL | | Some(ref x) => Some(x.is_empty()),
| |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.is_empty())`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:67:5
+ --> $DIR/manual_map_option.rs:66:5
|
LL | / match &&Some(String::new()) {
LL | | Some(x) => Some(x.len()),
| |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.len())`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:72:5
+ --> $DIR/manual_map_option.rs:71:5
|
LL | / match &&Some(0) {
LL | | &&Some(x) => Some(x + x),
| |_____^ help: try this: `Some(0).map(|x| x + x)`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:85:9
+ --> $DIR/manual_map_option.rs:84:9
|
LL | / match &mut Some(String::new()) {
LL | | Some(x) => Some(x.push_str("")),
| |_________^ help: try this: `Some(String::new()).as_mut().map(|x| x.push_str(""))`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:91:5
+ --> $DIR/manual_map_option.rs:90:5
|
LL | / match &mut Some(String::new()) {
LL | | Some(ref x) => Some(x.len()),
| |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.len())`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:96:5
+ --> $DIR/manual_map_option.rs:95:5
|
LL | / match &mut &Some(String::new()) {
LL | | Some(x) => Some(x.is_empty()),
| |_____^ help: try this: `Some(String::new()).as_ref().map(|x| x.is_empty())`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:101:5
+ --> $DIR/manual_map_option.rs:100:5
|
LL | / match Some((0, 1, 2)) {
LL | | Some((x, y, z)) => Some(x + y + z),
| |_____^ help: try this: `Some((0, 1, 2)).map(|(x, y, z)| x + y + z)`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:106:5
+ --> $DIR/manual_map_option.rs:105:5
|
LL | / match Some([1, 2, 3]) {
LL | | Some([first, ..]) => Some(first),
| |_____^ help: try this: `Some([1, 2, 3]).map(|[first, ..]| first)`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:111:5
+ --> $DIR/manual_map_option.rs:110:5
|
LL | / match &Some((String::new(), "test")) {
LL | | Some((x, y)) => Some((y, x)),
| |_____^ help: try this: `Some((String::new(), "test")).as_ref().map(|(x, y)| (y, x))`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:169:5
+ --> $DIR/manual_map_option.rs:168:5
|
LL | / match Some(0) {
LL | | Some(x) => Some(vec![x]),
| |_____^ help: try this: `Some(0).map(|x| vec![x])`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:174:5
+ --> $DIR/manual_map_option.rs:173:5
|
LL | / match option_env!("") {
LL | | Some(x) => Some(String::from(x)),
| |_____^ help: try this: `option_env!("").map(String::from)`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:194:12
+ --> $DIR/manual_map_option.rs:193:12
|
LL | } else if let Some(x) = Some(0) {
| ____________^
| |_____^ help: try this: `{ Some(0).map(|x| x + 1) }`
error: manual implementation of `Option::map`
- --> $DIR/manual_map_option.rs:202:12
+ --> $DIR/manual_map_option.rs:201:12
|
LL | } else if let Some(x) = Some(0) {
| ____________^
_ => (),
}
+ // Issue #7829
+ match 0 {
+ -1..=1 => (),
+ -2..=2 => (),
+ _ => (),
+ }
+
if let None = Some(42) {
// nothing
} else if let None = Some(42) {
#![warn(clippy::match_ref_pats)]
-#![allow(clippy::equatable_if_let)]
+#![allow(clippy::equatable_if_let, clippy::enum_variant_names)]
fn ref_pats() {
{
}
}
+fn non_alphabetic() {
+ let var = "~!@#$%^&*()-_=+FOO";
+
+ match var.to_ascii_lowercase().as_str() {
+ "1234567890" => {},
+ "~!@#$%^&*()-_=+foo" => {},
+ "\n\r\t\x7F" => {},
+ _ => {},
+ }
+}
+
+fn unicode_cased() {
+ let var = "ВОДЫ";
+
+ match var.to_lowercase().as_str() {
+ "水" => {},
+ "νερό" => {},
+ "воды" => {},
+ "물" => {},
+ _ => {},
+ }
+}
+
+fn titlecase() {
+ let var = "BarDz";
+
+ match var.to_lowercase().as_str() {
+ "foolj" => {},
+ "bardz" => {},
+ _ => {},
+ }
+}
+
+fn no_case_equivalent() {
+ let var = "barʁ";
+
+ match var.to_uppercase().as_str() {
+ "FOOɕ" => {},
+ "BARʁ" => {},
+ _ => {},
+ }
+}
+
fn addrof_unary_match() {
let var = "BAR";
}
}
+fn non_alphabetic_mismatch() {
+ let var = "~!@#$%^&*()-_=+FOO";
+
+ match var.to_ascii_lowercase().as_str() {
+ "1234567890" => {},
+ "~!@#$%^&*()-_=+Foo" => {},
+ "\n\r\t\x7F" => {},
+ _ => {},
+ }
+}
+
+fn unicode_cased_mismatch() {
+ let var = "ВОДЫ";
+
+ match var.to_lowercase().as_str() {
+ "水" => {},
+ "νερό" => {},
+ "Воды" => {},
+ "물" => {},
+ _ => {},
+ }
+}
+
+fn titlecase_mismatch() {
+ let var = "BarDz";
+
+ match var.to_lowercase().as_str() {
+ "foolj" => {},
+ "barDz" => {},
+ _ => {},
+ }
+}
+
+fn no_case_equivalent_mismatch() {
+ let var = "barʁ";
+
+ match var.to_uppercase().as_str() {
+ "FOOɕ" => {},
+ "bARʁ" => {},
+ _ => {},
+ }
+}
+
fn addrof_unary_match_mismatch() {
let var = "BAR";
error: this `match` arm has a differing case than its expression
- --> $DIR/match_str_case_mismatch.rs:68:9
+ --> $DIR/match_str_case_mismatch.rs:111:9
|
LL | "Bar" => {},
| ^^^^^
| ~~~~~
error: this `match` arm has a differing case than its expression
- --> $DIR/match_str_case_mismatch.rs:78:9
+ --> $DIR/match_str_case_mismatch.rs:121:9
+ |
+LL | "~!@#$%^&*()-_=+Foo" => {},
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+help: consider changing the case of this arm to respect `to_ascii_lowercase`
+ |
+LL | "~!@#$%^&*()-_=+foo" => {},
+ | ~~~~~~~~~~~~~~~~~~~~
+
+error: this `match` arm has a differing case than its expression
+ --> $DIR/match_str_case_mismatch.rs:133:9
+ |
+LL | "Воды" => {},
+ | ^^^^^^
+ |
+help: consider changing the case of this arm to respect `to_lowercase`
+ |
+LL | "воды" => {},
+ | ~~~~~~
+
+error: this `match` arm has a differing case than its expression
+ --> $DIR/match_str_case_mismatch.rs:144:9
+ |
+LL | "barDz" => {},
+ | ^^^^^^
+ |
+help: consider changing the case of this arm to respect `to_lowercase`
+ |
+LL | "bardz" => {},
+ | ~~~~~~
+
+error: this `match` arm has a differing case than its expression
+ --> $DIR/match_str_case_mismatch.rs:154:9
+ |
+LL | "bARʁ" => {},
+ | ^^^^^^
+ |
+help: consider changing the case of this arm to respect `to_uppercase`
+ |
+LL | "BARʁ" => {},
+ | ~~~~~~
+
+error: this `match` arm has a differing case than its expression
+ --> $DIR/match_str_case_mismatch.rs:164:9
|
LL | "Bar" => {},
| ^^^^^
| ~~~~~
error: this `match` arm has a differing case than its expression
- --> $DIR/match_str_case_mismatch.rs:93:9
+ --> $DIR/match_str_case_mismatch.rs:179:9
|
LL | "bAR" => {},
| ^^^^^
LL | "BAR" => {},
| ~~~~~
-error: aborting due to 3 previous errors
+error: aborting due to 7 previous errors
--- /dev/null
+error: `Err(_)` matches all errors
+ --> $DIR/match_wild_err_arm.rs:14:9
+ |
+LL | Err(_) => panic!("err"),
+ | ^^^^^^
+ |
+ = note: `-D clippy::match-wild-err-arm` implied by `-D warnings`
+ = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_)` matches all errors
+ --> $DIR/match_wild_err_arm.rs:20:9
+ |
+LL | Err(_) => panic!(),
+ | ^^^^^^
+ |
+ = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_)` matches all errors
+ --> $DIR/match_wild_err_arm.rs:26:9
+ |
+LL | Err(_) => {
+ | ^^^^^^
+ |
+ = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_e)` matches all errors
+ --> $DIR/match_wild_err_arm.rs:34:9
+ |
+LL | Err(_e) => panic!(),
+ | ^^^^^^^
+ |
+ = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: aborting due to 4 previous errors
+
--- /dev/null
+error: `Err(_)` matches all errors
+ --> $DIR/match_wild_err_arm.rs:14:9
+ |
+LL | Err(_) => panic!("err"),
+ | ^^^^^^
+ |
+ = note: `-D clippy::match-wild-err-arm` implied by `-D warnings`
+ = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_)` matches all errors
+ --> $DIR/match_wild_err_arm.rs:20:9
+ |
+LL | Err(_) => panic!(),
+ | ^^^^^^
+ |
+ = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_)` matches all errors
+ --> $DIR/match_wild_err_arm.rs:26:9
+ |
+LL | Err(_) => {
+ | ^^^^^^
+ |
+ = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: `Err(_e)` matches all errors
+ --> $DIR/match_wild_err_arm.rs:34:9
+ |
+LL | Err(_e) => panic!(),
+ | ^^^^^^^
+ |
+ = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
+
+error: aborting due to 4 previous errors
+
+// revisions: edition2018 edition2021
+// [edition2018] edition:2018
+// [edition2021] edition:2021
#![feature(exclusive_range_pattern)]
#![allow(clippy::match_same_arms)]
#![warn(clippy::match_wild_err_arm)]
+++ /dev/null
-error: `Err(_)` matches all errors
- --> $DIR/match_wild_err_arm.rs:11:9
- |
-LL | Err(_) => panic!("err"),
- | ^^^^^^
- |
- = note: `-D clippy::match-wild-err-arm` implied by `-D warnings`
- = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
-
-error: `Err(_)` matches all errors
- --> $DIR/match_wild_err_arm.rs:17:9
- |
-LL | Err(_) => panic!(),
- | ^^^^^^
- |
- = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
-
-error: `Err(_)` matches all errors
- --> $DIR/match_wild_err_arm.rs:23:9
- |
-LL | Err(_) => {
- | ^^^^^^
- |
- = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
-
-error: `Err(_e)` matches all errors
- --> $DIR/match_wild_err_arm.rs:31:9
- |
-LL | Err(_e) => panic!(),
- | ^^^^^^^
- |
- = note: match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable
-
-error: aborting due to 4 previous errors
-
// aux-build:option_helpers.rs
-// edition:2018
#![warn(clippy::all, clippy::pedantic)]
#![allow(
error: methods called `new` usually return `Self`
- --> $DIR/methods.rs:105:5
+ --> $DIR/methods.rs:104:5
|
LL | / fn new() -> i32 {
LL | | 0
= note: `-D clippy::new-ret-no-self` implied by `-D warnings`
error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead
- --> $DIR/methods.rs:126:13
+ --> $DIR/methods.rs:125:13
|
LL | let _ = v.iter().filter(|&x| {
| _____________^
// injected intrinsics by the compiler.
#![allow(dead_code)]
#![feature(global_asm)]
-
//! Some garbage docs for the crate here
#![doc = "More garbage"]
}
/// dox
pub mod public_interface {
- pub use internal_impl::documented as foo;
- pub use internal_impl::globbed::*;
- pub use internal_impl::undocumented1 as bar;
- pub use internal_impl::{documented, undocumented2};
+ pub use crate::internal_impl::documented as foo;
+ pub use crate::internal_impl::globbed::*;
+ pub use crate::internal_impl::undocumented1 as bar;
+ pub use crate::internal_impl::{documented, undocumented2};
}
fn main() {}
error: missing documentation for a type alias
- --> $DIR/missing-doc.rs:10:1
+ --> $DIR/missing-doc.rs:9:1
|
LL | type Typedef = String;
| ^^^^^^^^^^^^^^^^^^^^^^
= note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings`
error: missing documentation for a type alias
- --> $DIR/missing-doc.rs:11:1
+ --> $DIR/missing-doc.rs:10:1
|
LL | pub type PubTypedef = String;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a module
- --> $DIR/missing-doc.rs:13:1
+ --> $DIR/missing-doc.rs:12:1
|
LL | mod module_no_dox {}
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a module
- --> $DIR/missing-doc.rs:14:1
+ --> $DIR/missing-doc.rs:13:1
|
LL | pub mod pub_module_no_dox {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing-doc.rs:18:1
+ --> $DIR/missing-doc.rs:17:1
|
LL | pub fn foo2() {}
| ^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing-doc.rs:19:1
+ --> $DIR/missing-doc.rs:18:1
|
LL | fn foo3() {}
| ^^^^^^^^^^^^
error: missing documentation for an enum
- --> $DIR/missing-doc.rs:33:1
+ --> $DIR/missing-doc.rs:32:1
|
LL | / enum Baz {
LL | | BazA { a: isize, b: isize },
| |_^
error: missing documentation for a variant
- --> $DIR/missing-doc.rs:34:5
+ --> $DIR/missing-doc.rs:33:5
|
LL | BazA { a: isize, b: isize },
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a struct field
- --> $DIR/missing-doc.rs:34:12
+ --> $DIR/missing-doc.rs:33:12
|
LL | BazA { a: isize, b: isize },
| ^^^^^^^^
error: missing documentation for a struct field
- --> $DIR/missing-doc.rs:34:22
+ --> $DIR/missing-doc.rs:33:22
|
LL | BazA { a: isize, b: isize },
| ^^^^^^^^
error: missing documentation for a variant
- --> $DIR/missing-doc.rs:35:5
+ --> $DIR/missing-doc.rs:34:5
|
LL | BarB,
| ^^^^
error: missing documentation for an enum
- --> $DIR/missing-doc.rs:38:1
+ --> $DIR/missing-doc.rs:37:1
|
LL | / pub enum PubBaz {
LL | | PubBazA { a: isize },
| |_^
error: missing documentation for a variant
- --> $DIR/missing-doc.rs:39:5
+ --> $DIR/missing-doc.rs:38:5
|
LL | PubBazA { a: isize },
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a struct field
- --> $DIR/missing-doc.rs:39:15
+ --> $DIR/missing-doc.rs:38:15
|
LL | PubBazA { a: isize },
| ^^^^^^^^
error: missing documentation for a constant
- --> $DIR/missing-doc.rs:59:1
+ --> $DIR/missing-doc.rs:58:1
|
LL | const FOO: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^
error: missing documentation for a constant
- --> $DIR/missing-doc.rs:66:1
+ --> $DIR/missing-doc.rs:65:1
|
LL | pub const FOO4: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a static
- --> $DIR/missing-doc.rs:68:1
+ --> $DIR/missing-doc.rs:67:1
|
LL | static BAR: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a static
- --> $DIR/missing-doc.rs:75:1
+ --> $DIR/missing-doc.rs:74:1
|
LL | pub static BAR4: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a module
- --> $DIR/missing-doc.rs:77:1
+ --> $DIR/missing-doc.rs:76:1
|
LL | / mod internal_impl {
LL | | /// dox
| |_^
error: missing documentation for a function
- --> $DIR/missing-doc.rs:80:5
+ --> $DIR/missing-doc.rs:79:5
|
LL | pub fn undocumented1() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing-doc.rs:81:5
+ --> $DIR/missing-doc.rs:80:5
|
LL | pub fn undocumented2() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing-doc.rs:82:5
+ --> $DIR/missing-doc.rs:81:5
|
LL | fn undocumented3() {}
| ^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing-doc.rs:87:9
+ --> $DIR/missing-doc.rs:86:9
|
LL | pub fn also_undocumented1() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing-doc.rs:88:9
+ --> $DIR/missing-doc.rs:87:9
|
LL | fn also_undocumented2() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
#![warn(clippy::missing_panics_doc)]
#![allow(clippy::option_map_unit_fn)]
-
fn main() {}
/// This needs to be documented
error: docs for function which may panic missing `# Panics` section
- --> $DIR/missing_panics_doc.rs:7:1
+ --> $DIR/missing_panics_doc.rs:6:1
|
LL | / pub fn unwrap() {
LL | | let result = Err("Hi");
|
= note: `-D clippy::missing-panics-doc` implied by `-D warnings`
note: first possible panic found here
- --> $DIR/missing_panics_doc.rs:9:5
+ --> $DIR/missing_panics_doc.rs:8:5
|
LL | result.unwrap()
| ^^^^^^^^^^^^^^^
error: docs for function which may panic missing `# Panics` section
- --> $DIR/missing_panics_doc.rs:13:1
+ --> $DIR/missing_panics_doc.rs:12:1
|
LL | / pub fn panic() {
LL | | panic!("This function panics")
| |_^
|
note: first possible panic found here
- --> $DIR/missing_panics_doc.rs:14:5
+ --> $DIR/missing_panics_doc.rs:13:5
|
LL | panic!("This function panics")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
error: docs for function which may panic missing `# Panics` section
- --> $DIR/missing_panics_doc.rs:18:1
+ --> $DIR/missing_panics_doc.rs:17:1
|
LL | / pub fn todo() {
LL | | todo!()
| |_^
|
note: first possible panic found here
- --> $DIR/missing_panics_doc.rs:19:5
+ --> $DIR/missing_panics_doc.rs:18:5
|
LL | todo!()
| ^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
error: docs for function which may panic missing `# Panics` section
- --> $DIR/missing_panics_doc.rs:23:1
+ --> $DIR/missing_panics_doc.rs:22:1
|
LL | / pub fn inner_body(opt: Option<u32>) {
LL | | opt.map(|x| {
| |_^
|
note: first possible panic found here
- --> $DIR/missing_panics_doc.rs:26:13
+ --> $DIR/missing_panics_doc.rs:25:13
|
LL | panic!()
| ^^^^^^^^
- = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
error: docs for function which may panic missing `# Panics` section
- --> $DIR/missing_panics_doc.rs:32:1
+ --> $DIR/missing_panics_doc.rs:31:1
|
LL | / pub fn unreachable_and_panic() {
LL | | if true { unreachable!() } else { panic!() }
| |_^
|
note: first possible panic found here
- --> $DIR/missing_panics_doc.rs:33:39
+ --> $DIR/missing_panics_doc.rs:32:39
|
LL | if true { unreachable!() } else { panic!() }
| ^^^^^^^^
- = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
error: docs for function which may panic missing `# Panics` section
- --> $DIR/missing_panics_doc.rs:37:1
+ --> $DIR/missing_panics_doc.rs:36:1
|
LL | / pub fn assert_eq() {
LL | | let x = 0;
| |_^
|
note: first possible panic found here
- --> $DIR/missing_panics_doc.rs:39:5
+ --> $DIR/missing_panics_doc.rs:38:5
|
LL | assert_eq!(x, 0);
| ^^^^^^^^^^^^^^^^
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: docs for function which may panic missing `# Panics` section
- --> $DIR/missing_panics_doc.rs:43:1
+ --> $DIR/missing_panics_doc.rs:42:1
|
LL | / pub fn assert_ne() {
LL | | let x = 0;
| |_^
|
note: first possible panic found here
- --> $DIR/missing_panics_doc.rs:45:5
+ --> $DIR/missing_panics_doc.rs:44:5
|
LL | assert_ne!(x, 0);
| ^^^^^^^^^^^^^^^^
-// edition:2018
// FIXME: run-rustfix waiting on multi-span suggestions
#![warn(clippy::needless_borrow)]
error: this pattern creates a reference to a reference
- --> $DIR/needless_borrow_pat.rs:60:14
+ --> $DIR/needless_borrow_pat.rs:59:14
|
LL | Some(ref x) => x,
| ^^^^^ help: try this: `x`
= note: `-D clippy::needless-borrow` implied by `-D warnings`
error: this pattern creates a reference to a reference
- --> $DIR/needless_borrow_pat.rs:66:14
+ --> $DIR/needless_borrow_pat.rs:65:14
|
LL | Some(ref x) => *x,
| ^^^^^
| ~ ~
error: this pattern creates a reference to a reference
- --> $DIR/needless_borrow_pat.rs:72:14
+ --> $DIR/needless_borrow_pat.rs:71:14
|
LL | Some(ref x) => {
| ^^^^^
|
error: this pattern creates a reference to a reference
- --> $DIR/needless_borrow_pat.rs:82:14
+ --> $DIR/needless_borrow_pat.rs:81:14
|
LL | Some(ref x) => m1!(x),
| ^^^^^ help: try this: `x`
error: this pattern creates a reference to a reference
- --> $DIR/needless_borrow_pat.rs:87:15
+ --> $DIR/needless_borrow_pat.rs:86:15
|
LL | let _ = |&ref x: &&String| {
| ^^^^^ help: try this: `x`
error: this pattern creates a reference to a reference
- --> $DIR/needless_borrow_pat.rs:92:10
+ --> $DIR/needless_borrow_pat.rs:91:10
|
LL | let (ref y,) = (&x,);
| ^^^^^
|
error: this pattern creates a reference to a reference
- --> $DIR/needless_borrow_pat.rs:102:14
+ --> $DIR/needless_borrow_pat.rs:101:14
|
LL | Some(ref x) => x.0,
| ^^^^^ help: try this: `x`
error: this pattern creates a reference to a reference
- --> $DIR/needless_borrow_pat.rs:112:14
+ --> $DIR/needless_borrow_pat.rs:111:14
|
LL | E::A(ref x) | E::B(ref x) => *x,
| ^^^^^ ^^^^^
| ~ ~ ~
error: this pattern creates a reference to a reference
- --> $DIR/needless_borrow_pat.rs:118:21
+ --> $DIR/needless_borrow_pat.rs:117:21
|
LL | if let Some(ref x) = Some(&String::new());
| ^^^^^ help: try this: `x`
error: this pattern creates a reference to a reference
- --> $DIR/needless_borrow_pat.rs:126:12
+ --> $DIR/needless_borrow_pat.rs:125:12
|
LL | fn f2<'a>(&ref x: &&'a String) -> &'a String {
| ^^^^^
|
error: this pattern creates a reference to a reference
- --> $DIR/needless_borrow_pat.rs:133:11
+ --> $DIR/needless_borrow_pat.rs:132:11
|
LL | fn f(&ref x: &&String) {
| ^^^^^ help: try this: `x`
error: this pattern creates a reference to a reference
- --> $DIR/needless_borrow_pat.rs:141:11
+ --> $DIR/needless_borrow_pat.rs:140:11
|
LL | fn f(&ref x: &&String) {
| ^^^^^
x
}
+// No error; multiple input refs
+async fn func<'a>(args: &[&'a str]) -> Option<&'a str> {
+ args.get(0).cloned()
+}
+
// No error; static involved.
fn in_static_and_out<'a>(x: &'a u8, _y: &'static u8) -> &'a u8 {
x
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:45:1
+ --> $DIR/needless_lifetimes.rs:50:1
|
LL | fn deep_reference_3<'a>(x: &'a u8, _y: u8) -> Result<&'a u8, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:50:1
+ --> $DIR/needless_lifetimes.rs:55:1
|
LL | fn where_clause_without_lt<'a, T>(x: &'a u8, _y: u8) -> Result<&'a u8, ()>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:62:1
+ --> $DIR/needless_lifetimes.rs:67:1
|
LL | fn lifetime_param_2<'a, 'b>(_x: Ref<'a>, _y: &'b u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:86:1
+ --> $DIR/needless_lifetimes.rs:91:1
|
LL | fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:116:5
+ --> $DIR/needless_lifetimes.rs:121:5
|
LL | fn self_and_out<'s>(&'s self) -> &'s u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:125:5
+ --> $DIR/needless_lifetimes.rs:130:5
|
LL | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:144:1
+ --> $DIR/needless_lifetimes.rs:149:1
|
LL | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:174:1
+ --> $DIR/needless_lifetimes.rs:179:1
|
LL | fn trait_obj_elided2<'a>(_arg: &'a dyn Drop) -> &'a str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:180:1
+ --> $DIR/needless_lifetimes.rs:185:1
|
LL | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:199:1
+ --> $DIR/needless_lifetimes.rs:204:1
|
LL | fn named_input_elided_output<'a>(_arg: &'a str) -> &str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:207:1
+ --> $DIR/needless_lifetimes.rs:212:1
|
LL | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:243:1
+ --> $DIR/needless_lifetimes.rs:248:1
|
LL | fn out_return_type_lts<'a>(e: &'a str) -> Cow<'a> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:250:9
+ --> $DIR/needless_lifetimes.rs:255:9
|
LL | fn needless_lt<'a>(x: &'a u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:254:9
+ --> $DIR/needless_lifetimes.rs:259:9
|
LL | fn needless_lt<'a>(_x: &'a u8) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:267:9
+ --> $DIR/needless_lifetimes.rs:272:9
|
LL | fn baz<'a>(&'a self) -> impl Foo + 'a {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:296:5
+ --> $DIR/needless_lifetimes.rs:301:5
|
LL | fn impl_trait_elidable_nested_named_lifetimes<'a>(i: &'a i32, f: impl for<'b> Fn(&'b i32) -> &'b i32) -> &'a i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:299:5
+ --> $DIR/needless_lifetimes.rs:304:5
|
LL | fn impl_trait_elidable_nested_anonymous_lifetimes<'a>(i: &'a i32, f: impl Fn(&i32) -> &i32) -> &'a i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:308:5
+ --> $DIR/needless_lifetimes.rs:313:5
|
LL | fn generics_elidable<'a, T: Fn(&i32) -> &i32>(i: &'a i32, f: T) -> &'a i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:320:5
+ --> $DIR/needless_lifetimes.rs:325:5
|
LL | fn where_clause_elidadable<'a, T>(i: &'a i32, f: T) -> &'a i32
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:335:5
+ --> $DIR/needless_lifetimes.rs:340:5
|
LL | fn pointer_fn_elidable<'a>(i: &'a i32, f: fn(&i32) -> &i32) -> &'a i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:348:5
+ --> $DIR/needless_lifetimes.rs:353:5
|
LL | fn nested_fn_pointer_3<'a>(_: &'a i32) -> fn(fn(&i32) -> &i32) -> i32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/needless_lifetimes.rs:351:5
+ --> $DIR/needless_lifetimes.rs:356:5
|
LL | fn nested_fn_pointer_4<'a>(_: &'a i32) -> impl Fn(fn(&i32)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// run-rustfix
-// edition:2018
#![feature(let_else)]
#![allow(unused)]
// run-rustfix
-// edition:2018
#![feature(let_else)]
#![allow(unused)]
error: unneeded `return` statement
- --> $DIR/needless_return.rs:25:5
+ --> $DIR/needless_return.rs:24:5
|
LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true`
= note: `-D clippy::needless-return` implied by `-D warnings`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:29:5
+ --> $DIR/needless_return.rs:28:5
|
LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:34:9
+ --> $DIR/needless_return.rs:33:9
|
LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:36:9
+ --> $DIR/needless_return.rs:35:9
|
LL | return false;
| ^^^^^^^^^^^^^ help: remove `return`: `false`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:42:17
+ --> $DIR/needless_return.rs:41:17
|
LL | true => return false,
| ^^^^^^^^^^^^ help: remove `return`: `false`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:44:13
+ --> $DIR/needless_return.rs:43:13
|
LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:51:9
+ --> $DIR/needless_return.rs:50:9
|
LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:53:16
+ --> $DIR/needless_return.rs:52:16
|
LL | let _ = || return true;
| ^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:61:5
+ --> $DIR/needless_return.rs:60:5
|
LL | return;
| ^^^^^^^ help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:66:9
+ --> $DIR/needless_return.rs:65:9
|
LL | return;
| ^^^^^^^ help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:68:9
+ --> $DIR/needless_return.rs:67:9
|
LL | return;
| ^^^^^^^ help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:75:14
+ --> $DIR/needless_return.rs:74:14
|
LL | _ => return,
| ^^^^^^ help: replace `return` with an empty block: `{}`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:90:9
+ --> $DIR/needless_return.rs:89:9
|
LL | return String::from("test");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:92:9
+ --> $DIR/needless_return.rs:91:9
|
LL | return String::new();
| ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:113:32
+ --> $DIR/needless_return.rs:112:32
|
LL | bar.unwrap_or_else(|_| return)
| ^^^^^^ help: replace `return` with an empty block: `{}`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:118:13
+ --> $DIR/needless_return.rs:117:13
|
LL | return;
| ^^^^^^^ help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:120:20
+ --> $DIR/needless_return.rs:119:20
|
LL | let _ = || return;
| ^^^^^^ help: replace `return` with an empty block: `{}`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:126:32
+ --> $DIR/needless_return.rs:125:32
|
LL | res.unwrap_or_else(|_| return Foo)
| ^^^^^^^^^^ help: remove `return`: `Foo`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:135:5
+ --> $DIR/needless_return.rs:134:5
|
LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:139:5
+ --> $DIR/needless_return.rs:138:5
|
LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:144:9
+ --> $DIR/needless_return.rs:143:9
|
LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:146:9
+ --> $DIR/needless_return.rs:145:9
|
LL | return false;
| ^^^^^^^^^^^^^ help: remove `return`: `false`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:152:17
+ --> $DIR/needless_return.rs:151:17
|
LL | true => return false,
| ^^^^^^^^^^^^ help: remove `return`: `false`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:154:13
+ --> $DIR/needless_return.rs:153:13
|
LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:161:9
+ --> $DIR/needless_return.rs:160:9
|
LL | return true;
| ^^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:163:16
+ --> $DIR/needless_return.rs:162:16
|
LL | let _ = || return true;
| ^^^^^^^^^^^ help: remove `return`: `true`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:171:5
+ --> $DIR/needless_return.rs:170:5
|
LL | return;
| ^^^^^^^ help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:176:9
+ --> $DIR/needless_return.rs:175:9
|
LL | return;
| ^^^^^^^ help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:178:9
+ --> $DIR/needless_return.rs:177:9
|
LL | return;
| ^^^^^^^ help: remove `return`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:185:14
+ --> $DIR/needless_return.rs:184:14
|
LL | _ => return,
| ^^^^^^ help: replace `return` with an empty block: `{}`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:200:9
+ --> $DIR/needless_return.rs:199:9
|
LL | return String::from("test");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
error: unneeded `return` statement
- --> $DIR/needless_return.rs:202:9
+ --> $DIR/needless_return.rs:201:9
|
LL | return String::new();
| ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
impl MaybeInst {
fn fill(&mut self) {
let filled = match *self {
- MaybeInst::Split1(goto1) => panic!(1),
- MaybeInst::Split2(goto2) => panic!(2),
+ MaybeInst::Split1(goto1) => panic!("1"),
+ MaybeInst::Split2(goto2) => panic!("2"),
_ => unimplemented!(),
};
unimplemented!()
-// edition:2018
// run-rustfix
#![warn(clippy::option_if_let_else)]
#![allow(clippy::redundant_closure, clippy::ref_option_ref, clippy::equatable_if_let)]
-// edition:2018
// run-rustfix
#![warn(clippy::option_if_let_else)]
#![allow(clippy::redundant_closure, clippy::ref_option_ref, clippy::equatable_if_let)]
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:7:5
+ --> $DIR/option_if_let_else.rs:6:5
|
LL | / if let Some(x) = string {
LL | | (true, x)
= note: `-D clippy::option-if-let-else` implied by `-D warnings`
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:25:13
+ --> $DIR/option_if_let_else.rs:24:13
|
LL | let _ = if let Some(s) = *string { s.len() } else { 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())`
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:26:13
+ --> $DIR/option_if_let_else.rs:25:13
|
LL | let _ = if let Some(s) = &num { s } else { &0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:27:13
+ --> $DIR/option_if_let_else.rs:26:13
|
LL | let _ = if let Some(s) = &mut num {
| _____________^
|
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:33:13
+ --> $DIR/option_if_let_else.rs:32:13
|
LL | let _ = if let Some(ref s) = num { s } else { &0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:34:13
+ --> $DIR/option_if_let_else.rs:33:13
|
LL | let _ = if let Some(mut s) = num {
| _____________^
|
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:40:13
+ --> $DIR/option_if_let_else.rs:39:13
|
LL | let _ = if let Some(ref mut s) = num {
| _____________^
|
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:49:5
+ --> $DIR/option_if_let_else.rs:48:5
|
LL | / if let Some(x) = arg {
LL | | let y = x * x;
|
error: use Option::map_or_else instead of an if let/else
- --> $DIR/option_if_let_else.rs:62:13
+ --> $DIR/option_if_let_else.rs:61:13
|
LL | let _ = if let Some(x) = arg {
| _____________^
| |_____^ help: try: `arg.map_or_else(|| side_effect(), |x| x)`
error: use Option::map_or_else instead of an if let/else
- --> $DIR/option_if_let_else.rs:71:13
+ --> $DIR/option_if_let_else.rs:70:13
|
LL | let _ = if let Some(x) = arg {
| _____________^
|
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:100:13
+ --> $DIR/option_if_let_else.rs:99:13
|
LL | let _ = if let Some(x) = optional { x + 2 } else { 5 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:109:13
+ --> $DIR/option_if_let_else.rs:108:13
|
LL | let _ = if let Some(x) = Some(0) {
| _____________^
|
error: use Option::map_or_else instead of an if let/else
- --> $DIR/option_if_let_else.rs:137:13
+ --> $DIR/option_if_let_else.rs:136:13
|
LL | let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or_else(|| s.len(), |x| s.len() + x)`
error: use Option::map_or instead of an if let/else
- --> $DIR/option_if_let_else.rs:141:13
+ --> $DIR/option_if_let_else.rs:140:13
|
LL | let _ = if let Some(x) = Some(0) {
| _____________^
#![warn(clippy::panic_in_result_fn)]
#![allow(clippy::unnecessary_wraps)]
-
struct A;
impl A {
error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
- --> $DIR/panic_in_result_fn.rs:7:5
+ --> $DIR/panic_in_result_fn.rs:6:5
|
LL | / fn result_with_panic() -> Result<bool, String> // should emit lint
LL | | {
= note: `-D clippy::panic-in-result-fn` implied by `-D warnings`
= help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
note: return Err() instead of panicking
- --> $DIR/panic_in_result_fn.rs:9:9
+ --> $DIR/panic_in_result_fn.rs:8:9
|
LL | panic!("error");
| ^^^^^^^^^^^^^^^
- = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
- --> $DIR/panic_in_result_fn.rs:12:5
+ --> $DIR/panic_in_result_fn.rs:11:5
|
LL | / fn result_with_unimplemented() -> Result<bool, String> // should emit lint
LL | | {
|
= help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
note: return Err() instead of panicking
- --> $DIR/panic_in_result_fn.rs:14:9
+ --> $DIR/panic_in_result_fn.rs:13:9
|
LL | unimplemented!();
| ^^^^^^^^^^^^^^^^
= note: this error originates in the macro `unimplemented` (in Nightly builds, run with -Z macro-backtrace for more info)
error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
- --> $DIR/panic_in_result_fn.rs:17:5
+ --> $DIR/panic_in_result_fn.rs:16:5
|
LL | / fn result_with_unreachable() -> Result<bool, String> // should emit lint
LL | | {
|
= help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
note: return Err() instead of panicking
- --> $DIR/panic_in_result_fn.rs:19:9
+ --> $DIR/panic_in_result_fn.rs:18:9
|
LL | unreachable!();
| ^^^^^^^^^^^^^^
= note: this error originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info)
error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
- --> $DIR/panic_in_result_fn.rs:22:5
+ --> $DIR/panic_in_result_fn.rs:21:5
|
LL | / fn result_with_todo() -> Result<bool, String> // should emit lint
LL | | {
|
= help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
note: return Err() instead of panicking
- --> $DIR/panic_in_result_fn.rs:24:9
+ --> $DIR/panic_in_result_fn.rs:23:9
|
LL | todo!("Finish this");
| ^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `todo` (in Nightly builds, run with -Z macro-backtrace for more info)
error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
- --> $DIR/panic_in_result_fn.rs:53:1
+ --> $DIR/panic_in_result_fn.rs:52:1
|
LL | / fn function_result_with_panic() -> Result<bool, String> // should emit lint
LL | | {
|
= help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
note: return Err() instead of panicking
- --> $DIR/panic_in_result_fn.rs:55:5
+ --> $DIR/panic_in_result_fn.rs:54:5
|
LL | panic!("error");
| ^^^^^^^^^^^^^^^
- = note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the macro `$crate::panic::panic_2021` (in Nightly builds, run with -Z macro-backtrace for more info)
error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
- --> $DIR/panic_in_result_fn.rs:68:1
+ --> $DIR/panic_in_result_fn.rs:67:1
|
LL | / fn main() -> Result<(), String> {
LL | | todo!("finish main method");
|
= help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
note: return Err() instead of panicking
- --> $DIR/panic_in_result_fn.rs:69:5
+ --> $DIR/panic_in_result_fn.rs:68:5
|
LL | todo!("finish main method");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#![allow(
- unused,
- clippy::many_single_char_names,
- clippy::redundant_clone,
- clippy::if_then_panic
-)]
+#![allow(unused, clippy::many_single_char_names, clippy::redundant_clone)]
#![warn(clippy::ptr_arg)]
use std::borrow::Cow;
let _ = str.clone().clone();
}
}
+
+// No error for types behind an alias (#7699)
+type A = Vec<u8>;
+fn aliased(a: &A) {}
error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
- --> $DIR/ptr_arg.rs:12:14
+ --> $DIR/ptr_arg.rs:7:14
|
LL | fn do_vec(x: &Vec<i64>) {
| ^^^^^^^^^ help: change this to: `&[i64]`
= note: `-D clippy::ptr-arg` implied by `-D warnings`
error: writing `&String` instead of `&str` involves a new object where a slice will do
- --> $DIR/ptr_arg.rs:21:14
+ --> $DIR/ptr_arg.rs:16:14
|
LL | fn do_str(x: &String) {
| ^^^^^^^ help: change this to: `&str`
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
- --> $DIR/ptr_arg.rs:30:15
+ --> $DIR/ptr_arg.rs:25:15
|
LL | fn do_path(x: &PathBuf) {
| ^^^^^^^^ help: change this to: `&Path`
error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
- --> $DIR/ptr_arg.rs:43:18
+ --> $DIR/ptr_arg.rs:38:18
|
LL | fn do_vec(x: &Vec<i64>);
| ^^^^^^^^^ help: change this to: `&[i64]`
error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
- --> $DIR/ptr_arg.rs:56:14
+ --> $DIR/ptr_arg.rs:51:14
|
LL | fn cloned(x: &Vec<u8>) -> Vec<u8> {
| ^^^^^^^^
|
error: writing `&String` instead of `&str` involves a new object where a slice will do
- --> $DIR/ptr_arg.rs:65:18
+ --> $DIR/ptr_arg.rs:60:18
|
LL | fn str_cloned(x: &String) -> String {
| ^^^^^^^
|
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
- --> $DIR/ptr_arg.rs:73:19
+ --> $DIR/ptr_arg.rs:68:19
|
LL | fn path_cloned(x: &PathBuf) -> PathBuf {
| ^^^^^^^^
|
error: writing `&String` instead of `&str` involves a new object where a slice will do
- --> $DIR/ptr_arg.rs:81:44
+ --> $DIR/ptr_arg.rs:76:44
|
LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) {
| ^^^^^^^
| ~
error: using a reference to `Cow` is not recommended
- --> $DIR/ptr_arg.rs:95:25
+ --> $DIR/ptr_arg.rs:90:25
|
LL | fn test_cow_with_ref(c: &Cow<[i32]>) {}
| ^^^^^^^^^^^ help: change this to: `&[i32]`
error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices
- --> $DIR/ptr_arg.rs:148:21
+ --> $DIR/ptr_arg.rs:143:21
|
LL | fn foo_vec(vec: &Vec<u8>) {
| ^^^^^^^^
| ~~~~~~~~~~~~~~
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
- --> $DIR/ptr_arg.rs:153:23
+ --> $DIR/ptr_arg.rs:148:23
|
LL | fn foo_path(path: &PathBuf) {
| ^^^^^^^^
| ~~~~~~~~~~~~~~~~~~
error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do
- --> $DIR/ptr_arg.rs:158:21
+ --> $DIR/ptr_arg.rs:153:21
|
LL | fn foo_str(str: &PathBuf) {
| ^^^^^^^^
Some(0)
}
-fn result_func(x: Result<i32, &str>) -> Result<i32, &str> {
+fn func_returning_result() -> Result<i32, i32> {
+ Ok(1)
+}
+
+fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
let _ = x?;
x?;
let y = if let Ok(x) = x {
x
} else {
- return Err("some error");
+ return Err(0);
+ };
+
+ // issue #7859
+ // no warning
+ let _ = if let Ok(x) = func_returning_result() {
+ x
+ } else {
+ return Err(0);
};
+ // no warning
+ if func_returning_result().is_err() {
+ return func_returning_result();
+ }
+
Ok(y)
}
Some(0)
}
-fn result_func(x: Result<i32, &str>) -> Result<i32, &str> {
+fn func_returning_result() -> Result<i32, i32> {
+ Ok(1)
+}
+
+fn result_func(x: Result<i32, i32>) -> Result<i32, i32> {
let _ = if let Ok(x) = x { x } else { return x };
if x.is_err() {
let y = if let Ok(x) = x {
x
} else {
- return Err("some error");
+ return Err(0);
+ };
+
+ // issue #7859
+ // no warning
+ let _ = if let Ok(x) = func_returning_result() {
+ x
+ } else {
+ return Err(0);
};
+ // no warning
+ if func_returning_result().is_err() {
+ return func_returning_result();
+ }
+
Ok(y)
}
| |_____^ help: replace it with: `f()?;`
error: this if-let-else may be rewritten with the `?` operator
- --> $DIR/question_mark.rs:138:13
+ --> $DIR/question_mark.rs:142:13
|
LL | let _ = if let Ok(x) = x { x } else { return x };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `x?`
error: this block may be rewritten with the `?` operator
- --> $DIR/question_mark.rs:140:5
+ --> $DIR/question_mark.rs:144:5
|
LL | / if x.is_err() {
LL | | return x;
fn foo<F: Fn()>(_: &Alpha, _: F) {}
let x = Alpha;
// ok, data is moved while the clone is in use.
- foo(&x.clone(), move || {
+ foo(&x, move || {
let _ = x;
});
LL | let y = x.clone().join("matthias");
| ^^^^^^^^^
-error: aborting due to 14 previous errors
+error: redundant clone
+ --> $DIR/redundant_clone.rs:199:11
+ |
+LL | foo(&x.clone(), move || {
+ | ^^^^^^^^ help: remove this
+ |
+note: this value is dropped without further use
+ --> $DIR/redundant_clone.rs:199:10
+ |
+LL | foo(&x.clone(), move || {
+ | ^
+
+error: aborting due to 15 previous errors
-// edition:2018
// FIXME: run-rustfix waiting on multi-span suggestions
#![warn(clippy::ref_binding_to_reference)]
error: this pattern creates a reference to a reference
- --> $DIR/ref_binding_to_reference.rs:31:14
+ --> $DIR/ref_binding_to_reference.rs:30:14
|
LL | Some(ref x) => x,
| ^^^^^
| ~ ~~
error: this pattern creates a reference to a reference
- --> $DIR/ref_binding_to_reference.rs:37:14
+ --> $DIR/ref_binding_to_reference.rs:36:14
|
LL | Some(ref x) => {
| ^^^^^
|
error: this pattern creates a reference to a reference
- --> $DIR/ref_binding_to_reference.rs:47:14
+ --> $DIR/ref_binding_to_reference.rs:46:14
|
LL | Some(ref x) => m2!(x),
| ^^^^^
| ~ ~~
error: this pattern creates a reference to a reference
- --> $DIR/ref_binding_to_reference.rs:52:15
+ --> $DIR/ref_binding_to_reference.rs:51:15
|
LL | let _ = |&ref x: &&String| {
| ^^^^^
|
error: this pattern creates a reference to a reference
- --> $DIR/ref_binding_to_reference.rs:58:12
+ --> $DIR/ref_binding_to_reference.rs:57:12
|
LL | fn f2<'a>(&ref x: &&'a String) -> &'a String {
| ^^^^^
|
error: this pattern creates a reference to a reference
- --> $DIR/ref_binding_to_reference.rs:65:11
+ --> $DIR/ref_binding_to_reference.rs:64:11
|
LL | fn f(&ref x: &&String) {
| ^^^^^
|
error: this pattern creates a reference to a reference
- --> $DIR/ref_binding_to_reference.rs:73:11
+ --> $DIR/ref_binding_to_reference.rs:72:11
|
LL | fn f(&ref x: &&String) {
| ^^^^^
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::new_without_default)]
#![allow(clippy::redundant_static_lifetimes)]
+#![allow(clippy::bind_instead_of_map)]
+#![allow(clippy::box_collection)]
+#![allow(clippy::blocks_in_if_conditions)]
+#![allow(clippy::map_unwrap_or)]
+#![allow(clippy::unwrap_used)]
+#![allow(clippy::expect_used)]
+#![allow(clippy::for_loops_over_fallibles)]
+#![allow(clippy::useless_conversion)]
+#![allow(clippy::invisible_characters)]
+#![allow(clippy::single_char_add_str)]
+#![allow(clippy::match_result_ok)]
+// uplifted lints
+#![allow(invalid_value)]
+#![allow(array_into_iter)]
+#![allow(unused_labels)]
+#![allow(drop_bounds)]
+#![allow(temporary_cstring_as_ptr)]
+#![allow(non_fmt_panics)]
+#![allow(unknown_lints)]
+#![allow(invalid_atomic_ordering)]
+#![allow(enum_intrinsics_non_enums)]
// warn for the old lint name here, to test if the renaming worked
+#![warn(clippy::module_name_repetitions)]
+#![warn(clippy::new_without_default)]
+#![warn(clippy::redundant_static_lifetimes)]
#![warn(clippy::cognitive_complexity)]
+#![warn(clippy::bind_instead_of_map)]
+#![warn(clippy::box_collection)]
+#![warn(clippy::blocks_in_if_conditions)]
+#![warn(clippy::blocks_in_if_conditions)]
+#![warn(clippy::map_unwrap_or)]
+#![warn(clippy::map_unwrap_or)]
+#![warn(clippy::map_unwrap_or)]
+#![warn(clippy::unwrap_used)]
+#![warn(clippy::unwrap_used)]
+#![warn(clippy::expect_used)]
+#![warn(clippy::expect_used)]
+#![warn(clippy::for_loops_over_fallibles)]
+#![warn(clippy::for_loops_over_fallibles)]
+#![warn(clippy::useless_conversion)]
+#![warn(clippy::invisible_characters)]
+#![warn(clippy::single_char_add_str)]
+#![warn(clippy::match_result_ok)]
+// uplifted lints
+#![warn(invalid_value)]
+#![warn(array_into_iter)]
+#![warn(unused_labels)]
+#![warn(drop_bounds)]
+#![warn(temporary_cstring_as_ptr)]
+#![warn(non_fmt_panics)]
+#![warn(unknown_lints)]
+#![warn(invalid_atomic_ordering)]
#![warn(enum_intrinsics_non_enums)]
-#[warn(clippy::module_name_repetitions)]
fn main() {}
-
-#[warn(clippy::new_without_default)]
-struct Foo;
-
-#[warn(clippy::redundant_static_lifetimes)]
-fn foo() {}
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::new_without_default)]
#![allow(clippy::redundant_static_lifetimes)]
+#![allow(clippy::bind_instead_of_map)]
+#![allow(clippy::box_collection)]
+#![allow(clippy::blocks_in_if_conditions)]
+#![allow(clippy::map_unwrap_or)]
+#![allow(clippy::unwrap_used)]
+#![allow(clippy::expect_used)]
+#![allow(clippy::for_loops_over_fallibles)]
+#![allow(clippy::useless_conversion)]
+#![allow(clippy::invisible_characters)]
+#![allow(clippy::single_char_add_str)]
+#![allow(clippy::match_result_ok)]
+// uplifted lints
+#![allow(invalid_value)]
+#![allow(array_into_iter)]
+#![allow(unused_labels)]
+#![allow(drop_bounds)]
+#![allow(temporary_cstring_as_ptr)]
+#![allow(non_fmt_panics)]
+#![allow(unknown_lints)]
+#![allow(invalid_atomic_ordering)]
+#![allow(enum_intrinsics_non_enums)]
// warn for the old lint name here, to test if the renaming worked
+#![warn(clippy::stutter)]
+#![warn(clippy::new_without_default_derive)]
+#![warn(clippy::const_static_lifetime)]
#![warn(clippy::cyclomatic_complexity)]
+#![warn(clippy::option_and_then_some)]
+#![warn(clippy::box_vec)]
+#![warn(clippy::block_in_if_condition_expr)]
+#![warn(clippy::block_in_if_condition_stmt)]
+#![warn(clippy::option_map_unwrap_or)]
+#![warn(clippy::option_map_unwrap_or_else)]
+#![warn(clippy::result_map_unwrap_or_else)]
+#![warn(clippy::option_unwrap_used)]
+#![warn(clippy::result_unwrap_used)]
+#![warn(clippy::option_expect_used)]
+#![warn(clippy::result_expect_used)]
+#![warn(clippy::for_loop_over_option)]
+#![warn(clippy::for_loop_over_result)]
+#![warn(clippy::identity_conversion)]
+#![warn(clippy::zero_width_space)]
+#![warn(clippy::single_char_push_str)]
+#![warn(clippy::if_let_some_result)]
+// uplifted lints
+#![warn(clippy::invalid_ref)]
+#![warn(clippy::into_iter_on_array)]
+#![warn(clippy::unused_label)]
+#![warn(clippy::drop_bounds)]
+#![warn(clippy::temporary_cstring_as_ptr)]
+#![warn(clippy::panic_params)]
+#![warn(clippy::unknown_clippy_lints)]
+#![warn(clippy::invalid_atomic_ordering)]
#![warn(clippy::mem_discriminant_non_enum)]
-#[warn(clippy::stutter)]
fn main() {}
-
-#[warn(clippy::new_without_default_derive)]
-struct Foo;
-
-#[warn(clippy::const_static_lifetime)]
-fn foo() {}
+error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
+ --> $DIR/rename.rs:31:9
+ |
+LL | #![warn(clippy::stutter)]
+ | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
+ |
+ = note: `-D renamed-and-removed-lints` implied by `-D warnings`
+
+error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
+ --> $DIR/rename.rs:32:9
+ |
+LL | #![warn(clippy::new_without_default_derive)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
+
+error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
+ --> $DIR/rename.rs:33:9
+ |
+LL | #![warn(clippy::const_static_lifetime)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
+
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
- --> $DIR/rename.rs:10:9
+ --> $DIR/rename.rs:34:9
|
LL | #![warn(clippy::cyclomatic_complexity)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
+
+error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
+ --> $DIR/rename.rs:35:9
|
- = note: `-D renamed-and-removed-lints` implied by `-D warnings`
+LL | #![warn(clippy::option_and_then_some)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
-error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
- --> $DIR/rename.rs:11:9
+error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
+ --> $DIR/rename.rs:36:9
|
-LL | #![warn(clippy::mem_discriminant_non_enum)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
+LL | #![warn(clippy::box_vec)]
+ | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
-error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
- --> $DIR/rename.rs:13:8
+error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
+ --> $DIR/rename.rs:37:9
|
-LL | #[warn(clippy::stutter)]
- | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
+LL | #![warn(clippy::block_in_if_condition_expr)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
-error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
- --> $DIR/rename.rs:16:8
+error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
+ --> $DIR/rename.rs:38:9
|
-LL | #[warn(clippy::new_without_default_derive)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
+LL | #![warn(clippy::block_in_if_condition_stmt)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
-error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
- --> $DIR/rename.rs:19:8
+error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
+ --> $DIR/rename.rs:39:9
+ |
+LL | #![warn(clippy::option_map_unwrap_or)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
+
+error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
+ --> $DIR/rename.rs:40:9
+ |
+LL | #![warn(clippy::option_map_unwrap_or_else)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
+
+error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
+ --> $DIR/rename.rs:41:9
+ |
+LL | #![warn(clippy::result_map_unwrap_or_else)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
+
+error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
+ --> $DIR/rename.rs:42:9
+ |
+LL | #![warn(clippy::option_unwrap_used)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
+
+error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
+ --> $DIR/rename.rs:43:9
+ |
+LL | #![warn(clippy::result_unwrap_used)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
+
+error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
+ --> $DIR/rename.rs:44:9
+ |
+LL | #![warn(clippy::option_expect_used)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
+
+error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
+ --> $DIR/rename.rs:45:9
+ |
+LL | #![warn(clippy::result_expect_used)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
+
+error: lint `clippy::for_loop_over_option` has been renamed to `clippy::for_loops_over_fallibles`
+ --> $DIR/rename.rs:46:9
+ |
+LL | #![warn(clippy::for_loop_over_option)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles`
+
+error: lint `clippy::for_loop_over_result` has been renamed to `clippy::for_loops_over_fallibles`
+ --> $DIR/rename.rs:47:9
+ |
+LL | #![warn(clippy::for_loop_over_result)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles`
+
+error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
+ --> $DIR/rename.rs:48:9
+ |
+LL | #![warn(clippy::identity_conversion)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
+
+error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
+ --> $DIR/rename.rs:49:9
+ |
+LL | #![warn(clippy::zero_width_space)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
+
+error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
+ --> $DIR/rename.rs:50:9
+ |
+LL | #![warn(clippy::single_char_push_str)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
+
+error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
+ --> $DIR/rename.rs:51:9
+ |
+LL | #![warn(clippy::if_let_some_result)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
+
+error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
+ --> $DIR/rename.rs:53:9
+ |
+LL | #![warn(clippy::invalid_ref)]
+ | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
+
+error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
+ --> $DIR/rename.rs:54:9
+ |
+LL | #![warn(clippy::into_iter_on_array)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
+
+error: lint `clippy::unused_label` has been renamed to `unused_labels`
+ --> $DIR/rename.rs:55:9
+ |
+LL | #![warn(clippy::unused_label)]
+ | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
+
+error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
+ --> $DIR/rename.rs:56:9
+ |
+LL | #![warn(clippy::drop_bounds)]
+ | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
+
+error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
+ --> $DIR/rename.rs:57:9
+ |
+LL | #![warn(clippy::temporary_cstring_as_ptr)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
+
+error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
+ --> $DIR/rename.rs:58:9
+ |
+LL | #![warn(clippy::panic_params)]
+ | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
+
+error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
+ --> $DIR/rename.rs:59:9
+ |
+LL | #![warn(clippy::unknown_clippy_lints)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
+
+error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
+ --> $DIR/rename.rs:60:9
+ |
+LL | #![warn(clippy::invalid_atomic_ordering)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
+
+error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
+ --> $DIR/rename.rs:61:9
|
-LL | #[warn(clippy::const_static_lifetime)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
+LL | #![warn(clippy::mem_discriminant_non_enum)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
-error: aborting due to 5 previous errors
+error: aborting due to 30 previous errors
-// edition:2018
-
#![warn(clippy::all, clippy::pedantic)]
#![allow(
clippy::missing_errors_doc,
-// edition:2018
-
#![warn(clippy::all, clippy::pedantic)]
#![allow(
clippy::missing_errors_doc,
error: method `add` can be confused for the standard trait method `std::ops::Add::add`
- --> $DIR/method_list_1.rs:26:5
+ --> $DIR/method_list_1.rs:24:5
|
LL | / pub fn add(self, other: T) -> T {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::Add` or choosing a less ambiguous method name
error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut`
- --> $DIR/method_list_1.rs:30:5
+ --> $DIR/method_list_1.rs:28:5
|
LL | / pub fn as_mut(&mut self) -> &mut T {
LL | | unimplemented!()
= help: consider implementing the trait `std::convert::AsMut` or choosing a less ambiguous method name
error: method `as_ref` can be confused for the standard trait method `std::convert::AsRef::as_ref`
- --> $DIR/method_list_1.rs:34:5
+ --> $DIR/method_list_1.rs:32:5
|
LL | / pub fn as_ref(&self) -> &T {
LL | | unimplemented!()
= help: consider implementing the trait `std::convert::AsRef` or choosing a less ambiguous method name
error: method `bitand` can be confused for the standard trait method `std::ops::BitAnd::bitand`
- --> $DIR/method_list_1.rs:38:5
+ --> $DIR/method_list_1.rs:36:5
|
LL | / pub fn bitand(self, rhs: T) -> T {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::BitAnd` or choosing a less ambiguous method name
error: method `bitor` can be confused for the standard trait method `std::ops::BitOr::bitor`
- --> $DIR/method_list_1.rs:42:5
+ --> $DIR/method_list_1.rs:40:5
|
LL | / pub fn bitor(self, rhs: Self) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::BitOr` or choosing a less ambiguous method name
error: method `bitxor` can be confused for the standard trait method `std::ops::BitXor::bitxor`
- --> $DIR/method_list_1.rs:46:5
+ --> $DIR/method_list_1.rs:44:5
|
LL | / pub fn bitxor(self, rhs: Self) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::BitXor` or choosing a less ambiguous method name
error: method `borrow` can be confused for the standard trait method `std::borrow::Borrow::borrow`
- --> $DIR/method_list_1.rs:50:5
+ --> $DIR/method_list_1.rs:48:5
|
LL | / pub fn borrow(&self) -> &str {
LL | | unimplemented!()
= help: consider implementing the trait `std::borrow::Borrow` or choosing a less ambiguous method name
error: method `borrow_mut` can be confused for the standard trait method `std::borrow::BorrowMut::borrow_mut`
- --> $DIR/method_list_1.rs:54:5
+ --> $DIR/method_list_1.rs:52:5
|
LL | / pub fn borrow_mut(&mut self) -> &mut str {
LL | | unimplemented!()
= help: consider implementing the trait `std::borrow::BorrowMut` or choosing a less ambiguous method name
error: method `clone` can be confused for the standard trait method `std::clone::Clone::clone`
- --> $DIR/method_list_1.rs:58:5
+ --> $DIR/method_list_1.rs:56:5
|
LL | / pub fn clone(&self) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::clone::Clone` or choosing a less ambiguous method name
error: method `cmp` can be confused for the standard trait method `std::cmp::Ord::cmp`
- --> $DIR/method_list_1.rs:62:5
+ --> $DIR/method_list_1.rs:60:5
|
LL | / pub fn cmp(&self, other: &Self) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name
error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref`
- --> $DIR/method_list_1.rs:70:5
+ --> $DIR/method_list_1.rs:68:5
|
LL | / pub fn deref(&self) -> &Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::Deref` or choosing a less ambiguous method name
error: method `deref_mut` can be confused for the standard trait method `std::ops::DerefMut::deref_mut`
- --> $DIR/method_list_1.rs:74:5
+ --> $DIR/method_list_1.rs:72:5
|
LL | / pub fn deref_mut(&mut self) -> &mut Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::DerefMut` or choosing a less ambiguous method name
error: method `div` can be confused for the standard trait method `std::ops::Div::div`
- --> $DIR/method_list_1.rs:78:5
+ --> $DIR/method_list_1.rs:76:5
|
LL | / pub fn div(self, rhs: Self) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::Div` or choosing a less ambiguous method name
error: method `drop` can be confused for the standard trait method `std::ops::Drop::drop`
- --> $DIR/method_list_1.rs:82:5
+ --> $DIR/method_list_1.rs:80:5
|
LL | / pub fn drop(&mut self) {
LL | | unimplemented!()
-// edition:2018
-
#![warn(clippy::all, clippy::pedantic)]
#![allow(
clippy::missing_errors_doc,
error: method `eq` can be confused for the standard trait method `std::cmp::PartialEq::eq`
- --> $DIR/method_list_2.rs:27:5
+ --> $DIR/method_list_2.rs:25:5
|
LL | / pub fn eq(&self, other: &Self) -> bool {
LL | | unimplemented!()
= help: consider implementing the trait `std::cmp::PartialEq` or choosing a less ambiguous method name
error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter`
- --> $DIR/method_list_2.rs:31:5
+ --> $DIR/method_list_2.rs:29:5
|
LL | / pub fn from_iter<T>(iter: T) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::iter::FromIterator` or choosing a less ambiguous method name
error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
- --> $DIR/method_list_2.rs:35:5
+ --> $DIR/method_list_2.rs:33:5
|
LL | / pub fn from_str(s: &str) -> Result<Self, Self> {
LL | | unimplemented!()
= help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash`
- --> $DIR/method_list_2.rs:39:5
+ --> $DIR/method_list_2.rs:37:5
|
LL | / pub fn hash(&self, state: &mut T) {
LL | | unimplemented!()
= help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name
error: method `index` can be confused for the standard trait method `std::ops::Index::index`
- --> $DIR/method_list_2.rs:43:5
+ --> $DIR/method_list_2.rs:41:5
|
LL | / pub fn index(&self, index: usize) -> &Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name
error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut`
- --> $DIR/method_list_2.rs:47:5
+ --> $DIR/method_list_2.rs:45:5
|
LL | / pub fn index_mut(&mut self, index: usize) -> &mut Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name
error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter`
- --> $DIR/method_list_2.rs:51:5
+ --> $DIR/method_list_2.rs:49:5
|
LL | / pub fn into_iter(self) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name
error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul`
- --> $DIR/method_list_2.rs:55:5
+ --> $DIR/method_list_2.rs:53:5
|
LL | / pub fn mul(self, rhs: Self) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name
error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg`
- --> $DIR/method_list_2.rs:59:5
+ --> $DIR/method_list_2.rs:57:5
|
LL | / pub fn neg(self) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name
error: method `next` can be confused for the standard trait method `std::iter::Iterator::next`
- --> $DIR/method_list_2.rs:63:5
+ --> $DIR/method_list_2.rs:61:5
|
LL | / pub fn next(&mut self) -> Option<Self> {
LL | | unimplemented!()
= help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name
error: method `not` can be confused for the standard trait method `std::ops::Not::not`
- --> $DIR/method_list_2.rs:67:5
+ --> $DIR/method_list_2.rs:65:5
|
LL | / pub fn not(self) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name
error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem`
- --> $DIR/method_list_2.rs:71:5
+ --> $DIR/method_list_2.rs:69:5
|
LL | / pub fn rem(self, rhs: Self) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name
error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl`
- --> $DIR/method_list_2.rs:75:5
+ --> $DIR/method_list_2.rs:73:5
|
LL | / pub fn shl(self, rhs: Self) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name
error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr`
- --> $DIR/method_list_2.rs:79:5
+ --> $DIR/method_list_2.rs:77:5
|
LL | / pub fn shr(self, rhs: Self) -> Self {
LL | | unimplemented!()
= help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name
error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub`
- --> $DIR/method_list_2.rs:83:5
+ --> $DIR/method_list_2.rs:81:5
|
LL | / pub fn sub(self, rhs: Self) -> Self {
LL | | unimplemented!()
// run-rustfix
-// edition:2018
#![warn(clippy::single_component_path_imports)]
#![allow(unused_imports)]
// run-rustfix
-// edition:2018
#![warn(clippy::single_component_path_imports)]
#![allow(unused_imports)]
error: this import is redundant
- --> $DIR/single_component_path_imports.rs:24:5
+ --> $DIR/single_component_path_imports.rs:23:5
|
LL | use regex;
| ^^^^^^^^^^ help: remove it entirely
= note: `-D clippy::single-component-path-imports` implied by `-D warnings`
error: this import is redundant
- --> $DIR/single_component_path_imports.rs:6:1
+ --> $DIR/single_component_path_imports.rs:5:1
|
LL | use regex;
| ^^^^^^^^^^ help: remove it entirely
// run-rustfix
-// edition:2018
#![warn(clippy::single_component_path_imports)]
#![allow(unused_imports)]
// run-rustfix
-// edition:2018
#![warn(clippy::single_component_path_imports)]
#![allow(unused_imports)]
error: this import is redundant
- --> $DIR/single_component_path_imports_macro.rs:16:1
+ --> $DIR/single_component_path_imports_macro.rs:15:1
|
LL | use m2; // fail
| ^^^^^^^ help: remove it entirely
-// edition:2018
#![warn(clippy::single_component_path_imports)]
#![allow(unused_imports)]
error: this import is redundant
- --> $DIR/single_component_path_imports_nested_first.rs:14:10
+ --> $DIR/single_component_path_imports_nested_first.rs:13:10
|
LL | use {regex, serde};
| ^^^^^
= help: remove this import
error: this import is redundant
- --> $DIR/single_component_path_imports_nested_first.rs:14:17
+ --> $DIR/single_component_path_imports_nested_first.rs:13:17
|
LL | use {regex, serde};
| ^^^^^
= help: remove this import
error: this import is redundant
- --> $DIR/single_component_path_imports_nested_first.rs:5:1
+ --> $DIR/single_component_path_imports_nested_first.rs:4:1
|
LL | use regex;
| ^^^^^^^^^^ help: remove it entirely
-// edition:2018
#![warn(clippy::single_component_path_imports)]
#![allow(unused_imports)]
-// edition:2018
#![warn(clippy::single_component_path_imports)]
#![allow(unused_imports)]
--- /dev/null
+#[warn(clippy::string_slice)]
+#[allow(clippy::no_effect)]
+
+fn main() {
+ &"Ölkanne"[1..];
+ let m = "Mötörhead";
+ &m[2..5];
+ let s = String::from(m);
+ &s[0..2];
+}
--- /dev/null
+error: indexing into a string may panic if the index is within a UTF-8 character
+ --> $DIR/string_slice.rs:5:6
+ |
+LL | &"Ölkanne"[1..];
+ | ^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::string-slice` implied by `-D warnings`
+
+error: indexing into a string may panic if the index is within a UTF-8 character
+ --> $DIR/string_slice.rs:7:6
+ |
+LL | &m[2..5];
+ | ^^^^^^^
+
+error: indexing into a string may panic if the index is within a UTF-8 character
+ --> $DIR/string_slice.rs:9:6
+ |
+LL | &s[0..2];
+ | ^^^^^^^
+
+error: aborting due to 3 previous errors
+
--- /dev/null
+#![warn(clippy::unit_hash)]
+
+use std::collections::hash_map::DefaultHasher;
+use std::hash::Hash;
+
+enum Foo {
+ Empty,
+ WithValue(u8),
+}
+
+fn do_nothing() {}
+
+fn main() {
+ let mut state = DefaultHasher::new();
+ let my_enum = Foo::Empty;
+
+ match my_enum {
+ Foo::Empty => ().hash(&mut state),
+ Foo::WithValue(x) => x.hash(&mut state),
+ }
+
+ let res = ();
+ res.hash(&mut state);
+
+ #[allow(clippy::unit_arg)]
+ do_nothing().hash(&mut state);
+}
--- /dev/null
+error: this call to `hash` on the unit type will do nothing
+ --> $DIR/unit_hash.rs:18:23
+ |
+LL | Foo::Empty => ().hash(&mut state),
+ | ^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)`
+ |
+ = note: `-D clippy::unit-hash` implied by `-D warnings`
+ = note: the implementation of `Hash` for `()` is a no-op
+
+error: this call to `hash` on the unit type will do nothing
+ --> $DIR/unit_hash.rs:23:5
+ |
+LL | res.hash(&mut state);
+ | ^^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)`
+ |
+ = note: the implementation of `Hash` for `()` is a no-op
+
+error: this call to `hash` on the unit type will do nothing
+ --> $DIR/unit_hash.rs:26:5
+ |
+LL | do_nothing().hash(&mut state);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)`
+ |
+ = note: the implementation of `Hash` for `()` is a no-op
+
+error: aborting due to 3 previous errors
+
-// edition:2018
#![warn(clippy::unused_async)]
async fn foo() -> i32 {
error: unused `async` for function with no await statements
- --> $DIR/unused_async.rs:4:1
+ --> $DIR/unused_async.rs:3:1
|
LL | / async fn foo() -> i32 {
LL | | 4
// run-rustfix
-// edition:2018
// aux-build:proc_macro_derive.rs
#![warn(clippy::use_self)]
// run-rustfix
-// edition:2018
// aux-build:proc_macro_derive.rs
#![warn(clippy::use_self)]
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:23:21
+ --> $DIR/use_self.rs:22:21
|
LL | fn new() -> Foo {
| ^^^ help: use the applicable keyword: `Self`
= note: `-D clippy::use-self` implied by `-D warnings`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:24:13
+ --> $DIR/use_self.rs:23:13
|
LL | Foo {}
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:26:22
+ --> $DIR/use_self.rs:25:22
|
LL | fn test() -> Foo {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:27:13
+ --> $DIR/use_self.rs:26:13
|
LL | Foo::new()
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:32:25
+ --> $DIR/use_self.rs:31:25
|
LL | fn default() -> Foo {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:33:13
+ --> $DIR/use_self.rs:32:13
|
LL | Foo::new()
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:98:24
+ --> $DIR/use_self.rs:97:24
|
LL | fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:98:55
+ --> $DIR/use_self.rs:97:55
|
LL | fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:113:13
+ --> $DIR/use_self.rs:112:13
|
LL | TS(0)
| ^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:148:29
+ --> $DIR/use_self.rs:147:29
|
LL | fn bar() -> Bar {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:149:21
+ --> $DIR/use_self.rs:148:21
|
LL | Bar { foo: Foo {} }
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:160:21
+ --> $DIR/use_self.rs:159:21
|
LL | fn baz() -> Foo {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:161:13
+ --> $DIR/use_self.rs:160:13
|
LL | Foo {}
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:178:21
+ --> $DIR/use_self.rs:177:21
|
LL | let _ = Enum::B(42);
| ^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:179:21
+ --> $DIR/use_self.rs:178:21
|
LL | let _ = Enum::C { field: true };
| ^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:180:21
+ --> $DIR/use_self.rs:179:21
|
LL | let _ = Enum::A;
| ^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:222:13
+ --> $DIR/use_self.rs:221:13
|
LL | nested::A::fun_1();
| ^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:223:13
+ --> $DIR/use_self.rs:222:13
|
LL | nested::A::A;
| ^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:225:13
+ --> $DIR/use_self.rs:224:13
|
LL | nested::A {};
| ^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:244:13
+ --> $DIR/use_self.rs:243:13
|
LL | TestStruct::from_something()
| ^^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:258:25
+ --> $DIR/use_self.rs:257:25
|
LL | async fn g() -> S {
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:259:13
+ --> $DIR/use_self.rs:258:13
|
LL | S {}
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:263:16
+ --> $DIR/use_self.rs:262:16
|
LL | &p[S::A..S::B]
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:263:22
+ --> $DIR/use_self.rs:262:22
|
LL | &p[S::A..S::B]
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:286:29
+ --> $DIR/use_self.rs:285:29
|
LL | fn foo(value: T) -> Foo<T> {
| ^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:287:13
+ --> $DIR/use_self.rs:286:13
|
LL | Foo::<T> { value }
| ^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:459:13
+ --> $DIR/use_self.rs:458:13
|
LL | A::new::<submod::B>(submod::B {})
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:496:13
+ --> $DIR/use_self.rs:495:13
|
LL | S2::new()
| ^^ help: use the applicable keyword: `Self`
-// edition:2018
// aux-build:proc_macro_derive.rs
#![feature(rustc_private)]
error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
- --> $DIR/used_underscore_binding.rs:26:5
+ --> $DIR/used_underscore_binding.rs:25:5
|
LL | _foo + 1
| ^^^^
= note: `-D clippy::used-underscore-binding` implied by `-D warnings`
error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
- --> $DIR/used_underscore_binding.rs:31:20
+ --> $DIR/used_underscore_binding.rs:30:20
|
LL | println!("{}", _foo);
| ^^^^
error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
- --> $DIR/used_underscore_binding.rs:32:16
+ --> $DIR/used_underscore_binding.rs:31:16
|
LL | assert_eq!(_foo, _foo);
| ^^^^
error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
- --> $DIR/used_underscore_binding.rs:32:22
+ --> $DIR/used_underscore_binding.rs:31:22
|
LL | assert_eq!(_foo, _foo);
| ^^^^
error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
- --> $DIR/used_underscore_binding.rs:45:5
+ --> $DIR/used_underscore_binding.rs:44:5
|
LL | s._underscore_field += 1;
| ^^^^^^^^^^^^^^^^^^^
error: used binding `_i` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
- --> $DIR/used_underscore_binding.rs:100:16
+ --> $DIR/used_underscore_binding.rs:99:16
|
LL | uses_i(_i);
| ^^
+// edition:2015
// run-rustfix
// aux-build:wildcard_imports_helper.rs
+// the 2015 edition here is needed because edition 2018 changed the module system
+// (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint
+// no longer detects some of the cases starting with Rust 2018.
+// FIXME: We should likely add another edition 2021 test case for this lint
+
#![warn(clippy::wildcard_imports)]
-//#![allow(clippy::redundant_pub_crate)]
#![allow(unused)]
#![allow(clippy::unnecessary_wraps)]
#![warn(unused_imports)]
+// edition:2015
// run-rustfix
// aux-build:wildcard_imports_helper.rs
+// the 2015 edition here is needed because edition 2018 changed the module system
+// (see https://doc.rust-lang.org/edition-guide/rust-2018/path-changes.html) which means the lint
+// no longer detects some of the cases starting with Rust 2018.
+// FIXME: We should likely add another edition 2021 test case for this lint
+
#![warn(clippy::wildcard_imports)]
-//#![allow(clippy::redundant_pub_crate)]
#![allow(unused)]
#![allow(clippy::unnecessary_wraps)]
#![warn(unused_imports)]
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:12:5
+ --> $DIR/wildcard_imports.rs:17:5
|
LL | use crate::fn_mod::*;
| ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
= note: `-D clippy::wildcard-imports` implied by `-D warnings`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:13:5
+ --> $DIR/wildcard_imports.rs:18:5
|
LL | use crate::mod_mod::*;
| ^^^^^^^^^^^^^^^^^ help: try: `crate::mod_mod::inner_mod`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:14:5
+ --> $DIR/wildcard_imports.rs:19:5
|
LL | use crate::multi_fn_mod::*;
| ^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate::multi_fn_mod::{multi_bar, multi_foo, multi_inner_mod}`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:16:5
+ --> $DIR/wildcard_imports.rs:21:5
|
LL | use crate::struct_mod::*;
| ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::struct_mod::{A, inner_struct_mod}`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:20:5
+ --> $DIR/wildcard_imports.rs:25:5
|
LL | use wildcard_imports_helper::inner::inner_for_self_import::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::inner::inner_for_self_import::inner_extern_bar`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:21:5
+ --> $DIR/wildcard_imports.rs:26:5
|
LL | use wildcard_imports_helper::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:92:13
+ --> $DIR/wildcard_imports.rs:97:13
|
LL | use crate::fn_mod::*;
| ^^^^^^^^^^^^^^^^ help: try: `crate::fn_mod::foo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:98:75
+ --> $DIR/wildcard_imports.rs:103:75
|
LL | use wildcard_imports_helper::inner::inner_for_self_import::{self, *};
| ^ help: try: `inner_extern_foo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:99:13
+ --> $DIR/wildcard_imports.rs:104:13
|
LL | use wildcard_imports_helper::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternA, extern_foo}`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:110:20
+ --> $DIR/wildcard_imports.rs:115:20
|
LL | use self::{inner::*, inner2::*};
| ^^^^^^^^ help: try: `inner::inner_foo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:110:30
+ --> $DIR/wildcard_imports.rs:115:30
|
LL | use self::{inner::*, inner2::*};
| ^^^^^^^^^ help: try: `inner2::inner_bar`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:117:13
+ --> $DIR/wildcard_imports.rs:122:13
|
LL | use wildcard_imports_helper::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `wildcard_imports_helper::{ExternExportedEnum, ExternExportedStruct, extern_exported}`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:146:9
+ --> $DIR/wildcard_imports.rs:151:9
|
LL | use crate::in_fn_test::*;
| ^^^^^^^^^^^^^^^^^^^^ help: try: `crate::in_fn_test::{ExportedEnum, ExportedStruct, exported}`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:155:9
+ --> $DIR/wildcard_imports.rs:160:9
|
LL | use crate:: in_fn_test:: * ;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:156:9
+ --> $DIR/wildcard_imports.rs:161:9
|
LL | use crate:: fn_mod::
| _________^
| |_________^ help: try: `crate:: fn_mod::foo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:167:13
+ --> $DIR/wildcard_imports.rs:172:13
|
LL | use super::*;
| ^^^^^^^^ help: try: `super::foofoo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:202:17
+ --> $DIR/wildcard_imports.rs:207:17
|
LL | use super::*;
| ^^^^^^^^ help: try: `super::insidefoo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:210:13
+ --> $DIR/wildcard_imports.rs:215:13
|
LL | use super_imports::*;
| ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:219:17
+ --> $DIR/wildcard_imports.rs:224:17
|
LL | use super::super::*;
| ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:228:13
+ --> $DIR/wildcard_imports.rs:233:13
|
LL | use super::super::super_imports::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo`
error: usage of wildcard import
- --> $DIR/wildcard_imports.rs:236:13
+ --> $DIR/wildcard_imports.rs:241:13
|
LL | use super::*;
| ^^^^^^^^ help: try: `super::foofoo`
-// edition:2018
#![warn(clippy::wrong_self_convention)]
#![allow(dead_code)]
error: methods called `from_*` usually take no `self`
- --> $DIR/wrong_self_convention.rs:17:17
+ --> $DIR/wrong_self_convention.rs:16:17
|
LL | fn from_i32(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self`
- --> $DIR/wrong_self_convention.rs:23:21
+ --> $DIR/wrong_self_convention.rs:22:21
|
LL | pub fn from_i64(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
- --> $DIR/wrong_self_convention.rs:35:15
+ --> $DIR/wrong_self_convention.rs:34:15
|
LL | fn as_i32(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `into_*` usually take `self` by value
- --> $DIR/wrong_self_convention.rs:37:17
+ --> $DIR/wrong_self_convention.rs:36:17
|
LL | fn into_i32(&self) {}
| ^^^^^
= help: consider choosing a less ambiguous name
error: methods called `is_*` usually take `self` by reference or no `self`
- --> $DIR/wrong_self_convention.rs:39:15
+ --> $DIR/wrong_self_convention.rs:38:15
|
LL | fn is_i32(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
- --> $DIR/wrong_self_convention.rs:41:15
+ --> $DIR/wrong_self_convention.rs:40:15
|
LL | fn to_i32(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self`
- --> $DIR/wrong_self_convention.rs:43:17
+ --> $DIR/wrong_self_convention.rs:42:17
|
LL | fn from_i32(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
- --> $DIR/wrong_self_convention.rs:45:19
+ --> $DIR/wrong_self_convention.rs:44:19
|
LL | pub fn as_i64(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `into_*` usually take `self` by value
- --> $DIR/wrong_self_convention.rs:46:21
+ --> $DIR/wrong_self_convention.rs:45:21
|
LL | pub fn into_i64(&self) {}
| ^^^^^
= help: consider choosing a less ambiguous name
error: methods called `is_*` usually take `self` by reference or no `self`
- --> $DIR/wrong_self_convention.rs:47:19
+ --> $DIR/wrong_self_convention.rs:46:19
|
LL | pub fn is_i64(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
- --> $DIR/wrong_self_convention.rs:48:19
+ --> $DIR/wrong_self_convention.rs:47:19
|
LL | pub fn to_i64(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self`
- --> $DIR/wrong_self_convention.rs:49:21
+ --> $DIR/wrong_self_convention.rs:48:21
|
LL | pub fn from_i64(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
- --> $DIR/wrong_self_convention.rs:94:19
+ --> $DIR/wrong_self_convention.rs:93:19
|
LL | fn as_i32(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `into_*` usually take `self` by value
- --> $DIR/wrong_self_convention.rs:97:25
+ --> $DIR/wrong_self_convention.rs:96:25
|
LL | fn into_i32_ref(&self) {}
| ^^^^^
= help: consider choosing a less ambiguous name
error: methods called `is_*` usually take `self` by reference or no `self`
- --> $DIR/wrong_self_convention.rs:99:19
+ --> $DIR/wrong_self_convention.rs:98:19
|
LL | fn is_i32(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self`
- --> $DIR/wrong_self_convention.rs:103:21
+ --> $DIR/wrong_self_convention.rs:102:21
|
LL | fn from_i32(self) {}
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
- --> $DIR/wrong_self_convention.rs:118:19
+ --> $DIR/wrong_self_convention.rs:117:19
|
LL | fn as_i32(self);
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `into_*` usually take `self` by value
- --> $DIR/wrong_self_convention.rs:121:25
+ --> $DIR/wrong_self_convention.rs:120:25
|
LL | fn into_i32_ref(&self);
| ^^^^^
= help: consider choosing a less ambiguous name
error: methods called `is_*` usually take `self` by reference or no `self`
- --> $DIR/wrong_self_convention.rs:123:19
+ --> $DIR/wrong_self_convention.rs:122:19
|
LL | fn is_i32(self);
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self`
- --> $DIR/wrong_self_convention.rs:127:21
+ --> $DIR/wrong_self_convention.rs:126:21
|
LL | fn from_i32(self);
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `into_*` usually take `self` by value
- --> $DIR/wrong_self_convention.rs:145:25
+ --> $DIR/wrong_self_convention.rs:144:25
|
LL | fn into_i32_ref(&self);
| ^^^^^
= help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self`
- --> $DIR/wrong_self_convention.rs:151:21
+ --> $DIR/wrong_self_convention.rs:150:21
|
LL | fn from_i32(self);
| ^^^^
= help: consider choosing a less ambiguous name
error: methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value
- --> $DIR/wrong_self_convention.rs:175:22
+ --> $DIR/wrong_self_convention.rs:174:22
|
LL | fn to_u64_v2(&self) -> u64 {
| ^^^^^
= help: consider choosing a less ambiguous name
error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
- --> $DIR/wrong_self_convention.rs:184:19
+ --> $DIR/wrong_self_convention.rs:183:19
|
LL | fn to_u64(self) -> u64 {
| ^^^^
-// edition:2018
#![warn(clippy::wrong_self_convention)]
#![allow(dead_code)]
error: methods called `from_*` usually take no `self`
- --> $DIR/wrong_self_convention2.rs:55:29
+ --> $DIR/wrong_self_convention2.rs:54:29
|
LL | pub fn from_be_self(self) -> Self {
| ^^^^
= help: consider choosing a less ambiguous name
error: methods called `from_*` usually take no `self`
- --> $DIR/wrong_self_convention2.rs:64:25
+ --> $DIR/wrong_self_convention2.rs:63:25
|
LL | fn from_be_self(self) -> Self;
| ^^^^
-// edition:2018
#![warn(clippy::wrong_self_convention)]
#![allow(dead_code)]
error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
- --> $DIR/wrong_self_conventions_mut.rs:15:24
+ --> $DIR/wrong_self_conventions_mut.rs:14:24
|
LL | pub fn to_many(&mut self) -> Option<&mut [T]> {
| ^^^^^^^^^
= help: consider choosing a less ambiguous name
error: methods with the following characteristics: (`to_*` and `*_mut`) usually take `self` by mutable reference
- --> $DIR/wrong_self_conventions_mut.rs:23:28
+ --> $DIR/wrong_self_conventions_mut.rs:22:28
|
LL | pub fn to_many_mut(&self) -> Option<&[T]> {
| ^^^^^
if let Some(edition) = config.parse_edition(ln) {
self.compile_flags.push(format!("--edition={}", edition));
has_edition = true;
- if edition == "2021" {
- self.compile_flags.push("-Zunstable-options".to_string());
- }
}
config.parse_and_update_revisions(ln, &mut self.revisions);
let mut config = config();
config.target = "x86_64-pc-windows-gnu".to_owned();
- assert!(check_ignore(&config, "// only-i686"));
+ assert!(check_ignore(&config, "// only-x86"));
assert!(check_ignore(&config, "// only-linux"));
assert!(check_ignore(&config, "// only-msvc"));
assert!(check_ignore(&config, "// only-32bit"));
get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), is_dylib);
rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name));
}
- if !self.props.aux_crates.is_empty() {
- rustc.arg("-Zunstable-options");
- }
aux_dir
}
];
static ASM_SUPPORTED_ARCHS: &[&str] = &[
- "x86", "x86_64", "arm", "aarch64", "riscv32", "riscv64", "nvptx64", "hexagon", "mips",
- "mips64", "spirv", "wasm32",
+ "x86", "x86_64", "arm", "aarch64", "riscv32",
+ "riscv64",
+ // These targets require an additional asm_experimental_arch feature.
+ // "nvptx64", "hexagon", "mips", "mips64", "spirv", "wasm32",
];
pub fn has_asm_support(triple: &str) -> bool {
-Subproject commit 1f47693e02809c97db61b51247ae4e4d46744c61
+Subproject commit 04f03a360ab8fef3d9c0ff84de2d39b8a196c717
"test_folder": "",
"test_file": "",
};
- var correspondances = {
+ var correspondences = {
"--resource-suffix": "resource_suffix",
"--doc-folder": "doc_folder",
"--test-folder": "test_folder",
};
for (var i = 0; i < args.length; ++i) {
- if (args[i] === "--resource-suffix"
- || args[i] === "--doc-folder"
- || args[i] === "--test-folder"
- || args[i] === "--test-file"
- || args[i] === "--crate-name") {
+ if (correspondences.hasOwnProperty(args[i])) {
i += 1;
if (i >= args.length) {
console.log("Missing argument after `" + args[i - 1] + "` option.");
return null;
}
- opts[correspondances[args[i - 1]]] = args[i];
+ opts[correspondences[args[i - 1]]] = args[i];
} else if (args[i] === "--help") {
showHelp();
process.exit(0);
--- /dev/null
+name: rustdoc check
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+
+jobs:
+ rustdoc_check:
+ runs-on: ubuntu-latest
+ name: rustdoc check
+ steps:
+ - name: checkout
+ uses: actions/checkout@v2
+
+ - name: install rustup
+ run: |
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh
+ sh rustup-init.sh -y --default-toolchain none
+ rustup target add x86_64-unknown-linux-gnu
+
+ - name: document rustfmt
+ env:
+ RUSTDOCFLAGS: --document-private-items --enable-index-page --show-type-layout --generate-link-to-definition -Zunstable-options -Dwarnings
+ run: cargo doc -Zskip-rustdoc-fingerprint --no-deps -p rustfmt-nightly -p rustfmt-config_proc_macro
Controls the strategy for how imports are grouped together.
- **Default value**: `Preserve`
-- **Possible values**: `Preserve`, `StdExternalCrate`
+- **Possible values**: `Preserve`, `StdExternalCrate`, `One`
- **Stable**: No
#### `Preserve` (default):
use crate::models::Event;
```
+#### `One`:
+
+Discard existing import groups, and create a single group for everything
+
+```rust
+use super::schema::{Context, Payload};
+use super::update::convert_publish_payload;
+use crate::models::Event;
+use alloc::alloc::Layout;
+use broker::database::PooledConnection;
+use chrono::Utc;
+use core::f32;
+use juniper::{FieldError, FieldResult};
+use std::sync::Arc;
+use uuid::Uuid;
+```
+
## `reorder_modules`
Reorder `mod` declarations alphabetically in group.
## Debugging
Some `rewrite_*` methods use the `debug!` macro for printing useful information.
-These messages can be printed by using the environment variable `RUST_LOG=rustfmt=DEBUG`.
+These messages can be printed by using the environment variable `RUSTFMT_LOG=rustfmt=DEBUG`.
These traces can be helpful in understanding which part of the code was used
and get a better grasp on the execution flow.
## Limitations
-Rustfmt tries to work on as much Rust code as possible, sometimes, the code
+Rustfmt tries to work on as much Rust code as possible. Sometimes, the code
doesn't even need to compile! As we approach a 1.0 release we are also looking
to limit areas of instability; in particular, post-1.0, the formatting of most
code should not change as Rustfmt improves. However, there are some things that
binary and library targets of your crate.
You can run `rustfmt --help` for information about available arguments.
+The easiest way to run rustfmt against a project is with `cargo fmt`. `cargo fmt` works on both
+single-crate projects and [cargo workspaces](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html).
+Please see `cargo fmt --help` for usage information.
+
+You can specify the path to your own `rustfmt` binary for cargo to use by setting the`RUSTFMT`
+environment variable. This was added in v1.4.22, so you must have this version or newer to leverage this feature (`cargo fmt --version`)
+
+### Running `rustfmt` directly
+
+To format individual files or arbitrary codes from stdin, the `rustfmt` binary should be used. Some
+examples follow:
+
+- `rustfmt lib.rs main.rs` will format "lib.rs" and "main.rs" in place
+- `rustfmt` will read a code from stdin and write formatting to stdout
+ - `echo "fn main() {}" | rustfmt` would emit "fn main() {}".
+
+For more information, including arguments and emit options, see `rustfmt --help`.
+
+### Verifying code is formatted
When running with `--check`, Rustfmt will exit with `0` if Rustfmt would not
make any formatting changes to the input, and `1` if Rustfmt would make changes.
It will also print any found differences. (Older versions of Rustfmt don't
support `--check`, use `--write-mode diff`).
-A minimal Travis setup could look like this (requires Rust 1.24.0 or greater):
+A minimal Travis setup could look like this (requires Rust 1.31.0 or greater):
```yaml
language: rust
+++ /dev/null
-environment:
- global:
- PROJECT_NAME: rustfmt
-
-build: false
-
-test_script:
- - echo Why does no one have access to delete me?
## Installation
- Install [CLion](https://www.jetbrains.com/clion/), [IntelliJ Ultimate or CE](https://www.jetbrains.com/idea/) through the direct download link or using the [JetBrains Toolbox](https://www.jetbrains.com/toolbox/).
- CLion provides a built-in debugger interface but its not free like IntelliJ CE - which does not provide the debugger interface. (IntelliJ seems to lack the toolchain for that, see this discussion [intellij-rust/issues/535](https://github.com/intellij-rust/intellij-rust/issues/535))
-
-- Install the [Rust Plugin](https://intellij-rust.github.io/) by navigating to File -> Settings -> Plugins and press "Install JetBrains Plugin"
- ![plugins](https://user-images.githubusercontent.com/1133787/47240861-f40af680-d3e9-11e8-9b82-cdd5c8d5f5b8.png)
+ CLion and IntelliJ Ultimate [provide a built-in debugger interface](https://github.com/intellij-rust/intellij-rust#compatible-ides) but they are not free like IntelliJ CE.
+
+- Install the [Rust Plugin](https://intellij-rust.github.io/) by navigating to File → Settings → Plugins and searching the plugin in the Marketplace
+ ![plugins](https://user-images.githubusercontent.com/6505554/83944518-6f1e5c00-a81d-11ea-9c35-e16948811ba8.png)
-- Press "Install" on the rust plugin
- ![install rust](https://user-images.githubusercontent.com/1133787/47240803-c0c86780-d3e9-11e8-9265-22f735e4d7ed.png)
+- Press "Install" on the Rust plugin
+ ![install rust](https://user-images.githubusercontent.com/6505554/83944533-82c9c280-a81d-11ea-86b3-ee2e31bc7d12.png)
- Restart CLion/IntelliJ
## Configuration
-- Open the settings window (File -> Settings) and search for "reformat"
+### Run Rustfmt on save
+
+- Open Rustfmt settings (File → Settings → Languages & Frameworks → Rust → Rustfmt) and enable "Run rustfmt on Save"
+ ![run_rustfmt_on_save](https://user-images.githubusercontent.com/6505554/83944610-3468f380-a81e-11ea-9c34-0cbd18dd4969.png)
+
+- IntellJ uses autosave, so now your files will always be formatted according to rustfmt. Alternatively you can use Ctrl+S to reformat file manually
+
+### Bind shortcut to "Reformat File with Rustfmt" action
+
+- Open the settings window (File → Settings) and search for "reformat"
![keymap](https://user-images.githubusercontent.com/1133787/47240922-2ae10c80-d3ea-11e8-9d8f-c798d9749240.png)
- Right-click on "Reformat File with Rustfmt" and assign a keyboard shortcut
+++ /dev/null
-indent_style = "Visual"
-combine_control_expr = false
[toolchain]
-channel = "nightly-2021-10-20"
+channel = "nightly-2021-11-08"
components = ["rustc-dev"]
if next.is_doc_comment() {
let snippet = context.snippet(missing_span);
let (_, mlb) = has_newlines_before_after_comment(snippet);
- result.push_str(&mlb);
+ result.push_str(mlb);
}
}
result.push('\n');
if next.is_doc_comment() {
let snippet = context.snippet(missing_span);
let (_, mlb) = has_newlines_before_after_comment(snippet);
- result.push_str(&mlb);
+ result.push_str(mlb);
}
}
result.push('\n');
) {
assert_eq!(
expected_comment,
- format!("{}", DocCommentFormatter::new(&literal, style))
+ format!("{}", DocCommentFormatter::new(literal, style))
);
}
}
};
fn main() {
- env_logger::init();
+ env_logger::Builder::from_env("RUSTFMT_LOG").init();
let opts = make_opts();
let exit_code = match execute(&opts) {
fn get_targets_recursive(
manifest_path: Option<&Path>,
- mut targets: &mut BTreeSet<Target>,
+ targets: &mut BTreeSet<Target>,
visited: &mut BTreeSet<String>,
) -> Result<(), io::Error> {
let metadata = get_cargo_metadata(manifest_path)?;
for package in &metadata.packages {
- add_targets(&package.targets, &mut targets);
+ add_targets(&package.targets, targets);
// Look for local dependencies using information available since cargo v1.51
// It's theoretically possible someone could use a newer version of rustfmt with
.any(|p| p.manifest_path.eq(&manifest_path))
{
visited.insert(dependency.name.to_owned());
- get_targets_recursive(Some(&manifest_path), &mut targets, visited)?;
+ get_targets_recursive(Some(&manifest_path), targets, visited)?;
}
}
}
} else {
self.rewrites
.iter()
- .map(|rw| utils::unicode_str_width(&rw))
+ .map(|rw| utils::unicode_str_width(rw))
.sum()
} + last.tries;
let one_line_budget = if self.child_count == 1 {
ChainItemKind::Comment(_, CommentPosition::Top) => result.push_str(&connector),
_ => result.push_str(&connector),
}
- result.push_str(&rewrite);
+ result.push_str(rewrite);
}
Some(result)
/// attributes are valid rust attributes
/// See <https://doc.rust-lang.org/rustdoc/print.html#attributes>
fn new(attributes: &str) -> CodeBlockAttribute {
- for attribute in attributes.split(",") {
+ for attribute in attributes.split(',') {
match attribute.trim() {
"" | "rust" | "should_panic" | "no_run" | "edition2015" | "edition2018"
| "edition2021" => (),
result.push_str(line);
result.push_str(match iter.peek() {
Some(next_line) if next_line.is_empty() => sep.trim_end(),
- Some(..) => &sep,
+ Some(..) => sep,
None => "",
});
}
let is_last = i == count_newlines(orig);
if let Some(ref mut ib) = self.item_block {
- if ib.add_line(&line) {
+ if ib.add_line(line) {
return false;
}
self.is_prev_line_multi_line = false;
self.item_block = None;
if let Some(stripped) = line.strip_prefix("```") {
self.code_block_attr = Some(CodeBlockAttribute::new(stripped))
- } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(&line) {
- let ib = ItemizedBlock::new(&line);
+ } else if self.fmt.config.wrap_comments() && ItemizedBlock::is_itemized_line(line) {
+ let ib = ItemizedBlock::new(line);
self.item_block = Some(ib);
return false;
}
{
(&line[4..], true)
} else if let CommentStyle::Custom(opener) = *style {
- if let Some(ref stripped) = line.strip_prefix(opener) {
+ if let Some(stripped) = line.strip_prefix(opener) {
(stripped, true)
} else {
(&line[opener.trim_end().len()..], false)
None => unreachable!(),
};
- while let Some((kind, c)) = self.base.next() {
+ for (kind, c) in self.base.by_ref() {
// needed to set the kind of the ending character on the last line
self.kind = kind;
if c == '\n' {
context.parse_sess.span_to_filename(span),
vec![FormattingError::from_span(
span,
- &context.parse_sess,
+ context.parse_sess,
ErrorKind::LostComment,
)],
);
fn remove_comment_header(comment: &str) -> &str {
if comment.starts_with("///") || comment.starts_with("//!") {
&comment[3..]
- } else if let Some(ref stripped) = comment.strip_prefix("//") {
+ } else if let Some(stripped) = comment.strip_prefix("//") {
stripped
} else if (comment.starts_with("/**") && !comment.starts_with("/**/"))
|| comment.starts_with("/*!")
Windows,
/// Force CR (`\n).
Unix,
- /// `\r\n` in Windows, `\n`` on other platforms.
+ /// `\r\n` in Windows, `\n` on other platforms.
Native,
}
/// 2. other imports
/// 3. `self` / `crate` / `super` imports
StdExternalCrate,
+ /// Discard existing groups, and create a single group for everything
+ One,
}
#[config_type]
format!(r#"<file name="{}">"#, bin_file),
format!(
r#"<error line="2" severity="warning" message="Should be `{}`" />"#,
- XmlEscaped(&r#" println!("Hello, world!");"#),
+ XmlEscaped(r#" println!("Hello, world!");"#),
),
String::from("</file>"),
];
format!(r#"<file name="{}">"#, lib_file),
format!(
r#"<error line="2" severity="warning" message="Should be `{}`" />"#,
- XmlEscaped(&r#" println!("Greetings!");"#),
+ XmlEscaped(r#" println!("Greetings!");"#),
),
String::from("</file>"),
];
}: FormattedFile<'_>,
) -> Result<EmitterResult, io::Error> {
const CONTEXT_SIZE: usize = 3;
- let mismatch = make_diff(&original_text, formatted_text, CONTEXT_SIZE);
+ let mismatch = make_diff(original_text, formatted_text, CONTEXT_SIZE);
let has_diff = !mismatch.is_empty();
if has_diff {
}
_ => false,
},
- ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, &expr),
+ ast::ExprKind::Unary(_, ref expr) => needs_space_before_range(context, expr),
_ => false,
}
}
prefix: &str,
shape: Shape,
) -> Option<String> {
- if block_has_statements(&block) {
+ if block_has_statements(block) {
return None;
}
block: &ast::Block,
attrs: Option<&[ast::Attribute]>,
) -> bool {
- !block_has_statements(&block)
+ !block_has_statements(block)
&& !block_contains_comment(context, block)
&& attrs.map_or(true, |a| inner_attributes(a).is_empty())
}
let span = lit.span;
let symbol = lit.token.symbol.as_str();
- if symbol.starts_with("0x") {
+ if let Some(symbol_stripped) = symbol.strip_prefix("0x") {
let hex_lit = match context.config.hex_literal_case() {
HexLiteralCase::Preserve => None,
- HexLiteralCase::Upper => Some(symbol[2..].to_ascii_uppercase()),
- HexLiteralCase::Lower => Some(symbol[2..].to_ascii_lowercase()),
+ HexLiteralCase::Upper => Some(symbol_stripped.to_ascii_uppercase()),
+ HexLiteralCase::Lower => Some(symbol_stripped.to_ascii_lowercase()),
};
if let Some(hex_lit) = hex_lit {
return wrap_str(
};
let fields_str =
- wrap_struct_field(context, &attrs, &fields_str, shape, v_shape, one_line_width)?;
+ wrap_struct_field(context, attrs, &fields_str, shape, v_shape, one_line_width)?;
Some(format!("{} {{{}}}", path_str, fields_str))
// FIXME if context.config.indent_style() == Visual, but we run out
shape: Shape,
rhs_tactics: RhsTactics,
) -> Option<String> {
- let last_line_width = last_line_width(&lhs).saturating_sub(if lhs.contains('\n') {
+ let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') {
shape.indent.width()
} else {
0
if contains_comment {
let rhs = rhs.trim_start();
- combine_strs_with_missing_comments(context, &lhs, &rhs, between_span, shape, allow_extend)
+ combine_strs_with_missing_comments(context, &lhs, rhs, between_span, shape, allow_extend)
} else {
Some(lhs + &rhs)
}
has_rhs_comment: bool,
) -> Option<String> {
match orig_rhs {
+ Some(ref new_str) if new_str.is_empty() => {
+ return Some(String::new());
+ }
Some(ref new_str)
if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width =>
{
}
fn main() {
- env_logger::init();
+ env_logger::Builder::from_env("RUSTFMT_LOG").init();
let opts = Opts::from_args();
if let Err(e) = run(opts) {
println!("{}", e);
let snippet_provider = self.parse_session.snippet_provider(module.span);
let mut visitor = FmtVisitor::from_parse_sess(
&self.parse_session,
- &self.config,
+ self.config,
&snippet_provider,
self.report.clone(),
);
&mut visitor.buffer,
&path,
&visitor.skipped_range.borrow(),
- &self.config,
+ self.config,
&self.report,
);
}
fn main() {
- env_logger::init();
+ env_logger::Builder::from_env("RUSTFMT_LOG").init();
let opts = make_opts();
let matches = opts
shape: Shape,
) -> Option<String> {
let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| {
- crate::utils::format_visibility(context, &vis)
+ crate::utils::format_visibility(context, vis)
});
let use_str = self
.rewrite(context, shape.offset_left(vis.len())?)
fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option<String> {
let mut result = String::with_capacity(256);
let mut iter = self.path.iter().peekable();
- while let Some(ref segment) = iter.next() {
+ while let Some(segment) = iter.next() {
let segment_str = segment.rewrite(context, shape)?;
result.push_str(&segment_str);
if iter.peek().is_some() {
fn to_str(&self, context: &RewriteContext<'_>) -> String {
let mut result = String::with_capacity(128);
// Vis defaultness constness unsafety abi.
- result.push_str(&*format_visibility(context, &self.visibility));
+ result.push_str(&*format_visibility(context, self.visibility));
result.push_str(format_defaultness(self.defaultness));
result.push_str(format_constness(self.constness));
result.push_str(format_async(&self.is_async));
fn need_empty_line(a: &ast::AssocItemKind, b: &ast::AssocItemKind) -> bool {
match (a, b) {
(TyAlias(lty), TyAlias(rty))
- if both_type(<y.3, &rty.3) || both_opaque(<y.3, &rty.3) =>
+ if both_type(<y.ty, &rty.ty) || both_opaque(<y.ty, &rty.ty) =>
{
false
}
buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) {
(TyAlias(lty), TyAlias(rty))
- if both_type(<y.3, &rty.3) || both_opaque(<y.3, &rty.3) =>
+ if both_type(<y.ty, &rty.ty) || both_opaque(<y.ty, &rty.ty) =>
{
a.ident.as_str().cmp(&b.ident.as_str())
}
a.ident.as_str().cmp(&b.ident.as_str())
}
(Fn(..), Fn(..)) => a.span.lo().cmp(&b.span.lo()),
- (TyAlias(ty), _) if is_type(&ty.3) => Ordering::Less,
- (_, TyAlias(ty)) if is_type(&ty.3) => Ordering::Greater,
+ (TyAlias(ty), _) if is_type(&ty.ty) => Ordering::Less,
+ (_, TyAlias(ty)) if is_type(&ty.ty) => Ordering::Greater,
(TyAlias(..), _) => Ordering::Less,
(_, TyAlias(..)) => Ordering::Greater,
(Const(..), _) => Ordering::Less,
offset: Indent,
) -> Option<String> {
if let ast::ItemKind::Impl(impl_kind) = &item.kind {
- let ast::ImplKind {
+ let ast::Impl {
ref generics,
ref self_ty,
ref items,
offset: Indent,
) -> Option<String> {
if let ast::ItemKind::Impl(impl_kind) = &item.kind {
- let ast::ImplKind {
+ let ast::Impl {
unsafety,
polarity,
defaultness,
offset: Indent,
) -> Option<String> {
if let ast::ItemKind::Trait(trait_kind) = &item.kind {
- let ast::TraitKind(is_auto, unsafety, ref generics, ref generic_bounds, ref trait_items) =
- **trait_kind;
+ let ast::Trait {
+ is_auto,
+ unsafety,
+ ref generics,
+ ref bounds,
+ ref items,
+ } = **trait_kind;
let mut result = String::with_capacity(128);
let header = format!(
"{}{}{}trait ",
result.push_str(&generics_str);
// FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
- if !generic_bounds.is_empty() {
+ if !bounds.is_empty() {
let ident_hi = context
.snippet_provider
.span_after(item.span, &item.ident.as_str());
- let bound_hi = generic_bounds.last().unwrap().span().hi();
+ let bound_hi = bounds.last().unwrap().span().hi();
let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
if contains_comment(snippet) {
return None;
result = rewrite_assign_rhs_with(
context,
result + ":",
- generic_bounds,
+ bounds,
shape,
RhsTactics::ForceNextLineWithoutIndent,
)?;
let where_on_new_line = context.config.indent_style() != IndentStyle::Block;
let where_budget = context.budget(last_line_width(&result));
- let pos_before_where = if generic_bounds.is_empty() {
+ let pos_before_where = if bounds.is_empty() {
generics.where_clause.span.lo()
} else {
- generic_bounds[generic_bounds.len() - 1].span().hi()
+ bounds[bounds.len() - 1].span().hi()
};
let option = WhereClauseOption::snuggled(&generics_str);
let where_clause_str = rewrite_where_clause(
}
}
+ let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
+ let snippet = context.snippet(block_span);
+ let open_pos = snippet.find_uncommented("{")? + 1;
+
match context.config.brace_style() {
_ if last_line_contains_single_line_comment(&result)
|| last_line_width(&result) + 2 > context.budget(offset.width()) =>
{
result.push_str(&offset.to_string_with_newline(context.config));
}
+ _ if context.config.empty_item_single_line()
+ && items.is_empty()
+ && !result.contains('\n')
+ && !contains_comment(&snippet[open_pos..]) =>
+ {
+ result.push_str(" {}");
+ return Some(result);
+ }
BraceStyle::AlwaysNextLine => {
result.push_str(&offset.to_string_with_newline(context.config));
}
BraceStyle::PreferSameLine => result.push(' '),
BraceStyle::SameLineWhere => {
if result.contains('\n')
- || (!generics.where_clause.predicates.is_empty() && !trait_items.is_empty())
+ || (!generics.where_clause.predicates.is_empty() && !items.is_empty())
{
result.push_str(&offset.to_string_with_newline(context.config));
} else {
}
result.push('{');
- let block_span = mk_sp(generics.where_clause.span.hi(), item.span.hi());
- let snippet = context.snippet(block_span);
- let open_pos = snippet.find_uncommented("{")? + 1;
let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
- if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) {
+ if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
let mut visitor = FmtVisitor::from_context(context);
visitor.block_indent = offset.block_only().block_indent(context.config);
visitor.last_pos = block_span.lo() + BytePos(open_pos as u32);
- for item in trait_items {
+ for item in items {
visitor.visit_trait_item(item);
}
}
}
-struct OpaqueTypeBounds<'a> {
- generic_bounds: &'a ast::GenericBounds,
-}
-
-impl<'a> Rewrite for OpaqueTypeBounds<'a> {
- fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
- self.generic_bounds
- .rewrite(context, shape)
- .map(|s| format!("impl {}", s))
- }
-}
-
pub(crate) struct TraitAliasBounds<'a> {
generic_bounds: &'a ast::GenericBounds,
generics: &'a ast::Generics,
} else if fits_single_line {
Cow::from(" ")
} else {
- shape.indent.to_string_with_newline(&context.config)
+ shape.indent.to_string_with_newline(context.config)
};
Some(format!("{}{}{}", generic_bounds_str, space, where_str))
let alias = rewrite_ident(context, ident);
// 6 = "trait ", 2 = " ="
let g_shape = shape.offset_left(6)?.sub_width(2)?;
- let generics_str = rewrite_generics(context, &alias, generics, g_shape)?;
+ let generics_str = rewrite_generics(context, alias, generics, g_shape)?;
let vis_str = format_visibility(context, vis);
let lhs = format!("{}trait {} =", vis_str, generics_str);
// 1 = ";"
closer: &str,
) {
// 3 = " {}" or "();"
- let used_width = last_line_used_width(&result, offset.width()) + 3;
+ let used_width = last_line_used_width(result, offset.width()) + 3;
if used_width > context.config.max_width() {
result.push_str(&offset.to_string_with_newline(context.config))
}
Some(result)
}
-pub(crate) fn rewrite_type<R: Rewrite>(
- context: &RewriteContext<'_>,
+pub(crate) enum ItemVisitorKind<'a> {
+ Item(&'a ast::Item),
+ AssocTraitItem(&'a ast::AssocItem),
+ AssocImplItem(&'a ast::AssocItem),
+ ForeignItem(&'a ast::ForeignItem),
+}
+
+struct TyAliasRewriteInfo<'c, 'g>(
+ &'c RewriteContext<'c>,
+ Indent,
+ &'g ast::Generics,
+ symbol::Ident,
+ Span,
+);
+
+pub(crate) fn rewrite_type_alias<'a, 'b>(
+ ty_alias_kind: &ast::TyAlias,
+ context: &RewriteContext<'a>,
indent: Indent,
- ident: symbol::Ident,
- vis: &ast::Visibility,
- generics: &ast::Generics,
+ visitor_kind: &ItemVisitorKind<'b>,
+ span: Span,
+) -> Option<String> {
+ use ItemVisitorKind::*;
+
+ let ast::TyAlias {
+ defaultness,
+ ref generics,
+ ref bounds,
+ ref ty,
+ } = *ty_alias_kind;
+ let ty_opt = ty.as_ref().map(|t| &**t);
+ let (ident, vis) = match visitor_kind {
+ Item(i) => (i.ident, &i.vis),
+ AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
+ ForeignItem(i) => (i.ident, &i.vis),
+ };
+ let rw_info = &TyAliasRewriteInfo(context, indent, generics, ident, span);
+
+ // Type Aliases are formatted slightly differently depending on the context
+ // in which they appear, whether they are opaque, and whether they are associated.
+ // https://rustc-dev-guide.rust-lang.org/opaque-types-type-alias-impl-trait.html
+ // https://github.com/rust-dev-tools/fmt-rfcs/blob/master/guide/items.md#type-aliases
+ match (visitor_kind, ty_opt) {
+ (Item(_), None) => {
+ let op_ty = OpaqueType { bounds };
+ rewrite_ty(rw_info, Some(bounds), Some(&op_ty), vis)
+ }
+ (Item(_), Some(ty)) => rewrite_ty(rw_info, Some(bounds), Some(&*ty), vis),
+ (AssocImplItem(_), _) => {
+ let result = if let Some(ast::Ty {
+ kind: ast::TyKind::ImplTrait(_, ref bounds),
+ ..
+ }) = ty_opt
+ {
+ let op_ty = OpaqueType { bounds };
+ rewrite_ty(rw_info, None, Some(&op_ty), &DEFAULT_VISIBILITY)
+ } else {
+ rewrite_ty(rw_info, None, ty.as_ref(), vis)
+ }?;
+ match defaultness {
+ ast::Defaultness::Default(..) => Some(format!("default {}", result)),
+ _ => Some(result),
+ }
+ }
+ (AssocTraitItem(_), _) | (ForeignItem(_), _) => {
+ rewrite_ty(rw_info, Some(bounds), ty.as_ref(), vis)
+ }
+ }
+}
+
+fn rewrite_ty<R: Rewrite>(
+ rw_info: &TyAliasRewriteInfo<'_, '_>,
generic_bounds_opt: Option<&ast::GenericBounds>,
rhs: Option<&R>,
- span: Span,
+ vis: &ast::Visibility,
) -> Option<String> {
let mut result = String::with_capacity(128);
+ let TyAliasRewriteInfo(context, indent, generics, ident, span) = *rw_info;
result.push_str(&format!("{}type ", format_visibility(context, vis)));
let ident_str = rewrite_ident(context, ident);
}
}
-pub(crate) fn rewrite_opaque_type(
- context: &RewriteContext<'_>,
- indent: Indent,
- ident: symbol::Ident,
- generic_bounds: &ast::GenericBounds,
- generics: &ast::Generics,
- vis: &ast::Visibility,
- span: Span,
-) -> Option<String> {
- let opaque_type_bounds = OpaqueTypeBounds { generic_bounds };
- rewrite_type(
- context,
- indent,
- ident,
- vis,
- generics,
- Some(generic_bounds),
- Some(&opaque_type_bounds),
- span,
- )
-}
-
fn type_annotation_spacing(config: &Config) -> (&str, &str) {
(
if config.space_before_colon() { " " } else { "" },
}
}
-pub(crate) fn rewrite_impl_type(
- ident: symbol::Ident,
- vis: &ast::Visibility,
- defaultness: ast::Defaultness,
- ty_opt: Option<&ptr::P<ast::Ty>>,
- generics: &ast::Generics,
- context: &RewriteContext<'_>,
- indent: Indent,
- span: Span,
-) -> Option<String> {
- // Opaque type
- let result = if let Some(rustc_ast::ast::Ty {
- kind: ast::TyKind::ImplTrait(_, ref bounds),
- ..
- }) = ty_opt.map(|t| &**t)
- {
- rewrite_type(
- context,
- indent,
- ident,
- &DEFAULT_VISIBILITY,
- generics,
- None,
- Some(&OpaqueType { bounds }),
- span,
- )
- } else {
- rewrite_type(context, indent, ident, vis, generics, None, ty_opt, span)
- }?;
-
- match defaultness {
- ast::Defaultness::Default(..) => Some(format!("default {}", result)),
- _ => Some(result),
- }
-}
-
impl Rewrite for ast::FnRetTy {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
match *self {
)?;
Some(combine_strs_with_missing_comments(
context,
- ¶m_attrs,
+ param_attrs,
&format!("&{} {}self", lifetime_str, mut_str),
span,
shape,
}
None => Some(combine_strs_with_missing_comments(
context,
- ¶m_attrs,
+ param_attrs,
&format!("&{}self", mut_str),
span,
shape,
Some(combine_strs_with_missing_comments(
context,
- ¶m_attrs,
+ param_attrs,
&format!("{}self: {}", format_mutability(mutability), type_str),
span,
shape,
}
ast::SelfKind::Value(mutability) => Some(combine_strs_with_missing_comments(
context,
- ¶m_attrs,
+ param_attrs,
&format!("{}self", format_mutability(mutability)),
span,
shape,
}
// Skip `pub(crate)`.
- let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span);
+ let lo_after_visibility = get_bytepos_after_visibility(fn_sig.visibility, span);
// A conservative estimation, the goal is to be over all parens in generics
let params_start = fn_sig
.generics
let mut result = String::with_capacity(128);
let shape = Shape::indented(offset, context.config);
- result.push_str(&format_visibility(context, vis).trim());
+ result.push_str(format_visibility(context, vis).trim());
// Check for a missing comment between the visibility and the item name.
let after_vis = vis.span.hi();
}
}
- result.push_str(&rewrite_ident(context, ident));
+ result.push_str(rewrite_ident(context, ident));
result
}
let item_str = match self.kind {
ast::ForeignItemKind::Fn(ref fn_kind) => {
- let ast::FnKind(defaultness, ref fn_sig, ref generics, ref block) = **fn_kind;
- if let Some(ref body) = block {
+ let ast::Fn {
+ defaultness,
+ ref sig,
+ ref generics,
+ ref body,
+ } = **fn_kind;
+ if let Some(ref body) = body {
let mut visitor = FmtVisitor::from_context(context);
visitor.block_indent = shape.indent;
visitor.last_pos = self.span.lo();
let inner_attrs = inner_attributes(&self.attrs);
let fn_ctxt = visit::FnCtxt::Foreign;
visitor.visit_fn(
- visit::FnKind::Fn(fn_ctxt, self.ident, &fn_sig, &self.vis, Some(body)),
+ visit::FnKind::Fn(fn_ctxt, self.ident, &sig, &self.vis, Some(body)),
generics,
- &fn_sig.decl,
+ &sig.decl,
self.span,
defaultness,
Some(&inner_attrs),
context,
shape.indent,
self.ident,
- &FnSig::from_method_sig(&fn_sig, generics, &self.vis),
+ &FnSig::from_method_sig(&sig, generics, &self.vis),
span,
FnBraceStyle::None,
)
// 1 = ;
rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";")
}
- ast::ForeignItemKind::TyAlias(ref ty_alias_kind) => {
- let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) =
- **ty_alias_kind;
- rewrite_type(
- &context,
- shape.indent,
- self.ident,
- &self.vis,
- generics,
- Some(generic_bounds),
- type_default.as_ref(),
- self.span,
- )
+ ast::ForeignItemKind::TyAlias(ref ty_alias) => {
+ let (kind, span) = (&ItemVisitorKind::ForeignItem(&self), self.span);
+ rewrite_type_alias(ty_alias, context, shape.indent, kind, span)
}
ast::ForeignItemKind::MacCall(ref mac) => {
rewrite_macro(mac, None, context, shape, MacroPosition::Item)
combine_strs_with_missing_comments(
context,
&attrs_str,
- &item_str,
+ item_str,
missed_span,
shape,
allow_extend,
writeln!(
t,
"{}",
- FormatReportFormatterBuilder::new(&self)
+ FormatReportFormatterBuilder::new(self)
.enable_colors(true)
.build()
)?;
impl fmt::Display for FormatReport {
// Prints all the formatting errors.
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
- write!(fmt, "{}", FormatReportFormatterBuilder::new(&self).build())?;
+ write!(fmt, "{}", FormatReportFormatterBuilder::new(self).build())?;
Ok(())
}
}
result.push('\n');
result.push_str(indent_str);
// This is the width of the item (without comments).
- line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(&s));
+ line_len = item.item.as_ref().map_or(0, |s| unicode_str_width(s));
}
} else {
result.push(' ')
pub(crate) fn total_item_width(item: &ListItem) -> usize {
comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..]))
+ comment_len(item.post_comment.as_ref().map(|x| &(*x)[..]))
- + item.item.as_ref().map_or(0, |s| unicode_str_width(&s))
+ + item.item.as_ref().map_or(0, |s| unicode_str_width(s))
}
fn comment_len(comment: Option<&str>) -> usize {
})
.unwrap_or(false);
if is_like_block_indent_style {
- return trim_left_preserve_layout(context.snippet(span), indent, &context.config);
+ return trim_left_preserve_layout(context.snippet(span), indent, context.config);
}
context.skipped_range.borrow_mut().push((
// the `macro_name!` and `{ /* macro_body */ }` but skip modifying
// anything in between the braces (for now).
let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{');
- match trim_left_preserve_layout(snippet, shape.indent, &context.config) {
+ match trim_left_preserve_layout(snippet, shape.indent, context.config) {
Some(macro_body) => Some(format!("{} {}", macro_name, macro_body)),
None => Some(format!("{} {}", macro_name, snippet)),
}
break;
}
TokenTree::Token(ref t) => {
- buffer.push_str(&pprust::token_to_string(&t));
+ buffer.push_str(&pprust::token_to_string(t));
}
_ => return None,
}
let mut iter = args.iter().peekable();
let indent_str = shape.indent.to_string_with_newline(context.config);
- while let Some(ref arg) = iter.next() {
+ while let Some(arg) = iter.next() {
result.push_str(&arg.rewrite(context, shape, use_multiple_lines)?);
if use_multiple_lines
result.pop();
}
result.push_str(&indent_str);
- } else if let Some(ref next_arg) = iter.peek() {
+ } else if let Some(next_arg) = iter.peek() {
let space_before_dollar =
!arg.kind.ends_with_space() && next_arg.kind.starts_with_dollar();
let space_before_brace = next_arg.kind.starts_with_brace();
{
s += &indent_str;
}
- (s + l + "\n", indent_next_line(kind, &l, &config))
+ (s + l + "\n", indent_next_line(kind, l, &config))
},
)
.0;
MacroArg::Item(item) => item,
_ => return None,
};
- visitor.visit_item(&item);
+ visitor.visit_item(item);
}
let mut result = String::with_capacity(256);
- result.push_str(¯o_name);
+ result.push_str(macro_name);
result.push_str(opener);
result.push_str(&visitor.block_indent.to_string_with_newline(context.config));
result.push_str(visitor.buffer.trim());
.map(|a| {
context
.snippet(a.pat.span)
- .starts_with("|")
+ .starts_with('|')
.then(|| a.pat.span().lo())
})
.collect()
let can_extend =
|expr| !context.config.force_multiline_blocks() && can_flatten_block_around_this(expr);
- if let Some(ref block) = block_can_be_flattened(context, body) {
+ if let Some(block) = block_can_be_flattened(context, body) {
if let ast::StmtKind::Expr(ref expr) = block.stmts[0].kind {
if let ast::ExprKind::Block(..) = expr.kind {
flatten_arm_body(context, expr, None)
if comment_str.is_empty() {
String::new()
} else {
- rewrite_comment(comment_str, false, shape, &context.config)?
+ rewrite_comment(comment_str, false, shape, context.config)?
}
};
result.push_str(&arrow_comment);
}
result.push_str(&nested_indent_str);
- result.push_str(&body_str);
- result.push_str(&comma);
+ result.push_str(body_str);
+ result.push_str(comma);
return Some(result);
}
result.push_str(&arrow_comment);
}
result.push_str(&block_sep);
- result.push_str(&body_str);
+ result.push_str(body_str);
result.push_str(&body_suffix);
Some(result)
};
Directory, DirectoryOwnership, ModError, ModulePathSuccess, Parser, ParserError,
};
use crate::syntux::session::ParseSess;
-use crate::utils::contains_skip;
+use crate::utils::{contains_skip, mk_sp};
mod visitor;
self.visit_mod_from_ast(&krate.items)?;
}
+ let snippet_provider = self.parse_sess.snippet_provider(krate.span);
+
self.file_map.insert(
root_filename,
Module::new(
- krate.span,
+ mk_sp(snippet_provider.start_pos(), snippet_provider.end_pos()),
None,
Cow::Borrowed(&krate.items),
Cow::Borrowed(&krate.attrs),
/// Visit modules from AST.
fn visit_mod_from_ast(
&mut self,
- items: &'ast Vec<rustc_ast::ptr::P<ast::Item>>,
+ items: &'ast [rustc_ast::ptr::P<ast::Item>],
) -> Result<(), ModuleResolutionError> {
for item in items {
if is_cfg_if(item) {
};
self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))
}
- SubModKind::Internal(ref item) => {
+ SubModKind::Internal(item) => {
self.push_inline_mod_directory(item.ident, &item.attrs);
self.visit_sub_mod_after_directory_update(sub_mod, None)
}
}
match (sub_mod.ast_mod_kind, sub_mod.items) {
(Some(Cow::Borrowed(ast::ModKind::Loaded(items, _, _))), _) => {
- self.visit_mod_from_ast(&items)
+ self.visit_mod_from_ast(items)
+ }
+ (Some(Cow::Owned(ast::ModKind::Loaded(items, _, _))), _) | (_, Cow::Owned(items)) => {
+ self.visit_mod_outside_ast(items)
}
- (Some(Cow::Owned(..)), Cow::Owned(items)) => self.visit_mod_outside_ast(items),
(_, _) => Ok(()),
}
}
) -> Option<String> {
let last_item = self.last_item()?;
let rewrite = match last_item {
- OverflowableItem::Expr(ref expr) => {
+ OverflowableItem::Expr(expr) => {
match expr.kind {
// When overflowing the closure which consists of a single control flow
// expression, force to use block if its condition uses multi line.
for ((_, rewrite), s) in list.list.iter().zip(list.separators.iter()) {
if let Some(rewrite) = rewrite {
- if !is_single_line(&rewrite) || result.len() > shape.width {
+ if !is_single_line(rewrite) || result.len() > shape.width {
return None;
}
- result.push_str(&rewrite);
+ result.push_str(rewrite);
result.push(' ');
result.push_str(s);
result.push(' ');
shape: Shape,
context: &RewriteContext<'_>,
) -> Option<String> {
- let rhs_offset = shape.rhs_overhead(&context.config);
+ let rhs_offset = shape.rhs_overhead(context.config);
let nested_shape = (match context.config.indent_style() {
IndentStyle::Visual => shape.visual_indent(0),
IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
})
- .with_max_width(&context.config)
+ .with_max_width(context.config)
.sub_width(rhs_offset)?;
let indent_str = nested_shape.indent.to_string_with_newline(context.config);
let mut result = String::new();
- result.push_str(&list.list[0].1.as_ref()?);
+ result.push_str(list.list[0].1.as_ref()?);
for ((e, default_rw), s) in list.list[1..].iter().zip(list.separators.iter()) {
// The following test checks if we should keep two subexprs on the same
}
}
- result.push_str(&default_rw.as_ref()?);
+ result.push_str(default_rw.as_ref()?);
}
Some(result)
}
return node.rewrite(context, shape);
}
let nested_overhead = sep + 1;
- let rhs_offset = shape.rhs_overhead(&context.config);
+ let rhs_offset = shape.rhs_overhead(context.config);
let nested_shape = (match context.config.indent_style() {
IndentStyle::Visual => shape.visual_indent(0),
IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
})
- .with_max_width(&context.config)
+ .with_max_width(context.config)
.sub_width(rhs_offset)?;
let default_shape = match context.config.binop_separator() {
SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?,
context: &RewriteContext<'_>,
shape: Shape,
) -> Option<String> {
- let mut pat_vec: Vec<_> = pats.iter().map(|x| TuplePatField::Pat(x)).collect();
-
- if pat_vec.is_empty() {
+ if pats.is_empty() {
return Some(format!("{}()", path_str.unwrap_or_default()));
}
+ let mut pat_vec: Vec<_> = pats.iter().map(TuplePatField::Pat).collect();
+
let wildcard_suffix_len = count_wildcard_suffix_len(context, &pat_vec, span, shape);
let (pat_vec, span) = if context.config.condense_wildcard_suffixes() && wildcard_suffix_len >= 2
{
let path_str = path_str.unwrap_or_default();
overflow::rewrite_with_parens(
- &context,
+ context,
&path_str,
pat_vec.iter(),
shape,
};
let mut regrouped_items = match context.config.group_imports() {
- GroupImportsTactic::Preserve => vec![normalized_items],
+ GroupImportsTactic::Preserve | GroupImportsTactic::One => {
+ vec![normalized_items]
+ }
GroupImportsTactic::StdExternalCrate => group_imports(normalized_items),
};
span: Span,
) -> Result<(Vec<ast::Attribute>, Vec<ptr::P<ast::Item>>, Span), ParserError> {
let result = catch_unwind(AssertUnwindSafe(|| {
- let mut parser = new_parser_from_file(sess.inner(), &path, Some(span));
+ let mut parser = new_parser_from_file(sess.inner(), path, Some(span));
match parser.parse_mod(&TokenKind::Eof) {
Ok(result) => Some(result),
Err(mut e) => {
}
}));
match result {
- Ok(Some(m)) => {
- if !sess.has_errors() {
- return Ok(m);
- }
-
- if sess.can_reset_errors() {
- sess.reset_errors();
- return Ok(m);
- }
- Err(ParserError::ParseError)
+ Ok(Some(m)) if !sess.has_errors() => Ok(m),
+ Ok(Some(m)) if sess.can_reset_errors() => {
+ sess.reset_errors();
+ Ok(m)
}
- Ok(None) => Err(ParserError::ParseError),
+ Ok(_) => Err(ParserError::ParseError),
Err(..) if path.exists() => Err(ParserError::ParseError),
Err(_) => Err(ParserError::ParsePanicError),
}
}
pub(crate) fn ignore_file(&self, path: &FileName) -> bool {
- self.ignore_path_set.as_ref().is_match(&path)
+ self.ignore_path_set.as_ref().is_match(path)
}
pub(crate) fn set_silent_emitter(&mut self) {
debug!("Testing '{}'...", file_name.display());
- match idempotent_check(&file_name, &opt_config) {
+ match idempotent_check(&file_name, opt_config) {
Ok(ref report) if report.has_warnings() => {
- print!("{}", FormatReportFormatterBuilder::new(&report).build());
+ print!("{}", FormatReportFormatterBuilder::new(report).build());
fails += 1;
}
Ok(report) => reports.push(report),
use crate::{FileName, Input, Session};
-#[test]
-fn nested_out_of_line_mods_loaded() {
- // See also https://github.com/rust-lang/rustfmt/issues/4874
- let filename = "tests/mod-resolver/issue-4874/main.rs";
- let input_file = PathBuf::from(filename);
+fn verify_mod_resolution(input_file_name: &str, exp_misformatted_files: &[&str]) {
+ let input_file = PathBuf::from(input_file_name);
let config = read_config(&input_file);
let mut session = Session::<io::Stdout>::new(config, None);
let report = session
- .format(Input::File(filename.into()))
+ .format(Input::File(input_file_name.into()))
.expect("Should not have had any execution errors");
let errors_by_file = &report.internal.borrow().0;
- assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(
- "tests/mod-resolver/issue-4874/bar/baz.rs",
- ))));
- assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(
- "tests/mod-resolver/issue-4874/foo/qux.rs",
- ))));
+ for exp_file in exp_misformatted_files {
+ assert!(errors_by_file.contains_key(&FileName::Real(PathBuf::from(exp_file))));
+ }
+}
+
+#[test]
+fn nested_out_of_line_mods_loaded() {
+ // See also https://github.com/rust-lang/rustfmt/issues/4874
+ verify_mod_resolution(
+ "tests/mod-resolver/issue-4874/main.rs",
+ &[
+ "tests/mod-resolver/issue-4874/bar/baz.rs",
+ "tests/mod-resolver/issue-4874/foo/qux.rs",
+ ],
+ );
+}
+
+#[test]
+fn out_of_line_nested_inline_within_out_of_line() {
+ // See also https://github.com/rust-lang/rustfmt/issues/5063
+ verify_mod_resolution(
+ "tests/mod-resolver/issue-5063/main.rs",
+ &[
+ "tests/mod-resolver/issue-5063/foo/bar/baz.rs",
+ "tests/mod-resolver/issue-5063/foo.rs",
+ ],
+ );
}
result = combine_strs_with_missing_comments(
context,
result.trim_end(),
- &mt.ty.rewrite(&context, shape)?,
+ &mt.ty.rewrite(context, shape)?,
before_ty_span,
shape,
true,
let budget = shape.width.checked_sub(used_width)?;
let ty_str = mt
.ty
- .rewrite(&context, Shape::legacy(budget, shape.indent + used_width))?;
+ .rewrite(context, Shape::legacy(budget, shape.indent + used_width))?;
result.push_str(&ty_str);
}
(
VisibilityKind::Restricted { path: p, .. },
VisibilityKind::Restricted { path: q, .. },
- ) => pprust::path_to_string(&p) == pprust::path_to_string(&q),
+ ) => pprust::path_to_string(p) == pprust::path_to_string(q),
(VisibilityKind::Public, VisibilityKind::Public)
| (VisibilityKind::Inherited, VisibilityKind::Inherited)
| (
#[test]
fn test_remove_trailing_white_spaces() {
let s = " r#\"\n test\n \"#";
- assert_eq!(remove_trailing_white_spaces(&s), s);
+ assert_eq!(remove_trailing_white_spaces(s), s);
}
#[test]
let config = Config::default();
let indent = Indent::new(4, 0);
assert_eq!(
- trim_left_preserve_layout(&s, indent, &config),
+ trim_left_preserve_layout(s, indent, &config),
Some("aaa\n bbb\n ccc".to_string())
);
}
use crate::coverage::transform_missing_snippet;
use crate::items::{
format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate,
- rewrite_impl_type, rewrite_opaque_type, rewrite_type, FnBraceStyle, FnSig, StaticParts,
- StructParts,
+ rewrite_type_alias, FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts,
};
use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
use crate::modules::Module;
);
} else {
let shape = self.shape();
- let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape));
+ let rewrite = self.with_context(|ctx| stmt.rewrite(ctx, shape));
self.push_rewrite(stmt.span(), rewrite)
}
}
let comment_snippet = self.snippet(span);
- let align_to_right = if unindent_comment && contains_comment(&comment_snippet) {
+ let align_to_right = if unindent_comment && contains_comment(comment_snippet) {
let first_lines = comment_snippet.splitn(2, '/').next().unwrap_or("");
- last_line_width(first_lines) > last_line_width(&comment_snippet)
+ last_line_width(first_lines) > last_line_width(comment_snippet)
} else {
false
};
let filtered_attrs;
let mut attrs = &item.attrs;
let skip_context_saved = self.skip_context.clone();
- self.skip_context.update_with_attrs(&attrs);
+ self.skip_context.update_with_attrs(attrs);
let should_visit_node_again = match item.kind {
// For use/extern crate items, skip rewriting attributes but check for a skip attribute.
ast::ItemKind::Use(ref tree) => self.format_import(item, tree),
ast::ItemKind::Impl { .. } => {
let block_indent = self.block_indent;
- let rw = self.with_context(|ctx| format_impl(&ctx, item, block_indent));
+ let rw = self.with_context(|ctx| format_impl(ctx, item, block_indent));
self.push_rewrite(item.span, rw);
}
ast::ItemKind::Trait(..) => {
let block_indent = self.block_indent;
- let rw = self.with_context(|ctx| format_trait(&ctx, item, block_indent));
+ let rw = self.with_context(|ctx| format_trait(ctx, item, block_indent));
self.push_rewrite(item.span, rw);
}
ast::ItemKind::TraitAlias(ref generics, ref generic_bounds) => {
self.visit_static(&StaticParts::from_item(item));
}
ast::ItemKind::Fn(ref fn_kind) => {
- let ast::FnKind(defaultness, ref fn_signature, ref generics, ref block) =
- **fn_kind;
- if let Some(ref body) = block {
+ let ast::Fn {
+ defaultness,
+ ref sig,
+ ref generics,
+ ref body,
+ } = **fn_kind;
+ if let Some(ref body) = body {
let inner_attrs = inner_attributes(&item.attrs);
- let fn_ctxt = match fn_signature.header.ext {
+ let fn_ctxt = match sig.header.ext {
ast::Extern::None => visit::FnCtxt::Free,
_ => visit::FnCtxt::Foreign,
};
self.visit_fn(
- visit::FnKind::Fn(
- fn_ctxt,
- item.ident,
- &fn_signature,
- &item.vis,
- Some(body),
- ),
+ visit::FnKind::Fn(fn_ctxt, item.ident, &sig, &item.vis, Some(body)),
generics,
- &fn_signature.decl,
+ &sig.decl,
item.span,
defaultness,
Some(&inner_attrs),
} else {
let indent = self.block_indent;
let rewrite = self.rewrite_required_fn(
- indent,
- item.ident,
- &fn_signature,
- &item.vis,
- generics,
- item.span,
+ indent, item.ident, &sig, &item.vis, generics, item.span,
);
self.push_rewrite(item.span, rewrite);
}
}
- ast::ItemKind::TyAlias(ref alias_kind) => {
- let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref ty) =
- **alias_kind;
- match ty {
- Some(ty) => {
- let rewrite = rewrite_type(
- &self.get_context(),
- self.block_indent,
- item.ident,
- &item.vis,
- generics,
- Some(generic_bounds),
- Some(&*ty),
- item.span,
- );
- self.push_rewrite(item.span, rewrite);
- }
- None => {
- let rewrite = rewrite_opaque_type(
- &self.get_context(),
- self.block_indent,
- item.ident,
- generic_bounds,
- generics,
- &item.vis,
- item.span,
- );
- self.push_rewrite(item.span, rewrite);
- }
- }
+ ast::ItemKind::TyAlias(ref ty_alias) => {
+ use ItemVisitorKind::Item;
+ self.visit_ty_alias_kind(ty_alias, &Item(&item), item.span);
}
ast::ItemKind::GlobalAsm(..) => {
let snippet = Some(self.snippet(item.span).to_owned());
self.skip_context = skip_context_saved;
}
- pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
- skip_out_of_file_lines_range_visitor!(self, ti.span);
+ fn visit_ty_alias_kind(
+ &mut self,
+ ty_kind: &ast::TyAlias,
+ visitor_kind: &ItemVisitorKind<'_>,
+ span: Span,
+ ) {
+ let rewrite = rewrite_type_alias(
+ ty_kind,
+ &self.get_context(),
+ self.block_indent,
+ visitor_kind,
+ span,
+ );
+ self.push_rewrite(span, rewrite);
+ }
+
+ fn visit_assoc_item(&mut self, visitor_kind: &ItemVisitorKind<'_>) {
+ use ItemVisitorKind::*;
+ // TODO(calebcartwright): Not sure the skip spans are correct
+ let (ai, skip_span, assoc_ctxt) = match visitor_kind {
+ AssocTraitItem(ai) => (*ai, ai.span(), visit::AssocCtxt::Trait),
+ AssocImplItem(ai) => (*ai, ai.span, visit::AssocCtxt::Impl),
+ _ => unreachable!(),
+ };
+ skip_out_of_file_lines_range_visitor!(self, ai.span);
- if self.visit_attrs(&ti.attrs, ast::AttrStyle::Outer) {
- self.push_skipped_with_span(ti.attrs.as_slice(), ti.span(), ti.span());
+ if self.visit_attrs(&ai.attrs, ast::AttrStyle::Outer) {
+ self.push_skipped_with_span(&ai.attrs.as_slice(), skip_span, skip_span);
return;
}
// TODO(calebcartwright): consider enabling box_patterns feature gate
- match ti.kind {
- ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_trait_item(ti)),
- ast::AssocItemKind::Fn(ref fn_kind) => {
- let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind;
- if let Some(ref body) = block {
- let inner_attrs = inner_attributes(&ti.attrs);
- let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait);
+ match (&ai.kind, visitor_kind) {
+ (ast::AssocItemKind::Const(..), AssocTraitItem(_)) => {
+ self.visit_static(&StaticParts::from_trait_item(&ai))
+ }
+ (ast::AssocItemKind::Const(..), AssocImplItem(_)) => {
+ self.visit_static(&StaticParts::from_impl_item(&ai))
+ }
+ (ast::AssocItemKind::Fn(ref fn_kind), _) => {
+ let ast::Fn {
+ defaultness,
+ ref sig,
+ ref generics,
+ ref body,
+ } = **fn_kind;
+ if let Some(ref body) = body {
+ let inner_attrs = inner_attributes(&ai.attrs);
+ let fn_ctxt = visit::FnCtxt::Assoc(assoc_ctxt);
self.visit_fn(
- visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &ti.vis, Some(body)),
+ visit::FnKind::Fn(fn_ctxt, ai.ident, sig, &ai.vis, Some(body)),
generics,
&sig.decl,
- ti.span,
+ ai.span,
defaultness,
Some(&inner_attrs),
);
} else {
let indent = self.block_indent;
let rewrite =
- self.rewrite_required_fn(indent, ti.ident, sig, &ti.vis, generics, ti.span);
- self.push_rewrite(ti.span, rewrite);
+ self.rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span);
+ self.push_rewrite(ai.span, rewrite);
}
}
- ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
- let ast::TyAliasKind(_, ref generics, ref generic_bounds, ref type_default) =
- **ty_alias_kind;
- let rewrite = rewrite_type(
- &self.get_context(),
- self.block_indent,
- ti.ident,
- &ti.vis,
- generics,
- Some(generic_bounds),
- type_default.as_ref(),
- ti.span,
- );
- self.push_rewrite(ti.span, rewrite);
+ (ast::AssocItemKind::TyAlias(ref ty_alias), _) => {
+ self.visit_ty_alias_kind(ty_alias, visitor_kind, ai.span);
}
- ast::AssocItemKind::MacCall(ref mac) => {
- self.visit_mac(mac, Some(ti.ident), MacroPosition::Item);
+ (ast::AssocItemKind::MacCall(ref mac), _) => {
+ self.visit_mac(mac, Some(ai.ident), MacroPosition::Item);
}
+ _ => unreachable!(),
}
}
- pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) {
- skip_out_of_file_lines_range_visitor!(self, ii.span);
-
- if self.visit_attrs(&ii.attrs, ast::AttrStyle::Outer) {
- self.push_skipped_with_span(ii.attrs.as_slice(), ii.span, ii.span);
- return;
- }
+ pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) {
+ self.visit_assoc_item(&ItemVisitorKind::AssocTraitItem(ti));
+ }
- match ii.kind {
- ast::AssocItemKind::Fn(ref fn_kind) => {
- let ast::FnKind(defaultness, ref sig, ref generics, ref block) = **fn_kind;
- if let Some(ref body) = block {
- let inner_attrs = inner_attributes(&ii.attrs);
- let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Impl);
- self.visit_fn(
- visit::FnKind::Fn(fn_ctxt, ii.ident, sig, &ii.vis, Some(body)),
- generics,
- &sig.decl,
- ii.span,
- defaultness,
- Some(&inner_attrs),
- );
- } else {
- let indent = self.block_indent;
- let rewrite =
- self.rewrite_required_fn(indent, ii.ident, sig, &ii.vis, generics, ii.span);
- self.push_rewrite(ii.span, rewrite);
- }
- }
- ast::AssocItemKind::Const(..) => self.visit_static(&StaticParts::from_impl_item(ii)),
- ast::AssocItemKind::TyAlias(ref ty_alias_kind) => {
- let ast::TyAliasKind(defaultness, ref generics, _, ref ty) = **ty_alias_kind;
- self.push_rewrite(
- ii.span,
- rewrite_impl_type(
- ii.ident,
- &ii.vis,
- defaultness,
- ty.as_ref(),
- &generics,
- &self.get_context(),
- self.block_indent,
- ii.span,
- ),
- );
- }
- ast::AssocItemKind::MacCall(ref mac) => {
- self.visit_mac(mac, Some(ii.ident), MacroPosition::Item);
- }
- }
+ pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) {
+ self.visit_assoc_item(&ItemVisitorKind::AssocImplItem(ii));
}
fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option<symbol::Ident>, pos: MacroPosition) {
}
fn walk_mod_items(&mut self, items: &[rustc_ast::ptr::P<ast::Item>]) {
- self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&items));
+ self.visit_items_with_reordering(&ptr_vec_to_ref_vec(items));
}
fn walk_stmts(&mut self, stmts: &[Stmt<'_>], include_current_empty_semi: bool) {
--- /dev/null
+mod bar {
+ mod baz;}
\ No newline at end of file
--- /dev/null
+fn baz() { }
\ No newline at end of file
--- /dev/null
+fn main() {
+ println!("Hello, world!");
+}
+
+mod foo;
\ No newline at end of file
--- /dev/null
+// rustfmt-group_imports: One
+// rustfmt-imports_granularity: Crate
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+use std::sync::Arc;
+use alloc::vec::Vec;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
--- /dev/null
+// rustfmt-group_imports: One
+mod test {
+ use crate::foo::bar;
+
+ use std::path;
+ use crate::foo::bar2;
+}
--- /dev/null
+// rustfmt-group_imports: One
+// rustfmt-reorder_imports: false
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+use std::sync::Arc;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
--- /dev/null
+// rustfmt-group_imports: One
+use chrono::Utc;
+use super::update::convert_publish_payload;
+
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+
+use std::sync::Arc;
+
+use broker::database::PooledConnection;
+
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
--- /dev/null
+// rustfmt-brace_style: AlwaysNextLine
+// rustfmt-empty_item_single_line: false
+
+fn function()
+{
+
+}
+
+struct Struct
+{
+
+}
+
+enum Enum
+{
+
+}
+
+trait Trait
+{
+
+}
+
+impl<T> Trait for T
+{
+
+}
+
+trait Trait2<T>
+where
+ T: Copy + Display + Write + Read + FromStr, {}
+
+trait Trait3<T>
+where
+ T: Something
+ + SomethingElse
+ + Sync
+ + Send
+ + Display
+ + Debug
+ + Copy
+ + Hash
+ + Debug
+ + Display
+ + Write
+ + Read, {}
struct D<T> where T: Copy {}
}
+
+
+fn function()
+{
+
+}
+
+trait Trait
+{
+
+}
+
+impl<T> Trait for T
+{
+
+}
+
+trait Trait2<T>
+where
+ T: Copy + Display + Write + Read + FromStr, {}
+
+trait Trait3<T>
+where
+ T: Something
+ + SomethingElse
+ + Sync
+ + Send
+ + Display
+ + Debug
+ + Copy
+ + Hash
+ + Debug
+ + Display
+ + Write
+ + Read, {}
--- /dev/null
+// rustfmt-group_imports: One
+// rustfmt-imports_granularity: Crate
+use super::{
+ schema::{Context, Payload},
+ update::convert_publish_payload,
+};
+use crate::models::Event;
+use alloc::{alloc::Layout, vec::Vec};
+use broker::database::PooledConnection;
+use chrono::Utc;
+use core::f32;
+use juniper::{FieldError, FieldResult};
+use std::sync::Arc;
+use uuid::Uuid;
--- /dev/null
+// rustfmt-group_imports: One
+mod test {
+ use crate::foo::bar;
+ use crate::foo::bar2;
+ use std::path;
+}
--- /dev/null
+// rustfmt-group_imports: One
+// rustfmt-reorder_imports: false
+use chrono::Utc;
+use super::update::convert_publish_payload;
+use juniper::{FieldError, FieldResult};
+use uuid::Uuid;
+use alloc::alloc::Layout;
+use std::sync::Arc;
+use broker::database::PooledConnection;
+use super::schema::{Context, Payload};
+use core::f32;
+use crate::models::Event;
--- /dev/null
+// rustfmt-group_imports: One
+use super::schema::{Context, Payload};
+use super::update::convert_publish_payload;
+use crate::models::Event;
+use alloc::alloc::Layout;
+use broker::database::PooledConnection;
+use chrono::Utc;
+use core::f32;
+use juniper::{FieldError, FieldResult};
+use std::sync::Arc;
+use uuid::Uuid;
--- /dev/null
+// rustfmt-brace_style: AlwaysNextLine
+// rustfmt-empty_item_single_line: false
+
+fn function()
+{
+}
+
+struct Struct {}
+
+enum Enum {}
+
+trait Trait
+{
+}
+
+impl<T> Trait for T
+{
+}
+
+trait Trait2<T>
+where
+ T: Copy + Display + Write + Read + FromStr,
+{
+}
+
+trait Trait3<T>
+where
+ T: Something
+ + SomethingElse
+ + Sync
+ + Send
+ + Display
+ + Debug
+ + Copy
+ + Hash
+ + Debug
+ + Display
+ + Write
+ + Read,
+{
+}
--- /dev/null
+// rustfmt-trailing_comma: Always
+
+pub struct Matrix<T, const R: usize, const C: usize,>
+where
+ [T; R * C]:,
+{
+ contents: [T; R * C],
+}
--- /dev/null
+// rustfmt-trailing_comma: Never
+
+pub struct Matrix<T, const R: usize, const C: usize>
+where
+ [T; R * C]:
+{
+ contents: [T; R * C]
+}
--- /dev/null
+// leading comment
+
+#![rustfmt::skip]
+fn main() {
+ println!("main"); // commented
+}
+
+// post comment
--- /dev/null
+#![rustfmt::skip]
+
+mod a {
+ mod b {
+
+ }
+
+ // trailing comment b
+}
+
+// trailing comment a
--- /dev/null
+impl ThisIsALongStructNameToPushTheWhereToWrapLolololol where
+ [(); this_is_a_long_const_function_name()]:
+{
+}
where
T: Copy, {}
}
+
+fn function() {}
+
+trait Trait {}
+
+impl<T> Trait for T {}
+
+trait Trait2<T>
+where
+ T: Copy + Display + Write + Read + FromStr,
+{
+}
+
+trait Trait3<T>
+where
+ T: Something
+ + SomethingElse
+ + Sync
+ + Send
+ + Display
+ + Debug
+ + Copy
+ + Hash
+ + Debug
+ + Display
+ + Write
+ + Read,
+{
+}
&src_path.join("test/ui"),
&src_path.join("test/ui-fulldeps"),
&src_path.join("test/rustdoc-ui"),
+ &src_path.join("test/rustdoc"),
],
&mut |path| super::filter_dirs(path),
&mut |entry, contents| {
const ENTRY_LIMIT: usize = 1000;
// FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 1331;
-const ISSUES_ENTRY_LIMIT: usize = 2488;
+const ROOT_ENTRY_LIMIT: usize = 1275;
+const ISSUES_ENTRY_LIMIT: usize = 2310;
fn check_entries(path: &Path, bad: &mut bool) {
let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
allow-unauthenticated = [
"C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*", "F-*",
"D-*",
+ "needs-fcp",
+ "relnotes",
"requires-nightly",
"regression-*",
"perf-*",