diff --git a/Cargo.lock b/Cargo.lock index 28bd57ef6735c..fb7d2a4ac2fc6 100644 --- a/Cargo.lock +++ b/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", diff --git a/RELEASES.md b/RELEASES.md index 62d30842b230c..ce11a74b71f53 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -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/ diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml index adfce1008e1ed..f610e88b7fce5 100644 --- a/compiler/rustc_driver/Cargo.toml +++ b/compiler/rustc_driver/Cargo.toml @@ -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" } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 544efc124e117..3f50c68e3ebf5 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -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 builder = builder.with_env_filter(tracing_subscriber::EnvFilter::from_env(env)); - - builder.init() + 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); + + 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() -> ! { diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 81f65ac86900f..981b5bb8ba72f 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -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 diff --git a/compiler/rustc_error_codes/src/error_codes/E0777.md b/compiler/rustc_error_codes/src/error_codes/E0777.md new file mode 100644 index 0000000000000..8c5c6e28b65c6 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0777.md @@ -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 diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index e5cfb866938e5..c6287693dc9e6 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -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, diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 94b3fcf2850d2..4c95f19b96dc6 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -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) .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), diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 33caedfc19826..49e80f9d8a531 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -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, ] ); }; diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs new file mode 100644 index 0000000000000..d4f79036e5a18 --- /dev/null +++ b/compiler/rustc_lint/src/traits.rs @@ -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() {} + /// ``` + /// + /// {{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() + }); + } + } + } +} diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 7b5cf681f38fb..238bce94cf505 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -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 { 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("")) + p!("") } } // FIXME: for statics and functions, we could in principle print more detail. Some(GlobalAlloc::Static(def_id)) => p!(write("", def_id)), - Some(GlobalAlloc::Function(_)) => p!(write("")), - None => p!(write("")), + Some(GlobalAlloc::Function(_)) => p!(""), + None => p!(""), }, // 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 { 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 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 FmtPrinter<'_, '_, F> { ty::ReVar(_) => {} ty::ReErased => {} ty::ReStatic => { - p!(write("'static")); + p!("'static"); return Ok(self); } ty::ReEmpty(ty::UniverseIndex::ROOT) => { - p!(write("'")); + p!("'"); return Ok(self); } ty::ReEmpty(ui) => { @@ -1716,7 +1719,7 @@ impl FmtPrinter<'_, '_, F> { } } - p!(write("'_")); + p!("'_"); Ok(self) } @@ -1847,7 +1850,7 @@ where type Error = P::Error; fn print(&self, mut cx: P) -> Result { 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> { - 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") } } } diff --git a/compiler/rustc_mir/Cargo.toml b/compiler/rustc_mir/Cargo.toml index a6d22243d6df6..487668cfa1109 100644 --- a/compiler/rustc_mir/Cargo.toml +++ b/compiler/rustc_mir/Cargo.toml @@ -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" } diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index f97096984fa9b..93da6e3d38a93 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -48,8 +48,41 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> { FxHashMap<(Ty<'tcx>, Option>), Pointer>, } +// 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>, + /// 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>, 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); diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 2b244a04d2223..04f317401f15d 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -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>>, - // 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, K, V, marker::Leaf>, marker::Edge>>, } diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index aa1b5529df222..a2c7da6e6958e 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -568,6 +568,7 @@ pub unsafe fn align_of_val_raw(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() -> bool { intrinsics::needs_drop::() } diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md index fe426c4cec768..d8c704f451bfc 100644 --- a/src/bootstrap/CHANGELOG.md +++ b/src/bootstrap/CHANGELOG.md @@ -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 diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 4beeb9c87c4fd..6856cd338cfad 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -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[..]), diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index ead0bd0413b9c..371631154f72d 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -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 ({} -> {})", diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 795244e7cd4a4..c1a9d4fcd23fe 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -47,6 +47,9 @@ pub enum Subcommand { paths: Vec, }, Check { + // Whether to run checking over all targets (e.g., unit / integration + // tests). + all_targets: bool, paths: Vec, }, Clippy { @@ -250,6 +253,9 @@ To learn more about a subcommand, run `./x.py -h`", `//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 { diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 8fc9a009dce01..b2aa5844e4766 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -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 && \ diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index cf94ea384fd60..f234dc5c03b31 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -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; } diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr index 33260fa0e1e66..9ec9dd4bc9ab7 100644 --- a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr +++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr @@ -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 diff --git a/src/test/rustdoc-ui/intra-link-errors.rs b/src/test/rustdoc-ui/intra-link-errors.rs index 0278caf308776..ef928ae02f3e3 100644 --- a/src/test/rustdoc-ui/intra-link-errors.rs +++ b/src/test/rustdoc-ui/intra-link-errors.rs @@ -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 diff --git a/src/test/rustdoc-ui/intra-link-errors.stderr b/src/test/rustdoc-ui/intra-link-errors.stderr index b63f799535a1f..31e7fc48afde5 100644 --- a/src/test/rustdoc-ui/intra-link-errors.stderr +++ b/src/test/rustdoc-ui/intra-link-errors.stderr @@ -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 diff --git a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr index d946aa939800c..d8afa9e7efd59 100644 --- a/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr +++ b/src/test/rustdoc-ui/intra-link-span-ice-55723.stderr @@ -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 diff --git a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr index 76a2ac0c8cf02..67c48378fd2f4 100644 --- a/src/test/rustdoc-ui/intra-links-warning-crlf.stderr +++ b/src/test/rustdoc-ui/intra-links-warning-crlf.stderr @@ -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 `\]` diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr index 09db465df59fb..4cdb8bbdde782 100644 --- a/src/test/rustdoc-ui/intra-links-warning.stderr +++ b/src/test/rustdoc-ui/intra-links-warning.stderr @@ -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) diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr index 4e9134ea469bd..32be90193fe90 100644 --- a/src/test/rustdoc-ui/lint-group.stderr +++ b/src/test/rustdoc-ui/lint-group.stderr @@ -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 diff --git a/src/test/ui/const-generics/issues/issue-75299.rs b/src/test/ui/const-generics/issues/issue-75299.rs new file mode 100644 index 0000000000000..23f30a1eea073 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-75299.rs @@ -0,0 +1,11 @@ +// compile-flags: -Zmir-opt-level=3 +// run-pass + +#![feature(const_generics)] +#![allow(incomplete_features)] +fn main() { + fn foo() -> [u8; N] { + [0; N] + } + let _x = foo::<1>(); +} diff --git a/src/test/ui/drop-bounds/drop-bounds-impl-drop.rs b/src/test/ui/drop-bounds/drop-bounds-impl-drop.rs new file mode 100644 index 0000000000000..063efc7b31abd --- /dev/null +++ b/src/test/ui/drop-bounds/drop-bounds-impl-drop.rs @@ -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(); +} diff --git a/src/test/ui/drop-bounds/drop-bounds.rs b/src/test/ui/drop-bounds/drop-bounds.rs new file mode 100644 index 0000000000000..c73538278d3be --- /dev/null +++ b/src/test/ui/drop-bounds/drop-bounds.rs @@ -0,0 +1,19 @@ +#![deny(drop_bounds)] +fn foo() {} //~ ERROR +fn bar() +where + U: Drop, //~ ERROR +{ +} +fn baz(_x: impl Drop) {} //~ ERROR +struct Foo { //~ ERROR + _x: T +} +struct Bar where U: Drop { //~ ERROR + _x: U +} +trait Baz: Drop { //~ ERROR +} +impl Baz for T { //~ ERROR +} +fn main() {} diff --git a/src/test/ui/drop-bounds/drop-bounds.stderr b/src/test/ui/drop-bounds/drop-bounds.stderr new file mode 100644 index 0000000000000..15ba4c9a64989 --- /dev/null +++ b/src/test/ui/drop-bounds/drop-bounds.stderr @@ -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() {} + | ^^^^ + | +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 { + | ^^^^ + +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 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 Baz for T { + | ^^^^ + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/error-codes/E0777.rs b/src/test/ui/error-codes/E0777.rs new file mode 100644 index 0000000000000..ff70f73686665 --- /dev/null +++ b/src/test/ui/error-codes/E0777.rs @@ -0,0 +1,7 @@ +#[derive("Clone")] //~ ERROR E0777 +#[derive("Clone +")] +//~^^ ERROR E0777 +struct Foo; + +fn main() {} diff --git a/src/test/ui/error-codes/E0777.stderr b/src/test/ui/error-codes/E0777.stderr new file mode 100644 index 0000000000000..ea73c58993e2b --- /dev/null +++ b/src/test/ui/error-codes/E0777.stderr @@ -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`. diff --git a/src/test/ui/issues/issue-68951.rs b/src/test/ui/issues/issue-68951.rs new file mode 100644 index 0000000000000..1c1e92c5bbcbb --- /dev/null +++ b/src/test/ui/issues/issue-68951.rs @@ -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; + } +} diff --git a/src/test/ui/mir/issue-77359-simplify-arm-identity-.rs b/src/test/ui/mir/issue-77359-simplify-arm-identity.rs similarity index 100% rename from src/test/ui/mir/issue-77359-simplify-arm-identity-.rs rename to src/test/ui/mir/issue-77359-simplify-arm-identity.rs diff --git a/src/test/ui/pattern/issue-66501.rs b/src/test/ui/pattern/issue-66501.rs new file mode 100644 index 0000000000000..ffcfd4ad83e1f --- /dev/null +++ b/src/test/ui/pattern/issue-66501.rs @@ -0,0 +1,12 @@ +// check-pass + +#![allow(unreachable_patterns)] + +fn main() { + const CONST: &[Option<()>; 1] = &[Some(())]; + match &[Some(())] { + &[None] => {} + CONST => {} + &[Some(())] => {} + } +} diff --git a/src/test/ui/pattern/issue-72565.rs b/src/test/ui/pattern/issue-72565.rs new file mode 100644 index 0000000000000..1e262fd506765 --- /dev/null +++ b/src/test/ui/pattern/issue-72565.rs @@ -0,0 +1,8 @@ +const F: &'static dyn PartialEq = &7u32; + +fn main() { + let a: &dyn PartialEq = &7u32; + match a { + F => panic!(), //~ ERROR: `&dyn PartialEq` cannot be used in patterns + } +} diff --git a/src/test/ui/pattern/issue-72565.stderr b/src/test/ui/pattern/issue-72565.stderr new file mode 100644 index 0000000000000..2f82616b27764 --- /dev/null +++ b/src/test/ui/pattern/issue-72565.stderr @@ -0,0 +1,8 @@ +error: `&dyn PartialEq` cannot be used in patterns + --> $DIR/issue-72565.rs:6:9 + | +LL | F => panic!(), + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/simd/shuffle-not-out-of-bounds.rs b/src/test/ui/simd/shuffle-not-out-of-bounds.rs new file mode 100644 index 0000000000000..8a533453e75fd --- /dev/null +++ b/src/test/ui/simd/shuffle-not-out-of-bounds.rs @@ -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(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)); +} diff --git a/src/test/ui/simd/shuffle-not-out-of-bounds.stderr b/src/test/ui/simd/shuffle-not-out-of-bounds.stderr new file mode 100644 index 0000000000000..4806f2ca27b9e --- /dev/null +++ b/src/test/ui/simd/shuffle-not-out-of-bounds.stderr @@ -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`. diff --git a/src/test/ui/type-alias-impl-trait/issue-74244.rs b/src/test/ui/type-alias-impl-trait/issue-74244.rs new file mode 100644 index 0000000000000..bb4104b3d2519 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-74244.rs @@ -0,0 +1,20 @@ +#![feature(type_alias_impl_trait)] + +trait Allocator { + type Buffer; +} + +struct DefaultAllocator; + +impl Allocator for DefaultAllocator { + //~^ ERROR: the type parameter `T` is not constrained + type Buffer = (); +} + +type A = impl Fn(::Buffer); + +fn foo() -> A { + |_| () +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/issue-74244.stderr b/src/test/ui/type-alias-impl-trait/issue-74244.stderr new file mode 100644 index 0000000000000..ff6bacd277e1e --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-74244.stderr @@ -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 Allocator for DefaultAllocator { + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index c17a0e8333058..c5884361dff9d 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -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`" +} diff --git a/src/tools/clippy/clippy_lints/src/drop_bounds.rs b/src/tools/clippy/clippy_lints/src/drop_bounds.rs deleted file mode 100644 index ec3b6afa6300f..0000000000000 --- a/src/tools/clippy/clippy_lints/src/drop_bounds.rs +++ /dev/null @@ -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() {} - /// ``` - /// Could be written as: - /// ```rust - /// fn foo() {} - /// ``` - 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 - ); - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index c3ff34e6e1eed..70efdaeb9c669 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -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), diff --git a/src/tools/clippy/clippy_lints/src/utils/paths.rs b/src/tools/clippy/clippy_lints/src/utils/paths.rs index 1583afad208ab..be837a61dc07e 100644 --- a/src/tools/clippy/clippy_lints/src/utils/paths.rs +++ b/src/tools/clippy/clippy_lints/src/utils/paths.rs @@ -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"]; diff --git a/src/tools/clippy/src/lintlist/mod.rs b/src/tools/clippy/src/lintlist/mod.rs index 9603023ed0671..f6d529de9a3a2 100644 --- a/src/tools/clippy/src/lintlist/mod.rs +++ b/src/tools/clippy/src/lintlist/mod.rs @@ -423,13 +423,6 @@ pub static ref ALL_LINTS: Vec = 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", diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs index 3eefb232780f1..9e32fe36ece4d 100644 --- a/src/tools/clippy/tests/ui/deprecated.rs +++ b/src/tools/clippy/tests/ui/deprecated.rs @@ -8,5 +8,6 @@ #[warn(clippy::into_iter_on_array)] #[warn(clippy::unused_label)] #[warn(clippy::regex_macro)] +#[warn(clippy::drop_bounds)] fn main() {} diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr index a80e2bf31feb6..d3400a7be09fd 100644 --- a/src/tools/clippy/tests/ui/deprecated.stderr +++ b/src/tools/clippy/tests/ui/deprecated.stderr @@ -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 diff --git a/src/tools/clippy/tests/ui/drop_bounds.rs b/src/tools/clippy/tests/ui/drop_bounds.rs deleted file mode 100644 index 6d6a9dc078399..0000000000000 --- a/src/tools/clippy/tests/ui/drop_bounds.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![allow(unused)] -fn foo() {} -fn bar() -where - T: Drop, -{ -} -fn main() {} diff --git a/src/tools/clippy/tests/ui/drop_bounds.stderr b/src/tools/clippy/tests/ui/drop_bounds.stderr deleted file mode 100644 index 8208c0ed7e398..0000000000000 --- a/src/tools/clippy/tests/ui/drop_bounds.stderr +++ /dev/null @@ -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() {} - | ^^^^ - | - = 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 - diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 356705305d78b..0c52fee68a968 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -116,7 +116,6 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "libz-sys", "lock_api", "log", - "log_settings", "maybe-uninit", "md-5", "measureme",