mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 15:32:06 +00:00
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:
commit
2251766944
15
Cargo.lock
15
Cargo.lock
@ -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",
|
||||
|
@ -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/
|
||||
|
@ -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" }
|
||||
|
@ -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() -> ! {
|
||||
|
@ -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
|
||||
|
19
compiler/rustc_error_codes/src/error_codes/E0777.md
Normal file
19
compiler/rustc_error_codes/src/error_codes/E0777.md
Normal 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
|
@ -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,
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
]
|
||||
);
|
||||
};
|
||||
|
79
compiler/rustc_lint/src/traits.rs
Normal file
79
compiler/rustc_lint/src/traits.rs
Normal 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()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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" }
|
||||
|
@ -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);
|
||||
|
@ -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>>,
|
||||
}
|
||||
|
||||
|
@ -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>()
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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[..]),
|
||||
|
@ -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 ({} -> {})",
|
||||
|
@ -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 {
|
||||
|
@ -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 && \
|
||||
|
@ -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, ¬e);
|
||||
} else {
|
||||
diag.note(¬e);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 `\]`
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
11
src/test/ui/const-generics/issues/issue-75299.rs
Normal file
11
src/test/ui/const-generics/issues/issue-75299.rs
Normal 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>();
|
||||
}
|
14
src/test/ui/drop-bounds/drop-bounds-impl-drop.rs
Normal file
14
src/test/ui/drop-bounds/drop-bounds-impl-drop.rs
Normal 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();
|
||||
}
|
19
src/test/ui/drop-bounds/drop-bounds.rs
Normal file
19
src/test/ui/drop-bounds/drop-bounds.rs
Normal 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() {}
|
50
src/test/ui/drop-bounds/drop-bounds.stderr
Normal file
50
src/test/ui/drop-bounds/drop-bounds.stderr
Normal 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
|
||||
|
7
src/test/ui/error-codes/E0777.rs
Normal file
7
src/test/ui/error-codes/E0777.rs
Normal file
@ -0,0 +1,7 @@
|
||||
#[derive("Clone")] //~ ERROR E0777
|
||||
#[derive("Clone
|
||||
")]
|
||||
//~^^ ERROR E0777
|
||||
struct Foo;
|
||||
|
||||
fn main() {}
|
21
src/test/ui/error-codes/E0777.stderr
Normal file
21
src/test/ui/error-codes/E0777.stderr
Normal 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`.
|
9
src/test/ui/issues/issue-68951.rs
Normal file
9
src/test/ui/issues/issue-68951.rs
Normal 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;
|
||||
}
|
||||
}
|
12
src/test/ui/pattern/issue-66501.rs
Normal file
12
src/test/ui/pattern/issue-66501.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// check-pass
|
||||
|
||||
#![allow(unreachable_patterns)]
|
||||
|
||||
fn main() {
|
||||
const CONST: &[Option<()>; 1] = &[Some(())];
|
||||
match &[Some(())] {
|
||||
&[None] => {}
|
||||
CONST => {}
|
||||
&[Some(())] => {}
|
||||
}
|
||||
}
|
8
src/test/ui/pattern/issue-72565.rs
Normal file
8
src/test/ui/pattern/issue-72565.rs
Normal 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
|
||||
}
|
||||
}
|
8
src/test/ui/pattern/issue-72565.stderr
Normal file
8
src/test/ui/pattern/issue-72565.stderr
Normal 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
|
||||
|
191
src/test/ui/simd/shuffle-not-out-of-bounds.rs
Normal file
191
src/test/ui/simd/shuffle-not-out-of-bounds.rs
Normal 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));
|
||||
}
|
76
src/test/ui/simd/shuffle-not-out-of-bounds.stderr
Normal file
76
src/test/ui/simd/shuffle-not-out-of-bounds.stderr
Normal 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`.
|
20
src/test/ui/type-alias-impl-trait/issue-74244.rs
Normal file
20
src/test/ui/type-alias-impl-trait/issue-74244.rs
Normal 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() {}
|
9
src/test/ui/type-alias-impl-trait/issue-74244.stderr
Normal file
9
src/test/ui/type-alias-impl-trait/issue-74244.stderr
Normal 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`.
|
@ -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`"
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -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, it’s used in `update_lints`
|
||||
|
||||
// begin register lints, do not remove this comment, it’s 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),
|
||||
|
@ -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"];
|
||||
|
@ -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",
|
||||
|
@ -8,5 +8,6 @@
|
||||
#[warn(clippy::into_iter_on_array)]
|
||||
#[warn(clippy::unused_label)]
|
||||
#[warn(clippy::regex_macro)]
|
||||
#[warn(clippy::drop_bounds)]
|
||||
|
||||
fn main() {}
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,8 +0,0 @@
|
||||
#![allow(unused)]
|
||||
fn foo<T: Drop>() {}
|
||||
fn bar<T>()
|
||||
where
|
||||
T: Drop,
|
||||
{
|
||||
}
|
||||
fn main() {}
|
@ -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
|
||||
|
@ -116,7 +116,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
|
||||
"libz-sys",
|
||||
"lock_api",
|
||||
"log",
|
||||
"log_settings",
|
||||
"maybe-uninit",
|
||||
"md-5",
|
||||
"measureme",
|
||||
|
Loading…
Reference in New Issue
Block a user