Auto merge of #77517 - JohnTitor:rollup-msbd49e, r=JohnTitor

Rollup of 11 pull requests

Successful merges:

 - #75143 (Use `tracing` spans to trace the entire MIR interp stack)
 - #75699 (Uplift drop-bounds lint from clippy)
 - #76768 (Test and reject out-of-bounds shuffle vectors)
 - #77190 (updated p! macro to accept literals)
 - #77388 (Add some regression tests)
 - #77419 (Create E0777 error code for invalid argument in derive)
 - #77447 (BTreeMap: document DrainFilterInner better)
 - #77468 (Fix test name)
 - #77469 (Improve rustdoc error for failed intra-doc link resolution)
 - #77473 (Make --all-targets in x.py check opt-in)
 - #77508 (Fix capitalization in blog post name)

Failed merges:

r? `@ghost`
This commit is contained in:
bors 2020-10-04 04:33:28 +00:00
commit 2251766944
53 changed files with 865 additions and 330 deletions

View File

@ -1726,15 +1726,6 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "log_settings"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd"
dependencies = [
"lazy_static",
]
[[package]]
name = "lsp-codec"
version = "0.1.2"
@ -3523,6 +3514,7 @@ dependencies = [
"rustc_target",
"tracing",
"tracing-subscriber",
"tracing-tree",
"winapi 0.3.9",
]
@ -3810,7 +3802,6 @@ version = "0.0.0"
dependencies = [
"either",
"itertools 0.9.0",
"log_settings",
"polonius-engine",
"regex",
"rustc_apfloat",
@ -5105,9 +5096,9 @@ dependencies = [
[[package]]
name = "tracing-tree"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1a3dc4774db3a6b2d66a4f8d8de670e874ec3ed55615860c994927419b32c5f"
checksum = "43aac8afb493b08e1e1904956f7407c1e671b9c83b26a17e1bd83d6a3520e350"
dependencies = [
"ansi_term 0.12.1",
"atty",

View File

@ -90,7 +90,7 @@ Compatibility Notes
Internal Only
--------
- [Improved default settings for bootstrapping in `x.py`.][73964] You can read details about this change in the ["Changes To `x.py` Defaults"](https://blog.rust-lang.org/inside-rust/2020/08/30/changes-to-x-py-defaults.html) post on the Inside Rust blog.
- [Improved default settings for bootstrapping in `x.py`.][73964] You can read details about this change in the ["Changes to `x.py` defaults"](https://blog.rust-lang.org/inside-rust/2020/08/30/changes-to-x-py-defaults.html) post on the Inside Rust blog.
[1.47.0-cfg]: https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard
[75048]: https://github.com/rust-lang/rust/pull/75048/

View File

@ -11,6 +11,7 @@ crate-type = ["dylib"]
libc = "0.2"
tracing = { version = "0.1.18" }
tracing-subscriber = { version = "0.2.10", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
tracing-tree = "0.1.6"
rustc_middle = { path = "../rustc_middle" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_target = { path = "../rustc_target" }

View File

@ -1251,11 +1251,21 @@ pub fn init_env_logger(env: &str) {
Ok(s) if s.is_empty() => return,
Ok(_) => {}
}
let builder = tracing_subscriber::FmtSubscriber::builder();
let filter = tracing_subscriber::EnvFilter::from_env(env);
let layer = tracing_tree::HierarchicalLayer::default()
.with_indent_lines(true)
.with_ansi(true)
.with_targets(true)
.with_thread_ids(true)
.with_thread_names(true)
.with_wraparound(10)
.with_verbose_exit(true)
.with_verbose_entry(true)
.with_indent_amount(2);
let builder = builder.with_env_filter(tracing_subscriber::EnvFilter::from_env(env));
builder.init()
use tracing_subscriber::layer::SubscriberExt;
let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer);
tracing::subscriber::set_global_default(subscriber).unwrap();
}
pub fn main() -> ! {

View File

@ -459,6 +459,7 @@ E0773: include_str!("./error_codes/E0773.md"),
E0774: include_str!("./error_codes/E0774.md"),
E0775: include_str!("./error_codes/E0775.md"),
E0776: include_str!("./error_codes/E0776.md"),
E0777: include_str!("./error_codes/E0777.md"),
;
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard

View File

@ -0,0 +1,19 @@
A literal value was used inside `#[derive]`.
Erroneous code example:
```compile_fail,E0777
#[derive("Clone")] // error!
struct Foo;
```
Only paths to traits are allowed as argument inside `#[derive]`. You can find
more information about the `#[derive]` attribute in the [Rust Book].
```
#[derive(Clone)] // ok!
struct Foo;
```
[Rust Book]: https://doc.rust-lang.org/book/appendix-03-derivable-traits.html

View File

@ -18,7 +18,7 @@ use rustc_ast_pretty::pprust;
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
use rustc_data_structures::map_in_place::MapInPlace;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::{Applicability, PResult};
use rustc_errors::{struct_span_err, Applicability, PResult};
use rustc_feature::Features;
use rustc_parse::parser::Parser;
use rustc_parse::validate_attr;
@ -542,7 +542,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
fn error_derive_forbidden_on_non_adt(&self, derives: &[Path], item: &Annotatable) {
let attr = self.cx.sess.find_by_name(item.attrs(), sym::derive);
let span = attr.map_or(item.span(), |attr| attr.span);
let mut err = rustc_errors::struct_span_err!(
let mut err = struct_span_err!(
self.cx.sess,
span,
E0774,

View File

@ -5,7 +5,8 @@ use rustc_ast::token;
use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_ast::{self as ast, *};
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, ErrorReported};
use rustc_errors::{struct_span_err, Applicability, ErrorReported};
use rustc_lexer::is_ident;
use rustc_parse::nt_to_tokenstream;
use rustc_span::symbol::sym;
use rustc_span::{Span, DUMMY_SP};
@ -182,9 +183,22 @@ crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>)
.filter_map(|nmi| match nmi {
NestedMetaItem::Literal(lit) => {
error_reported_filter_map = true;
cx.struct_span_err(lit.span, "expected path to a trait, found literal")
.help("for example, write `#[derive(Debug)]` for `Debug`")
.emit();
let mut err = struct_span_err!(
cx.sess,
lit.span,
E0777,
"expected path to a trait, found literal",
);
let token = lit.token.to_string();
if token.starts_with('"')
&& token.len() > 2
&& is_ident(&token[1..token.len() - 1])
{
err.help(&format!("try using `#[derive({})]`", &token[1..token.len() - 1]));
} else {
err.help("for example, write `#[derive(Debug)]` for `Debug`");
}
err.emit();
None
}
NestedMetaItem::MetaItem(mi) => Some(mi),

View File

@ -53,6 +53,7 @@ mod non_ascii_idents;
mod nonstandard_style;
mod passes;
mod redundant_semicolon;
mod traits;
mod types;
mod unused;
@ -75,6 +76,7 @@ use internal::*;
use non_ascii_idents::*;
use nonstandard_style::*;
use redundant_semicolon::*;
use traits::*;
use types::*;
use unused::*;
@ -157,6 +159,7 @@ macro_rules! late_lint_passes {
MissingDebugImplementations: MissingDebugImplementations::default(),
ArrayIntoIter: ArrayIntoIter,
ClashingExternDeclarations: ClashingExternDeclarations::new(),
DropTraitConstraints: DropTraitConstraints,
]
);
};

View File

@ -0,0 +1,79 @@
use crate::LateContext;
use crate::LateLintPass;
use crate::LintContext;
use rustc_hir as hir;
use rustc_span::symbol::sym;
declare_lint! {
/// The `drop_bounds` lint checks for generics with `std::ops::Drop` as
/// bounds.
///
/// ### Example
///
/// ```rust
/// fn foo<T: Drop>() {}
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// `Drop` bounds do not really accomplish anything. A type may have
/// compiler-generated drop glue without implementing the `Drop` trait
/// itself. The `Drop` trait also only has one method, `Drop::drop`, and
/// that function is by fiat not callable in user code. So there is really
/// no use case for using `Drop` in trait bounds.
///
/// The most likely use case of a drop bound is to distinguish between
/// types that have destructors and types that don't. Combined with
/// specialization, a naive coder would write an implementation that
/// assumed a type could be trivially dropped, then write a specialization
/// for `T: Drop` that actually calls the destructor. Except that doing so
/// is not correct; String, for example, doesn't actually implement Drop,
/// but because String contains a Vec, assuming it can be trivially dropped
/// will leak memory.
pub DROP_BOUNDS,
Warn,
"bounds of the form `T: Drop` are useless"
}
declare_lint_pass!(
/// Lint for bounds of the form `T: Drop`, which usually
/// indicate an attempt to emulate `std::mem::needs_drop`.
DropTraitConstraints => [DROP_BOUNDS]
);
impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
use rustc_middle::ty::PredicateAtom::*;
let def_id = cx.tcx.hir().local_def_id(item.hir_id);
let predicates = cx.tcx.explicit_predicates_of(def_id);
for &(predicate, span) in predicates.predicates {
let trait_predicate = match predicate.skip_binders() {
Trait(trait_predicate, _constness) => trait_predicate,
_ => continue,
};
let def_id = trait_predicate.trait_ref.def_id;
if cx.tcx.lang_items().drop_trait() == Some(def_id) {
// Explicitly allow `impl Drop`, a drop-guards-as-Voldemort-type pattern.
if trait_predicate.trait_ref.self_ty().is_impl_trait() {
continue;
}
cx.struct_span_lint(DROP_BOUNDS, span, |lint| {
let needs_drop = match cx.tcx.get_diagnostic_item(sym::needs_drop) {
Some(needs_drop) => needs_drop,
None => return,
};
let msg = format!(
"bounds on `{}` are useless, consider instead \
using `{}` to detect if a type has a destructor",
predicate,
cx.tcx.def_path_str(needs_drop)
);
lint.build(&msg).emit()
});
}
}
}
}

View File

@ -28,6 +28,9 @@ use std::ops::{Deref, DerefMut};
use super::*;
macro_rules! p {
(@$lit:literal) => {
write!(scoped_cx!(), $lit)?
};
(@write($($data:expr),+)) => {
write!(scoped_cx!(), $($data),+)?
};
@ -37,8 +40,8 @@ macro_rules! p {
(@$method:ident($($arg:expr),*)) => {
scoped_cx!() = scoped_cx!().$method($($arg),*)?
};
($($kind:ident $data:tt),+) => {{
$(p!(@$kind $data);)+
($($elem:tt $(($($args:tt)*))?),+) => {{
$(p!(@ $elem $(($($args)*))?);)+
}};
}
macro_rules! define_scoped_cx {
@ -478,7 +481,7 @@ pub trait PrettyPrinter<'tcx>:
p!(print(self_ty));
if let Some(trait_ref) = trait_ref {
p!(write(" as "), print(trait_ref.print_only_trait_path()));
p!(" as ", print(trait_ref.print_only_trait_path()));
}
Ok(cx)
})
@ -495,9 +498,9 @@ pub trait PrettyPrinter<'tcx>:
self.generic_delimiters(|mut cx| {
define_scoped_cx!(cx);
p!(write("impl "));
p!("impl ");
if let Some(trait_ref) = trait_ref {
p!(print(trait_ref.print_only_trait_path()), write(" for "));
p!(print(trait_ref.print_only_trait_path()), " for ");
}
p!(print(self_ty));
@ -509,8 +512,8 @@ pub trait PrettyPrinter<'tcx>:
define_scoped_cx!(self);
match *ty.kind() {
ty::Bool => p!(write("bool")),
ty::Char => p!(write("char")),
ty::Bool => p!("bool"),
ty::Char => p!("char"),
ty::Int(t) => p!(write("{}", t.name_str())),
ty::Uint(t) => p!(write("{}", t.name_str())),
ty::Float(t) => p!(write("{}", t.name_str())),
@ -525,23 +528,23 @@ pub trait PrettyPrinter<'tcx>:
p!(print(tm.ty))
}
ty::Ref(r, ty, mutbl) => {
p!(write("&"));
p!("&");
if self.region_should_not_be_omitted(r) {
p!(print(r), write(" "));
p!(print(r), " ");
}
p!(print(ty::TypeAndMut { ty, mutbl }))
}
ty::Never => p!(write("!")),
ty::Never => p!("!"),
ty::Tuple(ref tys) => {
p!(write("("), comma_sep(tys.iter()));
p!("(", comma_sep(tys.iter()));
if tys.len() == 1 {
p!(write(","));
p!(",");
}
p!(write(")"))
p!(")")
}
ty::FnDef(def_id, substs) => {
let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs);
p!(print(sig), write(" {{"), print_value_path(def_id, substs), write("}}"));
p!(print(sig), " {{", print_value_path(def_id, substs), "}}");
}
ty::FnPtr(ref bare_fn) => p!(print(bare_fn)),
ty::Infer(infer_ty) => {
@ -555,7 +558,7 @@ pub trait PrettyPrinter<'tcx>:
p!(write("{}", infer_ty))
}
}
ty::Error(_) => p!(write("[type error]")),
ty::Error(_) => p!("[type error]"),
ty::Param(ref param_ty) => p!(write("{}", param_ty)),
ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
@ -567,11 +570,11 @@ pub trait PrettyPrinter<'tcx>:
ty::Dynamic(data, r) => {
let print_r = self.region_should_not_be_omitted(r);
if print_r {
p!(write("("));
p!("(");
}
p!(write("dyn "), print(data));
p!("dyn ", print(data));
if print_r {
p!(write(" + "), print(r), write(")"));
p!(" + ", print(r), ")");
}
}
ty::Foreign(def_id) => {
@ -597,7 +600,7 @@ pub trait PrettyPrinter<'tcx>:
p!(write("{}", name));
// FIXME(eddyb) print this with `print_def_path`.
if !substs.is_empty() {
p!(write("::"));
p!("::");
p!(generic_delimiters(|cx| cx.comma_sep(substs.iter())));
}
return Ok(self);
@ -608,7 +611,7 @@ pub trait PrettyPrinter<'tcx>:
let mut first = true;
let mut is_sized = false;
p!(write("impl"));
p!("impl");
for predicate in bounds.predicates {
// Note: We can't use `to_opt_poly_trait_ref` here as `predicate`
// may contain unbound variables. We therefore do this manually.
@ -634,21 +637,21 @@ pub trait PrettyPrinter<'tcx>:
if !is_sized {
p!(write("{}?Sized", if first { " " } else { "+" }));
} else if first {
p!(write(" Sized"));
p!(" Sized");
}
Ok(self)
})?);
}
ty::Str => p!(write("str")),
ty::Str => p!("str"),
ty::Generator(did, substs, movability) => {
p!(write("["));
match movability {
hir::Movability::Movable => {}
hir::Movability::Static => p!(write("static ")),
hir::Movability::Static => p!("static "),
}
if !self.tcx().sess.verbose() {
p!(write("generator"));
p!("generator");
// FIXME(eddyb) should use `def_span`.
if let Some(did) = did.as_local() {
let hir_id = self.tcx().hir().local_def_id_to_hir_id(did);
@ -661,7 +664,7 @@ pub trait PrettyPrinter<'tcx>:
p!(print_def_path(did, substs));
if substs.as_generator().is_valid() {
// Search for the first inference variable
p!(write(" upvar_tys=("));
p!(" upvar_tys=(");
let mut uninferred_ty =
substs.as_generator().upvar_tys().filter(|ty| ty.is_ty_infer());
if uninferred_ty.next().is_some() {
@ -669,15 +672,15 @@ pub trait PrettyPrinter<'tcx>:
} else {
self = self.comma_sep(substs.as_generator().upvar_tys())?;
}
p!(write(")"));
p!(")");
}
}
if substs.as_generator().is_valid() {
p!(write(" "), print(substs.as_generator().witness()));
p!(" ", print(substs.as_generator().witness()));
}
p!(write("]"));
p!("]")
}
ty::GeneratorWitness(types) => {
p!(in_binder(&types));
@ -690,7 +693,7 @@ pub trait PrettyPrinter<'tcx>:
if let Some(did) = did.as_local() {
let hir_id = self.tcx().hir().local_def_id_to_hir_id(did);
if self.tcx().sess.opts.debugging_opts.span_free_formats {
p!(write("@"), print_def_path(did.to_def_id(), substs));
p!("@", print_def_path(did.to_def_id(), substs));
} else {
let span = self.tcx().hir().span(hir_id);
p!(write("@{}", self.tcx().sess.source_map().span_to_string(span)));
@ -707,40 +710,40 @@ pub trait PrettyPrinter<'tcx>:
if uninferred_ty.next().is_some() {
// If the upvar substs contain an inference variable we haven't
// finished capture analysis.
p!(write(" closure_substs=(unavailable)"));
p!(" closure_substs=(unavailable)");
} else {
p!(write(" closure_kind_ty="), print(substs.as_closure().kind_ty()));
p!(" closure_kind_ty=", print(substs.as_closure().kind_ty()));
p!(
write(" closure_sig_as_fn_ptr_ty="),
" closure_sig_as_fn_ptr_ty=",
print(substs.as_closure().sig_as_fn_ptr_ty())
);
p!(write(" upvar_tys=("));
p!(" upvar_tys=(");
self = self.comma_sep(substs.as_closure().upvar_tys())?;
p!(write(")"));
p!(")");
}
}
}
p!(write("]"));
p!("]");
}
ty::Array(ty, sz) => {
p!(write("["), print(ty), write("; "));
p!("[", print(ty), "; ");
if self.tcx().sess.verbose() {
p!(write("{:?}", sz));
} else if let ty::ConstKind::Unevaluated(..) = sz.val {
// Do not try to evaluate unevaluated constants. If we are const evaluating an
// array length anon const, rustc will (with debug assertions) print the
// constant's path. Which will end up here again.
p!(write("_"));
p!("_");
} else if let Some(n) = sz.val.try_to_bits(self.tcx().data_layout.pointer_size) {
p!(write("{}", n));
} else if let ty::ConstKind::Param(param) = sz.val {
p!(write("{}", param));
} else {
p!(write("_"));
p!("_");
}
p!(write("]"))
p!("]")
}
ty::Slice(ty) => p!(write("["), print(ty), write("]")),
ty::Slice(ty) => p!("[", print(ty), "]"),
}
Ok(self)
@ -847,7 +850,7 @@ pub trait PrettyPrinter<'tcx>:
for (_, def_id) in auto_traits {
if !first {
p!(write(" + "));
p!(" + ");
}
first = false;
@ -865,16 +868,16 @@ pub trait PrettyPrinter<'tcx>:
) -> Result<Self, Self::Error> {
define_scoped_cx!(self);
p!(write("("), comma_sep(inputs.iter().copied()));
p!("(", comma_sep(inputs.iter().copied()));
if c_variadic {
if !inputs.is_empty() {
p!(write(", "));
p!(", ");
}
p!(write("..."));
p!("...");
}
p!(write(")"));
p!(")");
if !output.is_unit() {
p!(write(" -> "), print(output));
p!(" -> ", print(output));
}
Ok(self)
@ -945,7 +948,7 @@ pub trait PrettyPrinter<'tcx>:
self.pretty_print_bound_var(debruijn, bound_var)?
}
ty::ConstKind::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)),
ty::ConstKind::Error(_) => p!(write("[const error]")),
ty::ConstKind::Error(_) => p!("[const error]"),
};
Ok(self)
}
@ -987,17 +990,17 @@ pub trait PrettyPrinter<'tcx>:
{
p!(pretty_print_byte_str(byte_str))
} else {
p!(write("<too short allocation>"))
p!("<too short allocation>")
}
}
// FIXME: for statics and functions, we could in principle print more detail.
Some(GlobalAlloc::Static(def_id)) => p!(write("<static({:?})>", def_id)),
Some(GlobalAlloc::Function(_)) => p!(write("<function>")),
None => p!(write("<dangling pointer>")),
Some(GlobalAlloc::Function(_)) => p!("<function>"),
None => p!("<dangling pointer>"),
},
// Bool
(Scalar::Raw { data: 0, .. }, ty::Bool) => p!(write("false")),
(Scalar::Raw { data: 1, .. }, ty::Bool) => p!(write("true")),
(Scalar::Raw { data: 0, .. }, ty::Bool) => p!("false"),
(Scalar::Raw { data: 1, .. }, ty::Bool) => p!("true"),
// Float
(Scalar::Raw { data, .. }, ty::Float(ast::FloatTy::F32)) => {
p!(write("{}f32", Single::from_bits(data)))
@ -1093,13 +1096,13 @@ pub trait PrettyPrinter<'tcx>:
fn pretty_print_byte_str(mut self, byte_str: &'tcx [u8]) -> Result<Self::Const, Self::Error> {
define_scoped_cx!(self);
p!(write("b\""));
p!("b\"");
for &c in byte_str {
for e in std::ascii::escape_default(c) {
self.write_char(e as char)?;
}
}
p!(write("\""));
p!("\"");
Ok(self)
}
@ -1112,7 +1115,7 @@ pub trait PrettyPrinter<'tcx>:
define_scoped_cx!(self);
if self.tcx().sess.verbose() {
p!(write("ConstValue({:?}: ", ct), print(ty), write(")"));
p!(write("ConstValue({:?}: ", ct), print(ty), ")");
return Ok(self);
}
@ -1149,7 +1152,7 @@ pub trait PrettyPrinter<'tcx>:
let ptr = Pointer::new(AllocId(0), offset);
let byte_str = alloc.get_bytes(&self.tcx(), ptr, n).unwrap();
p!(write("*"));
p!("*");
p!(pretty_print_byte_str(byte_str));
Ok(self)
}
@ -1173,14 +1176,14 @@ pub trait PrettyPrinter<'tcx>:
match *ty.kind() {
ty::Array(..) => {
p!(write("["), comma_sep(fields), write("]"));
p!("[", comma_sep(fields), "]");
}
ty::Tuple(..) => {
p!(write("("), comma_sep(fields));
p!("(", comma_sep(fields));
if contents.fields.len() == 1 {
p!(write(","));
p!(",");
}
p!(write(")"));
p!(")");
}
ty::Adt(def, substs) if def.variants.is_empty() => {
p!(print_value_path(def.did, substs));
@ -1194,19 +1197,19 @@ pub trait PrettyPrinter<'tcx>:
match variant_def.ctor_kind {
CtorKind::Const => {}
CtorKind::Fn => {
p!(write("("), comma_sep(fields), write(")"));
p!("(", comma_sep(fields), ")");
}
CtorKind::Fictive => {
p!(write(" {{ "));
p!(" {{ ");
let mut first = true;
for (field_def, field) in variant_def.fields.iter().zip(fields) {
if !first {
p!(write(", "));
p!(", ");
}
p!(write("{}: ", field_def.ident), print(field));
first = false;
}
p!(write(" }}"));
p!(" }}");
}
}
}
@ -1224,7 +1227,7 @@ pub trait PrettyPrinter<'tcx>:
// fallback
p!(write("{:?}", ct));
if print_ty {
p!(write(": "), print(ty));
p!(": ", print(ty));
}
Ok(self)
}
@ -1637,7 +1640,7 @@ impl<F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> {
if this.print_alloc_ids {
p!(write("{:?}", p));
} else {
p!(write("&_"));
p!("&_");
}
Ok(this)
};
@ -1703,11 +1706,11 @@ impl<F: fmt::Write> FmtPrinter<'_, '_, F> {
ty::ReVar(_) => {}
ty::ReErased => {}
ty::ReStatic => {
p!(write("'static"));
p!("'static");
return Ok(self);
}
ty::ReEmpty(ty::UniverseIndex::ROOT) => {
p!(write("'<empty>"));
p!("'<empty>");
return Ok(self);
}
ty::ReEmpty(ui) => {
@ -1716,7 +1719,7 @@ impl<F: fmt::Write> FmtPrinter<'_, '_, F> {
}
}
p!(write("'_"));
p!("'_");
Ok(self)
}
@ -1847,7 +1850,7 @@ where
type Error = P::Error;
fn print(&self, mut cx: P) -> Result<Self::Output, Self::Error> {
define_scoped_cx!(cx);
p!(print(self.0), write(": "), print(self.1));
p!(print(self.0), ": ", print(self.1));
Ok(cx)
}
}
@ -1945,7 +1948,7 @@ define_print_and_forward_display! {
(self, cx):
&'tcx ty::List<Ty<'tcx>> {
p!(write("{{"), comma_sep(self.iter()), write("}}"))
p!("{{", comma_sep(self.iter()), "}}")
}
ty::TypeAndMut<'tcx> {
@ -1981,7 +1984,7 @@ define_print_and_forward_display! {
p!(write("extern {} ", self.abi));
}
p!(write("fn"), pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
p!("fn", pretty_fn_sig(self.inputs(), self.c_variadic, self.output()));
}
ty::InferTy {
@ -1990,7 +1993,7 @@ define_print_and_forward_display! {
return Ok(cx);
}
match *self {
ty::TyVar(_) => p!(write("_")),
ty::TyVar(_) => p!("_"),
ty::IntVar(_) => p!(write("{}", "{integer}")),
ty::FloatVar(_) => p!(write("{}", "{float}")),
ty::FreshTy(v) => p!(write("FreshTy({})", v)),
@ -2016,16 +2019,16 @@ define_print_and_forward_display! {
}
ty::SubtypePredicate<'tcx> {
p!(print(self.a), write(" <: "), print(self.b))
p!(print(self.a), " <: ", print(self.b))
}
ty::TraitPredicate<'tcx> {
p!(print(self.trait_ref.self_ty()), write(": "),
p!(print(self.trait_ref.self_ty()), ": ",
print(self.trait_ref.print_only_trait_path()))
}
ty::ProjectionPredicate<'tcx> {
p!(print(self.projection_ty), write(" == "), print(self.ty))
p!(print(self.projection_ty), " == ", print(self.ty))
}
ty::ProjectionTy<'tcx> {
@ -2034,9 +2037,9 @@ define_print_and_forward_display! {
ty::ClosureKind {
match *self {
ty::ClosureKind::Fn => p!(write("Fn")),
ty::ClosureKind::FnMut => p!(write("FnMut")),
ty::ClosureKind::FnOnce => p!(write("FnOnce")),
ty::ClosureKind::Fn => p!("Fn"),
ty::ClosureKind::FnMut => p!("FnMut"),
ty::ClosureKind::FnOnce => p!("FnOnce"),
}
}
@ -2051,7 +2054,7 @@ define_print_and_forward_display! {
match *self {
ty::PredicateAtom::Trait(ref data, constness) => {
if let hir::Constness::Const = constness {
p!(write("const "));
p!("const ");
}
p!(print(data))
}
@ -2059,33 +2062,23 @@ define_print_and_forward_display! {
ty::PredicateAtom::RegionOutlives(predicate) => p!(print(predicate)),
ty::PredicateAtom::TypeOutlives(predicate) => p!(print(predicate)),
ty::PredicateAtom::Projection(predicate) => p!(print(predicate)),
ty::PredicateAtom::WellFormed(arg) => p!(print(arg), write(" well-formed")),
ty::PredicateAtom::WellFormed(arg) => p!(print(arg), " well-formed"),
ty::PredicateAtom::ObjectSafe(trait_def_id) => {
p!(write("the trait `"),
print_def_path(trait_def_id, &[]),
write("` is object-safe"))
p!("the trait `", print_def_path(trait_def_id, &[]), "` is object-safe")
}
ty::PredicateAtom::ClosureKind(closure_def_id, _closure_substs, kind) => {
p!(write("the closure `"),
p!("the closure `",
print_value_path(closure_def_id, &[]),
write("` implements the trait `{}`", kind))
}
ty::PredicateAtom::ConstEvaluatable(def, substs) => {
p!(write("the constant `"),
print_value_path(def.did, substs),
write("` can be evaluated"))
p!("the constant `", print_value_path(def.did, substs), "` can be evaluated")
}
ty::PredicateAtom::ConstEquate(c1, c2) => {
p!(write("the constant `"),
print(c1),
write("` equals `"),
print(c2),
write("`"))
p!("the constant `", print(c1), "` equals `", print(c2), "`")
}
ty::PredicateAtom::TypeWellFormedFromEnv(ty) => {
p!(write("the type `"),
print(ty),
write("` is found in the environment"))
p!("the type `", print(ty), "` is found in the environment")
}
}
}

View File

@ -12,7 +12,6 @@ either = "1.5.0"
rustc_graphviz = { path = "../rustc_graphviz" }
itertools = "0.9"
tracing = "0.1"
log_settings = "0.1.1"
polonius-engine = "0.12.0"
regex = "1"
rustc_middle = { path = "../rustc_middle" }

View File

@ -48,8 +48,41 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Pointer<M::PointerTag>>,
}
// The Phantomdata exists to prevent this type from being `Send`. If it were sent across a thread
// boundary and dropped in the other thread, it would exit the span in the other thread.
struct SpanGuard(tracing::Span, std::marker::PhantomData<*const u8>);
impl SpanGuard {
/// By default a `SpanGuard` does nothing.
fn new() -> Self {
Self(tracing::Span::none(), std::marker::PhantomData)
}
/// If a span is entered, we exit the previous span (if any, normally none) and enter the
/// new span. This is mainly so we don't have to use `Option` for the `tracing_span` field of
/// `Frame` by creating a dummy span to being with and then entering it once the frame has
/// been pushed.
fn enter(&mut self, span: tracing::Span) {
// This executes the destructor on the previous instance of `SpanGuard`, ensuring that
// we never enter or exit more spans than vice versa. Unless you `mem::leak`, then we
// can't protect the tracing stack, but that'll just lead to weird logging, no actual
// problems.
*self = Self(span, std::marker::PhantomData);
self.0.with_subscriber(|(id, dispatch)| {
dispatch.enter(id);
});
}
}
impl Drop for SpanGuard {
fn drop(&mut self) {
self.0.with_subscriber(|(id, dispatch)| {
dispatch.exit(id);
});
}
}
/// A stack frame.
#[derive(Clone)]
pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> {
////////////////////////////////////////////////////////////////////////////////
// Function and callsite information
@ -80,6 +113,11 @@ pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> {
/// can either directly contain `Scalar` or refer to some part of an `Allocation`.
pub locals: IndexVec<mir::Local, LocalState<'tcx, Tag>>,
/// The span of the `tracing` crate is stored here.
/// When the guard is dropped, the span is exited. This gives us
/// a full stack trace on all tracing statements.
tracing_span: SpanGuard,
////////////////////////////////////////////////////////////////////////////////
// Current position within the function
////////////////////////////////////////////////////////////////////////////////
@ -184,6 +222,7 @@ impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> {
locals: self.locals,
loc: self.loc,
extra,
tracing_span: self.tracing_span,
}
}
}
@ -637,11 +676,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
return_place: Option<PlaceTy<'tcx, M::PointerTag>>,
return_to_block: StackPopCleanup,
) -> InterpResult<'tcx> {
if !self.stack().is_empty() {
info!("PAUSING({}) {}", self.frame_idx(), self.frame().instance);
}
::log_settings::settings().indentation += 1;
// first push a stack frame so we have access to the local substs
let pre_frame = Frame {
body,
@ -652,6 +686,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// all methods actually know about the frame
locals: IndexVec::new(),
instance,
tracing_span: SpanGuard::new(),
extra: (),
};
let frame = M::init_frame_extra(self, pre_frame)?;
@ -696,7 +731,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.frame_mut().locals = locals;
M::after_stack_push(self)?;
self.frame_mut().loc = Ok(mir::Location::START);
info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance);
let span = info_span!("frame", "{}", instance);
self.frame_mut().tracing_span.enter(span);
Ok(())
}
@ -747,10 +784,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// cause us to continue unwinding.
pub(super) fn pop_stack_frame(&mut self, unwinding: bool) -> InterpResult<'tcx> {
info!(
"LEAVING({}) {} (unwinding = {})",
self.frame_idx(),
self.frame().instance,
unwinding
"popping stack frame ({})",
if unwinding { "during unwinding" } else { "returning from function" }
);
// Sanity check `unwinding`.
@ -766,7 +801,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
throw_ub_format!("unwinding past the topmost frame of the stack");
}
::log_settings::settings().indentation -= 1;
let frame =
self.stack_mut().pop().expect("tried to pop a stack frame, but there were none");
@ -823,15 +857,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
}
if !self.stack().is_empty() {
info!(
"CONTINUING({}) {} (unwinding = {})",
self.frame_idx(),
self.frame().instance,
unwinding
);
}
Ok(())
}
@ -995,7 +1020,16 @@ where
{
fn hash_stable(&self, hcx: &mut StableHashingContext<'ctx>, hasher: &mut StableHasher) {
// Exhaustive match on fields to make sure we forget no field.
let Frame { body, instance, return_to_block, return_place, locals, loc, extra } = self;
let Frame {
body,
instance,
return_to_block,
return_place,
locals,
loc,
extra,
tracing_span: _,
} = self;
body.hash_stable(hcx, hasher);
instance.hash_stable(hcx, hasher);
return_to_block.hash_stable(hcx, hasher);

View File

@ -1701,10 +1701,14 @@ where
/// Most of the implementation of DrainFilter, independent of the type
/// of the predicate, thus also serving for BTreeSet::DrainFilter.
pub(super) struct DrainFilterInner<'a, K: 'a, V: 'a> {
/// Reference to the length field in the borrowed map, updated live.
length: &'a mut usize,
// dormant_root is wrapped in an Option to be able to `take` it.
/// Burried reference to the root field in the borrowed map.
/// Wrapped in `Option` to allow drop handler to `take` it.
dormant_root: Option<DormantMutRef<'a, node::Root<K, V>>>,
// cur_leaf_edge is wrapped in an Option because maps without root lack a leaf edge.
/// Contains a leaf edge preceding the next element to be returned, or the last leaf edge.
/// Empty if the map has no root, if iteration went beyond the last leaf edge,
/// or if a panic occurred in the predicate.
cur_leaf_edge: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
}

View File

@ -568,6 +568,7 @@ pub unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
#[inline]
#[stable(feature = "needs_drop", since = "1.21.0")]
#[rustc_const_stable(feature = "const_needs_drop", since = "1.36.0")]
#[rustc_diagnostic_item = "needs_drop"]
pub const fn needs_drop<T>() -> bool {
intrinsics::needs_drop::<T>()
}

View File

@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Non-breaking changes since the last major version]
None.
- `x.py check` needs opt-in to check tests (--all-targets) [#77473](https://github.com/rust-lang/rust/pull/77473)
## [Version 2] - 2020-09-25

View File

@ -532,7 +532,7 @@ impl<'a> Builder<'a> {
pub fn new(build: &Build) -> Builder<'_> {
let (kind, paths) = match build.config.cmd {
Subcommand::Build { ref paths } => (Kind::Build, &paths[..]),
Subcommand::Check { ref paths } => (Kind::Check, &paths[..]),
Subcommand::Check { ref paths, all_targets: _ } => (Kind::Check, &paths[..]),
Subcommand::Clippy { ref paths } => (Kind::Clippy, &paths[..]),
Subcommand::Fix { ref paths } => (Kind::Fix, &paths[..]),
Subcommand::Doc { ref paths, .. } => (Kind::Doc, &paths[..]),

View File

@ -1,9 +1,12 @@
//! Implementation of compiling the compiler and standard library, in "check"-based modes.
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, std_cargo};
use crate::config::TargetSelection;
use crate::tool::{prepare_tool_cargo, SourceType};
use crate::{
builder::{Builder, Kind, RunConfig, ShouldRun, Step},
Subcommand,
};
use crate::{Compiler, Mode};
use std::path::PathBuf;
@ -74,35 +77,37 @@ impl Step for Std {
//
// Currently only the "libtest" tree of crates does this.
let mut cargo = builder.cargo(
compiler,
Mode::Std,
SourceType::InTree,
target,
cargo_subcommand(builder.kind),
);
std_cargo(builder, target, compiler.stage, &mut cargo);
cargo.arg("--all-targets");
if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
let mut cargo = builder.cargo(
compiler,
Mode::Std,
SourceType::InTree,
target,
cargo_subcommand(builder.kind),
);
std_cargo(builder, target, compiler.stage, &mut cargo);
cargo.arg("--all-targets");
// Explicitly pass -p for all dependencies krates -- this will force cargo
// to also check the tests/benches/examples for these crates, rather
// than just the leaf crate.
for krate in builder.in_tree_crates("test") {
cargo.arg("-p").arg(krate.name);
// Explicitly pass -p for all dependencies krates -- this will force cargo
// to also check the tests/benches/examples for these crates, rather
// than just the leaf crate.
for krate in builder.in_tree_crates("test") {
cargo.arg("-p").arg(krate.name);
}
builder.info(&format!(
"Checking std test/bench/example targets ({} -> {})",
&compiler.host, target
));
run_cargo(
builder,
cargo,
args(builder.kind),
&libstd_test_stamp(builder, compiler, target),
vec![],
true,
);
}
builder.info(&format!(
"Checking std test/bench/example targets ({} -> {})",
&compiler.host, target
));
run_cargo(
builder,
cargo,
args(builder.kind),
&libstd_test_stamp(builder, compiler, target),
vec![],
true,
);
}
}
@ -143,7 +148,9 @@ impl Step for Rustc {
cargo_subcommand(builder.kind),
);
rustc_cargo(builder, &mut cargo, target);
cargo.arg("--all-targets");
if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
cargo.arg("--all-targets");
}
// Explicitly pass -p for all compiler krates -- this will force cargo
// to also check the tests/benches/examples for these crates, rather
@ -205,7 +212,9 @@ macro_rules! tool_check_step {
&[],
);
cargo.arg("--all-targets");
if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
cargo.arg("--all-targets");
}
builder.info(&format!(
"Checking {} artifacts ({} -> {})",

View File

@ -47,6 +47,9 @@ pub enum Subcommand {
paths: Vec<PathBuf>,
},
Check {
// Whether to run checking over all targets (e.g., unit / integration
// tests).
all_targets: bool,
paths: Vec<PathBuf>,
},
Clippy {
@ -250,6 +253,9 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
`/<build_base>/rustfix_missing_coverage.txt`",
);
}
"check" => {
opts.optflag("", "all-targets", "Check all targets");
}
"bench" => {
opts.optmulti("", "test-args", "extra arguments", "ARGS");
}
@ -484,7 +490,9 @@ Arguments:
let cmd = match subcommand.as_str() {
"build" | "b" => Subcommand::Build { paths },
"check" | "c" => Subcommand::Check { paths },
"check" | "c" => {
Subcommand::Check { paths, all_targets: matches.opt_present("all-targets") }
}
"clippy" => Subcommand::Clippy { paths },
"fix" => Subcommand::Fix { paths },
"test" | "t" => Subcommand::Test {

View File

@ -24,7 +24,7 @@ COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu --all-targets && \
python3 ../x.py build --stage 0 src/tools/build-manifest && \
python3 ../x.py test --stage 0 src/tools/compiletest && \
python3 ../x.py test --stage 2 src/tools/tidy && \

View File

@ -1576,22 +1576,27 @@ fn resolution_failure(
};
// See if this was a module: `[path]` or `[std::io::nope]`
if let Some(module) = last_found_module {
let module_name = collector.cx.tcx.item_name(module);
let note = format!(
"the module `{}` contains no item named `{}`",
module_name, unresolved
);
let note = if partial_res.is_some() {
// Part of the link resolved; e.g. `std::io::nonexistent`
let module_name = collector.cx.tcx.item_name(module);
format!("no item named `{}` in module `{}`", unresolved, module_name)
} else {
// None of the link resolved; e.g. `Notimported`
format!("no item named `{}` in scope", unresolved)
};
if let Some(span) = sp {
diag.span_label(span, &note);
} else {
diag.note(&note);
}
// If the link has `::` in it, assume it was meant to be an intra-doc link.
// Otherwise, the `[]` might be unrelated.
// FIXME: don't show this for autolinks (`<>`), `()` style links, or reference links
if !path_str.contains("::") {
diag.help(r#"to escape `[` and `]` characters, add '\' before them like `\[` or `\]`"#);
}
continue;
}

View File

@ -2,7 +2,7 @@ error: unresolved link to `v2`
--> $DIR/deny-intra-link-resolution-failure.rs:3:6
|
LL | /// [v2]
| ^^ the module `deny_intra_link_resolution_failure` contains no item named `v2`
| ^^ no item named `v2` in scope
|
note: the lint level is defined here
--> $DIR/deny-intra-link-resolution-failure.rs:1:9

View File

@ -6,23 +6,23 @@
/// [path::to::nonexistent::module]
//~^ ERROR unresolved link
//~| NOTE `intra_link_errors` contains no item named `path`
//~| NOTE no item named `path` in scope
/// [path::to::nonexistent::macro!]
//~^ ERROR unresolved link
//~| NOTE `intra_link_errors` contains no item named `path`
//~| NOTE no item named `path` in scope
/// [type@path::to::nonexistent::type]
//~^ ERROR unresolved link
//~| NOTE `intra_link_errors` contains no item named `path`
//~| NOTE no item named `path` in scope
/// [std::io::not::here]
//~^ ERROR unresolved link
//~| NOTE `io` contains no item named `not`
//~| NOTE no item named `not` in module `io`
/// [type@std::io::not::here]
//~^ ERROR unresolved link
//~| NOTE `io` contains no item named `not`
//~| NOTE no item named `not` in module `io`
/// [std::io::Error::x]
//~^ ERROR unresolved link

View File

@ -2,7 +2,7 @@ error: unresolved link to `path::to::nonexistent::module`
--> $DIR/intra-link-errors.rs:7:6
|
LL | /// [path::to::nonexistent::module]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the module `intra_link_errors` contains no item named `path`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in scope
|
note: the lint level is defined here
--> $DIR/intra-link-errors.rs:1:9
@ -14,25 +14,25 @@ error: unresolved link to `path::to::nonexistent::macro`
--> $DIR/intra-link-errors.rs:11:6
|
LL | /// [path::to::nonexistent::macro!]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the module `intra_link_errors` contains no item named `path`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in scope
error: unresolved link to `path::to::nonexistent::type`
--> $DIR/intra-link-errors.rs:15:6
|
LL | /// [type@path::to::nonexistent::type]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the module `intra_link_errors` contains no item named `path`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `path` in scope
error: unresolved link to `std::io::not::here`
--> $DIR/intra-link-errors.rs:19:6
|
LL | /// [std::io::not::here]
| ^^^^^^^^^^^^^^^^^^ the module `io` contains no item named `not`
| ^^^^^^^^^^^^^^^^^^ no item named `not` in module `io`
error: unresolved link to `std::io::not::here`
--> $DIR/intra-link-errors.rs:23:6
|
LL | /// [type@std::io::not::here]
| ^^^^^^^^^^^^^^^^^^^^^^^ the module `io` contains no item named `not`
| ^^^^^^^^^^^^^^^^^^^^^^^ no item named `not` in module `io`
error: unresolved link to `std::io::Error::x`
--> $DIR/intra-link-errors.rs:27:6

View File

@ -2,7 +2,7 @@ error: unresolved link to `i`
--> $DIR/intra-link-span-ice-55723.rs:9:10
|
LL | /// arr[i]
| ^ the module `intra_link_span_ice_55723` contains no item named `i`
| ^ no item named `i` in scope
|
note: the lint level is defined here
--> $DIR/intra-link-span-ice-55723.rs:1:9

View File

@ -2,7 +2,7 @@ warning: unresolved link to `error`
--> $DIR/intra-links-warning-crlf.rs:7:6
|
LL | /// [error]
| ^^^^^ the module `intra_links_warning_crlf` contains no item named `error`
| ^^^^^ no item named `error` in scope
|
= note: `#[warn(broken_intra_doc_links)]` on by default
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@ -11,7 +11,7 @@ warning: unresolved link to `error1`
--> $DIR/intra-links-warning-crlf.rs:12:11
|
LL | /// docs [error1]
| ^^^^^^ the module `intra_links_warning_crlf` contains no item named `error1`
| ^^^^^^ no item named `error1` in scope
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@ -19,7 +19,7 @@ warning: unresolved link to `error2`
--> $DIR/intra-links-warning-crlf.rs:15:11
|
LL | /// docs [error2]
| ^^^^^^ the module `intra_links_warning_crlf` contains no item named `error2`
| ^^^^^^ no item named `error2` in scope
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@ -27,7 +27,7 @@ warning: unresolved link to `error`
--> $DIR/intra-links-warning-crlf.rs:23:20
|
LL | * It also has an [error].
| ^^^^^ the module `intra_links_warning_crlf` contains no item named `error`
| ^^^^^ no item named `error` in scope
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

View File

@ -10,37 +10,37 @@ warning: unresolved link to `Bar::foo`
--> $DIR/intra-links-warning.rs:3:35
|
LL | //! Test with [Foo::baz], [Bar::foo], ...
| ^^^^^^^^ the module `intra_links_warning` contains no item named `Bar`
| ^^^^^^^^ no item named `Bar` in scope
warning: unresolved link to `Uniooon::X`
--> $DIR/intra-links-warning.rs:6:13
|
LL | //! , [Uniooon::X] and [Qux::Z].
| ^^^^^^^^^^ the module `intra_links_warning` contains no item named `Uniooon`
| ^^^^^^^^^^ no item named `Uniooon` in scope
warning: unresolved link to `Qux::Z`
--> $DIR/intra-links-warning.rs:6:30
|
LL | //! , [Uniooon::X] and [Qux::Z].
| ^^^^^^ the module `intra_links_warning` contains no item named `Qux`
| ^^^^^^ no item named `Qux` in scope
warning: unresolved link to `Uniooon::X`
--> $DIR/intra-links-warning.rs:10:14
|
LL | //! , [Uniooon::X] and [Qux::Z].
| ^^^^^^^^^^ the module `intra_links_warning` contains no item named `Uniooon`
| ^^^^^^^^^^ no item named `Uniooon` in scope
warning: unresolved link to `Qux::Z`
--> $DIR/intra-links-warning.rs:10:31
|
LL | //! , [Uniooon::X] and [Qux::Z].
| ^^^^^^ the module `intra_links_warning` contains no item named `Qux`
| ^^^^^^ no item named `Qux` in scope
warning: unresolved link to `Qux:Y`
--> $DIR/intra-links-warning.rs:14:13
|
LL | /// [Qux:Y]
| ^^^^^ the module `intra_links_warning` contains no item named `Qux:Y`
| ^^^^^ no item named `Qux:Y` in scope
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@ -48,7 +48,7 @@ warning: unresolved link to `error`
--> $DIR/intra-links-warning.rs:58:30
|
LL | * time to introduce a link [error]*/
| ^^^^^ the module `intra_links_warning` contains no item named `error`
| ^^^^^ no item named `error` in scope
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@ -56,7 +56,7 @@ warning: unresolved link to `error`
--> $DIR/intra-links-warning.rs:64:30
|
LL | * time to introduce a link [error]
| ^^^^^ the module `intra_links_warning` contains no item named `error`
| ^^^^^ no item named `error` in scope
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@ -70,7 +70,7 @@ LL | #[doc = "single line [error]"]
single line [error]
^^^^^
= note: the module `intra_links_warning` contains no item named `error`
= note: no item named `error` in scope
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: unresolved link to `error`
@ -83,7 +83,7 @@ LL | #[doc = "single line with \"escaping\" [error]"]
single line with "escaping" [error]
^^^^^
= note: the module `intra_links_warning` contains no item named `error`
= note: no item named `error` in scope
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: unresolved link to `error`
@ -98,14 +98,14 @@ LL | | /// [error]
[error]
^^^^^
= note: the module `intra_links_warning` contains no item named `error`
= note: no item named `error` in scope
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: unresolved link to `error1`
--> $DIR/intra-links-warning.rs:80:11
|
LL | /// docs [error1]
| ^^^^^^ the module `intra_links_warning` contains no item named `error1`
| ^^^^^^ no item named `error1` in scope
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@ -113,7 +113,7 @@ warning: unresolved link to `error2`
--> $DIR/intra-links-warning.rs:82:11
|
LL | /// docs [error2]
| ^^^^^^ the module `intra_links_warning` contains no item named `error2`
| ^^^^^^ no item named `error2` in scope
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@ -121,7 +121,7 @@ warning: unresolved link to `BarA`
--> $DIR/intra-links-warning.rs:21:10
|
LL | /// bar [BarA] bar
| ^^^^ the module `intra_links_warning` contains no item named `BarA`
| ^^^^ no item named `BarA` in scope
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@ -129,7 +129,7 @@ warning: unresolved link to `BarB`
--> $DIR/intra-links-warning.rs:27:9
|
LL | * bar [BarB] bar
| ^^^^ the module `intra_links_warning` contains no item named `BarB`
| ^^^^ no item named `BarB` in scope
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@ -137,7 +137,7 @@ warning: unresolved link to `BarC`
--> $DIR/intra-links-warning.rs:34:6
|
LL | bar [BarC] bar
| ^^^^ the module `intra_links_warning` contains no item named `BarC`
| ^^^^ no item named `BarC` in scope
|
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
@ -151,7 +151,7 @@ LL | #[doc = "Foo\nbar [BarD] bar\nbaz"]
bar [BarD] bar
^^^^
= note: the module `intra_links_warning` contains no item named `BarD`
= note: no item named `BarD` in scope
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: unresolved link to `BarF`
@ -167,7 +167,7 @@ LL | f!("Foo\nbar [BarF] bar\nbaz");
bar [BarF] bar
^^^^
= note: the module `intra_links_warning` contains no item named `BarF`
= note: no item named `BarF` in scope
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
= note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

View File

@ -32,7 +32,7 @@ error: unresolved link to `error`
--> $DIR/lint-group.rs:9:29
|
LL | /// what up, let's make an [error]
| ^^^^^ the module `lint_group` contains no item named `error`
| ^^^^^ no item named `error` in scope
|
note: the lint level is defined here
--> $DIR/lint-group.rs:7:9

View File

@ -0,0 +1,11 @@
// compile-flags: -Zmir-opt-level=3
// run-pass
#![feature(const_generics)]
#![allow(incomplete_features)]
fn main() {
fn foo<const N: usize>() -> [u8; N] {
[0; N]
}
let _x = foo::<1>();
}

View File

@ -0,0 +1,14 @@
// run-pass
#![deny(drop_bounds)]
// As a special exemption, `impl Drop` in the return position raises no error.
// This allows a convenient way to return an unnamed drop guard.
fn voldemort_type() -> impl Drop {
struct Voldemort;
impl Drop for Voldemort {
fn drop(&mut self) {}
}
Voldemort
}
fn main() {
let _ = voldemort_type();
}

View File

@ -0,0 +1,19 @@
#![deny(drop_bounds)]
fn foo<T: Drop>() {} //~ ERROR
fn bar<U>()
where
U: Drop, //~ ERROR
{
}
fn baz(_x: impl Drop) {} //~ ERROR
struct Foo<T: Drop> { //~ ERROR
_x: T
}
struct Bar<U> where U: Drop { //~ ERROR
_x: U
}
trait Baz: Drop { //~ ERROR
}
impl<T: Drop> Baz for T { //~ ERROR
}
fn main() {}

View File

@ -0,0 +1,50 @@
error: bounds on `T: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor
--> $DIR/drop-bounds.rs:2:11
|
LL | fn foo<T: Drop>() {}
| ^^^^
|
note: the lint level is defined here
--> $DIR/drop-bounds.rs:1:9
|
LL | #![deny(drop_bounds)]
| ^^^^^^^^^^^
error: bounds on `U: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor
--> $DIR/drop-bounds.rs:5:8
|
LL | U: Drop,
| ^^^^
error: bounds on `impl Drop: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor
--> $DIR/drop-bounds.rs:8:17
|
LL | fn baz(_x: impl Drop) {}
| ^^^^
error: bounds on `T: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor
--> $DIR/drop-bounds.rs:9:15
|
LL | struct Foo<T: Drop> {
| ^^^^
error: bounds on `U: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor
--> $DIR/drop-bounds.rs:12:24
|
LL | struct Bar<U> where U: Drop {
| ^^^^
error: bounds on `Self: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor
--> $DIR/drop-bounds.rs:15:12
|
LL | trait Baz: Drop {
| ^^^^
error: bounds on `T: Drop` are useless, consider instead using `std::mem::needs_drop` to detect if a type has a destructor
--> $DIR/drop-bounds.rs:17:9
|
LL | impl<T: Drop> Baz for T {
| ^^^^
error: aborting due to 7 previous errors

View File

@ -0,0 +1,7 @@
#[derive("Clone")] //~ ERROR E0777
#[derive("Clone
")]
//~^^ ERROR E0777
struct Foo;
fn main() {}

View File

@ -0,0 +1,21 @@
error[E0777]: expected path to a trait, found literal
--> $DIR/E0777.rs:1:10
|
LL | #[derive("Clone")]
| ^^^^^^^
|
= help: try using `#[derive(Clone)]`
error[E0777]: expected path to a trait, found literal
--> $DIR/E0777.rs:2:10
|
LL | #[derive("Clone
| __________^
LL | | ")]
| |_^
|
= help: for example, write `#[derive(Debug)]` for `Debug`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0777`.

View File

@ -0,0 +1,9 @@
// check-pass
fn main() {
let array = [0x42u8; 10];
for b in &array {
let lo = b & 0xf;
let hi = (b >> 4) & 0xf;
}
}

View File

@ -0,0 +1,12 @@
// check-pass
#![allow(unreachable_patterns)]
fn main() {
const CONST: &[Option<()>; 1] = &[Some(())];
match &[Some(())] {
&[None] => {}
CONST => {}
&[Some(())] => {}
}
}

View File

@ -0,0 +1,8 @@
const F: &'static dyn PartialEq<u32> = &7u32;
fn main() {
let a: &dyn PartialEq<u32> = &7u32;
match a {
F => panic!(), //~ ERROR: `&dyn PartialEq<u32>` cannot be used in patterns
}
}

View File

@ -0,0 +1,8 @@
error: `&dyn PartialEq<u32>` cannot be used in patterns
--> $DIR/issue-72565.rs:6:9
|
LL | F => panic!(),
| ^
error: aborting due to previous error

View File

@ -0,0 +1,191 @@
// build-fail
#![allow(non_camel_case_types)]
#![feature(repr_simd, platform_intrinsics)]
// Test for #73542 to verify out-of-bounds shuffle vectors do not compile.
#[repr(simd)]
#[derive(Copy, Clone)]
struct u8x2(u8, u8);
#[repr(simd)]
#[derive(Copy, Clone)]
struct u8x4(u8, u8, u8, u8);
#[repr(simd)]
#[derive(Copy, Clone)]
struct u8x8(u8, u8, u8, u8, u8, u8, u8, u8);
#[repr(simd)]
#[derive(Copy, Clone)]
struct u8x16(
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
);
#[repr(simd)]
#[derive(Copy, Clone)]
struct u8x32(
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
);
#[repr(simd)]
#[derive(Copy, Clone)]
struct u8x64(
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
u8,
);
// Test vectors by lane size. Since LLVM does not distinguish between a shuffle
// over two f32s and a shuffle over two u64s, or any other such combination,
// it is not necessary to test every possible vector, only lane counts.
macro_rules! test_shuffle_lanes {
($n:literal, $x:ident, $y:ident, $t:tt) => {
unsafe {
let shuffle: $x = {
const ARR: [u32; $n] = {
let mut arr = [0; $n];
arr[0] = $n * 2;
arr
};
extern "platform-intrinsic" {
pub fn $y<T, U>(x: T, y: T, idx: [u32; $n]) -> U;
}
let vec1 = $x$t;
let vec2 = $x$t;
$y(vec1, vec2, ARR)
};
}
}
}
//~^^^^^ ERROR: invalid monomorphization of `simd_shuffle2` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle4` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle8` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle16` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle32` intrinsic
//~| ERROR: invalid monomorphization of `simd_shuffle64` intrinsic
// Because the test is mostly embedded in a macro, all the errors have the same origin point.
// And unfortunately, standard comments, as in the UI test harness, disappear in macros!
fn main() {
test_shuffle_lanes!(2, u8x2, simd_shuffle2, (2, 1));
test_shuffle_lanes!(4, u8x4, simd_shuffle4, (4, 3, 2, 1));
test_shuffle_lanes!(8, u8x8, simd_shuffle8, (8, 7, 6, 5, 4, 3, 2, 1));
test_shuffle_lanes!(16, u8x16, simd_shuffle16,
(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
test_shuffle_lanes!(32, u8x32, simd_shuffle32,
(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
test_shuffle_lanes!(64, u8x64, simd_shuffle64,
(64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49,
48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33,
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
}

View File

@ -0,0 +1,76 @@
error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: shuffle index #0 is out of bounds (limit 4)
--> $DIR/shuffle-not-out-of-bounds.rs:163:21
|
LL | $y(vec1, vec2, ARR)
| ^^^^^^^^^^^^^^^^^^^
...
LL | test_shuffle_lanes!(2, u8x2, simd_shuffle2, (2, 1));
| ---------------------------------------------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: shuffle index #0 is out of bounds (limit 8)
--> $DIR/shuffle-not-out-of-bounds.rs:163:21
|
LL | $y(vec1, vec2, ARR)
| ^^^^^^^^^^^^^^^^^^^
...
LL | test_shuffle_lanes!(4, u8x4, simd_shuffle4, (4, 3, 2, 1));
| ---------------------------------------------------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: shuffle index #0 is out of bounds (limit 16)
--> $DIR/shuffle-not-out-of-bounds.rs:163:21
|
LL | $y(vec1, vec2, ARR)
| ^^^^^^^^^^^^^^^^^^^
...
LL | test_shuffle_lanes!(8, u8x8, simd_shuffle8, (8, 7, 6, 5, 4, 3, 2, 1));
| ---------------------------------------------------------------------- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0511]: invalid monomorphization of `simd_shuffle16` intrinsic: shuffle index #0 is out of bounds (limit 32)
--> $DIR/shuffle-not-out-of-bounds.rs:163:21
|
LL | $y(vec1, vec2, ARR)
| ^^^^^^^^^^^^^^^^^^^
...
LL | / test_shuffle_lanes!(16, u8x16, simd_shuffle16,
LL | | (16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
| |_________________________________________________________________- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0511]: invalid monomorphization of `simd_shuffle32` intrinsic: shuffle index #0 is out of bounds (limit 64)
--> $DIR/shuffle-not-out-of-bounds.rs:163:21
|
LL | $y(vec1, vec2, ARR)
| ^^^^^^^^^^^^^^^^^^^
...
LL | / test_shuffle_lanes!(32, u8x32, simd_shuffle32,
LL | | (32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
LL | | 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
| |_____________________________________________________________- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0511]: invalid monomorphization of `simd_shuffle64` intrinsic: shuffle index #0 is out of bounds (limit 128)
--> $DIR/shuffle-not-out-of-bounds.rs:163:21
|
LL | $y(vec1, vec2, ARR)
| ^^^^^^^^^^^^^^^^^^^
...
LL | / test_shuffle_lanes!(64, u8x64, simd_shuffle64,
LL | | (64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49,
LL | | 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33,
LL | | 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
LL | | 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
| |_________________________________________________________________- in this macro invocation
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0511`.

View File

@ -0,0 +1,20 @@
#![feature(type_alias_impl_trait)]
trait Allocator {
type Buffer;
}
struct DefaultAllocator;
impl<T> Allocator for DefaultAllocator {
//~^ ERROR: the type parameter `T` is not constrained
type Buffer = ();
}
type A = impl Fn(<DefaultAllocator as Allocator>::Buffer);
fn foo() -> A {
|_| ()
}
fn main() {}

View File

@ -0,0 +1,9 @@
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
--> $DIR/issue-74244.rs:9:6
|
LL | impl<T> Allocator for DefaultAllocator {
| ^ unconstrained type parameter
error: aborting due to previous error
For more information about this error, try `rustc --explain E0207`.

View File

@ -163,3 +163,12 @@ declare_deprecated_lint! {
pub REGEX_MACRO,
"the regex! macro has been removed from the regex crate in 2018"
}
declare_deprecated_lint! {
/// **What it does:** Nothing. This lint has been deprecated.
///
/// **Deprecation reason:** This lint has been uplifted to rustc and is now called
/// `drop_bounds`.
pub DROP_BOUNDS,
"this lint has been uplifted to rustc and is now called `drop_bounds`"
}

View File

@ -1,73 +0,0 @@
use crate::utils::{match_def_path, paths, span_lint};
use if_chain::if_chain;
use rustc_hir::{GenericBound, GenericParam, WhereBoundPredicate, WherePredicate};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! {
/// **What it does:** Checks for generics with `std::ops::Drop` as bounds.
///
/// **Why is this bad?** `Drop` bounds do not really accomplish anything.
/// A type may have compiler-generated drop glue without implementing the
/// `Drop` trait itself. The `Drop` trait also only has one method,
/// `Drop::drop`, and that function is by fiat not callable in user code.
/// So there is really no use case for using `Drop` in trait bounds.
///
/// The most likely use case of a drop bound is to distinguish between types
/// that have destructors and types that don't. Combined with specialization,
/// a naive coder would write an implementation that assumed a type could be
/// trivially dropped, then write a specialization for `T: Drop` that actually
/// calls the destructor. Except that doing so is not correct; String, for
/// example, doesn't actually implement Drop, but because String contains a
/// Vec, assuming it can be trivially dropped will leak memory.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// fn foo<T: Drop>() {}
/// ```
/// Could be written as:
/// ```rust
/// fn foo<T>() {}
/// ```
pub DROP_BOUNDS,
correctness,
"bounds of the form `T: Drop` are useless"
}
const DROP_BOUNDS_SUMMARY: &str = "bounds of the form `T: Drop` are useless, \
use `std::mem::needs_drop` to detect if a type has drop glue";
declare_lint_pass!(DropBounds => [DROP_BOUNDS]);
impl<'tcx> LateLintPass<'tcx> for DropBounds {
fn check_generic_param(&mut self, cx: &LateContext<'tcx>, p: &'tcx GenericParam<'_>) {
for bound in p.bounds.iter() {
lint_bound(cx, bound);
}
}
fn check_where_predicate(&mut self, cx: &LateContext<'tcx>, p: &'tcx WherePredicate<'_>) {
if let WherePredicate::BoundPredicate(WhereBoundPredicate { bounds, .. }) = p {
for bound in *bounds {
lint_bound(cx, bound);
}
}
}
}
fn lint_bound<'tcx>(cx: &LateContext<'tcx>, bound: &'tcx GenericBound<'_>) {
if_chain! {
if let GenericBound::Trait(t, _) = bound;
if let Some(def_id) = t.trait_ref.path.res.opt_def_id();
if match_def_path(cx, def_id, &paths::DROP_TRAIT);
then {
span_lint(
cx,
DROP_BOUNDS,
t.span,
DROP_BOUNDS_SUMMARY
);
}
}
}

View File

@ -179,7 +179,6 @@ mod derive;
mod doc;
mod double_comparison;
mod double_parens;
mod drop_bounds;
mod drop_forget_ref;
mod duration_subsec;
mod else_if_without_else;
@ -478,6 +477,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
"clippy::regex_macro",
"the regex! macro has been removed from the regex crate in 2018",
);
store.register_removed(
"clippy::drop_bounds",
"this lint has been uplifted to rustc and is now called `drop_bounds`",
);
// end deprecated lints, do not remove this comment, its used in `update_lints`
// begin register lints, do not remove this comment, its used in `update_lints`
@ -532,7 +535,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&doc::NEEDLESS_DOCTEST_MAIN,
&double_comparison::DOUBLE_COMPARISONS,
&double_parens::DOUBLE_PARENS,
&drop_bounds::DROP_BOUNDS,
&drop_forget_ref::DROP_COPY,
&drop_forget_ref::DROP_REF,
&drop_forget_ref::FORGET_COPY,
@ -959,7 +961,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box strings::StringLitAsBytes);
store.register_late_pass(|| box derive::Derive);
store.register_late_pass(|| box types::CharLitAsU8);
store.register_late_pass(|| box drop_bounds::DropBounds);
store.register_late_pass(|| box get_last_with_len::GetLastWithLen);
store.register_late_pass(|| box drop_forget_ref::DropForgetRef);
store.register_late_pass(|| box empty_enum::EmptyEnum);
@ -1282,7 +1283,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&doc::NEEDLESS_DOCTEST_MAIN),
LintId::of(&double_comparison::DOUBLE_COMPARISONS),
LintId::of(&double_parens::DOUBLE_PARENS),
LintId::of(&drop_bounds::DROP_BOUNDS),
LintId::of(&drop_forget_ref::DROP_COPY),
LintId::of(&drop_forget_ref::DROP_REF),
LintId::of(&drop_forget_ref::FORGET_COPY),
@ -1714,7 +1714,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&copies::IF_SAME_THEN_ELSE),
LintId::of(&derive::DERIVE_HASH_XOR_EQ),
LintId::of(&derive::DERIVE_ORD_XOR_PARTIAL_ORD),
LintId::of(&drop_bounds::DROP_BOUNDS),
LintId::of(&drop_forget_ref::DROP_COPY),
LintId::of(&drop_forget_ref::DROP_REF),
LintId::of(&drop_forget_ref::FORGET_COPY),

View File

@ -31,7 +31,6 @@ pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"];
pub const DISPLAY_TRAIT: [&str; 3] = ["core", "fmt", "Display"];
pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"];
pub const DROP: [&str; 3] = ["core", "mem", "drop"];
pub const DROP_TRAIT: [&str; 4] = ["core", "ops", "drop", "Drop"];
pub const DURATION: [&str; 3] = ["core", "time", "Duration"];
pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"];
pub const EXIT: [&str; 3] = ["std", "process", "exit"];

View File

@ -423,13 +423,6 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
deprecation: None,
module: "double_parens",
},
Lint {
name: "drop_bounds",
group: "correctness",
desc: "bounds of the form `T: Drop` are useless",
deprecation: None,
module: "drop_bounds",
},
Lint {
name: "drop_copy",
group: "correctness",

View File

@ -8,5 +8,6 @@
#[warn(clippy::into_iter_on_array)]
#[warn(clippy::unused_label)]
#[warn(clippy::regex_macro)]
#[warn(clippy::drop_bounds)]
fn main() {}

View File

@ -60,11 +60,17 @@ error: lint `clippy::regex_macro` has been removed: `the regex! macro has been r
LL | #[warn(clippy::regex_macro)]
| ^^^^^^^^^^^^^^^^^^^
error: lint `clippy::drop_bounds` has been removed: `this lint has been uplifted to rustc and is now called `drop_bounds``
--> $DIR/deprecated.rs:11:8
|
LL | #[warn(clippy::drop_bounds)]
| ^^^^^^^^^^^^^^^^^^^
error: lint `clippy::str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon`
--> $DIR/deprecated.rs:1:8
|
LL | #[warn(clippy::str_to_string)]
| ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 11 previous errors
error: aborting due to 12 previous errors

View File

@ -1,8 +0,0 @@
#![allow(unused)]
fn foo<T: Drop>() {}
fn bar<T>()
where
T: Drop,
{
}
fn main() {}

View File

@ -1,16 +0,0 @@
error: bounds of the form `T: Drop` are useless, use `std::mem::needs_drop` to detect if a type has drop glue
--> $DIR/drop_bounds.rs:2:11
|
LL | fn foo<T: Drop>() {}
| ^^^^
|
= note: `#[deny(clippy::drop_bounds)]` on by default
error: bounds of the form `T: Drop` are useless, use `std::mem::needs_drop` to detect if a type has drop glue
--> $DIR/drop_bounds.rs:5:8
|
LL | T: Drop,
| ^^^^
error: aborting due to 2 previous errors

View File

@ -116,7 +116,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
"libz-sys",
"lock_api",
"log",
"log_settings",
"maybe-uninit",
"md-5",
"measureme",