diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 1a6e56947916f..ac37c4973d870 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -700,11 +700,11 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option match args.named_args.get(&name) { + parse::ArgumentNamed(name, span) => match args.named_args.get(&name) { Some(&idx) => Some(idx), None => { let msg = format!("there is no argument named `{}`", name); - ecx.struct_span_err(span, &msg).emit(); + ecx.struct_span_err(template_span.from_inner(span), &msg).emit(); None } }, diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 584fbd1b605cd..6141d00f69712 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -11,7 +11,7 @@ use rustc_errors::{pluralize, Applicability, DiagnosticBuilder}; use rustc_expand::base::{self, *}; use rustc_parse_format as parse; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::{MultiSpan, Span}; +use rustc_span::{InnerSpan, MultiSpan, Span}; use smallvec::SmallVec; use std::borrow::Cow; @@ -26,7 +26,7 @@ enum ArgumentType { enum Position { Exact(usize), Capture(usize), - Named(Symbol), + Named(Symbol, InnerSpan), } struct Context<'a, 'b> { @@ -247,13 +247,13 @@ impl<'a, 'b> Context<'a, 'b> { match *p { parse::String(_) => {} parse::NextArgument(ref mut arg) => { - if let parse::ArgumentNamed(s) = arg.position { + if let parse::ArgumentNamed(s, _) = arg.position { arg.position = parse::ArgumentIs(lookup(s)); } - if let parse::CountIsName(s) = arg.format.width { + if let parse::CountIsName(s, _) = arg.format.width { arg.format.width = parse::CountIsParam(lookup(s)); } - if let parse::CountIsName(s) = arg.format.precision { + if let parse::CountIsName(s, _) = arg.format.precision { arg.format.precision = parse::CountIsParam(lookup(s)); } } @@ -276,7 +276,7 @@ impl<'a, 'b> Context<'a, 'b> { // it's written second, so it should come after width/precision. let pos = match arg.position { parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => Exact(i), - parse::ArgumentNamed(s) => Named(s), + parse::ArgumentNamed(s, span) => Named(s, span), }; let ty = Placeholder(match arg.format.ty { @@ -346,8 +346,8 @@ impl<'a, 'b> Context<'a, 'b> { parse::CountIsParam(i) => { self.verify_arg_type(Exact(i), Count); } - parse::CountIsName(s) => { - self.verify_arg_type(Named(s), Count); + parse::CountIsName(s, span) => { + self.verify_arg_type(Named(s, span), Count); } } } @@ -533,7 +533,7 @@ impl<'a, 'b> Context<'a, 'b> { } } - Named(name) => { + Named(name, span) => { match self.names.get(&name) { Some(&idx) => { // Treat as positional arg. @@ -548,7 +548,7 @@ impl<'a, 'b> Context<'a, 'b> { self.arg_types.push(Vec::new()); self.arg_unique_types.push(Vec::new()); let span = if self.is_literal { - *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp) + self.fmtsp.from_inner(span) } else { self.fmtsp }; @@ -559,7 +559,7 @@ impl<'a, 'b> Context<'a, 'b> { } else { let msg = format!("there is no argument named `{}`", name); let sp = if self.is_literal { - *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp) + self.fmtsp.from_inner(span) } else { self.fmtsp }; @@ -629,7 +629,7 @@ impl<'a, 'b> Context<'a, 'b> { } parse::CountImplied => count(sym::Implied, None), // should never be the case, names are already resolved - parse::CountIsName(_) => panic!("should never happen"), + parse::CountIsName(..) => panic!("should never happen"), } } @@ -676,7 +676,7 @@ impl<'a, 'b> Context<'a, 'b> { // should never be the case, because names are already // resolved. - parse::ArgumentNamed(_) => panic!("should never happen"), + parse::ArgumentNamed(..) => panic!("should never happen"), } }; diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index b3006672e2220..24c8245d3811c 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -1,38 +1,56 @@ -//! Generalized type folding mechanism. The setup is a bit convoluted -//! but allows for convenient usage. Let T be an instance of some -//! "foldable type" (one which implements `TypeFoldable`) and F be an -//! instance of a "folder" (a type which implements `TypeFolder`). Then -//! the setup is intended to be: +//! A generalized traversal mechanism for complex data structures that contain +//! type information. //! -//! T.fold_with(F) --calls--> F.fold_T(T) --calls--> T.super_fold_with(F) +//! There are two types of traversal. +//! - Folding. This is a modifying traversal. It consumes the data structure, +//! producing a (possibly) modified version of it. Both fallible and +//! infallible versions are available. The name is potentially +//! confusing, because this traversal is more like `Iterator::map` than +//! `Iterator::fold`. +//! - Visiting. This is a read-only traversal of the data structure. //! -//! This way, when you define a new folder F, you can override -//! `fold_T()` to customize the behavior, and invoke `T.super_fold_with()` -//! to get the original behavior. Meanwhile, to actually fold -//! something, you can just write `T.fold_with(F)`, which is -//! convenient. (Note that `fold_with` will also transparently handle -//! things like a `Vec` where T is foldable and so on.) +//! These traversals have limited flexibility. Only a small number of "types of +//! interest" within the complex data structures can receive custom +//! modification (when folding) or custom visitation (when visiting). These are +//! the ones containing the most important type-related information, such as +//! `Ty`, `Predicate`, `Region`, and `Const`. //! -//! In this ideal setup, the only function that actually *does* -//! anything is `T.super_fold_with()`, which traverses the type `T`. -//! Moreover, `T.super_fold_with()` should only ever call `T.fold_with()`. +//! There are two traits involved in each traversal type. +//! - The first trait is `TypeFoldable`, which is implemented once for many +//! types. This includes both (a) types of interest, and (b) all other +//! relevant types, including generic containers like `Vec` and `Option`. It +//! defines a "skeleton" of how they should be traversed, for both folding +//! and visiting. +//! - The second trait is `TypeFolder`/`FallibleTypeFolder` (for +//! infallible/fallible folding traversals) or `TypeVisitor` (for visiting +//! traversals). One of these is implemented for each folder/visitor. This +//! defines how types of interest are handled. //! -//! In some cases, we follow a degenerate pattern where we do not have -//! a `fold_T` method. Instead, `T.fold_with` traverses the structure directly. -//! This is suboptimal because the behavior cannot be overridden, but it's -//! much less work to implement. If you ever *do* need an override that -//! doesn't exist, it's not hard to convert the degenerate pattern into the -//! proper thing. +//! This means each traversal is a mixture of (a) generic traversal operations, +//! and (b) custom fold/visit operations that are specific to the +//! folder/visitor. +//! - The `TypeFoldable` impls handle most of the traversal, and call into +//! `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` when they encounter a +//! type of interest. +//! - A `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` may also call back into +//! a `TypeFoldable` impl, because (a) the types of interest are recursive +//! and can contain other types of interest, and (b) each folder/visitor +//! might provide custom handling only for some types of interest, or only +//! for some variants of each type of interest, and then use default +//! traversal for the remaining cases. //! -//! A `TypeFoldable` T can also be visited by a `TypeVisitor` V using similar setup: -//! -//! T.visit_with(V) --calls--> V.visit_T(T) --calls--> T.super_visit_with(V). -//! -//! These methods return true to indicate that the visitor has found what it is -//! looking for, and does not need to visit anything else. +//! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U: +//! TypeFoldable`, and an instance `S(ty, u)`, it would be visited like so: +//! ``` +//! s.visit_with(visitor) calls +//! - s.super_visit_with(visitor) calls +//! - ty.visit_with(visitor) calls +//! - visitor.visit_ty(ty) may call +//! - ty.super_visit_with(visitor) +//! - u.visit_with(visitor) +//! ``` use crate::mir; use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags}; -use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_data_structures::fx::FxHashSet; @@ -41,42 +59,67 @@ use std::collections::BTreeMap; use std::fmt; use std::ops::ControlFlow; -/// This trait is implemented for every type that can be folded. -/// Basically, every type that has a corresponding method in `TypeFolder`. +/// This trait is implemented for every type that can be folded/visited, +/// providing the skeleton of the traversal. /// -/// To implement this conveniently, use the derive macro located in `rustc_macros`. +/// To implement this conveniently, use the derive macro located in +/// `rustc_macros`. pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { - /// Consumers may find this more convenient to use with infallible folders than - /// [`try_super_fold_with`][`TypeFoldable::try_super_fold_with`], to which the - /// provided default definition delegates. Implementors **should not** override - /// this provided default definition, to ensure that the two methods are coherent - /// (provide a definition of `try_super_fold_with` instead). - fn super_fold_with>(self, folder: &mut F) -> Self { - self.try_super_fold_with(folder).into_ok() + /// The main entry point for folding. To fold a value `t` with a folder `f` + /// call: `t.try_fold_with(f)`. + /// + /// For types of interest (such as `Ty`), this default is overridden with a + /// method that calls a folder method specifically for that type (such as + /// `F::try_fold_ty`). This is where control transfers from `TypeFoldable` + /// to `TypeFolder`. + /// + /// For other types, this default is used. + fn try_fold_with>(self, folder: &mut F) -> Result { + self.try_super_fold_with(folder) } - /// Consumers may find this more convenient to use with infallible folders than - /// [`try_fold_with`][`TypeFoldable::try_fold_with`], to which the provided - /// default definition delegates. Implementors **should not** override this - /// provided default definition, to ensure that the two methods are coherent - /// (provide a definition of `try_fold_with` instead). + + /// A convenient alternative to [`try_fold_with`] for use with infallible + /// folders. Do not override this method, to ensure coherence with + /// `try_fold_with`. fn fold_with>(self, folder: &mut F) -> Self { self.try_fold_with(folder).into_ok() } + /// Traverses the type in question, typically by calling `try_fold_with` on + /// each field/element. This is true even for types of interest such as + /// `Ty`. This should only be called within `TypeFolder` methods, when + /// non-custom traversals are desired for types of interest. fn try_super_fold_with>( self, folder: &mut F, ) -> Result; - fn try_fold_with>(self, folder: &mut F) -> Result { - self.try_super_fold_with(folder) + /// A convenient alternative to [`try_super_fold_with`] for use with + /// infallible folders. Do not override this method, to ensure coherence + /// with `try_super_fold_with`. + fn super_fold_with>(self, folder: &mut F) -> Self { + self.try_super_fold_with(folder).into_ok() } - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow; + /// The entry point for visiting. To visit a value `t` with a visitor `v` + /// call: `t.visit_with(v)`. + /// + /// For types of interest (such as `Ty`), this default is overridden with a + /// method that calls a visitor method specifically for that type (such as + /// `V::visit_ty`). This is where control transfers from `TypeFoldable` to + /// `TypeVisitor`. + /// + /// For other types, this default is used. fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.super_visit_with(visitor) } + /// Traverses the type in question, typically by calling `visit_with` on + /// each field/element. This is true even for types of interest such as + /// `Ty`. This should only be called within `TypeVisitor` methods, when + /// non-custom traversals are desired for types of interest. + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow; + /// Returns `true` if `self` has any late-bound regions that are either /// bound by `binder` or bound by some binder outside of `binder`. /// If `binder` is `ty::INNERMOST`, this indicates whether @@ -168,24 +211,13 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { } } -impl<'tcx> TypeFoldable<'tcx> for hir::Constness { - fn try_super_fold_with>(self, _: &mut F) -> Result { - Ok(self) - } - fn super_visit_with>(&self, _: &mut V) -> ControlFlow { - ControlFlow::CONTINUE - } -} - -/// The `TypeFolder` trait defines the actual *folding*. There is a -/// method defined for every foldable type. Each of these has a -/// default implementation that does an "identity" fold. Within each -/// identity fold, it should invoke `foo.fold_with(self)` to fold each -/// sub-item. +/// This trait is implemented for every folding traversal. There is a fold +/// method defined for every type of interest. Each such method has a default +/// that does an "identity" fold. /// /// If this folder is fallible (and therefore its [`Error`][`TypeFolder::Error`] -/// associated type is something other than the default, never), -/// [`FallibleTypeFolder`] should be implemented manually; otherwise, +/// associated type is something other than the default `!`) then +/// [`FallibleTypeFolder`] should be implemented manually. Otherwise, /// a blanket implementation of [`FallibleTypeFolder`] will defer to /// the infallible methods of this trait to ensure that the two APIs /// are coherent. @@ -238,11 +270,9 @@ pub trait TypeFolder<'tcx>: Sized { } } -/// The `FallibleTypeFolder` trait defines the actual *folding*. There is a -/// method defined for every foldable type. Each of these has a -/// default implementation that does an "identity" fold. Within each -/// identity fold, it should invoke `foo.try_fold_with(self)` to fold each -/// sub-item. +/// This trait is implemented for every folding traversal. There is a fold +/// method defined for every type of interest. Each such method has a default +/// that does an "identity" fold. /// /// A blanket implementation of this trait (that defers to the relevant /// method of [`TypeFolder`]) is provided for all infallible folders in @@ -282,8 +312,8 @@ pub trait FallibleTypeFolder<'tcx>: TypeFolder<'tcx> { } } -// Blanket implementation of fallible trait for infallible folders -// delegates to infallible methods to prevent incoherence +// This blanket implementation of the fallible trait for infallible folders +// delegates to infallible methods to ensure coherence. impl<'tcx, F> FallibleTypeFolder<'tcx> for F where F: TypeFolder<'tcx, Error = !>, @@ -322,6 +352,9 @@ where } } +/// This trait is implemented for every visiting traversal. There is a visit +/// method defined for every type of interest. Each such method has a default +/// that recurses into the type's fields in a non-custom fashion. pub trait TypeVisitor<'tcx>: Sized { type BreakTy = !; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index c1d714ed8d65e..e4691dee7793a 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -8,6 +8,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::{self, InferConst, Lift, Term, Ty, TyCtxt}; use rustc_data_structures::functor::IdFunctor; +use rustc_hir as hir; use rustc_hir::def::Namespace; use rustc_hir::def_id::CRATE_DEF_INDEX; use rustc_index::vec::{Idx, IndexVec}; @@ -663,14 +664,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> { /////////////////////////////////////////////////////////////////////////// // TypeFoldable implementations. -// -// Ideally, each type should invoke `folder.fold_foo(self)` and -// nothing else. In some cases, though, we haven't gotten around to -// adding methods on the `folder` yet, and thus the folding is -// hard-coded here. This is less-flexible, because folders cannot -// override the behavior, but there are a lot of random types and one -// can easily refactor the folding into the TypeFolder trait as -// needed. /// AdtDefs are basically the same as a DefId. impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::AdtDef { @@ -1270,3 +1263,13 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> { self.substs.visit_with(visitor) } } + +impl<'tcx> TypeFoldable<'tcx> for hir::Constness { + fn try_super_fold_with>(self, _: &mut F) -> Result { + Ok(self) + } + + fn super_visit_with>(&self, _: &mut V) -> ControlFlow { + ControlFlow::CONTINUE + } +} diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 9d653de910fec..a6a2cbc277c20 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -95,7 +95,7 @@ pub enum Position { /// The argument is located at a specific index given in the format ArgumentIs(usize), /// The argument has a name. - ArgumentNamed(Symbol), + ArgumentNamed(Symbol, InnerSpan), } impl Position { @@ -147,7 +147,7 @@ pub enum Count { /// The count is specified explicitly. CountIs(usize), /// The count is specified by the argument with the given name. - CountIsName(Symbol), + CountIsName(Symbol, InnerSpan), /// The count is specified by the argument at the given index. CountIsParam(usize), /// The count is implied and cannot be explicitly specified. @@ -494,8 +494,11 @@ impl<'a> Parser<'a> { Some(ArgumentIs(i)) } else { match self.cur.peek() { - Some(&(_, c)) if rustc_lexer::is_id_start(c) => { - Some(ArgumentNamed(Symbol::intern(self.word()))) + Some(&(start, c)) if rustc_lexer::is_id_start(c) => { + let word = self.word(); + let end = start + word.len(); + let span = self.to_span_index(start).to(self.to_span_index(end)); + Some(ArgumentNamed(Symbol::intern(word), span)) } // This is an `ArgumentNext`. @@ -662,8 +665,9 @@ impl<'a> Parser<'a> { if word.is_empty() { self.cur = tmp; (CountImplied, None) - } else if self.consume('$') { - (CountIsName(Symbol::intern(word)), None) + } else if let Some(end) = self.consume_pos('$') { + let span = self.to_span_index(start + 1).to(self.to_span_index(end)); + (CountIsName(Symbol::intern(word), span), None) } else { self.cur = tmp; (CountImplied, None) diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs index b7693a85ad955..6c960fdc72bfd 100644 --- a/compiler/rustc_parse_format/src/tests.rs +++ b/compiler/rustc_parse_format/src/tests.rs @@ -221,8 +221,8 @@ fn format_counts() { fill: None, align: AlignUnknown, flags: 0, - precision: CountIsName(Symbol::intern("b")), - width: CountIsName(Symbol::intern("a")), + precision: CountIsName(Symbol::intern("b"), InnerSpan::new(6, 7)), + width: CountIsName(Symbol::intern("a"), InnerSpan::new(4, 4)), precision_span: None, width_span: None, ty: "?", diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index bdf677a63b632..b05dbbe898a41 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -309,23 +309,23 @@ impl<'tcx> OnUnimplementedFormatString { Piece::String(_) => (), // Normal string, no need to check it Piece::NextArgument(a) => match a.position { // `{Self}` is allowed - Position::ArgumentNamed(s) if s == kw::SelfUpper => (), + Position::ArgumentNamed(s, _) if s == kw::SelfUpper => (), // `{ThisTraitsName}` is allowed - Position::ArgumentNamed(s) if s == name => (), + Position::ArgumentNamed(s, _) if s == name => (), // `{from_method}` is allowed - Position::ArgumentNamed(s) if s == sym::from_method => (), + Position::ArgumentNamed(s, _) if s == sym::from_method => (), // `{from_desugaring}` is allowed - Position::ArgumentNamed(s) if s == sym::from_desugaring => (), + Position::ArgumentNamed(s, _) if s == sym::from_desugaring => (), // `{ItemContext}` is allowed - Position::ArgumentNamed(s) if s == sym::ItemContext => (), + Position::ArgumentNamed(s, _) if s == sym::ItemContext => (), // `{integral}` and `{integer}` and `{float}` are allowed - Position::ArgumentNamed(s) + Position::ArgumentNamed(s, _) if s == sym::integral || s == sym::integer_ || s == sym::float => { () } // So is `{A}` if A is a type parameter - Position::ArgumentNamed(s) => { + Position::ArgumentNamed(s, _) => { match generics.params.iter().find(|param| param.name == s) { Some(_) => (), None => { @@ -392,7 +392,7 @@ impl<'tcx> OnUnimplementedFormatString { .map(|p| match p { Piece::String(s) => s, Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s) => match generic_map.get(&s) { + Position::ArgumentNamed(s, _) => match generic_map.get(&s) { Some(val) => val, None if s == name => &trait_str, None => { diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 27c8a19783557..6dbda1005dd19 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -382,10 +382,15 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b tcx.sess, field_span, E0740, - "unions may not contain fields that need dropping" + "unions cannot contain fields that may need dropping" + ) + .note( + "a type is guaranteed not to need dropping \ + when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type", ) .multipart_suggestion_verbose( - "wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped", + "when the type does not implement `Copy`, \ + wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped", vec![ (ty_span.shrink_to_lo(), format!("std::mem::ManuallyDrop<")), (ty_span.shrink_to_hi(), ">".into()), diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 81e2b3bc1621f..a523ba286ec84 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -9,8 +9,10 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::{simplify_type, SimplifyParams}; use rustc_middle::ty::print::with_crate_prefix; +use rustc_middle::ty::ToPolyTraitRef; use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_span::lev_distance; use rustc_span::symbol::{kw, sym, Ident}; @@ -40,7 +42,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Err(..) => return false, }; + // This conditional prevents us from asking to call errors and unresolved types. + // It might seem that we can use `predicate_must_hold_modulo_regions`, + // but since a Dummy binder is used to fill in the FnOnce trait's arguments, + // type resolution always gives a "maybe" here. + if self.autoderef(span, ty).any(|(ty, _)| { + info!("check deref {:?} error", ty); + matches!(ty.kind(), ty::Error(_) | ty::Infer(_)) + }) { + return false; + } + self.autoderef(span, ty).any(|(ty, _)| { + info!("check deref {:?} impl FnOnce", ty); self.probe(|_| { let fn_once_substs = tcx.mk_substs_trait( ty, @@ -1196,9 +1210,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(adt) if adt.did.is_local() => adt, _ => continue, }; - let can_derive = match self.tcx.get_diagnostic_name(trait_pred.def_id()) { - Some(sym::Default) => !adt.is_enum(), - Some( + if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) { + let can_derive = match diagnostic_name { + sym::Default => !adt.is_enum(), sym::Eq | sym::PartialEq | sym::Ord @@ -1206,16 +1220,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | sym::Clone | sym::Copy | sym::Hash - | sym::Debug, - ) => true, - _ => false, - }; - if can_derive { - derives.push(( - format!("{}", trait_pred.self_ty()), - self.tcx.def_span(adt.did), - format!("{}", trait_pred.trait_ref.print_only_trait_name()), - )); + | sym::Debug => true, + _ => false, + }; + if can_derive { + let self_name = trait_pred.self_ty().to_string(); + let self_span = self.tcx.def_span(adt.did); + if let Some(poly_trait_ref) = pred.to_opt_poly_trait_pred() { + for super_trait in supertraits(self.tcx, poly_trait_ref.to_poly_trait_ref()) + { + if let Some(parent_diagnostic_name) = + self.tcx.get_diagnostic_name(super_trait.def_id()) + { + derives.push(( + self_name.clone(), + self_span.clone(), + parent_diagnostic_name.to_string(), + )); + } + } + } + derives.push((self_name, self_span, diagnostic_name.to_string())); + } else { + traits.push(self.tcx.def_span(trait_pred.def_id())); + } } else { traits.push(self.tcx.def_span(trait_pred.def_id())); } diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 320f5a97e0a24..e034adde1be86 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -2029,34 +2029,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.help("the semantics of slice patterns changed recently; see issue #62254"); } } else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span) - .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..))) + .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..))) { if let (Some(span), true) = (ti.span, ti.origin_expr) { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - let applicability = match self.resolve_vars_if_possible(ti.expected).kind() { - ty::Adt(adt_def, _) - if self.tcx.is_diagnostic_item(sym::Option, adt_def.did) - || self.tcx.is_diagnostic_item(sym::Result, adt_def.did) => - { - // Slicing won't work here, but `.as_deref()` might (issue #91328). - err.span_suggestion( - span, - "consider using `as_deref` here", - format!("{}.as_deref()", snippet), - Applicability::MaybeIncorrect, - ); - None - } - // FIXME: instead of checking for Vec only, we could check whether the - // type implements `Deref`; see - // https://github.com/rust-lang/rust/pull/91343#discussion_r761466979 - ty::Adt(adt_def, _) - if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did) => - { - Some(Applicability::MachineApplicable) + let applicability = Autoderef::new( + &self.infcx, + self.param_env, + self.body_id, + span, + self.resolve_vars_if_possible(ti.expected), + span, + ) + .find_map(|(ty, _)| { + match ty.kind() { + ty::Adt(adt_def, _) + if self.tcx.is_diagnostic_item(sym::Option, adt_def.did) + || self.tcx.is_diagnostic_item(sym::Result, adt_def.did) => + { + // Slicing won't work here, but `.as_deref()` might (issue #91328). + err.span_suggestion( + span, + "consider using `as_deref` here", + format!("{}.as_deref()", snippet), + Applicability::MaybeIncorrect, + ); + Some(None) + } + + ty::Slice(..) | ty::Array(..) => { + Some(Some(Applicability::MachineApplicable)) + } + + _ => None, } - _ => Some(Applicability::MaybeIncorrect), - }; + }) + .unwrap_or(Some(Applicability::MaybeIncorrect)); if let Some(applicability) = applicability { err.span_suggestion( diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index cdb961d4cfbc5..67f5b386ecd7f 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -2052,6 +2052,8 @@ where #[stable(feature = "std_collections_from_array", since = "1.56.0")] impl From<[(K, V); N]> for BTreeMap { + /// Converts a `[(K, V); N]` into a `BTreeMap<(K, V)>`. + /// /// ``` /// use std::collections::BTreeMap; /// diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 31df4e98ed746..a4315be74e36c 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1097,6 +1097,8 @@ impl FromIterator for BTreeSet { #[stable(feature = "std_collections_from_array", since = "1.56.0")] impl From<[T; N]> for BTreeSet { + /// Converts a `[T; N]` into a `BTreeSet`. + /// /// ``` /// use std::collections::BTreeSet; /// diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 4a07d5d4bed10..d81f24e72024d 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1953,6 +1953,8 @@ impl Hash for LinkedList { #[stable(feature = "std_collections_from_array", since = "1.56.0")] impl From<[T; N]> for LinkedList { + /// Converts a `[T; N]` into a `LinkedList`. + /// /// ``` /// use std::collections::LinkedList; /// diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index db2ad5e8d285c..763175fc0451f 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -3049,6 +3049,8 @@ impl From> for Vec { #[stable(feature = "std_collections_from_array", since = "1.56.0")] impl From<[T; N]> for VecDeque { + /// Converts a `[T; N]` into a `VecDeque`. + /// /// ``` /// use std::collections::VecDeque; /// diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index bd3262b51d480..3dc3eee4133b6 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2906,10 +2906,6 @@ impl From<&mut [T]> for Vec { #[cfg(not(no_global_oom_handling))] #[stable(feature = "vec_from_array", since = "1.44.0")] impl From<[T; N]> for Vec { - #[cfg(not(test))] - fn from(s: [T; N]) -> Vec { - <[T]>::into_vec(box s) - } /// Allocate a `Vec` and move `s`'s items into it. /// /// # Examples @@ -2917,6 +2913,11 @@ impl From<[T; N]> for Vec { /// ``` /// assert_eq!(Vec::from([1, 2, 3]), vec![1, 2, 3]); /// ``` + #[cfg(not(test))] + fn from(s: [T; N]) -> Vec { + <[T]>::into_vec(box s) + } + #[cfg(test)] fn from(s: [T; N]) -> Vec { crate::slice::into_vec(box s) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index feb9455565844..aef7ad7756803 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -315,6 +315,7 @@ impl Ord for Cell { #[stable(feature = "cell_from", since = "1.12.0")] #[rustc_const_unstable(feature = "const_convert", issue = "88674")] impl const From for Cell { + /// Creates a new `Cell` containing the given value. fn from(t: T) -> Cell { Cell::new(t) } @@ -1244,6 +1245,7 @@ impl Ord for RefCell { #[stable(feature = "cell_from", since = "1.12.0")] #[rustc_const_unstable(feature = "const_convert", issue = "88674")] impl const From for RefCell { + /// Creates a new `RefCell` containing the given value. fn from(t: T) -> RefCell { RefCell::new(t) } @@ -1979,6 +1981,7 @@ impl Default for UnsafeCell { #[stable(feature = "cell_from", since = "1.12.0")] #[rustc_const_unstable(feature = "const_convert", issue = "88674")] impl const From for UnsafeCell { + /// Creates a new `UnsafeCell` containing the given value. fn from(t: T) -> UnsafeCell { UnsafeCell::new(t) } diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 5566c2ffe87de..0ceedf936333d 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -538,6 +538,10 @@ impl const Into for T where U: ~const From, { + /// Calls `U::from(self)`. + /// + /// That is, this conversion is whatever the implementation of + /// [From]<T> for U chooses to do. fn into(self) -> U { U::from(self) } @@ -547,6 +551,7 @@ where #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_convert", issue = "88674")] impl const From for T { + /// Returns the argument unchanged. fn from(t: T) -> T { t } diff --git a/library/core/src/lazy.rs b/library/core/src/lazy.rs index 788f0cce01ba8..88826782a3d60 100644 --- a/library/core/src/lazy.rs +++ b/library/core/src/lazy.rs @@ -75,6 +75,7 @@ impl Eq for OnceCell {} #[unstable(feature = "once_cell", issue = "74465")] impl const From for OnceCell { + /// Creates a new `OnceCell` which already contains the given `value`. fn from(value: T) -> Self { OnceCell { inner: UnsafeCell::new(Some(value)) } } diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 3f5d3f62c9604..0aa8e9960a8dd 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -721,6 +721,9 @@ impl const From> for NonNull { #[stable(feature = "nonnull", since = "1.25.0")] #[rustc_const_unstable(feature = "const_convert", issue = "88674")] impl const From<&mut T> for NonNull { + /// Converts a `&mut T` to a `NonNull`. + /// + /// This conversion is safe and infallible since references cannot be null. #[inline] fn from(reference: &mut T) -> Self { // SAFETY: A mutable reference cannot be null. @@ -731,6 +734,9 @@ impl const From<&mut T> for NonNull { #[stable(feature = "nonnull", since = "1.25.0")] #[rustc_const_unstable(feature = "const_convert", issue = "88674")] impl const From<&T> for NonNull { + /// Converts a `&T` to a `NonNull`. + /// + /// This conversion is safe and infallible since references cannot be null. #[inline] fn from(reference: &T) -> Self { // SAFETY: A reference cannot be null, so the conditions for diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index f5c624c225f26..661d111c99d52 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -178,6 +178,9 @@ impl fmt::Pointer for Unique { #[unstable(feature = "ptr_internals", issue = "none")] impl const From<&mut T> for Unique { + /// Converts a `&mut T` to a `Unique`. + /// + /// This conversion is infallible since references cannot be null. #[inline] fn from(reference: &mut T) -> Self { // SAFETY: A mutable reference cannot be null diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 792016902aebe..9ee88dd601493 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1295,6 +1295,7 @@ impl const From for AtomicBool { #[stable(feature = "atomic_from", since = "1.23.0")] #[rustc_const_unstable(feature = "const_convert", issue = "88674")] impl const From<*mut T> for AtomicPtr { + /// Converts a `*mut T` into an `AtomicPtr`. #[inline] fn from(p: *mut T) -> Self { Self::new(p) diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 72a030617ad8a..41f0a25dbc3e0 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -243,7 +243,7 @@ impl Poll>> { #[stable(feature = "futures_api", since = "1.36.0")] #[rustc_const_unstable(feature = "const_convert", issue = "88674")] impl const From for Poll { - /// Convert to a `Ready` variant. + /// Moves the value into a [`Poll::Ready`] to make a `Poll`. /// /// # Example /// diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index c3f024026efad..6e70d5ca02d75 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -871,6 +871,8 @@ impl Borrow for CString { #[stable(feature = "cstring_from_cow_cstr", since = "1.28.0")] impl<'a> From> for CString { + /// Converts a `Cow<'a, CStr>` into a `CString`, by copying the contents if they are + /// borrowed. #[inline] fn from(s: Cow<'a, CStr>) -> Self { s.into_owned() @@ -879,6 +881,8 @@ impl<'a> From> for CString { #[stable(feature = "box_from_c_str", since = "1.17.0")] impl From<&CStr> for Box { + /// Converts a `&CStr` into a `Box`, + /// by copying the contents into a newly allocated [`Box`]. fn from(s: &CStr) -> Box { let boxed: Box<[u8]> = Box::from(s.to_bytes_with_nul()); unsafe { Box::from_raw(Box::into_raw(boxed) as *mut CStr) } @@ -887,6 +891,8 @@ impl From<&CStr> for Box { #[stable(feature = "box_from_cow", since = "1.45.0")] impl From> for Box { + /// Converts a `Cow<'a, CStr>` into a `Box`, + /// by copying the contents if they are borrowed. #[inline] fn from(cow: Cow<'_, CStr>) -> Box { match cow { @@ -984,6 +990,8 @@ impl From for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<&CStr> for Arc { + /// Converts a `&CStr` into a `Arc`, + /// by copying the contents into a newly allocated [`Arc`]. #[inline] fn from(s: &CStr) -> Arc { let arc: Arc<[u8]> = Arc::from(s.to_bytes_with_nul()); @@ -1004,6 +1012,8 @@ impl From for Rc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<&CStr> for Rc { + /// Converts a `&CStr` into a `Rc`, + /// by copying the contents into a newly allocated [`Rc`]. #[inline] fn from(s: &CStr) -> Rc { let rc: Rc<[u8]> = Rc::from(s.to_bytes_with_nul()); @@ -1530,6 +1540,7 @@ impl ToOwned for CStr { #[stable(feature = "cstring_asref", since = "1.7.0")] impl From<&CStr> for CString { + /// Copies the contents of the `&CStr` into a newly allocated `CString`. fn from(s: &CStr) -> CString { s.to_owned() } diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 81f72e34d9388..9b5e5d6c0cc4b 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -452,6 +452,8 @@ impl From for OsString { #[stable(feature = "rust1", since = "1.0.0")] impl> From<&T> for OsString { + /// Copies any value implementing [AsRef]<[OsStr]> + /// into a newly allocated [`OsString`]. fn from(s: &T) -> OsString { s.as_ref().to_os_string() } @@ -942,6 +944,7 @@ impl OsStr { #[stable(feature = "box_from_os_str", since = "1.17.0")] impl From<&OsStr> for Box { + /// Copies the string into a newly allocated [Box]<[OsStr]>. #[inline] fn from(s: &OsStr) -> Box { let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr; @@ -951,6 +954,8 @@ impl From<&OsStr> for Box { #[stable(feature = "box_from_cow", since = "1.45.0")] impl From> for Box { + /// Converts a `Cow<'a, OsStr>` into a [Box]<[OsStr]>, + /// by copying the contents if they are borrowed. #[inline] fn from(cow: Cow<'_, OsStr>) -> Box { match cow { @@ -1000,6 +1005,7 @@ impl From for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<&OsStr> for Arc { + /// Copies the string into a newly allocated [Arc]<[OsStr]>. #[inline] fn from(s: &OsStr) -> Arc { let arc = s.inner.into_arc(); @@ -1020,6 +1026,7 @@ impl From for Rc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<&OsStr> for Rc { + /// Copies the string into a newly allocated [Rc]<[OsStr]>. #[inline] fn from(s: &OsStr) -> Rc { let rc = s.inner.into_rc(); @@ -1029,6 +1036,7 @@ impl From<&OsStr> for Rc { #[stable(feature = "cow_from_osstr", since = "1.28.0")] impl<'a> From for Cow<'a, OsStr> { + /// Moves the string into a [`Cow::Owned`]. #[inline] fn from(s: OsString) -> Cow<'a, OsStr> { Cow::Owned(s) @@ -1037,6 +1045,7 @@ impl<'a> From for Cow<'a, OsStr> { #[stable(feature = "cow_from_osstr", since = "1.28.0")] impl<'a> From<&'a OsStr> for Cow<'a, OsStr> { + /// Converts the string reference into a [`Cow::Borrowed`]. #[inline] fn from(s: &'a OsStr) -> Cow<'a, OsStr> { Cow::Borrowed(s) @@ -1045,6 +1054,7 @@ impl<'a> From<&'a OsStr> for Cow<'a, OsStr> { #[stable(feature = "cow_from_osstr", since = "1.28.0")] impl<'a> From<&'a OsString> for Cow<'a, OsStr> { + /// Converts the string reference into a [`Cow::Borrowed`]. #[inline] fn from(s: &'a OsString) -> Cow<'a, OsStr> { Cow::Borrowed(s.as_os_str()) @@ -1053,6 +1063,8 @@ impl<'a> From<&'a OsString> for Cow<'a, OsStr> { #[stable(feature = "osstring_from_cow_osstr", since = "1.28.0")] impl<'a> From> for OsString { + /// Converts a `Cow<'a, OsStr>` into an [`OsString`], + /// by copying the contents if they are borrowed. #[inline] fn from(s: Cow<'a, OsStr>) -> Self { s.into_owned() diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 3f7f0f888476a..adb8b30ec0893 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -1600,7 +1600,7 @@ impl From> for Box { #[stable(feature = "path_buf_from_box", since = "1.18.0")] impl From> for PathBuf { - /// Converts a `Box` into a `PathBuf` + /// Converts a [Box]<[Path]> into a [`PathBuf`]. /// /// This conversion does not allocate or copy memory. #[inline] @@ -1611,7 +1611,7 @@ impl From> for PathBuf { #[stable(feature = "box_from_path_buf", since = "1.20.0")] impl From for Box { - /// Converts a `PathBuf` into a `Box` + /// Converts a [`PathBuf`] into a [Box]<[Path]>. /// /// This conversion currently should not allocate memory, /// but this behavior is not guaranteed on all platforms or in all future versions. @@ -1631,7 +1631,7 @@ impl Clone for Box { #[stable(feature = "rust1", since = "1.0.0")] impl> From<&T> for PathBuf { - /// Converts a borrowed `OsStr` to a `PathBuf`. + /// Converts a borrowed [`OsStr`] to a [`PathBuf`]. /// /// Allocates a [`PathBuf`] and copies the data into it. #[inline] diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 1f04890539604..e3fff155e4722 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1277,7 +1277,7 @@ impl fmt::Debug for Stdio { #[stable(feature = "stdio_from", since = "1.20.0")] impl From for Stdio { - /// Converts a `ChildStdin` into a `Stdio` + /// Converts a [`ChildStdin`] into a [`Stdio`]. /// /// # Examples /// @@ -1306,7 +1306,7 @@ impl From for Stdio { #[stable(feature = "stdio_from", since = "1.20.0")] impl From for Stdio { - /// Converts a `ChildStdout` into a `Stdio` + /// Converts a [`ChildStdout`] into a [`Stdio`]. /// /// # Examples /// @@ -1335,7 +1335,7 @@ impl From for Stdio { #[stable(feature = "stdio_from", since = "1.20.0")] impl From for Stdio { - /// Converts a `ChildStderr` into a `Stdio` + /// Converts a [`ChildStderr`] into a [`Stdio`]. /// /// # Examples /// @@ -1366,7 +1366,7 @@ impl From for Stdio { #[stable(feature = "stdio_from", since = "1.20.0")] impl From for Stdio { - /// Converts a `File` into a `Stdio` + /// Converts a [`File`](fs::File) into a [`Stdio`]. /// /// # Examples /// diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs index cb40b4e965b2a..b39701a3d4288 100644 --- a/library/test/src/cli.rs +++ b/library/test/src/cli.rs @@ -109,12 +109,10 @@ fn optgroups() -> getopts::Options { unstable-options = Allow use of experimental features", "unstable-options", ) - .optflagopt( + .optflag( "", "report-time", - "Show execution time of each test. Available values: - plain = do not colorize the execution time (default); - colored = colorize output according to the `color` parameter value; + "Show execution time of each test. Threshold values for colorized output can be configured via `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` and @@ -125,7 +123,6 @@ fn optgroups() -> getopts::Options { is 0.5 seconds, and the critical time is 2 seconds. Not available for --format=terse", - "plain|colored", ) .optflag( "", @@ -319,17 +316,12 @@ fn get_time_options( allow_unstable: bool, ) -> OptPartRes> { let report_time = unstable_optflag!(matches, allow_unstable, "report-time"); - let colored_opt_str = matches.opt_str("report-time"); - let mut report_time_colored = report_time && colored_opt_str == Some("colored".into()); let ensure_test_time = unstable_optflag!(matches, allow_unstable, "ensure-time"); // If `ensure-test-time` option is provided, time output is enforced, // so user won't be confused if any of tests will silently fail. let options = if report_time || ensure_test_time { - if ensure_test_time && !report_time { - report_time_colored = true; - } - Some(TestTimeOptions::new_from_env(ensure_test_time, report_time_colored)) + Some(TestTimeOptions::new_from_env(ensure_test_time)) } else { None }; diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs index 4726ae864df77..041df5216d7b3 100644 --- a/library/test/src/formatters/pretty.rs +++ b/library/test/src/formatters/pretty.rs @@ -98,7 +98,7 @@ impl PrettyFormatter { if let (Some(opts), Some(time)) = (self.time_options, exec_time) { let time_str = format!(" <{}>", time); - let color = if opts.colored { + let color = if self.use_color { if opts.is_critical(desc, time) { Some(term::color::RED) } else if opts.is_warn(desc, time) { diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index 9b9c520568662..d566dbc09f434 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -394,7 +394,6 @@ fn test_time_options_threshold() { let options = TestTimeOptions { error_on_excess: false, - colored: false, unit_threshold: unit.clone(), integration_threshold: integration.clone(), doctest_threshold: doc.clone(), diff --git a/library/test/src/time.rs b/library/test/src/time.rs index e0b6eadffa119..8c64e5d1b7339 100644 --- a/library/test/src/time.rs +++ b/library/test/src/time.rs @@ -137,14 +137,13 @@ pub struct TestTimeOptions { /// Denotes if the test critical execution time limit excess should be considered /// a test failure. pub error_on_excess: bool, - pub colored: bool, pub unit_threshold: TimeThreshold, pub integration_threshold: TimeThreshold, pub doctest_threshold: TimeThreshold, } impl TestTimeOptions { - pub fn new_from_env(error_on_excess: bool, colored: bool) -> Self { + pub fn new_from_env(error_on_excess: bool) -> Self { let unit_threshold = TimeThreshold::from_env_var(time_constants::UNIT_ENV_NAME) .unwrap_or_else(Self::default_unit); @@ -155,7 +154,7 @@ impl TestTimeOptions { let doctest_threshold = TimeThreshold::from_env_var(time_constants::DOCTEST_ENV_NAME) .unwrap_or_else(Self::default_doctest); - Self { error_on_excess, colored, unit_threshold, integration_threshold, doctest_threshold } + Self { error_on_excess, unit_threshold, integration_threshold, doctest_threshold } } pub fn is_warn(&self, test: &TestDesc, exec_time: &TestExecTime) -> bool { diff --git a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile index ef49904b53d6a..51645a81853fd 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile @@ -1,6 +1,6 @@ -FROM ubuntu:16.04 +FROM ubuntu:20.04 -RUN apt-get update && apt-get install -y --no-install-recommends \ +RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ g++ \ make \ ninja-build \ diff --git a/src/doc/rustc/src/tests/index.md b/src/doc/rustc/src/tests/index.md index 23a9f31e8e7da..0e0eb85db746a 100644 --- a/src/doc/rustc/src/tests/index.md +++ b/src/doc/rustc/src/tests/index.md @@ -267,7 +267,7 @@ Controls the format of the output. Valid options: Writes the results of the tests to the given file. -#### `--report-time` _FORMAT_ +#### `--report-time` ⚠️ 🚧 This option is [unstable](#unstable-options), and requires the `-Z unstable-options` flag. See [tracking issue diff --git a/src/doc/unstable-book/src/compiler-flags/report-time.md b/src/doc/unstable-book/src/compiler-flags/report-time.md index ac0093f77aec2..9e6a1fb000575 100644 --- a/src/doc/unstable-book/src/compiler-flags/report-time.md +++ b/src/doc/unstable-book/src/compiler-flags/report-time.md @@ -21,11 +21,8 @@ Sample usage command: Available options: ```sh ---report-time [plain|colored] - Show execution time of each test. Available values: - plain = do not colorize the execution time (default); - colored = colorize output according to the `color` - parameter value; +--report-time + Show execution time of each test. Threshold values for colorized output can be configured via `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` diff --git a/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr index 3b1d922a7f757..11c4e01f4186d 100644 --- a/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr +++ b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr @@ -23,10 +23,10 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:36:15 + --> $DIR/bad-template.rs:36:16 | LL | asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:38:15 @@ -123,10 +123,10 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:63:14 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:65:14 diff --git a/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr index 3b1d922a7f757..11c4e01f4186d 100644 --- a/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr +++ b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr @@ -23,10 +23,10 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:36:15 + --> $DIR/bad-template.rs:36:16 | LL | asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:38:15 @@ -123,10 +123,10 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:63:14 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:65:14 diff --git a/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr index 3b69186f1e18b..c198e0a69dde1 100644 --- a/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr +++ b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr @@ -23,10 +23,10 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:36:15 + --> $DIR/bad-template.rs:36:16 | LL | asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:38:15 @@ -123,10 +123,10 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:63:14 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:65:14 diff --git a/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr index 3b69186f1e18b..c198e0a69dde1 100644 --- a/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr +++ b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr @@ -23,10 +23,10 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:36:15 + --> $DIR/bad-template.rs:36:16 | LL | asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:38:15 @@ -123,10 +123,10 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:63:14 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:65:14 diff --git a/src/test/ui/binop/issue-28837.stderr b/src/test/ui/binop/issue-28837.stderr index 10f243bab1586..1875ea06a06d5 100644 --- a/src/test/ui/binop/issue-28837.stderr +++ b/src/test/ui/binop/issue-28837.stderr @@ -272,9 +272,9 @@ note: an implementation of `PartialOrd<_>` might be missing for `A` | LL | struct A; | ^^^^^^^^^ must implement `PartialOrd<_>` -help: consider annotating `A` with `#[derive(PartialOrd)]` +help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]` | -LL | #[derive(PartialOrd)] +LL | #[derive(PartialEq, PartialOrd)] | error[E0369]: binary operation `<=` cannot be applied to type `A` @@ -290,9 +290,9 @@ note: an implementation of `PartialOrd<_>` might be missing for `A` | LL | struct A; | ^^^^^^^^^ must implement `PartialOrd<_>` -help: consider annotating `A` with `#[derive(PartialOrd)]` +help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]` | -LL | #[derive(PartialOrd)] +LL | #[derive(PartialEq, PartialOrd)] | error[E0369]: binary operation `>` cannot be applied to type `A` @@ -308,9 +308,9 @@ note: an implementation of `PartialOrd<_>` might be missing for `A` | LL | struct A; | ^^^^^^^^^ must implement `PartialOrd<_>` -help: consider annotating `A` with `#[derive(PartialOrd)]` +help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]` | -LL | #[derive(PartialOrd)] +LL | #[derive(PartialEq, PartialOrd)] | error[E0369]: binary operation `>=` cannot be applied to type `A` @@ -326,9 +326,9 @@ note: an implementation of `PartialOrd<_>` might be missing for `A` | LL | struct A; | ^^^^^^^^^ must implement `PartialOrd<_>` -help: consider annotating `A` with `#[derive(PartialOrd)]` +help: consider annotating `A` with `#[derive(PartialEq, PartialOrd)]` | -LL | #[derive(PartialOrd)] +LL | #[derive(PartialEq, PartialOrd)] | error: aborting due to 15 previous errors diff --git a/src/test/ui/derives/issue-91550.rs b/src/test/ui/derives/issue-91550.rs new file mode 100644 index 0000000000000..56fd5ffa89eea --- /dev/null +++ b/src/test/ui/derives/issue-91550.rs @@ -0,0 +1,29 @@ +use std::collections::HashSet; + +/// natural case from the issue +struct Value(u32); + +fn main() { + let hs = HashSet::::new(); + hs.insert(Value(0)); //~ ERROR +} + +/// synthetic cases +pub struct NoDerives; + +struct Object(T); +impl Object { + fn use_eq(&self) {} +} +impl Object { + fn use_ord(&self) {} +} +impl Object { + fn use_ord_and_partial_ord(&self) {} +} + +fn function(foo: Object) { + foo.use_eq(); //~ ERROR + foo.use_ord(); //~ ERROR + foo.use_ord_and_partial_ord(); //~ ERROR +} diff --git a/src/test/ui/derives/issue-91550.stderr b/src/test/ui/derives/issue-91550.stderr new file mode 100644 index 0000000000000..bf4b7c7da0d50 --- /dev/null +++ b/src/test/ui/derives/issue-91550.stderr @@ -0,0 +1,84 @@ +error[E0599]: the method `insert` exists for struct `HashSet`, but its trait bounds were not satisfied + --> $DIR/issue-91550.rs:8:8 + | +LL | struct Value(u32); + | ------------------ + | | + | doesn't satisfy `Value: Eq` + | doesn't satisfy `Value: Hash` +... +LL | hs.insert(Value(0)); + | ^^^^^^ method cannot be called on `HashSet` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `Value: Eq` + `Value: Hash` +help: consider annotating `Value` with `#[derive(Eq, Hash, PartialEq)]` + | +LL | #[derive(Eq, Hash, PartialEq)] + | + +error[E0599]: the method `use_eq` exists for struct `Object`, but its trait bounds were not satisfied + --> $DIR/issue-91550.rs:26:9 + | +LL | pub struct NoDerives; + | --------------------- doesn't satisfy `NoDerives: Eq` +LL | +LL | struct Object(T); + | -------------------- method `use_eq` not found for this +... +LL | foo.use_eq(); + | ^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NoDerives: Eq` +help: consider annotating `NoDerives` with `#[derive(Eq, PartialEq)]` + | +LL | #[derive(Eq, PartialEq)] + | + +error[E0599]: the method `use_ord` exists for struct `Object`, but its trait bounds were not satisfied + --> $DIR/issue-91550.rs:27:9 + | +LL | pub struct NoDerives; + | --------------------- doesn't satisfy `NoDerives: Ord` +LL | +LL | struct Object(T); + | -------------------- method `use_ord` not found for this +... +LL | foo.use_ord(); + | ^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NoDerives: Ord` +help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` + | +LL | #[derive(Eq, Ord, PartialEq, PartialOrd)] + | + +error[E0599]: the method `use_ord_and_partial_ord` exists for struct `Object`, but its trait bounds were not satisfied + --> $DIR/issue-91550.rs:28:9 + | +LL | pub struct NoDerives; + | --------------------- + | | + | doesn't satisfy `NoDerives: Ord` + | doesn't satisfy `NoDerives: PartialOrd` +LL | +LL | struct Object(T); + | -------------------- method `use_ord_and_partial_ord` not found for this +... +LL | foo.use_ord_and_partial_ord(); + | ^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `NoDerives: Ord` + `NoDerives: PartialOrd` +help: consider annotating `NoDerives` with `#[derive(Eq, Ord, PartialEq, PartialOrd)]` + | +LL | #[derive(Eq, Ord, PartialEq, PartialOrd)] + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.rs b/src/test/ui/feature-gates/feature-gate-untagged_unions.rs index f5f9631c3bcf9..af8d8e92b20bd 100644 --- a/src/test/ui/feature-gates/feature-gate-untagged_unions.rs +++ b/src/test/ui/feature-gates/feature-gate-untagged_unions.rs @@ -13,7 +13,7 @@ union U22 { // OK } union U3 { - a: String, //~ ERROR unions may not contain fields that need dropping + a: String, //~ ERROR unions cannot contain fields that may need dropping } union U32 { // field that does not drop but is not `Copy`, either -- this is the real feature gate test! @@ -21,7 +21,7 @@ union U32 { // field that does not drop but is not `Copy`, either -- this is the } union U4 { - a: T, //~ ERROR unions may not contain fields that need dropping + a: T, //~ ERROR unions cannot contain fields that may need dropping } union U5 { // Having a drop impl is OK diff --git a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr index 0967cb7ba8bd2..9e4a89f80c852 100644 --- a/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr +++ b/src/test/ui/feature-gates/feature-gate-untagged_unions.stderr @@ -7,24 +7,26 @@ LL | a: std::cell::RefCell, = note: see issue #55149 for more information = help: add `#![feature(untagged_unions)]` to the crate attributes to enable -error[E0740]: unions may not contain fields that need dropping +error[E0740]: unions cannot contain fields that may need dropping --> $DIR/feature-gate-untagged_unions.rs:16:5 | LL | a: String, | ^^^^^^^^^ | -help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions may not contain fields that need dropping +error[E0740]: unions cannot contain fields that may need dropping --> $DIR/feature-gate-untagged_unions.rs:24:5 | LL | a: T, | ^^^^ | -help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + diff --git a/src/test/ui/fmt/format-args-capture-issue-93378.stderr b/src/test/ui/fmt/format-args-capture-issue-93378.stderr index 588541044fe13..b8e2b2afb3867 100644 --- a/src/test/ui/fmt/format-args-capture-issue-93378.stderr +++ b/src/test/ui/fmt/format-args-capture-issue-93378.stderr @@ -10,10 +10,10 @@ error: invalid reference to positional argument 0 (no arguments were given) --> $DIR/format-args-capture-issue-93378.rs:9:23 | LL | println!("{a:.n$} {b:.*}"); - | ------- ^^^--^ - | | | - | | this precision flag adds an extra required argument at position 0, which is why there are 3 arguments expected - | this parameter corresponds to the precision flag + | - ^^^--^ + | | | + | | this precision flag adds an extra required argument at position 0, which is why there are 3 arguments expected + | this parameter corresponds to the precision flag | = note: positional arguments are zero-based = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html diff --git a/src/test/ui/fmt/format-args-capture-issue-94010.rs b/src/test/ui/fmt/format-args-capture-issue-94010.rs new file mode 100644 index 0000000000000..bd03e9c93ae2a --- /dev/null +++ b/src/test/ui/fmt/format-args-capture-issue-94010.rs @@ -0,0 +1,7 @@ +fn main() { + const FOO: i32 = 123; + println!("{foo:X}"); + //~^ ERROR: cannot find value `foo` in this scope + println!("{:.foo$}", 0); + //~^ ERROR: cannot find value `foo` in this scope +} diff --git a/src/test/ui/fmt/format-args-capture-issue-94010.stderr b/src/test/ui/fmt/format-args-capture-issue-94010.stderr new file mode 100644 index 0000000000000..ed90dc855360a --- /dev/null +++ b/src/test/ui/fmt/format-args-capture-issue-94010.stderr @@ -0,0 +1,20 @@ +error[E0425]: cannot find value `foo` in this scope + --> $DIR/format-args-capture-issue-94010.rs:3:16 + | +LL | const FOO: i32 = 123; + | --------------------- similarly named constant `FOO` defined here +LL | println!("{foo:X}"); + | ^^^ help: a constant with a similar name exists (notice the capitalization): `FOO` + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/format-args-capture-issue-94010.rs:5:18 + | +LL | const FOO: i32 = 123; + | --------------------- similarly named constant `FOO` defined here +... +LL | println!("{:.foo$}", 0); + | ^^^ help: a constant with a similar name exists (notice the capitalization): `FOO` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/fmt/format-args-capture-missing-variables.stderr b/src/test/ui/fmt/format-args-capture-missing-variables.stderr index d53c206003f94..d980e7be273e8 100644 --- a/src/test/ui/fmt/format-args-capture-missing-variables.stderr +++ b/src/test/ui/fmt/format-args-capture-missing-variables.stderr @@ -7,40 +7,40 @@ LL | format!("{valuea} {valueb}", valuea=5, valuec=7); | formatting specifier missing error[E0425]: cannot find value `foo` in this scope - --> $DIR/format-args-capture-missing-variables.rs:2:17 + --> $DIR/format-args-capture-missing-variables.rs:2:18 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `bar` in this scope - --> $DIR/format-args-capture-missing-variables.rs:2:26 + --> $DIR/format-args-capture-missing-variables.rs:2:27 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/format-args-capture-missing-variables.rs:6:14 + --> $DIR/format-args-capture-missing-variables.rs:6:15 | LL | format!("{foo}"); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `valueb` in this scope - --> $DIR/format-args-capture-missing-variables.rs:8:23 + --> $DIR/format-args-capture-missing-variables.rs:8:24 | LL | format!("{valuea} {valueb}", valuea=5, valuec=7); - | ^^^^^^^^ not found in this scope + | ^^^^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/format-args-capture-missing-variables.rs:14:9 + --> $DIR/format-args-capture-missing-variables.rs:14:10 | LL | {foo} - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/format-args-capture-missing-variables.rs:19:13 + --> $DIR/format-args-capture-missing-variables.rs:19:14 | LL | panic!("{foo} {bar}", bar=1); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error: aborting due to 7 previous errors diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr index acc4e95f5bb7e..3f1f1006713ba 100644 --- a/src/test/ui/fmt/ifmt-bad-arg.stderr +++ b/src/test/ui/fmt/ifmt-bad-arg.stderr @@ -263,34 +263,34 @@ LL | println!("{:.*}"); = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html error[E0425]: cannot find value `foo` in this scope - --> $DIR/ifmt-bad-arg.rs:27:17 + --> $DIR/ifmt-bad-arg.rs:27:18 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `bar` in this scope - --> $DIR/ifmt-bad-arg.rs:27:26 + --> $DIR/ifmt-bad-arg.rs:27:27 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/ifmt-bad-arg.rs:31:14 + --> $DIR/ifmt-bad-arg.rs:31:15 | LL | format!("{foo}"); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `valueb` in this scope - --> $DIR/ifmt-bad-arg.rs:45:23 + --> $DIR/ifmt-bad-arg.rs:45:24 | LL | format!("{valuea} {valueb}", valuea=5, valuec=7); - | ^^^^^^^^ not found in this scope + | ^^^^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/ifmt-bad-arg.rs:60:9 + --> $DIR/ifmt-bad-arg.rs:60:10 | LL | {foo} - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0308]: mismatched types --> $DIR/ifmt-bad-arg.rs:78:32 diff --git a/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs new file mode 100644 index 0000000000000..26deb59876268 --- /dev/null +++ b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs @@ -0,0 +1,22 @@ +struct Struct(T); +impl Struct +//~^ ERROR cannot find type `T` in this scope +//~| NOTE not found in this scope +//~| HELP you might be missing a type parameter +where + T: Copy, + //~^ ERROR cannot find type `T` in this scope + //~| NOTE not found in this scope +{ + // The part where it claims that there is no method named `len` is a bug. Feel free to fix it. + // This test is intended to ensure that a different bug, where it claimed + // that `v` was a function, does not regress. + fn method(v: Vec) { v.len(); } + //~^ ERROR type annotations needed + //~| NOTE cannot infer type + //~| NOTE type must be known at this point + //~| ERROR no method named `len` + //~| NOTE private field, not a method +} + +fn main() {} diff --git a/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr new file mode 100644 index 0000000000000..958ce3c25d027 --- /dev/null +++ b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr @@ -0,0 +1,32 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/fn-help-with-err-generic-is-not-function.rs:2:13 + | +LL | impl Struct + | - ^ not found in this scope + | | + | help: you might be missing a type parameter: `` + +error[E0412]: cannot find type `T` in this scope + --> $DIR/fn-help-with-err-generic-is-not-function.rs:7:5 + | +LL | T: Copy, + | ^ not found in this scope + +error[E0282]: type annotations needed + --> $DIR/fn-help-with-err-generic-is-not-function.rs:14:31 + | +LL | fn method(v: Vec) { v.len(); } + | ^^^ cannot infer type + | + = note: type must be known at this point + +error[E0599]: no method named `len` found for struct `Vec` in the current scope + --> $DIR/fn-help-with-err-generic-is-not-function.rs:14:31 + | +LL | fn method(v: Vec) { v.len(); } + | ^^^ private field, not a method + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0282, E0412, E0599. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/functions-closures/fn-help-with-err.rs b/src/test/ui/functions-closures/fn-help-with-err.rs new file mode 100644 index 0000000000000..f8a81af786f7e --- /dev/null +++ b/src/test/ui/functions-closures/fn-help-with-err.rs @@ -0,0 +1,16 @@ +// This test case checks the behavior of typeck::check::method::suggest::is_fn on Ty::Error. +fn main() { + let arc = std::sync::Arc::new(oops); + //~^ ERROR cannot find value `oops` in this scope + //~| NOTE not found + // The error "note: `arc` is a function, perhaps you wish to call it" MUST NOT appear. + arc.blablabla(); + //~^ ERROR no method named `blablabla` + //~| NOTE method not found + let arc2 = std::sync::Arc::new(|| 1); + // The error "note: `arc2` is a function, perhaps you wish to call it" SHOULD appear + arc2.blablabla(); + //~^ ERROR no method named `blablabla` + //~| NOTE method not found + //~| NOTE `arc2` is a function, perhaps you wish to call it +} diff --git a/src/test/ui/functions-closures/fn-help-with-err.stderr b/src/test/ui/functions-closures/fn-help-with-err.stderr new file mode 100644 index 0000000000000..4d6b3282ad9e9 --- /dev/null +++ b/src/test/ui/functions-closures/fn-help-with-err.stderr @@ -0,0 +1,24 @@ +error[E0425]: cannot find value `oops` in this scope + --> $DIR/fn-help-with-err.rs:3:35 + | +LL | let arc = std::sync::Arc::new(oops); + | ^^^^ not found in this scope + +error[E0599]: no method named `blablabla` found for struct `Arc<_>` in the current scope + --> $DIR/fn-help-with-err.rs:7:9 + | +LL | arc.blablabla(); + | ^^^^^^^^^ method not found in `Arc<_>` + +error[E0599]: no method named `blablabla` found for struct `Arc<[closure@$DIR/fn-help-with-err.rs:10:36: 10:40]>` in the current scope + --> $DIR/fn-help-with-err.rs:12:10 + | +LL | arc2.blablabla(); + | ^^^^^^^^^ method not found in `Arc<[closure@$DIR/fn-help-with-err.rs:10:36: 10:40]>` + | + = note: `arc2` is a function, perhaps you wish to call it + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0425, E0599. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/typeck/issue-91328.fixed b/src/test/ui/typeck/issue-91328.fixed index 81b6a99607215..c0384399a92e6 100644 --- a/src/test/ui/typeck/issue-91328.fixed +++ b/src/test/ui/typeck/issue-91328.fixed @@ -34,4 +34,14 @@ fn baz(v: Vec) -> i32 { } } +fn qux(a: &Option>) -> i32 { + match a.as_deref() { + //~^ HELP: consider using `as_deref` here + Some([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + fn main() {} diff --git a/src/test/ui/typeck/issue-91328.rs b/src/test/ui/typeck/issue-91328.rs index e938d8f5c9f04..63602d26f970d 100644 --- a/src/test/ui/typeck/issue-91328.rs +++ b/src/test/ui/typeck/issue-91328.rs @@ -34,4 +34,14 @@ fn baz(v: Vec) -> i32 { } } +fn qux(a: &Option>) -> i32 { + match a { + //~^ HELP: consider using `as_deref` here + Some([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + fn main() {} diff --git a/src/test/ui/typeck/issue-91328.stderr b/src/test/ui/typeck/issue-91328.stderr index 96ad00cde4f7b..f2f407bcafff2 100644 --- a/src/test/ui/typeck/issue-91328.stderr +++ b/src/test/ui/typeck/issue-91328.stderr @@ -25,6 +25,15 @@ LL | LL | [a, b] => a + b, | ^^^^^^ pattern cannot match with input type `Vec` -error: aborting due to 3 previous errors +error[E0529]: expected an array or slice, found `Box<[i32; 2]>` + --> $DIR/issue-91328.rs:40:14 + | +LL | match a { + | - help: consider using `as_deref` here: `a.as_deref()` +LL | +LL | Some([a, b]) => a + b, + | ^^^^^^ pattern cannot match with input type `Box<[i32; 2]>` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0529`. diff --git a/src/test/ui/union/issue-41073.rs b/src/test/ui/union/issue-41073.rs index 91e9a0d0b659c..80474b807e7f3 100644 --- a/src/test/ui/union/issue-41073.rs +++ b/src/test/ui/union/issue-41073.rs @@ -1,7 +1,7 @@ #![feature(untagged_unions)] union Test { - a: A, //~ ERROR unions may not contain fields that need dropping + a: A, //~ ERROR unions cannot contain fields that may need dropping b: B } diff --git a/src/test/ui/union/issue-41073.stderr b/src/test/ui/union/issue-41073.stderr index 8edf4db441b9c..7d4208b10da80 100644 --- a/src/test/ui/union/issue-41073.stderr +++ b/src/test/ui/union/issue-41073.stderr @@ -1,10 +1,11 @@ -error[E0740]: unions may not contain fields that need dropping +error[E0740]: unions cannot contain fields that may need dropping --> $DIR/issue-41073.rs:4:5 | LL | a: A, | ^^^^ | -help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + diff --git a/src/test/ui/union/union-custom-drop.rs b/src/test/ui/union/union-custom-drop.rs index 8f816cc1b737c..4b333631ec0f7 100644 --- a/src/test/ui/union/union-custom-drop.rs +++ b/src/test/ui/union/union-custom-drop.rs @@ -4,7 +4,7 @@ #![feature(untagged_unions)] union Foo { - bar: Bar, //~ ERROR unions may not contain fields that need dropping + bar: Bar, //~ ERROR unions cannot contain fields that may need dropping } union Bar { diff --git a/src/test/ui/union/union-custom-drop.stderr b/src/test/ui/union/union-custom-drop.stderr index 65ca5fd931d67..b5579eeef0977 100644 --- a/src/test/ui/union/union-custom-drop.stderr +++ b/src/test/ui/union/union-custom-drop.stderr @@ -1,10 +1,11 @@ -error[E0740]: unions may not contain fields that need dropping +error[E0740]: unions cannot contain fields that may need dropping --> $DIR/union-custom-drop.rs:7:5 | LL | bar: Bar, | ^^^^^^^^ | -help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped | LL | bar: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + diff --git a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr index 146a627bcdef7..e8e65fe5d1d1d 100644 --- a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr @@ -16,9 +16,9 @@ LL | let w = u.clone(); = note: the following trait bounds were not satisfied: `CloneNoCopy: Copy` which is required by `U5: Clone` -help: consider annotating `CloneNoCopy` with `#[derive(Copy)]` +help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` | -LL | #[derive(Copy)] +LL | #[derive(Clone, Copy)] | error[E0277]: the trait bound `U1: Copy` is not satisfied diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr index 146a627bcdef7..e8e65fe5d1d1d 100644 --- a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr @@ -16,9 +16,9 @@ LL | let w = u.clone(); = note: the following trait bounds were not satisfied: `CloneNoCopy: Copy` which is required by `U5: Clone` -help: consider annotating `CloneNoCopy` with `#[derive(Copy)]` +help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` | -LL | #[derive(Copy)] +LL | #[derive(Clone, Copy)] | error[E0277]: the trait bound `U1: Copy` is not satisfied diff --git a/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr b/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr index f5e9681735c6f..93fe996d2a477 100644 --- a/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr +++ b/src/test/ui/union/union-with-drop-fields.mirunsafeck.stderr @@ -1,32 +1,35 @@ -error[E0740]: unions may not contain fields that need dropping +error[E0740]: unions cannot contain fields that may need dropping --> $DIR/union-with-drop-fields.rs:11:5 | LL | a: String, | ^^^^^^^^^ | -help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions may not contain fields that need dropping +error[E0740]: unions cannot contain fields that may need dropping --> $DIR/union-with-drop-fields.rs:19:5 | LL | a: S, | ^^^^ | -help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions may not contain fields that need dropping +error[E0740]: unions cannot contain fields that may need dropping --> $DIR/union-with-drop-fields.rs:24:5 | LL | a: T, | ^^^^ | -help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + diff --git a/src/test/ui/union/union-with-drop-fields.rs b/src/test/ui/union/union-with-drop-fields.rs index 96c293418b629..a7a8b69e784ab 100644 --- a/src/test/ui/union/union-with-drop-fields.rs +++ b/src/test/ui/union/union-with-drop-fields.rs @@ -8,7 +8,7 @@ union U { } union W { - a: String, //~ ERROR unions may not contain fields that need dropping + a: String, //~ ERROR unions cannot contain fields that may need dropping b: String, // OK, only one field is reported } @@ -16,12 +16,12 @@ struct S(String); // `S` doesn't implement `Drop` trait, but still has non-trivial destructor union Y { - a: S, //~ ERROR unions may not contain fields that need dropping + a: S, //~ ERROR unions cannot contain fields that may need dropping } // We don't know if `T` is trivially-destructable or not until trans union J { - a: T, //~ ERROR unions may not contain fields that need dropping + a: T, //~ ERROR unions cannot contain fields that may need dropping } union H { diff --git a/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr b/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr index f5e9681735c6f..93fe996d2a477 100644 --- a/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr +++ b/src/test/ui/union/union-with-drop-fields.thirunsafeck.stderr @@ -1,32 +1,35 @@ -error[E0740]: unions may not contain fields that need dropping +error[E0740]: unions cannot contain fields that may need dropping --> $DIR/union-with-drop-fields.rs:11:5 | LL | a: String, | ^^^^^^^^^ | -help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions may not contain fields that need dropping +error[E0740]: unions cannot contain fields that may need dropping --> $DIR/union-with-drop-fields.rs:19:5 | LL | a: S, | ^^^^ | -help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions may not contain fields that need dropping +error[E0740]: unions cannot contain fields that may need dropping --> $DIR/union-with-drop-fields.rs:24:5 | LL | a: T, | ^^^^ | -help: wrap the type with `std::mem::ManuallyDrop` and ensure it is manually dropped + = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type +help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index b0044695ea8a8..1fa6301ebd73d 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -453,7 +453,7 @@ impl SimpleFormatArgs { } } }, - ArgumentNamed(n) => { + ArgumentNamed(n, _) => { if let Some(x) = self.named.iter_mut().find(|x| x.0 == n) { match x.1.as_slice() { // A non-empty format string has been seen already.