diff options
1409 files changed, 18768 insertions, 8871 deletions
diff --git a/Cargo.lock b/Cargo.lock index 29c8c7ef004..fff30b0f27b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -556,7 +556,7 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "clippy" -version = "0.1.77" +version = "0.1.78" dependencies = [ "anstream", "clippy_config", @@ -584,7 +584,7 @@ dependencies = [ [[package]] name = "clippy_config" -version = "0.1.77" +version = "0.1.78" dependencies = [ "rustc-semver", "serde", @@ -607,7 +607,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.77" +version = "0.1.78" dependencies = [ "arrayvec", "cargo_metadata 0.18.0", @@ -632,7 +632,7 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.77" +version = "0.1.78" dependencies = [ "arrayvec", "clippy_config", @@ -1003,7 +1003,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" [[package]] name = "declare_clippy_lint" -version = "0.1.77" +version = "0.1.78" dependencies = [ "itertools", "quote", @@ -2090,9 +2090,9 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" dependencies = [ "libc", ] @@ -4374,6 +4374,7 @@ dependencies = [ "rustc_middle", "rustc_session", "rustc_span", + "rustc_ty_utils", "tracing", ] diff --git a/RELEASES.md b/RELEASES.md index 038a83cde84..20e317a4d23 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -7,7 +7,7 @@ Language -------- - [Document Rust ABI compatibility between various types](https://github.com/rust-lang/rust/pull/115476/) - [Also: guarantee that char and u32 are ABI-compatible](https://github.com/rust-lang/rust/pull/118032/) -- [Warn against ambiguous wide pointer comparisons](https://github.com/rust-lang/rust/pull/117758/) +- [Add lint `ambiguous_wide_pointer_comparisons` that supersedes `clippy::vtable_address_comparisons`](https://github.com/rust-lang/rust/pull/117758) <a id="1.76.0-Compiler"></a> diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 90ddeec4bc7..5cb79d9eea5 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -22,8 +22,6 @@ #![cfg_attr(test, feature(test))] #![feature(strict_provenance)] #![deny(unsafe_op_in_unsafe_fn)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #![allow(clippy::mut_from_ref)] // Arena allocators are one of the places where this pattern is fine. diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 76d838308b4..356e9fef439 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -18,8 +18,6 @@ #![feature(min_specialization)] #![feature(negative_impls)] #![feature(stmt_expr_attributes)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 3742cf9d881..fd717e82d26 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -205,7 +205,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &sym.qself, &sym.path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); hir::InlineAsmOperand::SymStatic { path, def_id } diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index d310f72f7a3..865a56b2c1f 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -85,7 +85,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let ty = l .ty .as_ref() - .map(|t| self.lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); + .map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable))); let init = l.kind.init().map(|init| self.lower_expr(init)); let hir_id = self.lower_node_id(l.id); let pat = self.lower_pat(&l.pat); diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 6ccf39b0cb1..d1ba93f0675 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -218,7 +218,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &delegation.qself, &delegation.path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); let block = delegation.body.as_deref(); diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index ec92afee47a..62253585695 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -1,4 +1,6 @@ -use rustc_errors::{codes::*, DiagnosticArgFromDisplay}; +use rustc_errors::{ + codes::*, AddToDiagnostic, Diagnostic, DiagnosticArgFromDisplay, SubdiagnosticMessageOp, +}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -38,14 +40,8 @@ pub struct InvalidAbi { pub struct InvalidAbiReason(pub &'static str); -impl rustc_errors::AddToDiagnostic for InvalidAbiReason { - fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { +impl AddToDiagnostic for InvalidAbiReason { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { #[allow(rustc::untranslatable_diagnostic)] diag.note(self.0); } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index c4798887637..942aae3d536 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -99,7 +99,7 @@ impl<'hir> LoweringContext<'_, 'hir> { seg, ParamMode::Optional, ParenthesizedGenericArgs::Err, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, // Method calls can't have bound modifiers None, @@ -141,13 +141,13 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::Cast(expr, ty) => { let expr = self.lower_expr(expr); let ty = - self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); hir::ExprKind::Cast(expr, ty) } ExprKind::Type(expr, ty) => { let expr = self.lower_expr(expr); let ty = - self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); hir::ExprKind::Type(expr, ty) } ExprKind::AddrOf(k, m, ohs) => { @@ -267,7 +267,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); hir::ExprKind::Path(qpath) @@ -295,7 +295,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf( self.lower_ty( container, - &ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf), + ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf), ), self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))), ), @@ -314,7 +314,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, )), self.arena @@ -1241,7 +1241,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); // Destructure like a tuple struct. @@ -1261,7 +1261,7 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); // Destructure like a unit struct. @@ -1286,7 +1286,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &se.qself, &se.path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); let fields_omitted = match &se.rest { diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 993ddf00eb5..11aa6b250b1 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -15,7 +15,7 @@ struct NodeCollector<'a, 'hir> { bodies: &'a SortedMap<ItemLocalId, &'hir Body<'hir>>, /// Outputs - nodes: IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>, + nodes: IndexVec<ItemLocalId, ParentedNode<'hir>>, parenting: LocalDefIdMap<ItemLocalId>, /// The parent of this node @@ -29,16 +29,19 @@ pub(super) fn index_hir<'hir>( tcx: TyCtxt<'hir>, item: hir::OwnerNode<'hir>, bodies: &SortedMap<ItemLocalId, &'hir Body<'hir>>, -) -> (IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>, LocalDefIdMap<ItemLocalId>) { - let mut nodes = IndexVec::new(); + num_nodes: usize, +) -> (IndexVec<ItemLocalId, ParentedNode<'hir>>, LocalDefIdMap<ItemLocalId>) { + let zero_id = ItemLocalId::new(0); + let err_node = ParentedNode { parent: zero_id, node: Node::Err(item.span()) }; + let mut nodes = IndexVec::from_elem_n(err_node, num_nodes); // This node's parent should never be accessed: the owner's parent is computed by the // hir_owner_parent query. Make it invalid (= ItemLocalId::MAX) to force an ICE whenever it is // used. - nodes.push(Some(ParentedNode { parent: ItemLocalId::INVALID, node: item.into() })); + nodes[zero_id] = ParentedNode { parent: ItemLocalId::INVALID, node: item.into() }; let mut collector = NodeCollector { tcx, owner: item.def_id(), - parent_node: ItemLocalId::new(0), + parent_node: zero_id, nodes, bodies, parenting: Default::default(), @@ -54,6 +57,14 @@ pub(super) fn index_hir<'hir>( OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item), }; + for (local_id, node) in collector.nodes.iter_enumerated() { + if let Node::Err(span) = node.node { + let hir_id = HirId { owner: item.def_id(), local_id }; + let msg = format!("ID {hir_id} not encountered when visiting item HIR"); + tcx.dcx().span_delayed_bug(*span, msg); + } + } + (collector.nodes, collector.parenting) } @@ -88,7 +99,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } } - self.nodes.insert(hir_id.local_id, ParentedNode { parent: self.parent_node, node }); + self.nodes[hir_id.local_id] = ParentedNode { parent: self.parent_node, node }; } fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_node_id: HirId, f: F) { @@ -254,6 +265,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_path_segment(&mut self, path_segment: &'hir PathSegment<'hir>) { + // FIXME: walk path segment with `path_segment.hir_id` parent. self.insert(path_segment.ident.span, path_segment.hir_id, Node::PathSegment(path_segment)); intravisit::walk_path_segment(self, path_segment); } @@ -348,4 +360,23 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.visit_nested_foreign_item(id); } + + fn visit_where_predicate(&mut self, predicate: &'hir WherePredicate<'hir>) { + match predicate { + WherePredicate::BoundPredicate(pred) => { + self.insert(pred.span, pred.hir_id, Node::WhereBoundPredicate(pred)); + self.with_parent(pred.hir_id, |this| { + intravisit::walk_where_predicate(this, predicate) + }) + } + _ => intravisit::walk_where_predicate(self, predicate), + } + } + + fn visit_array_length(&mut self, len: &'hir ArrayLen) { + match len { + ArrayLen::Infer(inf) => self.insert(inf.span, inf.hir_id, Node::ArrayLenInfer(inf)), + ArrayLen::Body(..) => intravisit::walk_array_len(self, len), + } + } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 2a3e172f771..fb52f9cf58f 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -189,7 +189,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy) }, @@ -218,7 +218,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let itctx = ImplTraitContext::Universal; let (generics, decl) = - this.lower_generics(generics, header.constness, id, &itctx, |this| { + this.lower_generics(generics, header.constness, id, itctx, |this| { this.lower_fn_decl( decl, id, @@ -263,7 +263,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { let guar = this.dcx().span_delayed_bug( @@ -274,7 +274,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } Some(ty) => this.lower_ty( ty, - &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false }, + ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: false }, ), }, ); @@ -285,7 +285,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.arena.alloc_from_iter( enum_definition.variants.iter().map(|x| this.lower_variant(x)), @@ -299,7 +299,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, struct_def), ); hir::ItemKind::Struct(struct_def, generics) @@ -309,7 +309,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, vdata), ); hir::ItemKind::Union(vdata, generics) @@ -339,7 +339,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // parent lifetime. let itctx = ImplTraitContext::Universal; let (generics, (trait_ref, lowered_ty)) = - self.lower_generics(ast_generics, *constness, id, &itctx, |this| { + self.lower_generics(ast_generics, *constness, id, itctx, |this| { let modifiers = TraitBoundModifiers { constness: match *constness { Const::Yes(span) => BoundConstness::Maybe(span), @@ -354,13 +354,13 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_trait_ref( modifiers, trait_ref, - &ImplTraitContext::Disallowed(ImplTraitPosition::Trait), + ImplTraitContext::Disallowed(ImplTraitPosition::Trait), ) }); let lowered_ty = this.lower_ty( ty, - &ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf), + ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf), ); (trait_ref, lowered_ty) @@ -400,11 +400,11 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, constness, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let bounds = this.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ); let items = this.arena.alloc_from_iter( items.iter().map(|item| this.lower_trait_item_ref(item)), @@ -420,11 +420,11 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { this.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) }, ); @@ -464,7 +464,7 @@ impl<'hir> LoweringContext<'_, 'hir> { body: Option<&Expr>, impl_trait_position: ImplTraitPosition, ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { - let ty = self.lower_ty(ty, &ImplTraitContext::Disallowed(impl_trait_position)); + let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(impl_trait_position)); (ty, self.lower_const_body(span, body)) } @@ -498,8 +498,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - let res = - self.expect_full_res_from_use(id).map(|res| self.lower_res(res)).collect(); + let res = self.lower_import_res(id, path.span); let path = self.lower_use_path(res, &path, ParamMode::Explicit); hir::ItemKind::Use(path, hir::UseKind::Single) } @@ -535,7 +534,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // for that we return the `{}` import (called the // `ListStem`). - let prefix = Path { segments, span: prefix.span.to(path.span), tokens: None }; + let span = prefix.span.to(path.span); + let prefix = Path { segments, span, tokens: None }; // Add all the nested `PathListItem`s to the HIR. for &(ref use_tree, id) in trees { @@ -569,9 +569,21 @@ impl<'hir> LoweringContext<'_, 'hir> { }); } - let res = - self.expect_full_res_from_use(id).map(|res| self.lower_res(res)).collect(); - let path = self.lower_use_path(res, &prefix, ParamMode::Explicit); + // Condition should match `build_reduced_graph_for_use_tree`. + let path = if trees.is_empty() + && !(prefix.segments.is_empty() + || prefix.segments.len() == 1 + && prefix.segments[0].ident.name == kw::PathRoot) + { + // For empty lists we need to lower the prefix so it is checked for things + // like stability later. + let res = self.lower_import_res(id, span); + self.lower_use_path(res, &prefix, ParamMode::Explicit) + } else { + // For non-empty lists we can just drop all the data, the prefix is already + // present in HIR as a part of nested imports. + self.arena.alloc(hir::UsePath { res: smallvec![], segments: &[], span }) + }; hir::ItemKind::Use(path, hir::UseKind::ListStem) } } @@ -626,7 +638,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let fdec = &sig.decl; let itctx = ImplTraitContext::Universal; let (generics, (fn_dec, fn_args)) = - self.lower_generics(generics, Const::No, i.id, &itctx, |this| { + self.lower_generics(generics, Const::No, i.id, itctx, |this| { ( // Disallow `impl Trait` in foreign items. this.lower_fn_decl( @@ -643,8 +655,8 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } ForeignItemKind::Static(t, m, _) => { - let ty = self - .lower_ty(t, &ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); + let ty = + self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); hir::ForeignItemKind::Static(ty, *m) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, @@ -715,11 +727,11 @@ impl<'hir> LoweringContext<'_, 'hir> { qself, path, ParamMode::ExplicitNamed, // no `'_` in declarations (Issue #61124) - &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy), + ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy), ); self.arena.alloc(t) } else { - self.lower_ty(&f.ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)) + self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)) }; let hir_id = self.lower_node_id(f.id); self.lower_attrs(hir_id, &f.attrs); @@ -748,12 +760,10 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, i.id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { - let ty = this.lower_ty( - ty, - &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy), - ); + let ty = this + .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); let body = expr.as_ref().map(|x| this.lower_const_body(i.span, Some(x))); hir::TraitItemKind::Const(ty, body) @@ -796,18 +806,18 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, Const::No, i.id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { let ty = ty.as_ref().map(|x| { this.lower_ty( x, - &ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy), + ImplTraitContext::Disallowed(ImplTraitPosition::AssocTy), ) }); hir::TraitItemKind::Type( this.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), ), ty, ) @@ -875,10 +885,10 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, Const::No, i.id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| { - let ty = this - .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); + let ty = + this.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); let body = this.lower_const_body(i.span, expr.as_deref()); hir::ImplItemKind::Const(ty, body) @@ -909,7 +919,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &generics, Const::No, i.id, - &ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| match ty { None => { let guar = this.dcx().span_delayed_bug( @@ -922,7 +932,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(ty) => { let ty = this.lower_ty( ty, - &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true }, + ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty: true }, ); hir::ImplItemKind::Type(ty) } @@ -1316,7 +1326,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // synthesize a host effect param for them. We reject `const` on them during AST validation. let constness = if kind == FnDeclKind::Inherent { sig.header.constness } else { Const::No }; let itctx = ImplTraitContext::Universal; - let (generics, decl) = self.lower_generics(generics, constness, id, &itctx, |this| { + let (generics, decl) = self.lower_generics(generics, constness, id, itctx, |this| { this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) @@ -1394,7 +1404,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics: &Generics, constness: Const, parent_node_id: NodeId, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, f: impl FnOnce(&mut Self) -> T, ) -> (&'hir hir::Generics<'hir>, T) { debug_assert!(self.impl_trait_defs.is_empty()); @@ -1600,7 +1610,7 @@ impl<'hir> LoweringContext<'_, 'hir> { bounds: &[GenericBound], colon_span: Option<Span>, parent_span: Span, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, origin: PredicateOrigin, ) -> Option<hir::WherePredicate<'hir>> { // Do not create a clause if we do not have anything inside it. @@ -1674,10 +1684,10 @@ impl<'hir> LoweringContext<'_, 'hir> { bound_generic_params: self .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder), bounded_ty: self - .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), + .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), bounds: self.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ), span: self.lower_span(*span), origin: PredicateOrigin::WhereClause, @@ -1688,7 +1698,7 @@ impl<'hir> LoweringContext<'_, 'hir> { lifetime: self.lower_lifetime(lifetime), bounds: self.lower_param_bounds( bounds, - &ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ), in_where_clause: true, }) @@ -1696,9 +1706,9 @@ impl<'hir> LoweringContext<'_, 'hir> { WherePredicate::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty, span }) => { hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty: self - .lower_ty(lhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), + .lower_ty(lhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), rhs_ty: self - .lower_ty(rhs_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), + .lower_ty(rhs_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), span: self.lower_span(*span), }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d6abaa8428b..4ef9c7607be 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -36,8 +36,6 @@ #![feature(assert_matches)] #![feature(box_patterns)] #![feature(let_chains)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; @@ -64,7 +62,7 @@ use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_session::parse::{add_feature_diagnostics, feature_err}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{DesugaringKind, Span, DUMMY_SP}; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; use std::collections::hash_map::Entry; use thin_vec::ThinVec; @@ -675,7 +673,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { (None, None) }; - let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies); + let num_nodes = self.item_local_id_counter.as_usize(); + let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes); let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies }; let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash }; @@ -750,8 +749,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res()) } - fn expect_full_res_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Res<NodeId>> { - self.resolver.get_import_res(id).present_items() + fn lower_import_res(&mut self, id: NodeId, span: Span) -> SmallVec<[Res; 3]> { + let res = self.resolver.get_import_res(id).present_items(); + let res: SmallVec<_> = res.map(|res| self.lower_res(res)).collect(); + if res.is_empty() { + self.dcx().span_delayed_bug(span, "no resolution for an import"); + return smallvec![Res::Err]; + } + res } fn make_lang_item_qpath(&mut self, lang_item: hir::LangItem, span: Span) -> hir::QPath<'hir> { @@ -1000,7 +1005,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_assoc_ty_constraint( &mut self, constraint: &AssocConstraint, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::TypeBinding<'hir> { debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx); // lower generic arguments of identifier in constraint @@ -1079,32 +1084,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TypeBindingKind::Equality { term } } AssocConstraintKind::Bound { bounds } => { - enum DesugarKind<'a> { + enum DesugarKind { ImplTrait, - Error(&'a ImplTraitPosition), + Error(ImplTraitPosition), Bound, } // Piggy-back on the `impl Trait` context to figure out the correct behavior. let desugar_kind = match itctx { - // We are in the return position: - // - // fn foo() -> impl Iterator<Item: Debug> - // - // so desugar to - // - // fn foo() -> impl Iterator<Item = impl Debug> - ImplTraitContext::ReturnPositionOpaqueTy { .. } - | ImplTraitContext::TypeAliasesOpaqueTy { .. } => DesugarKind::ImplTrait, - - // We are in the argument position, but within a dyn type: + // in an argument, RPIT, or TAIT, if we are within a dyn type: // // fn foo(x: dyn Iterator<Item: Debug>) // - // so desugar to + // then desugar to: // // fn foo(x: dyn Iterator<Item = impl Debug>) - ImplTraitContext::Universal if self.is_in_dyn_type => DesugarKind::ImplTrait, + // + // This is because dyn traits must have all of their associated types specified. + ImplTraitContext::ReturnPositionOpaqueTy { .. } + | ImplTraitContext::TypeAliasesOpaqueTy { .. } + | ImplTraitContext::Universal + if self.is_in_dyn_type => + { + DesugarKind::ImplTrait + } ImplTraitContext::Disallowed(position) if self.is_in_dyn_type => { DesugarKind::Error(position) @@ -1157,7 +1160,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { DesugarKind::Error(position) => { let guar = self.dcx().emit_err(errors::MisplacedAssocTyBinding { span: constraint.span, - position: DiagnosticArgFromDisplay(position), + position: DiagnosticArgFromDisplay(&position), }); let err_ty = &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar))); @@ -1204,7 +1207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_generic_arg( &mut self, arg: &ast::GenericArg, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::GenericArg<'hir> { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)), @@ -1283,7 +1286,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[instrument(level = "debug", skip(self))] - fn lower_ty(&mut self, t: &Ty, itctx: &ImplTraitContext) -> &'hir hir::Ty<'hir> { + fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> { self.arena.alloc(self.lower_ty_direct(t, itctx)) } @@ -1293,7 +1296,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option<ptr::P<QSelf>>, path: &Path, param_mode: ParamMode, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::Ty<'hir> { // Check whether we should interpret this as a bare trait object. // This check mirrors the one in late resolution. We only introduce this special case in @@ -1335,7 +1338,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.ty(span, hir::TyKind::Tup(tys)) } - fn lower_ty_direct(&mut self, t: &Ty, itctx: &ImplTraitContext) -> hir::Ty<'hir> { + fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { let kind = match &t.kind { TyKind::Infer => hir::TyKind::Infer, TyKind::Err => { @@ -1454,13 +1457,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::ReturnPositionOpaqueTy { origin, fn_kind } => self .lower_opaque_impl_trait( span, - *origin, + origin, *def_node_id, bounds, - Some(*fn_kind), + Some(fn_kind), itctx, ), - &ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self + ImplTraitContext::TypeAliasesOpaqueTy { in_assoc_ty } => self .lower_opaque_impl_trait( span, hir::OpaqueTyOrigin::TyAlias { in_assoc_ty }, @@ -1507,9 +1510,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .create_feature_err( MisplacedImplTrait { span: t.span, - position: DiagnosticArgFromDisplay(position), + position: DiagnosticArgFromDisplay(&position), }, - *feature, + feature, ) .emit(); hir::TyKind::Err(guar) @@ -1517,7 +1520,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed(position) => { let guar = self.dcx().emit_err(MisplacedImplTrait { span: t.span, - position: DiagnosticArgFromDisplay(position), + position: DiagnosticArgFromDisplay(&position), }); hir::TyKind::Err(guar) } @@ -1575,7 +1578,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { opaque_ty_node_id: NodeId, bounds: &GenericBounds, fn_kind: Option<FnDeclKind>, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::TyKind<'hir> { // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop @@ -1842,7 +1845,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed(ImplTraitPosition::PointerParam) } }; - self.lower_ty_direct(¶m.ty, &itctx) + self.lower_ty_direct(¶m.ty, itctx) })); let output = match coro { @@ -1870,7 +1873,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::Disallowed(ImplTraitPosition::PointerReturn) } }; - hir::FnRetTy::Return(self.lower_ty(ty, &itctx)) + hir::FnRetTy::Return(self.lower_ty(ty, itctx)) } FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)), }, @@ -1971,7 +1974,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { output: &FnRetTy, coro: CoroutineKind, opaque_ty_span: Span, - nested_impl_trait_context: ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future<Output = T>` from the return type. let output_ty = match output { @@ -1979,7 +1982,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the // `impl Future` opaque type that `async fn` implicitly // generates. - self.lower_ty(ty, &nested_impl_trait_context) + self.lower_ty(ty, itctx) } FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; @@ -2019,7 +2022,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bound( &mut self, tpb: &GenericBound, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::GenericBound<'hir> { match tpb { GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait( @@ -2158,7 +2161,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .map(|def| { self.lower_ty( def, - &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault), + ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault), ) }); @@ -2168,7 +2171,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } GenericParamKind::Const { ty, kw_span: _, default } => { let ty = self - .lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault)); + .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::GenericDefault)); // Not only do we deny const param defaults in binders but we also map them to `None` // since later compiler stages cannot handle them (and shouldn't need to be able to). @@ -2198,7 +2201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, modifiers: ast::TraitBoundModifiers, p: &TraitRef, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::TraitRef<'hir> { let path = match self.lower_qpath( p.ref_id, @@ -2218,7 +2221,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_poly_trait_ref( &mut self, p: &PolyTraitRef, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, modifiers: ast::TraitBoundModifiers, ) -> hir::PolyTraitRef<'hir> { let bound_generic_params = @@ -2227,7 +2230,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) } } - fn lower_mt(&mut self, mt: &MutTy, itctx: &ImplTraitContext) -> hir::MutTy<'hir> { + fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl } } @@ -2235,7 +2238,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bounds( &mut self, bounds: &[GenericBound], - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> hir::GenericBounds<'hir> { self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) } @@ -2243,7 +2246,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bounds_mut<'s>( &'s mut self, bounds: &'s [GenericBound], - itctx: &'s ImplTraitContext, + itctx: ImplTraitContext, ) -> impl Iterator<Item = hir::GenericBound<'hir>> + Captures<'s> + Captures<'a> { bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) } @@ -2279,7 +2282,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bounds, /* colon_span */ None, span, - &ImplTraitContext::Universal, + ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, ); diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 0af141ff99a..c097feb6b34 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -38,7 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct"); @@ -55,7 +55,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); break hir::PatKind::Path(qpath); @@ -66,7 +66,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself, path, ParamMode::Optional, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, ); diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index b58ac5c3dae..48941a232c2 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -27,7 +27,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { qself: &Option<ptr::P<QSelf>>, p: &Path, param_mode: ParamMode, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, // modifiers of the impl/bound if this is a trait path modifiers: Option<ast::TraitBoundModifiers>, ) -> hir::QPath<'hir> { @@ -196,6 +196,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &Path, param_mode: ParamMode, ) -> &'hir hir::UsePath<'hir> { + assert!((1..=3).contains(&res.len())); self.arena.alloc(hir::UsePath { res, segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| { @@ -204,7 +205,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment, param_mode, ParenthesizedGenericArgs::Err, - &ImplTraitContext::Disallowed(ImplTraitPosition::Path), + ImplTraitContext::Disallowed(ImplTraitPosition::Path), None, None, ) @@ -219,7 +220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segment: &PathSegment, param_mode: ParamMode, parenthesized_generic_args: ParenthesizedGenericArgs, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, constness: Option<ast::BoundConstness>, // Additional features ungated with a bound modifier like `async`. // This is passed down to the implicit associated type binding in @@ -373,7 +374,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, data: &AngleBracketedArgs, param_mode: ParamMode, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, ) -> (GenericArgsCtor<'hir>, bool) { let has_non_lt_args = data.args.iter().any(|arg| match arg { AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_)) @@ -404,7 +405,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_parenthesized_parameter_data( &mut self, data: &ParenthesizedArgs, - itctx: &ImplTraitContext, + itctx: ImplTraitContext, bound_modifier_allowed_features: Option<Lrc<[Symbol]>>, ) -> (GenericArgsCtor<'hir>, bool) { // Switch to `PassThrough` mode for anonymous lifetimes; this @@ -414,7 +415,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // we generally don't permit such things (see #51008). let ParenthesizedArgs { span, inputs, inputs_span, output } = data; let inputs = self.arena.alloc_from_iter(inputs.iter().map(|ty| { - self.lower_ty_direct(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) + self.lower_ty_direct(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam)) })); let output_ty = match output { // Only allow `impl Trait` in return position. i.e.: @@ -428,7 +429,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { self.lower_ty( ty, - &ImplTraitContext::FeatureGated( + ImplTraitContext::FeatureGated( ImplTraitPosition::FnTraitReturn, sym::impl_trait_in_fn_trait_return, ), @@ -436,7 +437,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } FnRetTy::Ty(ty) => { - self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) + self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)) } FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 5f54a0ddf8c..9662c73ca85 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -1,7 +1,7 @@ //! Errors emitted by ast_passes. use rustc_ast::ParamKindOrd; -use rustc_errors::{codes::*, AddToDiagnostic, Applicability}; +use rustc_errors::{codes::*, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessageOp}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -372,13 +372,7 @@ pub struct EmptyLabelManySpans(pub Vec<Span>); // The derive for `Vec<Span>` does multiple calls to `span_label`, adding commas between each impl AddToDiagnostic for EmptyLabelManySpans { - fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { diag.span_labels(self.0, ""); } } @@ -735,13 +729,7 @@ pub struct StableFeature { } impl AddToDiagnostic for StableFeature { - fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { diag.arg("name", self.name); diag.arg("since", self.since); diag.help(fluent::ast_passes_stable_since); diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index fa6cdd55c3d..74d0fff2734 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -11,8 +11,6 @@ #![feature(if_let_guard)] #![feature(iter_is_partitioned)] #![feature(let_chains)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] pub mod ast_validation; mod errors; diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs index 61617beb86b..b9e217a21e3 100644 --- a/compiler/rustc_ast_pretty/src/lib.rs +++ b/compiler/rustc_ast_pretty/src/lib.rs @@ -1,8 +1,6 @@ #![allow(internal_features)] #![feature(rustdoc_internals)] #![doc(rust_logo)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![feature(box_patterns)] mod helpers; diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index 3c5bcecddea..dd87a5c4dc3 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -8,8 +8,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![feature(let_chains)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 948af039537..6a683d129de 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::path_utils::allow_two_phase_borrow; use crate::place_ext::PlaceExt; use crate::BorrowIndex; diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 6cbcda37f50..429bcb74a8e 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -1,3 +1,6 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_errors::{codes::*, struct_span_code_err, DiagCtxt, DiagnosticBuilder}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index 041ac75ec01..ff11e4db121 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use rustc_data_structures::graph::scc::Sccs; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::ConstraintCategory; diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index becfa535a59..a58fe2b7447 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! This file provides API for compiler consumers. use rustc_hir::def_id::LocalDefId; diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 1bd891bdd68..bc5bd787956 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::graph::WithSuccessors; use rustc_index::bit_set::BitSet; diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index d0cf339e7ba..6fd80d005d9 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_middle::mir::visit::{ MutatingUseContext, NonMutatingUseContext, NonUseContext, PlaceContext, }; diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index bb5335febbf..a540fcee871 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use rustc_errors::DiagnosticBuilder; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 6debb3362b0..f87269960bc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1,5 +1,8 @@ // ignore-tidy-filelength +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use either::Either; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; @@ -401,66 +404,60 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let typeck = self.infcx.tcx.typeck(self.mir_def_id()); let hir_id = hir.parent_id(expr.hir_id); - if let Some(parent) = self.infcx.tcx.opt_hir_node(hir_id) { - let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent - && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind - && let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id) - { - (def_id.as_local(), args, 1) - } else if let hir::Node::Expr(parent_expr) = parent - && let hir::ExprKind::Call(call, args) = parent_expr.kind - && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind() - { - (def_id.as_local(), args, 0) - } else { - (None, &[][..], 0) + let parent = self.infcx.tcx.hir_node(hir_id); + let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind + && let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id) + { + (def_id.as_local(), args, 1) + } else if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::Call(call, args) = parent_expr.kind + && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind() + { + (def_id.as_local(), args, 0) + } else { + (None, &[][..], 0) + }; + if let Some(def_id) = def_id + && let node = + self.infcx.tcx.hir_node(self.infcx.tcx.local_def_id_to_hir_id(def_id)) + && let Some(fn_sig) = node.fn_sig() + && let Some(ident) = node.ident() + && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id) + && let Some(arg) = fn_sig.decl.inputs.get(pos + offset) + { + let mut span: MultiSpan = arg.span.into(); + span.push_span_label( + arg.span, + "this parameter takes ownership of the value".to_string(), + ); + let descr = match node.fn_kind() { + Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function", + Some(hir::intravisit::FnKind::Method(..)) => "method", + Some(hir::intravisit::FnKind::Closure) => "closure", }; - if let Some(def_id) = def_id - && let Some(node) = self - .infcx - .tcx - .opt_hir_node(self.infcx.tcx.local_def_id_to_hir_id(def_id)) - && let Some(fn_sig) = node.fn_sig() - && let Some(ident) = node.ident() - && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id) - && let Some(arg) = fn_sig.decl.inputs.get(pos + offset) - { - let mut span: MultiSpan = arg.span.into(); - span.push_span_label( - arg.span, - "this parameter takes ownership of the value".to_string(), - ); - let descr = match node.fn_kind() { - Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function", - Some(hir::intravisit::FnKind::Method(..)) => "method", - Some(hir::intravisit::FnKind::Closure) => "closure", - }; - span.push_span_label(ident.span, format!("in this {descr}")); - err.span_note( - span, - format!( - "consider changing this parameter type in {descr} `{ident}` to \ + span.push_span_label(ident.span, format!("in this {descr}")); + err.span_note( + span, + format!( + "consider changing this parameter type in {descr} `{ident}` to \ borrow instead if owning the value isn't necessary", - ), - ); - } - let place = &self.move_data.move_paths[mpi].place; - let ty = place.ty(self.body, self.infcx.tcx).ty; - if let hir::Node::Expr(parent_expr) = parent - && let hir::ExprKind::Call(call_expr, _) = parent_expr.kind - && let hir::ExprKind::Path(hir::QPath::LangItem( - LangItem::IntoIterIntoIter, - _, - )) = call_expr.kind - { - // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing. - } else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = - move_spans - { - // We already suggest cloning for these cases in `explain_captures`. - } else { - self.suggest_cloning(err, ty, expr, move_span); - } + ), + ); + } + let place = &self.move_data.move_paths[mpi].place; + let ty = place.ty(self.body, self.infcx.tcx).ty; + if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::Call(call_expr, _) = parent_expr.kind + && let hir::ExprKind::Path(hir::QPath::LangItem(LangItem::IntoIterIntoIter, _)) = + call_expr.kind + { + // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing. + } else if let UseSpans::FnSelfUse { kind: CallKind::Normal { .. }, .. } = move_spans + { + // We already suggest cloning for these cases in `explain_captures`. + } else { + self.suggest_cloning(err, ty, expr, move_span); } } if let Some(pat) = finder.pat { @@ -1762,7 +1759,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn_decl: hir::FnDecl { inputs, .. }, .. }) = e.kind - && let Some(hir::Node::Expr(body)) = self.tcx.opt_hir_node(body.hir_id) + && let hir::Node::Expr(body) = self.tcx.hir_node(body.hir_id) { self.suggest_arg = "this: &Self".to_string(); if inputs.len() > 0 { @@ -1828,11 +1825,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - if let Some(hir::Node::ImplItem(hir::ImplItem { + if let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(_fn_sig, body_id), .. - })) = self.infcx.tcx.opt_hir_node(self.mir_hir_id()) - && let Some(hir::Node::Expr(expr)) = self.infcx.tcx.opt_hir_node(body_id.hir_id) + }) = self.infcx.tcx.hir_node(self.mir_hir_id()) + && let hir::Node::Expr(expr) = self.infcx.tcx.hir_node(body_id.hir_id) { let mut finder = ExpressionFinder { capture_span: *capture_kind_span, @@ -2400,8 +2397,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let proper_span = proper_span.source_callsite(); if let Some(scope) = self.body.source_scopes.get(source_info.scope) && let ClearCrossCrate::Set(scope_data) = &scope.local_data - && let Some(node) = self.infcx.tcx.opt_hir_node(scope_data.lint_root) - && let Some(id) = node.body_id() + && let Some(id) = self.infcx.tcx.hir_node(scope_data.lint_root).body_id() && let hir::ExprKind::Block(block, _) = self.infcx.tcx.hir().body(id).value.kind { for stmt in block.stmts { diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 4f66468a865..483ecee850b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -1,5 +1,8 @@ //! Print diagnostics to explain why values are borrowed. +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; @@ -87,7 +90,7 @@ impl<'tcx> BorrowExplanation<'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind && let [hir::PathSegment { ident, args: None, .. }] = p.segments && let hir::def::Res::Local(hir_id) = p.res - && let Some(hir::Node::Pat(pat)) = tcx.opt_hir_node(hir_id) + && let hir::Node::Pat(pat) = tcx.hir_node(hir_id) { err.span_label(pat.span, format!("binding `{ident}` declared here")); } diff --git a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs index 2c4d953f011..ff4f2bb9614 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use std::collections::BTreeSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs index 2495613fea1..94b17e0a2f9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use std::collections::VecDeque; use std::rc::Rc; diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 0a0bb75a2a3..126a50c91b4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -1,3 +1,6 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 55649ec2f16..9e7fd45ec19 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1,3 +1,6 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use hir::ExprKind; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; use rustc_hir as hir; @@ -396,7 +399,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let upvar_hir_id = captured_place.get_root_variable(); - if let Some(Node::Pat(pat)) = self.infcx.tcx.opt_hir_node(upvar_hir_id) + if let Node::Pat(pat) = self.infcx.tcx.hir_node(upvar_hir_id) && let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, upvar_ident, _) = pat.kind { @@ -688,15 +691,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { break; } f_in_trait_opt.and_then(|f_in_trait| { - match self.infcx.tcx.opt_hir_node(f_in_trait) { - Some(Node::TraitItem(hir::TraitItem { + match self.infcx.tcx.hir_node(f_in_trait) { + Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn( hir::FnSig { decl: hir::FnDecl { inputs, .. }, .. }, _, ), .. - })) => { + }) => { let hir::Ty { span, .. } = inputs[local.index() - 1]; Some(span) } @@ -759,10 +762,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // // `let &b = a;` -> `let &(mut b) = a;` if let Some(hir_id) = hir_id - && let Some(hir::Node::Local(hir::Local { + && let hir::Node::Local(hir::Local { pat: hir::Pat { kind: hir::PatKind::Ref(_, _), .. }, .. - })) = self.infcx.tcx.opt_hir_node(hir_id) + }) = self.infcx.tcx.hir_node(hir_id) && let Ok(name) = self.infcx.tcx.sess.source_map().span_to_snippet(local_decl.source_info.span) { @@ -1206,7 +1209,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; if let Some(hir_id) = hir_id - && let Some(hir::Node::Local(local)) = self.infcx.tcx.opt_hir_node(hir_id) + && let hir::Node::Local(local) = self.infcx.tcx.hir_node(hir_id) { let tables = self.infcx.tcx.typeck(def_id.as_local().unwrap()); if let Some(clone_trait) = self.infcx.tcx.lang_items().clone_trait() diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index bac1d9dd57f..93e28a5f3f3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -1,6 +1,9 @@ //! Contains utilities for generating suggestions for borrowck errors related to unsatisfied //! outlives constraints. +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_middle::ty::RegionVid; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 8c8ca1ead40..e69d2ca966b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! Error reporting machinery for lifetime errors. use rustc_data_structures::fx::FxIndexSet; @@ -216,7 +214,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some(id) = placeholder.bound.kind.get_id() && let Some(placeholder_id) = id.as_local() && let gat_hir_id = self.infcx.tcx.local_def_id_to_hir_id(placeholder_id) - && let Some(generics_impl) = hir.get_parent(gat_hir_id).generics() + && let Some(generics_impl) = + hir.get_parent(hir.parent_id(gat_hir_id)).generics() { Some((gat_hir_id, generics_impl)) } else { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index c91b8eaab05..e008d230656 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -1,6 +1,10 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use std::fmt::{self, Display}; use std::iter; +use rustc_data_structures::fx::IndexEntry; use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -14,7 +18,7 @@ use crate::{universal_regions::DefiningTy, MirBorrowckCtxt}; /// A name for a particular region used in emitting diagnostics. This name could be a generated /// name like `'1`, a name used by the user like `'a`, or a name like `'static`. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub(crate) struct RegionName { /// The name of the region (interned). pub(crate) name: Symbol, @@ -25,7 +29,7 @@ pub(crate) struct RegionName { /// Denotes the source of a region that is named by a `RegionName`. For example, a free region that /// was named by the user would get `NamedLateParamRegion` and `'static` lifetime would get `Static`. /// This helps to print the right kinds of diagnostics. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub(crate) enum RegionNameSource { /// A bound (not free) region that was instantiated at the def site (not an HRTB). NamedEarlyParamRegion(Span), @@ -42,7 +46,7 @@ pub(crate) enum RegionNameSource { /// The region corresponding to the return type of a closure. AnonRegionFromOutput(RegionNameHighlight, &'static str), /// The region from a type yielded by a coroutine. - AnonRegionFromYieldTy(Span, String), + AnonRegionFromYieldTy(Span, Symbol), /// An anonymous region from an async fn. AnonRegionFromAsyncFn(Span), /// An anonymous region from an impl self type or trait @@ -51,7 +55,7 @@ pub(crate) enum RegionNameSource { /// Describes what to highlight to explain to the user that we're giving an anonymous region a /// synthesized name, and how to highlight it. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub(crate) enum RegionNameHighlight { /// The anonymous region corresponds to a reference that was found by traversing the type in the HIR. MatchedHirTy(Span), @@ -59,11 +63,11 @@ pub(crate) enum RegionNameHighlight { MatchedAdtAndSegment(Span), /// The anonymous region corresponds to a region where the type annotation is completely missing /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference. - CannotMatchHirTy(Span, String), + CannotMatchHirTy(Span, Symbol), /// The anonymous region corresponds to a region where the type annotation is completely missing /// from the code, and *even if* we print out the full name of the type, the region name won't /// be included. This currently occurs for opaque types like `impl Future`. - Occluded(Span, String), + Occluded(Span, Symbol), } impl RegionName { @@ -247,25 +251,28 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { assert!(self.regioncx.universal_regions().is_universal_region(fr)); - if let Some(value) = self.region_names.try_borrow_mut().unwrap().get(&fr) { - return Some(value.clone()); - } + match self.region_names.borrow_mut().entry(fr) { + IndexEntry::Occupied(precomputed_name) => Some(*precomputed_name.get()), + IndexEntry::Vacant(slot) => { + let new_name = self + .give_name_from_error_region(fr) + .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr)) + .or_else(|| { + self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr) + }); + + if let Some(new_name) = new_name { + slot.insert(new_name); + } + debug!("give_region_a_name: gave name {:?}", new_name); - let value = self - .give_name_from_error_region(fr) - .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr)); - - if let Some(value) = &value { - self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone()); + new_name + } } - - debug!("give_region_a_name: gave name {:?}", value); - value } /// Checks for the case where `fr` maps to something that the @@ -457,9 +464,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ); if type_name.contains(&format!("'{counter}")) { // Only add a label if we can confirm that a region was labelled. - RegionNameHighlight::CannotMatchHirTy(span, type_name) + RegionNameHighlight::CannotMatchHirTy(span, Symbol::intern(&type_name)) } else { - RegionNameHighlight::Occluded(span, type_name) + RegionNameHighlight::Occluded(span, Symbol::intern(&type_name)) } } @@ -888,7 +895,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { Some(RegionName { name: self.synthesize_region_name(), - source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name), + source: RegionNameSource::AnonRegionFromYieldTy(yield_span, Symbol::intern(&type_name)), }) } @@ -980,7 +987,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { Some(RegionName { name: region_name, source: RegionNameSource::AnonRegionFromArgument( - RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?.to_string()), + RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?), ), }) } else { diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 28e07f2a81e..0479cd8af35 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -1,6 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use crate::region_infer::RegionInferenceContext; use rustc_index::IndexSlice; use rustc_middle::mir::{Body, Local}; diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs index c54e7070478..68dc9a6764b 100644 --- a/compiler/rustc_borrowck/src/facts.rs +++ b/compiler/rustc_borrowck/src/facts.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::location::{LocationIndex, LocationTable}; use crate::BorrowIndex; use polonius_engine::AllFacts as PoloniusFacts; diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index bb64571889b..4dba34c11f9 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -111,14 +111,16 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { let (input_body, promoted) = tcx.mir_promoted(def); debug!("run query mir_borrowck: {}", tcx.def_path_str(def)); - if input_body.borrow().should_skip() { - debug!("Skipping borrowck because of injected body"); + let input_body: &Body<'_> = &input_body.borrow(); + + if input_body.should_skip() || input_body.tainted_by_errors.is_some() { + debug!("Skipping borrowck because of injected body or tainted body"); // Let's make up a borrowck result! Fun times! let result = BorrowCheckResult { concrete_opaque_types: FxIndexMap::default(), closure_requirements: None, used_mut_upvars: SmallVec::new(), - tainted_by_errors: None, + tainted_by_errors: input_body.tainted_by_errors, }; return tcx.arena.alloc(result); } @@ -127,7 +129,6 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build(); - let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexSlice<_, _> = &promoted.borrow(); let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0; debug!("mir_borrowck done"); diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/location.rs index 6f09393169f..63e59217e5d 100644 --- a/compiler/rustc_borrowck/src/location.rs +++ b/compiler/rustc_borrowck/src/location.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_index::IndexVec; use rustc_middle::mir::{BasicBlock, Body, Location}; diff --git a/compiler/rustc_borrowck/src/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs index 842e9008058..5129b32d492 100644 --- a/compiler/rustc_borrowck/src/member_constraints.rs +++ b/compiler/rustc_borrowck/src/member_constraints.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexMap; use rustc_index::{IndexSlice, IndexVec}; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 7ace013975e..80d79e1beb7 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! The entry point of the NLL borrow checker. use polonius_engine::{Algorithm, Output}; @@ -184,7 +182,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( // Solve the region constraints. let (closure_region_requirements, nll_errors) = - regioncx.solve(infcx, param_env, body, polonius_output.clone()); + regioncx.solve(infcx, body, polonius_output.clone()); if !nll_errors.is_empty() { // Suppress unhelpful extra errors in `infer_opaque_types`. diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index 4cfde47664e..adafad7fa2f 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation}; use crate::places_conflict; use crate::AccessDepth; diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs index 3d7e8c6ebf3..b59ab7fafa5 100644 --- a/compiler/rustc_borrowck/src/place_ext.rs +++ b/compiler/rustc_borrowck/src/place_ext.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::borrow_set::LocalsStateAtExit; use rustc_hir as hir; use rustc_middle::mir::ProjectionElem; diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 777ebf0d438..7e8dba43b71 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -50,8 +50,6 @@ //! and either equal or disjoint. //! - If we did run out of access, the borrow can access a part of it. -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::ArtificialField; use crate::Overlap; use crate::{AccessDepth, Deep, Shallow}; diff --git a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs index 5c9056272cc..93aae1a7f97 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_invalidations.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::graph::dominators::Dominators; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{self, BasicBlock, Body, Location, NonDivergingIntrinsic, Place, Rvalue}; diff --git a/compiler/rustc_borrowck/src/polonius/loan_kills.rs b/compiler/rustc_borrowck/src/polonius/loan_kills.rs index 5df94383702..53adad5561e 100644 --- a/compiler/rustc_borrowck/src/polonius/loan_kills.rs +++ b/compiler/rustc_borrowck/src/polonius/loan_kills.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{ Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index e9c9709bd1f..8bb3dc88b34 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! From the NLL RFC: "The deep [aka 'supporting'] prefixes for an //! place are formed by stripping away fields and derefs, except that //! we stop when we reach the deref of a shared reference. [...] " diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs index cfbb2766c33..53541b33c41 100644 --- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs +++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! As part of generating the regions, if you enable `-Zdump-mir=nll`, //! we will generate an annotated copy of the MIR that includes the //! state of region inference. This code handles emitting the region diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs index 408c8390e76..c103ba3c407 100644 --- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! This module provides linkage between RegionInferenceContext and //! `rustc_graphviz` traits, specialized to attaching borrowck analysis //! data to rendered labels. diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 89b203f80a4..3153b709ffe 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -658,7 +658,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(super) fn solve( &mut self, infcx: &InferCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, polonius_output: Option<Rc<PoloniusOutput>>, ) -> (Option<ClosureRegionRequirements<'tcx>>, RegionErrors<'tcx>) { @@ -674,7 +673,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // eagerly. let mut outlives_requirements = infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); - self.check_type_tests(infcx, body, outlives_requirements.as_mut(), &mut errors_buffer); + self.check_type_tests(infcx, outlives_requirements.as_mut(), &mut errors_buffer); debug!(?errors_buffer); debug!(?outlives_requirements); @@ -932,7 +931,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn check_type_tests( &self, infcx: &InferCtxt<'tcx>, - body: &Body<'tcx>, mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>, errors_buffer: &mut RegionErrors<'tcx>, ) { @@ -957,12 +955,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements { - if self.try_promote_type_test( - infcx, - body, - type_test, - propagated_outlives_requirements, - ) { + if self.try_promote_type_test(infcx, type_test, propagated_outlives_requirements) { continue; } } @@ -1016,7 +1009,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn try_promote_type_test( &self, infcx: &InferCtxt<'tcx>, - body: &Body<'tcx>, type_test: &TypeTest<'tcx>, propagated_outlives_requirements: &mut Vec<ClosureOutlivesRequirement<'tcx>>, ) -> bool { @@ -1179,35 +1171,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { Some(ClosureOutlivesSubject::Ty(ClosureOutlivesSubjectTy::bind(tcx, ty))) } - /// Returns a universally quantified region that outlives the - /// value of `r` (`r` may be existentially or universally - /// quantified). - /// - /// Since `r` is (potentially) an existential region, it has some - /// value which may include (a) any number of points in the CFG - /// and (b) any number of `end('x)` elements of universally - /// quantified regions. To convert this into a single universal - /// region we do as follows: - /// - /// - Ignore the CFG points in `'r`. All universally quantified regions - /// include the CFG anyhow. - /// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding - /// a result `'y`. - #[instrument(skip(self), level = "debug", ret)] - pub(crate) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid { - debug!(r = %self.region_value_str(r)); - - // Find the smallest universal region that contains all other - // universal regions within `region`. - let mut lub = self.universal_regions.fr_fn_body; - let r_scc = self.constraint_sccs.scc(r); - for ur in self.scc_values.universal_regions_outlived_by(r_scc) { - lub = self.universal_region_relations.postdom_upper_bound(lub, ur); - } - - lub - } - /// Like `universal_upper_bound`, but returns an approximation more suitable /// for diagnostics. If `r` contains multiple disjoint universal regions /// (e.g. 'a and 'b in `fn foo<'a, 'b> { ... }`, we pick the lower-numbered region. diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 462b5c8da42..636c174e002 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -418,6 +418,8 @@ fn check_opaque_type_parameter_valid( .into_iter() .map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id)) .collect(); + #[allow(rustc::diagnostic_outside_of_impl)] + #[allow(rustc::untranslatable_diagnostic)] return Err(tcx .dcx() .struct_span_err(span, "non-defining opaque type use in defining scope") diff --git a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs index fe56bd54a3f..eeb944702a7 100644 --- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs +++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::constraints::ConstraintSccIndex; use crate::RegionInferenceContext; use itertools::Itertools; diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index e147f62011d..b1caaa63881 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::SparseBitMatrix; diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index a31d39e14cd..dca8df32800 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use crate::BorrowckInferCtxt; use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 52559f9039b..c97e3170166 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -5,10 +5,13 @@ use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelega use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; -use rustc_middle::ty::GenericArgKind; -use rustc_middle::ty::{self, TyCtxt}; -use rustc_middle::ty::{TypeFoldable, TypeVisitableExt}; +use rustc_middle::traits::query::NoSolution; +use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::{Span, DUMMY_SP}; +use rustc_trait_selection::solve::deeply_normalize; +use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; +use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use crate::{ constraints::OutlivesConstraint, @@ -33,6 +36,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> { /// our special inference variable there, we would mess that up. region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, + param_env: ty::ParamEnv<'tcx>, known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], locations: Locations, span: Span, @@ -47,6 +51,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { universal_regions: &'a UniversalRegions<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, + param_env: ty::ParamEnv<'tcx>, known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], locations: Locations, span: Span, @@ -59,6 +64,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { universal_regions, region_bound_pairs, implicit_region_bound, + param_env, known_type_outlives_obligations, locations, span, @@ -137,36 +143,68 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { // Extract out various useful fields we'll need below. let ConstraintConversion { tcx, + infcx, region_bound_pairs, implicit_region_bound, known_type_outlives_obligations, .. } = *self; - let ty::OutlivesPredicate(k1, r2) = predicate; - match k1.unpack() { - GenericArgKind::Lifetime(r1) => { - let r1_vid = self.to_region_vid(r1); - let r2_vid = self.to_region_vid(r2); - self.add_outlives(r1_vid, r2_vid, constraint_category); + let mut outlives_predicates = vec![(predicate, constraint_category)]; + for iteration in 0.. { + if outlives_predicates.is_empty() { + break; + } + + if !self.tcx.recursion_limit().value_within_limit(iteration) { + bug!( + "FIXME(-Znext-solver): Overflowed when processing region obligations: {outlives_predicates:#?}" + ); } - GenericArgKind::Type(t1) => { - // we don't actually use this for anything, but - // the `TypeOutlives` code needs an origin. - let origin = infer::RelateParamBound(DUMMY_SP, t1, None); + let mut next_outlives_predicates = vec![]; + for (ty::OutlivesPredicate(k1, r2), constraint_category) in outlives_predicates { + match k1.unpack() { + GenericArgKind::Lifetime(r1) => { + let r1_vid = self.to_region_vid(r1); + let r2_vid = self.to_region_vid(r2); + self.add_outlives(r1_vid, r2_vid, constraint_category); + } - TypeOutlives::new( - &mut *self, - tcx, - region_bound_pairs, - Some(implicit_region_bound), - known_type_outlives_obligations, - ) - .type_must_outlive(origin, t1, r2, constraint_category); + GenericArgKind::Type(mut t1) => { + // Normalize the type we receive from a `TypeOutlives` obligation + // in the new trait solver. + if infcx.next_trait_solver() { + t1 = self.normalize_and_add_type_outlives_constraints( + t1, + &mut next_outlives_predicates, + ); + } + + // we don't actually use this for anything, but + // the `TypeOutlives` code needs an origin. + let origin = infer::RelateParamBound(DUMMY_SP, t1, None); + + TypeOutlives::new( + &mut *self, + tcx, + region_bound_pairs, + Some(implicit_region_bound), + known_type_outlives_obligations, + ) + .type_must_outlive( + origin, + t1, + r2, + constraint_category, + ); + } + + GenericArgKind::Const(_) => unreachable!(), + } } - GenericArgKind::Const(_) => unreachable!(), + outlives_predicates = next_outlives_predicates; } } @@ -232,6 +270,42 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { debug!("add_type_test(type_test={:?})", type_test); self.constraints.type_tests.push(type_test); } + + fn normalize_and_add_type_outlives_constraints( + &self, + ty: Ty<'tcx>, + next_outlives_predicates: &mut Vec<( + ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>, + ConstraintCategory<'tcx>, + )>, + ) -> Ty<'tcx> { + let result = CustomTypeOp::new( + |ocx| { + deeply_normalize( + ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env), + ty, + ) + .map_err(|_| NoSolution) + }, + "normalize type outlives obligation", + ) + .fully_perform(self.infcx, self.span); + + match result { + Ok(TypeOpOutput { output: ty, constraints, .. }) => { + if let Some(constraints) = constraints { + assert!( + constraints.member_constraints.is_empty(), + "no member constraints expected from normalizing: {:#?}", + constraints.member_constraints + ); + next_outlives_predicates.extend(constraints.outlives.iter().copied()); + } + ty + } + Err(_) => ty, + } + } } impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> { diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index d518f54fd25..2e0caf44819 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -8,8 +8,11 @@ use rustc_infer::infer::region_constraints::GenericKind; use rustc_infer::infer::InferCtxt; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::query::OutlivesBound; +use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt}; -use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; +use rustc_span::{ErrorGuaranteed, DUMMY_SP}; +use rustc_trait_selection::solve::deeply_normalize; +use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use std::rc::Rc; use type_op::TypeOpOutput; @@ -52,7 +55,6 @@ pub(crate) struct CreateResult<'tcx> { pub(crate) fn create<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], implicit_region_bound: ty::Region<'tcx>, universal_regions: &Rc<UniversalRegions<'tcx>>, constraints: &mut MirTypeckRegionConstraints<'tcx>, @@ -60,7 +62,6 @@ pub(crate) fn create<'tcx>( UniversalRegionRelationsBuilder { infcx, param_env, - known_type_outlives_obligations, implicit_region_bound, constraints, universal_regions: universal_regions.clone(), @@ -178,7 +179,6 @@ impl UniversalRegionRelations<'_> { struct UniversalRegionRelationsBuilder<'this, 'tcx> { infcx: &'this InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>], universal_regions: Rc<UniversalRegions<'tcx>>, implicit_region_bound: ty::Region<'tcx>, constraints: &'this mut MirTypeckRegionConstraints<'tcx>, @@ -222,6 +222,32 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { self.relate_universal_regions(fr, fr_fn_body); } + // Normalize the assumptions we use to borrowck the program. + let mut constraints = vec![]; + let mut known_type_outlives_obligations = vec![]; + for bound in param_env.caller_bounds() { + let Some(mut outlives) = bound.as_type_outlives_clause() else { continue }; + + // In the new solver, normalize the type-outlives obligation assumptions. + if self.infcx.next_trait_solver() { + match deeply_normalize( + self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), self.param_env), + outlives, + ) { + Ok(normalized_outlives) => { + outlives = normalized_outlives; + } + Err(e) => { + self.infcx.err_ctxt().report_fulfillment_errors(e); + } + } + } + + known_type_outlives_obligations.push(outlives); + } + let known_type_outlives_obligations = + self.infcx.tcx.arena.alloc_slice(&known_type_outlives_obligations); + let unnormalized_input_output_tys = self .universal_regions .unnormalized_input_tys @@ -239,7 +265,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { // the `relations` is built. let mut normalized_inputs_and_output = Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1); - let mut constraints = vec![]; for ty in unnormalized_input_output_tys { debug!("build: input_or_output={:?}", ty); // We add implied bounds from both the unnormalized and normalized ty. @@ -304,7 +329,19 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { } for c in constraints { - self.push_region_constraints(c, span); + constraint_conversion::ConstraintConversion::new( + self.infcx, + &self.universal_regions, + &self.region_bound_pairs, + self.implicit_region_bound, + param_env, + known_type_outlives_obligations, + Locations::All(span), + span, + ConstraintCategory::Internal, + self.constraints, + ) + .convert_all(c); } CreateResult { @@ -313,30 +350,12 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { outlives: self.outlives.freeze(), inverse_outlives: self.inverse_outlives.freeze(), }), - known_type_outlives_obligations: self.known_type_outlives_obligations, + known_type_outlives_obligations, region_bound_pairs: self.region_bound_pairs, normalized_inputs_and_output, } } - #[instrument(skip(self, data), level = "debug")] - fn push_region_constraints(&mut self, data: &QueryRegionConstraints<'tcx>, span: Span) { - debug!("constraints generated: {:#?}", data); - - constraint_conversion::ConstraintConversion::new( - self.infcx, - &self.universal_regions, - &self.region_bound_pairs, - self.implicit_region_bound, - self.known_type_outlives_obligations, - Locations::All(span), - span, - ConstraintCategory::Internal, - self.constraints, - ) - .convert_all(data); - } - /// Update the type of a single local, which should represent /// either the return type of the MIR or one of its arguments. At /// the same time, compute and add any implied bounds that come diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index cdb187e0776..cfb46f3ac8a 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] //! This pass type-checks the MIR to ensure it is not broken. use std::rc::Rc; @@ -156,10 +154,6 @@ pub(crate) fn type_check<'mir, 'tcx>( } = free_region_relations::create( infcx, param_env, - // FIXME(-Znext-solver): These are unnormalized. Normalize them. - infcx.tcx.arena.alloc_from_iter( - param_env.caller_bounds().iter().filter_map(|clause| clause.as_type_outlives_clause()), - ), implicit_region_bound, universal_regions, &mut constraints, @@ -217,7 +211,6 @@ pub(crate) fn type_check<'mir, 'tcx>( CustomTypeOp::new( |ocx| { ocx.infcx.register_member_constraints( - param_env, opaque_type_key, decl.hidden_type.ty, decl.hidden_type.span, @@ -1144,6 +1137,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.borrowck_context.universal_regions, self.region_bound_pairs, self.implicit_region_bound, + self.param_env, self.known_type_outlives_obligations, locations, locations.span(self.body), @@ -1987,6 +1981,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::SizedBound, ); } + &Rvalue::NullaryOp(NullOp::DebugAssertions, _) => {} Rvalue::ShallowInitBox(operand, ty) => { self.check_operand(operand, location); @@ -2759,6 +2754,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.borrowck_context.universal_regions, self.region_bound_pairs, self.implicit_region_bound, + self.param_env, self.known_type_outlives_obligations, locations, DUMMY_SP, // irrelevant; will be overridden. diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 111eaaf60f7..a7bdfa4eae7 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -12,6 +12,9 @@ //! The code in this file doesn't *do anything* with those results; it //! just returns them for other code to use. +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, LocalDefId}; diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index 6ac8e1ba715..81757a62e5b 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxIndexSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index eadb48ddd36..8d2e06bf30d 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ - codes::*, AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, - Level, MultiSpan, SingleLabelManySpans, + codes::*, AddToDiagnostic, DiagCtxt, Diagnostic, DiagnosticBuilder, EmissionGuarantee, + IntoDiagnostic, Level, MultiSpan, SingleLabelManySpans, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -611,13 +611,7 @@ pub(crate) struct FormatUnusedArg { // Allow the singular form to be a subdiagnostic of the multiple-unused // form of diagnostic. impl AddToDiagnostic for FormatUnusedArg { - fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, f: F) - where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) { diag.arg("named", self.named); let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into()); diag.span_label(self.span, msg); diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 4d7957ef4dd..d30ccab2394 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -2,6 +2,8 @@ //! injecting code into the crate before it is lowered to HIR. #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(rustdoc_internals)] #![doc(rust_logo)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 0afd6d0e670..a7e76fbc128 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -767,6 +767,15 @@ fn codegen_stmt<'tcx>( NullOp::OffsetOf(fields) => { layout.offset_of_subfield(fx, fields.iter()).bytes() } + NullOp::DebugAssertions => { + let val = fx.tcx.sess.opts.debug_assertions; + let val = CValue::by_val( + fx.bcx.ins().iconst(types::I8, i64::try_from(val).unwrap()), + fx.layout_of(fx.tcx.types.bool), + ); + lval.write_cvalue(fx, val); + return; + } }; let val = CValue::by_val( fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(val).unwrap()), diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 416f87fcc87..7c432e9c590 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -3,6 +3,8 @@ #![cfg_attr(doc, doc(rust_logo))] #![feature(rustc_private)] // Note: please avoid adding other feature gates where possible +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] #![warn(unreachable_pub)] diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs index 9f361d36886..142f86b003d 100644 --- a/compiler/rustc_codegen_gcc/src/attributes.rs +++ b/compiler/rustc_codegen_gcc/src/attributes.rs @@ -62,9 +62,6 @@ pub fn from_fn_attrs<'gcc, 'tcx>( if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { func.add_attribute(FnAttribute::Cold); } - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) { - func.add_attribute(FnAttribute::ReturnsTwice); - } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) { func.add_attribute(FnAttribute::Pure); } diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index f8f054db65e..863b6333bcc 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -27,8 +27,6 @@ #![recursion_limit="256"] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] extern crate rustc_apfloat; extern crate rustc_ast; diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl index d5bc04f594d..d14fe0299e6 100644 --- a/compiler/rustc_codegen_llvm/messages.ftl +++ b/compiler/rustc_codegen_llvm/messages.ftl @@ -28,6 +28,8 @@ codegen_llvm_invalid_minimum_alignment_not_power_of_two = codegen_llvm_invalid_minimum_alignment_too_large = invalid minimum global alignment: {$align} is too large +codegen_llvm_invalid_target_feature_prefix = target feature `{$feature}` must begin with a `+` or `-`" + codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}" codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err} diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 0a7ea599431..07c83f1aa08 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -356,9 +356,6 @@ pub fn from_fn_attrs<'ll, 'tcx>( if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { to_add.push(AttributeKind::Cold.create_attr(cx.llcx)); } - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_RETURNS_TWICE) { - to_add.push(AttributeKind::ReturnsTwice.create_attr(cx.llcx)); - } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::FFI_PURE) { to_add.push(MemoryEffects::ReadOnly.create_attr(cx.llcx)); } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 76c9ac6614a..f961cd2d00b 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -461,6 +461,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D } ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id), ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id), + ty::CoroutineClosure(..) => build_closure_env_di_node(cx, unique_type_id), ty::Coroutine(..) => enums::build_coroutine_di_node(cx, unique_type_id), ty::Adt(def, ..) => match def.adt_kind() { AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id), @@ -1068,6 +1069,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( let (&def_id, up_var_tys) = match closure_or_coroutine_ty.kind() { ty::Coroutine(def_id, args) => (def_id, args.as_coroutine().prefix_tys()), ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()), + ty::CoroutineClosure(def_id, args) => (def_id, args.as_coroutine_closure().upvar_tys()), _ => { bug!( "build_upvar_field_di_nodes() called with non-closure-or-coroutine-type: {:?}", @@ -1153,7 +1155,8 @@ fn build_closure_env_di_node<'ll, 'tcx>( unique_type_id: UniqueTypeId<'tcx>, ) -> DINodeCreationResult<'ll> { let closure_env_type = unique_type_id.expect_ty(); - let &ty::Closure(def_id, _args) = closure_env_type.kind() else { + let &(ty::Closure(def_id, _) | ty::CoroutineClosure(def_id, _)) = closure_env_type.kind() + else { bug!("build_closure_env_di_node() called with non-closure-type: {:?}", closure_env_type) }; let containing_scope = get_namespace_for_item(cx, def_id); diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index e839d278bea..587c5e9e8d2 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -253,3 +253,9 @@ pub struct MismatchedDataLayout<'a> { pub llvm_target: &'a str, pub llvm_layout: &'a str, } + +#[derive(Diagnostic)] +#[diag(codegen_llvm_invalid_target_feature_prefix)] +pub(crate) struct InvalidTargetFeaturePrefix<'a> { + pub feature: &'a str, +} diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index b4512af38e3..e3e48ecb3aa 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1985,10 +1985,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>( match in_elem.kind() { ty::RawPtr(p) => { - let (metadata, check_sized) = p.ty.ptr_metadata_ty(bx.tcx, |ty| { + let metadata = p.ty.ptr_metadata_ty(bx.tcx, |ty| { bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) }); - assert!(!check_sized); // we are in codegen, so we shouldn't see these types require!( metadata.is_unit(), InvalidMonomorphization::CastFatPointer { span, name, ty: in_elem } @@ -2000,10 +1999,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } match out_elem.kind() { ty::RawPtr(p) => { - let (metadata, check_sized) = p.ty.ptr_metadata_ty(bx.tcx, |ty| { + let metadata = p.ty.ptr_metadata_ty(bx.tcx, |ty| { bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) }); - assert!(!check_sized); // we are in codegen, so we shouldn't see these types require!( metadata.is_unit(), InvalidMonomorphization::CastFatPointer { span, name, ty: out_elem } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index f4f29078190..de96bf477ad 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -15,8 +15,6 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(impl_trait_in_assoc_type)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 4ad44a42738..d0044086c61 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -184,7 +184,6 @@ pub enum AttributeKind { SanitizeMemory = 22, NonLazyBind = 23, OptimizeNone = 24, - ReturnsTwice = 25, ReadNone = 26, SanitizeHWAddress = 28, WillReturn = 29, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 99f4488ac0f..4bb400b1879 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -1,7 +1,7 @@ use crate::back::write::create_informational_target_machine; use crate::errors::{ - PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, - UnknownCTargetFeaturePrefix, UnstableCTargetFeature, + InvalidTargetFeaturePrefix, PossibleFeature, TargetFeatureDisableOrEnable, + UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature, }; use crate::llvm; use libc::c_int; @@ -511,7 +511,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str sess.target .features .split(',') - .filter(|v| !v.is_empty() && backend_feature_name(v).is_some()) + .filter(|v| !v.is_empty() && backend_feature_name(sess, v).is_some()) .map(String::from), ); @@ -535,7 +535,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str } }; - let feature = backend_feature_name(s)?; + let feature = backend_feature_name(sess, s)?; // Warn against use of LLVM specific feature names and unstable features on the CLI. if diagnostics { let feature_state = supported_features.iter().find(|&&(v, _)| v == feature); @@ -611,11 +611,11 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str /// Returns a feature name for the given `+feature` or `-feature` string. /// /// Only allows features that are backend specific (i.e. not [`RUSTC_SPECIFIC_FEATURES`].) -fn backend_feature_name(s: &str) -> Option<&str> { +fn backend_feature_name<'a>(sess: &Session, s: &'a str) -> Option<&'a str> { // features must start with a `+` or `-`. - let feature = s.strip_prefix(&['+', '-'][..]).unwrap_or_else(|| { - bug!("target feature `{}` must begin with a `+` or `-`", s); - }); + let feature = s + .strip_prefix(&['+', '-'][..]) + .unwrap_or_else(|| sess.dcx().emit_fatal(InvalidTargetFeaturePrefix { feature: s })); // Rustc-specific feature requests like `+crt-static` or `-crt-static` // are not passed down to LLVM. if RUSTC_SPECIFIC_FEATURES.contains(&feature) { diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index f796ce0990f..f7630719368 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -123,6 +123,17 @@ impl CodegenCx<'_, '_> { return false; } + // Match clang by only supporting COFF and ELF for now. + if self.tcx.sess.target.is_like_osx { + return false; + } + + // With pie relocation model calls of functions defined in the translation + // unit can use copy relocations. + if self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration { + return true; + } + // Thread-local variables generally don't support copy relocations. let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval) .is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True); @@ -130,18 +141,12 @@ impl CodegenCx<'_, '_> { return false; } - // Match clang by only supporting COFF and ELF for now. - if self.tcx.sess.target.is_like_osx { - return false; + // Respect the direct-access-external-data to override default behavior if present. + if let Some(direct) = self.tcx.sess.direct_access_external_data() { + return direct; } // Static relocation model should force copy relocations everywhere. - if self.tcx.sess.relocation_model() == RelocModel::Static { - return true; - } - - // With pie relocation model calls of functions defined in the translation - // unit can use copy relocations. - self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration + self.tcx.sess.relocation_model() == RelocModel::Static } } diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 7d2f5bb193a..c4aaf421444 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -9,7 +9,7 @@ ar_archive_writer = "0.1.5" bitflags = "2.4.1" cc = "1.0.69" itertools = "0.11" -jobserver = "0.1.27" +jobserver = "0.1.28" pathdiff = "0.2.0" regex = "1.4" rustc_arena = { path = "../rustc_arena" } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 4211f875dd0..9b24339d255 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1810,7 +1810,7 @@ impl Translate for SharedEmitter { } impl Emitter for SharedEmitter { - fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { + fn emit_diagnostic(&mut self, diag: rustc_errors::Diagnostic) { let args: FxHashMap<DiagnosticArgName, DiagnosticArgValue> = diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect(); drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 47b1b080119..b387d0b2258 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -103,9 +103,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { match name { sym::cold => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, sym::rustc_allocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR, - sym::ffi_returns_twice => { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE - } sym::ffi_pure => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE, sym::ffi_const => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST, sym::rustc_nounwind => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND, diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index fc833a3863e..1afc597a7ef 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -2,6 +2,8 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(if_let_guard)] diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 266505d3f26..5c6060a7159 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -672,17 +672,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let val = match null_op { mir::NullOp::SizeOf => { assert!(bx.cx().type_is_sized(ty)); - layout.size.bytes() + let val = layout.size.bytes(); + bx.cx().const_usize(val) } mir::NullOp::AlignOf => { assert!(bx.cx().type_is_sized(ty)); - layout.align.abi.bytes() + let val = layout.align.abi.bytes(); + bx.cx().const_usize(val) } mir::NullOp::OffsetOf(fields) => { - layout.offset_of_subfield(bx.cx(), fields.iter()).bytes() + let val = layout.offset_of_subfield(bx.cx(), fields.iter()).bytes(); + bx.cx().const_usize(val) + } + mir::NullOp::DebugAssertions => { + let val = bx.tcx().sess.opts.debug_assertions; + bx.cx().const_bool(val) } }; - let val = bx.cx().const_usize(val); let tcx = self.cx.tcx(); OperandRef { val: OperandValue::Immediate(val), diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index a158fc6e260..ac7dfbb261d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -1,5 +1,6 @@ use rustc_middle::mir; use rustc_middle::mir::NonDivergingIntrinsic; +use rustc_session::config::OptLevel; use super::FunctionCx; use super::LocalRef; @@ -67,8 +68,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_coverage(bx, coverage, statement.source_info.scope); } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => { - let op_val = self.codegen_operand(bx, op); - bx.assume(op_val.immediate()); + if !matches!(bx.tcx().sess.opts.optimize, OptLevel::No | OptLevel::Less) { + let op_val = self.codegen_operand(bx, op); + bx.assume(op_val.immediate()); + } } mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping( mir::CopyNonOverlapping { ref count, ref src, ref dst }, diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 6a92ed9717d..a2d0f1c5583 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -1,5 +1,3 @@ -use std::mem; - use either::{Left, Right}; use rustc_hir::def::DefKind; @@ -24,12 +22,13 @@ use crate::interpret::{ }; // Returns a pointer to where the result lives +#[instrument(level = "trace", skip(ecx, body), ret)] fn eval_body_using_ecx<'mir, 'tcx>( ecx: &mut CompileTimeEvalContext<'mir, 'tcx>, cid: GlobalId<'tcx>, body: &'mir mir::Body<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { - debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env); + trace!(?ecx.param_env); let tcx = *ecx.tcx; assert!( cid.promoted.is_some() @@ -75,11 +74,8 @@ fn eval_body_using_ecx<'mir, 'tcx>( None => InternKind::Constant, } }; - let check_alignment = mem::replace(&mut ecx.machine.check_alignment, CheckAlignment::No); // interning doesn't need to respect alignment intern_const_alloc_recursive(ecx, intern_kind, &ret)?; - ecx.machine.check_alignment = check_alignment; - debug!("eval_body_using_ecx done: {:?}", ret); Ok(ret) } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 751fbfacaad..38e7843761b 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -41,13 +41,12 @@ pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine< /// allocation is interned immutably; if it is `Mutability::Mut`, then the allocation *must be* /// already mutable (as a sanity check). /// -/// `recursive_alloc` is called for all recursively encountered allocations. +/// Returns an iterator over all relocations referred to by this allocation. fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>( ecx: &'rt mut InterpCx<'mir, 'tcx, M>, alloc_id: AllocId, mutability: Mutability, - mut recursive_alloc: impl FnMut(&InterpCx<'mir, 'tcx, M>, CtfeProvenance), -) -> Result<(), ()> { +) -> Result<impl Iterator<Item = CtfeProvenance> + 'tcx, ()> { trace!("intern_shallow {:?}", alloc_id); // remove allocation let Some((_kind, mut alloc)) = ecx.memory.alloc_map.remove(&alloc_id) else { @@ -65,14 +64,10 @@ fn intern_shallow<'rt, 'mir, 'tcx, T, M: CompileTimeMachine<'mir, 'tcx, T>>( assert_eq!(alloc.mutability, Mutability::Mut); } } - // record child allocations - for &(_, prov) in alloc.provenance().ptrs().iter() { - recursive_alloc(ecx, prov); - } // link the alloc id to the actual allocation let alloc = ecx.tcx.mk_const_alloc(alloc); ecx.tcx.set_alloc_id_memory(alloc_id, alloc); - Ok(()) + Ok(alloc.0.0.provenance().ptrs().iter().map(|&(_, prov)| prov)) } /// How a constant value should be interned. @@ -128,12 +123,16 @@ pub fn intern_const_alloc_recursive< } }; - // Initialize recursive interning. + // Intern the base allocation, and initialize todo list for recursive interning. let base_alloc_id = ret.ptr().provenance.unwrap().alloc_id(); - let mut todo = vec![(base_alloc_id, base_mutability)]; + // First we intern the base allocation, as it requires a different mutability. + // This gives us the initial set of nested allocations, which will then all be processed + // recursively in the loop below. + let mut todo: Vec<_> = + intern_shallow(ecx, base_alloc_id, base_mutability).unwrap().map(|prov| prov).collect(); // We need to distinguish "has just been interned" from "was already in `tcx`", // so we track this in a separate set. - let mut just_interned = FxHashSet::default(); + let mut just_interned: FxHashSet<_> = std::iter::once(base_alloc_id).collect(); // Whether we encountered a bad mutable pointer. // We want to first report "dangling" and then "mutable", so we need to delay reporting these // errors. @@ -147,52 +146,56 @@ pub fn intern_const_alloc_recursive< // raw pointers, so we cannot rely on validation to catch them -- and since interning runs // before validation, and interning doesn't know the type of anything, this means we can't show // better errors. Maybe we should consider doing validation before interning in the future. - while let Some((alloc_id, mutability)) = todo.pop() { + while let Some(prov) = todo.pop() { + let alloc_id = prov.alloc_id(); + // Crucially, we check this *before* checking whether the `alloc_id` + // has already been interned. The point of this check is to ensure that when + // there are multiple pointers to the same allocation, they are *all* immutable. + // Therefore it would be bad if we only checked the first pointer to any given + // allocation. + // (It is likely not possible to actually have multiple pointers to the same allocation, + // so alternatively we could also check that and ICE if there are multiple such pointers.) + if intern_kind != InternKind::Promoted + && inner_mutability == Mutability::Not + && !prov.immutable() + { + if ecx.tcx.try_get_global_alloc(alloc_id).is_some() + && !just_interned.contains(&alloc_id) + { + // This is a pointer to some memory from another constant. We encounter mutable + // pointers to such memory since we do not always track immutability through + // these "global" pointers. Allowing them is harmless; the point of these checks + // during interning is to justify why we intern the *new* allocations immutably, + // so we can completely ignore existing allocations. We also don't need to add + // this to the todo list, since after all it is already interned. + continue; + } + // Found a mutable pointer inside a const where inner allocations should be + // immutable. We exclude promoteds from this, since things like `&mut []` and + // `&None::<Cell<i32>>` lead to promotion that can produce mutable pointers. We rely + // on the promotion analysis not screwing up to ensure that it is sound to intern + // promoteds as immutable. + found_bad_mutable_pointer = true; + } if ecx.tcx.try_get_global_alloc(alloc_id).is_some() { // Already interned. debug_assert!(!ecx.memory.alloc_map.contains_key(&alloc_id)); continue; } just_interned.insert(alloc_id); - intern_shallow(ecx, alloc_id, mutability, |ecx, prov| { - let alloc_id = prov.alloc_id(); - if intern_kind != InternKind::Promoted - && inner_mutability == Mutability::Not - && !prov.immutable() - { - if ecx.tcx.try_get_global_alloc(alloc_id).is_some() - && !just_interned.contains(&alloc_id) - { - // This is a pointer to some memory from another constant. We encounter mutable - // pointers to such memory since we do not always track immutability through - // these "global" pointers. Allowing them is harmless; the point of these checks - // during interning is to justify why we intern the *new* allocations immutably, - // so we can completely ignore existing allocations. We also don't need to add - // this to the todo list, since after all it is already interned. - return; - } - // Found a mutable pointer inside a const where inner allocations should be - // immutable. We exclude promoteds from this, since things like `&mut []` and - // `&None::<Cell<i32>>` lead to promotion that can produce mutable pointers. We rely - // on the promotion analysis not screwing up to ensure that it is sound to intern - // promoteds as immutable. - found_bad_mutable_pointer = true; - } - // We always intern with `inner_mutability`, and furthermore we ensured above that if - // that is "immutable", then there are *no* mutable pointers anywhere in the newly - // interned memory -- justifying that we can indeed intern immutably. However this also - // means we can *not* easily intern immutably here if `prov.immutable()` is true and - // `inner_mutability` is `Mut`: there might be other pointers to that allocation, and - // we'd have to somehow check that they are *all* immutable before deciding that this - // allocation can be made immutable. In the future we could consider analyzing all - // pointers before deciding which allocations can be made immutable; but for now we are - // okay with losing some potential for immutability here. This can anyway only affect - // `static mut`. - todo.push((alloc_id, inner_mutability)); - }) - .map_err(|()| { + // We always intern with `inner_mutability`, and furthermore we ensured above that if + // that is "immutable", then there are *no* mutable pointers anywhere in the newly + // interned memory -- justifying that we can indeed intern immutably. However this also + // means we can *not* easily intern immutably here if `prov.immutable()` is true and + // `inner_mutability` is `Mut`: there might be other pointers to that allocation, and + // we'd have to somehow check that they are *all* immutable before deciding that this + // allocation can be made immutable. In the future we could consider analyzing all + // pointers before deciding which allocations can be made immutable; but for now we are + // okay with losing some potential for immutability here. This can anyway only affect + // `static mut`. + todo.extend(intern_shallow(ecx, alloc_id, inner_mutability).map_err(|()| { ecx.tcx.dcx().emit_err(DanglingPtrInFinal { span: ecx.tcx.span, kind: intern_kind }) - })?; + })?); } if found_bad_mutable_pointer { return Err(ecx @@ -220,13 +223,13 @@ pub fn intern_const_alloc_for_constprop< return Ok(()); } // Move allocation to `tcx`. - intern_shallow(ecx, alloc_id, Mutability::Not, |_ecx, _| { + for _ in intern_shallow(ecx, alloc_id, Mutability::Not).map_err(|()| err_ub!(DeadLocal))? { // We are not doing recursive interning, so we don't currently support provenance. // (If this assertion ever triggers, we should just implement a // proper recursive interning loop -- or just call `intern_const_alloc_recursive`. panic!("`intern_const_alloc_for_constprop` called on allocation with nested provenance") - }) - .map_err(|()| err_ub!(DeadLocal).into()) + } + Ok(()) } impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>> @@ -247,15 +250,14 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>> let dest = self.allocate(layout, MemoryKind::Stack)?; f(self, &dest.clone().into())?; let alloc_id = dest.ptr().provenance.unwrap().alloc_id(); // this was just allocated, it must have provenance - intern_shallow(self, alloc_id, Mutability::Not, |ecx, prov| { + for prov in intern_shallow(self, alloc_id, Mutability::Not).unwrap() { // We are not doing recursive interning, so we don't currently support provenance. // (If this assertion ever triggers, we should just implement a // proper recursive interning loop -- or just call `intern_const_alloc_recursive`. - if !ecx.tcx.try_get_global_alloc(prov.alloc_id()).is_some() { + if !self.tcx.try_get_global_alloc(prov.alloc_id()).is_some() { panic!("`intern_with_temp_alloc` with nested allocations"); } - }) - .unwrap(); + } Ok(alloc_id) } } diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index d48329b6c69..f0f1008aba8 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -246,13 +246,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); } let val = match null_op { - mir::NullOp::SizeOf => layout.size.bytes(), - mir::NullOp::AlignOf => layout.align.abi.bytes(), + mir::NullOp::SizeOf => { + let val = layout.size.bytes(); + Scalar::from_target_usize(val, self) + } + mir::NullOp::AlignOf => { + let val = layout.align.abi.bytes(); + Scalar::from_target_usize(val, self) + } mir::NullOp::OffsetOf(fields) => { - layout.offset_of_subfield(self, fields.iter()).bytes() + let val = layout.offset_of_subfield(self, fields.iter()).bytes(); + Scalar::from_target_usize(val, self) + } + mir::NullOp::DebugAssertions => { + // The checks hidden behind this are always better done by the interpreter + // itself, because it knows the runtime state better. + Scalar::from_bool(false) } }; - self.write_scalar(Scalar::from_target_usize(val, self), &dest)?; + self.write_scalar(val, &dest)?; } ShallowInitBox(ref operand, _) => { diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 85a2e4778d2..ff20fc5092c 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -377,12 +377,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // to fields, which can yield non-normalized types. So we need to provide a // normalization function. let normalize = |ty| self.tcx.normalize_erasing_regions(self.param_env, ty); - let (meta, only_if_sized) = ty.ptr_metadata_ty(*self.tcx, normalize); - assert!( - !only_if_sized, - "there should be no more 'maybe has that metadata' types during interpretation" - ); - meta + ty.ptr_metadata_ty(*self.tcx, normalize) }; return Ok(meta_ty(caller) == meta_ty(callee)); } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 811c2c3c208..90cde81c018 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -993,10 +993,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Complain about any other kind of error -- those are bad because we'd like to // report them in a way that shows *where* in the value the issue lies. Err(err) => { - bug!( - "Unexpected Undefined Behavior error during validation: {}", - self.format_error(err) - ); + bug!("Unexpected error during validation: {}", self.format_error(err)); } } } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 946a49982aa..839cfd8d85a 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -5,9 +5,9 @@ Rust MIR: a lowered representation of Rust. */ #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] #![feature(rustdoc_internals)] #![doc(rust_logo)] -#![deny(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(decl_macro)] diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 89c65d92325..ee3f349c6b8 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -20,7 +20,7 @@ use std::mem; use std::ops::{ControlFlow, Deref}; use super::ops::{self, NonConstOp, Status}; -use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop, NeedsNonConstDrop}; +use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop}; use super::resolver::FlowSensitiveAnalysis; use super::{ConstCx, Qualif}; use crate::const_eval::is_unstable_const_fn; @@ -149,37 +149,10 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { let return_loc = ccx.body.terminator_loc(return_block); - let custom_eq = match ccx.const_kind() { - // We don't care whether a `const fn` returns a value that is not structurally - // matchable. Functions calls are opaque and always use type-based qualification, so - // this value should never be used. - hir::ConstContext::ConstFn => true, - - // If we know that all values of the return type are structurally matchable, there's no - // need to run dataflow. - // Opaque types do not participate in const generics or pattern matching, so we can safely count them out. - _ if ccx.body.return_ty().has_opaque_types() - || !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) => - { - false - } - - hir::ConstContext::Const { .. } | hir::ConstContext::Static(_) => { - let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx) - .into_engine(ccx.tcx, ccx.body) - .iterate_to_fixpoint() - .into_results_cursor(ccx.body); - - cursor.seek_after_primary_effect(return_loc); - cursor.get().contains(RETURN_PLACE) - } - }; - ConstQualifs { needs_drop: self.needs_drop(ccx, RETURN_PLACE, return_loc), needs_non_const_drop: self.needs_non_const_drop(ccx, RETURN_PLACE, return_loc), has_mut_interior: self.has_mut_interior(ccx, RETURN_PLACE, return_loc), - custom_eq, tainted_by_errors, } } @@ -571,7 +544,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::Cast(_, _, _) => {} - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) => {} + Rvalue::NullaryOp( + NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::DebugAssertions, + _, + ) => {} Rvalue::ShallowInitBox(_, _) => {} Rvalue::UnaryOp(_, operand) => { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 1efa52df581..67fef208079 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -10,7 +10,7 @@ use rustc_middle::mir::*; use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty}; use rustc_trait_selection::traits::{ - self, ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, + ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, }; use super::ConstCx; @@ -24,7 +24,6 @@ pub fn in_any_value_of_ty<'tcx>( has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty), needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty), needs_non_const_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty), - custom_eq: CustomEq::in_any_value_of_ty(cx, ty), tainted_by_errors, } } @@ -213,35 +212,6 @@ impl Qualif for NeedsNonConstDrop { } } -/// A constant that cannot be used as part of a pattern in a `match` expression. -pub struct CustomEq; - -impl Qualif for CustomEq { - const ANALYSIS_NAME: &'static str = "flow_custom_eq"; - - fn in_qualifs(qualifs: &ConstQualifs) -> bool { - qualifs.custom_eq - } - - fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { - // If *any* component of a composite data type does not implement `Structural{Partial,}Eq`, - // we know that at least some values of that type are not structural-match. I say "some" - // because that component may be part of an enum variant (e.g., - // `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be - // structural-match (`Option::None`). - traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some() - } - - fn in_adt_inherently<'tcx>( - cx: &ConstCx<'_, 'tcx>, - def: AdtDef<'tcx>, - args: GenericArgsRef<'tcx>, - ) -> bool { - let ty = Ty::new_adt(cx.tcx, def, args); - !ty.is_structural_eq_shallow(cx.tcx) - } -} - // FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return. /// Returns `true` if this `Rvalue` contains qualif `Q`. diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index c4542aaa7b2..5ce6a71c4bd 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -60,6 +60,8 @@ impl<'tcx> MirPass<'tcx> for Validator { ty::Closure(..) => Abi::RustCall, ty::CoroutineClosure(..) => Abi::RustCall, ty::Coroutine(..) => Abi::Rust, + // No need to do MIR validation on error bodies + ty::Error(_) => return, _ => { span_bug!(body.span, "unexpected body ty: {:?} phase {:?}", body_ty, mir_phase) } @@ -1139,7 +1141,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { Rvalue::Repeat(_, _) | Rvalue::ThreadLocalRef(_) | Rvalue::AddressOf(_, _) - | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) + | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::DebugAssertions, _) | Rvalue::Discriminant(_) => {} } self.super_rvalue(rvalue, location); diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 08aa68ca54a..0635d8552ae 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -11,7 +11,7 @@ either = "1.0" elsa = "=1.7.1" ena = "0.14.2" indexmap = { version = "2.0.0" } -jobserver_crate = { version = "0.1.27", package = "jobserver" } +jobserver_crate = { version = "0.1.28", package = "jobserver" } libc = "0.2" measureme = "11" rustc-hash = "1.1.0" diff --git a/compiler/rustc_data_structures/src/jobserver.rs b/compiler/rustc_data_structures/src/jobserver.rs index 412e33aaa65..89088bc5c1b 100644 --- a/compiler/rustc_data_structures/src/jobserver.rs +++ b/compiler/rustc_data_structures/src/jobserver.rs @@ -23,7 +23,10 @@ static GLOBAL_CLIENT: LazyLock<Result<Client, String>> = LazyLock::new(|| { if matches!( error.kind(), - FromEnvErrorKind::NoEnvVar | FromEnvErrorKind::NoJobserver | FromEnvErrorKind::Unsupported + FromEnvErrorKind::NoEnvVar + | FromEnvErrorKind::NoJobserver + | FromEnvErrorKind::NegativeFd + | FromEnvErrorKind::Unsupported ) { return Ok(default_client()); } diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index a71d012db2d..2b799d6f5d3 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -11,8 +11,6 @@ #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] #![cfg_attr(not(parallel_compiler), feature(cell_leak))] -#![deny(rustc::diagnostic_outside_of_impl)] -#![deny(rustc::untranslatable_diagnostic)] #![deny(unsafe_op_in_unsafe_fn)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 5903c43ae98..60f11b1bdd4 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -12,8 +12,6 @@ #![feature(let_chains)] #![feature(panic_update_hook)] #![feature(result_flattening)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; @@ -24,7 +22,9 @@ use rustc_data_structures::profiling::{ get_resident_set_size, print_time_passes_entry, TimePassesFormat, }; use rustc_errors::registry::Registry; -use rustc_errors::{markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, PResult}; +use rustc_errors::{ + markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, FatalError, PResult, +}; use rustc_feature::find_gated_cfg; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; @@ -1231,11 +1231,10 @@ fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> { /// The compiler currently unwinds with a special sentinel value to abort /// compilation on fatal errors. This function catches that sentinel and turns /// the panic into a `Result` instead. -pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuaranteed> { +pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, FatalError> { catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| { if value.is::<rustc_errors::FatalErrorMarker>() { - #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() + FatalError } else { panic::resume_unwind(value); } @@ -1245,9 +1244,9 @@ pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuarantee /// Variant of `catch_fatal_errors` for the `interface::Result` return type /// that also computes the exit code. pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 { - match catch_fatal_errors(f).flatten() { - Ok(()) => EXIT_SUCCESS, - Err(_) => EXIT_FAILURE, + match catch_fatal_errors(f) { + Ok(Ok(())) => EXIT_SUCCESS, + _ => EXIT_FAILURE, } } diff --git a/compiler/rustc_error_codes/src/error_codes/E0724.md b/compiler/rustc_error_codes/src/error_codes/E0724.md index 70578acbe0d..bcefd0a7479 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0724.md +++ b/compiler/rustc_error_codes/src/error_codes/E0724.md @@ -1,9 +1,12 @@ +#### Note: this error code is no longer emitted by the compiler. + + `#[ffi_returns_twice]` was used on something other than a foreign function declaration. Erroneous code example: -```compile_fail,E0724 +```compile_fail #![feature(ffi_returns_twice)] #![crate_type = "lib"] @@ -15,7 +18,7 @@ pub fn foo() {} For example, we might correct the previous example by declaring the function inside of an `extern` block. -``` +```compile_fail #![feature(ffi_returns_twice)] extern "C" { diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 5b2766618fc..da688e385aa 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -5,8 +5,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![deny(rustdoc::invalid_codeblock_attributes)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] // This higher-order macro defines the error codes that are in use. It is used // in the `rustc_errors` crate. Removed error codes are listed in the comment diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 8fd7c576479..e174cba7813 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -3,8 +3,6 @@ #![feature(lazy_cell)] #![feature(rustc_attrs)] #![feature(type_alias_impl_trait)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] @@ -378,7 +376,7 @@ impl From<Cow<'static, str>> for DiagnosticMessage { } } -/// A workaround for "good path" ICEs when formatting types in disabled lints. +/// A workaround for good_path_delayed_bug ICEs when formatting types in disabled lints. /// /// Delays formatting until `.into(): DiagnosticMessage` is used. pub struct DelayDm<F>(pub F); diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 949f52ef6b5..37f568f12a7 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -44,15 +44,15 @@ impl Translate for AnnotateSnippetEmitter { impl Emitter for AnnotateSnippetEmitter { /// The entry point for the diagnostics generation - fn emit_diagnostic(&mut self, diag: &Diagnostic) { + fn emit_diagnostic(&mut self, mut diag: Diagnostic) { let fluent_args = to_fluent_args(diag.args()); - let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(diag, &fluent_args); + let mut suggestions = diag.suggestions.unwrap_or(vec![]); + self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &mut primary_span, - &mut children, + &mut diag.span, + &mut diag.children, &diag.level, self.macro_backtrace, ); @@ -62,9 +62,9 @@ impl Emitter for AnnotateSnippetEmitter { &diag.messages, &fluent_args, &diag.code, - &primary_span, - &children, - suggestions, + &diag.span, + &diag.children, + &suggestions, ); } @@ -85,7 +85,11 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String { /// Maps `Diagnostic::Level` to `snippet::AnnotationType` fn annotation_type_for_level(level: Level) -> AnnotationType { match level { - Level::Bug | Level::DelayedBug(_) | Level::Fatal | Level::Error => AnnotationType::Error, + Level::Bug + | Level::Fatal + | Level::Error + | Level::DelayedBug + | Level::GoodPathDelayedBug => AnnotationType::Error, Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning, Level::Note | Level::OnceNote => AnnotationType::Note, Level::Help | Level::OnceHelp => AnnotationType::Help, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 8ad4925cff2..03717a4d654 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,8 +1,7 @@ use crate::snippet::Style; use crate::{ - CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, - ErrCode, Level, MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, - SuggestionStyle, + CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, ErrCode, Level, + MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle, }; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_error_messages::fluent_value_from_str_list_sep_by_and; @@ -78,11 +77,12 @@ where /// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used /// (to optionally perform eager translation). - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage; + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F); } +pub trait SubdiagnosticMessageOp = + Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage; + /// Trait implemented by lint types. This should not be implemented manually. Instead, use /// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic]. #[rustc_diagnostic_item = "DecorateLint"] @@ -235,19 +235,16 @@ impl Diagnostic { pub fn is_error(&self) -> bool { match self.level { - Level::Bug - | Level::DelayedBug(DelayedBugKind::Normal) - | Level::Fatal - | Level::Error - | Level::FailureNote => true, + Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true, - Level::ForceWarning(_) + Level::GoodPathDelayedBug + | Level::ForceWarning(_) | Level::Warning - | Level::DelayedBug(DelayedBugKind::GoodPath) | Level::Note | Level::OnceNote | Level::Help | Level::OnceHelp + | Level::FailureNote | Level::Allow | Level::Expect(_) => false, } @@ -306,11 +303,11 @@ impl Diagnostic { #[track_caller] pub fn downgrade_to_delayed_bug(&mut self) { assert!( - self.is_error(), + matches!(self.level, Level::Error | Level::DelayedBug), "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error", self.level ); - self.level = Level::DelayedBug(DelayedBugKind::Normal); + self.level = Level::DelayedBug; } /// Appends a labeled span to the diagnostic. diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index faff7f0b526..e484bef0e0b 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -99,16 +99,20 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { } /// `ErrorGuaranteed::emit_producing_guarantee` uses this. - // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed { let diag = self.take_diag(); - // Only allow a guarantee if the `level` wasn't switched to a - // non-error. The field isn't `pub`, but the whole `Diagnostic` can be - // overwritten with a new one, thanks to `DerefMut`. + // The only error levels that produce `ErrorGuaranteed` are + // `Error` and `DelayedBug`. But `DelayedBug` should never occur here + // because delayed bugs have their level changed to `Bug` when they are + // actually printed, so they produce an ICE. + // + // (Also, even though `level` isn't `pub`, the whole `Diagnostic` could + // be overwritten with a new one thanks to `DerefMut`. So this assert + // protects against that, too.) assert!( - diag.is_error(), - "emitted non-error ({:?}) diagnostic from `DiagnosticBuilder<ErrorGuaranteed>`", + matches!(diag.level, Level::Error | Level::DelayedBug), + "invalid diagnostic level ({:?})", diag.level, ); diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 15effd3cbec..e936ebc7185 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -2,7 +2,7 @@ use crate::diagnostic::DiagnosticLocation; use crate::{fluent_generated as fluent, AddToDiagnostic}; use crate::{ DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, ErrCode, IntoDiagnostic, - IntoDiagnosticArg, Level, + IntoDiagnosticArg, Level, SubdiagnosticMessageOp, }; use rustc_ast as ast; use rustc_ast_pretty::pprust; @@ -299,7 +299,7 @@ pub struct SingleLabelManySpans { pub label: &'static str, } impl AddToDiagnostic for SingleLabelManySpans { - fn add_to_diagnostic_with<F>(self, diag: &mut crate::Diagnostic, _: F) { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut crate::Diagnostic, _: F) { diag.span_labels(self.spans, self.label); } } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 4be5ed923e5..b9e92dbb31c 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -193,7 +193,7 @@ pub type DynEmitter = dyn Emitter + DynSend; /// Emitter trait for emitting errors. pub trait Emitter: Translate { /// Emit a structured diagnostic. - fn emit_diagnostic(&mut self, diag: &Diagnostic); + fn emit_diagnostic(&mut self, diag: Diagnostic); /// Emit a notification that an artifact has been output. /// Currently only supported for the JSON format. @@ -230,17 +230,17 @@ pub trait Emitter: Translate { /// /// * If the current `Diagnostic` has only one visible `CodeSuggestion`, /// we format the `help` suggestion depending on the content of the - /// substitutions. In that case, we return the modified span only. + /// substitutions. In that case, we modify the span and clear the + /// suggestions. /// /// * If the current `Diagnostic` has multiple suggestions, - /// we return the original `primary_span` and the original suggestions. - fn primary_span_formatted<'a>( + /// we leave `primary_span` and the suggestions untouched. + fn primary_span_formatted( &mut self, - diag: &'a Diagnostic, + primary_span: &mut MultiSpan, + suggestions: &mut Vec<CodeSuggestion>, fluent_args: &FluentArgs<'_>, - ) -> (MultiSpan, &'a [CodeSuggestion]) { - let mut primary_span = diag.span.clone(); - let suggestions = diag.suggestions.as_deref().unwrap_or(&[]); + ) { if let Some((sugg, rest)) = suggestions.split_first() { let msg = self.translate_message(&sugg.msg, fluent_args).map_err(Report::new).unwrap(); if rest.is_empty() && @@ -287,16 +287,15 @@ pub trait Emitter: Translate { primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg); // We return only the modified primary_span - (primary_span, &[]) + suggestions.clear(); } else { // if there are multiple suggestions, print them all in full // to be consistent. We could try to figure out if we can // make one (or the first one) inline, but that would give // undue importance to a semi-random suggestion - (primary_span, suggestions) } } else { - (primary_span, suggestions) + // do nothing } } @@ -518,16 +517,15 @@ impl Emitter for HumanEmitter { self.sm.as_ref() } - fn emit_diagnostic(&mut self, diag: &Diagnostic) { + fn emit_diagnostic(&mut self, mut diag: Diagnostic) { let fluent_args = to_fluent_args(diag.args()); - let mut children = diag.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(diag, &fluent_args); - debug!("emit_diagnostic: suggestions={:?}", suggestions); + let mut suggestions = diag.suggestions.unwrap_or(vec![]); + self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( - &mut primary_span, - &mut children, + &mut diag.span, + &mut diag.children, &diag.level, self.macro_backtrace, ); @@ -537,9 +535,9 @@ impl Emitter for HumanEmitter { &diag.messages, &fluent_args, &diag.code, - &primary_span, - &children, - suggestions, + &diag.span, + &diag.children, + &suggestions, self.track_diagnostics.then_some(&diag.emitted_at), ); } @@ -576,9 +574,8 @@ impl Emitter for SilentEmitter { None } - fn emit_diagnostic(&mut self, diag: &Diagnostic) { + fn emit_diagnostic(&mut self, mut diag: Diagnostic) { if diag.level == Level::Fatal { - let mut diag = diag.clone(); diag.note(self.fatal_note.clone()); self.fatal_dcx.emit_diagnostic(diag); } @@ -2116,6 +2113,7 @@ impl HumanEmitter { } if !self.short_message { for child in children { + assert!(child.level.can_be_top_or_sub().1); let span = &child.span; if let Err(err) = self.emit_messages_default_inner( span, diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 6f922998279..470e3d52452 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -176,7 +176,7 @@ impl Translate for JsonEmitter { } impl Emitter for JsonEmitter { - fn emit_diagnostic(&mut self, diag: &crate::Diagnostic) { + fn emit_diagnostic(&mut self, diag: crate::Diagnostic) { let data = Diagnostic::from_errors_diagnostic(diag, self); let result = self.emit(EmitTyped::Diagnostic(data)); if let Err(e) = result { @@ -201,7 +201,7 @@ impl Emitter for JsonEmitter { } FutureBreakageItem { diagnostic: EmitTyped::Diagnostic(Diagnostic::from_errors_diagnostic( - &diag, self, + diag, self, )), } }) @@ -340,7 +340,7 @@ struct UnusedExterns<'a, 'b, 'c> { } impl Diagnostic { - fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic { + fn from_errors_diagnostic(diag: crate::Diagnostic, je: &JsonEmitter) -> Diagnostic { let args = to_fluent_args(diag.args()); let sugg = diag.suggestions.iter().flatten().map(|sugg| { let translated_message = @@ -382,6 +382,28 @@ impl Diagnostic { Ok(()) } } + + let translated_message = je.translate_messages(&diag.messages, &args); + + let code = if let Some(code) = diag.code { + Some(DiagnosticCode { + code: code.to_string(), + explanation: je.registry.as_ref().unwrap().try_find_description(code).ok(), + }) + } else if let Some(IsLint { name, .. }) = &diag.is_lint { + Some(DiagnosticCode { code: name.to_string(), explanation: None }) + } else { + None + }; + let level = diag.level.to_str(); + let spans = DiagnosticSpan::from_multispan(&diag.span, &args, je); + let children = diag + .children + .iter() + .map(|c| Diagnostic::from_sub_diagnostic(c, &args, je)) + .chain(sugg) + .collect(); + let buf = BufWriter::default(); let output = buf.clone(); je.json_rendered @@ -398,30 +420,12 @@ impl Diagnostic { let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); let output = String::from_utf8(output).unwrap(); - let translated_message = je.translate_messages(&diag.messages, &args); - - let code = if let Some(code) = diag.code { - Some(DiagnosticCode { - code: code.to_string(), - explanation: je.registry.as_ref().unwrap().try_find_description(code).ok(), - }) - } else if let Some(IsLint { name, .. }) = &diag.is_lint { - Some(DiagnosticCode { code: name.to_string(), explanation: None }) - } else { - None - }; - Diagnostic { message: translated_message.to_string(), code, - level: diag.level.to_str(), - spans: DiagnosticSpan::from_multispan(&diag.span, &args, je), - children: diag - .children - .iter() - .map(|c| Diagnostic::from_sub_diagnostic(c, &args, je)) - .chain(sugg) - .collect(), + level, + spans, + children, rendered: Some(output), } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 9ec636dcc9c..7216fa8f5e4 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -5,6 +5,8 @@ // tidy-alphabetical-start #![allow(incomplete_features)] #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] @@ -19,6 +21,7 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![feature(trait_alias)] #![feature(try_blocks)] #![feature(yeet_expr)] // tidy-alphabetical-end @@ -35,6 +38,7 @@ pub use codes::*; pub use diagnostic::{ AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgName, DiagnosticArgValue, DiagnosticStyledString, IntoDiagnosticArg, StringPart, SubDiagnostic, + SubdiagnosticMessageOp, }; pub use diagnostic_builder::{ BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort, IntoDiagnostic, @@ -429,6 +433,10 @@ struct DiagCtxtInner { /// The number of non-lint errors that have been emitted, including duplicates. err_count: usize, + /// The number of stashed errors. Unlike the other counts, this can go up + /// and down, so it doesn't guarantee anything. + stashed_err_count: usize, + /// The error count shown to the user at the end. deduplicated_err_count: usize, /// The warning count shown to the user at the end. @@ -439,7 +447,7 @@ struct DiagCtxtInner { has_printed: bool, emitter: Box<DynEmitter>, - span_delayed_bugs: Vec<DelayedDiagnostic>, + delayed_bugs: Vec<DelayedDiagnostic>, good_path_delayed_bugs: Vec<DelayedDiagnostic>, /// This flag indicates that an expected diagnostic was emitted and suppressed. /// This is used for the `good_path_delayed_bugs` check. @@ -523,8 +531,7 @@ fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) { pub static TRACK_DIAGNOSTIC: AtomicRef<fn(Diagnostic, &mut dyn FnMut(Diagnostic))> = AtomicRef::new(&(default_track_diagnostic as _)); -#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] -pub enum DelayedBugKind { +enum DelayedBugKind { Normal, GoodPath, } @@ -557,11 +564,6 @@ impl Drop for DiagCtxtInner { self.flush_delayed(DelayedBugKind::Normal) } - // FIXME(eddyb) this explains what `good_path_delayed_bugs` are! - // They're `span_delayed_bugs` but for "require some diagnostic happened" - // instead of "require some error happened". Sadly that isn't ideal, as - // lints can be `#[allow]`'d, potentially leading to this triggering. - // Also, "good path" should be replaced with a better naming. if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() { self.flush_delayed(DelayedBugKind::GoodPath); } @@ -604,11 +606,12 @@ impl DiagCtxt { flags: DiagCtxtFlags { can_emit_warnings: true, ..Default::default() }, lint_err_count: 0, err_count: 0, + stashed_err_count: 0, deduplicated_err_count: 0, deduplicated_warn_count: 0, has_printed: false, emitter, - span_delayed_bugs: Vec::new(), + delayed_bugs: Vec::new(), good_path_delayed_bugs: Vec::new(), suppressed_expected_diag: false, taught_diagnostics: Default::default(), @@ -660,12 +663,13 @@ impl DiagCtxt { let mut inner = self.inner.borrow_mut(); inner.lint_err_count = 0; inner.err_count = 0; + inner.stashed_err_count = 0; inner.deduplicated_err_count = 0; inner.deduplicated_warn_count = 0; inner.has_printed = false; // actually free the underlying memory (which `clear` would not do) - inner.span_delayed_bugs = Default::default(); + inner.delayed_bugs = Default::default(); inner.good_path_delayed_bugs = Default::default(); inner.taught_diagnostics = Default::default(); inner.emitted_diagnostic_codes = Default::default(); @@ -681,10 +685,8 @@ impl DiagCtxt { let key = (span.with_parent(None), key); if diag.is_error() { - if diag.is_lint.is_some() { - inner.lint_err_count += 1; - } else { - inner.err_count += 1; + if diag.is_lint.is_none() { + inner.stashed_err_count += 1; } } @@ -700,10 +702,8 @@ impl DiagCtxt { let key = (span.with_parent(None), key); let diag = inner.stashed_diagnostics.remove(&key)?; if diag.is_error() { - if diag.is_lint.is_some() { - inner.lint_err_count -= 1; - } else { - inner.err_count -= 1; + if diag.is_lint.is_none() { + inner.stashed_err_count -= 1; } } Some(DiagnosticBuilder::new_diagnostic(self, diag)) @@ -714,7 +714,7 @@ impl DiagCtxt { } /// Emit all stashed diagnostics. - pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> { + pub fn emit_stashed_diagnostics(&self) { self.inner.borrow_mut().emit_stashed_diagnostics() } @@ -851,6 +851,7 @@ impl DiagCtxt { self.struct_span_warn(span, msg).emit() } + #[track_caller] pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! { self.struct_span_bug(span, msg).emit() } @@ -866,8 +867,7 @@ impl DiagCtxt { /// directly). #[track_caller] pub fn delayed_bug(&self, msg: impl Into<DiagnosticMessage>) -> ErrorGuaranteed { - DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg) - .emit() + DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).emit() } /// Like `delayed_bug`, but takes an additional span. @@ -880,15 +880,12 @@ impl DiagCtxt { sp: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, ) -> ErrorGuaranteed { - DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg) - .with_span(sp) - .emit() + DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).with_span(sp).emit() } - // FIXME(eddyb) note the comment inside `impl Drop for DiagCtxtInner`, that's - // where the explanation of what "good path" is (also, it should be renamed). + /// Ensures that a diagnostic is printed. See `Level::GoodPathDelayedBug`. pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) { - DiagnosticBuilder::<()>::new(self, DelayedBug(DelayedBugKind::GoodPath), msg).emit() + DiagnosticBuilder::<()>::new(self, GoodPathDelayedBug, msg).emit() } #[track_caller] @@ -932,40 +929,52 @@ impl DiagCtxt { self.struct_bug(msg).emit() } - /// This excludes lint errors and delayed bugs. + /// This excludes lint errors, delayed bugs, and stashed errors. #[inline] pub fn err_count(&self) -> usize { self.inner.borrow().err_count } - /// This excludes lint errors and delayed bugs. + /// This excludes normal errors, lint errors and delayed bugs. Unless + /// absolutely necessary, avoid using this. It's dubious because stashed + /// errors can later be cancelled, so the presence of a stashed error at + /// some point of time doesn't guarantee anything -- there are no + /// `ErrorGuaranteed`s here. + pub fn stashed_err_count(&self) -> usize { + self.inner.borrow().stashed_err_count + } + + /// This excludes lint errors, delayed bugs, and stashed errors. pub fn has_errors(&self) -> Option<ErrorGuaranteed> { self.inner.borrow().has_errors().then(|| { + // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() + ErrorGuaranteed::unchecked_error_guaranteed() }) } - /// This excludes delayed bugs. Unless absolutely necessary, prefer - /// `has_errors` to this method. + /// This excludes delayed bugs and stashed errors. Unless absolutely + /// necessary, prefer `has_errors` to this method. pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> { let inner = self.inner.borrow(); let result = inner.has_errors() || inner.lint_err_count > 0; result.then(|| { + // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() + ErrorGuaranteed::unchecked_error_guaranteed() }) } - /// Unless absolutely necessary, prefer `has_errors` or - /// `has_errors_or_lint_errors` to this method. + /// This excludes stashed errors. Unless absolutely necessary, prefer + /// `has_errors` or `has_errors_or_lint_errors` to this method. pub fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option<ErrorGuaranteed> { let inner = self.inner.borrow(); let result = - inner.has_errors() || inner.lint_err_count > 0 || !inner.span_delayed_bugs.is_empty(); + inner.has_errors() || inner.lint_err_count > 0 || !inner.delayed_bugs.is_empty(); result.then(|| { + // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() + ErrorGuaranteed::unchecked_error_guaranteed() }) } @@ -991,9 +1000,13 @@ impl DiagCtxt { match (errors.len(), warnings.len()) { (0, 0) => return, - (0, _) => inner - .emitter - .emit_diagnostic(&Diagnostic::new(Warning, DiagnosticMessage::Str(warnings))), + (0, _) => { + // Use `inner.emitter` directly, otherwise the warning might not be emitted, e.g. + // with a configuration like `--cap-lints allow --force-warn bare_trait_objects`. + inner + .emitter + .emit_diagnostic(Diagnostic::new(Warning, DiagnosticMessage::Str(warnings))); + } (_, 0) => { inner.emit_diagnostic(Diagnostic::new(Fatal, errors)); } @@ -1057,7 +1070,7 @@ impl DiagCtxt { } pub fn force_print_diagnostic(&self, db: Diagnostic) { - self.inner.borrow_mut().emitter.emit_diagnostic(&db); + self.inner.borrow_mut().emitter.emit_diagnostic(db); } pub fn emit_diagnostic(&self, diagnostic: Diagnostic) -> Option<ErrorGuaranteed> { @@ -1222,16 +1235,13 @@ impl DiagCtxt { // `DiagCtxtInner::foo`. impl DiagCtxtInner { /// Emit all stashed diagnostics. - fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> { + fn emit_stashed_diagnostics(&mut self) { let has_errors = self.has_errors(); - let mut reported = None; for (_, diag) in std::mem::take(&mut self.stashed_diagnostics).into_iter() { // Decrement the count tracking the stash; emitting will increment it. if diag.is_error() { - if diag.is_lint.is_some() { - self.lint_err_count -= 1; - } else { - self.err_count -= 1; + if diag.is_lint.is_none() { + self.stashed_err_count -= 1; } } else { // Unless they're forced, don't flush stashed warnings when @@ -1241,50 +1251,25 @@ impl DiagCtxtInner { continue; } } - let reported_this = self.emit_diagnostic(diag); - reported = reported.or(reported_this); + self.emit_diagnostic(diag); } - reported } + // Return value is only `Some` if the level is `Error` or `DelayedBug`. fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option<ErrorGuaranteed> { - // The `LintExpectationId` can be stable or unstable depending on when it was created. - // Diagnostics created before the definition of `HirId`s are unstable and can not yet - // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by - // a stable one by the `LintLevelsBuilder`. - if let Some(LintExpectationId::Unstable { .. }) = diagnostic.level.get_expectation_id() { - self.unstable_expect_diagnostics.push(diagnostic); - return None; - } + assert!(diagnostic.level.can_be_top_or_sub().0); - // FIXME(eddyb) this should check for `has_errors` and stop pushing - // once *any* errors were emitted (and truncate `span_delayed_bugs` - // when an error is first emitted, also), but maybe there's a case - // in which that's not sound? otherwise this is really inefficient. - match diagnostic.level { - DelayedBug(_) if self.flags.eagerly_emit_delayed_bugs => { - diagnostic.level = Error; - } - DelayedBug(DelayedBugKind::Normal) => { - let backtrace = std::backtrace::Backtrace::capture(); - self.span_delayed_bugs - .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); - #[allow(deprecated)] - return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); - } - DelayedBug(DelayedBugKind::GoodPath) => { - let backtrace = std::backtrace::Backtrace::capture(); - self.good_path_delayed_bugs - .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); + if let Some(expectation_id) = diagnostic.level.get_expectation_id() { + // The `LintExpectationId` can be stable or unstable depending on when it was created. + // Diagnostics created before the definition of `HirId`s are unstable and can not yet + // be stored. Instead, they are buffered until the `LintExpectationId` is replaced by + // a stable one by the `LintLevelsBuilder`. + if let LintExpectationId::Unstable { .. } = expectation_id { + self.unstable_expect_diagnostics.push(diagnostic); return None; } - _ => {} - } - - // This must come after the possible promotion of `DelayedBug` to - // `Error` above. - if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() { - diagnostic.level = Bug; + self.suppressed_expected_diag = true; + self.fulfilled_expectations.insert(expectation_id.normalize()); } if diagnostic.has_future_breakage() { @@ -1295,21 +1280,45 @@ impl DiagCtxtInner { self.future_breakage_diagnostics.push(diagnostic.clone()); } - if let Some(expectation_id) = diagnostic.level.get_expectation_id() { - self.suppressed_expected_diag = true; - self.fulfilled_expectations.insert(expectation_id.normalize()); + if matches!(diagnostic.level, DelayedBug | GoodPathDelayedBug) + && self.flags.eagerly_emit_delayed_bugs + { + diagnostic.level = Error; } - if diagnostic.level == Warning && !self.flags.can_emit_warnings { - if diagnostic.has_future_breakage() { + match diagnostic.level { + // This must come after the possible promotion of `DelayedBug`/`GoodPathDelayedBug` to + // `Error` above. + Fatal | Error if self.treat_next_err_as_bug() => { + diagnostic.level = Bug; + } + DelayedBug => { + // FIXME(eddyb) this should check for `has_errors` and stop pushing + // once *any* errors were emitted (and truncate `delayed_bugs` + // when an error is first emitted, also), but maybe there's a case + // in which that's not sound? otherwise this is really inefficient. + let backtrace = std::backtrace::Backtrace::capture(); + self.delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); + #[allow(deprecated)] + return Some(ErrorGuaranteed::unchecked_error_guaranteed()); + } + GoodPathDelayedBug => { + let backtrace = std::backtrace::Backtrace::capture(); + self.good_path_delayed_bugs + .push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); + return None; + } + Warning if !self.flags.can_emit_warnings => { + if diagnostic.has_future_breakage() { + (*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {}); + } + return None; + } + Allow | Expect(_) => { (*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {}); + return None; } - return None; - } - - if matches!(diagnostic.level, Expect(_) | Allow) { - (*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {}); - return None; + _ => {} } let mut guaranteed = None; @@ -1325,11 +1334,16 @@ impl DiagCtxtInner { !self.emitted_diagnostics.insert(diagnostic_hash) }; + let level = diagnostic.level; + let is_error = diagnostic.is_error(); + let is_lint = diagnostic.is_lint.is_some(); + // Only emit the diagnostic if we've been asked to deduplicate or // haven't already emitted an equivalent diagnostic. if !(self.flags.deduplicate_diagnostics && already_emitted) { debug!(?diagnostic); debug!(?self.emitted_diagnostics); + let already_emitted_sub = |sub: &mut SubDiagnostic| { debug!(?sub); if sub.level != OnceNote && sub.level != OnceHelp { @@ -1341,7 +1355,6 @@ impl DiagCtxtInner { debug!(?diagnostic_hash); !self.emitted_diagnostics.insert(diagnostic_hash) }; - diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {}); if already_emitted { diagnostic.note( @@ -1349,26 +1362,28 @@ impl DiagCtxtInner { ); } - self.emitter.emit_diagnostic(&diagnostic); - if diagnostic.is_error() { + if is_error { self.deduplicated_err_count += 1; } else if matches!(diagnostic.level, ForceWarning(_) | Warning) { self.deduplicated_warn_count += 1; } self.has_printed = true; + + self.emitter.emit_diagnostic(diagnostic); } - if diagnostic.is_error() { - if diagnostic.is_lint.is_some() { + + if is_error { + if is_lint { self.lint_err_count += 1; } else { self.err_count += 1; } self.panic_if_treat_err_as_bug(); + } - #[allow(deprecated)] - { - guaranteed = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); - } + #[allow(deprecated)] + if level == Level::Error { + guaranteed = Some(ErrorGuaranteed::unchecked_error_guaranteed()); } }); @@ -1397,12 +1412,12 @@ impl DiagCtxtInner { fn flush_delayed(&mut self, kind: DelayedBugKind) { let (bugs, note1) = match kind { DelayedBugKind::Normal => ( - std::mem::take(&mut self.span_delayed_bugs), - "no errors encountered even though `span_delayed_bug` issued", + std::mem::take(&mut self.delayed_bugs), + "no errors encountered even though delayed bugs were created", ), DelayedBugKind::GoodPath => ( std::mem::take(&mut self.good_path_delayed_bugs), - "no warnings or errors encountered even though `good_path_delayed_bugs` issued", + "no warnings or errors encountered even though good path delayed bugs were created", ), }; let note2 = "those delayed bugs will now be shown as internal compiler errors"; @@ -1441,8 +1456,8 @@ impl DiagCtxtInner { let mut bug = if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner }; - // "Undelay" the `DelayedBug`s (into plain `Bug`s). - if !matches!(bug.level, DelayedBug(_)) { + // "Undelay" the delayed bugs (into plain `Bug`s). + if !matches!(bug.level, DelayedBug | GoodPathDelayedBug) { // NOTE(eddyb) not panicking here because we're already producing // an ICE, and the more information the merrier. bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel { @@ -1508,35 +1523,59 @@ impl DelayedDiagnostic { } } +/// Level is_error EmissionGuarantee Top-level Sub Used in lints? +/// ----- -------- ----------------- --------- --- -------------- +/// Bug yes BugAbort yes - - +/// Fatal yes FatalAbort/FatalError(*) yes - - +/// Error yes ErrorGuaranteed yes - yes +/// DelayedBug yes ErrorGuaranteed yes - - +/// GoodPathDelayedBug - () yes - - +/// ForceWarning - () yes - lint-only +/// Warning - () yes yes yes +/// Note - () rare yes - +/// OnceNote - () - yes lint-only +/// Help - () rare yes - +/// OnceHelp - () - yes lint-only +/// FailureNote - () rare - - +/// Allow - () yes - lint-only +/// Expect - () yes - lint-only +/// +/// (*) `FatalAbort` normally, `FatalError` in the non-aborting "almost fatal" case that is +/// occasionally used. +/// #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] pub enum Level { /// For bugs in the compiler. Manifests as an ICE (internal compiler error) panic. - /// - /// Its `EmissionGuarantee` is `BugAbort`. Bug, - /// This is a strange one: lets you register an error without emitting it. If compilation ends - /// without any other errors occurring, this will be emitted as a bug. Otherwise, it will be - /// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths - /// that should only be reached when compiling erroneous code. - /// - /// Its `EmissionGuarantee` is `ErrorGuaranteed` for `Normal` delayed bugs, and `()` for - /// `GoodPath` delayed bugs. - DelayedBug(DelayedBugKind), - /// An error that causes an immediate abort. Used for things like configuration errors, /// internal overflows, some file operation errors. - /// - /// Its `EmissionGuarantee` is `FatalAbort`, except in the non-aborting "almost fatal" case - /// that is occasionally used, where it is `FatalError`. Fatal, /// An error in the code being compiled, which prevents compilation from finishing. This is the /// most common case. - /// - /// Its `EmissionGuarantee` is `ErrorGuaranteed`. Error, + /// This is a strange one: lets you register an error without emitting it. If compilation ends + /// without any other errors occurring, this will be emitted as a bug. Otherwise, it will be + /// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths + /// that should only be reached when compiling erroneous code. + DelayedBug, + + /// Like `DelayedBug`, but weaker: lets you register an error without emitting it. If + /// compilation ends without any other diagnostics being emitted (and without an expected lint + /// being suppressed), this will be emitted as a bug. Otherwise, it will be silently dropped. + /// I.e. "expect other diagnostics are emitted (or suppressed)" semantics. Useful on code paths + /// that should only be reached when emitting diagnostics, e.g. for expensive one-time + /// diagnostic formatting operations. + /// + /// FIXME(nnethercote) good path delayed bugs are semantically strange: if printed they produce + /// an ICE, but they don't satisfy `is_error` and they don't guarantee an error is emitted. + /// Plus there's the extra complication with expected (suppressed) lints. They have limited + /// use, and are used in very few places, and "good path" isn't a good name. It would be good + /// to remove them. + GoodPathDelayedBug, + /// A `force-warn` lint warning about the code being compiled. Does not prevent compilation /// from finishing. /// @@ -1545,45 +1584,28 @@ pub enum Level { ForceWarning(Option<LintExpectationId>), /// A warning about the code being compiled. Does not prevent compilation from finishing. - /// - /// Its `EmissionGuarantee` is `()`. Warning, - /// A message giving additional context. Rare, because notes are more commonly attached to other - /// diagnostics such as errors. - /// - /// Its `EmissionGuarantee` is `()`. + /// A message giving additional context. Note, - /// A note that is only emitted once. Rare, mostly used in circumstances relating to lints. - /// - /// Its `EmissionGuarantee` is `()`. + /// A note that is only emitted once. OnceNote, - /// A message suggesting how to fix something. Rare, because help messages are more commonly - /// attached to other diagnostics such as errors. - /// - /// Its `EmissionGuarantee` is `()`. + /// A message suggesting how to fix something. Help, - /// A help that is only emitted once. Rare. - /// - /// Its `EmissionGuarantee` is `()`. + /// A help that is only emitted once. OnceHelp, - /// Similar to `Note`, but used in cases where compilation has failed. Rare. - /// - /// Its `EmissionGuarantee` is `()`. + /// Similar to `Note`, but used in cases where compilation has failed. When printed for human + /// consumption, it doesn't have any kind of `note:` label. FailureNote, /// Only used for lints. - /// - /// Its `EmissionGuarantee` is `()`. Allow, /// Only used for lints. - /// - /// Its `EmissionGuarantee` is `()`. Expect(LintExpectationId), } @@ -1597,7 +1619,7 @@ impl Level { fn color(self) -> ColorSpec { let mut spec = ColorSpec::new(); match self { - Bug | DelayedBug(_) | Fatal | Error => { + Bug | Fatal | Error | DelayedBug | GoodPathDelayedBug => { spec.set_fg(Some(Color::Red)).set_intense(true); } ForceWarning(_) | Warning => { @@ -1617,7 +1639,7 @@ impl Level { pub fn to_str(self) -> &'static str { match self { - Bug | DelayedBug(_) => "error: internal compiler error", + Bug | DelayedBug | GoodPathDelayedBug => "error: internal compiler error", Fatal | Error => "error", ForceWarning(_) | Warning => "warning", Note | OnceNote => "note", @@ -1637,6 +1659,19 @@ impl Level { _ => None, } } + + // Can this level be used in a top-level diagnostic message and/or a + // subdiagnostic message? + fn can_be_top_or_sub(&self) -> (bool, bool) { + match self { + Bug | DelayedBug | Fatal | Error | GoodPathDelayedBug | ForceWarning(_) + | FailureNote | Allow | Expect(_) => (true, false), + + Warning | Note | Help => (true, true), + + OnceNote | OnceHelp => (false, true), + } + } } // FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite. diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 657e19277a7..cfeb31fc4c8 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] - use crate::base::ast::NestedMetaItem; use crate::errors; use crate::expand::{self, AstFragment, Invocation}; diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index 2cf6a8df7c5..4da86d77dc8 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -10,7 +10,7 @@ #![feature(proc_macro_internals)] #![feature(proc_macro_span)] #![feature(try_blocks)] -#![deny(rustc::untranslatable_diagnostic)] +#![allow(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 1155366db85..18f6ae35054 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -77,7 +77,7 @@ declare_features! ( /// Allows empty structs and enum variants with braces. (accepted, braced_empty_structs, "1.8.0", Some(29720)), /// Allows `c"foo"` literals. - (accepted, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723)), + (accepted, c_str_literals, "1.77.0", Some(105723)), /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`. (accepted, cfg_attr_multi, "1.33.0", Some(54881)), /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 68b6f69854d..019cc1c847e 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -440,9 +440,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ experimental!(optimize), ), - gated!( - ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice) - ), gated!(ffi_pure, Normal, template!(Word), WarnFollowing, experimental!(ffi_pure)), gated!(ffi_const, Normal, template!(Word), WarnFollowing, experimental!(ffi_const)), gated!( diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index cd1d9b13daa..f1c8f2e2dde 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -15,8 +15,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![feature(lazy_cell)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] mod accepted; mod builtin_attrs; diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 85fcf6a9994..008c59e1be3 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -33,7 +33,7 @@ declare_features! ( // ------------------------------------------------------------------------- /// Allows using the `amdgpu-kernel` ABI. - (removed, abi_amdgpu_kernel, "CURRENT_RUSTC_VERSION", Some(51575), None), + (removed, abi_amdgpu_kernel, "1.77.0", Some(51575), None), (removed, advanced_slice_patterns, "1.0.0", Some(62254), Some("merged into `#![feature(slice_patterns)]`")), (removed, allocator, "1.0.0", None, None), @@ -97,6 +97,9 @@ declare_features! ( /// Allows `#[doc(include = "some-file")]`. (removed, external_doc, "1.54.0", Some(44732), Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")), + /// Allows using `#[ffi_returns_twice]` on foreign functions. + (removed, ffi_returns_twice, "CURRENT_RUSTC_VERSION", Some(58314), + Some("being investigated by the ffi-unwind project group")), /// Allows generators to be cloned. (removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")), /// Allows defining generators. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index d00621d8254..42fc24c937b 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -356,7 +356,7 @@ declare_features! ( /// Allows `#[track_caller]` on async functions. (unstable, async_fn_track_caller, "1.73.0", Some(110011)), /// Allows `for await` loops. - (unstable, async_for_loop, "CURRENT_RUSTC_VERSION", Some(118898)), + (unstable, async_for_loop, "1.77.0", Some(118898)), /// Allows builtin # foo() syntax (unstable, builtin_syntax, "1.71.0", Some(110680)), /// Treat `extern "C"` function as nounwind. @@ -370,7 +370,7 @@ declare_features! ( /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used. (unstable, cfg_sanitize, "1.41.0", Some(39699)), /// Allows `cfg(sanitizer_cfi_generalize_pointers)` and `cfg(sanitizer_cfi_normalize_integers)`. - (unstable, cfg_sanitizer_cfi, "CURRENT_RUSTC_VERSION", Some(89653)), + (unstable, cfg_sanitizer_cfi, "1.77.0", Some(89653)), /// Allows `cfg(target_abi = "...")`. (unstable, cfg_target_abi, "1.55.0", Some(80970)), /// Allows `cfg(target(abi = "..."))`. @@ -465,8 +465,6 @@ declare_features! ( (unstable, ffi_const, "1.45.0", Some(58328)), /// Allows the use of `#[ffi_pure]` on foreign functions. (unstable, ffi_pure, "1.45.0", Some(58329)), - /// Allows using `#[ffi_returns_twice]` on foreign functions. - (unstable, ffi_returns_twice, "1.34.0", Some(58314)), /// Allows using `#[repr(align(...))]` on function items (unstable, fn_align, "1.53.0", Some(82232)), /// Support delegating implementation of functions to other already implemented functions. @@ -516,7 +514,7 @@ declare_features! ( (unstable, marker_trait_attr, "1.30.0", Some(29864)), /// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are /// unambiguously sound. - (incomplete, min_exhaustive_patterns, "CURRENT_RUSTC_VERSION", Some(119612)), + (incomplete, min_exhaustive_patterns, "1.77.0", Some(119612)), /// A minimal, sound subset of specialization intended to be used by the /// standard library until the soundness issues with specialization /// are fixed. @@ -552,7 +550,7 @@ declare_features! ( /// Allows using enums in offset_of! (unstable, offset_of_enum, "1.75.0", Some(120141)), /// Allows using multiple nested field accesses in offset_of! - (unstable, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)), + (unstable, offset_of_nested, "1.77.0", Some(120140)), /// Allows using `#[optimize(X)]`. (unstable, optimize_attribute, "1.34.0", Some(54882)), /// Allows macro attributes on expressions, statements and non-inline modules. diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs index fc65d1eb8c4..e3784409af8 100644 --- a/compiler/rustc_fluent_macro/src/lib.rs +++ b/compiler/rustc_fluent_macro/src/lib.rs @@ -4,8 +4,6 @@ #![feature(rustdoc_internals)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_span)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(rustc::default_hash_types)] use proc_macro::TokenStream; diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs index 81d63338145..3359fef8c1c 100644 --- a/compiler/rustc_fs_util/src/lib.rs +++ b/compiler/rustc_fs_util/src/lib.rs @@ -1,6 +1,4 @@ #![feature(absolute_path)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use std::ffi::CString; use std::fs; diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index eba3215d931..43bee5c4be0 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -276,8 +276,6 @@ #![feature(rustdoc_internals)] #![doc(rust_logo)] #![allow(internal_features)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use LabelText::*; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ff50086ff8f..abf7a695fd2 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -163,10 +163,6 @@ impl Lifetime { (LifetimeSuggestionPosition::Normal, self.ident.span) } } - - pub fn is_static(&self) -> bool { - self.res == LifetimeName::Static - } } /// A `Path` is essentially Rust's notion of a name; for instance, @@ -835,7 +831,7 @@ pub struct OwnerNodes<'tcx> { // The zeroth node's parent should never be accessed: the owner's parent is computed by the // hir_owner_parent query. It is set to `ItemLocalId::INVALID` to force an ICE if accidentally // used. - pub nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>, + pub nodes: IndexVec<ItemLocalId, ParentedNode<'tcx>>, /// Content of local bodies. pub bodies: SortedMap<ItemLocalId, &'tcx Body<'tcx>>, } @@ -843,9 +839,8 @@ pub struct OwnerNodes<'tcx> { impl<'tcx> OwnerNodes<'tcx> { pub fn node(&self) -> OwnerNode<'tcx> { use rustc_index::Idx; - let node = self.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; - let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. - node + // Indexing must ensure it is an OwnerNode. + self.nodes[ItemLocalId::new(0)].node.as_owner().unwrap() } } @@ -860,9 +855,7 @@ impl fmt::Debug for OwnerNodes<'_> { .nodes .iter_enumerated() .map(|(id, parented_node)| { - let parented_node = parented_node.as_ref().map(|node| node.parent); - - debug_fn(move |f| write!(f, "({id:?}, {parented_node:?})")) + debug_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent)) }) .collect::<Vec<_>>(), ) @@ -3351,13 +3344,15 @@ impl<'hir> OwnerNode<'hir> { } } - pub fn span(&self) -> Span { + // Span by reference to pass to `Node::Err`. + #[allow(rustc::pass_by_value)] + pub fn span(&self) -> &'hir Span { match self { OwnerNode::Item(Item { span, .. }) | OwnerNode::ForeignItem(ForeignItem { span, .. }) | OwnerNode::ImplItem(ImplItem { span, .. }) - | OwnerNode::TraitItem(TraitItem { span, .. }) => *span, - OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span, + | OwnerNode::TraitItem(TraitItem { span, .. }) => span, + OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => inner_span, } } @@ -3486,17 +3481,19 @@ pub enum Node<'hir> { Arm(&'hir Arm<'hir>), Block(&'hir Block<'hir>), Local(&'hir Local<'hir>), - /// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants /// with synthesized constructors. Ctor(&'hir VariantData<'hir>), - Lifetime(&'hir Lifetime), GenericParam(&'hir GenericParam<'hir>), - Crate(&'hir Mod<'hir>), - Infer(&'hir InferArg), + WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>), + // FIXME: Merge into `Node::Infer`. + ArrayLenInfer(&'hir InferArg), + // Span by reference to minimize `Node`'s size + #[allow(rustc::pass_by_value)] + Err(&'hir Span), } impl<'hir> Node<'hir> { @@ -3541,7 +3538,10 @@ impl<'hir> Node<'hir> { | Node::Crate(..) | Node::Ty(..) | Node::TraitRef(..) - | Node::Infer(..) => None, + | Node::Infer(..) + | Node::WhereBoundPredicate(..) + | Node::ArrayLenInfer(..) + | Node::Err(..) => None, } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 27c834d848f..52e1109ff92 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -108,8 +108,8 @@ impl<'a> FnKind<'a> { /// An abstract representation of the HIR `rustc_middle::hir::map::Map`. pub trait Map<'hir> { - /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. - fn find(&self, hir_id: HirId) -> Option<Node<'hir>>; + /// Retrieves the `Node` corresponding to `id`. + fn hir_node(&self, hir_id: HirId) -> Node<'hir>; fn body(&self, id: BodyId) -> &'hir Body<'hir>; fn item(&self, id: ItemId) -> &'hir Item<'hir>; fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>; @@ -119,7 +119,7 @@ pub trait Map<'hir> { // Used when no map is actually available, forcing manual implementation of nested visitors. impl<'hir> Map<'hir> for ! { - fn find(&self, _: HirId) -> Option<Node<'hir>> { + fn hir_node(&self, _: HirId) -> Node<'hir> { *self; } fn body(&self, _: BodyId) -> &'hir Body<'hir> { @@ -669,6 +669,7 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<' pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) { match len { + // FIXME: Use `visit_infer` here. ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id), ArrayLen::Body(c) => visitor.visit_anon_const(c), } diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 6c64d802e68..aff946ac580 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -9,8 +9,6 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![feature(variant_count)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 54d0fb6ffab..d6f604c180b 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -33,10 +33,6 @@ hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the as hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes -hir_analysis_async_trait_impl_should_be_async = - method `{$method_name}` should be async because the method from the trait is async - .trait_item_label = required because the trait method is async - hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit while auto-dereferencing `{$ty}` .label = deref recursion limit reached .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`) @@ -210,6 +206,9 @@ hir_analysis_manual_implementation = .label = manual implementations of `{$trait_name}` are experimental .help = add `#![feature(unboxed_closures)]` to the crate attributes to enable +hir_analysis_method_should_return_future = method should be `async` or return a future, but it is synchronous + .note = this method is `async` so it expects a future to be returned + hir_analysis_missing_one_of_trait_item = not all trait items implemented, missing one of: `{$missing_items_msg}` .label = missing one of `{$missing_items_msg}` in implementation .note = required because of this annotation diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index e37119e7d4d..1ae267d1a40 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -243,9 +243,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { speculative: bool, dup_bindings: &mut FxHashMap<DefId, Span>, path_span: Span, - constness: ty::BoundConstness, only_self_bounds: OnlySelfBounds, - polarity: ty::ImplPolarity, ) -> Result<(), ErrorGuaranteed> { // Given something like `U: SomeTrait<T = X>`, we want to produce a // predicate like `<U as SomeTrait>::T = X`. This is somewhat diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index e67a44d96ad..3c64b102bae 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -14,6 +14,7 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::traits::FulfillmentError; +use rustc_middle::query::Key; use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; @@ -859,6 +860,56 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.set_tainted_by_errors(err.emit()); } + + /// On ambiguous associated type, look for an associated function whose name matches the + /// extended path and, if found, emit an E0223 error with a structured suggestion. + /// e.g. for `String::from::utf8`, suggest `String::from_utf8` (#109195) + pub(crate) fn maybe_report_similar_assoc_fn( + &self, + span: Span, + qself_ty: Ty<'tcx>, + qself: &hir::Ty<'_>, + ) -> Result<(), ErrorGuaranteed> { + let tcx = self.tcx(); + if let Some((_, node)) = tcx.hir().parent_iter(qself.hir_id).skip(1).next() + && let hir::Node::Expr(hir::Expr { + kind: + hir::ExprKind::Path(hir::QPath::TypeRelative( + hir::Ty { + kind: + hir::TyKind::Path(hir::QPath::TypeRelative( + _, + hir::PathSegment { ident: ident2, .. }, + )), + .. + }, + hir::PathSegment { ident: ident3, .. }, + )), + .. + }) = node + && let Some(ty_def_id) = qself_ty.ty_def_id() + && let Ok([inherent_impl]) = tcx.inherent_impls(ty_def_id) + && let name = format!("{ident2}_{ident3}") + && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx + .associated_items(inherent_impl) + .filter_by_name_unhygienic(Symbol::intern(&name)) + .next() + { + let reported = + struct_span_code_err!(tcx.dcx(), span, E0223, "ambiguous associated type") + .with_span_suggestion_verbose( + ident2.span.to(ident3.span), + format!("there is an associated function with a similar name: `{name}`"), + name, + Applicability::MaybeIncorrect, + ) + .emit(); + self.set_tainted_by_errors(reported); + Err(reported) + } else { + Ok(()) + } + } } /// Emits an error regarding forbidden type binding associations diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 30b10446afc..aa826c1f268 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -16,7 +16,7 @@ use rustc_middle::ty::{ self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, TyCtxt, }; use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS; -use rustc_span::{symbol::kw, Span}; +use rustc_span::symbol::kw; use smallvec::SmallVec; /// Report an error that a generic argument did not match the generic parameter that was @@ -404,7 +404,6 @@ pub fn create_args_for_parent_generic_args<'tcx: 'a, 'a>( /// Used specifically for function calls. pub fn check_generic_arg_count_for_call( tcx: TyCtxt<'_>, - span: Span, def_id: DefId, generics: &ty::Generics, seg: &hir::PathSegment<'_>, @@ -418,17 +417,7 @@ pub fn check_generic_arg_count_for_call( }; let has_self = generics.parent.is_none() && generics.has_self; - check_generic_arg_count( - tcx, - span, - def_id, - seg, - generics, - gen_args, - gen_pos, - has_self, - seg.infer_args, - ) + check_generic_arg_count(tcx, def_id, seg, generics, gen_args, gen_pos, has_self, seg.infer_args) } /// Checks that the correct number of generic arguments have been provided. @@ -436,7 +425,6 @@ pub fn check_generic_arg_count_for_call( #[instrument(skip(tcx, gen_pos), level = "debug")] pub(crate) fn check_generic_arg_count( tcx: TyCtxt<'_>, - span: Span, def_id: DefId, seg: &hir::PathSegment<'_>, gen_params: &ty::Generics, diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 89f39897ea8..d438d3e7c60 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -12,7 +12,7 @@ use crate::astconv::errors::prohibit_assoc_ty_binding; use crate::astconv::generics::{check_generic_arg_count, create_args_for_parent_generic_args}; use crate::bounds::Bounds; use crate::collect::HirPlaceholderCollector; -use crate::errors::{AmbiguousLifetimeBound, TypeofReservedKeywordUsed}; +use crate::errors::AmbiguousLifetimeBound; use crate::middle::resolve_bound_vars as rbv; use crate::require_c_abi_if_c_variadic; use rustc_ast::TraitObjectSyntax; @@ -25,13 +25,13 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{walk_generics, Visitor as _}; -use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; +use rustc_hir::{GenericArg, GenericArgs}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::{ - self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, IsSuggestable, ParamEnv, Ty, - TyCtxt, TypeVisitableExt, + self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt, + TypeVisitableExt, }; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; @@ -379,7 +379,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut arg_count = check_generic_arg_count( tcx, - span, def_id, seg, generics, @@ -773,9 +772,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { speculative, &mut dup_bindings, binding.span, - constness, only_self_bounds, - polarity, ); // Okay to ignore `Err` because of `ErrorGuaranteed` (see above). } @@ -1373,6 +1370,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) .emit() // Already reported in an earlier stage. } else { + self.maybe_report_similar_assoc_fn(span, qself_ty, qself)?; + let traits: Vec<_> = self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident); @@ -2491,7 +2490,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let opaque_ty = tcx.hir().item(item_id); match opaque_ty.kind { - hir::ItemKind::OpaqueTy(&hir::OpaqueTy { origin, .. }) => { + hir::ItemKind::OpaqueTy(&hir::OpaqueTy { .. }) => { let local_def_id = item_id.owner_id.def_id; // If this is an RPITIT and we are using the new RPITIT lowering scheme, we // generate the def_id of an associated type for the trait and return as @@ -2501,7 +2500,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { local_def_id.to_def_id() }; - self.impl_trait_ty_to_ty(def_id, lifetimes, origin, in_trait) + self.impl_trait_ty_to_ty(def_id, lifetimes, in_trait) } ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i), } @@ -2537,21 +2536,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Ty::new_array_with_const_len(tcx, self.ast_ty_to_ty(ty), length) } - hir::TyKind::Typeof(e) => { - let ty_erased = tcx.type_of(e.def_id).instantiate_identity(); - let ty = tcx.fold_regions(ty_erased, |r, _| { - if r.is_erased() { tcx.lifetimes.re_static } else { r } - }); - let span = ast_ty.span; - let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) { - (ty, Some((span, Applicability::MachineApplicable))) - } else { - (ty, None) - }; - tcx.dcx().emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg }); - - ty - } + hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(), hir::TyKind::Infer => { // Infer also appears as the type of arguments or return // values in an ExprKind::Closure, or as @@ -2571,7 +2556,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, def_id: DefId, lifetimes: &[hir::GenericArg<'_>], - origin: OpaqueTyOrigin, in_trait: bool, ) -> Ty<'tcx> { debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 379c1154e5f..6edd68f1bae 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1,5 +1,5 @@ use super::potentially_plural_count; -use crate::errors::LifetimesOrBoundsMismatchOnTrait; +use crate::errors::{LifetimesOrBoundsMismatchOnTrait, MethodShouldReturnFuture}; use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed}; @@ -10,7 +10,7 @@ use rustc_hir::{GenericParamKind, ImplItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::util; +use rustc_infer::traits::{util, FulfillmentError}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::util::ExplicitSelf; @@ -74,7 +74,6 @@ fn check_method_is_structurally_compatible<'tcx>( compare_generic_param_kinds(tcx, impl_m, trait_m, delay)?; compare_number_of_method_arguments(tcx, impl_m, trait_m, delay)?; compare_synthetic_generics(tcx, impl_m, trait_m, delay)?; - compare_asyncness(tcx, impl_m, trait_m, delay)?; check_region_bounds_on_impl_item(tcx, impl_m, trait_m, delay)?; Ok(()) } @@ -414,36 +413,6 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> { } } -fn compare_asyncness<'tcx>( - tcx: TyCtxt<'tcx>, - impl_m: ty::AssocItem, - trait_m: ty::AssocItem, - delay: bool, -) -> Result<(), ErrorGuaranteed> { - if tcx.asyncness(trait_m.def_id).is_async() { - match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() { - ty::Alias(ty::Opaque, ..) => { - // allow both `async fn foo()` and `fn foo() -> impl Future` - } - ty::Error(_) => { - // We don't know if it's ok, but at least it's already an error. - } - _ => { - return Err(tcx - .dcx() - .create_err(crate::errors::AsyncTraitImplShouldBeAsync { - span: tcx.def_span(impl_m.def_id), - method_name: trait_m.name, - trait_item_span: tcx.hir().span_if_local(trait_m.def_id), - }) - .emit_unless(delay)); - } - }; - } - - Ok(()) -} - /// Given a method def-id in an impl, compare the method signature of the impl /// against the trait that it's implementing. In doing so, infer the hidden types /// that this method's signature provides to satisfy each return-position `impl Trait` @@ -695,8 +664,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( // RPITs. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - let reported = infcx.err_ctxt().report_fulfillment_errors(errors); - return Err(reported); + if let Err(guar) = try_report_async_mismatch(tcx, infcx, &errors, trait_m, impl_m, impl_sig) + { + return Err(guar); + } + + let guar = infcx.err_ctxt().report_fulfillment_errors(errors); + return Err(guar); } // Finally, resolve all regions. This catches wily misuses of @@ -1990,6 +1964,10 @@ pub(super) fn check_type_bounds<'tcx>( impl_ty: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + tcx.ensure().coherent_trait(impl_trait_ref.def_id)?; + let param_env = tcx.param_env(impl_ty.def_id); debug!(?param_env); @@ -2248,3 +2226,47 @@ fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str { ty::AssocKind::Type => "type", } } + +/// Manually check here that `async fn foo()` wasn't matched against `fn foo()`, +/// and extract a better error if so. +fn try_report_async_mismatch<'tcx>( + tcx: TyCtxt<'tcx>, + infcx: &InferCtxt<'tcx>, + errors: &[FulfillmentError<'tcx>], + trait_m: ty::AssocItem, + impl_m: ty::AssocItem, + impl_sig: ty::FnSig<'tcx>, +) -> Result<(), ErrorGuaranteed> { + if !tcx.asyncness(trait_m.def_id).is_async() { + return Ok(()); + } + + let ty::Alias(ty::Projection, ty::AliasTy { def_id: async_future_def_id, .. }) = + *tcx.fn_sig(trait_m.def_id).skip_binder().skip_binder().output().kind() + else { + bug!("expected `async fn` to return an RPITIT"); + }; + + for error in errors { + if let traits::BindingObligation(def_id, _) = *error.root_obligation.cause.code() + && def_id == async_future_def_id + && let Some(proj) = error.root_obligation.predicate.to_opt_poly_projection_pred() + && let Some(proj) = proj.no_bound_vars() + && infcx.can_eq( + error.root_obligation.param_env, + proj.term.ty().unwrap(), + impl_sig.output(), + ) + { + // FIXME: We should suggest making the fn `async`, but extracting + // the right span is a bit difficult. + return Err(tcx.sess.dcx().emit_err(MethodShouldReturnFuture { + span: tcx.def_span(impl_m.def_id), + method_name: trait_m.name, + trait_item_span: tcx.hir().span_if_local(trait_m.def_id), + })); + } + } + + Ok(()) +} diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 649ac6c5aeb..3d803258c8e 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -43,8 +43,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { return None; } let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - match tcx.opt_hir_node(hir_id) { - Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => { + match tcx.hir_node(hir_id) { + Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => { generics.params.is_empty().not().then_some(generics.span) } _ => { @@ -58,8 +58,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { return None; } let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - match tcx.opt_hir_node(hir_id) { - Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => { + match tcx.hir_node(hir_id) { + Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) => { Some(generics.where_clause_span) } _ => { @@ -80,8 +80,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { return None; } let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); - match tcx.opt_hir_node(hir_id) { - Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. })) => { + match tcx.hir_node(hir_id) { + Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. }) => { Some(fn_sig.decl.output.span()) } _ => { @@ -202,7 +202,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { let start_t = tcx.type_of(start_def_id).instantiate_identity(); match start_t.kind() { ty::FnDef(..) => { - if let Some(Node::Item(it)) = tcx.opt_hir_node(start_id) { + if let Node::Item(it) = tcx.hir_node(start_id) { if let hir::ItemKind::Fn(sig, generics, _) = &it.kind { let mut error = false; if !generics.params.is_empty() { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 2d0d6611444..96b0cffc8a3 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -112,7 +112,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir | sym::forget | sym::black_box | sym::variant_count - | sym::ptr_mask => hir::Unsafety::Normal, + | sym::ptr_mask + | sym::debug_assertions => hir::Unsafety::Normal, _ => hir::Unsafety::Unsafe, }; @@ -461,6 +462,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { (0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize) } + sym::debug_assertions => (0, Vec::new(), tcx.types.bool), + other => { tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other }); return; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 885cfbd0fe2..646a84b043c 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1005,6 +1005,11 @@ fn check_associated_item( enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| { let item = tcx.associated_item(item_id); + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + tcx.ensure() + .coherent_trait(tcx.parent(item.trait_item_def_id.unwrap_or(item_id.into())))?; + let self_ty = match item.container { ty::TraitContainer => tcx.types.self_param, ty::ImplContainer => tcx.type_of(item.container_id(tcx)).instantiate_identity(), @@ -1291,6 +1296,9 @@ fn check_impl<'tcx>( // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity(); + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + tcx.ensure().coherent_trait(trait_ref.def_id)?; let trait_ref = wfcx.normalize( ast_trait_ref.path.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 1dabb6feb5e..4860555de20 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -344,11 +344,18 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { kind: hir::ExprKind::Closure(hir::Closure { kind, .. }), .. }) = node { + // See `ClosureArgsParts`, `CoroutineArgsParts`, and `CoroutineClosureArgsParts` + // for info on the usage of each of these fields. let dummy_args = match kind { ClosureKind::Closure => &["<closure_kind>", "<closure_signature>", "<upvars>"][..], - ClosureKind::Coroutine(_) => { - &["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..] - } + ClosureKind::Coroutine(_) => &[ + "<coroutine_kind>", + "<resume_ty>", + "<yield_ty>", + "<return_ty>", + "<witness>", + "<upvars>", + ][..], ClosureKind::CoroutineClosure(_) => &[ "<closure_kind>", "<closure_signature_parts>", diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 5cdcc1bb860..20a7663f864 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -9,6 +9,8 @@ use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, Ty use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; +use crate::errors::TypeofReservedKeywordUsed; + use super::bad_placeholder; use super::ItemCtxt; pub use opaque::test_opaque_hidden_types; @@ -39,8 +41,18 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { { return tcx.types.usize; } - Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => { - return tcx.typeck(def_id).node_type(e.hir_id); + Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), span, .. }) if e.hir_id == hir_id => { + let ty = tcx.typeck(def_id).node_type(e.hir_id); + let ty = tcx.fold_regions(ty, |r, _| { + if r.is_erased() { ty::Region::new_error_misc(tcx) } else { r } + }); + let (ty, opt_sugg) = if let Some(ty) = ty.make_suggestable(tcx, false) { + (ty, Some((span, Applicability::MachineApplicable))) + } else { + (ty, None) + }; + tcx.dcx().emit_err(TypeofReservedKeywordUsed { span, ty, opt_sugg }); + return ty; } Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. }) | Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. }) @@ -509,6 +521,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty x => bug!("unexpected non-type Node::GenericParam: {:?}", x), }, + Node::ArrayLenInfer(_) => tcx.types.usize, + x => { bug!("unexpected sort of node in type_of(): {:?}", x); } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 4eba31e327f..bec53693d6c 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -167,17 +167,6 @@ pub struct LifetimesOrBoundsMismatchOnTrait { } #[derive(Diagnostic)] -#[diag(hir_analysis_async_trait_impl_should_be_async)] -pub struct AsyncTraitImplShouldBeAsync { - #[primary_span] - // #[label] - pub span: Span, - #[label(hir_analysis_trait_item_label)] - pub trait_item_span: Option<Span>, - pub method_name: Symbol, -} - -#[derive(Diagnostic)] #[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)] pub struct DropImplOnWrongItem { #[primary_span] @@ -1513,6 +1502,16 @@ pub struct NotSupportedDelegation<'a> { } #[derive(Diagnostic)] +#[diag(hir_analysis_method_should_return_future)] +pub struct MethodShouldReturnFuture { + #[primary_span] + pub span: Span, + pub method_name: Symbol, + #[note] + pub trait_item_span: Option<Span>, +} + +#[derive(Diagnostic)] #[diag(hir_analysis_unused_generic_parameter)] pub(crate) struct UnusedGenericParameter { #[primary_span] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 454cb97ac14..883d416ecd1 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -55,7 +55,9 @@ This API is completely unstable and subject to change. */ +#![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::potential_query_instability)] +#![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] @@ -169,11 +171,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { tcx.sess.time("coherence_checking", || { // Check impls constrain their parameters - let mut res = + let res = tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module)); for &trait_def_id in tcx.all_local_trait_impls(()).keys() { - res = res.and(tcx.ensure().coherent_trait(trait_def_id)); + let _ = tcx.ensure().coherent_trait(trait_def_id); } // these queries are executed for side-effects (error reporting): res.and(tcx.ensure().crate_inherent_impls(())) @@ -209,7 +211,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { tcx.ensure().check_unused_traits(()); - if let Some(reported) = tcx.dcx().has_errors() { Err(reported) } else { Ok(()) } + Ok(()) } /// A quasi-deprecated helper used in rustdoc and clippy to get diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index 501915d2e7e..3b1ee2975fd 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -771,8 +771,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { ); if let Some(parent_node) = self.tcx.hir().opt_parent_id(self.path_segment.hir_id) - && let Some(parent_node) = self.tcx.opt_hir_node(parent_node) - && let hir::Node::Expr(expr) = parent_node + && let hir::Node::Expr(expr) = self.tcx.hir_node(parent_node) { match &expr.kind { hir::ExprKind::Path(qpath) => self diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 9d0c5cb0f32..b90fa03a3dc 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2,8 +2,6 @@ //! the definitions in this file have equivalents in `rustc_ast_pretty`. #![recursion_limit = "256"] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] use rustc_ast as ast; use rustc_ast::util::parser::{self, AssocOp, Fixity}; @@ -23,7 +21,7 @@ use std::cell::Cell; use std::vec; pub fn id_to_string(map: &dyn rustc_hir::intravisit::Map<'_>, hir_id: hir::HirId) -> String { - to_string(&map, |s| s.print_node(map.find(hir_id).unwrap())) + to_string(&map, |s| s.print_node(map.hir_node(hir_id))) } pub enum AnnNode<'a> { @@ -117,6 +115,13 @@ impl<'a> State<'a> { Node::Ctor(..) => panic!("cannot print isolated Ctor"), Node::Local(a) => self.print_local_decl(a), Node::Crate(..) => panic!("cannot print Crate"), + Node::WhereBoundPredicate(pred) => { + self.print_formal_generic_params(pred.bound_generic_params); + self.print_type(pred.bounded_ty); + self.print_bounds(":", pred.bounds); + } + Node::ArrayLenInfer(_) => self.word("_"), + Node::Err(_) => self.word("/*ERROR*/"), } } } diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index cf1f232229d..7ea0469dedd 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -1,7 +1,11 @@ use crate::coercion::{AsCoercionSite, CoerceMany}; use crate::{Diverges, Expectation, FnCtxt, Needs}; -use rustc_errors::Diagnostic; -use rustc_hir::{self as hir, ExprKind}; +use rustc_errors::{Applicability, Diagnostic}; +use rustc_hir::{ + self as hir, + def::{CtorOf, DefKind, Res}, + ExprKind, PatKind, +}; use rustc_hir_pretty::ty_to_string; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; @@ -273,7 +277,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Returns `true` if there was an error forcing the coercion to the `()` type. pub(super) fn if_fallback_coercion<T>( &self, - span: Span, + if_span: Span, + cond_expr: &'tcx hir::Expr<'tcx>, then_expr: &'tcx hir::Expr<'tcx>, coercion: &mut CoerceMany<'tcx, '_, T>, ) -> bool @@ -283,29 +288,106 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If this `if` expr is the parent's function return expr, // the cause of the type coercion is the return type, point at it. (#25228) let hir_id = self.tcx.hir().parent_id(self.tcx.hir().parent_id(then_expr.hir_id)); - let ret_reason = self.maybe_get_coercion_reason(hir_id, span); - let cause = self.cause(span, ObligationCauseCode::IfExpressionWithNoElse); + let ret_reason = self.maybe_get_coercion_reason(hir_id, if_span); + let cause = self.cause(if_span, ObligationCauseCode::IfExpressionWithNoElse); let mut error = false; coercion.coerce_forced_unit( self, &cause, - |err| { - if let Some((span, msg)) = &ret_reason { - err.span_label(*span, msg.clone()); - } else if let ExprKind::Block(block, _) = &then_expr.kind - && let Some(expr) = &block.expr - { - err.span_label(expr.span, "found here"); - } - err.note("`if` expressions without `else` evaluate to `()`"); - err.help("consider adding an `else` block that evaluates to the expected type"); - error = true; - }, + |err| self.explain_if_expr(err, ret_reason, if_span, cond_expr, then_expr, &mut error), false, ); error } + /// Explain why `if` expressions without `else` evaluate to `()` and detect likely irrefutable + /// `if let PAT = EXPR {}` expressions that could be turned into `let PAT = EXPR;`. + fn explain_if_expr( + &self, + err: &mut Diagnostic, + ret_reason: Option<(Span, String)>, + if_span: Span, + cond_expr: &'tcx hir::Expr<'tcx>, + then_expr: &'tcx hir::Expr<'tcx>, + error: &mut bool, + ) { + if let Some((if_span, msg)) = ret_reason { + err.span_label(if_span, msg.clone()); + } else if let ExprKind::Block(block, _) = then_expr.kind + && let Some(expr) = block.expr + { + err.span_label(expr.span, "found here"); + } + err.note("`if` expressions without `else` evaluate to `()`"); + err.help("consider adding an `else` block that evaluates to the expected type"); + *error = true; + if let ExprKind::Let(hir::Let { span, pat, init, .. }) = cond_expr.kind + && let ExprKind::Block(block, _) = then_expr.kind + // Refutability checks occur on the MIR, so we approximate it here by checking + // if we have an enum with a single variant or a struct in the pattern. + && let PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..) = pat.kind + && let hir::QPath::Resolved(_, path) = qpath + { + match path.res { + Res::Def(DefKind::Ctor(CtorOf::Struct, _), _) => { + // Structs are always irrefutable. Their fields might not be, but we + // don't check for that here, it's only an approximation. + } + Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) + if self + .tcx + .adt_def(self.tcx.parent(self.tcx.parent(def_id))) + .variants() + .len() + == 1 => + { + // There's only a single variant in the `enum`, so we can suggest the + // irrefutable `let` instead of `if let`. + } + _ => return, + } + + let mut sugg = vec![ + // Remove the `if` + (if_span.until(*span), String::new()), + ]; + match (block.stmts, block.expr) { + ([first, ..], Some(expr)) => { + let padding = self + .tcx + .sess + .source_map() + .indentation_before(first.span) + .unwrap_or_else(|| String::new()); + sugg.extend([ + (init.span.between(first.span), format!(";\n{padding}")), + (expr.span.shrink_to_hi().with_hi(block.span.hi()), String::new()), + ]); + } + ([], Some(expr)) => { + let padding = self + .tcx + .sess + .source_map() + .indentation_before(expr.span) + .unwrap_or_else(|| String::new()); + sugg.extend([ + (init.span.between(expr.span), format!(";\n{padding}")), + (expr.span.shrink_to_hi().with_hi(block.span.hi()), String::new()), + ]); + } + // If there's no value in the body, then the `if` expression would already + // be of type `()`, so checking for those cases is unnecessary. + (_, None) => return, + } + err.multipart_suggestion( + "consider using an irrefutable `let` binding instead", + sugg, + Applicability::MaybeIncorrect, + ); + } + } + pub fn maybe_get_coercion_reason( &self, hir_id: hir::HirId, diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index bed0d80787f..68add9e27c8 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -41,7 +41,7 @@ pub fn check_legal_trait_for_method_call( receiver: Option<Span>, expr_span: Span, trait_id: DefId, -) { +) -> Result<(), ErrorGuaranteed> { if tcx.lang_items().drop_trait() == Some(trait_id) { let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) { errors::ExplicitDestructorCallSugg::Snippet { @@ -51,8 +51,9 @@ pub fn check_legal_trait_for_method_call( } else { errors::ExplicitDestructorCallSugg::Empty(span) }; - tcx.dcx().emit_err(errors::ExplicitDestructorCall { span, sugg }); + return Err(tcx.dcx().emit_err(errors::ExplicitDestructorCall { span, sugg })); } + tcx.coherent_trait(trait_id) } #[derive(Debug)] diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 58823ea30ce..f21de1609cb 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -448,13 +448,35 @@ impl<'a, 'tcx> CastCheck<'tcx> { ); } } - let msg = "an `as` expression can only be used to convert between primitive \ - types or to coerce to a specific trait object"; + + let (msg, note) = if let ty::Adt(adt, _) = self.expr_ty.kind() + && adt.is_enum() + && self.cast_ty.is_numeric() + { + ( + "an `as` expression can be used to convert enum types to numeric \ + types only if the enum type is unit-only or field-less", + Some( + "see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information", + ), + ) + } else { + ( + "an `as` expression can only be used to convert between primitive \ + types or to coerce to a specific trait object", + None, + ) + }; + if label { err.span_label(self.span, msg); } else { err.note(msg); } + + if let Some(note) = note { + err.note(note); + } } else { err.span_label(self.span, "invalid cast"); } diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index ca636ebcade..2beabc0835d 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1715,8 +1715,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { let ret_msg = "return a value for the case when the loop has zero elements to iterate on"; let ret_ty_msg = "otherwise consider changing the return type to account for that possibility"; - if let Some(node) = tcx.opt_hir_node(item.into()) - && let Some(body_id) = node.body_id() + let node = tcx.hir_node(item.into()); + if let Some(body_id) = node.body_id() && let Some(sig) = node.fn_sig() && let hir::ExprKind::Block(block, _) = hir.body(body_id).value.kind && !ty.is_never() diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index b6dfc34d3ac..d8974251de0 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -561,11 +561,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut parent; 'outer: loop { // Climb the HIR tree to see if the current `Expr` is part of a `break;` statement. - let Some( - hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Semi(&ref p), .. }) - | hir::Node::Block(hir::Block { expr: Some(&ref p), .. }) - | hir::Node::Expr(&ref p), - ) = self.tcx.opt_hir_node(parent_id) + let (hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Semi(&ref p), .. }) + | hir::Node::Block(hir::Block { expr: Some(&ref p), .. }) + | hir::Node::Expr(&ref p)) = self.tcx.hir_node(parent_id) else { break; }; @@ -578,20 +576,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut direct = false; loop { // Climb the HIR tree to find the (desugared) `loop` this `break` corresponds to. - let parent = match self.tcx.opt_hir_node(parent_id) { - Some(hir::Node::Expr(&ref parent)) => { + let parent = match self.tcx.hir_node(parent_id) { + hir::Node::Expr(&ref parent) => { parent_id = self.tcx.hir().parent_id(parent.hir_id); parent } - Some(hir::Node::Stmt(hir::Stmt { + hir::Node::Stmt(hir::Stmt { hir_id, kind: hir::StmtKind::Semi(&ref parent) | hir::StmtKind::Expr(&ref parent), .. - })) => { + }) => { parent_id = self.tcx.hir().parent_id(*hir_id); parent } - Some(hir::Node::Block(_)) => { + hir::Node::Block(_) => { parent_id = self.tcx.hir().parent_id(parent_id); parent } @@ -680,17 +678,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error: Option<TypeError<'tcx>>, ) { let parent = self.tcx.hir().parent_id(expr.hir_id); - match (self.tcx.opt_hir_node(parent), error) { - (Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _) + match (self.tcx.hir_node(parent), error) { + (hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. }), _) if init.hir_id == expr.hir_id => { // Point at `let` assignment type. err.span_label(ty.span, "expected due to this"); } ( - Some(hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Assign(lhs, rhs, _), .. - })), + hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }), Some(TypeError::Sorts(ExpectedFound { expected, .. })), ) if rhs.hir_id == expr.hir_id && !expected.is_closure() => { // We ignore closures explicitly because we already point at them elsewhere. @@ -725,7 +721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, hir::Path { res: hir::def::Res::Local(hir_id), .. }, )) => { - if let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(*hir_id) { + if let hir::Node::Pat(pat) = self.tcx.hir_node(*hir_id) { primary_span = pat.span; secondary_span = pat.span; match self.tcx.hir().find_parent(pat.hir_id) { @@ -774,9 +770,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } ( - Some(hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Binary(_, lhs, rhs), .. - })), + hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(_, lhs, rhs), .. }), Some(TypeError::Sorts(ExpectedFound { expected, .. })), ) if rhs.hir_id == expr.hir_id && self.typeck_results.borrow().expr_ty_adjusted_opt(lhs) == Some(expected) => @@ -797,8 +791,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else { return; }; - let Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. })) = - self.tcx.opt_hir_node(parent) + let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) = + self.tcx.hir_node(parent) else { return; }; @@ -1022,13 +1016,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Path { res: hir::def::Res::Local(bind_hir_id), .. }, )) = expr.kind { - let bind = self.tcx.opt_hir_node(*bind_hir_id); - let parent = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*bind_hir_id)); - if let Some(hir::Node::Pat(hir::Pat { - kind: hir::PatKind::Binding(_, _hir_id, _, _), - .. - })) = bind - && let Some(hir::Node::Pat(hir::Pat { default_binding_modes: false, .. })) = parent + let bind = self.tcx.hir_node(*bind_hir_id); + let parent = self.tcx.hir_node(self.tcx.hir().parent_id(*bind_hir_id)); + if let hir::Node::Pat(hir::Pat { + kind: hir::PatKind::Binding(_, _hir_id, _, _), .. + }) = bind + && let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent { return true; } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 70afb042441..10e12d01b1f 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use crate::fluent_generated as fluent; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg, - MultiSpan, SubdiagnosticMessage, + MultiSpan, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; @@ -195,10 +195,7 @@ pub struct TypeMismatchFruTypo { } impl AddToDiagnostic for TypeMismatchFruTypo { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { diag.arg("expr", self.expr.as_deref().unwrap_or("NONE")); // Only explain that `a ..b` is a range if it's split up @@ -373,10 +370,7 @@ pub struct RemoveSemiForCoerce { } impl AddToDiagnostic for RemoveSemiForCoerce { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { let mut multispan: MultiSpan = self.semi.into(); multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr); multispan.push_span_label(self.ret, fluent::hir_typeck_remove_semi_for_coerce_ret); @@ -547,14 +541,8 @@ pub enum CastUnknownPointerSub { From(Span), } -impl rustc_errors::AddToDiagnostic for CastUnknownPointerSub { - fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, f: F) - where - F: Fn( - &mut Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, - { +impl AddToDiagnostic for CastUnknownPointerSub { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) { match self { CastUnknownPointerSub::To(span) => { let msg = f(diag, crate::fluent_generated::hir_typeck_label_to); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 1adde8c21b8..292b85eb97f 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1017,7 +1017,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { then: impl FnOnce(&hir::Expr<'_>), ) { let mut parent = self.tcx.hir().parent_id(original_expr_id); - while let Some(node) = self.tcx.opt_hir_node(parent) { + loop { + let node = self.tcx.hir_node(parent); match node { hir::Node::Expr(hir::Expr { kind: @@ -1118,7 +1119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We won't diverge unless both branches do (or the condition does). self.diverges.set(cond_diverges | then_diverges & else_diverges); } else { - self.if_fallback_coercion(sp, then_expr, &mut coerce); + self.if_fallback_coercion(sp, cond_expr, then_expr, &mut coerce); // If the condition is false we can't diverge. self.diverges.set(cond_diverges); @@ -1471,8 +1472,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let hir::TyKind::Array(_, length) = ty.peel_refs().kind && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length - && let Some(span) = self.tcx.hir().opt_span(hir_id) { + let span = self.tcx.hir().span(hir_id); match self.dcx().steal_diagnostic(span, StashKey::UnderscoreForArrayLengths) { Some(mut err) => { err.span_suggestion( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 60eb40bd8fe..36c3eef82fc 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -521,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// We must not attempt to select obligations after this method has run, or risk query cycle /// ICE. #[instrument(level = "debug", skip(self))] - pub(in super::super) fn resolve_coroutine_interiors(&self, def_id: DefId) { + pub(in super::super) fn resolve_coroutine_interiors(&self) { // Try selecting all obligations that are not blocked on inference variables. // Once we start unifying coroutine witnesses, trying to select obligations on them will // trigger query cycle ICEs, as doing so requires MIR. @@ -1105,13 +1105,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let container_id = assoc_item.container_id(tcx); debug!(?def_id, ?container, ?container_id); match container { - ty::TraitContainer => callee::check_legal_trait_for_method_call( - tcx, - path_span, - None, - span, - container_id, - ), + ty::TraitContainer => { + if let Err(e) = callee::check_legal_trait_for_method_call( + tcx, + path_span, + None, + span, + container_id, + ) { + self.set_tainted_by_errors(e); + } + } ty::ImplContainer => { if segments.len() == 1 { // `<T>::assoc` will end up here, and so @@ -1175,14 +1179,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // parameter internally, but we don't allow users to specify the // parameter's value explicitly, so we have to do some error- // checking here. - let arg_count = check_generic_arg_count_for_call( - tcx, - span, - def_id, - generics, - seg, - IsMethodCall::No, - ); + let arg_count = + check_generic_arg_count_for_call(tcx, def_id, generics, seg, IsMethodCall::No); if let ExplicitLateBound::Yes = arg_count.explicit_late_bound { explicit_late_bound = ExplicitLateBound::Yes; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index d30c7a4fb38..35b3f27d791 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2060,7 +2060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let node = self .tcx .opt_local_def_id_to_hir_id(self.tcx.hir().get_parent_item(call_expr.hir_id)) - .and_then(|hir_id| self.tcx.opt_hir_node(hir_id)); + .map(|hir_id| self.tcx.hir_node(hir_id)); match node { Some(hir::Node::Item(item)) => call_finder.visit_item(item), Some(hir::Node::TraitItem(item)) => call_finder.visit_trait_item(item), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 5395ffda1d1..ed0bdb9bdaa 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -682,8 +682,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // is and we were expecting a Box, ergo Pin<Box<expected>>, we // can suggest Box::pin. let parent = self.tcx.hir().parent_id(expr.hir_id); - let Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) = - self.tcx.opt_hir_node(parent) + let Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. }) = + self.tcx.hir_node(parent) else { return false; }; @@ -908,9 +908,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty::Param(expected_ty_as_param) = expected.kind() else { return }; - let fn_node = self.tcx.opt_hir_node(fn_id); + let fn_node = self.tcx.hir_node(fn_id); - let Some(hir::Node::Item(hir::Item { + let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn( hir::FnSig { @@ -921,7 +921,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _body_id, ), .. - })) = fn_node + }) = fn_node else { return; }; @@ -1053,9 +1053,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let ty = self.normalize(expr.span, ty); if self.can_coerce(found, ty) { - if let Some(node) = self.tcx.opt_hir_node(fn_id) - && let Some(owner_node) = node.as_owner() - && let Some(span) = expr.span.find_ancestor_inside(owner_node.span()) + if let Some(owner_node) = self.tcx.hir_node(fn_id).as_owner() + && let Some(span) = expr.span.find_ancestor_inside(*owner_node.span()) { err.multipart_suggestion( "you might have meant to return this value", @@ -1684,15 +1683,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, hir::Path { segments: [_], res: crate::Res::Local(binding), .. }, )) => { - let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = self.tcx.opt_hir_node(*binding) - else { - return expr; - }; - let Some(parent) = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*hir_id)) else { + let hir::Node::Pat(hir::Pat { hir_id, .. }) = self.tcx.hir_node(*binding) else { return expr; }; - match parent { + match self.tcx.hir_node(self.tcx.hir().parent_id(*hir_id)) { // foo.clone() hir::Node::Local(hir::Local { init: Some(init), .. }) => { self.note_type_is_not_clone_inner_expr(init) @@ -1703,8 +1698,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { kind: hir::PatKind::Tuple(pats, ..), .. }) => { - let Some(hir::Node::Local(hir::Local { init: Some(init), .. })) = - self.tcx.opt_hir_node(self.tcx.hir().parent_id(*pat_hir_id)) + let hir::Node::Local(hir::Local { init: Some(init), .. }) = + self.tcx.hir_node(self.tcx.hir().parent_id(*pat_hir_id)) else { return expr; }; @@ -1736,10 +1731,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr_kind && let hir::Path { segments: [_], res: crate::Res::Local(binding), .. } = call_expr_path - && let Some(hir::Node::Pat(hir::Pat { hir_id, .. })) = - self.tcx.opt_hir_node(*binding) - && let Some(closure) = self.tcx.opt_hir_node(self.tcx.hir().parent_id(*hir_id)) - && let hir::Node::Local(hir::Local { init: Some(init), .. }) = closure + && let hir::Node::Pat(hir::Pat { hir_id, .. }) = self.tcx.hir_node(*binding) + && let hir::Node::Local(hir::Local { init: Some(init), .. }) = + self.tcx.hir_node(self.tcx.hir().parent_id(*hir_id)) && let Expr { kind: hir::ExprKind::Closure(hir::Closure { body: body_id, .. }), .. @@ -1979,20 +1973,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Unroll desugaring, to make sure this works for `for` loops etc. loop { parent = self.tcx.hir().parent_id(id); - if let Some(parent_span) = self.tcx.hir().opt_span(parent) { - if parent_span.find_ancestor_inside(expr.span).is_some() { - // The parent node is part of the same span, so is the result of the - // same expansion/desugaring and not the 'real' parent node. - id = parent; - continue; - } + let parent_span = self.tcx.hir().span(parent); + if parent_span.find_ancestor_inside(expr.span).is_some() { + // The parent node is part of the same span, so is the result of the + // same expansion/desugaring and not the 'real' parent node. + id = parent; + continue; } break; } - if let Some(hir::Node::Block(&hir::Block { - span: block_span, expr: Some(e), .. - })) = self.tcx.opt_hir_node(parent) + if let hir::Node::Block(&hir::Block { span: block_span, expr: Some(e), .. }) = + self.tcx.hir_node(parent) { if e.hir_id == id { if let Some(span) = expr.span.find_ancestor_inside(block_span) { @@ -2220,30 +2212,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let local_parent = self.tcx.hir().parent_id(local_id); - let Some(Node::Param(hir::Param { hir_id: param_hir_id, .. })) = - self.tcx.opt_hir_node(local_parent) + let Node::Param(hir::Param { hir_id: param_hir_id, .. }) = self.tcx.hir_node(local_parent) else { return None; }; let param_parent = self.tcx.hir().parent_id(*param_hir_id); - let Some(Node::Expr(hir::Expr { + let Node::Expr(hir::Expr { hir_id: expr_hir_id, kind: hir::ExprKind::Closure(hir::Closure { fn_decl: closure_fn_decl, .. }), .. - })) = self.tcx.opt_hir_node(param_parent) + }) = self.tcx.hir_node(param_parent) else { return None; }; let expr_parent = self.tcx.hir().parent_id(*expr_hir_id); - let hir = self.tcx.opt_hir_node(expr_parent); + let hir = self.tcx.hir_node(expr_parent); let closure_params_len = closure_fn_decl.inputs.len(); let ( - Some(Node::Expr(hir::Expr { + Node::Expr(hir::Expr { kind: hir::ExprKind::MethodCall(method_path, receiver, ..), .. - })), + }), 1, ) = (hir, closure_params_len) else { @@ -2674,10 +2665,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool { if let hir::ExprKind::If(..) = expr.kind { let parent_id = self.tcx.hir().parent_id(expr.hir_id); - if let Some(Node::Expr(hir::Expr { - kind: hir::ExprKind::If(_, _, Some(else_expr)), - .. - })) = self.tcx.opt_hir_node(parent_id) + if let Node::Expr(hir::Expr { + kind: hir::ExprKind::If(_, _, Some(else_expr)), .. + }) = self.tcx.hir_node(parent_id) { return else_expr.hir_id == expr.hir_id; } @@ -3067,7 +3057,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; }; let parent = self.tcx.hir().parent_id(expr.hir_id); - if let Some(hir::Node::ExprField(_)) = self.tcx.opt_hir_node(parent) { + if let hir::Node::ExprField(_) = self.tcx.hir_node(parent) { // Ignore `Foo { field: a..Default::default() }` return; } @@ -3146,7 +3136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir::def::Res::Local(hir_id) = path.res else { return; }; - let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(hir_id) else { + let hir::Node::Pat(pat) = self.tcx.hir_node(hir_id) else { return; }; let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) = diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index deb3ad2edc7..315dc4330ad 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -1,3 +1,5 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(try_blocks)] @@ -286,7 +288,7 @@ fn typeck_with_fallback<'tcx>( debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations()); // This must be the last thing before `report_ambiguity_errors`. - fcx.resolve_coroutine_interiors(def_id.to_def_id()); + fcx.resolve_coroutine_interiors(); debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations()); diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 1ce0240f7b8..f9297550c57 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -436,7 +436,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { pub(crate) fn cat_rvalue( &self, hir_id: hir::HirId, - span: Span, + // FIXME: remove + _span: Span, expr_ty: Ty<'tcx>, ) -> PlaceWithHirId<'tcx> { PlaceWithHirId::new(hir_id, expr_ty, PlaceBase::Rvalue, Vec::new()) diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 6f18cc51b11..3a44c6c2410 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -356,7 +356,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { let arg_count_correct = check_generic_arg_count_for_call( self.tcx, - self.span, pick.item.def_id, generics, seg, @@ -630,13 +629,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) { // Disallow calls to the method `drop` defined in the `Drop` trait. if let Some(trait_def_id) = pick.item.trait_container(self.tcx) { - callee::check_legal_trait_for_method_call( + if let Err(e) = callee::check_legal_trait_for_method_call( self.tcx, self.span, Some(self.self_expr.span), self.call_expr.span, trait_def_id, - ) + ) { + self.set_tainted_by_errors(e); + } } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 2a1c417a16b..81b82393515 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -230,7 +230,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind && let hir::def::Res::Local(hir_id) = path.res - && let Some(hir::Node::Pat(b)) = self.tcx.opt_hir_node(hir_id) + && let hir::Node::Pat(b) = self.tcx.hir_node(hir_id) && let Some(hir::Node::Param(p)) = self.tcx.hir().find_parent(b.hir_id) && let Some(node) = self.tcx.hir().find_parent(p.hir_id) && let Some(decl) = node.fn_decl() @@ -541,6 +541,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut bound_spans: SortedMap<Span, Vec<String>> = Default::default(); let mut restrict_type_params = false; + let mut suggested_derive = false; let mut unsatisfied_bounds = false; if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) { let msg = "consider using `len` instead"; @@ -555,6 +556,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement" )); } + } else if !unsatisfied_predicates.is_empty() && matches!(rcvr_ty.kind(), ty::Param(_)) { + // We special case the situation where we are looking for `_` in + // `<TypeParam as _>::method` because otherwise the machinery will look for blanket + // implementations that have unsatisfied trait bounds to suggest, leading us to claim + // things like "we're looking for a trait with method `cmp`, both `Iterator` and `Ord` + // have one, in order to implement `Ord` you need to restrict `TypeParam: FnPtr` so + // that `impl<T: FnPtr> Ord for T` can apply", which is not what we want. We have a type + // parameter, we want to directly say "`Ord::cmp` and `Iterator::cmp` exist, restrict + // `TypeParam: Ord` or `TypeParam: Iterator`"". That is done further down when calling + // `self.suggest_traits_to_import`, so we ignore the `unsatisfied_predicates` + // suggestions. } else if !unsatisfied_predicates.is_empty() { let mut type_params = FxIndexMap::default(); @@ -917,20 +929,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .enumerate() .collect::<Vec<(usize, String)>>(); - for ((span, add_where_or_comma), obligations) in type_params.into_iter() { - restrict_type_params = true; - // #74886: Sort here so that the output is always the same. - let obligations = obligations.into_sorted_stable_ord(); - err.span_suggestion_verbose( - span, - format!( - "consider restricting the type parameter{s} to satisfy the \ - trait bound{s}", - s = pluralize!(obligations.len()) - ), - format!("{} {}", add_where_or_comma, obligations.join(", ")), - Applicability::MaybeIncorrect, - ); + if !matches!(rcvr_ty.peel_refs().kind(), ty::Param(_)) { + for ((span, add_where_or_comma), obligations) in type_params.into_iter() { + restrict_type_params = true; + // #74886: Sort here so that the output is always the same. + let obligations = obligations.into_sorted_stable_ord(); + err.span_suggestion_verbose( + span, + format!( + "consider restricting the type parameter{s} to satisfy the trait \ + bound{s}", + s = pluralize!(obligations.len()) + ), + format!("{} {}", add_where_or_comma, obligations.join(", ")), + Applicability::MaybeIncorrect, + ); + } } bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically. @@ -978,7 +992,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "the following trait bounds were not satisfied:\n{bound_list}" )); } - self.suggest_derive(&mut err, unsatisfied_predicates); + suggested_derive = self.suggest_derive(&mut err, unsatisfied_predicates); unsatisfied_bounds = true; } @@ -1201,7 +1215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params { + if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params || suggested_derive { } else { self.suggest_traits_to_import( &mut err, @@ -1211,7 +1225,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args.map(|args| args.len() + 1), source, no_match_data.out_of_scope_traits.clone(), - unsatisfied_predicates, static_candidates, unsatisfied_bounds, expected.only_has_type(self), @@ -1326,7 +1339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected); - return Some(err); + Some(err) } fn note_candidates_on_method_error( @@ -2004,7 +2017,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { visitor.visit_body(body); let parent = self.tcx.hir().parent_id(seg1.hir_id); - if let Some(Node::Expr(call_expr)) = self.tcx.opt_hir_node(parent) + if let Node::Expr(call_expr) = self.tcx.hir_node(parent) && let Some(expr) = visitor.result && let Some(self_ty) = self.node_ty_opt(expr.hir_id) { @@ -2471,7 +2484,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>, )], - ) { + ) -> bool { let mut derives = self.note_predicate_source_and_get_derives(err, unsatisfied_predicates); derives.sort(); derives.dedup(); @@ -2496,6 +2509,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } + !derives_grouped.is_empty() } fn note_derefed_ty_has_method( @@ -2698,11 +2712,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { inputs_len: Option<usize>, source: SelfSource<'tcx>, valid_out_of_scope_traits: Vec<DefId>, - unsatisfied_predicates: &[( - ty::Predicate<'tcx>, - Option<ty::Predicate<'tcx>>, - Option<ObligationCause<'tcx>>, - )], static_candidates: &[CandidateSource], unsatisfied_bounds: bool, return_type: Option<Ty<'tcx>>, @@ -2919,19 +2928,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // this isn't perfect (that is, there are cases when // implementing a trait would be legal but is rejected // here). - unsatisfied_predicates.iter().all(|(p, _, _)| { - match p.kind().skip_binder() { - // Hide traits if they are present in predicates as they can be fixed without - // having to implement them. - ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => { - t.def_id() == info.def_id - } - ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => { - p.projection_ty.def_id == info.def_id - } - _ => false, - } - }) && (type_is_local || info.def_id.is_local()) + (type_is_local || info.def_id.is_local()) && !self.tcx.trait_is_auto(info.def_id) && self .associated_value(info.def_id, item_name) @@ -3254,7 +3251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let parent = self.tcx.hir().parent_id(expr.hir_id); - if let Some(Node::Expr(call_expr)) = self.tcx.opt_hir_node(parent) + if let Node::Expr(call_expr) = self.tcx.hir_node(parent) && let hir::ExprKind::MethodCall( hir::PathSegment { ident: method_name, .. }, self_expr, diff --git a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs index b9b3ed53dae..34ce0ab1f8b 100644 --- a/compiler/rustc_hir_typeck/src/rvalue_scopes.rs +++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs @@ -73,9 +73,7 @@ pub fn resolve_rvalue_scopes<'a, 'tcx>( debug!("start resolving rvalue scopes, def_id={def_id:?}"); debug!("rvalue_scope: rvalue_candidates={:?}", scope_tree.rvalue_candidates); for (&hir_id, candidate) in &scope_tree.rvalue_candidates { - let Some(Node::Expr(expr)) = tcx.opt_hir_node(hir_id) else { - bug!("hir node does not exist") - }; + let Node::Expr(expr) = tcx.hir_node(hir_id) else { bug!("hir node does not exist") }; record_rvalue_scope(&mut rvalue_scopes, expr, candidate); } rvalue_scopes diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index c4773a88521..211109b5941 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -972,9 +972,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Ok(mut s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) { if s.starts_with('$') { // Looks like a macro fragment. Try to find the real block. - if let Some(hir::Node::Expr(&hir::Expr { + if let hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Block(block, ..), .. - })) = self.tcx.opt_hir_node(body_id.hir_id) { + }) = self.tcx.hir_node(body_id.hir_id) { // If the body is a block (with `{..}`), we use the span of that block. // E.g. with a `|| $body` expanded from a `m!({ .. })`, we use `{ .. }`, and not `$body`. // Since we know it's a block, we know we can insert the `let _ = ..` without diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 3430a5fb00d..94f6c06157e 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -753,10 +753,14 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { } fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed { - match self.fcx.dcx().has_errors() { - Some(e) => e, - None => self - .fcx + if let Some(guar) = self.fcx.dcx().has_errors() { + guar + } else if self.fcx.dcx().stashed_err_count() > 0 { + // Without this case we sometimes get uninteresting and extraneous + // "type annotations needed" errors. + self.fcx.dcx().delayed_bug("error in Resolver") + } else { + self.fcx .err_ctxt() .emit_inference_failure_err( self.fcx.tcx.hir().body_owner_def_id(self.body.id()), @@ -765,7 +769,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { E0282, false, ) - .emit(), + .emit() } } diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 82f02b7d47a..0729986f32f 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -5,8 +5,6 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index 854841206b8..6fcb3a024ab 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![cfg_attr( feature = "nightly", feature(extend_one, min_specialization, new_uninit, step_trait, test) diff --git a/compiler/rustc_index_macros/src/lib.rs b/compiler/rustc_index_macros/src/lib.rs index 72567b43a5f..532cac5791e 100644 --- a/compiler/rustc_index_macros/src/lib.rs +++ b/compiler/rustc_index_macros/src/lib.rs @@ -31,17 +31,17 @@ mod newtype; /// - `#[max = 0xFFFF_FFFD]`: specifies the max value, which allows niche /// optimizations. The default max value is 0xFFFF_FF00. /// - `#[gate_rustc_only]`: makes parts of the generated code nightly-only. -/// -/// `SpecOptionPartialEq` is specialized by this macro, so using it requires enabling -/// `#![feature(min_specialization)]` for the crate. #[proc_macro] #[cfg_attr( feature = "nightly", - allow_internal_unstable(step_trait, rustc_attrs, trusted_step, spec_option_partial_eq) + allow_internal_unstable( + step_trait, + rustc_attrs, + trusted_step, + spec_option_partial_eq, + min_specialization + ) )] -// FIXME: Remove the above comment about `min_specialization` once bootstrap is bumped, -// and the corresponding one on SpecOptionPartialEq -#[cfg_attr(all(feature = "nightly", not(bootstrap)), allow_internal_unstable(min_specialization))] pub fn newtype_index(input: TokenStream) -> TokenStream { newtype::newtype(input) } diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 0a128218c92..8bfc05d6a96 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -1,7 +1,7 @@ use hir::GenericParamKind; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, - DiagnosticStyledString, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage, + DiagnosticStyledString, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessageOp, }; use rustc_hir as hir; use rustc_hir::FnRetTy; @@ -225,10 +225,7 @@ pub enum RegionOriginNote<'a> { } impl AddToDiagnostic for RegionOriginNote<'_> { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { let mut label_or_note = |span, msg: DiagnosticMessage| { let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); @@ -289,10 +286,7 @@ pub enum LifetimeMismatchLabels { } impl AddToDiagnostic for LifetimeMismatchLabels { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { match self { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { diag.span_label(param_span, fluent::infer_declared_different); @@ -336,10 +330,7 @@ pub struct AddLifetimeParamsSuggestion<'a> { } impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { let mut mk_suggestion = || { let ( hir::Ty { kind: hir::TyKind::Ref(lifetime_sub, _), .. }, @@ -437,10 +428,7 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq { } impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { - fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(mut self, diag: &mut Diagnostic, _: F) { self.unmet_requirements .push_span_label(self.binding_span, fluent::infer_msl_introduces_static); diag.span_note(self.unmet_requirements, fluent::infer_msl_unmet_req); @@ -755,10 +743,7 @@ pub struct ConsiderBorrowingParamHelp { } impl AddToDiagnostic for ConsiderBorrowingParamHelp { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into<DiagnosticMessage> is required @@ -799,10 +784,7 @@ pub struct DynTraitConstraintSuggestion { } impl AddToDiagnostic for DynTraitConstraintSuggestion { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) { let mut multi_span: MultiSpan = vec![self.span].into(); multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label); multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement); @@ -845,10 +827,7 @@ pub struct ReqIntroducedLocations { } impl AddToDiagnostic for ReqIntroducedLocations { - fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(mut self, diag: &mut Diagnostic, f: F) { for sp in self.spans { self.span.push_span_label(sp, fluent::infer_ril_introduced_here); } @@ -867,10 +846,7 @@ pub struct MoreTargeted { } impl AddToDiagnostic for MoreTargeted { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _f: F) { diag.code(E0772); diag.primary_message(fluent::infer_more_targeted); diag.arg("ident", self.ident); @@ -1289,10 +1265,7 @@ pub struct SuggestTuplePatternMany { } impl AddToDiagnostic for SuggestTuplePatternMany { - fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) { diag.arg("path", self.path); let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into()); diag.multipart_suggestions( diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 331e3633e90..a59a4df7729 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -1,6 +1,6 @@ use crate::fluent_generated as fluent; use crate::infer::error_reporting::nice_region_error::find_anon_type; -use rustc_errors::{AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessage}; +use rustc_errors::{AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessageOp}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{symbol::kw, Span}; @@ -160,10 +160,7 @@ impl RegionExplanation<'_> { } impl AddToDiagnostic for RegionExplanation<'_> { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, f: F) { diag.arg("pref_kind", self.prefix); diag.arg("suff_kind", self.suffix); diag.arg("desc_kind", self.desc.kind); diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 0f1af81d9f0..859593e1194 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -87,6 +87,7 @@ impl<'tcx> InferCtxt<'tcx> { reported_signature_mismatch: self.reported_signature_mismatch.clone(), tainted_by_errors: self.tainted_by_errors.clone(), err_count_on_creation: self.err_count_on_creation, + stashed_err_count_on_creation: self.stashed_err_count_on_creation, universe: self.universe.clone(), intercrate, next_trait_solver: self.next_trait_solver, diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index d825a2920ee..156a4f71017 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -481,7 +481,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> { } ty::ConstKind::Infer(InferConst::EffectVar(vid)) => { match self.infcx.unwrap().probe_effect_var(vid) { - Some(value) => return self.fold_const(value.as_const(self.tcx)), + Some(value) => return self.fold_const(value), None => { return self.canonicalize_const_var( CanonicalVarInfo { kind: CanonicalVarKind::Effect }, diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index 386fdb09ba5..1f68a5a9c61 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -24,6 +24,7 @@ use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind}; use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind}; use rustc_index::IndexVec; +use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::GenericArg; use rustc_middle::ty::{self, List, Ty, TyCtxt}; @@ -152,7 +153,12 @@ impl<'tcx> InferCtxt<'tcx> { ) .into(), CanonicalVarKind::Effect => { - let vid = self.inner.borrow_mut().effect_unification_table().new_key(None).vid; + let vid = self + .inner + .borrow_mut() + .effect_unification_table() + .new_key(EffectVarValue::Unknown) + .vid; ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid), self.tcx.types.bool) .into() } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index cf9d9333783..dd9ed80ca72 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -71,6 +71,7 @@ use rustc_hir::lang_items::LangItem; use rustc_middle::dep_graph::DepContext; use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError}; use rustc_middle::ty::relate::{self, RelateResult, TypeRelation}; +use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{ self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -519,10 +520,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit(); } - RegionResolutionError::CannotNormalize(ty, origin) => { + RegionResolutionError::CannotNormalize(clause, origin) => { + let clause: ty::Clause<'tcx> = + clause.map_bound(ty::ClauseKind::TypeOutlives).to_predicate(self.tcx); self.tcx .dcx() - .struct_span_err(origin.span(), format!("cannot normalize `{ty}`")) + .struct_span_err(origin.span(), format!("cannot normalize `{clause}`")) .emit(); } } @@ -2179,8 +2182,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if let Some(tykind) = tykind && let hir::TyKind::Array(_, length) = tykind && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length - && let Some(span) = self.tcx.hir().opt_span(*hir_id) { + let span = self.tcx.hir().span(*hir_id); Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: sz.found }) } else { None diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index d256994d8d1..2d5fa1b5c70 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -151,13 +151,8 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for TypeFreshener<'a, 'tcx> { self.freshen_const(opt_ct, ty::InferConst::Var(v), ty::InferConst::Fresh, ct.ty()) } ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => { - let opt_ct = self - .infcx - .inner - .borrow_mut() - .effect_unification_table() - .probe_value(v) - .map(|effect| effect.as_const(self.infcx.tcx)); + let opt_ct = + self.infcx.inner.borrow_mut().effect_unification_table().probe_value(v).known(); self.freshen_const( opt_ct, ty::InferConst::EffectVar(v), diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 4a1169e68e0..6137506d4a9 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -99,7 +99,7 @@ pub enum RegionResolutionError<'tcx> { Region<'tcx>, // the placeholder `'b` ), - CannotNormalize(Ty<'tcx>, SubregionOrigin<'tcx>), + CannotNormalize(ty::PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>), } impl<'tcx> RegionResolutionError<'tcx> { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 101735b2961..78ef70398e5 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -8,6 +8,7 @@ pub use self::ValuePairs::*; pub use relate::combine::ObligationEmittingRelation; use rustc_data_structures::captures::Captures; use rustc_data_structures::undo_log::UndoLogs; +use rustc_middle::infer::unify_key::EffectVarValue; use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use self::opaque_types::OpaqueTypeStorage; @@ -25,8 +26,8 @@ use rustc_data_structures::unify as ut; use rustc_errors::{DiagCtxt, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; +use rustc_middle::infer::unify_key::ConstVariableValue; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; -use rustc_middle::infer::unify_key::{ConstVariableValue, EffectVarValue}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::{select, DefiningAnchor}; @@ -305,6 +306,12 @@ pub struct InferCtxt<'tcx> { // FIXME(matthewjasper) Merge into `tainted_by_errors` err_count_on_creation: usize, + /// Track how many errors were stashed when this infcx is created. + /// Used for the same purpose as `err_count_on_creation`, even + /// though it's weaker because the count can go up and down. + // FIXME(matthewjasper) Merge into `tainted_by_errors` + stashed_err_count_on_creation: usize, + /// What is the innermost universe we have created? Starts out as /// `UniverseIndex::root()` but grows from there as we enter /// universal quantifiers. @@ -710,6 +717,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { reported_signature_mismatch: Default::default(), tainted_by_errors: Cell::new(None), err_count_on_creation: tcx.dcx().err_count(), + stashed_err_count_on_creation: tcx.dcx().stashed_err_count(), universe: Cell::new(ty::UniverseIndex::ROOT), intercrate, next_trait_solver, @@ -818,7 +826,7 @@ impl<'tcx> InferCtxt<'tcx> { (0..table.len()) .map(|i| ty::EffectVid::from_usize(i)) - .filter(|&vid| table.probe_value(vid).is_none()) + .filter(|&vid| table.probe_value(vid).is_unknown()) .map(|v| { ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v), self.tcx.types.bool) }) @@ -862,7 +870,7 @@ impl<'tcx> InferCtxt<'tcx> { } #[instrument(skip(self, snapshot), level = "debug")] - fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'tcx>) { + fn rollback_to(&self, snapshot: CombinedSnapshot<'tcx>) { let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot; self.universe.set(universe); @@ -894,7 +902,7 @@ impl<'tcx> InferCtxt<'tcx> { self.commit_from(snapshot); } Err(_) => { - self.rollback_to("commit_if_ok -- error", snapshot); + self.rollback_to(snapshot); } } r @@ -908,7 +916,7 @@ impl<'tcx> InferCtxt<'tcx> { { let snapshot = self.start_snapshot(); let r = f(&snapshot); - self.rollback_to("probe", snapshot); + self.rollback_to(snapshot); r } @@ -1031,10 +1039,9 @@ impl<'tcx> InferCtxt<'tcx> { _ => {} } - let ty::SubtypePredicate { a_is_expected, a, b } = - self.instantiate_binder_with_placeholders(predicate); - - Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b)) + self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| { + Ok(self.at(cause, param_env).sub_exp(DefineOpaqueTypes::No, a_is_expected, a, b)) + }) } pub fn region_outlives_predicate( @@ -1042,10 +1049,12 @@ impl<'tcx> InferCtxt<'tcx> { cause: &traits::ObligationCause<'tcx>, predicate: ty::PolyRegionOutlivesPredicate<'tcx>, ) { - let ty::OutlivesPredicate(r_a, r_b) = self.instantiate_binder_with_placeholders(predicate); - let origin = - SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span)); - self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` + self.enter_forall(predicate, |ty::OutlivesPredicate(r_a, r_b)| { + let origin = SubregionOrigin::from_obligation_cause(cause, || { + RelateRegionParamBound(cause.span) + }); + self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` + }) } /// Number of type variables created so far. @@ -1236,7 +1245,8 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn var_for_effect(&self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { - let effect_vid = self.inner.borrow_mut().effect_unification_table().new_key(None).vid; + let effect_vid = + self.inner.borrow_mut().effect_unification_table().new_key(EffectVarValue::Unknown).vid; let ty = self .tcx .type_of(param.def_id) @@ -1259,26 +1269,24 @@ impl<'tcx> InferCtxt<'tcx> { /// inference variables, regionck errors). #[must_use = "this method does not have any side effects"] pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> { - debug!( - "is_tainted_by_errors(err_count={}, err_count_on_creation={}, \ - tainted_by_errors={})", - self.dcx().err_count(), - self.err_count_on_creation, - self.tainted_by_errors.get().is_some() - ); - - if let Some(e) = self.tainted_by_errors.get() { - return Some(e); - } - - if self.dcx().err_count() > self.err_count_on_creation { - // errors reported since this infcx was made - let e = self.dcx().has_errors().unwrap(); - self.set_tainted_by_errors(e); - return Some(e); + if let Some(guar) = self.tainted_by_errors.get() { + Some(guar) + } else if self.dcx().err_count() > self.err_count_on_creation { + // Errors reported since this infcx was made. + let guar = self.dcx().has_errors().unwrap(); + self.set_tainted_by_errors(guar); + Some(guar) + } else if self.dcx().stashed_err_count() > self.stashed_err_count_on_creation { + // Errors stashed since this infcx was made. Not entirely reliable + // because the count of stashed errors can go down. But without + // this case we get a moderate number of uninteresting and + // extraneous "type annotations needed" errors. + let guar = self.dcx().delayed_bug("tainted_by_errors: stashed bug awaiting emission"); + self.set_tainted_by_errors(guar); + Some(guar) + } else { + None } - - None } /// Set the "tainted by errors" flag to true. We call this when we @@ -1416,8 +1424,8 @@ impl<'tcx> InferCtxt<'tcx> { } } - pub fn probe_effect_var(&self, vid: EffectVid) -> Option<EffectVarValue<'tcx>> { - self.inner.borrow_mut().effect_unification_table().probe_value(vid) + pub fn probe_effect_var(&self, vid: EffectVid) -> Option<ty::Const<'tcx>> { + self.inner.borrow_mut().effect_unification_table().probe_value(vid).known() } /// Attempts to resolve all type/region/const variables in @@ -1453,7 +1461,7 @@ impl<'tcx> InferCtxt<'tcx> { // Use this method if you'd like to find some substitution of the binder's // variables (e.g. during a method call). If there isn't a [`BoundRegionConversionTime`] // that corresponds to your use case, consider whether or not you should - // use [`InferCtxt::instantiate_binder_with_placeholders`] instead. + // use [`InferCtxt::enter_forall`] instead. pub fn instantiate_binder_with_fresh_vars<T>( &self, span: Span, @@ -1897,7 +1905,8 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ShallowResolver<'a, 'tcx> { .borrow_mut() .effect_unification_table() .probe_value(vid) - .map_or(ct, |val| val.as_const(self.infcx.tcx)), + .known() + .unwrap_or(ct), _ => ct, } } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 5ee0a606a5f..46c4f80cb0c 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -327,7 +327,6 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(level = "debug", skip(self))] pub fn register_member_constraints( &self, - param_env: ty::ParamEnv<'tcx>, opaque_type_key: OpaqueTypeKey<'tcx>, concrete_ty: Ty<'tcx>, span: Span, @@ -687,7 +686,7 @@ fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hi let res = hir_id == scope; trace!( "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}", - tcx.opt_hir_node(hir_id), + tcx.hir_node(hir_id), tcx.hir_node(opaque_hir_id), res ); diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 926e198b219..a4f9316b502 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -4,8 +4,8 @@ use super::region_constraints::RegionConstraintData; use super::{InferCtxt, RegionResolutionError, SubregionOrigin}; use crate::infer::free_regions::RegionRelations; use crate::infer::lexical_region_resolve; -use rustc_middle::traits::query::OutlivesBound; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::traits::query::{NoSolution, OutlivesBound}; +use rustc_middle::ty; pub mod components; pub mod env; @@ -49,12 +49,15 @@ impl<'tcx> InferCtxt<'tcx> { pub fn resolve_regions_with_normalize( &self, outlives_env: &OutlivesEnvironment<'tcx>, - deeply_normalize_ty: impl Fn(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result<Ty<'tcx>, Ty<'tcx>>, + deeply_normalize_ty: impl Fn( + ty::PolyTypeOutlivesPredicate<'tcx>, + SubregionOrigin<'tcx>, + ) -> Result<ty::PolyTypeOutlivesPredicate<'tcx>, NoSolution>, ) -> Vec<RegionResolutionError<'tcx>> { match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) { Ok(()) => {} - Err((ty, origin)) => { - return vec![RegionResolutionError::CannotNormalize(ty, origin)]; + Err((clause, origin)) => { + return vec![RegionResolutionError::CannotNormalize(clause, origin)]; } }; diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index b10bf98e8b5..7208f17fb34 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -68,8 +68,9 @@ use crate::infer::{ use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::undo_log::UndoLogs; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::ty::GenericArgKind; +use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{GenericArgKind, PolyTypeOutlivesPredicate}; use rustc_span::DUMMY_SP; use smallvec::smallvec; @@ -125,11 +126,15 @@ impl<'tcx> InferCtxt<'tcx> { /// invoked after all type-inference variables have been bound -- /// right before lexical region resolution. #[instrument(level = "debug", skip(self, outlives_env, deeply_normalize_ty))] - pub fn process_registered_region_obligations<E>( + pub fn process_registered_region_obligations( &self, outlives_env: &OutlivesEnvironment<'tcx>, - mut deeply_normalize_ty: impl FnMut(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result<Ty<'tcx>, E>, - ) -> Result<(), (E, SubregionOrigin<'tcx>)> { + mut deeply_normalize_ty: impl FnMut( + PolyTypeOutlivesPredicate<'tcx>, + SubregionOrigin<'tcx>, + ) + -> Result<PolyTypeOutlivesPredicate<'tcx>, NoSolution>, + ) -> Result<(), (PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>)> { assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); let normalized_caller_bounds: Vec<_> = outlives_env @@ -137,38 +142,53 @@ impl<'tcx> InferCtxt<'tcx> { .caller_bounds() .iter() .filter_map(|clause| { - let bound_clause = clause.kind(); - let ty::ClauseKind::TypeOutlives(outlives) = bound_clause.skip_binder() else { - return None; - }; + let outlives = clause.as_type_outlives_clause()?; Some( deeply_normalize_ty( - outlives.0, + outlives, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP), ) - .map(|ty| bound_clause.rebind(ty::OutlivesPredicate(ty, outlives.1))), + // FIXME(-Znext-solver): How do we accurately report an error span here :( + .map_err(|NoSolution| { + (outlives, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)) + }), ) }) - // FIXME(-Znext-solver): How do we accurately report an error here :( - .try_collect() - .map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?; - - let my_region_obligations = self.take_registered_region_obligations(); - - for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { - let sup_type = - deeply_normalize_ty(sup_type, origin.clone()).map_err(|e| (e, origin.clone()))?; - debug!(?sup_type, ?sub_region, ?origin); - - let outlives = &mut TypeOutlives::new( - self, - self.tcx, - outlives_env.region_bound_pairs(), - None, - &normalized_caller_bounds, - ); - let category = origin.to_constraint_category(); - outlives.type_must_outlive(origin, sup_type, sub_region, category); + .try_collect()?; + + // Must loop since the process of normalizing may itself register region obligations. + for iteration in 0.. { + let my_region_obligations = self.take_registered_region_obligations(); + if my_region_obligations.is_empty() { + break; + } + + if !self.tcx.recursion_limit().value_within_limit(iteration) { + bug!( + "FIXME(-Znext-solver): Overflowed when processing region obligations: {my_region_obligations:#?}" + ); + } + + for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { + let outlives = ty::Binder::dummy(ty::OutlivesPredicate(sup_type, sub_region)); + let ty::OutlivesPredicate(sup_type, sub_region) = + deeply_normalize_ty(outlives, origin.clone()) + .map_err(|NoSolution| (outlives, origin.clone()))? + .no_bound_vars() + .expect("started with no bound vars, should end with no bound vars"); + + debug!(?sup_type, ?sub_region, ?origin); + + let outlives = &mut TypeOutlives::new( + self, + self.tcx, + outlives_env.region_bound_pairs(), + None, + &normalized_caller_bounds, + ); + let category = origin.to_constraint_category(); + outlives.type_must_outlive(origin, sup_type, sub_region, category); + } } Ok(()) diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs index 1c120646f1f..7edfbf02a68 100644 --- a/compiler/rustc_infer/src/infer/relate/combine.rs +++ b/compiler/rustc_infer/src/infer/relate/combine.rs @@ -202,11 +202,7 @@ impl<'tcx> InferCtxt<'tcx> { ty::ConstKind::Infer(InferConst::EffectVar(a_vid)), ty::ConstKind::Infer(InferConst::EffectVar(b_vid)), ) => { - self.inner - .borrow_mut() - .effect_unification_table() - .unify_var_var(a_vid, b_vid) - .map_err(|a| effect_unification_error(self.tcx, relation.a_is_expected(), a))?; + self.inner.borrow_mut().effect_unification_table().union(a_vid, b_vid); return Ok(a); } @@ -225,27 +221,19 @@ impl<'tcx> InferCtxt<'tcx> { } (ty::ConstKind::Infer(InferConst::Var(vid)), _) => { - return self.unify_const_variable(vid, b, relation.param_env()); + return self.unify_const_variable(vid, b); } (_, ty::ConstKind::Infer(InferConst::Var(vid))) => { - return self.unify_const_variable(vid, a, relation.param_env()); + return self.unify_const_variable(vid, a); } (ty::ConstKind::Infer(InferConst::EffectVar(vid)), _) => { - return self.unify_effect_variable( - relation.a_is_expected(), - vid, - EffectVarValue::Const(b), - ); + return Ok(self.unify_effect_variable(vid, b)); } (_, ty::ConstKind::Infer(InferConst::EffectVar(vid))) => { - return self.unify_effect_variable( - !relation.a_is_expected(), - vid, - EffectVarValue::Const(a), - ); + return Ok(self.unify_effect_variable(vid, a)); } (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) @@ -310,7 +298,6 @@ impl<'tcx> InferCtxt<'tcx> { &self, target_vid: ty::ConstVid, ct: ty::Const<'tcx>, - param_env: ty::ParamEnv<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { let span = match self.inner.borrow_mut().const_unification_table().probe_value(target_vid) { ConstVariableValue::Known { value } => { @@ -366,18 +353,12 @@ impl<'tcx> InferCtxt<'tcx> { Ok(Ty::new_float(self.tcx, val)) } - fn unify_effect_variable( - &self, - vid_is_expected: bool, - vid: ty::EffectVid, - val: EffectVarValue<'tcx>, - ) -> RelateResult<'tcx, ty::Const<'tcx>> { + fn unify_effect_variable(&self, vid: ty::EffectVid, val: ty::Const<'tcx>) -> ty::Const<'tcx> { self.inner .borrow_mut() .effect_unification_table() - .unify_var_value(vid, Some(val)) - .map_err(|e| effect_unification_error(self.tcx, vid_is_expected, e))?; - Ok(val.as_const(self.tcx)) + .union_value(vid, EffectVarValue::Known(val)); + val } } @@ -579,11 +560,3 @@ fn float_unification_error<'tcx>( let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v; TypeError::FloatMismatch(ExpectedFound::new(a_is_expected, a, b)) } - -fn effect_unification_error<'tcx>( - _tcx: TyCtxt<'tcx>, - _a_is_expected: bool, - (_a, _b): (EffectVarValue<'tcx>, EffectVarValue<'tcx>), -) -> TypeError<'tcx> { - bug!("unexpected effect unification error") -} diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 440df8c8936..90be80f67b4 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -38,24 +38,25 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { // First, we instantiate each bound region in the supertype with a // fresh placeholder region. Note that this automatically creates // a new universe if needed. - let sup_prime = self.infcx.instantiate_binder_with_placeholders(sup); + self.infcx.enter_forall(sup, |sup_prime| { + // Next, we instantiate each bound region in the subtype + // with a fresh region variable. These region variables -- + // but no other preexisting region variables -- can name + // the placeholders. + let sub_prime = + self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub); + debug!("a_prime={:?}", sub_prime); + debug!("b_prime={:?}", sup_prime); - // Next, we instantiate each bound region in the subtype - // with a fresh region variable. These region variables -- - // but no other preexisting region variables -- can name - // the placeholders. - let sub_prime = self.infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, sub); - - debug!("a_prime={:?}", sub_prime); - debug!("b_prime={:?}", sup_prime); - - // Compare types now that bound regions have been replaced. - let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime)?; - - debug!("OK result={result:?}"); - // NOTE: returning the result here would be dangerous as it contains - // placeholders which **must not** be named afterwards. - Ok(()) + // Compare types now that bound regions have been replaced. + let result = self.sub(sub_is_expected).relate(sub_prime, sup_prime); + if result.is_ok() { + debug!("OK result={result:?}"); + } + // NOTE: returning the result here would be dangerous as it contains + // placeholders which **must not** be named afterwards. + result.map(|_| ()) + }) } } @@ -68,9 +69,11 @@ impl<'tcx> InferCtxt<'tcx> { /// This is the first step of checking subtyping when higher-ranked things are involved. /// For more details visit the relevant sections of the [rustc dev guide]. /// + /// `fn enter_forall` should be preferred over this method. + /// /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html #[instrument(level = "debug", skip(self), ret)] - pub fn instantiate_binder_with_placeholders<T>(&self, binder: ty::Binder<'tcx, T>) -> T + pub fn enter_forall_and_leak_universe<T>(&self, binder: ty::Binder<'tcx, T>) -> T where T: TypeFoldable<TyCtxt<'tcx>> + Copy, { @@ -106,6 +109,31 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx.replace_bound_vars_uncached(binder, delegate) } + /// Replaces all bound variables (lifetimes, types, and constants) bound by + /// `binder` with placeholder variables in a new universe and then calls the + /// closure `f` with the instantiated value. The new placeholders can only be + /// named by inference variables created inside of the closure `f` or afterwards. + /// + /// This is the first step of checking subtyping when higher-ranked things are involved. + /// For more details visit the relevant sections of the [rustc dev guide]. + /// + /// This method should be preferred over `fn enter_forall_and_leak_universe`. + /// + /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html + #[instrument(level = "debug", skip(self, f))] + pub fn enter_forall<T, U>(&self, forall: ty::Binder<'tcx, T>, f: impl FnOnce(T) -> U) -> U + where + T: TypeFoldable<TyCtxt<'tcx>> + Copy, + { + // FIXME: currently we do nothing to prevent placeholders with the new universe being + // used after exiting `f`. For example region subtyping can result in outlives constraints + // that name placeholders created in this function. Nested goals from type relations can + // also contain placeholders created by this function. + let value = self.enter_forall_and_leak_universe(forall); + debug!("?value"); + f(value) + } + /// See [RegionConstraintCollector::leak_check][1]. We only check placeholder /// leaking into `outer_universe`, i.e. placeholders which cannot be named by that /// universe. diff --git a/compiler/rustc_infer/src/infer/relate/nll.rs b/compiler/rustc_infer/src/infer/relate/nll.rs index 8b80646a386..5e2d2af9b85 100644 --- a/compiler/rustc_infer/src/infer/relate/nll.rs +++ b/compiler/rustc_infer/src/infer/relate/nll.rs @@ -261,52 +261,55 @@ where Ok(a) } - #[instrument(skip(self), level = "debug")] - fn instantiate_binder_with_placeholders<T>(&mut self, binder: ty::Binder<'tcx, T>) -> T + fn enter_forall<T, U>( + &mut self, + binder: ty::Binder<'tcx, T>, + f: impl FnOnce(&mut Self, T) -> U, + ) -> U where T: ty::TypeFoldable<TyCtxt<'tcx>> + Copy, { - if let Some(inner) = binder.no_bound_vars() { - return inner; - } - - let mut next_region = { - let nll_delegate = &mut self.delegate; - let mut lazy_universe = None; + let value = if let Some(inner) = binder.no_bound_vars() { + inner + } else { + let mut next_region = { + let nll_delegate = &mut self.delegate; + let mut lazy_universe = None; + + move |br: ty::BoundRegion| { + // The first time this closure is called, create a + // new universe for the placeholders we will make + // from here out. + let universe = lazy_universe.unwrap_or_else(|| { + let universe = nll_delegate.create_next_universe(); + lazy_universe = Some(universe); + universe + }); + + let placeholder = ty::PlaceholderRegion { universe, bound: br }; + debug!(?placeholder); + let placeholder_reg = nll_delegate.next_placeholder_region(placeholder); + debug!(?placeholder_reg); + + placeholder_reg + } + }; - move |br: ty::BoundRegion| { - // The first time this closure is called, create a - // new universe for the placeholders we will make - // from here out. - let universe = lazy_universe.unwrap_or_else(|| { - let universe = nll_delegate.create_next_universe(); - lazy_universe = Some(universe); - universe - }); - - let placeholder = ty::PlaceholderRegion { universe, bound: br }; - debug!(?placeholder); - let placeholder_reg = nll_delegate.next_placeholder_region(placeholder); - debug!(?placeholder_reg); - - placeholder_reg - } - }; + let delegate = FnMutDelegate { + regions: &mut next_region, + types: &mut |_bound_ty: ty::BoundTy| { + unreachable!("we only replace regions in nll_relate, not types") + }, + consts: &mut |_bound_var: ty::BoundVar, _ty| { + unreachable!("we only replace regions in nll_relate, not consts") + }, + }; - let delegate = FnMutDelegate { - regions: &mut next_region, - types: &mut |_bound_ty: ty::BoundTy| { - unreachable!("we only replace regions in nll_relate, not types") - }, - consts: &mut |_bound_var: ty::BoundVar, _ty| { - unreachable!("we only replace regions in nll_relate, not consts") - }, + self.infcx.tcx.replace_bound_vars_uncached(binder, delegate) }; - let replaced = self.infcx.tcx.replace_bound_vars_uncached(binder, delegate); - debug!(?replaced); - - replaced + debug!(?value); + f(self, value) } #[instrument(skip(self), level = "debug")] @@ -630,10 +633,10 @@ where // Note: the order here is important. Create the placeholders first, otherwise // we assign the wrong universe to the existential! - let b_replaced = self.instantiate_binder_with_placeholders(b); - let a_replaced = self.instantiate_binder_with_existentials(a); - - self.relate(a_replaced, b_replaced)?; + self.enter_forall(b, |this, b| { + let a = this.instantiate_binder_with_existentials(a); + this.relate(a, b) + })?; self.ambient_variance = variance; } @@ -650,10 +653,10 @@ where let variance = std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant); - let a_replaced = self.instantiate_binder_with_placeholders(a); - let b_replaced = self.instantiate_binder_with_existentials(b); - - self.relate(a_replaced, b_replaced)?; + self.enter_forall(a, |this, a| { + let b = this.instantiate_binder_with_existentials(b); + this.relate(a, b) + })?; self.ambient_variance = variance; } diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 959b0903127..d5999331dfa 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -237,14 +237,13 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerResolver<'_, 'tcx> { } ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => { debug_assert_eq!(c.ty(), self.infcx.tcx.types.bool); - match self.infcx.probe_effect_var(vid) { - Some(c) => c.as_const(self.infcx.tcx), - None => ty::Const::new_infer( + self.infcx.probe_effect_var(vid).unwrap_or_else(|| { + ty::Const::new_infer( self.infcx.tcx, ty::InferConst::EffectVar(self.infcx.root_effect_var(vid)), self.infcx.tcx.types.bool, - ), - } + ) + }) } _ => { if c.has_infer() { diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index e2dd4b49e1a..622cdf0c7b8 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -16,6 +16,8 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(extend_one)] diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index 1ceb245dcc7..7401654aea8 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{codes::*, struct_span_code_err, Applicability, DiagnosticBuilder, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::Map; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; @@ -62,7 +61,7 @@ pub fn report_object_safety_error<'tcx>( err.span_label(span, format!("`{trait_str}` cannot be made into an object")); if let Some(hir_id) = hir_id - && let Some(hir::Node::Ty(ty)) = tcx.hir().find(hir_id) + && let hir::Node::Ty(ty) = tcx.hir_node(hir_id) && let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind { let mut hir_id = hir_id; diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs index 69414a13795..7d69e49b209 100644 --- a/compiler/rustc_interface/src/lib.rs +++ b/compiler/rustc_interface/src/lib.rs @@ -4,8 +4,6 @@ #![feature(let_chains)] #![feature(thread_spawn_unchecked)] #![feature(try_blocks)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 97956404120..50b2bf7da15 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -778,6 +778,10 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { // kindck is gone now). -nmatsakis if let Some(reported) = sess.dcx().has_errors() { return Err(reported); + } else if sess.dcx().stashed_err_count() > 0 { + // Without this case we sometimes get delayed bug ICEs and I don't + // understand why. -nnethercote + return Err(sess.dcx().delayed_bug("some stashed error is waiting for use")); } sess.time("misc_checking_3", || { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 2d4963a8b90..bfc4fc07d4c 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -749,6 +749,7 @@ fn test_unstable_options_tracking_hash() { tracked!(debug_macros, true); tracked!(default_hidden_visibility, Some(true)); tracked!(dep_info_omit_d_target, true); + tracked!(direct_access_external_data, Some(true)); tracked!(dual_proc_macros, true); tracked!(dwarf_version, Some(5)); tracked!(emit_thin_lto, false); diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index f6c9289b529..ca84e930c24 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -18,8 +18,7 @@ //! lexeme types. //! //! [`rustc_parse::lexer`]: ../rustc_parse/lexer/index.html -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] + // We want to be able to build this crate with a stable compiler, // so no `#![feature]` attributes should be added. #![deny(unstable_features)] diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index eb42730f69a..0fa61c5d87e 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -188,6 +188,23 @@ pub(super) fn builtin( #[allow(rustc::potential_query_instability)] let possibilities: Vec<Symbol> = sess.parse_sess.check_config.expecteds.keys().copied().collect(); + + let mut names_possibilities: Vec<_> = if value.is_none() { + // We later sort and display all the possibilities, so the order here does not matter. + #[allow(rustc::potential_query_instability)] + sess.parse_sess + .check_config + .expecteds + .iter() + .filter_map(|(k, v)| match v { + ExpectedValues::Some(v) if v.contains(&Some(name)) => Some(k), + _ => None, + }) + .collect() + } else { + Vec::new() + }; + let is_from_cargo = std::env::var_os("CARGO").is_some(); let mut is_feature_cfg = name == sym::feature; @@ -262,17 +279,30 @@ pub(super) fn builtin( } is_feature_cfg |= best_match == sym::feature; - } else if !possibilities.is_empty() { - let mut possibilities = - possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>(); - possibilities.sort(); - let possibilities = possibilities.join("`, `"); + } else { + if !names_possibilities.is_empty() && names_possibilities.len() <= 3 { + names_possibilities.sort(); + for cfg_name in names_possibilities.iter() { + db.span_suggestion( + name_span, + "found config with similar value", + format!("{cfg_name} = \"{name}\""), + Applicability::MaybeIncorrect, + ); + } + } + if !possibilities.is_empty() { + let mut possibilities = + possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>(); + possibilities.sort(); + let possibilities = possibilities.join("`, `"); - // The list of expected names can be long (even by default) and - // so the diagnostic produced can take a lot of space. To avoid - // cloging the user output we only want to print that diagnostic - // once. - db.help_once(format!("expected names are: `{possibilities}`")); + // The list of expected names can be long (even by default) and + // so the diagnostic produced can take a lot of space. To avoid + // cloging the user output we only want to print that diagnostic + // once. + db.help_once(format!("expected names are: `{possibilities}`")); + } } let inst = if let Some((value, _value_span)) = value { diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 3bd0c1b8031..21d4b6fa65b 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -1,5 +1,5 @@ use crate::fluent_generated as fluent; -use rustc_errors::{codes::*, AddToDiagnostic, Diagnostic, SubdiagnosticMessage}; +use rustc_errors::{codes::*, AddToDiagnostic, Diagnostic, SubdiagnosticMessageOp}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::lint::Level; use rustc_span::{Span, Symbol}; @@ -24,10 +24,7 @@ pub enum OverruledAttributeSub { } impl AddToDiagnostic for OverruledAttributeSub { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { match self { OverruledAttributeSub::DefaultSource { id } => { diag.note(fluent::lint_default_source); diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index eb2490a47d0..516df14c894 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -345,7 +345,7 @@ declare_tool_lint! { /// /// More details on translatable diagnostics can be found [here](https://rustc-dev-guide.rust-lang.org/diagnostics/translation.html). pub rustc::UNTRANSLATABLE_DIAGNOSTIC, - Allow, + Deny, "prevent creation of diagnostics which cannot be translated", report_in_external_macro: true } @@ -357,7 +357,7 @@ declare_tool_lint! { /// /// More details on diagnostics implementations can be found [here](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html). pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL, - Allow, + Deny, "prevent creation of diagnostics outside of `IntoDiagnostic`/`AddToDiagnostic` impls", report_in_external_macro: true } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index caa01556591..d3d7698e7f9 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -364,14 +364,11 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( // Note: `passes` is often empty. In that case, it's faster to run // `builtin_lints` directly rather than bundling it up into the // `RuntimeCombinedLateLintPass`. - let mut passes: Vec<_> = unerased_lint_store(tcx.sess) - .late_module_passes - .iter() - .map(|mk_pass| (mk_pass)(tcx)) - .collect(); - if passes.is_empty() { + let late_module_passes = &unerased_lint_store(tcx.sess).late_module_passes; + if late_module_passes.is_empty() { late_lint_mod_inner(tcx, module_def_id, context, builtin_lints); } else { + let mut passes: Vec<_> = late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); passes.push(Box::new(builtin_lints)); let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] }; late_lint_mod_inner(tcx, module_def_id, context, pass); diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 0a15671e686..5c2a422a2b7 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -34,11 +34,9 @@ #![feature(if_let_guard)] #![feature(iter_order_by)] #![feature(let_chains)] -#![cfg_attr(not(bootstrap), feature(trait_upcasting))] +#![feature(trait_upcasting)] #![feature(min_specialization)] #![feature(rustc_attrs)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] @@ -520,6 +518,11 @@ fn register_builtins(store: &mut LintStore) { "illegal_floating_point_literal_pattern", "no longer a warning, float patterns behave the same as `==`", ); + store.register_removed( + "nontrivial_structural_match", + "no longer needed, see RFC #3535 \ + <https://rust-lang.github.io/rfcs/3535-constants-in-patterns.html> for more information", + ); } fn register_internals(store: &mut LintStore) { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index f916deb4a46..42d9760f8aa 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,12 +1,13 @@ -#![allow(rustc::untranslatable_diagnostic)] #![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] + use std::num::NonZeroU32; use crate::errors::RequestedLevel; use crate::fluent_generated as fluent; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, - DiagnosticMessage, DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle, + DiagnosticMessage, DiagnosticStyledString, SubdiagnosticMessageOp, SuggestionStyle, }; use rustc_hir::def_id::DefId; use rustc_macros::{LintDiagnostic, Subdiagnostic}; @@ -268,10 +269,7 @@ pub struct SuggestChangingAssocTypes<'a, 'b> { } impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { // Access to associates types should use `<T as Bound>::Assoc`, which does not need a // bound. Let's see if this type does that. @@ -323,10 +321,7 @@ pub struct BuiltinTypeAliasGenericBoundsSuggestion { } impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { diag.multipart_suggestion( fluent::lint_suggestion, self.suggestions, @@ -443,10 +438,7 @@ pub struct BuiltinUnpermittedTypeInitSub { } impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { let mut err = self.err; loop { if let Some(span) = err.span { @@ -497,10 +489,7 @@ pub struct BuiltinClashingExternSub<'a> { } impl AddToDiagnostic for BuiltinClashingExternSub<'_> { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { let mut expected_str = DiagnosticStyledString::new(); expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); let mut found_str = DiagnosticStyledString::new(); @@ -766,10 +755,7 @@ pub struct HiddenUnicodeCodepointsDiagLabels { } impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { for (c, span) in self.spans { diag.span_label(span, format!("{c:?}")); } @@ -783,10 +769,7 @@ pub enum HiddenUnicodeCodepointsDiagSub { // Used because of multiple multipart_suggestion and note impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { diag.multipart_suggestion_with_style( @@ -934,10 +917,7 @@ pub struct NonBindingLetSub { } impl AddToDiagnostic for NonBindingLetSub { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar; if can_suggest_binding { @@ -1217,10 +1197,7 @@ pub enum NonSnakeCaseDiagSub { } impl AddToDiagnostic for NonSnakeCaseDiagSub { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { match self { NonSnakeCaseDiagSub::Label { span } => { diag.span_label(span, fluent::lint_label); @@ -1413,10 +1390,7 @@ pub enum OverflowingBinHexSign { } impl AddToDiagnostic for OverflowingBinHexSign { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { match self { OverflowingBinHexSign::Positive => { diag.note(fluent::lint_positive_note); diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index bed5d3c80c0..cf825be7a55 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -77,101 +77,104 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { for (pred, pred_span) in cx.tcx.explicit_item_bounds(def_id).instantiate_identity_iter_copied() { - let predicate = infcx.instantiate_binder_with_placeholders(pred.kind()); - let ty::ClauseKind::Projection(proj) = predicate else { - continue; - }; - // Only check types, since those are the only things that may - // have opaques in them anyways. - let Some(proj_term) = proj.term.ty() else { continue }; + infcx.enter_forall(pred.kind(), |predicate| { + let ty::ClauseKind::Projection(proj) = predicate else { + return; + }; + // Only check types, since those are the only things that may + // have opaques in them anyways. + let Some(proj_term) = proj.term.ty() else { return }; - // HACK: `impl Trait<Assoc = impl Trait2>` from an RPIT is "ok"... - if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind() - && cx.tcx.parent(opaque_ty.def_id) == def_id - && matches!( - opaque.origin, - hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) - ) - { - continue; - } + // HACK: `impl Trait<Assoc = impl Trait2>` from an RPIT is "ok"... + if let ty::Alias(ty::Opaque, opaque_ty) = *proj_term.kind() + && cx.tcx.parent(opaque_ty.def_id) == def_id + && matches!( + opaque.origin, + hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) + ) + { + return; + } - // HACK: `async fn() -> Self` in traits is "ok"... - // This is not really that great, but it's similar to why the `-> Self` - // return type is well-formed in traits even when `Self` isn't sized. - if let ty::Param(param_ty) = *proj_term.kind() - && param_ty.name == kw::SelfUpper - && matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(_)) - && opaque.in_trait - { - continue; - } + // HACK: `async fn() -> Self` in traits is "ok"... + // This is not really that great, but it's similar to why the `-> Self` + // return type is well-formed in traits even when `Self` isn't sized. + if let ty::Param(param_ty) = *proj_term.kind() + && param_ty.name == kw::SelfUpper + && matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(_)) + && opaque.in_trait + { + return; + } - let proj_ty = - Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.args); - // For every instance of the projection type in the bounds, - // replace them with the term we're assigning to the associated - // type in our opaque type. - let proj_replacer = &mut BottomUpFolder { - tcx: cx.tcx, - ty_op: |ty| if ty == proj_ty { proj_term } else { ty }, - lt_op: |lt| lt, - ct_op: |ct| ct, - }; - // For example, in `impl Trait<Assoc = impl Send>`, for all of the bounds on `Assoc`, - // e.g. `type Assoc: OtherTrait`, replace `<impl Trait as Trait>::Assoc: OtherTrait` - // with `impl Send: OtherTrait`. - for (assoc_pred, assoc_pred_span) in cx - .tcx - .explicit_item_bounds(proj.projection_ty.def_id) - .iter_instantiated_copied(cx.tcx, proj.projection_ty.args) - { - let assoc_pred = assoc_pred.fold_with(proj_replacer); - let Ok(assoc_pred) = traits::fully_normalize( - infcx, - traits::ObligationCause::dummy(), - cx.param_env, - assoc_pred, - ) else { - continue; + let proj_ty = + Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.args); + // For every instance of the projection type in the bounds, + // replace them with the term we're assigning to the associated + // type in our opaque type. + let proj_replacer = &mut BottomUpFolder { + tcx: cx.tcx, + ty_op: |ty| if ty == proj_ty { proj_term } else { ty }, + lt_op: |lt| lt, + ct_op: |ct| ct, }; - // If that predicate doesn't hold modulo regions (but passed during type-check), - // then we must've taken advantage of the hack in `project_and_unify_types` where - // we replace opaques with inference vars. Emit a warning! - if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new( - cx.tcx, - traits::ObligationCause::dummy(), - cx.param_env, - assoc_pred, - )) { - // If it's a trait bound and an opaque that doesn't satisfy it, - // then we can emit a suggestion to add the bound. - let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) { - ( - ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), - ty::ClauseKind::Trait(trait_pred), - ) => Some(AddBound { - suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(), - trait_ref: trait_pred.print_modifiers_and_trait_path(), - }), - _ => None, + // For example, in `impl Trait<Assoc = impl Send>`, for all of the bounds on `Assoc`, + // e.g. `type Assoc: OtherTrait`, replace `<impl Trait as Trait>::Assoc: OtherTrait` + // with `impl Send: OtherTrait`. + for (assoc_pred, assoc_pred_span) in cx + .tcx + .explicit_item_bounds(proj.projection_ty.def_id) + .iter_instantiated_copied(cx.tcx, proj.projection_ty.args) + { + let assoc_pred = assoc_pred.fold_with(proj_replacer); + let Ok(assoc_pred) = traits::fully_normalize( + infcx, + traits::ObligationCause::dummy(), + cx.param_env, + assoc_pred, + ) else { + continue; }; - cx.emit_span_lint( - OPAQUE_HIDDEN_INFERRED_BOUND, - pred_span, - OpaqueHiddenInferredBoundLint { - ty: Ty::new_opaque( - cx.tcx, - def_id, - ty::GenericArgs::identity_for_item(cx.tcx, def_id), - ), - proj_ty: proj_term, - assoc_pred_span, - add_bound, - }, - ); + + // If that predicate doesn't hold modulo regions (but passed during type-check), + // then we must've taken advantage of the hack in `project_and_unify_types` where + // we replace opaques with inference vars. Emit a warning! + if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new( + cx.tcx, + traits::ObligationCause::dummy(), + cx.param_env, + assoc_pred, + )) { + // If it's a trait bound and an opaque that doesn't satisfy it, + // then we can emit a suggestion to add the bound. + let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) { + ( + ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), + ty::ClauseKind::Trait(trait_pred), + ) => Some(AddBound { + suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(), + trait_ref: trait_pred.print_modifiers_and_trait_path(), + }), + _ => None, + }; + + cx.emit_span_lint( + OPAQUE_HIDDEN_INFERRED_BOUND, + pred_span, + OpaqueHiddenInferredBoundLint { + ty: Ty::new_opaque( + cx.tcx, + def_id, + ty::GenericArgs::identity_for_item(cx.tcx, def_id), + ), + proj_ty: proj_term, + assoc_pred_span, + add_bound, + }, + ); + } } - } + }); } } } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 07c0e75a71c..6a2a2c1e48e 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3,6 +3,9 @@ //! These are the built-in lints that are emitted direct in the main //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. +//! +//! When removing a lint, make sure to also add a call to `register_removed` in +//! compiler/rustc_lint/src/lib.rs. use crate::{declare_lint, declare_lint_pass, FutureIncompatibilityReason}; use rustc_span::edition::Edition; @@ -66,7 +69,6 @@ declare_lint_pass! { MUST_NOT_SUSPEND, NAMED_ARGUMENTS_USED_POSITIONALLY, NON_EXHAUSTIVE_OMITTED_PATTERNS, - NONTRIVIAL_STRUCTURAL_MATCH, ORDER_DEPENDENT_TRAIT_OBJECTS, OVERLAPPING_RANGE_ENDPOINTS, PATTERNS_IN_FNS_WITHOUT_BODY, @@ -2280,8 +2282,8 @@ declare_lint! { Warn, "constant used in pattern contains value of non-structural-match type in a field or a variant", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, - reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>", + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, + reference: "issue #120362 <https://github.com/rust-lang/rust/issues/120362>", }; } @@ -2336,47 +2338,8 @@ declare_lint! { Warn, "pointers are not structural-match", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, - reference: "issue #62411 <https://github.com/rust-lang/rust/issues/70861>", - }; -} - -declare_lint! { - /// The `nontrivial_structural_match` lint detects constants that are used in patterns, - /// whose type is not structural-match and whose initializer body actually uses values - /// that are not structural-match. So `Option<NotStructuralMatch>` is ok if the constant - /// is just `None`. - /// - /// ### Example - /// - /// ```rust,compile_fail - /// #![deny(nontrivial_structural_match)] - /// - /// #[derive(Copy, Clone, Debug)] - /// struct NoDerive(u32); - /// impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } - /// impl Eq for NoDerive { } - /// fn main() { - /// const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0]; - /// match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; - /// } - /// ``` - /// - /// {{produces}} - /// - /// ### Explanation - /// - /// Previous versions of Rust accepted constants in patterns, even if those constants' types - /// did not have `PartialEq` derived. Thus the compiler falls back to runtime execution of - /// `PartialEq`, which can report that two constants are not equal even if they are - /// bit-equivalent. - pub NONTRIVIAL_STRUCTURAL_MATCH, - Warn, - "constant used in pattern of non-structural-match type and the constant's initializer \ - expression contains values of non-structural-match types", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, - reference: "issue #73448 <https://github.com/rust-lang/rust/issues/73448>", + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, + reference: "issue #120362 <https://github.com/rust-lang/rust/issues/120362>", }; } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index eed35326c45..8b7e82d2113 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -1,6 +1,4 @@ #![feature(min_specialization)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 5bfffc5d911..6d578c97f3f 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -76,7 +76,6 @@ enum LLVMRustAttribute { SanitizeMemory = 22, NonLazyBind = 23, OptimizeNone = 24, - ReturnsTwice = 25, ReadNone = 26, SanitizeHWAddress = 28, WillReturn = 29, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 0df7b7eed11..a2dfebec594 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -250,8 +250,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { return Attribute::NonLazyBind; case OptimizeNone: return Attribute::OptimizeNone; - case ReturnsTwice: - return Attribute::ReturnsTwice; case ReadNone: return Attribute::ReadNone; case SanitizeHWAddress: diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index ca0aec71052..6a570c97c88 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(rustdoc_internals)] diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index e3464cb8a2d..1a78f9f0f86 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -38,9 +38,6 @@ //! debugging, you can make changes inside those crates and quickly run main.rs //! to read the debug logs. -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] - use std::env::{self, VarError}; use std::fmt::{self, Display}; use std::io::{self, IsTerminal}; diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index c029b931e7d..3a5f289559e 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -89,10 +89,7 @@ impl SubdiagnosticDeriveBuilder { gen impl rustc_errors::AddToDiagnostic for @Self { fn add_to_diagnostic_with<__F>(self, #diag: &mut rustc_errors::Diagnostic, #f: __F) where - __F: core::ops::Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage - ) -> rustc_errors::SubdiagnosticMessage, + __F: rustc_errors::SubdiagnosticMessageOp, { #implementation } diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 9e85a59b5b9..af65c908ee6 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -6,8 +6,6 @@ #![feature(proc_macro_span)] #![feature(proc_macro_tracked_env)] #![allow(rustc::default_hash_types)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] use synstructure::decl_derive; diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index bb02a8a1e47..c18f0e7b7b9 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -534,7 +534,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { ) -> Option<CrateNum> { self.used_extern_options.insert(name); match self.maybe_resolve_crate(name, dep_kind, None) { - Ok(cnum) => Some(cnum), + Ok(cnum) => { + self.cstore.set_used_recursively(cnum); + Some(cnum) + } Err(err) => { let missing_core = self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err(); @@ -1067,6 +1070,16 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> { self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok() } + + pub fn unload_unused_crates(&mut self) { + for opt_cdata in &mut self.cstore.metas { + if let Some(cdata) = opt_cdata + && !cdata.used() + { + *opt_cdata = None; + } + } + } } fn global_allocator_spans(krate: &ast::Crate) -> Vec<Span> { diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 471425e8017..2e7130f3565 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -15,8 +15,6 @@ #![feature(try_blocks)] #![feature(never_type)] #![allow(rustc::potential_query_instability)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] extern crate proc_macro; diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 20e3ae3ba94..11cb1bb6d9e 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -106,6 +106,8 @@ pub(crate) struct CrateMetadata { private_dep: bool, /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`. host_hash: Option<Svh>, + /// The crate was used non-speculatively. + used: bool, /// Additional data used for decoding `HygieneData` (e.g. `SyntaxContext` /// and `ExpnId`). @@ -1811,6 +1813,7 @@ impl CrateMetadata { source: Lrc::new(source), private_dep, host_hash, + used: false, extern_crate: None, hygiene_context: Default::default(), def_key_cache: Default::default(), @@ -1860,6 +1863,10 @@ impl CrateMetadata { self.private_dep &= private_dep; } + pub(crate) fn used(&self) -> bool { + self.used + } + pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> { self.root.required_panic_strategy } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 0b352a02b64..7cd2f58779f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -26,6 +26,7 @@ use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; use std::any::Any; +use std::mem; use super::{Decodable, DecodeContext, DecodeIterator}; @@ -576,12 +577,24 @@ impl CStore { self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess) } + pub fn set_used_recursively(&mut self, cnum: CrateNum) { + let cmeta = self.get_crate_data_mut(cnum); + if !cmeta.used { + cmeta.used = true; + let dependencies = mem::take(&mut cmeta.dependencies); + for &dep_cnum in &dependencies { + self.set_used_recursively(dep_cnum); + } + self.get_crate_data_mut(cnum).dependencies = dependencies; + } + } + pub(crate) fn update_extern_crate(&mut self, cnum: CrateNum, extern_crate: ExternCrate) { let cmeta = self.get_crate_data_mut(cnum); if cmeta.update_extern_crate(extern_crate) { // Propagate the extern crate info to dependencies if it was updated. let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate }; - let dependencies = std::mem::take(&mut cmeta.dependencies); + let dependencies = mem::take(&mut cmeta.dependencies); for &dep_cnum in &dependencies { self.update_extern_crate(dep_cnum, extern_crate); } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 542caf86223..79aa9a547f7 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -386,7 +386,7 @@ impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> { } } -// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would +// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. macro_rules! record { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ @@ -398,7 +398,7 @@ macro_rules! record { }}; } -// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_value($value))`, which would +// Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_array($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. macro_rules! record_array { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ @@ -1388,13 +1388,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if should_encode_fn_sig(def_kind) { record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } - // FIXME: Some anonymous constants produced by `#[rustc_legacy_const_generics]` - // do not have corresponding HIR nodes, so some queries usually making sense for - // anonymous constants will not work on them and panic. It's not clear whether it - // can cause any observable issues or not. - let anon_const_without_hir = def_kind == DefKind::AnonConst - && tcx.opt_hir_node(tcx.local_def_id_to_hir_id(local_id)).is_none(); - if should_encode_generics(def_kind) && !anon_const_without_hir { + if should_encode_generics(def_kind) { let g = tcx.generics_of(def_id); record!(self.tables.generics_of[def_id] <- g); record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id)); @@ -1408,7 +1402,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } } - if should_encode_type(tcx, local_id, def_kind) && !anon_const_without_hir { + if should_encode_type(tcx, local_id, def_kind) { record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id)); } if should_encode_constness(def_kind) { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index ba1ae46626b..bf72aac1033 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -158,22 +158,14 @@ impl<'tcx> TyCtxt<'tcx> { } /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. - pub fn opt_hir_node(self, id: HirId) -> Option<Node<'tcx>> { - let owner = self.hir_owner_nodes(id.owner); - let node = owner.nodes[id.local_id].as_ref()?; - Some(node.node) - } - - /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. #[inline] pub fn opt_hir_node_by_def_id(self, id: LocalDefId) -> Option<Node<'tcx>> { - self.opt_hir_node(self.opt_local_def_id_to_hir_id(id)?) + Some(self.hir_node(self.opt_local_def_id_to_hir_id(id)?)) } - /// Retrieves the `hir::Node` corresponding to `id`, panicking if it cannot be found. - #[track_caller] + /// Retrieves the `hir::Node` corresponding to `id`. pub fn hir_node(self, id: HirId) -> Node<'tcx> { - self.opt_hir_node(id).unwrap_or_else(|| bug!("couldn't find HIR node for hir id {id:?}")) + self.hir_owner_nodes(id.owner).nodes[id.local_id].node } /// Retrieves the `hir::Node` corresponding to `id`, panicking if it cannot be found. @@ -230,10 +222,13 @@ impl<'hir> Map<'hir> { /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`]. pub fn opt_parent_id(self, id: HirId) -> Option<HirId> { if id.local_id == ItemLocalId::from_u32(0) { + // FIXME: This function never returns `None` right now, and the parent chain end is + // determined by checking for `parent(id) == id`. This function should return `None` + // for the crate root instead. Some(self.tcx.hir_owner_parent(id.owner)) } else { let owner = self.tcx.hir_owner_nodes(id.owner); - let node = owner.nodes[id.local_id].as_ref()?; + let node = &owner.nodes[id.local_id]; let hir_id = HirId { owner: id.owner, local_id: node.parent }; // HIR indexing should have checked that. debug_assert_ne!(id.local_id, node.parent); @@ -252,11 +247,12 @@ impl<'hir> Map<'hir> { } pub fn find_parent(self, hir_id: HirId) -> Option<Node<'hir>> { - self.tcx.opt_hir_node(self.opt_parent_id(hir_id)?) + Some(self.tcx.hir_node(self.opt_parent_id(hir_id)?)) } pub fn get_if_local(self, id: DefId) -> Option<Node<'hir>> { - id.as_local().and_then(|id| self.tcx.opt_hir_node(self.tcx.opt_local_def_id_to_hir_id(id)?)) + id.as_local() + .and_then(|id| Some(self.tcx.hir_node(self.tcx.opt_local_def_id_to_hir_id(id)?))) } pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> { @@ -285,20 +281,12 @@ impl<'hir> Map<'hir> { #[track_caller] pub fn fn_decl_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { - if let Some(node) = self.tcx.opt_hir_node(hir_id) { - node.fn_decl() - } else { - bug!("no node for hir_id `{}`", hir_id) - } + self.tcx.hir_node(hir_id).fn_decl() } #[track_caller] pub fn fn_sig_by_hir_id(self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> { - if let Some(node) = self.tcx.opt_hir_node(hir_id) { - node.fn_sig() - } else { - bug!("no node for hir_id `{}`", hir_id) - } + self.tcx.hir_node(hir_id).fn_sig() } #[track_caller] @@ -317,10 +305,7 @@ impl<'hir> Map<'hir> { /// item (possibly associated), a closure, or a `hir::AnonConst`. pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId { let parent = self.parent_id(hir_id); - assert!( - self.tcx.opt_hir_node(parent).is_some_and(|n| is_body_owner(n, hir_id)), - "{hir_id:?}" - ); + assert!(is_body_owner(self.tcx.hir_node(parent), hir_id), "{hir_id:?}"); parent } @@ -572,7 +557,7 @@ impl<'hir> Map<'hir> { /// until the crate root is reached. Prefer this over your own loop using `parent_id`. #[inline] pub fn parent_iter(self, current_id: HirId) -> impl Iterator<Item = (HirId, Node<'hir>)> { - self.parent_id_iter(current_id).filter_map(move |id| Some((id, self.tcx.opt_hir_node(id)?))) + self.parent_id_iter(current_id).map(move |id| (id, self.tcx.hir_node(id))) } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` @@ -624,7 +609,7 @@ impl<'hir> Map<'hir> { pub fn get_return_block(self, id: HirId) -> Option<HirId> { let mut iter = self.parent_iter(id).peekable(); let mut ignore_tail = false; - if let Some(Node::Expr(Expr { kind: ExprKind::Ret(_), .. })) = self.tcx.opt_hir_node(id) { + if let Node::Expr(Expr { kind: ExprKind::Ret(_), .. }) = self.tcx.hir_node(id) { // When dealing with `return` statements, we don't care about climbing only tail // expressions. ignore_tail = true; @@ -777,8 +762,8 @@ impl<'hir> Map<'hir> { } pub fn expect_variant(self, id: HirId) -> &'hir Variant<'hir> { - match self.tcx.opt_hir_node(id) { - Some(Node::Variant(variant)) => variant, + match self.tcx.hir_node(id) { + Node::Variant(variant) => variant, _ => bug!("expected variant, found {}", self.node_to_string(id)), } } @@ -796,18 +781,18 @@ impl<'hir> Map<'hir> { } pub fn expect_expr(self, id: HirId) -> &'hir Expr<'hir> { - match self.tcx.opt_hir_node(id) { - Some(Node::Expr(expr)) => expr, + match self.tcx.hir_node(id) { + Node::Expr(expr) => expr, _ => bug!("expected expr, found {}", self.node_to_string(id)), } } #[inline] fn opt_ident(self, id: HirId) -> Option<Ident> { - match self.tcx.opt_hir_node(id)? { + match self.tcx.hir_node(id) { Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident), // A `Ctor` doesn't have an identifier itself, but its parent - // struct/variant does. Compare with `hir::Map::opt_span`. + // struct/variant does. Compare with `hir::Map::span`. Node::Ctor(..) => match self.find_parent(id)? { Node::Item(item) => Some(item.ident), Node::Variant(variant) => Some(variant.ident), @@ -845,11 +830,6 @@ impl<'hir> Map<'hir> { /// Gets the span of the definition of the specified HIR node. /// This is used by `tcx.def_span`. pub fn span(self, hir_id: HirId) -> Span { - self.opt_span(hir_id) - .unwrap_or_else(|| bug!("hir::map::Map::span: id not in map: {:?}", hir_id)) - } - - pub fn opt_span(self, hir_id: HirId) -> Option<Span> { fn until_within(outer: Span, end: Span) -> Span { if let Some(end) = end.find_ancestor_inside(outer) { outer.with_hi(end.hi()) @@ -873,7 +853,7 @@ impl<'hir> Map<'hir> { } } - let span = match self.tcx.opt_hir_node(hir_id)? { + let span = match self.tcx.hir_node(hir_id) { // Function-like. Node::Item(Item { kind: ItemKind::Fn(sig, ..), span: outer_span, .. }) | Node::TraitItem(TraitItem { @@ -945,7 +925,7 @@ impl<'hir> Map<'hir> { ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()), _ => named_span(item.span, item.ident, None), }, - Node::Ctor(_) => return self.opt_span(self.parent_id(hir_id)), + Node::Ctor(_) => return self.span(self.parent_id(hir_id)), Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl_span, .. }), span, @@ -957,7 +937,7 @@ impl<'hir> Map<'hir> { _ => self.span_with_body(hir_id), }; debug_assert_eq!(span.ctxt(), self.span_with_body(hir_id).ctxt()); - Some(span) + span } /// Like `hir.span()`, but includes the body of items @@ -994,6 +974,9 @@ impl<'hir> Map<'hir> { Node::Infer(i) => i.span, Node::Local(local) => local.span, Node::Crate(item) => item.spans.inner_span, + Node::WhereBoundPredicate(pred) => pred.span, + Node::ArrayLenInfer(inf) => inf.span, + Node::Err(span) => *span, } } @@ -1057,8 +1040,8 @@ impl<'hir> Map<'hir> { } impl<'hir> intravisit::Map<'hir> for Map<'hir> { - fn find(&self, hir_id: HirId) -> Option<Node<'hir>> { - self.tcx.opt_hir_node(hir_id) + fn hir_node(&self, hir_id: HirId) -> Node<'hir> { + self.tcx.hir_node(hir_id) } fn body(&self, id: BodyId) -> &'hir Body<'hir> { @@ -1175,8 +1158,8 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { let span_str = || map.tcx.sess.source_map().span_to_snippet(map.span(id)).unwrap_or_default(); let node_str = |prefix| format!("{id} ({prefix} `{}`)", span_str()); - match map.tcx.opt_hir_node(id) { - Some(Node::Item(item)) => { + match map.tcx.hir_node(id) { + Node::Item(item) => { let item_str = match item.kind { ItemKind::ExternCrate(..) => "extern crate", ItemKind::Use(..) => "use", @@ -1204,10 +1187,10 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { }; format!("{id} ({item_str} {})", path_str(item.owner_id.def_id)) } - Some(Node::ForeignItem(item)) => { + Node::ForeignItem(item) => { format!("{id} (foreign item {})", path_str(item.owner_id.def_id)) } - Some(Node::ImplItem(ii)) => { + Node::ImplItem(ii) => { let kind = match ii.kind { ImplItemKind::Const(..) => "assoc const", ImplItemKind::Fn(..) => "method", @@ -1215,7 +1198,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { }; format!("{id} ({kind} `{}` in {})", ii.ident, path_str(ii.owner_id.def_id)) } - Some(Node::TraitItem(ti)) => { + Node::TraitItem(ti) => { let kind = match ti.kind { TraitItemKind::Const(..) => "assoc constant", TraitItemKind::Fn(..) => "trait method", @@ -1224,38 +1207,40 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String { format!("{id} ({kind} `{}` in {})", ti.ident, path_str(ti.owner_id.def_id)) } - Some(Node::Variant(variant)) => { + Node::Variant(variant) => { format!("{id} (variant `{}` in {})", variant.ident, path_str(variant.def_id)) } - Some(Node::Field(field)) => { + Node::Field(field) => { format!("{id} (field `{}` in {})", field.ident, path_str(field.def_id)) } - Some(Node::AnonConst(_)) => node_str("const"), - Some(Node::ConstBlock(_)) => node_str("const"), - Some(Node::Expr(_)) => node_str("expr"), - Some(Node::ExprField(_)) => node_str("expr field"), - Some(Node::Stmt(_)) => node_str("stmt"), - Some(Node::PathSegment(_)) => node_str("path segment"), - Some(Node::Ty(_)) => node_str("type"), - Some(Node::TypeBinding(_)) => node_str("type binding"), - Some(Node::TraitRef(_)) => node_str("trait ref"), - Some(Node::Pat(_)) => node_str("pat"), - Some(Node::PatField(_)) => node_str("pattern field"), - Some(Node::Param(_)) => node_str("param"), - Some(Node::Arm(_)) => node_str("arm"), - Some(Node::Block(_)) => node_str("block"), - Some(Node::Infer(_)) => node_str("infer"), - Some(Node::Local(_)) => node_str("local"), - Some(Node::Ctor(ctor)) => format!( + Node::AnonConst(_) => node_str("const"), + Node::ConstBlock(_) => node_str("const"), + Node::Expr(_) => node_str("expr"), + Node::ExprField(_) => node_str("expr field"), + Node::Stmt(_) => node_str("stmt"), + Node::PathSegment(_) => node_str("path segment"), + Node::Ty(_) => node_str("type"), + Node::TypeBinding(_) => node_str("type binding"), + Node::TraitRef(_) => node_str("trait ref"), + Node::Pat(_) => node_str("pat"), + Node::PatField(_) => node_str("pattern field"), + Node::Param(_) => node_str("param"), + Node::Arm(_) => node_str("arm"), + Node::Block(_) => node_str("block"), + Node::Infer(_) => node_str("infer"), + Node::Local(_) => node_str("local"), + Node::Ctor(ctor) => format!( "{id} (ctor {})", ctor.ctor_def_id().map_or("<missing path>".into(), |def_id| path_str(def_id)), ), - Some(Node::Lifetime(_)) => node_str("lifetime"), - Some(Node::GenericParam(param)) => { + Node::Lifetime(_) => node_str("lifetime"), + Node::GenericParam(param) => { format!("{id} (generic_param {})", path_str(param.def_id)) } - Some(Node::Crate(..)) => String::from("(root_crate)"), - None => format!("{id} (unknown node)"), + Node::Crate(..) => String::from("(root_crate)"), + Node::WhereBoundPredicate(_) => node_str("where bound predicate"), + Node::ArrayLenInfer(_) => node_str("array len infer"), + Node::Err(_) => node_str("error"), } } diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 94191df30a5..f66cd2370e3 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -12,7 +12,7 @@ use rustc_data_structures::sync::{try_par_for_each_in, DynSend, DynSync}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::*; -use rustc_span::{ErrorGuaranteed, ExpnId, DUMMY_SP}; +use rustc_span::{ErrorGuaranteed, ExpnId}; /// Gather the LocalDefId for each item-like within a module, including items contained within /// bodies. The Ids are in visitor order. This is used to partition a pass between modules. @@ -148,10 +148,7 @@ pub fn provide(providers: &mut Providers) { providers.hir_attrs = |tcx, id| { tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs) }; - providers.def_span = |tcx, def_id| { - let hir_id = tcx.local_def_id_to_hir_id(def_id); - tcx.hir().opt_span(hir_id).unwrap_or(DUMMY_SP) - }; + providers.def_span = |tcx, def_id| tcx.hir().span(tcx.local_def_id_to_hir_id(def_id)); providers.def_ident_span = |tcx, def_id| { let hir_id = tcx.local_def_id_to_hir_id(def_id); tcx.hir().opt_ident_span(hir_id) diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index c35799ef47f..63c0ebd5f6b 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -194,33 +194,37 @@ impl<'tcx> UnifyValue for ConstVariableValue<'tcx> { /// values for the effect inference variable #[derive(Clone, Copy, Debug)] pub enum EffectVarValue<'tcx> { - /// The host effect is on, enabling access to syscalls, filesystem access, etc. - Host, - /// The host effect is off. Execution is restricted to const operations only. - NoHost, - Const(ty::Const<'tcx>), + Unknown, + Known(ty::Const<'tcx>), } impl<'tcx> EffectVarValue<'tcx> { - pub fn as_const(self, tcx: TyCtxt<'tcx>) -> ty::Const<'tcx> { + pub fn known(self) -> Option<ty::Const<'tcx>> { match self { - EffectVarValue::Host => tcx.consts.true_, - EffectVarValue::NoHost => tcx.consts.false_, - EffectVarValue::Const(c) => c, + EffectVarValue::Unknown => None, + EffectVarValue::Known(value) => Some(value), + } + } + + pub fn is_unknown(self) -> bool { + match self { + EffectVarValue::Unknown => true, + EffectVarValue::Known(_) => false, } } } impl<'tcx> UnifyValue for EffectVarValue<'tcx> { - type Error = (EffectVarValue<'tcx>, EffectVarValue<'tcx>); + type Error = NoError; fn unify_values(value1: &Self, value2: &Self) -> Result<Self, Self::Error> { - match (value1, value2) { - (EffectVarValue::Host, EffectVarValue::Host) => Ok(EffectVarValue::Host), - (EffectVarValue::NoHost, EffectVarValue::NoHost) => Ok(EffectVarValue::NoHost), - (EffectVarValue::NoHost | EffectVarValue::Host, _) - | (_, EffectVarValue::NoHost | EffectVarValue::Host) => Err((*value1, *value2)), - (EffectVarValue::Const(_), EffectVarValue::Const(_)) => { - bug!("equating two const variables, both of which have known values") + match (*value1, *value2) { + (EffectVarValue::Unknown, EffectVarValue::Unknown) => Ok(EffectVarValue::Unknown), + (EffectVarValue::Unknown, EffectVarValue::Known(val)) + | (EffectVarValue::Known(val), EffectVarValue::Unknown) => { + Ok(EffectVarValue::Known(val)) + } + (EffectVarValue::Known(_), EffectVarValue::Known(_)) => { + bug!("equating known inference variables: {value1:?} {value2:?}") } } } @@ -229,7 +233,7 @@ impl<'tcx> UnifyValue for EffectVarValue<'tcx> { #[derive(PartialEq, Copy, Clone, Debug)] pub struct EffectVidKey<'tcx> { pub vid: ty::EffectVid, - pub phantom: PhantomData<EffectVarValue<'tcx>>, + pub phantom: PhantomData<ty::Const<'tcx>>, } impl<'tcx> From<ty::EffectVid> for EffectVidKey<'tcx> { @@ -239,7 +243,7 @@ impl<'tcx> From<ty::EffectVid> for EffectVidKey<'tcx> { } impl<'tcx> UnifyKey for EffectVidKey<'tcx> { - type Value = Option<EffectVarValue<'tcx>>; + type Value = EffectVarValue<'tcx>; #[inline] fn index(&self) -> u32 { self.vid.as_u32() diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index ddfb2ece39f..2aaece1060a 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -30,6 +30,7 @@ #![feature(assert_matches)] #![feature(box_patterns)] #![feature(core_intrinsics)] +#![feature(const_type_name)] #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] #![feature(coroutines)] @@ -48,7 +49,7 @@ #![feature(associated_type_bounds)] #![feature(rustc_attrs)] #![feature(control_flow_enum)] -#![cfg_attr(not(bootstrap), feature(trait_upcasting))] +#![feature(trait_upcasting)] #![feature(try_blocks)] #![feature(decl_macro)] #![feature(extract_if)] @@ -57,8 +58,10 @@ #![feature(const_option)] #![feature(ptr_alignment_type)] #![feature(macro_metavar_expr)] -#![allow(rustc::potential_query_instability)] #![allow(internal_features)] +#![allow(rustc::potential_query_instability)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #[macro_use] extern crate bitflags; diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index e11c9371118..7d6d39a2a8a 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -74,35 +74,32 @@ bitflags! { /// `#[used]`: indicates that LLVM can't eliminate this function (but the /// linker can!). const USED = 1 << 9; - /// `#[ffi_returns_twice]`, indicates that an extern function can return - /// multiple times - const FFI_RETURNS_TWICE = 1 << 10; /// `#[track_caller]`: allow access to the caller location - const TRACK_CALLER = 1 << 11; + const TRACK_CALLER = 1 << 10; /// #[ffi_pure]: applies clang's `pure` attribute to a foreign function /// declaration. - const FFI_PURE = 1 << 12; + const FFI_PURE = 1 << 11; /// #[ffi_const]: applies clang's `const` attribute to a foreign function /// declaration. - const FFI_CONST = 1 << 13; + const FFI_CONST = 1 << 12; /// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a /// function as an entry function from Non-Secure code. - const CMSE_NONSECURE_ENTRY = 1 << 14; + const CMSE_NONSECURE_ENTRY = 1 << 13; /// `#[coverage(off)]`: indicates that the function should be ignored by /// the MIR `InstrumentCoverage` pass and not added to the coverage map /// during codegen. - const NO_COVERAGE = 1 << 15; + const NO_COVERAGE = 1 << 14; /// `#[used(linker)]`: /// indicates that neither LLVM nor the linker will eliminate this function. - const USED_LINKER = 1 << 16; + const USED_LINKER = 1 << 15; /// `#[rustc_deallocator]`: a hint to LLVM that the function only deallocates memory. - const DEALLOCATOR = 1 << 17; + const DEALLOCATOR = 1 << 16; /// `#[rustc_reallocator]`: a hint to LLVM that the function only reallocates memory. - const REALLOCATOR = 1 << 18; + const REALLOCATOR = 1 << 17; /// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory. - const ALLOCATOR_ZEROED = 1 << 19; + const ALLOCATOR_ZEROED = 1 << 18; /// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function. - const NO_BUILTINS = 1 << 20; + const NO_BUILTINS = 1 << 19; } } rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 9475b89aa15..e22d5228628 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -140,8 +140,12 @@ fn to_profiler_name(type_name: &'static str) -> &'static str { /// loop that goes over each available MIR and applies `run_pass`. pub trait MirPass<'tcx> { fn name(&self) -> &'static str { - let name = std::any::type_name::<Self>(); - if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name } + // FIXME Simplify the implementation once more `str` methods get const-stable. + // See copypaste in `MirLint` + const { + let name = std::any::type_name::<Self>(); + crate::util::common::c_name(name) + } } fn profiler_name(&self) -> &'static str { diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 6f587fdd53c..b601b465668 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -907,6 +907,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { NullOp::SizeOf => write!(fmt, "SizeOf({t})"), NullOp::AlignOf => write!(fmt, "AlignOf({t})"), NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t}, {fields:?})"), + NullOp::DebugAssertions => write!(fmt, "cfg!(debug_assertions)"), } } ThreadLocalRef(did) => ty::tls::with(|tcx| { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 98642adc190..90b6df1dd1f 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -189,7 +189,7 @@ pub struct BorrowCheckResult<'tcx> { /// The result of the `mir_const_qualif` query. /// -/// Each field (except `error_occurred`) corresponds to an implementer of the `Qualif` trait in +/// Each field (except `tainted_by_errors`) corresponds to an implementer of the `Qualif` trait in /// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each /// `Qualif`. #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)] @@ -197,7 +197,6 @@ pub struct ConstQualifs { pub has_mut_interior: bool, pub needs_drop: bool, pub needs_non_const_drop: bool, - pub custom_eq: bool, pub tainted_by_errors: Option<ErrorGuaranteed>, } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index ca56e1fd92c..40af453f6ce 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1361,6 +1361,8 @@ pub enum NullOp<'tcx> { AlignOf, /// Returns the offset of a field OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>), + /// cfg!(debug_assertions), but expanded in codegen + DebugAssertions, } #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 4780042a510..5bc151de659 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -194,6 +194,7 @@ impl<'tcx> Rvalue<'tcx> { Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { tcx.types.usize } + Rvalue::NullaryOp(NullOp::DebugAssertions, _) => tcx.types.bool, Rvalue::Aggregate(ref ak, ref ops) => match **ak { AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64), AggregateKind::Tuple => { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 0fed4ccc62a..e1e5d68148f 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -1038,7 +1038,6 @@ impl<'tcx> PatRangeBoundary<'tcx> { a.partial_cmp(&b) } ty::Int(ity) => { - use rustc_middle::ty::layout::IntegerExt; let size = rustc_target::abi::Integer::from_int_ty(&tcx, *ity).size(); let a = size.sign_extend(a) as i128; let b = size.sign_extend(b) as i128; diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index b4054f8ff5e..fd5302dc75b 100644 --- a/compiler/rustc_middle/src/traits/util.rs +++ b/compiler/rustc_middle/src/traits/util.rs @@ -1,46 +1,60 @@ use rustc_data_structures::fx::FxHashSet; -use crate::ty::{PolyTraitRef, TyCtxt}; +use crate::ty::{Clause, PolyTraitRef, ToPolyTraitRef, ToPredicate, TyCtxt}; -/// Given a PolyTraitRef, get the PolyTraitRefs of the trait's (transitive) supertraits. +/// Given a [`PolyTraitRef`], get the [`Clause`]s implied by the trait's definition. +/// /// This only exists in `rustc_middle` because the more powerful elaborator depends on /// `rustc_infer` for elaborating outlives bounds -- this should only be used for pretty /// printing. +pub fn super_predicates_for_pretty_printing<'tcx>( + tcx: TyCtxt<'tcx>, + trait_ref: PolyTraitRef<'tcx>, +) -> impl Iterator<Item = Clause<'tcx>> { + let clause = trait_ref.to_predicate(tcx); + Elaborator { tcx, visited: FxHashSet::from_iter([clause]), stack: vec![clause] } +} + +/// Like [`super_predicates_for_pretty_printing`], except it only returns traits and filters out +/// all other [`Clause`]s. pub fn supertraits_for_pretty_printing<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: PolyTraitRef<'tcx>, ) -> impl Iterator<Item = PolyTraitRef<'tcx>> { - Elaborator { tcx, visited: FxHashSet::from_iter([trait_ref]), stack: vec![trait_ref] } + super_predicates_for_pretty_printing(tcx, trait_ref).filter_map(|clause| { + clause.as_trait_clause().map(|trait_clause| trait_clause.to_poly_trait_ref()) + }) } struct Elaborator<'tcx> { tcx: TyCtxt<'tcx>, - visited: FxHashSet<PolyTraitRef<'tcx>>, - stack: Vec<PolyTraitRef<'tcx>>, + visited: FxHashSet<Clause<'tcx>>, + stack: Vec<Clause<'tcx>>, } impl<'tcx> Elaborator<'tcx> { fn elaborate(&mut self, trait_ref: PolyTraitRef<'tcx>) { - let supertrait_refs = self - .tcx - .super_predicates_of(trait_ref.def_id()) - .predicates - .into_iter() - .flat_map(|(pred, _)| pred.subst_supertrait(self.tcx, &trait_ref).as_trait_clause()) - .map(|t| t.map_bound(|pred| pred.trait_ref)) - .filter(|supertrait_ref| self.visited.insert(*supertrait_ref)); - - self.stack.extend(supertrait_refs); + let super_predicates = + self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map( + |&(pred, _)| { + let clause = pred.subst_supertrait(self.tcx, &trait_ref); + self.visited.insert(clause).then_some(clause) + }, + ); + + self.stack.extend(super_predicates); } } impl<'tcx> Iterator for Elaborator<'tcx> { - type Item = PolyTraitRef<'tcx>; + type Item = Clause<'tcx>; - fn next(&mut self) -> Option<PolyTraitRef<'tcx>> { - if let Some(trait_ref) = self.stack.pop() { - self.elaborate(trait_ref); - Some(trait_ref) + fn next(&mut self) -> Option<Clause<'tcx>> { + if let Some(clause) = self.stack.pop() { + if let Some(trait_clause) = clause.as_trait_clause() { + self.elaborate(trait_clause.to_poly_trait_ref()); + } + Some(clause) } else { None } diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs index a2794a100f1..417f1932c6f 100644 --- a/compiler/rustc_middle/src/ty/_match.rs +++ b/compiler/rustc_middle/src/ty/_match.rs @@ -55,7 +55,7 @@ impl<'tcx> TypeRelation<'tcx> for MatchAgainstFreshVars<'tcx> { fn regions( &mut self, a: ty::Region<'tcx>, - b: ty::Region<'tcx>, + _b: ty::Region<'tcx>, ) -> RelateResult<'tcx, ty::Region<'tcx>> { Ok(a) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 14d2a93e167..b747f0a4fb6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1193,7 +1193,7 @@ impl<'tcx> TyCtxt<'tcx> { let (suitable_region_binding_scope, bound_region) = loop { let def_id = match region.kind() { ty::ReLateParam(fr) => fr.bound_region.get_id()?.as_local()?, - ty::ReEarlyParam(ebr) => ebr.def_id.expect_local(), + ty::ReEarlyParam(ebr) => ebr.def_id.as_local()?, _ => return None, // not a free region }; let scope = self.local_parent(def_id); diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 8678f388298..13cc5cbed44 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -98,6 +98,7 @@ impl<'tcx, T> IsSuggestable<'tcx> for T where T: TypeVisitable<TyCtxt<'tcx>> + TypeFoldable<TyCtxt<'tcx>>, { + #[tracing::instrument(level = "debug", skip(tcx))] fn is_suggestable(self, tcx: TyCtxt<'tcx>, infer_suggestable: bool) -> bool { self.visit_with(&mut IsSuggestableVisitor { tcx, infer_suggestable }).is_continue() } @@ -533,6 +534,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> { match c.kind() { ConstKind::Infer(InferConst::Var(_)) if self.infer_suggestable => {} + // effect variables are always suggestable, because they are not visible + ConstKind::Infer(InferConst::EffectVar(_)) => {} + ConstKind::Infer(..) | ConstKind::Bound(..) | ConstKind::Placeholder(..) diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 9c1f4b20d2c..8848d216f5b 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -765,7 +765,14 @@ fn polymorphize<'tcx>( let def_id = instance.def_id(); let upvars_ty = match tcx.type_of(def_id).skip_binder().kind() { ty::Closure(..) => Some(args.as_closure().tupled_upvars_ty()), - ty::Coroutine(..) => Some(args.as_coroutine().tupled_upvars_ty()), + ty::Coroutine(..) => { + assert_eq!( + args.as_coroutine().kind_ty(), + tcx.types.unit, + "polymorphization does not support coroutines from async closures" + ); + Some(args.as_coroutine().tupled_upvars_ty()) + } _ => None, }; let has_upvars = upvars_ty.is_some_and(|ty| !ty.tuple_fields().is_empty()); diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index c0bfd2380ad..f90703e6184 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1,7 +1,7 @@ use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::query::IntoQueryParam; use crate::query::Providers; -use crate::traits::util::supertraits_for_pretty_printing; +use crate::traits::util::{super_predicates_for_pretty_printing, supertraits_for_pretty_printing}; use crate::ty::GenericArgKind; use crate::ty::{ ConstInt, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable, @@ -1255,8 +1255,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // Generate the main trait ref, including associated types. let mut first = true; - if let Some(principal) = predicates.principal() { - self.wrap_binder(&principal, |principal, cx| { + if let Some(bound_principal) = predicates.principal() { + self.wrap_binder(&bound_principal, |principal, cx| { define_scoped_cx!(cx); p!(print_def_path(principal.def_id, &[])); @@ -1281,19 +1281,53 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { // HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`, // in order to place the projections inside the `<...>`. if !resugared { - // Use a type that can't appear in defaults of type parameters. - let dummy_cx = Ty::new_fresh(cx.tcx(), 0); - let principal = principal.with_self_ty(cx.tcx(), dummy_cx); + let principal_with_self = + principal.with_self_ty(cx.tcx(), cx.tcx().types.trait_object_dummy_self); let args = cx .tcx() - .generics_of(principal.def_id) - .own_args_no_defaults(cx.tcx(), principal.args); - - let mut projections: Vec<_> = predicates.projection_bounds().collect(); - projections.sort_by_cached_key(|proj| { - cx.tcx().item_name(proj.item_def_id()).to_string() - }); + .generics_of(principal_with_self.def_id) + .own_args_no_defaults(cx.tcx(), principal_with_self.args); + + let bound_principal_with_self = bound_principal + .with_self_ty(cx.tcx(), cx.tcx().types.trait_object_dummy_self); + + let super_projections: Vec<_> = + super_predicates_for_pretty_printing(cx.tcx(), bound_principal_with_self) + .filter_map(|clause| clause.as_projection_clause()) + .collect(); + + let mut projections: Vec<_> = predicates + .projection_bounds() + .filter(|&proj| { + // Filter out projections that are implied by the super predicates. + let proj_is_implied = super_projections.iter().any(|&super_proj| { + let super_proj = super_proj.map_bound(|super_proj| { + ty::ExistentialProjection::erase_self_ty(cx.tcx(), super_proj) + }); + + // This function is sometimes called on types with erased and + // anonymized regions, but the super projections can still + // contain named regions. So we erase and anonymize everything + // here to compare the types modulo regions below. + let proj = cx.tcx().erase_regions(proj); + let proj = cx.tcx().anonymize_bound_vars(proj); + let super_proj = cx.tcx().erase_regions(super_proj); + let super_proj = cx.tcx().anonymize_bound_vars(super_proj); + + proj == super_proj + }); + !proj_is_implied + }) + .map(|proj| { + // Skip the binder, because we don't want to print the binder in + // front of the associated item. + proj.skip_binder() + }) + .collect(); + + projections + .sort_by_cached_key(|proj| cx.tcx().item_name(proj.def_id).to_string()); if !args.is_empty() || !projections.is_empty() { p!(generic_delimiters(|cx| { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 927924452f9..f592acd4b6f 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1052,6 +1052,7 @@ impl<'tcx, T> Binder<'tcx, T> { where T: TypeVisitable<TyCtxt<'tcx>>, { + // `self.value` is equivalent to `self.skip_binder()` if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } } @@ -1312,6 +1313,7 @@ impl<'tcx> PolyFnSig<'tcx> { self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs()) } #[inline] + #[track_caller] pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound_ref(|fn_sig| fn_sig.inputs()[index]) } @@ -2277,12 +2279,12 @@ impl<'tcx> Ty<'tcx> { } /// Returns the type of metadata for (potentially fat) pointers to this type, - /// and a boolean signifying if this is conditional on this type being `Sized`. - pub fn ptr_metadata_ty( + /// or the struct tail if the metadata type cannot be determined. + pub fn ptr_metadata_ty_or_tail( self, tcx: TyCtxt<'tcx>, normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, - ) -> (Ty<'tcx>, bool) { + ) -> Result<Ty<'tcx>, Ty<'tcx>> { let tail = tcx.struct_tail_with_normalize(self, normalize, || {}); match tail.kind() { // Sized types @@ -2305,31 +2307,47 @@ impl<'tcx> Ty<'tcx> { | ty::Error(_) // Extern types have metadata = (). | ty::Foreign(..) - // `dyn*` has no metadata + // `dyn*` has metadata = (). | ty::Dynamic(_, _, ty::DynStar) - // If returned by `struct_tail_without_normalization` this is a unit struct + // If returned by `struct_tail_with_normalize` this is a unit struct // without any fields, or not a struct, and therefore is Sized. | ty::Adt(..) - // If returned by `struct_tail_without_normalization` this is the empty tuple, + // If returned by `struct_tail_with_normalize` this is the empty tuple, // a.k.a. unit type, which is Sized - | ty::Tuple(..) => (tcx.types.unit, false), + | ty::Tuple(..) => Ok(tcx.types.unit), + + ty::Str | ty::Slice(_) => Ok(tcx.types.usize), - ty::Str | ty::Slice(_) => (tcx.types.usize, false), ty::Dynamic(_, _, ty::Dyn) => { let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None); - (tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()]), false) - }, + Ok(tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()])) + } - // type parameters only have unit metadata if they're sized, so return true - // to make sure we double check this during confirmation - ty::Param(_) | ty::Alias(..) => (tcx.types.unit, true), + // We don't know the metadata of `self`, but it must be equal to the + // metadata of `tail`. + ty::Param(_) | ty::Alias(..) => Err(tail), ty::Infer(ty::TyVar(_)) | ty::Bound(..) | ty::Placeholder(..) - | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("`ptr_metadata_ty` applied to unexpected type: {:?} (tail = {:?})", self, tail) - } + | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => bug!( + "`ptr_metadata_ty_or_tail` applied to unexpected type: {self:?} (tail = {tail:?})" + ), + } + } + + /// Returns the type of metadata for (potentially fat) pointers to this type. + /// Causes an ICE if the metadata type cannot be determined. + pub fn ptr_metadata_ty( + self, + tcx: TyCtxt<'tcx>, + normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, + ) -> Ty<'tcx> { + match self.ptr_metadata_ty_or_tail(tcx, normalize) { + Ok(metadata) => metadata, + Err(tail) => bug!( + "`ptr_metadata_ty` failed to get metadata for type: {self:?} (tail = {tail:?})" + ), } } diff --git a/compiler/rustc_middle/src/util/common.rs b/compiler/rustc_middle/src/util/common.rs index df101a2f6e4..dd3a36c7bf8 100644 --- a/compiler/rustc_middle/src/util/common.rs +++ b/compiler/rustc_middle/src/util/common.rs @@ -65,3 +65,19 @@ pub fn indenter() -> Indenter { debug!(">>"); Indenter { _cannot_construct_outside_of_this_module: () } } + +// const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }` +pub const fn c_name(name: &'static str) -> &'static str { + // FIXME Simplify the implementation once more `str` methods get const-stable. + // and inline into call site + let bytes = name.as_bytes(); + let mut i = bytes.len(); + while i > 0 && bytes[i - 1] != b':' { + i = i - 1; + } + let (_, bytes) = bytes.split_at(i); + match std::str::from_utf8(bytes) { + Ok(name) => name, + Err(_) => name, + } +} diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 065c93e86a8..dba8e8b6499 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -40,43 +40,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, candidate: &mut Candidate<'pat, 'tcx>, ) -> bool { - // repeatedly simplify match pairs until fixed point is reached debug!("{candidate:#?}"); - - // existing_bindings and new_bindings exists to keep the semantics in order. - // Reversing the binding order for bindings after `@` changes the binding order in places - // it shouldn't be changed, for example `let (Some(a), Some(b)) = (x, y)` + // In order to please the borrow checker, in a pattern like `x @ pat` we must lower the + // bindings in `pat` before `x`. E.g. (#69971): + // + // struct NonCopyStruct { + // copy_field: u32, + // } + // + // fn foo1(x: NonCopyStruct) { + // let y @ NonCopyStruct { copy_field: z } = x; + // // the above should turn into + // let z = x.copy_field; + // let y = x; + // } // - // To avoid this, the binding occurs in the following manner: - // * the bindings for one iteration of the following loop occurs in order (i.e. left to - // right) - // * the bindings from the previous iteration of the loop is prepended to the bindings from - // the current iteration (in the implementation this is done by mem::swap and extend) - // * after all iterations, these new bindings are then appended to the bindings that were - // preexisting (i.e. `candidate.binding` when the function was called). + // We can't just reverse the binding order, because we must preserve pattern-order + // otherwise, e.g. in `let (Some(a), Some(b)) = (x, y)`. Our rule then is: deepest-first, + // and bindings at the same depth stay in source order. + // + // To do this, every time around the loop we prepend the newly found bindings to the + // bindings we already had. // // example: // candidate.bindings = [1, 2, 3] - // binding in iter 1: [4, 5] - // binding in iter 2: [6, 7] + // bindings in iter 1: [4, 5] + // bindings in iter 2: [6, 7] // - // final binding: [1, 2, 3, 6, 7, 4, 5] - let mut existing_bindings = mem::take(&mut candidate.bindings); - let mut new_bindings = Vec::new(); + // final bindings: [6, 7, 4, 5, 1, 2, 3] + let mut accumulated_bindings = mem::take(&mut candidate.bindings); + // Repeatedly simplify match pairs until fixed point is reached loop { - let match_pairs = mem::take(&mut candidate.match_pairs); - - if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] = - &*match_pairs - { - existing_bindings.extend_from_slice(&new_bindings); - mem::swap(&mut candidate.bindings, &mut existing_bindings); - candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats); - return true; - } - let mut changed = false; - for match_pair in match_pairs { + for match_pair in mem::take(&mut candidate.match_pairs) { match self.simplify_match_pair(match_pair, candidate) { Ok(()) => { changed = true; @@ -86,36 +82,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } } - // Avoid issue #69971: the binding order should be right to left if there are more - // bindings after `@` to please the borrow checker - // Ex - // struct NonCopyStruct { - // copy_field: u32, - // } - // - // fn foo1(x: NonCopyStruct) { - // let y @ NonCopyStruct { copy_field: z } = x; - // // the above should turn into - // let z = x.copy_field; - // let y = x; - // } - candidate.bindings.extend_from_slice(&new_bindings); - mem::swap(&mut candidate.bindings, &mut new_bindings); + + // This does: accumulated_bindings = candidate.bindings.take() ++ accumulated_bindings + candidate.bindings.extend_from_slice(&accumulated_bindings); + mem::swap(&mut candidate.bindings, &mut accumulated_bindings); candidate.bindings.clear(); if !changed { - existing_bindings.extend_from_slice(&new_bindings); - mem::swap(&mut candidate.bindings, &mut existing_bindings); - // Move or-patterns to the end, because they can result in us - // creating additional candidates, so we want to test them as - // late as possible. - candidate - .match_pairs - .sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. })); - debug!(simplified = ?candidate, "simplify_candidate"); - return false; // if we were not able to simplify any, done. + // If we were not able to simplify anymore, done. + break; } } + + // Store computed bindings back in `candidate`. + mem::swap(&mut candidate.bindings, &mut accumulated_bindings); + + let did_expand_or = + if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] = + &*candidate.match_pairs + { + candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats); + candidate.match_pairs.clear(); + true + } else { + false + }; + + // Move or-patterns to the end, because they can result in us + // creating additional candidates, so we want to test them as + // late as possible. + candidate.match_pairs.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. })); + debug!(simplified = ?candidate, "simplify_candidate"); + + did_expand_or } /// Given `candidate` that has a single or-pattern for its match-pairs, @@ -271,7 +270,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Variant { adt_def, args, variant_index, ref subpatterns } => { let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| { i == variant_index || { - self.tcx.features().exhaustive_patterns + (self.tcx.features().exhaustive_patterns + || self.tcx.features().min_exhaustive_patterns) && !v .inhabited_predicate(self.tcx, adt_def) .instantiate(self.tcx, args) diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 9a2f2ceced1..2b1a9fef360 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -666,7 +666,7 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - let yield_ty = args.yield_ty(); let return_ty = args.return_ty(); ( - vec![closure_ty, args.resume_ty()], + vec![closure_ty, resume_ty], return_ty, Some(Box::new(CoroutineInfo::initial( tcx.coroutine_kind(def_id).unwrap(), @@ -675,8 +675,39 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) - ))), ) } - _ => { - span_bug!(span, "expected type of closure body to be a closure or coroutine"); + ty::CoroutineClosure(did, args) => { + let args = args.as_coroutine_closure(); + let sig = tcx.liberate_late_bound_regions( + def_id.to_def_id(), + args.coroutine_closure_sig(), + ); + let self_ty = match args.kind() { + ty::ClosureKind::Fn => { + Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty) + } + ty::ClosureKind::FnMut => { + Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, closure_ty) + } + ty::ClosureKind::FnOnce => closure_ty, + }; + ( + [self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()).collect(), + sig.to_coroutine( + tcx, + args.parent_args(), + args.kind_ty(), + tcx.coroutine_for_closure(*did), + Ty::new_error(tcx, guar), + ), + None, + ) + } + ty::Error(_) => (vec![closure_ty, closure_ty], closure_ty, None), + kind => { + span_bug!( + span, + "expected type of closure body to be a closure or coroutine, got {kind:?}" + ); } } } diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 6827797df37..2d366948771 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -655,7 +655,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let drops = if destination.is_some() { &mut self.scopes.breakable_scopes[break_index].break_drops } else { - self.scopes.breakable_scopes[break_index].continue_drops.as_mut().unwrap() + let Some(drops) = self.scopes.breakable_scopes[break_index].continue_drops.as_mut() + else { + self.tcx.dcx().span_delayed_bug( + source_info.span, + "unlabelled `continue` within labelled block", + ); + self.cfg.terminate(block, source_info, TerminatorKind::Unreachable); + + return self.cfg.start_new_block().unit(); + }; + drops }; let drop_idx = self.scopes.scopes[scope_index + 1..] diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 232b6033946..0bc5fe6ef89 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -2,7 +2,7 @@ use crate::fluent_generated as fluent; use rustc_errors::DiagnosticArgValue; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessage, + IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -420,10 +420,7 @@ pub struct UnsafeNotInheritedLintNote { } impl AddToDiagnostic for UnsafeNotInheritedLintNote { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body); let body_start = self.body_span.shrink_to_lo(); let body_end = self.body_span.shrink_to_hi(); @@ -866,10 +863,7 @@ pub struct Variant { } impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { diag.arg("ty", self.ty); let mut spans = MultiSpan::from(self.adt_def_span); diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index a3d88b12696..43e44b47e3f 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -1,6 +1,9 @@ //! Construction of MIR from HIR. //! //! This crate also contains the match exhaustiveness and usefulness checking. + +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(assert_matches)] #![feature(associated_type_bounds)] #![feature(box_patterns)] diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index 337493d15de..508936be29d 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -72,15 +72,14 @@ pub fn check_drop_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id)) && let Some(drop_trait) = tcx.lang_items().drop_trait() && drop_trait == trait_ref.instantiate_identity().def_id + // avoid erroneous `Drop` impls from causing ICEs below + && let sig = tcx.fn_sig(def_id).instantiate_identity() + && sig.inputs().skip_binder().len() == 1 { // It was. Now figure out for what type `Drop` is implemented and then // check for recursion. - if let ty::Ref(_, dropped_ty, _) = tcx - .liberate_late_bound_regions( - def_id.to_def_id(), - tcx.fn_sig(def_id).instantiate_identity().input(0), - ) - .kind() + if let ty::Ref(_, dropped_ty, _) = + tcx.liberate_late_bound_regions(def_id.to_def_id(), sig.input(0)).kind() { check_recursion(tcx, body, RecursiveDrop { drop_for: *dropped_ty }); } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index caf7f4227db..692f4511bb8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -291,7 +291,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { err = err.and(check_never_pattern(cx, pat)); }); err?; - Ok(cx.pattern_arena.alloc(cx.lower_pat(pat))) + Ok(self.pattern_arena.alloc(cx.lower_pat(pat))) } } @@ -388,7 +388,6 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { typeck_results: self.typeck_results, param_env: self.param_env, module: self.tcx.parent_module(self.lint_level).to_def_id(), - pattern_arena: self.pattern_arena, dropless_arena: self.dropless_arena, match_lint_level: self.lint_level, whole_match_span, @@ -666,7 +665,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { // Emit an extra note if the first uncovered witness would be uninhabited // if we disregard visibility. - let witness_1_is_privately_uninhabited = if self.tcx.features().exhaustive_patterns + let witness_1_is_privately_uninhabited = if (self.tcx.features().exhaustive_patterns + || self.tcx.features().min_exhaustive_patterns) && let Some(witness_1) = witnesses.get(0) && let ty::Adt(adt, args) = witness_1.ty().kind() && adt.is_enum() diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 9d3a9bf6745..18a00724c3d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -1,6 +1,5 @@ use rustc_apfloat::Float; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_index::Idx; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::Obligation; @@ -17,8 +16,8 @@ use std::cell::Cell; use super::PatCtxt; use crate::errors::{ - IndirectStructuralMatch, InvalidPattern, NaNPattern, NonPartialEqMatch, - NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern, + IndirectStructuralMatch, InvalidPattern, NaNPattern, NonPartialEqMatch, PointerPattern, + TypeNotStructural, UnionPattern, UnsizedPattern, }; impl<'a, 'tcx> PatCtxt<'a, 'tcx> { @@ -33,11 +32,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { cv: mir::Const<'tcx>, id: hir::HirId, span: Span, - check_body_for_struct_match_violation: Option<DefId>, ) -> Box<Pat<'tcx>> { let infcx = self.tcx.infer_ctxt().build(); let mut convert = ConstToPat::new(self, id, span, infcx); - convert.to_pat(cv, check_body_for_struct_match_violation) + convert.to_pat(cv) } } @@ -103,11 +101,7 @@ impl<'tcx> ConstToPat<'tcx> { ty.is_structural_eq_shallow(self.infcx.tcx) } - fn to_pat( - &mut self, - cv: mir::Const<'tcx>, - check_body_for_struct_match_violation: Option<DefId>, - ) -> Box<Pat<'tcx>> { + fn to_pat(&mut self, cv: mir::Const<'tcx>) -> Box<Pat<'tcx>> { trace!(self.treat_byte_string_as_slice); // This method is just a wrapper handling a validity check; the heavy lifting is // performed by the recursive `recur` method, which is not meant to be @@ -116,14 +110,6 @@ impl<'tcx> ConstToPat<'tcx> { // once indirect_structural_match is a full fledged error, this // level of indirection can be eliminated - let mir_structural_match_violation = check_body_for_struct_match_violation.map(|def_id| { - // `mir_const_qualif` must be called with the `DefId` of the item where the const is - // defined, not where it is declared. The difference is significant for associated - // constants. - self.tcx().mir_const_qualif(def_id).custom_eq - }); - debug!(?check_body_for_struct_match_violation, ?mir_structural_match_violation); - let have_valtree = matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_))); let inlined_const_as_pat = match cv { @@ -137,15 +123,15 @@ impl<'tcx> ConstToPat<'tcx> { | ty::ConstKind::Expr(_) => { span_bug!(self.span, "unexpected const in `to_pat`: {:?}", c.kind()) } - ty::ConstKind::Value(valtree) => self - .recur(valtree, cv.ty(), mir_structural_match_violation.unwrap_or(false)) - .unwrap_or_else(|_: FallbackToOpaqueConst| { + ty::ConstKind::Value(valtree) => { + self.recur(valtree, cv.ty()).unwrap_or_else(|_: FallbackToOpaqueConst| { Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Constant { value: cv }, }) - }), + }) + } }, mir::Const::Unevaluated(_, _) => { span_bug!(self.span, "unevaluated const in `to_pat`: {cv:?}") @@ -160,7 +146,12 @@ impl<'tcx> ConstToPat<'tcx> { if self.saw_const_match_error.get().is_none() { // If we were able to successfully convert the const to some pat (possibly with some // lints, but no errors), double-check that all types in the const implement - // `Structural` and `PartialEq`. + // `PartialEq`. Even if we have a valtree, we may have found something + // in there with non-structural-equality, meaning we match using `PartialEq` + // and we hence have to check that that impl exists. + // This is all messy but not worth cleaning up: at some point we'll emit + // a hard error when we don't have a valtree or when we find something in + // the valtree that is not structural; then this can all be made a lot simpler. let structural = traits::search_for_structural_match_violation(self.span, self.tcx(), cv.ty()); @@ -170,19 +161,12 @@ impl<'tcx> ConstToPat<'tcx> { structural ); - // This can occur because const qualification treats all associated constants as - // opaque, whereas `search_for_structural_match_violation` tries to monomorphize them - // before it runs. - // - // FIXME(#73448): Find a way to bring const qualification into parity with - // `search_for_structural_match_violation`. - if structural.is_none() && mir_structural_match_violation.unwrap_or(false) { - warn!("MIR const-checker found novel structural match violation. See #73448."); - return inlined_const_as_pat; - } - if let Some(non_sm_ty) = structural { if !self.type_has_partial_eq_impl(cv.ty()) { + // This is reachable and important even if we have a valtree: there might be + // non-structural things in a valtree, in which case we fall back to `PartialEq` + // comparison, in which case we better make sure the trait is implemented for + // each inner type (and not just for the surrounding type). let e = if let ty::Adt(def, ..) = non_sm_ty.kind() { if def.is_union() { let err = UnionPattern { span: self.span }; @@ -201,35 +185,18 @@ impl<'tcx> ConstToPat<'tcx> { // We errored. Signal that in the pattern, so that follow up errors can be silenced. let kind = PatKind::Error(e); return Box::new(Pat { span: self.span, ty: cv.ty(), kind }); - } else if let ty::Adt(..) = cv.ty().kind() - && matches!(cv, mir::Const::Val(..)) - { - // This branch is only entered when the current `cv` is `mir::Const::Val`. - // This is because `mir::Const::ty` has already been handled by `Self::recur` - // and the invalid types may be ignored. + } else if !have_valtree { + // Not being structural prevented us from constructing a valtree, + // so this is definitely a case we want to reject. let err = TypeNotStructural { span: self.span, non_sm_ty }; let e = self.tcx().dcx().emit_err(err); let kind = PatKind::Error(e); return Box::new(Pat { span: self.span, ty: cv.ty(), kind }); - } else if !self.saw_const_match_lint.get() { - if let Some(mir_structural_match_violation) = mir_structural_match_violation { - match non_sm_ty.kind() { - ty::Adt(..) if mir_structural_match_violation => { - self.tcx().emit_node_span_lint( - lint::builtin::INDIRECT_STRUCTURAL_MATCH, - self.id, - self.span, - IndirectStructuralMatch { non_sm_ty }, - ); - } - _ => { - debug!( - "`search_for_structural_match_violation` found one, but `CustomEq` was \ - not in the qualifs for that `const`" - ); - } - } - } + } else { + // This could be a violation in an inactive enum variant. + // Since we have a valtree, we trust that we have traversed the full valtree and + // complained about structural match violations there, so we don't + // have to check anything any more. } } else if !have_valtree && !self.saw_const_match_lint.get() { // The only way valtree construction can fail without the structural match @@ -299,7 +266,7 @@ impl<'tcx> ConstToPat<'tcx> { let field = FieldIdx::new(idx); // Patterns can only use monomorphic types. let ty = self.tcx().normalize_erasing_regions(self.param_env, ty); - Ok(FieldPat { field, pattern: self.recur(val, ty, false)? }) + Ok(FieldPat { field, pattern: self.recur(val, ty)? }) }) .collect() } @@ -310,7 +277,6 @@ impl<'tcx> ConstToPat<'tcx> { &self, cv: ValTree<'tcx>, ty: Ty<'tcx>, - mir_structural_match_violation: bool, ) -> Result<Box<Pat<'tcx>>, FallbackToOpaqueConst> { let id = self.id; let span = self.span; @@ -395,7 +361,7 @@ impl<'tcx> ConstToPat<'tcx> { prefix: cv .unwrap_branch() .iter() - .map(|val| self.recur(*val, *elem_ty, false)) + .map(|val| self.recur(*val, *elem_ty)) .collect::<Result<_, _>>()?, slice: None, suffix: Box::new([]), @@ -404,7 +370,7 @@ impl<'tcx> ConstToPat<'tcx> { prefix: cv .unwrap_branch() .iter() - .map(|val| self.recur(*val, *elem_ty, false)) + .map(|val| self.recur(*val, *elem_ty)) .collect::<Result<_, _>>()?, slice: None, suffix: Box::new([]), @@ -471,7 +437,7 @@ impl<'tcx> ConstToPat<'tcx> { _ => *pointee_ty, }; // References have the same valtree representation as their pointee. - let subpattern = self.recur(cv, pointee_ty, false)?; + let subpattern = self.recur(cv, pointee_ty)?; self.behind_reference.set(old); PatKind::Deref { subpattern } } @@ -512,25 +478,6 @@ impl<'tcx> ConstToPat<'tcx> { } }; - if self.saw_const_match_error.get().is_none() - && !self.saw_const_match_lint.get() - && mir_structural_match_violation - // FIXME(#73448): Find a way to bring const qualification into parity with - // `search_for_structural_match_violation` and then remove this condition. - - // Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we - // could get `Option<NonStructEq>`, even though `Option` is annotated with derive. - && let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, ty) - { - self.saw_const_match_lint.set(true); - tcx.emit_node_span_lint( - lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH, - id, - span, - NontrivialStructuralMatch { non_sm_ty }, - ); - } - Ok(Box::new(Pat { span, ty, kind })) } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 2190ad14b55..1a5cf13e289 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -542,7 +542,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { match const_value { Ok(const_) => { - let pattern = self.const_to_pat(const_, id, span, Some(instance.def_id())); + let pattern = self.const_to_pat(const_, id, span); if !is_associated_const { return pattern; @@ -612,7 +612,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }; if let Some(lit_input) = lit_input { match tcx.at(expr.span).lit_to_const(lit_input) { - Ok(c) => return self.const_to_pat(Const::Ty(c), id, span, None).kind, + Ok(c) => return self.const_to_pat(Const::Ty(c), id, span).kind, // If an error occurred, ignore that it's a literal // and leave reporting the error up to const eval of // the unevaluated constant below. @@ -635,17 +635,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span)) { - let subpattern = self.const_to_pat( - Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), - id, - span, - None, - ); + let subpattern = + self.const_to_pat(Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), id, span); PatKind::InlineConstant { subpattern, def: def_id } } else { // If that fails, convert it to an opaque constant pattern. match tcx.const_eval_resolve(self.param_env, uneval, Some(span)) { - Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span, None).kind, + Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span).kind, Err(ErrorHandled::TooGeneric(_)) => { // If we land here it means the const can't be evaluated because it's `TooGeneric`. let e = self.tcx.dcx().emit_err(ConstPatternDependsOnGenericParameter { span }); @@ -681,9 +677,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let lit_input = LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; match self.tcx.at(expr.span).lit_to_const(lit_input) { - Ok(constant) => { - self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span, None).kind - } + Ok(constant) => self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span).kind, Err(LitToConstError::Reported(e)) => PatKind::Error(e), Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 23111cc3199..a4b58e5bfc1 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -4,8 +4,6 @@ #![feature(let_chains)] #![feature(min_specialization)] #![feature(try_blocks)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 30dd915521c..80e0d0baf57 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -429,7 +429,10 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) - | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {} + | Rvalue::NullaryOp( + NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..) | NullOp::DebugAssertions, + _, + ) => {} } } diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 451d3be255f..ba70a4453d6 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -41,6 +41,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { ty::Closure(..) => Abi::RustCall, ty::CoroutineClosure(..) => Abi::RustCall, ty::Coroutine(..) => Abi::Rust, + ty::Error(_) => return, _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), }; let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi); diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index f2448ee3d44..04d0a4f303f 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -541,12 +541,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } #[instrument(level = "trace", skip(self), ret)] - fn eval_rvalue( - &mut self, - rvalue: &Rvalue<'tcx>, - location: Location, - dest: &Place<'tcx>, - ) -> Option<()> { + fn eval_rvalue(&mut self, rvalue: &Rvalue<'tcx>, dest: &Place<'tcx>) -> Option<()> { if !dest.projection.is_empty() { return None; } @@ -639,6 +634,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { NullOp::OffsetOf(fields) => { op_layout.offset_of_subfield(self, fields.iter()).bytes() } + NullOp::DebugAssertions => return None, }; ImmTy::from_scalar(Scalar::from_target_usize(val, self), layout).into() } @@ -734,7 +730,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { _ if place.is_indirect() => {} ConstPropMode::NoPropagation => self.ensure_not_propagated(place.local), ConstPropMode::OnlyInsideOwnBlock | ConstPropMode::FullConstProp => { - if self.eval_rvalue(rvalue, location, place).is_none() { + if self.eval_rvalue(rvalue, place).is_none() { // Const prop failed, so erase the destination, ensuring that whatever happens // from here on, does not know about the previous value. // This is important in case we have diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index fcd4715b9e8..e40f4520671 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::{self, dump_mir, MirPass}; -use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt}; +use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, TypeVisitableExt}; use rustc_target::abi::FieldIdx; pub struct ByMoveBody; @@ -23,7 +23,10 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { return; }; let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; - let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!() }; + if coroutine_ty.references_error() { + return; + } + let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") }; let coroutine_kind = args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(); if coroutine_kind == ty::ClosureKind::FnOnce { diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 8c11dea5d4e..9a1d8bae6b4 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -1,4 +1,5 @@ -use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::captures::Captures; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::graph::WithNumNodes; use rustc_index::bit_set::BitSet; use rustc_index::IndexVec; @@ -38,19 +39,27 @@ impl Debug for BcbCounter { } } +#[derive(Debug)] +pub(super) enum CounterIncrementSite { + Node { bcb: BasicCoverageBlock }, + Edge { from_bcb: BasicCoverageBlock, to_bcb: BasicCoverageBlock }, +} + /// Generates and stores coverage counter and coverage expression information /// associated with nodes/edges in the BCB graph. pub(super) struct CoverageCounters { - next_counter_id: CounterId, + /// List of places where a counter-increment statement should be injected + /// into MIR, each with its corresponding counter ID. + counter_increment_sites: IndexVec<CounterId, CounterIncrementSite>, /// Coverage counters/expressions that are associated with individual BCBs. bcb_counters: IndexVec<BasicCoverageBlock, Option<BcbCounter>>, /// Coverage counters/expressions that are associated with the control-flow /// edge between two BCBs. /// - /// The iteration order of this map can affect the precise contents of MIR, - /// so we use `FxIndexMap` to avoid query stability hazards. - bcb_edge_counters: FxIndexMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>, + /// We currently don't iterate over this map, but if we do in the future, + /// switch it back to `FxIndexMap` to avoid query stability hazards. + bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>, /// Tracks which BCBs have a counter associated with some incoming edge. /// Only used by assertions, to verify that BCBs with incoming edge /// counters do not have their own physical counters (expressions are allowed). @@ -71,9 +80,9 @@ impl CoverageCounters { let num_bcbs = basic_coverage_blocks.num_nodes(); let mut this = Self { - next_counter_id: CounterId::START, + counter_increment_sites: IndexVec::new(), bcb_counters: IndexVec::from_elem_n(None, num_bcbs), - bcb_edge_counters: FxIndexMap::default(), + bcb_edge_counters: FxHashMap::default(), bcb_has_incoming_edge_counters: BitSet::new_empty(num_bcbs), expressions: IndexVec::new(), }; @@ -84,8 +93,8 @@ impl CoverageCounters { this } - fn make_counter(&mut self) -> BcbCounter { - let id = self.next_counter(); + fn make_counter(&mut self, site: CounterIncrementSite) -> BcbCounter { + let id = self.counter_increment_sites.push(site); BcbCounter::Counter { id } } @@ -103,15 +112,8 @@ impl CoverageCounters { self.make_expression(lhs, Op::Add, rhs) } - /// Counter IDs start from one and go up. - fn next_counter(&mut self) -> CounterId { - let next = self.next_counter_id; - self.next_counter_id = self.next_counter_id + 1; - next - } - pub(super) fn num_counters(&self) -> usize { - self.next_counter_id.as_usize() + self.counter_increment_sites.len() } #[cfg(test)] @@ -171,22 +173,26 @@ impl CoverageCounters { self.bcb_counters[bcb] } - pub(super) fn bcb_node_counters( + /// Returns an iterator over all the nodes/edges in the coverage graph that + /// should have a counter-increment statement injected into MIR, along with + /// each site's corresponding counter ID. + pub(super) fn counter_increment_sites( &self, - ) -> impl Iterator<Item = (BasicCoverageBlock, &BcbCounter)> { - self.bcb_counters - .iter_enumerated() - .filter_map(|(bcb, counter_kind)| Some((bcb, counter_kind.as_ref()?))) + ) -> impl Iterator<Item = (CounterId, &CounterIncrementSite)> { + self.counter_increment_sites.iter_enumerated() } - /// For each edge in the BCB graph that has an associated counter, yields - /// that edge's *from* and *to* nodes, and its counter. - pub(super) fn bcb_edge_counters( + /// Returns an iterator over the subset of BCB nodes that have been associated + /// with a counter *expression*, along with the ID of that expression. + pub(super) fn bcb_nodes_with_coverage_expressions( &self, - ) -> impl Iterator<Item = (BasicCoverageBlock, BasicCoverageBlock, &BcbCounter)> { - self.bcb_edge_counters - .iter() - .map(|(&(from_bcb, to_bcb), counter_kind)| (from_bcb, to_bcb, counter_kind)) + ) -> impl Iterator<Item = (BasicCoverageBlock, ExpressionId)> + Captures<'_> { + self.bcb_counters.iter_enumerated().filter_map(|(bcb, &counter_kind)| match counter_kind { + // Yield the BCB along with its associated expression ID. + Some(BcbCounter::Expression { id }) => Some((bcb, id)), + // This BCB is associated with a counter or nothing, so skip it. + Some(BcbCounter::Counter { .. }) | None => None, + }) } pub(super) fn into_expressions(self) -> IndexVec<ExpressionId, Expression> { @@ -339,7 +345,8 @@ impl<'a> MakeBcbCounters<'a> { // program results in a tight infinite loop, but it should still compile. let one_path_to_target = !self.basic_coverage_blocks.bcb_has_multiple_in_edges(bcb); if one_path_to_target || self.bcb_predecessors(bcb).contains(&bcb) { - let counter_kind = self.coverage_counters.make_counter(); + let counter_kind = + self.coverage_counters.make_counter(CounterIncrementSite::Node { bcb }); if one_path_to_target { debug!("{bcb:?} gets a new counter: {counter_kind:?}"); } else { @@ -401,7 +408,8 @@ impl<'a> MakeBcbCounters<'a> { } // Make a new counter to count this edge. - let counter_kind = self.coverage_counters.make_counter(); + let counter_kind = + self.coverage_counters.make_counter(CounterIncrementSite::Edge { from_bcb, to_bcb }); debug!("Edge {from_bcb:?}->{to_bcb:?} gets a new counter: {counter_kind:?}"); self.coverage_counters.set_bcb_edge_counter(from_bcb, to_bcb, counter_kind) } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 3aa41250fd3..4c5be0a3f4b 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -7,7 +7,7 @@ mod spans; #[cfg(test)] mod tests; -use self::counters::{BcbCounter, CoverageCounters}; +use self::counters::{CounterIncrementSite, CoverageCounters}; use self::graph::{BasicCoverageBlock, CoverageGraph}; use self::spans::{BcbMapping, BcbMappingKind, CoverageSpans}; @@ -155,61 +155,52 @@ fn inject_coverage_statements<'tcx>( bcb_has_coverage_spans: impl Fn(BasicCoverageBlock) -> bool, coverage_counters: &CoverageCounters, ) { - // Process the counters associated with BCB nodes. - for (bcb, counter_kind) in coverage_counters.bcb_node_counters() { - let do_inject = match counter_kind { - // Counter-increment statements always need to be injected. - BcbCounter::Counter { .. } => true, - // The only purpose of expression-used statements is to detect - // when a mapping is unreachable, so we only inject them for - // expressions with one or more mappings. - BcbCounter::Expression { .. } => bcb_has_coverage_spans(bcb), - }; - if do_inject { - inject_statement( - mir_body, - make_mir_coverage_kind(counter_kind), - basic_coverage_blocks[bcb].leader_bb(), - ); - } - } - - // Process the counters associated with BCB edges. - for (from_bcb, to_bcb, counter_kind) in coverage_counters.bcb_edge_counters() { - let do_inject = match counter_kind { - // Counter-increment statements always need to be injected. - BcbCounter::Counter { .. } => true, - // BCB-edge expressions never have mappings, so they never need - // a corresponding statement. - BcbCounter::Expression { .. } => false, + // Inject counter-increment statements into MIR. + for (id, counter_increment_site) in coverage_counters.counter_increment_sites() { + // Determine the block to inject a counter-increment statement into. + // For BCB nodes this is just their first block, but for edges we need + // to create a new block between the two BCBs, and inject into that. + let target_bb = match *counter_increment_site { + CounterIncrementSite::Node { bcb } => basic_coverage_blocks[bcb].leader_bb(), + CounterIncrementSite::Edge { from_bcb, to_bcb } => { + // Create a new block between the last block of `from_bcb` and + // the first block of `to_bcb`. + let from_bb = basic_coverage_blocks[from_bcb].last_bb(); + let to_bb = basic_coverage_blocks[to_bcb].leader_bb(); + + let new_bb = inject_edge_counter_basic_block(mir_body, from_bb, to_bb); + debug!( + "Edge {from_bcb:?} (last {from_bb:?}) -> {to_bcb:?} (leader {to_bb:?}) \ + requires a new MIR BasicBlock {new_bb:?} for counter increment {id:?}", + ); + new_bb + } }; - if !do_inject { - continue; - } - - // We need to inject a coverage statement into a new BB between the - // last BB of `from_bcb` and the first BB of `to_bcb`. - let from_bb = basic_coverage_blocks[from_bcb].last_bb(); - let to_bb = basic_coverage_blocks[to_bcb].leader_bb(); - let new_bb = inject_edge_counter_basic_block(mir_body, from_bb, to_bb); - debug!( - "Edge {from_bcb:?} (last {from_bb:?}) -> {to_bcb:?} (leader {to_bb:?}) \ - requires a new MIR BasicBlock {new_bb:?} for edge counter {counter_kind:?}", - ); - - // Inject a counter into the newly-created BB. - inject_statement(mir_body, make_mir_coverage_kind(counter_kind), new_bb); + inject_statement(mir_body, CoverageKind::CounterIncrement { id }, target_bb); } -} -fn make_mir_coverage_kind(counter_kind: &BcbCounter) -> CoverageKind { - match *counter_kind { - BcbCounter::Counter { id } => CoverageKind::CounterIncrement { id }, - BcbCounter::Expression { id } => CoverageKind::ExpressionUsed { id }, + // For each counter expression that is directly associated with at least one + // span, we inject an "expression-used" statement, so that coverage codegen + // can check whether the injected statement survived MIR optimization. + // (BCB edges can't have spans, so we only need to process BCB nodes here.) + // + // See the code in `rustc_codegen_llvm::coverageinfo::map_data` that deals + // with "expressions seen" and "zero terms". + for (bcb, expression_id) in coverage_counters + .bcb_nodes_with_coverage_expressions() + .filter(|&(bcb, _)| bcb_has_coverage_spans(bcb)) + { + inject_statement( + mir_body, + CoverageKind::ExpressionUsed { id: expression_id }, + basic_coverage_blocks[bcb].leader_bb(), + ); } } +/// Given two basic blocks that have a control-flow edge between them, creates +/// and returns a new block that sits between those blocks. fn inject_edge_counter_basic_block( mir_body: &mut mir::Body<'_>, from_bb: BasicBlock, diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index b0d758bcbfe..663abbece85 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -59,6 +59,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { ty::Closure(..) => Abi::RustCall, ty::CoroutineClosure(..) => Abi::RustCall, ty::Coroutine(..) => Abi::Rust, + ty::Error(_) => return false, _ => span_bug!(body.span, "unexpected body ty: {:?}", body_ty), }; let body_can_unwind = layout::fn_can_unwind(tcx, Some(def_id), body_abi); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index f9798bc4e70..36c441a3945 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -489,6 +489,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { NullOp::OffsetOf(fields) => { layout.offset_of_subfield(&self.ecx, fields.iter()).bytes() } + NullOp::DebugAssertions => return None, }; let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap(); let imm = ImmTy::try_from_uint(val, usize_layout)?; @@ -1231,8 +1232,8 @@ impl<'tcx> MutVisitor<'tcx> for StorageRemover<'tcx> { fn visit_operand(&mut self, operand: &mut Operand<'tcx>, _: Location) { if let Operand::Move(place) = *operand - && let Some(local) = place.as_local() - && self.reused_locals.contains(local) + && !place.is_indirect_first_projection() + && self.reused_locals.contains(place.local) { *operand = Operand::Copy(place); } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index e77553a03d6..be19bd8349e 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1027,21 +1027,16 @@ fn try_instance_mir<'tcx>( tcx: TyCtxt<'tcx>, instance: InstanceDef<'tcx>, ) -> Result<&'tcx Body<'tcx>, &'static str> { - match instance { - ty::InstanceDef::DropGlue(_, Some(ty)) => match ty.kind() { - ty::Adt(def, args) => { - let fields = def.all_fields(); - for field in fields { - let field_ty = field.ty(tcx, args); - if field_ty.has_param() && field_ty.has_projections() { - return Err("cannot build drop shim for polymorphic type"); - } - } - - Ok(tcx.instance_mir(instance)) + if let ty::InstanceDef::DropGlue(_, Some(ty)) = instance + && let ty::Adt(def, args) = ty.kind() + { + let fields = def.all_fields(); + for field in fields { + let field_ty = field.ty(tcx, args); + if field_ty.has_param() && field_ty.has_projections() { + return Err("cannot build drop shim for polymorphic type"); } - _ => Ok(tcx.instance_mir(instance)), - }, - _ => Ok(tcx.instance_mir(instance)), + } } + Ok(tcx.instance_mir(instance)) } diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index a28db0defc9..f65eb5cbea9 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -2,10 +2,12 @@ use crate::simplify::simplify_duplicate_switch_targets; use rustc_middle::mir::*; +use rustc_middle::ty::layout; use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt}; use rustc_span::symbol::Symbol; use rustc_target::abi::FieldIdx; +use rustc_target::spec::abi::Abi; pub struct InstSimplify; @@ -38,6 +40,7 @@ impl<'tcx> MirPass<'tcx> for InstSimplify { block.terminator.as_mut().unwrap(), &mut block.statements, ); + ctx.simplify_nounwind_call(block.terminator.as_mut().unwrap()); simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap()); } } @@ -252,6 +255,28 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { terminator.kind = TerminatorKind::Goto { target: destination_block }; } + fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) { + let TerminatorKind::Call { func, unwind, .. } = &mut terminator.kind else { + return; + }; + + let Some((def_id, _)) = func.const_fn_def() else { + return; + }; + + let body_ty = self.tcx.type_of(def_id).skip_binder(); + let body_abi = match body_ty.kind() { + ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(), + ty::Closure(..) => Abi::RustCall, + ty::Coroutine(..) => Abi::Rust, + _ => bug!("unexpected body ty: {:?}", body_ty), + }; + + if !layout::fn_can_unwind(self.tcx, Some(def_id), body_abi) { + *unwind = UnwindAction::Unreachable; + } + } + fn simplify_intrinsic_assert( &self, terminator: &mut Terminator<'tcx>, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 031515ea958..8e5d69605aa 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -1,5 +1,3 @@ -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![feature(assert_matches)] #![feature(box_patterns)] #![feature(const_type_name)] diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 897375e0e16..f43b85173d4 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -21,6 +21,17 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { sym::unreachable => { terminator.kind = TerminatorKind::Unreachable; } + sym::debug_assertions => { + let target = target.unwrap(); + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + *destination, + Rvalue::NullaryOp(NullOp::DebugAssertions, tcx.types.bool), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; + } sym::forget => { if let Some(target) = *target { block.statements.push(Statement { diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 605e1ad46d7..77478cc741d 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -8,18 +8,10 @@ use crate::{lint::lint_body, validate, MirPass}; pub trait MirLint<'tcx> { fn name(&self) -> &'static str { // FIXME Simplify the implementation once more `str` methods get const-stable. + // See copypaste in `MirPass` const { let name = std::any::type_name::<Self>(); - let bytes = name.as_bytes(); - let mut i = bytes.len(); - while i > 0 && bytes[i - 1] != b':' { - i = i - 1; - } - let (_, bytes) = bytes.split_at(i); - match std::str::from_utf8(bytes) { - Ok(name) => name, - Err(_) => name, - } + rustc_middle::util::common::c_name(name) } } diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index c00093ea27e..577b8f2080f 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -446,6 +446,7 @@ impl<'tcx> Validator<'_, 'tcx> { NullOp::SizeOf => {} NullOp::AlignOf => {} NullOp::OffsetOf(_) => {} + NullOp::DebugAssertions => {} }, Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable), diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index b0cfa3568ca..7f36ae91f1a 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -1,8 +1,6 @@ #![feature(array_windows)] #![feature(is_sorted)] #![allow(rustc::potential_query_instability)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 4f6ea66df7b..5cfebcaa5a5 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -156,7 +156,7 @@ where placed }; - // Merge until we have at most `max_cgu_count` codegen units. + // Merge until we don't exceed the max CGU count. // `merge_codegen_units` is responsible for updating the CGU size // estimates. { diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 86a64d90deb..3c3a8d6fbb9 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3,8 +3,8 @@ use std::borrow::Cow; use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; use rustc_errors::{ - codes::*, AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, IntoDiagnostic, Level, - SubdiagnosticMessage, + codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + IntoDiagnostic, Level, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; @@ -1475,10 +1475,7 @@ pub(crate) struct FnTraitMissingParen { } impl AddToDiagnostic for FnTraitMissingParen { - fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn(&mut rustc_errors::Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); let applicability = if self.machine_applicable { Applicability::MachineApplicable diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index d5fa1108687..5bd8bb72bd6 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -1,11 +1,13 @@ //! The main parser interface. +#![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(array_windows)] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(let_chains)] -#![allow(internal_features)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e36a648e203..1a57474bac2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2911,12 +2911,22 @@ impl<'a> Parser<'a> { Ok(arm) => arms.push(arm), Err(e) => { // Recover by skipping to the end of the block. - e.emit(); + let guar = e.emit(); self.recover_stmt(); let span = lo.to(self.token.span); if self.token == token::CloseDelim(Delimiter::Brace) { self.bump(); } + // Always push at least one arm to make the match non-empty + arms.push(Arm { + attrs: Default::default(), + pat: self.mk_pat(span, ast::PatKind::Err(guar)), + guard: None, + body: Some(self.mk_expr_err(span)), + span, + id: DUMMY_NODE_ID, + is_placeholder: false, + }); return Ok(self.mk_expr_with_attrs( span, ExprKind::Match(scrutinee, arms), diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index d76ee161da6..0b65f400825 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -9,8 +9,6 @@ html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))) )] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] // We want to be able to build this crate with a stable compiler, // so no `#![feature]` attributes should be added. #![deny(unstable_features)] diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index d41cc724408..648ef9d51de 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -323,9 +323,6 @@ passes_ffi_const_invalid_target = passes_ffi_pure_invalid_target = `#[ffi_pure]` may only be used on foreign functions -passes_ffi_returns_twice_invalid_target = - `#[ffi_returns_twice]` may only be used on foreign functions - passes_has_incoherent_inherent_impl = `rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits. .label = only adts, extern types and traits are supported diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0f0027db01d..ec704dec352 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -192,7 +192,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } sym::ffi_pure => self.check_ffi_pure(attr.span, attrs, target), sym::ffi_const => self.check_ffi_const(attr.span, target), - sym::ffi_returns_twice => self.check_ffi_returns_twice(attr.span, target), sym::rustc_const_unstable | sym::rustc_const_stable | sym::unstable @@ -828,10 +827,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.doc_attr_str_error(meta, "keyword"); return false; } - match self.tcx.opt_hir_node(hir_id).and_then(|node| match node { + let item_kind = match self.tcx.hir_node(hir_id) { hir::Node::Item(item) => Some(&item.kind), _ => None, - }) { + }; + match item_kind { Some(ItemKind::Mod(module)) => { if !module.item_ids.is_empty() { self.dcx().emit_err(errors::DocKeywordEmptyMod { span: meta.span() }); @@ -854,10 +854,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } fn check_doc_fake_variadic(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool { - match self.tcx.opt_hir_node(hir_id).and_then(|node| match node { + let item_kind = match self.tcx.hir_node(hir_id) { hir::Node::Item(item) => Some(&item.kind), _ => None, - }) { + }; + match item_kind { Some(ItemKind::Impl(i)) => { let is_valid = matches!(&i.self_ty.kind, hir::TyKind::Tup([_])) || if let hir::TyKind::BareFn(bare_fn_ty) = &i.self_ty.kind { @@ -1309,15 +1310,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_ffi_returns_twice(&self, attr_span: Span, target: Target) -> bool { - if target == Target::ForeignFn { - true - } else { - self.dcx().emit_err(errors::FfiReturnsTwiceInvalidTarget { attr_span }); - false - } - } - /// Warns against some misuses of `#[must_use]` fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool { if !matches!( @@ -2231,8 +2223,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } else { // special case when `#[macro_export]` is applied to a macro 2.0 - let (macro_definition, _) = - self.tcx.opt_hir_node(hir_id).unwrap().expect_item().expect_macro(); + let (macro_definition, _) = self.tcx.hir_node(hir_id).expect_item().expect_macro(); let is_decl_macro = !macro_definition.macro_rules; if is_decl_macro { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index d19987cb33c..e11102c459e 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -4,6 +4,7 @@ // is dead. use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; +use hir::ItemKind; use rustc_data_structures::unord::UnordSet; use rustc_errors::MultiSpan; use rustc_hir as hir; @@ -14,7 +15,7 @@ use rustc_hir::{Node, PatKind, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt, Visibility}; use rustc_session::lint; use rustc_session::lint::builtin::DEAD_CODE; use rustc_span::symbol::{sym, Symbol}; @@ -381,9 +382,46 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { intravisit::walk_item(self, item) } hir::ItemKind::ForeignMod { .. } => {} + hir::ItemKind::Trait(..) => { + for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) { + if let Some(local_def_id) = impl_def_id.as_local() + && let ItemKind::Impl(impl_ref) = + self.tcx.hir().expect_item(local_def_id).kind + { + // skip items + // mark dependent traits live + intravisit::walk_generics(self, impl_ref.generics); + // mark dependent parameters live + intravisit::walk_path(self, impl_ref.of_trait.unwrap().path); + } + } + + intravisit::walk_item(self, item) + } _ => intravisit::walk_item(self, item), }, Node::TraitItem(trait_item) => { + // mark corresponing ImplTerm live + let trait_item_id = trait_item.owner_id.to_def_id(); + if let Some(trait_id) = self.tcx.trait_of_item(trait_item_id) { + // mark the trait live + self.check_def_id(trait_id); + + for impl_id in self.tcx.all_impls(trait_id) { + if let Some(local_impl_id) = impl_id.as_local() + && let ItemKind::Impl(impl_ref) = + self.tcx.hir().expect_item(local_impl_id).kind + { + // mark self_ty live + intravisit::walk_ty(self, impl_ref.self_ty); + if let Some(&impl_item_id) = + self.tcx.impl_item_implementor_ids(impl_id).get(&trait_item_id) + { + self.check_def_id(impl_item_id); + } + } + } + } intravisit::walk_trait_item(self, trait_item); } Node::ImplItem(impl_item) => { @@ -636,10 +674,6 @@ fn check_item<'tcx>( } } DefKind::Impl { of_trait } => { - if of_trait { - worklist.push((id.owner_id.def_id, ComesFromAllowExpect::No)); - } - // get DefIds from another query let local_def_ids = tcx .associated_item_def_ids(id.owner_id) @@ -648,7 +682,11 @@ fn check_item<'tcx>( // And we access the Map here to get HirId from LocalDefId for id in local_def_ids { - if of_trait { + // for impl trait blocks, mark associate functions live if the trait is public + if of_trait + && (!matches!(tcx.def_kind(id), DefKind::AssocFn) + || tcx.local_visibility(id) == Visibility::Public) + { worklist.push((id, ComesFromAllowExpect::No)); } else if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id) { worklist.push((id, comes_from_allow)); @@ -679,7 +717,7 @@ fn check_trait_item( use hir::TraitItemKind::{Const, Fn}; if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) { let trait_item = tcx.hir().trait_item(id); - if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_))) + if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..)) && let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id) { @@ -948,7 +986,8 @@ impl<'tcx> DeadVisitor<'tcx> { | DefKind::TyAlias | DefKind::Enum | DefKind::Union - | DefKind::ForeignTy => self.warn_dead_code(def_id, "used"), + | DefKind::ForeignTy + | DefKind::Trait => self.warn_dead_code(def_id, "used"), DefKind::Struct => self.warn_dead_code(def_id, "constructed"), DefKind::Variant | DefKind::Field => bug!("should be handled specially"), _ => {} @@ -973,18 +1012,33 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { let module_items = tcx.hir_module_items(module); for item in module_items.items() { - if let hir::ItemKind::Impl(impl_item) = tcx.hir().item(item).kind { - let mut dead_items = Vec::new(); - for item in impl_item.items { - let def_id = item.id.owner_id.def_id; - if !visitor.is_live_code(def_id) { - let name = tcx.item_name(def_id.to_def_id()); - let level = visitor.def_lint_level(def_id); + let def_kind = tcx.def_kind(item.owner_id); - dead_items.push(DeadItem { def_id, name, level }) + let mut dead_codes = Vec::new(); + // if we have diagnosed the trait, do not diagnose unused methods + if matches!(def_kind, DefKind::Impl { .. }) + || (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id)) + { + for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) { + // We have diagnosed unused methods in traits + if matches!(def_kind, DefKind::Impl { of_trait: true }) + && tcx.def_kind(def_id) == DefKind::AssocFn + || def_kind == DefKind::Trait && tcx.def_kind(def_id) != DefKind::AssocFn + { + continue; + } + + if let Some(local_def_id) = def_id.as_local() + && !visitor.is_live_code(local_def_id) + { + let name = tcx.item_name(def_id); + let level = visitor.def_lint_level(local_def_id); + dead_codes.push(DeadItem { def_id: local_def_id, name, level }); } } - visitor.warn_multiple(item.owner_id.def_id, "used", dead_items, ReportOn::NamedField); + } + if !dead_codes.is_empty() { + visitor.warn_multiple(item.owner_id.def_id, "used", dead_codes, ReportOn::NamedField); } if !live_symbols.contains(&item.owner_id.def_id) { @@ -997,7 +1051,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { continue; } - let def_kind = tcx.def_kind(item.owner_id); if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind { let adt = tcx.adt_def(item.owner_id); let mut dead_variants = Vec::new(); @@ -1044,8 +1097,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { for foreign_item in module_items.foreign_items() { visitor.check_definition(foreign_item.owner_id.def_id); } - - // We do not warn trait items. } pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 77bfe57e370..a732bdbca51 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -8,6 +8,7 @@ use rustc_ast::Label; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, DiagnosticSymbolList, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan, + SubdiagnosticMessageOp, }; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -390,13 +391,6 @@ pub struct FfiConstInvalidTarget { pub attr_span: Span, } -#[derive(Diagnostic)] -#[diag(passes_ffi_returns_twice_invalid_target, code = E0724)] -pub struct FfiReturnsTwiceInvalidTarget { - #[primary_span] - pub attr_span: Span, -} - #[derive(LintDiagnostic)] #[diag(passes_must_use_async)] pub struct MustUseAsync { @@ -1739,7 +1733,7 @@ pub struct UnusedVariableTryPrefix { #[derive(Subdiagnostic)] pub enum UnusedVariableSugg { - #[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")] + #[multipart_suggestion(passes_suggestion, applicability = "maybe-incorrect")] TryPrefixSugg { #[suggestion_part(code = "_{name}")] spans: Vec<Span>, @@ -1760,7 +1754,7 @@ pub struct UnusedVariableStringInterp { } impl AddToDiagnostic for UnusedVariableStringInterp { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation); diag.multipart_suggestion( crate::fluent_generated::passes_string_interpolation_only_works, @@ -1778,7 +1772,7 @@ pub struct UnusedVarTryIgnore { } #[derive(Subdiagnostic)] -#[multipart_suggestion(passes_suggestion, applicability = "machine-applicable")] +#[multipart_suggestion(passes_suggestion, applicability = "maybe-incorrect")] pub struct UnusedVarTryIgnoreSugg { #[suggestion_part(code = "{name}: _")] pub shorthands: Vec<Span>, diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 862b76b1f60..064af5aec35 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -12,8 +12,6 @@ #![feature(map_try_insert)] #![feature(min_specialization)] #![feature(try_blocks)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index f7c382bcd7a..3a8dc377520 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -123,6 +123,7 @@ enum LiveNodeKind { VarDefNode(Span, HirId), ClosureNode, ExitNode, + ErrNode, } fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { @@ -133,6 +134,7 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { VarDefNode(s, _) => format!("Var def node [{}]", sm.span_to_diagnostic_string(s)), ClosureNode => "Closure node".to_owned(), ExitNode => "Exit node".to_owned(), + ErrNode => "Error node".to_owned(), } } @@ -967,10 +969,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Now that we know the label we're going to, // look it up in the continue loop nodes table - self.cont_ln - .get(&sc) - .cloned() - .unwrap_or_else(|| span_bug!(expr.span, "continue to unknown label")) + self.cont_ln.get(&sc).cloned().unwrap_or_else(|| { + self.ir.tcx.dcx().span_delayed_bug(expr.span, "continue to unknown label"); + self.ir.add_live_node(ErrNode) + }) } hir::ExprKind::Assign(ref l, ref r, _) => { diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 0f8cc583b03..e10a22cdf31 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -134,7 +134,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { Err(hir::LoopIdError::UnresolvedLabel) => None, }; - if let Some(Node::Block(_)) = loop_id.and_then(|id| self.tcx.opt_hir_node(id)) { + if let Some(Node::Block(_)) = loop_id.map(|id| self.tcx.hir_node(id)) { return; } @@ -186,7 +186,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { match destination.target_id { Ok(loop_id) => { - if let Node::Block(block) = self.tcx.opt_hir_node(loop_id).unwrap() { + if let Node::Block(block) = self.tcx.hir_node(loop_id) { self.sess.dcx().emit_err(ContinueLabeledBlock { span: e.span, block_span: block.span, diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index 88770b0c43b..2dffdc9846c 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessage}; +use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessageOp}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::thir::Pat; use rustc_middle::ty::Ty; @@ -23,7 +23,10 @@ impl<'tcx> Uncovered<'tcx> { span: Span, cx: &RustcMatchCheckCtxt<'p, 'tcx>, witnesses: Vec<WitnessPat<'p, 'tcx>>, - ) -> Self { + ) -> Self + where + 'tcx: 'p, + { let witness_1 = cx.hoist_witness_pat(witnesses.get(0).unwrap()); Self { span, @@ -59,10 +62,7 @@ pub struct Overlap<'tcx> { } impl<'tcx> AddToDiagnostic for Overlap<'tcx> { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { let Overlap { span, range } = self; // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 8e16d4d7bf4..164dc36b679 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -1,5 +1,8 @@ //! Analysis of patterns, notably match exhaustiveness checking. +#![allow(rustc::untranslatable_diagnostic)] +#![allow(rustc::diagnostic_outside_of_impl)] + pub mod constructor; #[cfg(feature = "rustc")] pub mod errors; @@ -119,7 +122,7 @@ pub trait TypeCx: Sized + fmt::Debug { /// `DeconstructedPat`. Only invoqued when `pat.ctor()` is `Struct | Variant(_) | UnionField`. fn write_variant_name( f: &mut fmt::Formatter<'_>, - pat: &crate::pat::DeconstructedPat<'_, Self>, + pat: &crate::pat::DeconstructedPat<Self>, ) -> fmt::Result; /// Raise a bug. @@ -130,9 +133,9 @@ pub trait TypeCx: Sized + fmt::Debug { /// The default implementation does nothing. fn lint_overlapping_range_endpoints( &self, - _pat: &DeconstructedPat<'_, Self>, + _pat: &DeconstructedPat<Self>, _overlaps_on: IntRange, - _overlaps_with: &[&DeconstructedPat<'_, Self>], + _overlaps_with: &[&DeconstructedPat<Self>], ) { } } @@ -140,7 +143,7 @@ pub trait TypeCx: Sized + fmt::Debug { /// The arm of a match expression. #[derive(Debug)] pub struct MatchArm<'p, Cx: TypeCx> { - pub pat: &'p DeconstructedPat<'p, Cx>, + pub pat: &'p DeconstructedPat<Cx>, pub has_guard: bool, pub arm_data: Cx::ArmData, } diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs index 3f1497540d2..30e775733de 100644 --- a/compiler/rustc_pattern_analysis/src/lints.rs +++ b/compiler/rustc_pattern_analysis/src/lints.rs @@ -10,7 +10,7 @@ use crate::MatchArm; /// Traverse the patterns to collect any variants of a non_exhaustive enum that fail to be mentioned /// in a given column. #[instrument(level = "debug", skip(cx), ret)] -fn collect_nonexhaustive_missing_variants<'a, 'p, 'tcx>( +fn collect_nonexhaustive_missing_variants<'p, 'tcx>( cx: &RustcMatchCheckCtxt<'p, 'tcx>, column: &PatternColumn<'p, RustcMatchCheckCtxt<'p, 'tcx>>, ) -> Result<Vec<WitnessPat<'p, 'tcx>>, ErrorGuaranteed> { diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index d419ee46a8e..9bde23c7bf1 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -6,7 +6,7 @@ use std::fmt; use smallvec::{smallvec, SmallVec}; use crate::constructor::{Constructor, Slice, SliceKind}; -use crate::{Captures, TypeCx}; +use crate::TypeCx; use self::Constructor::*; @@ -21,9 +21,9 @@ use self::Constructor::*; /// This happens if a private or `non_exhaustive` field is uninhabited, because the code mustn't /// observe that it is uninhabited. In that case that field is not included in `fields`. Care must /// be taken when converting to/from `thir::Pat`. -pub struct DeconstructedPat<'p, Cx: TypeCx> { +pub struct DeconstructedPat<Cx: TypeCx> { ctor: Constructor<Cx>, - fields: &'p [DeconstructedPat<'p, Cx>], + fields: Vec<DeconstructedPat<Cx>>, ty: Cx::Ty, /// Extra data to store in a pattern. `None` if the pattern is a wildcard that does not /// correspond to a user-supplied pattern. @@ -32,14 +32,20 @@ pub struct DeconstructedPat<'p, Cx: TypeCx> { useful: Cell<bool>, } -impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { +impl<Cx: TypeCx> DeconstructedPat<Cx> { pub fn wildcard(ty: Cx::Ty) -> Self { - DeconstructedPat { ctor: Wildcard, fields: &[], ty, data: None, useful: Cell::new(false) } + DeconstructedPat { + ctor: Wildcard, + fields: Vec::new(), + ty, + data: None, + useful: Cell::new(false), + } } pub fn new( ctor: Constructor<Cx>, - fields: &'p [DeconstructedPat<'p, Cx>], + fields: Vec<DeconstructedPat<Cx>>, ty: Cx::Ty, data: Cx::PatData, ) -> Self { @@ -62,17 +68,17 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { self.data.as_ref() } - pub fn iter_fields(&self) -> impl Iterator<Item = &'p DeconstructedPat<'p, Cx>> + Captures<'_> { + pub fn iter_fields<'a>(&'a self) -> impl Iterator<Item = &'a DeconstructedPat<Cx>> { self.fields.iter() } /// Specialize this pattern with a constructor. /// `other_ctor` can be different from `self.ctor`, but must be covered by it. - pub(crate) fn specialize( - &self, + pub(crate) fn specialize<'a>( + &'a self, other_ctor: &Constructor<Cx>, ctor_arity: usize, - ) -> SmallVec<[PatOrWild<'p, Cx>; 2]> { + ) -> SmallVec<[PatOrWild<'a, Cx>; 2]> { let wildcard_sub_tys = || (0..ctor_arity).map(|_| PatOrWild::Wild).collect(); match (&self.ctor, other_ctor) { // Return a wildcard for each field of `other_ctor`. @@ -139,7 +145,7 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> { } /// This is best effort and not good enough for a `Display` impl. -impl<'p, Cx: TypeCx> fmt::Debug for DeconstructedPat<'p, Cx> { +impl<Cx: TypeCx> fmt::Debug for DeconstructedPat<Cx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let pat = self; let mut first = true; @@ -221,7 +227,7 @@ pub(crate) enum PatOrWild<'p, Cx: TypeCx> { /// A non-user-provided wildcard, created during specialization. Wild, /// A user-provided pattern. - Pat(&'p DeconstructedPat<'p, Cx>), + Pat(&'p DeconstructedPat<Cx>), } impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> { @@ -236,7 +242,7 @@ impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> { impl<'p, Cx: TypeCx> Copy for PatOrWild<'p, Cx> {} impl<'p, Cx: TypeCx> PatOrWild<'p, Cx> { - pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat<'p, Cx>> { + pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat<Cx>> { match self { PatOrWild::Wild => None, PatOrWild::Pat(pat) => Some(pat), diff --git a/compiler/rustc_pattern_analysis/src/pat_column.rs b/compiler/rustc_pattern_analysis/src/pat_column.rs index 0339818d61d..ce14fdc364f 100644 --- a/compiler/rustc_pattern_analysis/src/pat_column.rs +++ b/compiler/rustc_pattern_analysis/src/pat_column.rs @@ -13,7 +13,7 @@ use crate::{Captures, MatchArm, TypeCx}; #[derive(Debug)] pub struct PatternColumn<'p, Cx: TypeCx> { /// This must not contain an or-pattern. `expand_and_push` takes care to expand them. - patterns: Vec<&'p DeconstructedPat<'p, Cx>>, + patterns: Vec<&'p DeconstructedPat<Cx>>, } impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { @@ -41,7 +41,7 @@ impl<'p, Cx: TypeCx> PatternColumn<'p, Cx> { pub fn head_ty(&self) -> Option<&Cx::Ty> { self.patterns.first().map(|pat| pat.ty()) } - pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'p DeconstructedPat<'p, Cx>> + Captures<'a> { + pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'p DeconstructedPat<Cx>> + Captures<'a> { self.patterns.iter().copied() } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index b60f32f71c2..a8fe0cb6a1d 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -1,8 +1,7 @@ -use smallvec::SmallVec; use std::fmt; use std::iter::once; -use rustc_arena::{DroplessArena, TypedArena}; +use rustc_arena::DroplessArena; use rustc_hir::def_id::DefId; use rustc_hir::HirId; use rustc_index::{Idx, IndexVec}; @@ -27,8 +26,7 @@ use crate::constructor::Constructor::*; pub type Constructor<'p, 'tcx> = crate::constructor::Constructor<RustcMatchCheckCtxt<'p, 'tcx>>; pub type ConstructorSet<'p, 'tcx> = crate::constructor::ConstructorSet<RustcMatchCheckCtxt<'p, 'tcx>>; -pub type DeconstructedPat<'p, 'tcx> = - crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>; +pub type DeconstructedPat<'p, 'tcx> = crate::pat::DeconstructedPat<RustcMatchCheckCtxt<'p, 'tcx>>; pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type Usefulness<'p, 'tcx> = crate::usefulness::Usefulness<'p, RustcMatchCheckCtxt<'p, 'tcx>>; pub type UsefulnessReport<'p, 'tcx> = @@ -64,7 +62,7 @@ impl<'tcx> RevealedTy<'tcx> { } #[derive(Clone)] -pub struct RustcMatchCheckCtxt<'p, 'tcx> { +pub struct RustcMatchCheckCtxt<'p, 'tcx: 'p> { pub tcx: TyCtxt<'tcx>, pub typeck_results: &'tcx ty::TypeckResults<'tcx>, /// The module in which the match occurs. This is necessary for @@ -74,8 +72,6 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx> { /// outside its module and should not be matchable with an empty match statement. pub module: DefId, pub param_env: ty::ParamEnv<'tcx>, - /// To allocate lowered patterns - pub pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>, /// To allocate the result of `self.ctor_sub_tys()` pub dropless_arena: &'p DroplessArena, /// Lint level at the match. @@ -91,13 +87,13 @@ pub struct RustcMatchCheckCtxt<'p, 'tcx> { pub known_valid_scrutinee: bool, } -impl<'p, 'tcx> fmt::Debug for RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> fmt::Debug for RustcMatchCheckCtxt<'p, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RustcMatchCheckCtxt").finish() } } -impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> { /// Type inference occasionally gives us opaque types in places where corresponding patterns /// have more specific types. To avoid inconsistencies as well as detect opaque uninhabited /// types, we use the corresponding concrete type if possible. @@ -459,21 +455,20 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { /// Note: the input patterns must have been lowered through /// `rustc_mir_build::thir::pattern::check_match::MatchVisitor::lower_pattern`. pub fn lower_pat(&self, pat: &'p Pat<'tcx>) -> DeconstructedPat<'p, 'tcx> { - let singleton = |pat| std::slice::from_ref(self.pattern_arena.alloc(pat)); let cx = self; let ty = cx.reveal_opaque_ty(pat.ty); let ctor; - let fields: &[_]; + let mut fields: Vec<_>; match &pat.kind { PatKind::AscribeUserType { subpattern, .. } | PatKind::InlineConstant { subpattern, .. } => return self.lower_pat(subpattern), PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat), PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard; - fields = &[]; + fields = vec![]; } PatKind::Deref { subpattern } => { - fields = singleton(self.lower_pat(subpattern)); + fields = vec![self.lower_pat(subpattern)]; ctor = match ty.kind() { // This is a box pattern. ty::Adt(adt, ..) if adt.is_box() => Struct, @@ -485,15 +480,14 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { match ty.kind() { ty::Tuple(fs) => { ctor = Struct; - let mut wilds: SmallVec<[_; 2]> = fs + fields = fs .iter() .map(|ty| cx.reveal_opaque_ty(ty)) .map(|ty| DeconstructedPat::wildcard(ty)) .collect(); for pat in subpatterns { - wilds[pat.field.index()] = self.lower_pat(&pat.pattern); + fields[pat.field.index()] = self.lower_pat(&pat.pattern); } - fields = cx.pattern_arena.alloc_from_iter(wilds); } ty::Adt(adt, args) if adt.is_box() => { // The only legal patterns of type `Box` (outside `std`) are `_` and box @@ -515,7 +509,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { DeconstructedPat::wildcard(self.reveal_opaque_ty(args.type_at(0))) }; ctor = Struct; - fields = singleton(pat); + fields = vec![pat]; } ty::Adt(adt, _) => { ctor = match pat.kind { @@ -535,14 +529,12 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { ty }, ); - let mut wilds: SmallVec<[_; 2]> = - tys.map(|ty| DeconstructedPat::wildcard(ty)).collect(); + fields = tys.map(|ty| DeconstructedPat::wildcard(ty)).collect(); for pat in subpatterns { if let Some(i) = field_id_to_id[pat.field.index()] { - wilds[i] = self.lower_pat(&pat.pattern); + fields[i] = self.lower_pat(&pat.pattern); } } - fields = cx.pattern_arena.alloc_from_iter(wilds); } _ => bug!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, ty), } @@ -554,7 +546,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { Some(b) => Bool(b), None => Opaque(OpaqueId::new()), }; - fields = &[]; + fields = vec![]; } ty::Char | ty::Int(_) | ty::Uint(_) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -570,7 +562,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } None => Opaque(OpaqueId::new()), }; - fields = &[]; + fields = vec![]; } ty::Float(ty::FloatTy::F32) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -581,7 +573,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } None => Opaque(OpaqueId::new()), }; - fields = &[]; + fields = vec![]; } ty::Float(ty::FloatTy::F64) => { ctor = match value.try_eval_bits(cx.tcx, cx.param_env) { @@ -592,7 +584,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } None => Opaque(OpaqueId::new()), }; - fields = &[]; + fields = vec![]; } ty::Ref(_, t, _) if t.is_str() => { // We want a `&str` constant to behave like a `Deref` pattern, to be compatible @@ -603,16 +595,16 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { // subfields. // Note: `t` is `str`, not `&str`. let ty = self.reveal_opaque_ty(*t); - let subpattern = DeconstructedPat::new(Str(*value), &[], ty, pat); + let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), ty, pat); ctor = Ref; - fields = singleton(subpattern) + fields = vec![subpattern] } // All constants that can be structurally matched have already been expanded // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are // opaque. _ => { ctor = Opaque(OpaqueId::new()); - fields = &[]; + fields = vec![]; } } } @@ -649,7 +641,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } _ => bug!("invalid type for range pattern: {}", ty.inner()), }; - fields = &[]; + fields = vec![]; } PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => { let array_len = match ty.kind() { @@ -665,26 +657,23 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { SliceKind::FixedLen(prefix.len() + suffix.len()) }; ctor = Slice(Slice::new(array_len, kind)); - fields = cx.pattern_arena.alloc_from_iter( - prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)), - ) + fields = prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)).collect(); } PatKind::Or { .. } => { ctor = Or; let pats = expand_or_pat(pat); - fields = - cx.pattern_arena.alloc_from_iter(pats.into_iter().map(|p| self.lower_pat(p))) + fields = pats.into_iter().map(|p| self.lower_pat(p)).collect(); } PatKind::Never => { // A never pattern matches all the values of its type (namely none). Moreover it // must be compatible with other constructors, since we can use `!` on a type like // `Result<!, !>` which has other constructors. Hence we lower it as a wildcard. ctor = Wildcard; - fields = &[]; + fields = vec![]; } PatKind::Error(_) => { ctor = Opaque(OpaqueId::new()); - fields = &[]; + fields = vec![]; } } DeconstructedPat::new(ctor, fields, ty, pat) @@ -855,7 +844,7 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> { } } -impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { +impl<'p, 'tcx: 'p> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { type Ty = RevealedTy<'tcx>; type Error = ErrorGuaranteed; type VariantIdx = VariantIdx; @@ -889,7 +878,7 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { fn write_variant_name( f: &mut fmt::Formatter<'_>, - pat: &crate::pat::DeconstructedPat<'_, Self>, + pat: &crate::pat::DeconstructedPat<Self>, ) -> fmt::Result { if let ty::Adt(adt, _) = pat.ty().kind() { if adt.is_box() { @@ -908,9 +897,9 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> { fn lint_overlapping_range_endpoints( &self, - pat: &crate::pat::DeconstructedPat<'_, Self>, + pat: &crate::pat::DeconstructedPat<Self>, overlaps_on: IntRange, - overlaps_with: &[&crate::pat::DeconstructedPat<'_, Self>], + overlaps_with: &[&crate::pat::DeconstructedPat<Self>], ) { let overlap_as_pat = self.hoist_pat_range(&overlaps_on, *pat.ty()); let overlaps: Vec<_> = overlaps_with diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index bbb68b353e4..80a807b4f27 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -767,12 +767,6 @@ impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> { fn ctor_arity(&self, ctor: &Constructor<Cx>) -> usize { self.cx.ctor_arity(ctor, self.ty) } - fn ctor_sub_tys( - &'a self, - ctor: &'a Constructor<Cx>, - ) -> impl Iterator<Item = Cx::Ty> + ExactSizeIterator + Captures<'a> { - self.cx.ctor_sub_tys(ctor, self.ty) - } fn ctors_for_ty(&self) -> Result<ConstructorSet<Cx>, Cx::Error> { self.cx.ctors_for_ty(self.ty) } @@ -828,6 +822,38 @@ impl fmt::Display for ValidityConstraint { } } +/// Data about a place under investigation. +struct PlaceInfo<Cx: TypeCx> { + /// The type of the place. + ty: Cx::Ty, + /// Whether the place is known to contain valid data. + validity: ValidityConstraint, + /// Whether the place is the scrutinee itself or a subplace of it. + is_scrutinee: bool, +} + +impl<Cx: TypeCx> PlaceInfo<Cx> { + fn specialize<'a>( + &'a self, + cx: &'a Cx, + ctor: &'a Constructor<Cx>, + ) -> impl Iterator<Item = Self> + ExactSizeIterator + Captures<'a> { + let ctor_sub_tys = cx.ctor_sub_tys(ctor, &self.ty); + let ctor_sub_validity = self.validity.specialize(ctor); + ctor_sub_tys.map(move |ty| PlaceInfo { + ty, + validity: ctor_sub_validity, + is_scrutinee: false, + }) + } +} + +impl<Cx: TypeCx> Clone for PlaceInfo<Cx> { + fn clone(&self) -> Self { + Self { ty: self.ty.clone(), validity: self.validity, is_scrutinee: self.is_scrutinee } + } +} + /// Represents a pattern-tuple under investigation. // The three lifetimes are: // - 'p coming from the input @@ -848,7 +874,7 @@ impl<'p, Cx: TypeCx> Clone for PatStack<'p, Cx> { } impl<'p, Cx: TypeCx> PatStack<'p, Cx> { - fn from_pattern(pat: &'p DeconstructedPat<'p, Cx>) -> Self { + fn from_pattern(pat: &'p DeconstructedPat<Cx>) -> Self { PatStack { pats: smallvec![PatOrWild::Pat(pat)], relevant: true } } @@ -1001,10 +1027,9 @@ struct Matrix<'p, Cx: TypeCx> { /// each column must have the same type. Each column corresponds to a place within the /// scrutinee. rows: Vec<MatrixRow<'p, Cx>>, - /// Track the type of each column/place. - place_ty: SmallVec<[Cx::Ty; 2]>, - /// Track for each column/place whether it contains a known valid value. - place_validity: SmallVec<[ValidityConstraint; 2]>, + /// Track info about each place. Each place corresponds to a column in `rows`, and their types + /// must match. + place_info: SmallVec<[PlaceInfo<Cx>; 2]>, /// Track whether the virtual wildcard row used to compute exhaustiveness is relevant. See top /// of the file for details on relevancy. wildcard_row_is_relevant: bool, @@ -1032,10 +1057,10 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { scrut_ty: Cx::Ty, scrut_validity: ValidityConstraint, ) -> Self { + let place_info = PlaceInfo { ty: scrut_ty, validity: scrut_validity, is_scrutinee: true }; let mut matrix = Matrix { rows: Vec::with_capacity(arms.len()), - place_ty: smallvec![scrut_ty], - place_validity: smallvec![scrut_validity], + place_info: smallvec![place_info], wildcard_row_is_relevant: true, }; for (row_id, arm) in arms.iter().enumerate() { @@ -1051,11 +1076,11 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { matrix } - fn head_ty(&self) -> Option<&Cx::Ty> { - self.place_ty.first() + fn head_place(&self) -> Option<&PlaceInfo<Cx>> { + self.place_info.first() } fn column_count(&self) -> usize { - self.place_ty.len() + self.place_info.len() } fn rows( @@ -1083,18 +1108,13 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> { ctor: &Constructor<Cx>, ctor_is_relevant: bool, ) -> Result<Matrix<'p, Cx>, Cx::Error> { - let ctor_sub_tys = pcx.ctor_sub_tys(ctor); - let arity = ctor_sub_tys.len(); - let specialized_place_ty = ctor_sub_tys.chain(self.place_ty[1..].iter().cloned()).collect(); - let ctor_sub_validity = self.place_validity[0].specialize(ctor); - let specialized_place_validity = std::iter::repeat(ctor_sub_validity) - .take(arity) - .chain(self.place_validity[1..].iter().copied()) - .collect(); + let subfield_place_info = self.place_info[0].specialize(pcx.cx, ctor); + let arity = subfield_place_info.len(); + let specialized_place_info = + subfield_place_info.chain(self.place_info[1..].iter().cloned()).collect(); let mut matrix = Matrix { rows: Vec::new(), - place_ty: specialized_place_ty, - place_validity: specialized_place_validity, + place_info: specialized_place_info, wildcard_row_is_relevant: self.wildcard_row_is_relevant && ctor_is_relevant, }; for (i, row) in self.rows().enumerate() { @@ -1127,11 +1147,11 @@ impl<'p, Cx: TypeCx> fmt::Debug for Matrix<'p, Cx> { .map(|row| row.iter().map(|pat| format!("{pat:?}")).collect()) .collect(); pretty_printed_matrix - .push(self.place_validity.iter().map(|validity| format!("{validity}")).collect()); + .push(self.place_info.iter().map(|place| format!("{}", place.validity)).collect()); let column_count = self.column_count(); assert!(self.rows.iter().all(|row| row.len() == column_count)); - assert!(self.place_validity.len() == column_count); + assert!(self.place_info.len() == column_count); let column_widths: Vec<usize> = (0..column_count) .map(|col| pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0)) .collect(); @@ -1432,11 +1452,10 @@ fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>( /// - unspecialization, where we lift the results from the previous step into results for this step /// (using `apply_constructor` and by updating `row.useful` for each parent row). /// This is all explained at the top of the file. -#[instrument(level = "debug", skip(mcx, is_top_level), ret)] +#[instrument(level = "debug", skip(mcx), ret)] fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( mcx: UsefulnessCtxt<'a, Cx>, matrix: &mut Matrix<'p, Cx>, - is_top_level: bool, ) -> Result<WitnessMatrix<Cx>, Cx::Error> { debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count())); @@ -1447,7 +1466,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( return Ok(WitnessMatrix::empty()); } - let Some(ty) = matrix.head_ty().cloned() else { + let Some(place) = matrix.head_place() else { // The base case: there are no columns in the matrix. We are morally pattern-matching on (). // A row is useful iff it has no (unguarded) rows above it. let mut useful = true; // Whether the next row is useful. @@ -1467,18 +1486,17 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( }; }; - debug!("ty: {ty:?}"); - let pcx = &PlaceCtxt { cx: mcx.tycx, ty: &ty }; + let ty = &place.ty.clone(); // Clone it out so we can mutate `matrix` later. + let pcx = &PlaceCtxt { cx: mcx.tycx, ty }; + debug!("ty: {:?}", pcx.ty); let ctors_for_ty = pcx.ctors_for_ty()?; - // Whether the place/column we are inspecting is known to contain valid data. - let place_validity = matrix.place_validity[0]; // We treat match scrutinees of type `!` or `EmptyEnum` differently. let is_toplevel_exception = - is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors); + place.is_scrutinee && matches!(ctors_for_ty, ConstructorSet::NoConstructors); // Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if // it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`). - let empty_arms_are_unreachable = place_validity.is_known_valid() + let empty_arms_are_unreachable = place.validity.is_known_valid() && (is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on() || mcx.tycx.is_min_exhaustive_patterns_feature_on()); @@ -1502,11 +1520,9 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( split_ctors.push(Constructor::Missing); } - // Decide what constructors to report. - let is_integers = matches!(ctors_for_ty, ConstructorSet::Integers { .. }); - let always_report_all = is_top_level && !is_integers; - // Whether we should report "Enum::A and Enum::C are missing" or "_ is missing". - let report_individual_missing_ctors = always_report_all || !all_missing; + // Whether we should report "Enum::A and Enum::C are missing" or "_ is missing". At the top + // level we prefer to list all constructors. + let report_individual_missing_ctors = place.is_scrutinee || !all_missing; // Which constructors are considered missing. We ensure that `!missing_ctors.is_empty() => // split_ctors.contains(Missing)`. The converse usually holds except when // `!place_validity.is_known_valid()`. @@ -1525,7 +1541,7 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>( let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty(); let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant)?; let mut witnesses = ensure_sufficient_stack(|| { - compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false) + compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix) })?; // Transform witnesses for `spec_matrix` into witnesses for `matrix`. @@ -1575,7 +1591,7 @@ pub enum Usefulness<'p, Cx: TypeCx> { /// The arm is useful. This additionally carries a set of or-pattern branches that have been /// found to be redundant despite the overall arm being useful. Used only in the presence of /// or-patterns, otherwise it stays empty. - Useful(Vec<&'p DeconstructedPat<'p, Cx>>), + Useful(Vec<&'p DeconstructedPat<Cx>>), /// The arm is redundant and can be removed without changing the behavior of the match /// expression. Redundant, @@ -1600,8 +1616,7 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>( ) -> Result<UsefulnessReport<'p, Cx>, Cx::Error> { let cx = UsefulnessCtxt { tycx }; let mut matrix = Matrix::new(arms, scrut_ty, scrut_validity); - let non_exhaustiveness_witnesses = - compute_exhaustiveness_and_usefulness(cx, &mut matrix, true)?; + let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness(cx, &mut matrix)?; let non_exhaustiveness_witnesses: Vec<_> = non_exhaustiveness_witnesses.single_column(); let arm_usefulness: Vec<_> = arms diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index 90803c20d43..e7a32771f35 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -16,5 +16,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } +rustc_ty_utils = { path = "../rustc_ty_utils" } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index a37d8822480..6d8e7ba937e 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -5,8 +5,6 @@ #![feature(associated_type_defaults)] #![feature(try_blocks)] #![feature(let_chains)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; @@ -21,7 +19,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, PatKind}; +use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind}; use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level}; use rustc_middle::query::Providers; use rustc_middle::ty::GenericArgs; @@ -98,9 +96,6 @@ trait DefIdVisitor<'tcx> { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<Self::BreakTy> { self.skeleton().visit_trait(trait_ref) } - fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<Self::BreakTy> { - self.skeleton().visit_projection_ty(projection) - } fn visit_predicates( &mut self, predicates: ty::GenericPredicates<'tcx>, @@ -173,6 +168,10 @@ where { type BreakTy = V::BreakTy; + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> { + self.visit_clause(p.as_clause().unwrap()) + } + fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> { let tcx = self.def_id_visitor.tcx(); // GenericArgs are not visited here because they are visited below @@ -1076,6 +1075,14 @@ impl<'tcx> TypePrivacyVisitor<'tcx> { } } +impl<'tcx> rustc_ty_utils::sig_types::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> { + type BreakTy = (); + fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> ControlFlow<()> { + self.span = span; + value.visit_with(&mut self.skeleton()) + } +} + impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { fn visit_nested_body(&mut self, body_id: hir::BodyId) { let old_maybe_typeck_results = @@ -1086,18 +1093,15 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) { self.span = hir_ty.span; - if let Some(typeck_results) = self.maybe_typeck_results { - // Types in bodies. - if self.visit(typeck_results.node_type(hir_ty.hir_id)).is_break() { - return; - } - } else { - // Types in signatures. - // FIXME: This is very ineffective. Ideally each HIR type should be converted - // into a semantic type only once and the result should be cached somehow. - if self.visit(rustc_hir_analysis::hir_ty_to_ty(self.tcx, hir_ty)).is_break() { - return; - } + if self + .visit( + self.maybe_typeck_results + .unwrap_or_else(|| span_bug!(hir_ty.span, "`hir::Ty` outside of a body")) + .node_type(hir_ty.hir_id), + ) + .is_break() + { + return; } intravisit::walk_ty(self, hir_ty); @@ -1105,56 +1109,20 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { self.span = inf.span; - if let Some(typeck_results) = self.maybe_typeck_results { - if let Some(ty) = typeck_results.node_type_opt(inf.hir_id) { - if self.visit(ty).is_break() { - return; - } - } else { - // FIXME: check types of const infers here. + if let Some(ty) = self + .maybe_typeck_results + .unwrap_or_else(|| span_bug!(inf.span, "`hir::InferArg` outside of a body")) + .node_type_opt(inf.hir_id) + { + if self.visit(ty).is_break() { + return; } } else { - span_bug!(self.span, "`hir::InferArg` outside of a body"); + // FIXME: check types of const infers here. } intravisit::walk_inf(self, inf); } - fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef<'tcx>) { - self.span = trait_ref.path.span; - if self.maybe_typeck_results.is_some() { - // Privacy of traits in bodies is checked as a part of trait object types. - } else { - let bounds = rustc_hir_analysis::hir_trait_to_predicates( - self.tcx, - trait_ref, - // NOTE: This isn't really right, but the actual type doesn't matter here. It's - // just required by `ty::TraitRef`. - self.tcx.types.never, - ); - - for (clause, _) in bounds.clauses() { - match clause.kind().skip_binder() { - ty::ClauseKind::Trait(trait_predicate) => { - if self.visit_trait(trait_predicate.trait_ref).is_break() { - return; - } - } - ty::ClauseKind::Projection(proj_predicate) => { - let term = self.visit(proj_predicate.term); - if term.is_break() - || self.visit_projection_ty(proj_predicate.projection_ty).is_break() - { - return; - } - } - _ => {} - } - } - } - - intravisit::walk_trait_ref(self, trait_ref); - } - // Check types of expressions fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { if self.check_expr_pat_type(expr.hir_id, expr.span) { @@ -1727,7 +1695,26 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { // inferred types of expressions and patterns. let span = tcx.def_span(module_def_id); let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span }; - tcx.hir().visit_item_likes_in_module(module_def_id, &mut visitor); + + let module = tcx.hir_module_items(module_def_id); + for def_id in module.definitions() { + rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor); + + if let Some(body_id) = tcx.hir().maybe_body_owned_by(def_id) { + visitor.visit_nested_body(body_id); + } + } + + for id in module.items() { + if let ItemKind::Impl(i) = tcx.hir().item(id).kind { + if let Some(item) = i.of_trait { + let trait_ref = tcx.impl_trait_ref(id.owner_id.def_id).unwrap(); + let trait_ref = trait_ref.instantiate_identity(); + visitor.span = item.path.span; + visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref.print_only_trait_path()); + } + } + } } fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities { diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 818a67a7deb..0fe5b9c664a 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -6,8 +6,6 @@ #![feature(min_specialization)] #![feature(rustc_attrs)] #![allow(rustc::potential_query_instability, unused_parens)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 2faa4876798..b6ac54a9ab5 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -52,7 +52,7 @@ impl From<DepNodeIndex> for QueryInvocationId { } } -pub(crate) struct MarkFrame<'a> { +pub struct MarkFrame<'a> { index: SerializedDepNodeIndex, parent: Option<&'a MarkFrame<'a>>, } @@ -754,7 +754,6 @@ impl<D: Deps> DepGraphData<D> { &self, qcx: Qcx, parent_dep_node_index: SerializedDepNodeIndex, - dep_node: &DepNode, frame: Option<&MarkFrame<'_>>, ) -> Option<()> { let dep_dep_node_color = self.colors.get(parent_dep_node_index); @@ -861,7 +860,7 @@ impl<D: Deps> DepGraphData<D> { let prev_deps = self.previous.edge_targets_from(prev_dep_node_index); for dep_dep_node_index in prev_deps { - self.try_mark_parent_green(qcx, dep_dep_node_index, dep_node, Some(&frame))?; + self.try_mark_parent_green(qcx, dep_dep_node_index, Some(&frame))?; } // If we got here without hitting a `return` that means that all diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs index 9b66b9a48d9..416f556f57d 100644 --- a/compiler/rustc_query_system/src/lib.rs +++ b/compiler/rustc_query_system/src/lib.rs @@ -4,8 +4,6 @@ #![feature(min_specialization)] #![feature(let_chains)] #![allow(rustc::potential_query_instability, internal_features)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 02847a0f5f9..0747685c35c 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -118,17 +118,27 @@ resolve_forward_declared_generic_param = .label = defaulted generic parameters cannot be forward declared resolve_generic_params_from_outer_item = - can't use generic parameters from outer item - .label = use of generic parameter from outer item + can't use {$is_self -> + [true] `Self` + *[false] generic parameters + } from outer item + .label = use of {$is_self -> + [true] `Self` + *[false] generic parameter + } from outer item .refer_to_type_directly = refer to the type directly here instead .suggestion = try introducing a local generic parameter here +resolve_generic_params_from_outer_item_const = a `const` is a separate item from the item that contains it + resolve_generic_params_from_outer_item_const_param = const parameter from outer item resolve_generic_params_from_outer_item_self_ty_alias = `Self` type implicitly declared here, by this `impl` resolve_generic_params_from_outer_item_self_ty_param = can't use `Self` here +resolve_generic_params_from_outer_item_static = a `static` is a separate item from the item that contains it + resolve_generic_params_from_outer_item_ty_param = type parameter from outer item @@ -292,6 +302,9 @@ resolve_underscore_lifetime_name_cannot_be_used_here = resolve_unexpected_res_change_ty_to_const_param_sugg = you might have meant to write a const parameter here +resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg = + if you meant to collect the rest of the slice in `{$ident}`, use the at operator + resolve_unreachable_label = use of unreachable label `{$name}` .label = unreachable label `{$name}` diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index f3a6eb65a72..d91a865e38a 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -561,13 +561,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { resolution_error: ResolutionError<'a>, ) -> DiagnosticBuilder<'_> { match resolution_error { - ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params) => { + ResolutionError::GenericParamsFromOuterItem(outer_res, has_generic_params, def_kind) => { use errs::GenericParamsFromOuterItemLabel as Label; + let static_or_const = match def_kind { + DefKind::Static(_) => Some(errs::GenericParamsFromOuterItemStaticOrConst::Static), + DefKind::Const => Some(errs::GenericParamsFromOuterItemStaticOrConst::Const), + _ => None, + }; + let is_self = matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }); let mut err = errs::GenericParamsFromOuterItem { span, label: None, refer_to_type_directly: None, sugg: None, + static_or_const, + is_self, }; let sm = self.tcx.sess.source_map(); diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 655fc9812d7..adc4cd911a7 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -45,6 +45,17 @@ pub(crate) struct GenericParamsFromOuterItem { pub(crate) refer_to_type_directly: Option<Span>, #[subdiagnostic] pub(crate) sugg: Option<GenericParamsFromOuterItemSugg>, + #[subdiagnostic] + pub(crate) static_or_const: Option<GenericParamsFromOuterItemStaticOrConst>, + pub(crate) is_self: bool, +} + +#[derive(Subdiagnostic)] +pub(crate) enum GenericParamsFromOuterItemStaticOrConst { + #[note(resolve_generic_params_from_outer_item_static)] + Static, + #[note(resolve_generic_params_from_outer_item_const)] + Const, } #[derive(Subdiagnostic)] @@ -800,3 +811,17 @@ pub(crate) struct UnexpectedResChangeTyToConstParamSugg { #[applicability] pub applicability: Applicability, } + +#[derive(Subdiagnostic)] +#[suggestion( + resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg, + code = "{snippet}", + applicability = "maybe-incorrect", + style = "verbose" +)] +pub(crate) struct UnexpectedResUseAtOpInSlicePatWithRangeSugg { + #[primary_span] + pub span: Span, + pub ident: Ident, + pub snippet: String, +} diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 7fb9db16e9c..e47f2bdd4d2 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -10,9 +10,7 @@ use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; -use crate::late::{ - ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind, -}; +use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind}; use crate::macros::{sub_namespace_match, MacroRulesScope}; use crate::BindingKey; use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize}; @@ -1090,7 +1088,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { | RibKind::ForwardGenericParamBan => { // Nothing to do. Continue. } - RibKind::Item(_) | RibKind::AssocItem => { + RibKind::Item(..) | RibKind::AssocItem => { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. @@ -1155,7 +1153,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => { for rib in ribs { - let has_generic_params: HasGenericParams = match rib.kind { + let (has_generic_params, def_kind) = match rib.kind { RibKind::Normal | RibKind::FnOrCoroutine | RibKind::Module(..) @@ -1213,7 +1211,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } // This was an attempt to use a type parameter outside its scope. - RibKind::Item(has_generic_params) => has_generic_params, + RibKind::Item(has_generic_params, def_kind) => { + (has_generic_params, def_kind) + } RibKind::ConstParamTy => { if let Some(span) = finalize { self.report_error( @@ -1231,7 +1231,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(span) = finalize { self.report_error( span, - ResolutionError::GenericParamsFromOuterItem(res, has_generic_params), + ResolutionError::GenericParamsFromOuterItem( + res, + has_generic_params, + def_kind, + ), ); } return Res::Err; @@ -1239,7 +1243,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } Res::Def(DefKind::ConstParam, _) => { for rib in ribs { - let has_generic_params = match rib.kind { + let (has_generic_params, def_kind) = match rib.kind { RibKind::Normal | RibKind::FnOrCoroutine | RibKind::Module(..) @@ -1276,7 +1280,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { continue; } - RibKind::Item(has_generic_params) => has_generic_params, + RibKind::Item(has_generic_params, def_kind) => { + (has_generic_params, def_kind) + } RibKind::ConstParamTy => { if let Some(span) = finalize { self.report_error( @@ -1295,7 +1301,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(span) = finalize { self.report_error( span, - ResolutionError::GenericParamsFromOuterItem(res, has_generic_params), + ResolutionError::GenericParamsFromOuterItem( + res, + has_generic_params, + def_kind, + ), ); } return Res::Err; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 1f2803d4368..6bd221ff058 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -23,6 +23,7 @@ use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate}; +use rustc_metadata::creader::CStore; use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::{bug, span_bug}; use rustc_session::config::{CrateType, ResolveDocLinks}; @@ -185,7 +186,7 @@ pub(crate) enum RibKind<'a> { FnOrCoroutine, /// We passed through an item scope. Disallow upvars. - Item(HasGenericParams), + Item(HasGenericParams, DefKind), /// We're in a constant item. Can't refer to dynamic stuff. /// @@ -225,7 +226,7 @@ impl RibKind<'_> { | RibKind::MacroDefinition(_) | RibKind::ConstParamTy | RibKind::InlineAsmSym => false, - RibKind::AssocItem | RibKind::Item(_) | RibKind::ForwardGenericParamBan => true, + RibKind::AssocItem | RibKind::Item(..) | RibKind::ForwardGenericParamBan => true, } } @@ -869,11 +870,12 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id)); + let def_kind = self.r.local_def_kind(foreign_item.id); match foreign_item.kind { ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), LifetimeRibKind::Generics { binder: foreign_item.id, kind: LifetimeBinderKind::Item, @@ -885,7 +887,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, ForeignItemKind::Fn(box Fn { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), LifetimeRibKind::Generics { binder: foreign_item.id, kind: LifetimeBinderKind::Function, @@ -895,7 +897,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, ); } ForeignItemKind::Static(..) => { - self.with_static_rib(|this| { + self.with_static_rib(def_kind, |this| { visit::walk_foreign_item(this, foreign_item); }); } @@ -1644,7 +1646,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { debug!(?rib.kind); match rib.kind { LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { - let res = self.create_fresh_lifetime(lifetime.id, lifetime.ident, binder); + let res = self.create_fresh_lifetime(lifetime.ident, binder); self.record_lifetime_res(lifetime.id, res, elision_candidate); return; } @@ -1736,7 +1738,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn create_fresh_lifetime(&mut self, id: NodeId, ident: Ident, binder: NodeId) -> LifetimeRes { + fn create_fresh_lifetime(&mut self, ident: Ident, binder: NodeId) -> LifetimeRes { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); debug!(?ident.span); @@ -1757,7 +1759,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { #[instrument(level = "debug", skip(self))] fn resolve_elided_lifetimes_in_path( &mut self, - path_id: NodeId, partial_res: PartialRes, path: &[Segment], source: PathSource<'_>, @@ -1890,7 +1891,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Group all suggestions into the first record. let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime); for id in node_ids { - let res = self.create_fresh_lifetime(id, ident, binder); + let res = self.create_fresh_lifetime(ident, binder); self.record_lifetime_res( id, res, @@ -2266,10 +2267,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) { debug!("resolve_adt"); + let kind = self.r.local_def_kind(item.id); self.with_current_self_item(item, |this| { this.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), kind), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Item, @@ -2343,11 +2345,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let name = item.ident.name; debug!("(resolving item) resolving {} ({:?})", name, item.kind); + let def_kind = self.r.local_def_kind(item.id); match item.kind { ItemKind::TyAlias(box TyAlias { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Item, @@ -2360,7 +2363,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::Fn(box Fn { ref generics, .. }) => { self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Function, @@ -2399,7 +2402,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Item, @@ -2420,7 +2423,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // Create a new rib for the trait-wide type parameters. self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::Item, @@ -2454,7 +2457,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => { - self.with_static_rib(|this| { + self.with_static_rib(def_kind, |this| { this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| { this.visit_ty(ty); }); @@ -2469,11 +2472,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => { self.with_generic_param_rib( &generics.params, - RibKind::Item(if self.r.tcx.features().generic_const_items { - HasGenericParams::Yes(generics.span) - } else { - HasGenericParams::No - }), + RibKind::Item( + if self.r.tcx.features().generic_const_items { + HasGenericParams::Yes(generics.span) + } else { + HasGenericParams::No + }, + def_kind, + ), LifetimeRibKind::Generics { binder: item.id, kind: LifetimeBinderKind::ConstItem, @@ -2558,7 +2564,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let mut add_bindings_for_ns = |ns| { let parent_rib = self.ribs[ns] .iter() - .rfind(|r| matches!(r.kind, RibKind::Item(_))) + .rfind(|r| matches!(r.kind, RibKind::Item(..))) .expect("associated item outside of an item"); seen_bindings.extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span))); }; @@ -2693,8 +2699,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.label_ribs.pop(); } - fn with_static_rib(&mut self, f: impl FnOnce(&mut Self)) { - let kind = RibKind::Item(HasGenericParams::No); + fn with_static_rib(&mut self, def_kind: DefKind, f: impl FnOnce(&mut Self)) { + let kind = RibKind::Item(HasGenericParams::No, def_kind); self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f)) } @@ -2875,7 +2881,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // If applicable, create a rib for the type parameters. self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span)), + RibKind::Item(HasGenericParams::Yes(generics.span), self.r.local_def_kind(item_id)), LifetimeRibKind::Generics { span: generics.span, binder: item_id, @@ -3935,7 +3941,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if record_partial_res == RecordPartialRes::Yes { // Avoid recording definition of `A::B` in `<T as A>::B::C`. self.r.record_partial_res(node_id, partial_res); - self.resolve_elided_lifetimes_in_path(node_id, partial_res, path, source, path_span); + self.resolve_elided_lifetimes_in_path(partial_res, path, source, path_span); } partial_res @@ -4541,14 +4547,20 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { if let Some(res) = res && let Some(def_id) = res.opt_def_id() && !def_id.is_local() - && self.r.tcx.crate_types().contains(&CrateType::ProcMacro) - && matches!( - self.r.tcx.sess.opts.resolve_doc_links, - ResolveDocLinks::ExportedMetadata - ) { - // Encoding foreign def ids in proc macro crate metadata will ICE. - return None; + if self.r.tcx.crate_types().contains(&CrateType::ProcMacro) + && matches!( + self.r.tcx.sess.opts.resolve_doc_links, + ResolveDocLinks::ExportedMetadata + ) + { + // Encoding foreign def ids in proc macro crate metadata will ICE. + return None; + } + // Doc paths should be resolved speculatively and should not produce any + // diagnostics, but if they are indeed resolved, then we need to keep the + // corresponding crate alive. + CStore::from_tcx_mut(self.r.tcx).set_used_recursively(def_id.krate); } res }); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 310c126213a..5d712461993 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1077,24 +1077,34 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err: &mut Diagnostic, path: &[Segment], ) { - if let Some(pat) = self.diagnostic_metadata.current_pat - && let ast::PatKind::Range(Some(start), None, range) = &pat.kind - && let ExprKind::Path(None, range_path) = &start.kind + let Some(pat) = self.diagnostic_metadata.current_pat else { return }; + let (bound, side, range) = match &pat.kind { + ast::PatKind::Range(Some(bound), None, range) => (bound, Side::Start, range), + ast::PatKind::Range(None, Some(bound), range) => (bound, Side::End, range), + _ => return, + }; + if let ExprKind::Path(None, range_path) = &bound.kind && let [segment] = &range_path.segments[..] && let [s] = path && segment.ident == s.ident + && segment.ident.span.eq_ctxt(range.span) { - // We've encountered `[first, rest..]` where the user might have meant - // `[first, rest @ ..]` (#88404). - err.span_suggestion_verbose( - segment.ident.span.between(range.span), - format!( - "if you meant to collect the rest of the slice in `{}`, use the at operator", - segment.ident, - ), - " @ ", - Applicability::MaybeIncorrect, - ); + // We've encountered `[first, rest..]` (#88404) or `[first, ..rest]` (#120591) + // where the user might have meant `[first, rest @ ..]`. + let (span, snippet) = match side { + Side::Start => (segment.ident.span.between(range.span), " @ ".into()), + Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)), + }; + err.subdiagnostic(errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg { + span, + ident: segment.ident, + snippet, + }); + } + + enum Side { + Start, + End, } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 9d09d060b59..6c0f2b89347 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -17,7 +17,9 @@ #![feature(let_chains)] #![feature(rustc_attrs)] #![allow(rustdoc::private_intra_doc_links)] +#![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::potential_query_instability)] +#![allow(rustc::untranslatable_diagnostic)] #![allow(internal_features)] #[macro_use] @@ -184,7 +186,7 @@ struct BindingError { #[derive(Debug)] enum ResolutionError<'a> { /// Error E0401: can't use type or const parameters from outer item. - GenericParamsFromOuterItem(Res, HasGenericParams), + GenericParamsFromOuterItem(Res, HasGenericParams, DefKind), /// Error E0403: the name is already used for a type or const parameter in this generic /// parameter list. NameAlreadyUsedInParameterList(Symbol, Span), @@ -1217,6 +1219,10 @@ impl<'tcx> Resolver<'_, 'tcx> { self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) } + fn local_def_kind(&self, node: NodeId) -> DefKind { + self.tcx.def_kind(self.local_def_id(node)) + } + /// Adds a definition with a parent definition. fn create_def( &mut self, @@ -1625,6 +1631,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.tcx .sess .time("resolve_postprocess", || self.crate_loader(|c| c.postprocess(krate))); + self.crate_loader(|c| c.unload_unused_crates()); }); // Make sure we don't mutate the cstore from here on. diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 9c34aa93957..95833f532f4 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -17,8 +17,6 @@ #![feature(ptr_sub_ptr)] #![cfg_attr(test, feature(test))] #![allow(rustc::internal)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] pub use self::serialize::{Decodable, Decoder, Encodable, Encoder}; diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 0d6328fbb07..58e1394c090 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -4,8 +4,6 @@ #![feature(rustc_attrs)] #![feature(map_many_mut)] #![feature(iter_intersperse)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] #[macro_use] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index d8d201d5f24..ea93ac5841f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1572,6 +1572,8 @@ options! { dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED], "in dep-info output, omit targets for tracking dependencies of the dep-info files \ themselves (default: no)"), + direct_access_external_data: Option<bool> = (None, parse_opt_bool, [TRACKED], + "Direct or use GOT indirect to reference external data symbols"), dual_proc_macros: bool = (false, parse_bool, [TRACKED], "load proc macros for both target and host, but only link to the target (default: no)"), dump_dep_graph: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index f6af5a4f87e..0c084660761 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -315,7 +315,7 @@ impl Session { pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> { // We must include lint errors here. if let Some(reported) = self.dcx().has_errors_or_lint_errors() { - let _ = self.dcx().emit_stashed_diagnostics(); + self.dcx().emit_stashed_diagnostics(); Err(reported) } else { Ok(()) @@ -767,6 +767,13 @@ impl Session { self.opts.unstable_opts.tls_model.unwrap_or(self.target.tls_model) } + pub fn direct_access_external_data(&self) -> Option<bool> { + self.opts + .unstable_opts + .direct_access_external_data + .or(self.target.direct_access_external_data) + } + pub fn split_debuginfo(&self) -> SplitDebuginfo { self.opts.cg.split_debuginfo.unwrap_or(self.target.split_debuginfo) } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 41a4edfc03b..501d6f7d304 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -257,6 +257,7 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> { OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf( indices.iter().map(|idx| idx.stable(tables)).collect(), ), + DebugAssertions => stable_mir::mir::NullOp::DebugAssertions, } } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index ea6766ea583..7d95a0bc478 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -17,8 +17,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![deny(rustc::diagnostic_outside_of_impl)] -#![deny(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] #![feature(array_windows)] @@ -2477,10 +2475,9 @@ where pub struct ErrorGuaranteed(()); impl ErrorGuaranteed { - /// To be used only if you really know what you are doing... ideally, we would find a way to - /// eliminate all calls to this method. - #[deprecated = "`Session::span_delayed_bug` should be preferred over this function"] - pub fn unchecked_claim_error_was_emitted() -> Self { + /// Don't use this outside of `DiagCtxtInner::emit_diagnostic`! + #[deprecated = "should only be used in `DiagCtxtInner::emit_diagnostic`"] + pub fn unchecked_error_guaranteed() -> Self { ErrorGuaranteed(()) } } diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs index 5788d11ed43..51f8aa04e8a 100644 --- a/compiler/rustc_span/src/source_map/tests.rs +++ b/compiler/rustc_span/src/source_map/tests.rs @@ -1,5 +1,7 @@ use super::*; +use rustc_data_structures::sync::FreezeLock; + fn init_source_map() -> SourceMap { let sm = SourceMap::new(FilePathMapping::empty()); sm.new_source_file(PathBuf::from("blork.rs").into(), "first line.\nsecond line".to_string()); @@ -263,53 +265,6 @@ fn t10() { ); } -/// Returns the span corresponding to the `n`th occurrence of `substring` in `source_text`. -trait SourceMapExtension { - fn span_substr( - &self, - file: &Lrc<SourceFile>, - source_text: &str, - substring: &str, - n: usize, - ) -> Span; -} - -impl SourceMapExtension for SourceMap { - fn span_substr( - &self, - file: &Lrc<SourceFile>, - source_text: &str, - substring: &str, - n: usize, - ) -> Span { - eprintln!( - "span_substr(file={:?}/{:?}, substring={:?}, n={})", - file.name, file.start_pos, substring, n - ); - let mut i = 0; - let mut hi = 0; - loop { - let offset = source_text[hi..].find(substring).unwrap_or_else(|| { - panic!( - "source_text `{}` does not have {} occurrences of `{}`, only {}", - source_text, n, substring, i - ); - }); - let lo = hi + offset; - hi = lo + substring.len(); - if i == n { - let span = Span::with_root_ctxt( - BytePos(lo as u32 + file.start_pos.0), - BytePos(hi as u32 + file.start_pos.0), - ); - assert_eq!(&self.span_to_snippet(span).unwrap()[..], substring); - return span; - } - i += 1; - } - } -} - // Takes a unix-style path and returns a platform specific path. fn path(p: &str) -> PathBuf { path_str(p).into() diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 362aaca6364..02bb1fde75c 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -91,8 +91,6 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index bffb3681f13..b19c5b6f28f 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -17,8 +17,6 @@ #![feature(min_specialization)] #![feature(rustc_attrs)] #![feature(step_trait)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(internal_features)] use std::path::{Path, PathBuf}; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 6c698c5b01d..d04bcb2d78a 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1543,6 +1543,7 @@ supported_targets! { ("armebv7r-none-eabihf", armebv7r_none_eabihf), ("armv7r-none-eabi", armv7r_none_eabi), ("armv7r-none-eabihf", armv7r_none_eabihf), + ("armv8r-none-eabihf", armv8r_none_eabihf), ("x86_64-pc-solaris", x86_64_pc_solaris), ("sparcv9-sun-solaris", sparcv9_sun_solaris), @@ -1886,6 +1887,8 @@ pub struct TargetOptions { /// passed, and cannot be disabled even via `-C`. Corresponds to `llc /// -mattr=$features`. pub features: StaticCow<str>, + /// Direct or use GOT indirect to reference external data symbols + pub direct_access_external_data: Option<bool>, /// Whether dynamic linking is available on this target. Defaults to false. pub dynamic_linking: bool, /// Whether dynamic linking can export TLS globals. Defaults to true. @@ -2280,6 +2283,7 @@ impl Default for TargetOptions { asm_args: cvs![], cpu: "generic".into(), features: "".into(), + direct_access_external_data: None, dynamic_linking: false, dll_tls_export: true, only_cdylib: false, @@ -2579,6 +2583,12 @@ impl Target { base.$key_name = s as u32; } } ); + ($key_name:ident, Option<bool>) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) { + base.$key_name = Some(s); + } + } ); ($key_name:ident, Option<u64>) => ( { let name = (stringify!($key_name)).replace("_", "-"); if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) { @@ -3007,6 +3017,7 @@ impl Target { key!(cpu); key!(features); key!(dynamic_linking, bool); + key!(direct_access_external_data, Option<bool>); key!(dll_tls_export, bool); key!(only_cdylib, bool); key!(executables, bool); @@ -3261,6 +3272,7 @@ impl ToJson for Target { target_option_val!(cpu); target_option_val!(features); target_option_val!(dynamic_linking); + target_option_val!(direct_access_external_data); target_option_val!(dll_tls_export); target_option_val!(only_cdylib); target_option_val!(executables); diff --git a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs new file mode 100644 index 00000000000..28dba4f7f5d --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs @@ -0,0 +1,35 @@ +// Targets the Little-endian Cortex-R52 processor (ARMv8-R) + +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub fn target() -> Target { + Target { + llvm_target: "armv8r-none-eabihf".into(), + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: "arm".into(), + + options: TargetOptions { + abi: "eabihf".into(), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + relocation_model: RelocModel::Static, + panic_strategy: PanicStrategy::Abort, + // The Cortex-R52 has two variants with respect to floating-point support: + // 1. fp-armv8, SP-only, with 16 DP (32 SP) registers + // 2. neon-fp-armv8, SP+DP, with 32 DP registers + // Use the lesser of these two options as the default, as it will produce code + // compatible with either variant. + // + // Reference: + // Arm Cortex-R52 Processor Technical Reference Manual + // - Chapter 15 Advanced SIMD and floating-point support + features: "+fp-armv8,-fp64,-d32".into(), + max_atomic_width: Some(64), + emit_debug_gdb_scripts: false, + // GCC defaults to 8 for arm-none here. + c_enum_min_bits: Some(8), + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs index cb24e740c86..f4350708986 100644 --- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs @@ -12,6 +12,7 @@ pub fn target() -> Target { features: "+f,+d".into(), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), + direct_access_external_data: Some(false), ..base::linux_gnu::opts() }, } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 7894f8dd98f..20cd573f46e 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1,7 +1,7 @@ use crate::fluent_generated as fluent; use rustc_errors::{ codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessage, + EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessageOp, }; use rustc_macros::Diagnostic; use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty}; @@ -102,10 +102,7 @@ pub enum AdjustSignatureBorrow { } impl AddToDiagnostic for AdjustSignatureBorrow { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { match self { AdjustSignatureBorrow::Borrow { to_borrow } => { diag.arg("len", to_borrow.len()); diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 5ec45212bc7..053ecfc681c 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -14,6 +14,8 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![allow(internal_features)] +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(control_flow_enum)] diff --git a/compiler/rustc_trait_selection/src/regions.rs b/compiler/rustc_trait_selection/src/regions.rs index e8929f114e1..756db7cc206 100644 --- a/compiler/rustc_trait_selection/src/regions.rs +++ b/compiler/rustc_trait_selection/src/regions.rs @@ -1,5 +1,6 @@ use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferCtxt, RegionResolutionError}; +use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; pub trait InferCtxtRegionExt<'tcx> { @@ -31,7 +32,7 @@ impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { ), ty, ) - .map_err(|_| ty) + .map_err(|_| NoSolution) } else { Ok(ty) } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 7052fd776b0..81c0cfea85a 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -8,7 +8,7 @@ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::Reveal; use rustc_middle::traits::solve::inspect::ProbeKind; use rustc_middle::traits::solve::{ - CandidateSource, CanonicalResponse, Certainty, Goal, QueryResult, + CandidateSource, CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult, }; use rustc_middle::traits::BuiltinImplSource; use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams}; @@ -276,25 +276,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { &mut self, goal: Goal<'tcx, G>, ) -> Vec<Candidate<'tcx>> { - let dummy_candidate = |this: &mut EvalCtxt<'_, 'tcx>, certainty| { - let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc); - let result = this.evaluate_added_goals_and_make_canonical_response(certainty).unwrap(); - let mut dummy_probe = this.inspect.new_probe(); - dummy_probe.probe_kind(ProbeKind::TraitCandidate { source, result: Ok(result) }); - this.inspect.finish_probe(dummy_probe); - vec![Candidate { source, result }] - }; - let Some(normalized_self_ty) = self.try_normalize_ty(goal.param_env, goal.predicate.self_ty()) else { debug!("overflow while evaluating self type"); - return dummy_candidate(self, Certainty::OVERFLOW); + return self.forced_ambiguity(MaybeCause::Overflow); }; if normalized_self_ty.is_ty_var() { debug!("self type has been normalized to infer"); - return dummy_candidate(self, Certainty::AMBIGUOUS); + return self.forced_ambiguity(MaybeCause::Ambiguity); } let goal = @@ -315,11 +306,26 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { self.assemble_param_env_candidates(goal, &mut candidates); - self.assemble_coherence_unknowable_candidates(goal, &mut candidates); + match self.solver_mode() { + SolverMode::Normal => self.discard_impls_shadowed_by_env(goal, &mut candidates), + SolverMode::Coherence => { + self.assemble_coherence_unknowable_candidates(goal, &mut candidates) + } + } candidates } + fn forced_ambiguity(&mut self, cause: MaybeCause) -> Vec<Candidate<'tcx>> { + let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc); + let certainty = Certainty::Maybe(cause); + let result = self.evaluate_added_goals_and_make_canonical_response(certainty).unwrap(); + let mut dummy_probe = self.inspect.new_probe(); + dummy_probe.probe_kind(ProbeKind::TraitCandidate { source, result: Ok(result) }); + self.inspect.finish_probe(dummy_probe); + vec![Candidate { source, result }] + } + #[instrument(level = "debug", skip_all)] fn assemble_non_blanket_impl_candidates<G: GoalKind<'tcx>>( &mut self, @@ -542,7 +548,27 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, G>, candidates: &mut Vec<Candidate<'tcx>>, ) { - let alias_ty = match goal.predicate.self_ty().kind() { + let () = self.probe(|_| ProbeKind::NormalizedSelfTyAssembly).enter(|ecx| { + ecx.assemble_alias_bound_candidates_recur(goal.predicate.self_ty(), goal, candidates); + }); + } + + /// For some deeply nested `<T>::A::B::C::D` rigid associated type, + /// we should explore the item bounds for all levels, since the + /// `associated_type_bounds` feature means that a parent associated + /// type may carry bounds for a nested associated type. + /// + /// If we have a projection, check that its self type is a rigid projection. + /// If so, continue searching by recursively calling after normalization. + // FIXME: This may recurse infinitely, but I can't seem to trigger it without + // hitting another overflow error something. Add a depth parameter needed later. + fn assemble_alias_bound_candidates_recur<G: GoalKind<'tcx>>( + &mut self, + self_ty: Ty<'tcx>, + goal: Goal<'tcx, G>, + candidates: &mut Vec<Candidate<'tcx>>, + ) { + let (kind, alias_ty) = match *self_ty.kind() { ty::Bool | ty::Char | ty::Int(_) @@ -567,13 +593,27 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Param(_) | ty::Placeholder(..) | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) - | ty::Alias(ty::Inherent, _) - | ty::Alias(ty::Weak, _) | ty::Error(_) => return, - ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) - | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"), - // Excluding IATs and type aliases here as they don't have meaningful item bounds. - ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty, + ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) | ty::Bound(..) => { + bug!("unexpected self type for `{goal:?}`") + } + + ty::Infer(ty::TyVar(_)) => { + // If we hit infer when normalizing the self type of an alias, + // then bail with ambiguity. We should never encounter this on + // the *first* iteration of this recursive function. + if let Ok(result) = + self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + { + candidates.push(Candidate { source: CandidateSource::AliasBound, result }); + } + return; + } + + ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty), + ty::Alias(ty::Inherent | ty::Weak, _) => { + unreachable!("Weak and Inherent aliases should have been normalized away already") + } }; for assumption in @@ -581,9 +621,28 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { { match G::consider_alias_bound_candidate(self, goal, assumption) { Ok(result) => { - candidates.push(Candidate { source: CandidateSource::AliasBound, result }) + candidates.push(Candidate { source: CandidateSource::AliasBound, result }); + } + Err(NoSolution) => {} + } + } + + if kind != ty::Projection { + return; + } + + match self.try_normalize_ty(goal.param_env, alias_ty.self_ty()) { + // Recurse on the self type of the projection. + Some(next_self_ty) => { + self.assemble_alias_bound_candidates_recur(next_self_ty, goal, candidates); + } + // Bail if we overflow when normalizing, adding an ambiguous candidate. + None => { + if let Ok(result) = + self.evaluate_added_goals_and_make_canonical_response(Certainty::OVERFLOW) + { + candidates.push(Candidate { source: CandidateSource::AliasBound, result }); } - Err(NoSolution) => (), } } } @@ -779,6 +838,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + /// In coherence we have to not only care about all impls we know about, but + /// also consider impls which may get added in a downstream or sibling crate + /// or which an upstream impl may add in a minor release. + /// + /// To do so we add an ambiguous candidate in case such an unknown impl could + /// apply to the current goal. #[instrument(level = "debug", skip_all)] fn assemble_coherence_unknowable_candidates<G: GoalKind<'tcx>>( &mut self, @@ -786,11 +851,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates: &mut Vec<Candidate<'tcx>>, ) { let tcx = self.tcx(); - match self.solver_mode() { - SolverMode::Normal => return, - SolverMode::Coherence => {} - }; - let result = self.probe_misc_candidate("coherence unknowable").enter(|ecx| { let trait_ref = goal.predicate.trait_ref(tcx); #[derive(Debug)] @@ -820,46 +880,65 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + /// If there's a where-bound for the current goal, do not use any impl candidates + /// to prove the current goal. Most importantly, if there is a where-bound which does + /// not specify any associated types, we do not allow normalizing the associated type + /// by using an impl, even if it would apply. + /// + /// <https://github.com/rust-lang/trait-system-refactor-initiative/issues/76> + // FIXME(@lcnr): The current structure here makes me unhappy and feels ugly. idk how + // to improve this however. However, this should make it fairly straightforward to refine + // the filtering going forward, so it seems alright-ish for now. + fn discard_impls_shadowed_by_env<G: GoalKind<'tcx>>( + &mut self, + goal: Goal<'tcx, G>, + candidates: &mut Vec<Candidate<'tcx>>, + ) { + let tcx = self.tcx(); + let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> = + goal.with(tcx, goal.predicate.trait_ref(tcx)); + let mut trait_candidates_from_env = Vec::new(); + self.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env); + self.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env); + if !trait_candidates_from_env.is_empty() { + let trait_env_result = self.merge_candidates(trait_candidates_from_env); + match trait_env_result.unwrap().value.certainty { + // If proving the trait goal succeeds by using the env, + // we freely drop all impl candidates. + // + // FIXME(@lcnr): It feels like this could easily hide + // a forced ambiguity candidate added earlier. + // This feels dangerous. + Certainty::Yes => { + candidates.retain(|c| match c.source { + CandidateSource::Impl(_) | CandidateSource::BuiltinImpl(_) => false, + CandidateSource::ParamEnv(_) | CandidateSource::AliasBound => true, + }); + } + // If it is still ambiguous we instead just force the whole goal + // to be ambig and wait for inference constraints. See + // tests/ui/traits/next-solver/env-shadows-impls/ambig-env-no-shadow.rs + Certainty::Maybe(cause) => { + *candidates = self.forced_ambiguity(cause); + } + } + } + } + /// If there are multiple ways to prove a trait or projection goal, we have /// to somehow try to merge the candidates into one. If that fails, we return /// ambiguity. #[instrument(level = "debug", skip(self), ret)] pub(super) fn merge_candidates( &mut self, - mut candidates: Vec<Candidate<'tcx>>, + candidates: Vec<Candidate<'tcx>>, ) -> QueryResult<'tcx> { // First try merging all candidates. This is complete and fully sound. let responses = candidates.iter().map(|c| c.result).collect::<Vec<_>>(); if let Some(result) = self.try_merge_responses(&responses) { return Ok(result); + } else { + self.flounder(&responses) } - - // We then check whether we should prioritize `ParamEnv` candidates. - // - // Doing so is incomplete and would therefore be unsound during coherence. - match self.solver_mode() { - SolverMode::Coherence => (), - // Prioritize `ParamEnv` candidates only if they do not guide inference. - // - // This is still incomplete as we may add incorrect region bounds. - SolverMode::Normal => { - let param_env_responses = candidates - .iter() - .filter(|c| { - matches!( - c.source, - CandidateSource::ParamEnv(_) | CandidateSource::AliasBound - ) - }) - .map(|c| c.result) - .collect::<Vec<_>>(); - if let Some(result) = self.try_merge_responses(¶m_env_responses) { - // We strongly prefer alias and param-env bounds here, even if they affect inference. - // See https://github.com/rust-lang/trait-system-refactor-initiative/issues/11. - return Ok(result); - } - } - } - self.flounder(&responses) } } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 4b95d26f9f8..819b070cf8b 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -20,7 +20,7 @@ use crate::solve::EvalCtxt; pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, -) -> Result<Vec<Ty<'tcx>>, NoSolution> { +) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution> { let tcx = ecx.tcx(); match *ty.kind() { ty::Uint(_) @@ -34,7 +34,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( | ty::Char => Ok(vec![]), // Treat `str` like it's defined as `struct str([u8]);` - ty::Str => Ok(vec![Ty::new_slice(tcx, tcx.types.u8)]), + ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(tcx, tcx.types.u8))]), ty::Dynamic(..) | ty::Param(..) @@ -47,46 +47,48 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( } ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => { - Ok(vec![element_ty]) + Ok(vec![ty::Binder::dummy(element_ty)]) } - ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![element_ty]), + ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![ty::Binder::dummy(element_ty)]), ty::Tuple(tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet - Ok(tys.iter().collect()) + Ok(tys.iter().map(ty::Binder::dummy).collect()) } - ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]), + ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]), - ty::CoroutineClosure(_, args) => Ok(vec![args.as_coroutine_closure().tupled_upvars_ty()]), + ty::CoroutineClosure(_, args) => { + Ok(vec![ty::Binder::dummy(args.as_coroutine_closure().tupled_upvars_ty())]) + } ty::Coroutine(_, args) => { let coroutine_args = args.as_coroutine(); - Ok(vec![coroutine_args.tupled_upvars_ty(), coroutine_args.witness()]) + Ok(vec![ + ty::Binder::dummy(coroutine_args.tupled_upvars_ty()), + ty::Binder::dummy(coroutine_args.witness()), + ]) } ty::CoroutineWitness(def_id, args) => Ok(ecx .tcx() .coroutine_hidden_types(def_id) - .map(|bty| { - ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars( - tcx, - bty.instantiate(tcx, args), - )) - }) + .map(|bty| replace_erased_lifetimes_with_bound_vars(tcx, bty.instantiate(tcx, args))) .collect()), // For `PhantomData<T>`, we pass `T`. - ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![args.type_at(0)]), + ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]), - ty::Adt(def, args) => Ok(def.all_fields().map(|f| f.ty(tcx, args)).collect()), + ty::Adt(def, args) => { + Ok(def.all_fields().map(|f| ty::Binder::dummy(f.ty(tcx, args))).collect()) + } ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { // We can resolve the `impl Trait` to its concrete type, // which enforces a DAG between the functions requiring // the auto trait bounds in question. - Ok(vec![tcx.type_of(def_id).instantiate(tcx, args)]) + Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, args))]) } } } @@ -116,7 +118,7 @@ pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>( pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, -) -> Result<Vec<Ty<'tcx>>, NoSolution> { +) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution> { match *ty.kind() { ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Uint(_) @@ -150,11 +152,11 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( bug!("unexpected type `{ty}`") } - ty::Tuple(tys) => Ok(tys.to_vec()), + ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()), ty::Adt(def, args) => { let sized_crit = def.sized_constraint(ecx.tcx()); - Ok(sized_crit.iter_instantiated(ecx.tcx(), args).collect()) + Ok(sized_crit.iter_instantiated(ecx.tcx(), args).map(ty::Binder::dummy).collect()) } } } @@ -163,7 +165,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ecx: &EvalCtxt<'_, 'tcx>, ty: Ty<'tcx>, -) -> Result<Vec<Ty<'tcx>>, NoSolution> { +) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution> { match *ty.kind() { ty::FnDef(..) | ty::FnPtr(_) | ty::Error(_) => Ok(vec![]), @@ -194,9 +196,9 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( bug!("unexpected type `{ty}`") } - ty::Tuple(tys) => Ok(tys.to_vec()), + ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()), - ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]), + ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]), ty::CoroutineClosure(..) => Err(NoSolution), @@ -205,7 +207,10 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( Movability::Movable => { if ecx.tcx().features().coroutine_clone { let coroutine = args.as_coroutine(); - Ok(vec![coroutine.tupled_upvars_ty(), coroutine.witness()]) + Ok(vec![ + ty::Binder::dummy(coroutine.tupled_upvars_ty()), + ty::Binder::dummy(coroutine.witness()), + ]) } else { Err(NoSolution) } @@ -216,10 +221,10 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( .tcx() .coroutine_hidden_types(def_id) .map(|bty| { - ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars( + replace_erased_lifetimes_with_bound_vars( ecx.tcx(), bty.instantiate(ecx.tcx(), args), - )) + ) }) .collect()), } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 76c50a11102..803379af005 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -477,10 +477,11 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } } } else { - let kind = self.infcx.instantiate_binder_with_placeholders(kind); - let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); - self.add_goal(GoalSource::Misc, goal); - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + self.infcx.enter_forall(kind, |kind| { + let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); + self.add_goal(GoalSource::Misc, goal); + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } } @@ -801,13 +802,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ) } - pub(super) fn instantiate_binder_with_placeholders<T: TypeFoldable<TyCtxt<'tcx>> + Copy>( + pub(super) fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>> + Copy, U>( &self, value: ty::Binder<'tcx, T>, - ) -> T { - self.infcx.instantiate_binder_with_placeholders(value) + f: impl FnOnce(T) -> U, + ) -> U { + self.infcx.enter_forall(value, f) } - pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T where T: TypeFoldable<TyCtxt<'tcx>>, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 315df06be41..69b69930432 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -31,103 +31,108 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { ) -> SelectionResult<'tcx, Selection<'tcx>> { assert!(self.next_trait_solver()); - let trait_goal = Goal::new( - self.tcx, - obligation.param_env, - self.instantiate_binder_with_placeholders(obligation.predicate), - ); - - let (result, _) = EvalCtxt::enter_root(self, GenerateProofTree::Never, |ecx| { - let goal = Goal::new(ecx.tcx(), trait_goal.param_env, trait_goal.predicate); - let (orig_values, canonical_goal) = ecx.canonicalize_goal(goal); - let mut candidates = ecx.compute_canonical_trait_candidates(canonical_goal); - - // pseudo-winnow - if candidates.len() == 0 { - return Err(SelectionError::Unimplemented); - } else if candidates.len() > 1 { - let mut i = 0; - while i < candidates.len() { - let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| { - candidate_should_be_dropped_in_favor_of( - ecx.tcx(), - &candidates[i], - &candidates[j], - ) - }); - if should_drop_i { - candidates.swap_remove(i); - } else { - i += 1; - if i > 1 { - return Ok(None); + self.enter_forall(obligation.predicate, |pred| { + let trait_goal = Goal::new(self.tcx, obligation.param_env, pred); + + let (result, _) = EvalCtxt::enter_root(self, GenerateProofTree::Never, |ecx| { + let goal = Goal::new(ecx.tcx(), trait_goal.param_env, trait_goal.predicate); + let (orig_values, canonical_goal) = ecx.canonicalize_goal(goal); + let mut candidates = ecx.compute_canonical_trait_candidates(canonical_goal); + + // pseudo-winnow + if candidates.len() == 0 { + return Err(SelectionError::Unimplemented); + } else if candidates.len() > 1 { + let mut i = 0; + while i < candidates.len() { + let should_drop_i = (0..candidates.len()).filter(|&j| i != j).any(|j| { + candidate_should_be_dropped_in_favor_of( + ecx.tcx(), + &candidates[i], + &candidates[j], + ) + }); + if should_drop_i { + candidates.swap_remove(i); + } else { + i += 1; + if i > 1 { + return Ok(None); + } } } } - } - let candidate = candidates.pop().unwrap(); - let (certainty, nested_goals) = ecx - .instantiate_and_apply_query_response( - trait_goal.param_env, - orig_values, - candidate.result, - ) - .map_err(|_| SelectionError::Unimplemented)?; - - Ok(Some((candidate, certainty, nested_goals))) - }); - - let (candidate, certainty, nested_goals) = match result { - Ok(Some((candidate, certainty, nested_goals))) => (candidate, certainty, nested_goals), - Ok(None) => return Ok(None), - Err(e) => return Err(e), - }; - - let nested_obligations: Vec<_> = nested_goals - .into_iter() - .map(|goal| { - Obligation::new(self.tcx, ObligationCause::dummy(), goal.param_env, goal.predicate) - }) - .collect(); - - let goal = self.resolve_vars_if_possible(trait_goal); - match (certainty, candidate.source) { - // Rematching the implementation will instantiate the same nested goals that - // would have caused the ambiguity, so we can still make progress here regardless. - (_, CandidateSource::Impl(def_id)) => { - rematch_impl(self, goal, def_id, nested_obligations) - } + let candidate = candidates.pop().unwrap(); + let (certainty, nested_goals) = ecx + .instantiate_and_apply_query_response( + trait_goal.param_env, + orig_values, + candidate.result, + ) + .map_err(|_| SelectionError::Unimplemented)?; + + Ok(Some((candidate, certainty, nested_goals))) + }); + + let (candidate, certainty, nested_goals) = match result { + Ok(Some((candidate, certainty, nested_goals))) => { + (candidate, certainty, nested_goals) + } + Ok(None) => return Ok(None), + Err(e) => return Err(e), + }; + + let nested_obligations: Vec<_> = nested_goals + .into_iter() + .map(|goal| { + Obligation::new( + self.tcx, + ObligationCause::dummy(), + goal.param_env, + goal.predicate, + ) + }) + .collect(); + + let goal = self.resolve_vars_if_possible(trait_goal); + match (certainty, candidate.source) { + // Rematching the implementation will instantiate the same nested goals that + // would have caused the ambiguity, so we can still make progress here regardless. + (_, CandidateSource::Impl(def_id)) => { + rematch_impl(self, goal, def_id, nested_obligations) + } - // If an unsize goal is ambiguous, then we can manually rematch it to make - // selection progress for coercion during HIR typeck. If it is *not* ambiguous, - // but is `BuiltinImplSource::Misc`, it may have nested `Unsize` goals, - // and we need to rematch those to detect tuple unsizing and trait upcasting. - // FIXME: This will be wrong if we have param-env or where-clause bounds - // with the unsize goal -- we may need to mark those with different impl - // sources. - (Certainty::Maybe(_), CandidateSource::BuiltinImpl(src)) - | (Certainty::Yes, CandidateSource::BuiltinImpl(src @ BuiltinImplSource::Misc)) - if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) => - { - rematch_unsize(self, goal, nested_obligations, src, certainty) - } + // If an unsize goal is ambiguous, then we can manually rematch it to make + // selection progress for coercion during HIR typeck. If it is *not* ambiguous, + // but is `BuiltinImplSource::Misc`, it may have nested `Unsize` goals, + // and we need to rematch those to detect tuple unsizing and trait upcasting. + // FIXME: This will be wrong if we have param-env or where-clause bounds + // with the unsize goal -- we may need to mark those with different impl + // sources. + (Certainty::Maybe(_), CandidateSource::BuiltinImpl(src)) + | (Certainty::Yes, CandidateSource::BuiltinImpl(src @ BuiltinImplSource::Misc)) + if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) => + { + rematch_unsize(self, goal, nested_obligations, src, certainty) + } - // Technically some builtin impls have nested obligations, but if - // `Certainty::Yes`, then they should've all been verified and don't - // need re-checking. - (Certainty::Yes, CandidateSource::BuiltinImpl(src)) => { - Ok(Some(ImplSource::Builtin(src, nested_obligations))) - } + // Technically some builtin impls have nested obligations, but if + // `Certainty::Yes`, then they should've all been verified and don't + // need re-checking. + (Certainty::Yes, CandidateSource::BuiltinImpl(src)) => { + Ok(Some(ImplSource::Builtin(src, nested_obligations))) + } - // It's fine not to do anything to rematch these, since there are no - // nested obligations. - (Certainty::Yes, CandidateSource::ParamEnv(_) | CandidateSource::AliasBound) => { - Ok(Some(ImplSource::Param(nested_obligations))) - } + // It's fine not to do anything to rematch these, since there are no + // nested obligations. + (Certainty::Yes, CandidateSource::ParamEnv(_) | CandidateSource::AliasBound) => { + Ok(Some(ImplSource::Param(nested_obligations))) + } - (Certainty::Maybe(_), _) => Ok(None), - } + (Certainty::Maybe(_), _) => Ok(None), + } + }) } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index f08622816ec..63555a305d8 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -140,7 +140,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { ) } ty::PredicateKind::Subtype(pred) => { - let (a, b) = infcx.instantiate_binder_with_placeholders( + let (a, b) = infcx.enter_forall_and_leak_universe( goal.predicate.kind().rebind((pred.a, pred.b)), ); let expected_found = ExpectedFound::new(true, a, b); @@ -150,7 +150,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { ) } ty::PredicateKind::Coerce(pred) => { - let (a, b) = infcx.instantiate_binder_with_placeholders( + let (a, b) = infcx.enter_forall_and_leak_universe( goal.predicate.kind().rebind((pred.a, pred.b)), ); let expected_found = ExpectedFound::new(false, a, b); diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 6984f0ba694..a7330136fe7 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -124,25 +124,6 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } } - #[instrument(level = "debug", skip(self))] - fn compute_closure_kind_goal( - &mut self, - goal: Goal<'tcx, (DefId, ty::GenericArgsRef<'tcx>, ty::ClosureKind)>, - ) -> QueryResult<'tcx> { - let (_, args, expected_kind) = goal.predicate; - let found_kind = args.as_closure().kind_ty().to_opt_closure_kind(); - - let Some(found_kind) = found_kind else { - return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); - }; - if found_kind.extends(expected_kind) { - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } else { - Err(NoSolution) - } - } - - #[instrument(level = "debug", skip(self))] fn compute_object_safe_goal(&mut self, trait_def_id: DefId) -> QueryResult<'tcx> { if self.tcx().check_is_object_safe(trait_def_id) { self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 47ba549022d..d177109c420 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -491,6 +491,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { goal: Goal<'tcx, Self>, ) -> QueryResult<'tcx> { let tcx = ecx.tcx(); + let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); + assert_eq!(metadata_def_id, goal.predicate.def_id()); ecx.probe_misc_candidate("builtin pointee").enter(|ecx| { let metadata_ty = match goal.predicate.self_ty().kind() { ty::Bool @@ -522,7 +524,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { } ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => { - // FIXME(ptr_metadata): It would also be possible to return a `Ok(Ambig)` with no constraints. + // This is the "fallback impl" for type parameters, unnormalizable projections + // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`. + // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't + // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`. let sized_predicate = ty::TraitRef::from_lang_item( tcx, LangItem::Sized, @@ -536,30 +541,16 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() { None => tcx.types.unit, - Some(field_def) => { - let self_ty = field_def.ty(tcx, args); - // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? - ecx.add_goal( - GoalSource::Misc, - goal.with(tcx, goal.predicate.with_self_ty(tcx, self_ty)), - ); - return ecx - .evaluate_added_goals_and_make_canonical_response(Certainty::Yes); + Some(tail_def) => { + let tail_ty = tail_def.ty(tcx, args); + Ty::new_projection(tcx, metadata_def_id, [tail_ty]) } }, ty::Adt(_, _) => tcx.types.unit, ty::Tuple(elements) => match elements.last() { None => tcx.types.unit, - Some(&self_ty) => { - // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? - ecx.add_goal( - GoalSource::Misc, - goal.with(tcx, goal.predicate.with_self_ty(tcx, self_ty)), - ); - return ecx - .evaluate_added_goals_and_make_canonical_response(Certainty::Yes); - } + Some(&tail_ty) => Ty::new_projection(tcx, metadata_def_id, [tail_ty]), }, ty::Infer( diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index fd09a6b671d..044832224e5 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -1049,14 +1049,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { fn probe_and_evaluate_goal_for_constituent_tys( &mut self, goal: Goal<'tcx, TraitPredicate<'tcx>>, - constituent_tys: impl Fn(&EvalCtxt<'_, 'tcx>, Ty<'tcx>) -> Result<Vec<Ty<'tcx>>, NoSolution>, + constituent_tys: impl Fn( + &EvalCtxt<'_, 'tcx>, + Ty<'tcx>, + ) -> Result<Vec<ty::Binder<'tcx, Ty<'tcx>>>, NoSolution>, ) -> QueryResult<'tcx> { self.probe_misc_candidate("constituent tys").enter(|ecx| { ecx.add_goals( GoalSource::ImplWhereBound, constituent_tys(ecx, goal.predicate.self_ty())? .into_iter() - .map(|ty| goal.with(ecx.tcx(), goal.predicate.with_self_ty(ecx.tcx(), ty))) + .map(|ty| { + ecx.enter_forall(ty, |ty| { + goal.with(ecx.tcx(), goal.predicate.with_self_ty(ecx.tcx(), ty)) + }) + }) .collect::<Vec<_>>(), ); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 7933654a915..81c72fc4b7b 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } let outlives_env = OutlivesEnvironment::new(full_env); - let _ = infcx.process_registered_region_obligations::<!>(&outlives_env, |ty, _| Ok(ty)); + let _ = infcx.process_registered_region_obligations(&outlives_env, |ty, _| Ok(ty)); let region_data = infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone(); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 4b20de26219..cbe9a238b1c 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -971,7 +971,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { let Goal { param_env, predicate } = goal.goal(); - // For bound predicates we simply call `infcx.instantiate_binder_with_placeholders` + // For bound predicates we simply call `infcx.enter_forall` // and then prove the resulting predicate as a nested goal. let trait_ref = match predicate.kind().no_bound_vars() { Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index b246e476bed..c6f5af08013 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -21,51 +21,62 @@ pub fn recompute_applicable_impls<'tcx>( let impl_may_apply = |impl_def_id| { let ocx = ObligationCtxt::new(infcx); - let placeholder_obligation = - infcx.instantiate_binder_with_placeholders(obligation.predicate); - let obligation_trait_ref = - ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref); - - let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args); - let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref); - - if let Err(_) = - ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref) - { - return false; - } + infcx.enter_forall(obligation.predicate, |placeholder_obligation| { + let obligation_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + placeholder_obligation.trait_ref, + ); + + let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); + let impl_trait_ref = + tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args); + let impl_trait_ref = + ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref); + + if let Err(_) = + ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, impl_trait_ref) + { + return false; + } - let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args); - ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| { - Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) - })); + let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args); + ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| { + Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) + })); - ocx.select_where_possible().is_empty() + ocx.select_where_possible().is_empty() + }) }; let param_env_candidate_may_apply = |poly_trait_predicate: ty::PolyTraitPredicate<'tcx>| { let ocx = ObligationCtxt::new(infcx); - let placeholder_obligation = - infcx.instantiate_binder_with_placeholders(obligation.predicate); - let obligation_trait_ref = - ocx.normalize(&ObligationCause::dummy(), param_env, placeholder_obligation.trait_ref); - - let param_env_predicate = infcx.instantiate_binder_with_fresh_vars( - DUMMY_SP, - BoundRegionConversionTime::HigherRankedType, - poly_trait_predicate, - ); - let param_env_trait_ref = - ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref); - - if let Err(_) = - ocx.eq(&ObligationCause::dummy(), param_env, obligation_trait_ref, param_env_trait_ref) - { - return false; - } + infcx.enter_forall(obligation.predicate, |placeholder_obligation| { + let obligation_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + placeholder_obligation.trait_ref, + ); + + let param_env_predicate = infcx.instantiate_binder_with_fresh_vars( + DUMMY_SP, + BoundRegionConversionTime::HigherRankedType, + poly_trait_predicate, + ); + let param_env_trait_ref = + ocx.normalize(&ObligationCause::dummy(), param_env, param_env_predicate.trait_ref); + + if let Err(_) = ocx.eq( + &ObligationCause::dummy(), + param_env, + obligation_trait_ref, + param_env_trait_ref, + ) { + return false; + } - ocx.select_where_possible().is_empty() + ocx.select_where_possible().is_empty() + }) }; let mut ambiguities = Vec::new(); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 972da180a33..ceff7187646 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -64,39 +64,44 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> Option<(DefId, GenericArgsRef<'tcx>)> { let tcx = self.tcx; let param_env = obligation.param_env; - let trait_ref = self.instantiate_binder_with_placeholders(trait_ref); - let trait_self_ty = trait_ref.self_ty(); + self.enter_forall(trait_ref, |trait_ref| { + let trait_self_ty = trait_ref.self_ty(); - let mut self_match_impls = vec![]; - let mut fuzzy_match_impls = vec![]; + let mut self_match_impls = vec![]; + let mut fuzzy_match_impls = vec![]; - self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| { - let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id); - let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args); + self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| { + let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id); + let impl_trait_ref = + tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args); - let impl_self_ty = impl_trait_ref.self_ty(); + let impl_self_ty = impl_trait_ref.self_ty(); - if self.can_eq(param_env, trait_self_ty, impl_self_ty) { - self_match_impls.push((def_id, impl_args)); + if self.can_eq(param_env, trait_self_ty, impl_self_ty) { + self_match_impls.push((def_id, impl_args)); - if iter::zip(trait_ref.args.types().skip(1), impl_trait_ref.args.types().skip(1)) + if iter::zip( + trait_ref.args.types().skip(1), + impl_trait_ref.args.types().skip(1), + ) .all(|(u, v)| self.fuzzy_match_tys(u, v, false).is_some()) - { - fuzzy_match_impls.push((def_id, impl_args)); + { + fuzzy_match_impls.push((def_id, impl_args)); + } } - } - }); + }); - let impl_def_id_and_args = if self_match_impls.len() == 1 { - self_match_impls[0] - } else if fuzzy_match_impls.len() == 1 { - fuzzy_match_impls[0] - } else { - return None; - }; + let impl_def_id_and_args = if self_match_impls.len() == 1 { + self_match_impls[0] + } else if fuzzy_match_impls.len() == 1 { + fuzzy_match_impls[0] + } else { + return None; + }; - tcx.has_attr(impl_def_id_and_args.0, sym::rustc_on_unimplemented) - .then_some(impl_def_id_and_args) + tcx.has_attr(impl_def_id_and_args.0, sym::rustc_on_unimplemented) + .then_some(impl_def_id_and_args) + }) } /// Used to set on_unimplemented's `ItemContext` diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 243f583aed8..f68200b6f4d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -19,7 +19,7 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::{Map, Visitor}; +use rustc_hir::intravisit::Visitor; use rustc_hir::is_range_literal; use rustc_hir::lang_items::LangItem; use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node}; @@ -774,7 +774,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if steps > 0 { // Don't care about `&mut` because `DerefMut` is used less // often and user will not expect that an autoderef happens. - if let Some(hir::Node::Expr(hir::Expr { + if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf( hir::BorrowKind::Ref, @@ -782,7 +782,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { expr, ), .. - })) = self.tcx.opt_hir_node(*arg_hir_id) + }) = self.tcx.hir_node(*arg_hir_id) { let derefs = "*".repeat(steps); err.span_suggestion_verbose( @@ -1199,7 +1199,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let Res::Local(hir_id) = path.res else { return; }; - let Some(hir::Node::Pat(pat)) = self.tcx.opt_hir_node(hir_id) else { + let hir::Node::Pat(pat) = self.tcx.hir_node(hir_id) else { return; }; let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) = @@ -1248,52 +1248,55 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); - let ty = self.instantiate_binder_with_placeholders(self_ty); - let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { - return false; - }; - let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false }; - let ty::Param(param) = inner_ty.kind() else { return false }; - let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = - obligation.cause.code() - else { - return false; - }; - let arg_node = self.tcx.hir_node(*arg_hir_id); - let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else { return false }; + self.enter_forall(self_ty, |ty: Ty<'_>| { + let Some(generics) = self.tcx.hir().get_generics(obligation.cause.body_id) else { + return false; + }; + let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false }; + let ty::Param(param) = inner_ty.kind() else { return false }; + let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = + obligation.cause.code() + else { + return false; + }; + let arg_node = self.tcx.hir_node(*arg_hir_id); + let Node::Expr(Expr { kind: hir::ExprKind::Path(_), .. }) = arg_node else { + return false; + }; - let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None); - let has_clone = |ty| { - self.type_implements_trait(clone_trait, [ty], obligation.param_env) - .must_apply_modulo_regions() - }; + let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None); + let has_clone = |ty| { + self.type_implements_trait(clone_trait, [ty], obligation.param_env) + .must_apply_modulo_regions() + }; - let new_obligation = self.mk_trait_obligation_with_new_self_ty( - obligation.param_env, - trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)), - ); + let new_obligation = self.mk_trait_obligation_with_new_self_ty( + obligation.param_env, + trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)), + ); - if self.predicate_may_hold(&new_obligation) && has_clone(ty) { - if !has_clone(param.to_ty(self.tcx)) { - suggest_constraining_type_param( - self.tcx, - generics, - err, - param.name.as_str(), - "Clone", - Some(clone_trait), - None, + if self.predicate_may_hold(&new_obligation) && has_clone(ty) { + if !has_clone(param.to_ty(self.tcx)) { + suggest_constraining_type_param( + self.tcx, + generics, + err, + param.name.as_str(), + "Clone", + Some(clone_trait), + None, + ); + } + err.span_suggestion_verbose( + obligation.cause.span.shrink_to_hi(), + "consider using clone here", + ".clone()".to_string(), + Applicability::MaybeIncorrect, ); + return true; } - err.span_suggestion_verbose( - obligation.cause.span.shrink_to_hi(), - "consider using clone here", - ".clone()", - Applicability::MaybeIncorrect, - ); - return true; - } - false + false + }) } /// Extracts information about a callable type for diagnostics. This is a @@ -1786,7 +1789,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let Res::Local(hir_id) = path.res - && let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(hir_id) + && let hir::Node::Pat(binding) = self.tcx.hir_node(hir_id) && let Some(hir::Node::Local(local)) = self.tcx.hir().find_parent(binding.hir_id) && let None = local.ty && let Some(binding_expr) = local.init @@ -2198,7 +2201,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let ty::FnPtr(found) = found.kind() else { return; }; - let Some(Node::Expr(arg)) = self.tcx.opt_hir_node(*arg_hir_id) else { + let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) else { return; }; let hir::ExprKind::Path(path) = arg.kind else { @@ -3186,8 +3189,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ObligationCauseCode::VariableType(hir_id) => { let parent_node = tcx.hir().parent_id(hir_id); - match tcx.opt_hir_node(parent_node) { - Some(Node::Local(hir::Local { ty: Some(ty), .. })) => { + match tcx.hir_node(parent_node) { + Node::Local(hir::Local { ty: Some(ty), .. }) => { err.span_suggestion_verbose( ty.span.shrink_to_lo(), "consider borrowing here", @@ -3196,10 +3199,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); err.note("all local variables must have a statically known size"); } - Some(Node::Local(hir::Local { + Node::Local(hir::Local { init: Some(hir::Expr { kind: hir::ExprKind::Index(..), span, .. }), .. - })) => { + }) => { // When encountering an assignment of an unsized trait, like // `let x = ""[..];`, provide a suggestion to borrow the initializer in // order to use have a slice instead. @@ -3211,7 +3214,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); err.note("all local variables must have a statically known size"); } - Some(Node::Param(param)) => { + Node::Param(param) => { err.span_suggestion_verbose( param.ty_span.shrink_to_lo(), "function arguments must have a statically known size, borrowed types \ @@ -3233,7 +3236,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let borrowed_msg = "function arguments must have a statically known size, borrowed \ types always have a known size"; if let Some(hir_id) = hir_id - && let Some(hir::Node::Param(param)) = self.tcx.hir().find(hir_id) + && let hir::Node::Param(param) = self.tcx.hir_node(hir_id) && let Some(item) = self.tcx.hir().find_parent(hir_id) && let Some(decl) = item.fn_decl() && let Some(t) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span)) @@ -3247,7 +3250,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // param._ty_span ty = Some(t); } else if let Some(hir_id) = hir_id - && let Some(hir::Node::Ty(t)) = self.tcx.hir().find(hir_id) + && let hir::Node::Ty(t) = self.tcx.hir_node(hir_id) { ty = Some(t); } @@ -3958,7 +3961,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { call_hir_id: HirId, ) { let tcx = self.tcx; - if let Some(Node::Expr(expr)) = tcx.opt_hir_node(arg_hir_id) + if let Node::Expr(expr) = tcx.hir_node(arg_hir_id) && let Some(typeck_results) = &self.typeck_results { if let hir::Expr { kind: hir::ExprKind::Block(block, _), .. } = expr { @@ -4038,26 +4041,27 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let Some(where_pred) = where_pred.as_trait_clause() && let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred() { - let where_pred = self.instantiate_binder_with_placeholders(where_pred); - let failed_pred = self.instantiate_binder_with_fresh_vars( - expr.span, - BoundRegionConversionTime::FnCall, - failed_pred, - ); + self.enter_forall(where_pred, |where_pred| { + let failed_pred = self.instantiate_binder_with_fresh_vars( + expr.span, + BoundRegionConversionTime::FnCall, + failed_pred, + ); - let zipped = iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args); - for (expected, actual) in zipped { - self.probe(|_| { - match self.at(&ObligationCause::misc(expr.span, body_id), param_env).eq( - DefineOpaqueTypes::No, - expected, - actual, - ) { - Ok(_) => (), // We ignore nested obligations here for now. - Err(err) => type_diffs.push(err), - } - }) - } + let zipped = + iter::zip(where_pred.trait_ref.args, failed_pred.trait_ref.args); + for (expected, actual) in zipped { + self.probe(|_| { + match self + .at(&ObligationCause::misc(expr.span, body_id), param_env) + .eq(DefineOpaqueTypes::No, expected, actual) + { + Ok(_) => (), // We ignore nested obligations here for now. + Err(err) => type_diffs.push(err), + } + }) + } + }) } else if let Some(where_pred) = where_pred.as_projection_clause() && let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred() && let Some(found) = failed_pred.skip_binder().term.ty() @@ -4074,9 +4078,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let hir::Path { res: Res::Local(hir_id), .. } = path - && let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(*hir_id) + && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id) && let parent_hir_id = self.tcx.hir().parent_id(binding.hir_id) - && let Some(hir::Node::Local(local)) = self.tcx.opt_hir_node(parent_hir_id) + && let hir::Node::Local(local) = self.tcx.hir_node(parent_hir_id) && let Some(binding_expr) = local.init { // If the expression we're calling on is a binding, we want to point at the @@ -4087,17 +4091,16 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.point_at_chain(expr, typeck_results, type_diffs, param_env, err); } } - let call_node = tcx.opt_hir_node(call_hir_id); - if let Some(Node::Expr(hir::Expr { - kind: hir::ExprKind::MethodCall(path, rcvr, ..), .. - })) = call_node + let call_node = tcx.hir_node(call_hir_id); + if let Node::Expr(hir::Expr { kind: hir::ExprKind::MethodCall(path, rcvr, ..), .. }) = + call_node { if Some(rcvr.span) == err.span.primary_span() { err.replace_span_with(path.ident.span, true); } } - if let Some(Node::Expr(expr)) = tcx.opt_hir_node(call_hir_id) { + if let Node::Expr(expr) = tcx.hir_node(call_hir_id) { if let hir::ExprKind::Call(hir::Expr { span, .. }, _) | hir::ExprKind::MethodCall( hir::PathSegment { ident: Ident { span, .. }, .. }, @@ -4334,7 +4337,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let hir::Path { res: Res::Local(hir_id), .. } = path - && let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(*hir_id) + && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id) && let Some(parent) = self.tcx.hir().find_parent(binding.hir_id) { // We've reached the root of the method call chain... @@ -4615,14 +4618,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { { self.probe(|_| { let ocx = ObligationCtxt::new(self); - let pred = self.instantiate_binder_with_placeholders(pred); - let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred); - ocx.register_obligation(Obligation::new( - self.tcx, - ObligationCause::dummy(), - param_env, - pred, - )); + self.enter_forall(pred, |pred| { + let pred = ocx.normalize(&ObligationCause::dummy(), param_env, pred); + ocx.register_obligation(Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + pred, + )); + }); if !ocx.select_where_possible().is_empty() { // encountered errors. return; @@ -4769,13 +4773,13 @@ fn hint_missing_borrow<'tcx>( } let found_args = match found.kind() { - ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(), + ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()), kind => { span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind) } }; let expected_args = match expected.kind() { - ty::FnPtr(f) => infcx.instantiate_binder_with_placeholders(*f).inputs().iter(), + ty::FnPtr(f) => infcx.enter_forall(*f, |f| f.inputs().iter()), kind => { span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 1ac0f172ef4..07e4fef9dd4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -993,13 +993,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) -> Result<(), ErrorGuaranteed> { if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() - && let Some(Node::Expr(arg)) = self.tcx.opt_hir_node(*arg_hir_id) + && let Node::Expr(arg) = self.tcx.hir_node(*arg_hir_id) && let arg = arg.peel_borrows() && let hir::ExprKind::Path(hir::QPath::Resolved( None, hir::Path { res: hir::def::Res::Local(hir_id), .. }, )) = arg.kind - && let Some(Node::Pat(pat)) = self.tcx.opt_hir_node(*hir_id) + && let Node::Pat(pat) = self.tcx.hir_node(*hir_id) && let Some((preds, guar)) = self.reported_trait_errors.borrow().get(&pat.span) && preds.contains(&obligation.predicate) { @@ -1037,10 +1037,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_id); - let body_id = match self.tcx.opt_hir_node(hir_id) { - Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) => { - body_id - } + let body_id = match self.tcx.hir_node(hir_id) { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => body_id, _ => return false, }; let mut v = V { search_span: span, found: None }; @@ -1163,7 +1161,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path - && let Some(hir::Node::Pat(binding)) = self.tcx.opt_hir_node(*hir_id) + && let hir::Node::Pat(binding) = self.tcx.hir_node(*hir_id) && let Some(parent) = self.tcx.hir().find_parent(binding.hir_id) { // We've reached the root of the method call chain... @@ -1307,12 +1305,13 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let mut pred = obligation.predicate.to_opt_poly_trait_pred(); while let Some((next_code, next_pred)) = code.parent() { if let Some(pred) = pred { - let pred = self.instantiate_binder_with_placeholders(pred); - diag.note(format!( - "`{}` must implement `{}`, but it does not", - pred.self_ty(), - pred.print_modifiers_and_trait_path() - )); + self.enter_forall(pred, |pred| { + diag.note(format!( + "`{}` must implement `{}`, but it does not", + pred.self_ty(), + pred.print_modifiers_and_trait_path() + )); + }) } code = next_code; pred = next_pred; @@ -2017,70 +2016,78 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let [single] = &impl_candidates { if self.probe(|_| { let ocx = ObligationCtxt::new(self); - let obligation_trait_ref = self.instantiate_binder_with_placeholders(trait_ref); - let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id); - let impl_trait_ref = ocx.normalize( - &ObligationCause::dummy(), - param_env, - ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args), - ); - ocx.register_obligations( - self.tcx - .predicates_of(single.impl_def_id) - .instantiate(self.tcx, impl_args) - .into_iter() - .map(|(clause, _)| { - Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause) - }), - ); - if !ocx.select_where_possible().is_empty() { - return false; - } + self.enter_forall(trait_ref, |obligation_trait_ref| { + let impl_args = self.fresh_args_for_item(DUMMY_SP, single.impl_def_id); + let impl_trait_ref = ocx.normalize( + &ObligationCause::dummy(), + param_env, + ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args), + ); - let mut terrs = vec![]; - for (obligation_arg, impl_arg) in - std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args) - { - if let Err(terr) = - ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg) - { - terrs.push(terr); - } + ocx.register_obligations( + self.tcx + .predicates_of(single.impl_def_id) + .instantiate(self.tcx, impl_args) + .into_iter() + .map(|(clause, _)| { + Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + clause, + ) + }), + ); if !ocx.select_where_possible().is_empty() { return false; } - } - // Literally nothing unified, just give up. - if terrs.len() == impl_trait_ref.args.len() { - return false; - } + let mut terrs = vec![]; + for (obligation_arg, impl_arg) in + std::iter::zip(obligation_trait_ref.args, impl_trait_ref.args) + { + if let Err(terr) = + ocx.eq(&ObligationCause::dummy(), param_env, impl_arg, obligation_arg) + { + terrs.push(terr); + } + if !ocx.select_where_possible().is_empty() { + return false; + } + } - let cand = - self.resolve_vars_if_possible(impl_trait_ref).fold_with(&mut BottomUpFolder { - tcx: self.tcx, - ty_op: |ty| ty, - lt_op: |lt| lt, - ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()), - }); - err.highlighted_help(vec![ - StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())), - StringPart::highlighted("is"), - StringPart::normal(" implemented for `"), - StringPart::highlighted(cand.self_ty().to_string()), - StringPart::normal("`"), - ]); + // Literally nothing unified, just give up. + if terrs.len() == impl_trait_ref.args.len() { + return false; + } - if let [TypeError::Sorts(exp_found)] = &terrs[..] { - let exp_found = self.resolve_vars_if_possible(*exp_found); - err.help(format!( - "for that trait implementation, expected `{}`, found `{}`", - exp_found.expected, exp_found.found - )); - } + let cand = self.resolve_vars_if_possible(impl_trait_ref).fold_with( + &mut BottomUpFolder { + tcx: self.tcx, + ty_op: |ty| ty, + lt_op: |lt| lt, + ct_op: |ct| ct.normalize(self.tcx, ty::ParamEnv::empty()), + }, + ); + err.highlighted_help(vec![ + StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())), + StringPart::highlighted("is"), + StringPart::normal(" implemented for `"), + StringPart::highlighted(cand.self_ty().to_string()), + StringPart::normal("`"), + ]); + + if let [TypeError::Sorts(exp_found)] = &terrs[..] { + let exp_found = self.resolve_vars_if_possible(*exp_found); + err.help(format!( + "for that trait implementation, expected `{}`, found `{}`", + exp_found.expected, exp_found.found + )); + } - true + true + }) }) { return true; } @@ -2371,6 +2378,12 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { return e; } + if let Err(guar) = self.tcx.ensure().coherent_trait(trait_ref.def_id()) { + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + return guar; + } + // This is kind of a hack: it frequently happens that some earlier // error prevents types from being fully inferred, and then we get // a bunch of uninteresting errors saying something like "<generic @@ -2666,6 +2679,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let Some(e) = self.tainted_by_errors() { return e; } + + if let Err(guar) = + self.tcx.ensure().coherent_trait(self.tcx.parent(data.projection_ty.def_id)) + { + // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case + // other `Foo` impls are incoherent. + return guar; + } let subst = data .projection_ty .args diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 0337672b302..5ef7a202a12 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -358,8 +358,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { | ty::PredicateKind::Coerce(_) | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) | ty::PredicateKind::ConstEquate(..) => { - let pred = - ty::Binder::dummy(infcx.instantiate_binder_with_placeholders(binder)); + let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder)); ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)])) } ty::PredicateKind::Ambiguous => ProcessResult::Unchanged, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 0dc11d785c4..054402acb5c 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -40,6 +40,7 @@ use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::sym; use std::collections::BTreeMap; +use std::ops::ControlFlow; pub use rustc_middle::traits::Reveal; @@ -250,8 +251,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( let infcx = selcx.infcx; let r = infcx.commit_if_ok(|_snapshot| { let old_universe = infcx.universe(); - let placeholder_predicate = - infcx.instantiate_binder_with_placeholders(obligation.predicate); + let placeholder_predicate = infcx.enter_forall_and_leak_universe(obligation.predicate); let new_universe = infcx.universe(); let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate); @@ -1615,32 +1615,44 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( candidate_set: &mut ProjectionCandidateSet<'tcx>, ) { debug!("assemble_candidates_from_trait_def(..)"); + let mut ambiguous = false; + selcx.for_each_item_bound( + obligation.predicate.self_ty(), + |selcx, clause, _| { + let Some(clause) = clause.as_projection_clause() else { + return ControlFlow::Continue(()); + }; - let tcx = selcx.tcx(); - // Check whether the self-type is itself a projection. - // If so, extract what we know from the trait and try to come up with a good answer. - let bounds = match *obligation.predicate.self_ty().kind() { - // Excluding IATs and type aliases here as they don't have meaningful item bounds. - ty::Alias(ty::Projection | ty::Opaque, ref data) => { - tcx.item_bounds(data.def_id).instantiate(tcx, data.args) - } - ty::Infer(ty::TyVar(_)) => { - // If the self-type is an inference variable, then it MAY wind up - // being a projected type, so induce an ambiguity. - candidate_set.mark_ambiguous(); - return; - } - _ => return, - }; + let is_match = + selcx.infcx.probe(|_| selcx.match_projection_projections(obligation, clause, true)); - assemble_candidates_from_predicates( - selcx, - obligation, - candidate_set, - ProjectionCandidate::TraitDef, - bounds.iter(), - true, + match is_match { + ProjectionMatchesProjection::Yes => { + candidate_set.push_candidate(ProjectionCandidate::TraitDef(clause)); + + if !obligation.predicate.has_non_region_infer() { + // HACK: Pick the first trait def candidate for a fully + // inferred predicate. This is to allow duplicates that + // differ only in normalization. + return ControlFlow::Break(()); + } + } + ProjectionMatchesProjection::Ambiguous => { + candidate_set.mark_ambiguous(); + } + ProjectionMatchesProjection::No => {} + } + + ControlFlow::Continue(()) + }, + // `ProjectionCandidateSet` is borrowed in the above closure, + // so just mark ambiguous outside of the closure. + || ambiguous = true, ); + + if ambiguous { + candidate_set.mark_ambiguous(); + } } /// In the case of a trait object like @@ -1936,10 +1948,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // Integers and floats are always Sized, and so have unit type metadata. | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true, - // type parameters, opaques, and unnormalized projections have pointer - // metadata if they're known (e.g. by the param_env) to be sized + // We normalize from `Wrapper<Tail>::Metadata` to `Tail::Metadata` if able. + // Otherwise, type parameters, opaques, and unnormalized projections have + // unit metadata if they're known (e.g. by the param_env) to be sized. ty::Param(_) | ty::Alias(..) - if selcx.infcx.predicate_must_hold_modulo_regions( + if self_ty != tail || selcx.infcx.predicate_must_hold_modulo_regions( &obligation.with( selcx.tcx(), ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]), @@ -2315,7 +2328,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( assert_eq!(metadata_def_id, item_def_id); let mut obligations = Vec::new(); - let (metadata_ty, check_is_sized) = self_ty.ptr_metadata_ty(tcx, |ty| { + let normalize = |ty| { normalize_with_depth_to( selcx, obligation.param_env, @@ -2324,16 +2337,27 @@ fn confirm_builtin_candidate<'cx, 'tcx>( ty, &mut obligations, ) + }; + let metadata_ty = self_ty.ptr_metadata_ty_or_tail(tcx, normalize).unwrap_or_else(|tail| { + if tail == self_ty { + // This is the "fallback impl" for type parameters, unnormalizable projections + // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`. + // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't + // exist. Instead, `Pointee<Metadata = ()>` should be a supertrait of `Sized`. + let sized_predicate = ty::TraitRef::from_lang_item( + tcx, + LangItem::Sized, + obligation.cause.span(), + [self_ty], + ); + obligations.push(obligation.with(tcx, sized_predicate)); + tcx.types.unit + } else { + // We know that `self_ty` has the same metadata as `tail`. This allows us + // to prove predicates like `Wrapper<Tail>::Metadata == Tail::Metadata`. + Ty::new_projection(tcx, metadata_def_id, [tail]) + } }); - if check_is_sized { - let sized_predicate = ty::TraitRef::from_lang_item( - tcx, - LangItem::Sized, - obligation.cause.span(), - [self_ty], - ); - obligations.push(obligation.with(tcx, sized_predicate)); - } (metadata_ty.into(), obligations) } else { bug!("unexpected builtin trait with associated type: {:?}", obligation.predicate); diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs index 4c0c57377e0..a050b30317a 100644 --- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs +++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs @@ -41,7 +41,28 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// not entirely accurate if inference variables are involved. /// /// This version may conservatively fail when outlives obligations - /// are required. + /// are required. Therefore, this version should only be used for + /// optimizations or diagnostics and be treated as if it can always + /// return `false`. + /// + /// # Example + /// + /// ``` + /// # #![allow(dead_code)] + /// trait Trait {} + /// + /// fn check<T: Trait>() {} + /// + /// fn foo<T: 'static>() + /// where + /// &'static T: Trait, + /// { + /// // Evaluating `&'?0 T: Trait` adds a `'?0: 'static` outlives obligation, + /// // which means that `predicate_must_hold_considering_regions` will return + /// // `false`. + /// check::<&'_ T>(); + /// } + /// ``` fn predicate_must_hold_considering_regions( &self, obligation: &PredicateObligation<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index eb4b3b7a62e..f9a292c2bd7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -6,13 +6,16 @@ //! //! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly +use std::ops::ControlFlow; + use hir::def_id::DefId; use hir::LangItem; +use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_infer::traits::ObligationCause; use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError}; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; -use rustc_middle::ty::{self, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt}; use crate::traits; use crate::traits::query::evaluate_obligation::InferCtxtExt; @@ -158,11 +161,50 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => return, } - let result = self - .infcx - .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); + self.infcx.probe(|_| { + let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); + let placeholder_trait_predicate = + self.infcx.enter_forall_and_leak_universe(poly_trait_predicate); + debug!(?placeholder_trait_predicate); + + // The bounds returned by `item_bounds` may contain duplicates after + // normalization, so try to deduplicate when possible to avoid + // unnecessary ambiguity. + let mut distinct_normalized_bounds = FxHashSet::default(); + self.for_each_item_bound::<!>( + placeholder_trait_predicate.self_ty(), + |selcx, bound, idx| { + let Some(bound) = bound.as_trait_clause() else { + return ControlFlow::Continue(()); + }; + if bound.polarity() != placeholder_trait_predicate.polarity { + return ControlFlow::Continue(()); + } - candidates.vec.extend(result.into_iter().map(|idx| ProjectionCandidate(idx))); + selcx.infcx.probe(|_| { + match selcx.match_normalize_trait_ref( + obligation, + bound.to_poly_trait_ref(), + placeholder_trait_predicate.trait_ref, + ) { + Ok(None) => { + candidates.vec.push(ProjectionCandidate(idx)); + } + Ok(Some(normalized_trait)) + if distinct_normalized_bounds.insert(normalized_trait) => + { + candidates.vec.push(ProjectionCandidate(idx)); + } + _ => {} + } + }); + + ControlFlow::Continue(()) + }, + // On ambiguity. + || candidates.ambiguous = true, + ); + }); } /// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller @@ -775,64 +817,63 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.probe(|_snapshot| { let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); - let placeholder_trait_predicate = - self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate); - - let self_ty = placeholder_trait_predicate.self_ty(); - let principal_trait_ref = match self_ty.kind() { - ty::Dynamic(data, ..) => { - if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { - debug!( - "assemble_candidates_from_object_ty: matched builtin bound, \ + self.infcx.enter_forall(poly_trait_predicate, |placeholder_trait_predicate| { + let self_ty = placeholder_trait_predicate.self_ty(); + let principal_trait_ref = match self_ty.kind() { + ty::Dynamic(data, ..) => { + if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { + debug!( + "assemble_candidates_from_object_ty: matched builtin bound, \ pushing candidate" - ); - candidates.vec.push(BuiltinObjectCandidate); - return; - } + ); + candidates.vec.push(BuiltinObjectCandidate); + return; + } - if let Some(principal) = data.principal() { - if !self.infcx.tcx.features().object_safe_for_dispatch { - principal.with_self_ty(self.tcx(), self_ty) - } else if self.tcx().check_is_object_safe(principal.def_id()) { - principal.with_self_ty(self.tcx(), self_ty) + if let Some(principal) = data.principal() { + if !self.infcx.tcx.features().object_safe_for_dispatch { + principal.with_self_ty(self.tcx(), self_ty) + } else if self.tcx().check_is_object_safe(principal.def_id()) { + principal.with_self_ty(self.tcx(), self_ty) + } else { + return; + } } else { + // Only auto trait bounds exist. return; } - } else { - // Only auto trait bounds exist. + } + ty::Infer(ty::TyVar(_)) => { + debug!("assemble_candidates_from_object_ty: ambiguous"); + candidates.ambiguous = true; // could wind up being an object type return; } - } - ty::Infer(ty::TyVar(_)) => { - debug!("assemble_candidates_from_object_ty: ambiguous"); - candidates.ambiguous = true; // could wind up being an object type - return; - } - _ => return, - }; - - debug!(?principal_trait_ref, "assemble_candidates_from_object_ty"); - - // Count only those upcast versions that match the trait-ref - // we are looking for. Specifically, do not only check for the - // correct trait, but also the correct type parameters. - // For example, we may be trying to upcast `Foo` to `Bar<i32>`, - // but `Foo` is declared as `trait Foo: Bar<u32>`. - let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref) - .enumerate() - .filter(|&(_, upcast_trait_ref)| { - self.infcx.probe(|_| { - self.match_normalize_trait_ref( - obligation, - upcast_trait_ref, - placeholder_trait_predicate.trait_ref, - ) - .is_ok() + _ => return, + }; + + debug!(?principal_trait_ref, "assemble_candidates_from_object_ty"); + + // Count only those upcast versions that match the trait-ref + // we are looking for. Specifically, do not only check for the + // correct trait, but also the correct type parameters. + // For example, we may be trying to upcast `Foo` to `Bar<i32>`, + // but `Foo` is declared as `trait Foo: Bar<u32>`. + let candidate_supertraits = util::supertraits(self.tcx(), principal_trait_ref) + .enumerate() + .filter(|&(_, upcast_trait_ref)| { + self.infcx.probe(|_| { + self.match_normalize_trait_ref( + obligation, + upcast_trait_ref, + placeholder_trait_predicate.trait_ref, + ) + .is_ok() + }) }) - }) - .map(|(idx, _)| ObjectCandidate(idx)); + .map(|(idx, _)| ObjectCandidate(idx)); - candidates.vec.extend(candidate_supertraits); + candidates.vec.extend(candidate_supertraits); + }) }) } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index f2dc4b1be73..6ca24933979 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -159,23 +159,29 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let trait_predicate = self.infcx.shallow_resolve(obligation.predicate); let placeholder_trait_predicate = - self.infcx.instantiate_binder_with_placeholders(trait_predicate).trait_ref; + self.infcx.enter_forall_and_leak_universe(trait_predicate).trait_ref; let placeholder_self_ty = placeholder_trait_predicate.self_ty(); let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate); - let (def_id, args) = match *placeholder_self_ty.kind() { - // Excluding IATs and type aliases here as they don't have meaningful item bounds. - ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) => { - (def_id, args) - } - _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty), - }; - let candidate_predicate = - tcx.item_bounds(def_id).map_bound(|i| i[idx]).instantiate(tcx, args); + let candidate_predicate = self + .for_each_item_bound( + placeholder_self_ty, + |_, clause, clause_idx| { + if clause_idx == idx { + ControlFlow::Break(clause) + } else { + ControlFlow::Continue(()) + } + }, + || unreachable!(), + ) + .break_value() + .expect("expected to index into clause that exists"); let candidate = candidate_predicate .as_trait_clause() .expect("projection candidate is not a trait predicate") .map_bound(|t| t.trait_ref); + let mut obligations = Vec::new(); let candidate = normalize_with_depth_to( self, @@ -194,8 +200,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_err(|_| Unimplemented) })?); - if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() { - let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args); + // FIXME(compiler-errors): I don't think this is needed. + if let ty::Alias(ty::Projection, alias_ty) = placeholder_self_ty.kind() { + let predicates = tcx.predicates_of(alias_ty.def_id).instantiate_own(tcx, alias_ty.args); for (predicate, _) in predicates { let normalized = normalize_with_depth_to( self, @@ -402,7 +409,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = obligation.derived_cause(BuiltinDerivedObligation); let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let trait_ref = self.infcx.instantiate_binder_with_placeholders(poly_trait_ref); + let trait_ref = self.infcx.enter_forall_and_leak_universe(poly_trait_ref); let trait_obligations: Vec<PredicateObligation<'_>> = self.impl_or_trait_obligations( &cause, obligation.recursion_depth + 1, @@ -493,7 +500,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tcx = self.tcx(); debug!(?obligation, ?index, "confirm_object_candidate"); - let trait_predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + let trait_predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let self_ty = self.infcx.shallow_resolve(trait_predicate.self_ty()); let obligation_trait_ref = ty::Binder::dummy(trait_predicate.trait_ref); let ty::Dynamic(data, ..) = *self_ty.kind() else { @@ -691,7 +698,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = obligation.derived_cause(BuiltinDerivedObligation); // Confirm the `type Output: Sized;` bound that is present on `FnOnce` - let output_ty = self.infcx.instantiate_binder_with_placeholders(sig.output()); + let output_ty = self.infcx.enter_forall_and_leak_universe(sig.output()); let output_ty = normalize_with_depth_to( self, obligation.param_env, @@ -712,7 +719,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) -> Vec<PredicateObligation<'tcx>> { debug!(?obligation, "confirm_trait_alias_candidate"); - let predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + let predicate = self.infcx.enter_forall_and_leak_universe(obligation.predicate); let trait_ref = predicate.trait_ref; let trait_def_id = trait_ref.def_id; let args = trait_ref.args; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 7f41c73b72f..ac6cfcdeb59 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -52,6 +52,7 @@ use std::cell::{Cell, RefCell}; use std::cmp; use std::fmt::{self, Display}; use std::iter; +use std::ops::ControlFlow; pub use rustc_middle::traits::select::*; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -483,7 +484,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Instead, we select the right impl now but report "`Bar` does // not implement `Clone`". if candidates.len() == 1 { - return self.filter_reservation_impls(candidates.pop().unwrap(), stack.obligation); + return self.filter_reservation_impls(candidates.pop().unwrap()); } // Winnow, but record the exact outcome of evaluation, which @@ -557,7 +558,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // Just one candidate left. - self.filter_reservation_impls(candidates.pop().unwrap().candidate, stack.obligation) + self.filter_reservation_impls(candidates.pop().unwrap().candidate) } /////////////////////////////////////////////////////////////////////////// @@ -1436,7 +1437,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn filter_reservation_impls( &mut self, candidate: SelectionCandidate<'tcx>, - obligation: &PolyTraitObligation<'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { let tcx = self.tcx(); // Treat reservation impls as ambiguity. @@ -1593,71 +1593,41 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.infcx.selection_cache.insert((param_env, pred), dep_node, candidate); } - /// Matches a predicate against the bounds of its self type. - /// - /// Given an obligation like `<T as Foo>::Bar: Baz` where the self type is - /// a projection, look at the bounds of `T::Bar`, see if we can find a - /// `Baz` bound. We return indexes into the list returned by - /// `tcx.item_bounds` for any applicable bounds. - #[instrument(level = "debug", skip(self), ret)] - fn match_projection_obligation_against_definition_bounds( + /// Looks at the item bounds of the projection or opaque type. + /// If this is a nested rigid projection, such as + /// `<<T as Tr1>::Assoc as Tr2>::Assoc`, consider the item bounds + /// on both `Tr1::Assoc` and `Tr2::Assoc`, since we may encounter + /// relative bounds on both via the `associated_type_bounds` feature. + pub(super) fn for_each_item_bound<T>( &mut self, - obligation: &PolyTraitObligation<'tcx>, - ) -> smallvec::SmallVec<[usize; 2]> { - let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); - let placeholder_trait_predicate = - self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate); - debug!(?placeholder_trait_predicate); - - let tcx = self.infcx.tcx; - let (def_id, args) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() { - ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. }) => { - (def_id, args) - } - _ => { - span_bug!( - obligation.cause.span, - "match_projection_obligation_against_definition_bounds() called \ - but self-ty is not a projection: {:?}", - placeholder_trait_predicate.trait_ref.self_ty() - ); - } - }; - let bounds = tcx.item_bounds(def_id).instantiate(tcx, args); + mut self_ty: Ty<'tcx>, + mut for_each: impl FnMut(&mut Self, ty::Clause<'tcx>, usize) -> ControlFlow<T, ()>, + on_ambiguity: impl FnOnce(), + ) -> ControlFlow<T, ()> { + let mut idx = 0; + loop { + let (kind, alias_ty) = match *self_ty.kind() { + ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) => (kind, alias_ty), + ty::Infer(ty::TyVar(_)) => { + on_ambiguity(); + return ControlFlow::Continue(()); + } + _ => return ControlFlow::Continue(()), + }; - // The bounds returned by `item_bounds` may contain duplicates after - // normalization, so try to deduplicate when possible to avoid - // unnecessary ambiguity. - let mut distinct_normalized_bounds = FxHashSet::default(); + for bound in + self.tcx().item_bounds(alias_ty.def_id).instantiate(self.tcx(), alias_ty.args) + { + for_each(self, bound, idx)?; + idx += 1; + } - bounds - .iter() - .enumerate() - .filter_map(|(idx, bound)| { - let bound_predicate = bound.kind(); - if let ty::ClauseKind::Trait(pred) = bound_predicate.skip_binder() { - let bound = bound_predicate.rebind(pred.trait_ref); - if self.infcx.probe(|_| { - match self.match_normalize_trait_ref( - obligation, - bound, - placeholder_trait_predicate.trait_ref, - ) { - Ok(None) => true, - Ok(Some(normalized_trait)) - if distinct_normalized_bounds.insert(normalized_trait) => - { - true - } - _ => false, - } - }) { - return Some(idx); - } - } - None - }) - .collect() + if kind == ty::Projection { + self_ty = alias_ty.self_ty(); + } else { + return ControlFlow::Continue(()); + } + } } /// Equates the trait in `obligation` with trait bound. If the two traits @@ -2386,7 +2356,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { .flat_map(|ty| { let ty: ty::Binder<'tcx, Ty<'tcx>> = types.rebind(*ty); // <----/ - let placeholder_ty = self.infcx.instantiate_binder_with_placeholders(ty); + let placeholder_ty = self.infcx.enter_forall_and_leak_universe(ty); let Normalized { value: normalized_ty, mut obligations } = ensure_sufficient_stack(|| { project::normalize_with_depth( @@ -2472,7 +2442,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { obligation: &PolyTraitObligation<'tcx>, ) -> Result<Normalized<'tcx, GenericArgsRef<'tcx>>, ()> { let placeholder_obligation = - self.infcx.instantiate_binder_with_placeholders(obligation.predicate); + self.infcx.enter_forall_and_leak_universe(obligation.predicate); let placeholder_obligation_trait_ref = placeholder_obligation.trait_ref; let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id); diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index c7916ec60bb..e73bbf6048e 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -1,7 +1,5 @@ //! Queries that are independent from the main solver code. -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index c80389a3a4d..ac4f67d1b55 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -1,8 +1,6 @@ #![feature(alloc_layout_extra)] #![feature(never_type)] #![allow(dead_code, unused_variables)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate tracing; diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 51acb99d29b..fd392d11e83 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -15,8 +15,6 @@ #![feature(iterator_try_collect)] #![feature(let_chains)] #![feature(never_type)] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #[macro_use] extern crate rustc_middle; @@ -37,7 +35,7 @@ mod layout_sanity_check; mod needs_drop; mod opaque_types; mod representability; -mod sig_types; +pub mod sig_types; mod structural_match; mod ty; diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index 3aaa2e73bb8..70f1f099688 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -1,5 +1,3 @@ -#![allow(rustc::untranslatable_diagnostic, rustc::diagnostic_outside_of_impl)] - use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; use rustc_middle::query::Providers; diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index b155a4ac87b..38cc558380c 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -4,11 +4,11 @@ use std::ops::ControlFlow; use rustc_hir::{def::DefKind, def_id::LocalDefId}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Span; use rustc_type_ir::visit::TypeVisitable; -pub(crate) trait SpannedTypeVisitor<'tcx> { +pub trait SpannedTypeVisitor<'tcx> { type BreakTy = !; fn visit( &mut self, @@ -17,7 +17,7 @@ pub(crate) trait SpannedTypeVisitor<'tcx> { ) -> ControlFlow<Self::BreakTy>; } -pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( +pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( tcx: TyCtxt<'tcx>, item: LocalDefId, visitor: &mut V, @@ -42,11 +42,10 @@ pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( DefKind::TyAlias {..} | DefKind::AssocTy | // Walk over the type of the item DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => { - let span = match tcx.hir_node_by_def_id(item).ty() { - Some(ty) => ty.span, - _ => tcx.def_span(item), - }; - visitor.visit(span, tcx.type_of(item).instantiate_identity()); + if let Some(ty) = tcx.hir_node_by_def_id(item).ty() { + // Associated types in traits don't necessarily have a type that we can visit + visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())?; + } for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { visitor.visit(span, pred)?; } @@ -59,7 +58,16 @@ pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // Look at field types DefKind::Struct | DefKind::Union | DefKind::Enum => { let span = tcx.def_ident_span(item).unwrap(); - visitor.visit(span, tcx.type_of(item).instantiate_identity()); + let ty = tcx.type_of(item).instantiate_identity(); + visitor.visit(span, ty); + let ty::Adt(def, args) = ty.kind() else { + span_bug!(span, "invalid type for {kind:?}: {:#?}", ty.kind()) + }; + for field in def.all_fields() { + let span = tcx.def_ident_span(field.did).unwrap(); + let ty = field.ty(tcx, args); + visitor.visit(span, ty); + } for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { visitor.visit(span, pred)?; } @@ -89,7 +97,6 @@ pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( } } | DefKind::Variant - | DefKind::ForeignTy | DefKind::TyParam | DefKind::ConstParam | DefKind::Ctor(_, _) @@ -103,6 +110,7 @@ pub(crate) fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // These don't have any types. | DefKind::ExternCrate | DefKind::ForeignMod + | DefKind::ForeignTy | DefKind::Macro(_) | DefKind::GlobalAsm | DefKind::Mod diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 83efbfb855f..f498c5531fc 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -2,8 +2,6 @@ feature = "nightly", feature(associated_type_defaults, min_specialization, never_type, rustc_attrs) )] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] #![allow(rustc::usage_of_ty_tykind)] #![cfg_attr(feature = "nightly", allow(internal_features))] diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 3b5e41e8d85..777c649fabd 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -163,8 +163,7 @@ pub enum RegionKind<I: Interner> { /// A placeholder region -- the higher-ranked version of `ReLateParam`. /// Should not exist outside of type inference. /// - /// Used when instantiating a `forall` binder via - /// `infcx.instantiate_binder_with_placeholders`. + /// Used when instantiating a `forall` binder via `infcx.enter_forall`. RePlaceholder(I::PlaceholderRegion), /// Erased region, used by trait selection, in MIR and during codegen. diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 38877f7a77f..be727f024c6 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -639,6 +639,7 @@ impl Rvalue { Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => { Ok(Ty::usize_ty()) } + Rvalue::NullaryOp(NullOp::DebugAssertions, _) => Ok(Ty::bool_ty()), Rvalue::Aggregate(ak, ops) => match *ak { AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64), AggregateKind::Tuple => Ok(Ty::new_tuple( @@ -1005,6 +1006,8 @@ pub enum NullOp { AlignOf, /// Returns the offset of a field. OffsetOf(Vec<(VariantIdx, FieldIdx)>), + /// cfg!(debug_assertions), but at codegen time + DebugAssertions, } impl Operand { diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 94e6924f41a..49f5f53f9b3 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -207,11 +207,7 @@ impl<T, A: Allocator> RawVec<T, A> { // Allocators currently return a `NonNull<[u8]>` whose length // matches the size requested. If that ever changes, the capacity // here should change to `ptr.len() / mem::size_of::<T>()`. - Self { - ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }, - cap: unsafe { Cap(capacity) }, - alloc, - } + Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc } } } @@ -239,6 +235,11 @@ impl<T, A: Allocator> RawVec<T, A> { self.ptr.as_ptr() } + #[inline] + pub fn non_null(&self) -> NonNull<T> { + NonNull::from(self.ptr) + } + /// Gets the capacity of the allocation. /// /// This will always be `usize::MAX` if `T` is zero-sized. @@ -398,7 +399,7 @@ impl<T, A: Allocator> RawVec<T, A> { // Allocators currently return a `NonNull<[u8]>` whose length matches // the size requested. If that ever changes, the capacity here should // change to `ptr.len() / mem::size_of::<T>()`. - self.ptr = unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }; + self.ptr = Unique::from(ptr.cast()); self.cap = unsafe { Cap(cap) }; } diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs index 4033f4eb068..f4e392760c8 100644 --- a/library/alloc/src/slice.rs +++ b/library/alloc/src/slice.rs @@ -51,7 +51,7 @@ pub use core::slice::{from_mut, from_ref}; pub use core::slice::{from_mut_ptr_range, from_ptr_range}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{from_raw_parts, from_raw_parts_mut}; -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] pub use core::slice::{ChunkBy, ChunkByMut}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::slice::{Chunks, Windows}; diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs index b12910f3690..3fe83242a30 100644 --- a/library/alloc/src/vec/cow.rs +++ b/library/alloc/src/vec/cow.rs @@ -15,7 +15,7 @@ impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> { } } -#[stable(feature = "cow_from_array_ref", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "cow_from_array_ref", since = "1.77.0")] impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> { /// Creates a [`Borrowed`] variant of [`Cow`] /// from a reference to an array. diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 654ce09afcd..7800560da94 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -136,7 +136,7 @@ impl<T, A: Allocator> IntoIter<T, A> { // struct and then overwriting &mut self. // this creates less assembly self.cap = 0; - self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) }; + self.buf = RawVec::NEW.non_null(); self.ptr = self.buf; self.end = self.buf.as_ptr(); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index b3e5ecc9240..08e3cdedc66 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2861,16 +2861,16 @@ impl<T, A: Allocator> IntoIterator for Vec<T, A> { #[inline] fn into_iter(self) -> Self::IntoIter { unsafe { - let mut me = ManuallyDrop::new(self); + let me = ManuallyDrop::new(self); let alloc = ManuallyDrop::new(ptr::read(me.allocator())); - let begin = me.as_mut_ptr(); + let buf = me.buf.non_null(); + let begin = buf.as_ptr(); let end = if T::IS_ZST { begin.wrapping_byte_add(me.len()) } else { begin.add(me.len()) as *const T }; let cap = me.buf.capacity(); - let buf = NonNull::new_unchecked(begin); IntoIter { buf, phantom: PhantomData, cap, alloc, ptr: buf, end } } } diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 85cce81f2c1..743f07644e3 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -576,7 +576,7 @@ impl<T, const N: usize> [T; N] { /// // We can still access the original array: it has not been moved. /// assert_eq!(strings.len(), 3); /// ``` - #[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "array_methods", since = "1.77.0")] pub fn each_ref(&self) -> [&T; N] { from_trusted_iterator(self.iter()) } @@ -595,7 +595,7 @@ impl<T, const N: usize> [T; N] { /// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]); /// assert_eq!(floats, [0.0, 2.7, -1.0]); /// ``` - #[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "array_methods", since = "1.77.0")] pub fn each_mut(&mut self) -> [&mut T; N] { from_trusted_iterator(self.iter_mut()) } diff --git a/library/core/src/async_iter/async_iter.rs b/library/core/src/async_iter/async_iter.rs index db71a286b6d..489f95bbf10 100644 --- a/library/core/src/async_iter/async_iter.rs +++ b/library/core/src/async_iter/async_iter.rs @@ -47,7 +47,7 @@ pub trait AsyncIterator { /// Rust's usual rules apply: calls must never cause undefined behavior /// (memory corruption, incorrect use of `unsafe` functions, or the like), /// regardless of the async iterator's state. - #[cfg_attr(not(bootstrap), lang = "async_iterator_poll_next")] + #[lang = "async_iterator_poll_next"] fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>; /// Returns the bounds on the remaining length of the async iterator. @@ -145,7 +145,7 @@ pub trait IntoAsyncIterator { type IntoAsyncIter: AsyncIterator<Item = Self::Item>; /// Converts `self` into an async iterator - #[cfg_attr(not(bootstrap), lang = "into_async_iter_into_iter")] + #[lang = "into_async_iter_into_iter"] fn into_async_iter(self) -> Self::IntoAsyncIter; } diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 177f39b59ae..7bd592492a5 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -27,7 +27,7 @@ pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char { unsafe { assert_unsafe_precondition!( "invalid value for `char`", - (i: u32) => char_try_from_u32(i).is_ok() + (i: u32 = i) => char_try_from_u32(i).is_ok() ); transmute(i) } diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 5c44ca69451..97c3c9e6fae 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -148,7 +148,7 @@ pub const unsafe fn assert_unchecked(cond: bool) { unsafe { intrinsics::assert_unsafe_precondition!( "hint::assert_unchecked must never be called when the condition is false", - (cond: bool) => cond, + (cond: bool = cond) => cond, ); crate::intrinsics::assume(cond); } diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 43124535ab5..18c82f97c28 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -56,7 +56,7 @@ use crate::marker::DiscriminantKind; use crate::marker::Tuple; -use crate::mem; +use crate::mem::{self, align_of}; pub mod mir; pub mod simd; @@ -947,7 +947,7 @@ extern "rust-intrinsic" { /// own, or if it does not enable any significant optimizations. /// /// This intrinsic does not have a stable counterpart. - #[rustc_const_stable(feature = "const_assume", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "const_assume", since = "1.77.0")] #[rustc_nounwind] pub fn assume(b: bool); @@ -2567,16 +2567,18 @@ extern "rust-intrinsic" { /// matter what*. #[rustc_const_unstable(feature = "is_val_statically_known", issue = "none")] #[rustc_nounwind] - #[cfg(not(bootstrap))] pub fn is_val_statically_known<T: Copy>(arg: T) -> bool; + + #[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")] + #[rustc_safe_intrinsic] + #[cfg(not(bootstrap))] + pub(crate) fn debug_assertions() -> bool; } -// FIXME: Seems using `unstable` here completely ignores `rustc_allow_const_fn_unstable` -// and thus compiling stage0 core doesn't work. -#[rustc_const_stable(feature = "is_val_statically_known", since = "0.0.0")] #[cfg(bootstrap)] -pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool { - false +#[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")] +pub(crate) const fn debug_assertions() -> bool { + cfg!(debug_assertions) } // Some functions are defined here because they accidentally got made @@ -2587,10 +2589,27 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool { /// Check that the preconditions of an unsafe function are followed, if debug_assertions are on, /// and only at runtime. /// -/// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)` -/// where the names specified will be moved into the macro as captured variables, and defines an item -/// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics -/// for the function declarations and can be omitted if there is no generics. +/// This macro should be called as +/// `assert_unsafe_precondition!((expr => name: Type, expr => name: Type) => Expression)` +/// where each `expr` will be evaluated and passed in as function argument `name: Type`. Then all +/// those arguments are passed to a function via [`const_eval_select`]. +/// +/// These checks are behind a condition which is evaluated at codegen time, not expansion time like +/// [`debug_assert`]. This means that a standard library built with optimizations and debug +/// assertions disabled will have these checks optimized out of its monomorphizations, but if a +/// a caller of the standard library has debug assertions enabled and monomorphizes an expansion of +/// this macro, that monomorphization will contain the check. +/// +/// Since these checks cannot be optimized out in MIR, some care must be taken in both call and +/// implementation to mitigate their compile-time overhead. The runtime function that we +/// [`const_eval_select`] to is monomorphic, `#[inline(never)]`, and `#[rustc_nounwind]`. That +/// combination of properties ensures that the code for the checks is only compiled once, and has a +/// minimal impact on the caller's code size. +/// +/// Caller should also introducing any other `let` bindings or any code outside this macro in order +/// to call it. Since the precompiled standard library is built with full debuginfo and these +/// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough +/// debuginfo to have a measurable compile-time impact on debug builds. /// /// # Safety /// @@ -2604,26 +2623,24 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool { /// /// So in a sense it is UB if this macro is useful, but we expect callers of `unsafe fn` to make /// the occasional mistake, and this check should help them figure things out. -#[allow_internal_unstable(const_eval_select)] // permit this to be called in stably-const fn +#[allow_internal_unstable(const_eval_select, delayed_debug_assertions)] // permit this to be called in stably-const fn macro_rules! assert_unsafe_precondition { - ($name:expr, $([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr $(,)?) => { - if cfg!(debug_assertions) { - // allow non_snake_case to allow capturing const generics - #[allow(non_snake_case)] - #[inline(always)] - fn runtime$(<$($tt)*>)?($($i:$ty),*) { + ($message:expr, ($($name:ident:$ty:ty = $arg:expr),*$(,)?) => $e:expr $(,)?) => { + { + #[inline(never)] + #[rustc_nounwind] + fn precondition_check($($name:$ty),*) { if !$e { - // don't unwind to reduce impact on code size ::core::panicking::panic_nounwind( - concat!("unsafe precondition(s) violated: ", $name) + concat!("unsafe precondition(s) violated: ", $message) ); } } - #[allow(non_snake_case)] - #[inline] - const fn comptime$(<$($tt)*>)?($(_:$ty),*) {} + const fn comptime($(_:$ty),*) {} - ::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime); + if ::core::intrinsics::debug_assertions() { + ::core::intrinsics::const_eval_select(($($arg,)*), comptime, precondition_check); + } } }; } @@ -2632,30 +2649,47 @@ pub(crate) use assert_unsafe_precondition; /// Checks whether `ptr` is properly aligned with respect to /// `align_of::<T>()`. #[inline] -pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool { - !ptr.is_null() && ptr.is_aligned() +pub(crate) fn is_aligned_and_not_null(ptr: *const (), align: usize) -> bool { + !ptr.is_null() && ptr.is_aligned_to(align) } -/// Checks whether an allocation of `len` instances of `T` exceeds -/// the maximum allowed allocation size. #[inline] -pub(crate) fn is_valid_allocation_size<T>(len: usize) -> bool { - let max_len = const { - let size = crate::mem::size_of::<T>(); - if size == 0 { usize::MAX } else { isize::MAX as usize / size } - }; +pub(crate) fn is_valid_allocation_size(size: usize, len: usize) -> bool { + let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size }; len <= max_len } +pub(crate) fn is_nonoverlapping_mono( + src: *const (), + dst: *const (), + size: usize, + count: usize, +) -> bool { + let src_usize = src.addr(); + let dst_usize = dst.addr(); + let Some(size) = size.checked_mul(count) else { + crate::panicking::panic_nounwind( + "is_nonoverlapping: `size_of::<T>() * count` overflows a usize", + ) + }; + let diff = src_usize.abs_diff(dst_usize); + // If the absolute distance between the ptrs is at least as big as the size of the buffer, + // they do not overlap. + diff >= size +} + /// Checks whether the regions of memory starting at `src` and `dst` of size /// `count * size_of::<T>()` do *not* overlap. #[inline] pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool { let src_usize = src.addr(); let dst_usize = dst.addr(); - let size = mem::size_of::<T>() - .checked_mul(count) - .expect("is_nonoverlapping: `size_of::<T>() * count` overflows a usize"); + let Some(size) = mem::size_of::<T>().checked_mul(count) else { + // Use panic_nounwind instead of Option::expect, so that this function is nounwind. + crate::panicking::panic_nounwind( + "is_nonoverlapping: `size_of::<T>() * count` overflows a usize", + ) + }; let diff = src_usize.abs_diff(dst_usize); // If the absolute distance between the ptrs is at least as big as the size of the buffer, // they do not overlap. @@ -2749,13 +2783,13 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) - #[doc(alias = "memcpy")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] +#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"] pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[rustc_nounwind] pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); } @@ -2766,10 +2800,16 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us assert_unsafe_precondition!( "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ and the specified memory ranges do not overlap", - [T](src: *const T, dst: *mut T, count: usize) => - is_aligned_and_not_null(src) - && is_aligned_and_not_null(dst) - && is_nonoverlapping(src, dst, count) + ( + src: *const () = src as *const (), + dst: *mut () = dst as *mut (), + size: usize = size_of::<T>(), + align: usize = align_of::<T>(), + count: usize = count, + ) => + is_aligned_and_not_null(src, align) + && is_aligned_and_not_null(dst, align) + && is_nonoverlapping_mono(src, dst, size, count) ); copy_nonoverlapping(src, dst, count) } @@ -2845,13 +2885,13 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us #[doc(alias = "memmove")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_allowed_through_unstable_modules] -#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] +#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_copy"] pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { extern "rust-intrinsic" { - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[rustc_nounwind] fn copy<T>(src: *const T, dst: *mut T, count: usize); } @@ -2859,9 +2899,15 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) { // SAFETY: the safety contract for `copy` must be upheld by the caller. unsafe { assert_unsafe_precondition!( - "ptr::copy requires that both pointer arguments are aligned and non-null", - [T](src: *const T, dst: *mut T) => - is_aligned_and_not_null(src) && is_aligned_and_not_null(dst) + "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ + and the specified memory ranges do not overlap", + ( + src: *const () = src as *const (), + dst: *mut () = dst as *mut (), + align: usize = align_of::<T>(), + ) => + is_aligned_and_not_null(src, align) + && is_aligned_and_not_null(dst, align) ); copy(src, dst, count) } @@ -2934,7 +2980,10 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) { unsafe { assert_unsafe_precondition!( "ptr::write_bytes requires that the destination pointer is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *const () = dst as *const (), + align: usize = align_of::<T>(), + ) => is_aligned_and_not_null(addr, align) ); write_bytes(dst, val, count) } diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index d348e31609d..02665b2676c 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -105,7 +105,6 @@ //! } //! //! #[custom_mir(dialect = "runtime", phase = "optimized")] -#![cfg_attr(bootstrap, doc = "#[cfg(any())]")] // disable the following function in doctests when `bootstrap` is set //! fn push_and_pop<T>(v: &mut Vec<T>, value: T) { //! mir!( //! let _unused; @@ -357,7 +356,6 @@ define!("mir_unwind_resume", define!("mir_storage_live", fn StorageLive<T>(local: T)); define!("mir_storage_dead", fn StorageDead<T>(local: T)); -#[cfg(not(bootstrap))] define!("mir_assume", fn Assume(operand: bool)); define!("mir_deinit", fn Deinit<T>(place: T)); define!("mir_checked", fn Checked<T>(binop: T) -> (T, bool)); diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a3279dcafef..b54680a61b4 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -111,7 +111,6 @@ // // Library features: // tidy-alphabetical-start -#![cfg_attr(not(bootstrap), feature(offset_of_nested))] #![feature(char_indices_offset)] #![feature(const_align_of_val)] #![feature(const_align_of_val_raw)] @@ -135,6 +134,7 @@ #![feature(const_hint_assert_unchecked)] #![feature(const_index_range_slice_index)] #![feature(const_int_unchecked_arith)] +#![feature(const_intrinsic_copy)] #![feature(const_intrinsic_forget)] #![feature(const_ipv4)] #![feature(const_ipv6)] @@ -180,6 +180,7 @@ #![feature(maybe_uninit_uninit_array)] #![feature(non_null_convenience)] #![feature(offset_of_enum)] +#![feature(offset_of_nested)] #![feature(panic_internals)] #![feature(ptr_alignment_type)] #![feature(ptr_metadata)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index d6e0e1895cd..2e22129d7b6 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -225,77 +225,6 @@ marker_impls! { {T: ?Sized} &T, } -/// Required trait for constants used in pattern matches. -/// -/// Any type that derives `Eq` automatically implements this trait, *regardless* -/// of whether its type parameters implement `Eq`. -/// -/// This is a hack to work around a limitation in our type system. -/// -/// # Background -/// -/// We want to require that types of consts used in pattern matches -/// have the attribute `#[derive(PartialEq, Eq)]`. -/// -/// In a more ideal world, we could check that requirement by just checking that -/// the given type implements both the `StructuralPartialEq` trait *and* -/// the `Eq` trait. However, you can have ADTs that *do* `derive(PartialEq, Eq)`, -/// and be a case that we want the compiler to accept, and yet the constant's -/// type fails to implement `Eq`. -/// -/// Namely, a case like this: -/// -/// ```rust -/// #[derive(PartialEq, Eq)] -/// struct Wrap<X>(X); -/// -/// fn higher_order(_: &()) { } -/// -/// const CFN: Wrap<fn(&())> = Wrap(higher_order); -/// -/// #[allow(pointer_structural_match)] -/// fn main() { -/// match CFN { -/// CFN => {} -/// _ => {} -/// } -/// } -/// ``` -/// -/// (The problem in the above code is that `Wrap<fn(&())>` does not implement -/// `PartialEq`, nor `Eq`, because `for<'a> fn(&'a _)` does not implement those -/// traits.) -/// -/// Therefore, we cannot rely on naive check for `StructuralPartialEq` and -/// mere `Eq`. -/// -/// As a hack to work around this, we use two separate traits injected by each -/// of the two derives (`#[derive(PartialEq)]` and `#[derive(Eq)]`) and check -/// that both of them are present as part of structural-match checking. -#[unstable(feature = "structural_match", issue = "31434")] -#[diagnostic::on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")] -#[lang = "structural_teq"] -#[cfg(bootstrap)] -pub trait StructuralEq { - // Empty. -} - -// FIXME: Remove special cases of these types from the compiler pattern checking code and always check `T: StructuralEq` instead -marker_impls! { - #[unstable(feature = "structural_match", issue = "31434")] - #[cfg(bootstrap)] - StructuralEq for - usize, u8, u16, u32, u64, u128, - isize, i8, i16, i32, i64, i128, - bool, - char, - str /* Technically requires `[u8]: StructuralEq` */, - (), - {T, const N: usize} [T; N], - {T} [T], - {T: ?Sized} &T, -} - /// Types whose values can be duplicated simply by copying bits. /// /// By default, variable bindings have 'move semantics.' In other @@ -860,10 +789,6 @@ impl<T: ?Sized> Default for PhantomData<T> { #[unstable(feature = "structural_match", issue = "31434")] impl<T: ?Sized> StructuralPartialEq for PhantomData<T> {} -#[unstable(feature = "structural_match", issue = "31434")] -#[cfg(bootstrap)] -impl<T: ?Sized> StructuralEq for PhantomData<T> {} - /// Compiler-internal trait used to indicate the type of enum discriminants. /// /// This trait is automatically implemented for every type and does not add any @@ -1041,22 +966,8 @@ pub trait PointerLike {} #[unstable(feature = "adt_const_params", issue = "95174")] #[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] #[allow(multiple_supertrait_upcastable)] -#[cfg(not(bootstrap))] pub trait ConstParamTy: StructuralPartialEq + Eq {} -/// A marker for types which can be used as types of `const` generic parameters. -/// -/// These types must have a proper equivalence relation (`Eq`) and it must be automatically -/// derived (`StructuralPartialEq`). There's a hard-coded check in the compiler ensuring -/// that all fields are also `ConstParamTy`, which implies that recursively, all fields -/// are `StructuralPartialEq`. -#[lang = "const_param_ty"] -#[unstable(feature = "adt_const_params", issue = "95174")] -#[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] -#[allow(multiple_supertrait_upcastable)] -#[cfg(bootstrap)] -pub trait ConstParamTy: StructuralEq + StructuralPartialEq + Eq {} - /// Derive macro generating an impl of the trait `ConstParamTy`. #[rustc_builtin_macro] #[unstable(feature = "adt_const_params", issue = "95174")] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 318a99e23ec..e247b9ed83d 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1393,19 +1393,9 @@ impl<T> SizedTypeProperties for T {} /// /// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); /// ``` -#[cfg(not(bootstrap))] -#[stable(feature = "offset_of", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "offset_of", since = "1.77.0")] #[allow_internal_unstable(builtin_syntax, hint_must_use)] pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { // The `{}` is for better error messages crate::hint::must_use({builtin # offset_of($Container, $($fields)+)}) } - -#[cfg(bootstrap)] -#[stable(feature = "offset_of", since = "CURRENT_RUSTC_VERSION")] -#[allow_internal_unstable(builtin_syntax, hint_must_use)] -#[allow(missing_docs)] -pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) { - // The `{}` is for better error messages - crate::hint::must_use({builtin # offset_of($Container, $($fields).+)}) -} diff --git a/library/core/src/net/mod.rs b/library/core/src/net/mod.rs index 5bae4d2f0c4..0786165fe9e 100644 --- a/library/core/src/net/mod.rs +++ b/library/core/src/net/mod.rs @@ -9,7 +9,7 @@ //! * [`SocketAddr`] represents socket addresses of either IPv4 or IPv6; [`SocketAddrV4`] //! and [`SocketAddrV6`] are respectively IPv4 and IPv6 socket addresses -#![stable(feature = "ip_in_core", since = "CURRENT_RUSTC_VERSION")] +#![stable(feature = "ip_in_core", since = "1.77.0")] #[stable(feature = "rust1", since = "1.0.0")] pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 1124719fc8d..288ad8e8d87 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -3,15 +3,13 @@ use crate::cmp::Ordering; use crate::fmt; use crate::hash::{Hash, Hasher}; -#[cfg(bootstrap)] -use crate::marker::StructuralEq; +use crate::intrinsics; use crate::marker::StructuralPartialEq; use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem}; use crate::str::FromStr; use super::from_str_radix; use super::{IntErrorKind, ParseIntError}; -use crate::intrinsics; mod private { #[unstable( @@ -35,7 +33,7 @@ mod private { pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {} macro_rules! impl_zeroable_primitive { - ($NonZero:ident ( $primitive:ty )) => { + ($primitive:ty) => { #[unstable( feature = "nonzero_internals", reason = "implementation detail which may disappear or be replaced at any time", @@ -52,18 +50,18 @@ macro_rules! impl_zeroable_primitive { }; } -impl_zeroable_primitive!(NonZeroU8(u8)); -impl_zeroable_primitive!(NonZeroU16(u16)); -impl_zeroable_primitive!(NonZeroU32(u32)); -impl_zeroable_primitive!(NonZeroU64(u64)); -impl_zeroable_primitive!(NonZeroU128(u128)); -impl_zeroable_primitive!(NonZeroUsize(usize)); -impl_zeroable_primitive!(NonZeroI8(i8)); -impl_zeroable_primitive!(NonZeroI16(i16)); -impl_zeroable_primitive!(NonZeroI32(i32)); -impl_zeroable_primitive!(NonZeroI64(i64)); -impl_zeroable_primitive!(NonZeroI128(i128)); -impl_zeroable_primitive!(NonZeroIsize(isize)); +impl_zeroable_primitive!(u8); +impl_zeroable_primitive!(u16); +impl_zeroable_primitive!(u32); +impl_zeroable_primitive!(u64); +impl_zeroable_primitive!(u128); +impl_zeroable_primitive!(usize); +impl_zeroable_primitive!(i8); +impl_zeroable_primitive!(i16); +impl_zeroable_primitive!(i32); +impl_zeroable_primitive!(i64); +impl_zeroable_primitive!(i128); +impl_zeroable_primitive!(isize); /// A value that is known not to equal zero. /// @@ -83,6 +81,87 @@ impl_zeroable_primitive!(NonZeroIsize(isize)); #[rustc_diagnostic_item = "NonZero"] pub struct NonZero<T: ZeroablePrimitive>(T); +impl<T> NonZero<T> +where + T: ZeroablePrimitive, +{ + /// Creates a non-zero if the given value is not zero. + #[stable(feature = "nonzero", since = "1.28.0")] + #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] + #[must_use] + #[inline] + pub const fn new(n: T) -> Option<Self> { + // SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has + // the same layout and size as `T`, with `0` representing `None`. + unsafe { intrinsics::transmute_unchecked(n) } + } + + /// Creates a non-zero without checking whether the value is non-zero. + /// This results in undefined behaviour if the value is zero. + /// + /// # Safety + /// + /// The value must not be zero. + #[stable(feature = "nonzero", since = "1.28.0")] + #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] + #[must_use] + #[inline] + pub const unsafe fn new_unchecked(n: T) -> Self { + match Self::new(n) { + Some(n) => n, + None => { + // SAFETY: The caller guarantees that `n` is non-zero, so this is unreachable. + unsafe { + intrinsics::assert_unsafe_precondition!( + "NonZero::new_unchecked requires the argument to be non-zero", + () => false, + ); + intrinsics::unreachable() + } + } + } + } + + /// Converts a reference to a non-zero mutable reference + /// if the referenced value is not zero. + #[unstable(feature = "nonzero_from_mut", issue = "106290")] + #[must_use] + #[inline] + pub fn from_mut(n: &mut T) -> Option<&mut Self> { + // SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has + // the same layout and size as `T`, with `0` representing `None`. + let opt_n = unsafe { &mut *(n as *mut T as *mut Option<Self>) }; + + opt_n.as_mut() + } + + /// Converts a mutable reference to a non-zero mutable reference + /// without checking whether the referenced value is non-zero. + /// This results in undefined behavior if the referenced value is zero. + /// + /// # Safety + /// + /// The referenced value must not be zero. + #[unstable(feature = "nonzero_from_mut", issue = "106290")] + #[must_use] + #[inline] + pub unsafe fn from_mut_unchecked(n: &mut T) -> &mut Self { + match Self::from_mut(n) { + Some(n) => n, + None => { + // SAFETY: The caller guarantees that `n` references a value that is non-zero, so this is unreachable. + unsafe { + intrinsics::assert_unsafe_precondition!( + "NonZero::from_mut_unchecked requires the argument to dereference as non-zero", + () => false, + ); + intrinsics::unreachable() + } + } + } + } +} + macro_rules! impl_nonzero_fmt { ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { $( @@ -100,7 +179,6 @@ macro_rules! impl_nonzero_fmt { macro_rules! nonzero_integer { ( #[$stability:meta] - #[$const_new_unchecked_stability:meta] Self = $Ty:ident, Primitive = $signedness:ident $Int:ident, $(UnsignedNonZero = $UnsignedNonZero:ident,)? @@ -143,74 +221,6 @@ macro_rules! nonzero_integer { pub type $Ty = NonZero<$Int>; impl $Ty { - /// Creates a non-zero without checking whether the value is non-zero. - /// This results in undefined behaviour if the value is zero. - /// - /// # Safety - /// - /// The value must not be zero. - #[$stability] - #[$const_new_unchecked_stability] - #[must_use] - #[inline] - pub const unsafe fn new_unchecked(n: $Int) -> Self { - crate::panic::debug_assert_nounwind!( - n != 0, - concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument") - ); - // SAFETY: this is guaranteed to be safe by the caller. - unsafe { - Self(n) - } - } - - /// Creates a non-zero if the given value is not zero. - #[$stability] - #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] - #[must_use] - #[inline] - pub const fn new(n: $Int) -> Option<Self> { - if n != 0 { - // SAFETY: we just checked that there's no `0` - Some(unsafe { Self(n) }) - } else { - None - } - } - - /// Converts a primitive mutable reference to a non-zero mutable reference - /// without checking whether the referenced value is non-zero. - /// This results in undefined behavior if `*n` is zero. - /// - /// # Safety - /// The referenced value must not be currently zero. - #[unstable(feature = "nonzero_from_mut", issue = "106290")] - #[must_use] - #[inline] - pub unsafe fn from_mut_unchecked(n: &mut $Int) -> &mut Self { - // SAFETY: Self is repr(transparent), and the value is assumed to be non-zero. - unsafe { - let n_alias = &mut *n; - core::intrinsics::assert_unsafe_precondition!( - concat!(stringify!($Ty), "::from_mut_unchecked requires the argument to dereference as non-zero"), - (n_alias: &mut $Int) => *n_alias != 0 - ); - &mut *(n as *mut $Int as *mut Self) - } - } - - /// Converts a primitive mutable reference to a non-zero mutable reference - /// if the referenced integer is not zero. - #[unstable(feature = "nonzero_from_mut", issue = "106290")] - #[must_use] - #[inline] - pub fn from_mut(n: &mut $Int) -> Option<&mut Self> { - // SAFETY: Self is repr(transparent), and the value is non-zero. - // As long as the returned reference is alive, - // the user cannot `*n = 0` directly. - (*n != 0).then(|| unsafe { &mut *(n as *mut $Int as *mut Self) }) - } - /// Returns the value as a primitive type. #[$stability] #[inline] @@ -569,10 +579,6 @@ macro_rules! nonzero_integer { #[$stability] impl Eq for $Ty {} - #[unstable(feature = "structural_match", issue = "31434")] - #[cfg(bootstrap)] - impl StructuralEq for $Ty {} - #[$stability] impl PartialOrd for $Ty { #[inline] @@ -724,7 +730,6 @@ macro_rules! nonzero_integer { (Self = $Ty:ident, Primitive = unsigned $Int:ident $(,)?) => { nonzero_integer! { #[stable(feature = "nonzero", since = "1.28.0")] - #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] Self = $Ty, Primitive = unsigned $Int, UnsignedPrimitive = $Int, @@ -735,7 +740,6 @@ macro_rules! nonzero_integer { (Self = $Ty:ident, Primitive = signed $Int:ident, $($rest:tt)*) => { nonzero_integer! { #[stable(feature = "signed_nonzero", since = "1.34.0")] - #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] Self = $Ty, Primitive = signed $Int, $($rest)* @@ -757,7 +761,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls { fn div(self, other: $Ty) -> $Int { // SAFETY: div by zero is checked because `other` is a nonzero, // and MIN/-1 is checked because `self` is an unsigned int. - unsafe { crate::intrinsics::unchecked_div(self, other.get()) } + unsafe { intrinsics::unchecked_div(self, other.get()) } } } @@ -770,7 +774,7 @@ macro_rules! nonzero_integer_signedness_dependent_impls { fn rem(self, other: $Ty) -> $Int { // SAFETY: rem by zero is checked because `other` is a nonzero, // and MIN/-1 is checked because `self` is an unsigned int. - unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } + unsafe { intrinsics::unchecked_rem(self, other.get()) } } } }; diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index bb3cdde66d1..fd50f804748 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -73,6 +73,7 @@ append_const_msg )] #[doc(alias = "+")] +#[const_trait] pub trait Add<Rhs = Self> { /// The resulting type after applying the `+` operator. #[stable(feature = "rust1", since = "1.0.0")] @@ -94,7 +95,8 @@ pub trait Add<Rhs = Self> { macro_rules! add_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl Add for $t { + #[rustc_const_unstable(feature = "const_ops", issue = "90080")] + impl const Add for $t { type Output = $t; #[inline] diff --git a/library/core/src/ops/async_function.rs b/library/core/src/ops/async_function.rs index 19b1220f05e..d6b06ffb7fc 100644 --- a/library/core/src/ops/async_function.rs +++ b/library/core/src/ops/async_function.rs @@ -8,7 +8,7 @@ use crate::marker::Tuple; #[rustc_paren_sugar] #[fundamental] #[must_use = "async closures are lazy and do nothing unless called"] -#[cfg_attr(not(bootstrap), lang = "async_fn")] +#[lang = "async_fn"] pub trait AsyncFn<Args: Tuple>: AsyncFnMut<Args> { /// Future returned by [`AsyncFn::async_call`]. #[unstable(feature = "async_fn_traits", issue = "none")] @@ -28,7 +28,7 @@ pub trait AsyncFn<Args: Tuple>: AsyncFnMut<Args> { #[rustc_paren_sugar] #[fundamental] #[must_use = "async closures are lazy and do nothing unless called"] -#[cfg_attr(not(bootstrap), lang = "async_fn_mut")] +#[lang = "async_fn_mut"] pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> { /// Future returned by [`AsyncFnMut::async_call_mut`]. #[unstable(feature = "async_fn_traits", issue = "none")] @@ -48,7 +48,7 @@ pub trait AsyncFnMut<Args: Tuple>: AsyncFnOnce<Args> { #[rustc_paren_sugar] #[fundamental] #[must_use = "async closures are lazy and do nothing unless called"] -#[cfg_attr(not(bootstrap), lang = "async_fn_once")] +#[lang = "async_fn_once"] pub trait AsyncFnOnce<Args: Tuple> { /// Future returned by [`AsyncFnOnce::async_call_once`]. #[unstable(feature = "async_fn_traits", issue = "none")] diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs index 6faded76a4a..6e067f95da9 100644 --- a/library/core/src/ops/coroutine.rs +++ b/library/core/src/ops/coroutine.rs @@ -111,7 +111,7 @@ pub trait Coroutine<R = ()> { /// been returned previously. While coroutine literals in the language are /// guaranteed to panic on resuming after `Complete`, this is not guaranteed /// for all implementations of the `Coroutine` trait. - #[cfg_attr(not(bootstrap), lang = "coroutine_resume")] + #[lang = "coroutine_resume"] fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return>; } diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs index e809273c9ed..727a22e454d 100644 --- a/library/core/src/ops/range.rs +++ b/library/core/src/ops/range.rs @@ -726,7 +726,7 @@ impl<T> Bound<T> { /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded); /// ``` #[inline] - #[stable(feature = "bound_map", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "bound_map", since = "1.77.0")] pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Bound<U> { match self { Unbounded => Unbounded, diff --git a/library/core/src/option.rs b/library/core/src/option.rs index c94e7d73a2a..d4c40c49934 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1033,7 +1033,6 @@ impl<T> Option<T> { #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] pub const unsafe fn unwrap_unchecked(self) -> T { - debug_assert!(self.is_some()); match self { Some(val) => val, // SAFETY: the safety contract must be upheld by the caller. @@ -1074,18 +1073,23 @@ impl<T> Option<T> { } } - /// Calls the provided closure with a reference to the contained value (if [`Some`]). + /// Calls a function with a reference to the contained value if [`Some`]. + /// + /// Returns the original option. /// /// # Examples /// /// ``` - /// let v = vec![1, 2, 3, 4, 5]; + /// let list = vec![1, 2, 3]; /// - /// // prints "got: 4" - /// let x: Option<&usize> = v.get(3).inspect(|x| println!("got: {x}")); + /// // prints "got: 2" + /// let x = list + /// .get(1) + /// .inspect(|x| println!("got: {x}")) + /// .expect("list should be long enough"); /// /// // prints nothing - /// let x: Option<&usize> = v.get(5).inspect(|x| println!("got: {x}")); + /// list.get(5).inspect(|x| println!("got: {x}")); /// ``` #[inline] #[stable(feature = "result_option_inspect", since = "1.76.0")] @@ -2155,7 +2159,6 @@ impl<T: PartialEq> PartialEq for Option<T> { /// /// Once that's fixed, `Option` should go back to deriving `PartialEq`, as /// it used to do before <https://github.com/rust-lang/rust/pull/103556>. -/// The comment regarding this trait on the `newtype_index` macro should be removed if this is done. #[unstable(feature = "spec_option_partial_eq", issue = "none", reason = "exposed only for rustc")] #[doc(hidden)] pub trait SpecOptionPartialEq: Sized { diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index bf47d767a92..85595b059ad 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -448,22 +448,6 @@ mod prim_unit {} #[doc(hidden)] impl () {} -// Fake impl that's only really used for docs. -#[cfg(doc)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for () { - fn clone(&self) -> Self { - loop {} - } -} - -// Fake impl that's only really used for docs. -#[cfg(doc)] -#[stable(feature = "rust1", since = "1.0.0")] -impl Copy for () { - // empty -} - #[rustc_doc_primitive = "pointer"] #[doc(alias = "ptr")] #[doc(alias = "*")] @@ -1690,23 +1674,3 @@ mod prim_fn {} // See src/librustdoc/passes/collect_trait_impls.rs:collect_trait_impls #[doc(hidden)] impl<Ret, T> fn(T) -> Ret {} - -// Fake impl that's only really used for docs. -#[cfg(doc)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(fake_variadic)] -/// This trait is implemented on function pointers with any number of arguments. -impl<Ret, T> Clone for fn(T) -> Ret { - fn clone(&self) -> Self { - loop {} - } -} - -// Fake impl that's only really used for docs. -#[cfg(doc)] -#[stable(feature = "rust1", since = "1.0.0")] -#[doc(fake_variadic)] -/// This trait is implemented on function pointers with any number of arguments. -impl<Ret, T> Copy for fn(T) -> Ret { - // empty -} diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index f3ceadee24c..c5e3df07a1c 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -806,13 +806,15 @@ impl<T: ?Sized> *const T { where T: Sized, { - let this = self; // SAFETY: The comparison has no side-effects, and the intrinsic // does this check internally in the CTFE implementation. unsafe { assert_unsafe_precondition!( - "ptr::sub_ptr requires `this >= origin`", - [T](this: *const T, origin: *const T) => this >= origin + "ptr::sub_ptr requires `self >= origin`", + ( + this: *const () = self as *const (), + origin: *const () = origin as *const (), + ) => this >= origin ) }; @@ -1284,7 +1286,7 @@ impl<T: ?Sized> *const T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1304,7 +1306,7 @@ impl<T: ?Sized> *const T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index dce7e035fc7..0fb9017e6d9 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -381,11 +381,11 @@ use crate::cmp::Ordering; use crate::fmt; use crate::hash; use crate::intrinsics::{ - self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping, + self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping_mono, }; use crate::marker::FnPtr; -use crate::mem::{self, MaybeUninit}; +use crate::mem::{self, align_of, size_of, MaybeUninit}; mod alignment; #[unstable(feature = "ptr_alignment_type", issue = "102070")] @@ -967,10 +967,16 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) { assert_unsafe_precondition!( "ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null \ and the specified memory ranges do not overlap", - [T](x: *mut T, y: *mut T, count: usize) => - is_aligned_and_not_null(x) - && is_aligned_and_not_null(y) - && is_nonoverlapping(x, y, count) + ( + x: *mut () = x as *mut (), + y: *mut () = y as *mut (), + size: usize = size_of::<T>(), + align: usize = align_of::<T>(), + count: usize = count, + ) => + is_aligned_and_not_null(x, align) + && is_aligned_and_not_null(y, align) + && is_nonoverlapping_mono(x, y, size, count) ); } @@ -1061,7 +1067,10 @@ pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T { unsafe { assert_unsafe_precondition!( "ptr::replace requires that the pointer argument is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *const () = dst as *const (), + align: usize = align_of::<T>(), + ) => is_aligned_and_not_null(addr, align) ); mem::swap(&mut *dst, &mut src); // cannot overlap } @@ -1176,7 +1185,6 @@ pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] -#[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_read"] pub const unsafe fn read<T>(src: *const T) -> T { @@ -1208,9 +1216,13 @@ pub const unsafe fn read<T>(src: *const T) -> T { // SAFETY: the caller must guarantee that `src` is valid for reads. unsafe { + #[cfg(debug_assertions)] // Too expensive to always enable (for now?) assert_unsafe_precondition!( "ptr::read requires that the pointer argument is aligned and non-null", - [T](src: *const T) => is_aligned_and_not_null(src) + ( + addr: *const () = src as *const (), + align: usize = align_of::<T>(), + ) => is_aligned_and_not_null(addr, align) ); crate::intrinsics::read_via_copy(src) } @@ -1294,7 +1306,11 @@ pub const unsafe fn read<T>(src: *const T) -> T { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")] -#[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)] +#[rustc_allow_const_fn_unstable( + const_mut_refs, + const_maybe_uninit_as_mut_ptr, + const_intrinsic_copy +)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[rustc_diagnostic_item = "ptr_read_unaligned"] pub const unsafe fn read_unaligned<T>(src: *const T) -> T { @@ -1408,9 +1424,13 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) { // `dst` cannot overlap `src` because the caller has mutable access // to `dst` while `src` is owned by this function. unsafe { + #[cfg(debug_assertions)] // Too expensive to always enable (for now?) assert_unsafe_precondition!( "ptr::write requires that the pointer argument is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *mut () = dst as *mut (), + align: usize = align_of::<T>(), + ) => is_aligned_and_not_null(addr, align) ); intrinsics::write_via_move(dst, src) } @@ -1578,7 +1598,10 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T { unsafe { assert_unsafe_precondition!( "ptr::read_volatile requires that the pointer argument is aligned and non-null", - [T](src: *const T) => is_aligned_and_not_null(src) + ( + addr: *const () = src as *const (), + align: usize = align_of::<T>(), + ) => is_aligned_and_not_null(addr, align) ); intrinsics::volatile_load(src) } @@ -1653,7 +1676,10 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) { unsafe { assert_unsafe_precondition!( "ptr::write_volatile requires that the pointer argument is aligned and non-null", - [T](dst: *mut T) => is_aligned_and_not_null(dst) + ( + addr: *mut () = dst as *mut (), + align: usize = align_of::<T>(), + ) => is_aligned_and_not_null(addr, align) ); intrinsics::volatile_store(dst, src); } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 3e47c4f440a..376673d67c1 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1385,7 +1385,7 @@ impl<T: ?Sized> *mut T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1405,7 +1405,7 @@ impl<T: ?Sized> *mut T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1425,7 +1425,7 @@ impl<T: ?Sized> *mut T { /// See [`ptr::copy`] for safety concerns and examples. /// /// [`ptr::copy`]: crate::ptr::copy() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces @@ -1445,7 +1445,7 @@ impl<T: ?Sized> *mut T { /// See [`ptr::copy_nonoverlapping`] for safety concerns and examples. /// /// [`ptr::copy_nonoverlapping`]: crate::ptr::copy_nonoverlapping() - #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")] + #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")] #[stable(feature = "pointer_methods", since = "1.26.0")] #[inline(always)] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d18082c3048..320cd5eb3b2 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -218,7 +218,10 @@ impl<T: ?Sized> NonNull<T> { pub const unsafe fn new_unchecked(ptr: *mut T) -> Self { // SAFETY: the caller must guarantee that `ptr` is non-null. unsafe { - assert_unsafe_precondition!("NonNull::new_unchecked requires that the pointer is non-null", [T: ?Sized](ptr: *mut T) => !ptr.is_null()); + assert_unsafe_precondition!( + "NonNull::new_unchecked requires that the pointer is non-null", + (ptr: *mut () = ptr as *mut ()) => !ptr.is_null() + ); NonNull { pointer: ptr as _ } } } @@ -470,7 +473,7 @@ impl<T: ?Sized> NonNull<T> { #[inline] pub const fn cast<U>(self) -> NonNull<U> { // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null - unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) } + unsafe { NonNull { pointer: self.as_ptr() as *mut U } } } /// Calculates the offset from a pointer. @@ -1588,8 +1591,7 @@ impl<T> NonNull<[T]> { #[unstable(feature = "slice_ptr_get", issue = "74265")] #[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")] pub const fn as_non_null_ptr(self) -> NonNull<T> { - // SAFETY: We know `self` is non-null. - unsafe { NonNull::new_unchecked(self.as_ptr().as_mut_ptr()) } + self.cast() } /// Returns a raw pointer to the slice's buffer. @@ -1825,9 +1827,7 @@ impl<T: ?Sized> hash::Hash for NonNull<T> { impl<T: ?Sized> From<Unique<T>> for NonNull<T> { #[inline] fn from(unique: Unique<T>) -> Self { - // SAFETY: A Unique pointer cannot be null, so the conditions for - // new_unchecked() are respected. - unsafe { NonNull::new_unchecked(unique.as_ptr()) } + unique.as_non_null_ptr() } } @@ -1850,8 +1850,7 @@ impl<T: ?Sized> From<&T> for NonNull<T> { /// 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 - // new_unchecked() are respected. + // SAFETY: A reference cannot be null. unsafe { NonNull { pointer: reference as *const T } } } } diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index 067f1541e31..b74d691e454 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -106,6 +106,13 @@ impl<T: ?Sized> Unique<T> { self.pointer.as_ptr() } + /// Acquires the underlying `*mut` pointer. + #[must_use = "`self` will be dropped if the result is not used"] + #[inline] + pub const fn as_non_null_ptr(self) -> NonNull<T> { + self.pointer + } + /// Dereferences the content. /// /// The resulting lifetime is bound to self so this behaves "as if" @@ -138,7 +145,7 @@ impl<T: ?Sized> Unique<T> { pub const fn cast<U>(self) -> Unique<U> { // FIXME(const-hack): replace with `From` // SAFETY: is `NonNull` - unsafe { Unique::new_unchecked(self.pointer.cast().as_ptr()) } + Unique { pointer: self.pointer.cast(), _marker: PhantomData } } } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 1f448984e53..80f7fe75e82 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -830,7 +830,9 @@ impl<T, E> Result<T, E> { } } - /// Calls the provided closure with a reference to the contained value (if [`Ok`]). + /// Calls a function with a reference to the contained value if [`Ok`]. + /// + /// Returns the original result. /// /// # Examples /// @@ -851,7 +853,9 @@ impl<T, E> Result<T, E> { self } - /// Calls the provided closure with a reference to the contained error (if [`Err`]). + /// Calls a function with a reference to the contained value if [`Err`]. + /// + /// Returns the original result. /// /// # Examples /// diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 2d4c7e78aea..1429313c890 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -87,12 +87,13 @@ unsafe impl<T: Sync> Send for Iter<'_, T> {} impl<'a, T> Iter<'a, T> { #[inline] pub(super) fn new(slice: &'a [T]) -> Self { - let ptr = slice.as_ptr(); + let len = slice.len(); + let ptr: NonNull<T> = NonNull::from(slice).cast(); // SAFETY: Similar to `IterMut::new`. unsafe { - let end_or_len = if T::IS_ZST { invalid(slice.len()) } else { ptr.add(slice.len()) }; + let end_or_len = if T::IS_ZST { invalid(len) } else { ptr.as_ptr().add(len) }; - Self { ptr: NonNull::new_unchecked(ptr as *mut T), end_or_len, _marker: PhantomData } + Self { ptr, end_or_len, _marker: PhantomData } } } @@ -208,7 +209,8 @@ unsafe impl<T: Send> Send for IterMut<'_, T> {} impl<'a, T> IterMut<'a, T> { #[inline] pub(super) fn new(slice: &'a mut [T]) -> Self { - let ptr = slice.as_mut_ptr(); + let len = slice.len(); + let ptr: NonNull<T> = NonNull::from(slice).cast(); // SAFETY: There are several things here: // // `ptr` has been obtained by `slice.as_ptr()` where `slice` is a valid @@ -226,10 +228,9 @@ impl<'a, T> IterMut<'a, T> { // See the `next_unchecked!` and `is_empty!` macros as well as the // `post_inc_start` method for more information. unsafe { - let end_or_len = - if T::IS_ZST { invalid_mut(slice.len()) } else { ptr.add(slice.len()) }; + let end_or_len = if T::IS_ZST { invalid_mut(len) } else { ptr.as_ptr().add(len) }; - Self { ptr: NonNull::new_unchecked(ptr), end_or_len, _marker: PhantomData } + Self { ptr, end_or_len, _marker: PhantomData } } } @@ -3252,21 +3253,21 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for IterMut<'a, T> { /// /// [`chunk_by`]: slice::chunk_by /// [slices]: slice -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ChunkBy<'a, T: 'a, P> { slice: &'a [T], predicate: P, } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> ChunkBy<'a, T, P> { pub(super) fn new(slice: &'a [T], predicate: P) -> Self { ChunkBy { slice, predicate } } } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> Iterator for ChunkBy<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3300,7 +3301,7 @@ where } } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> DoubleEndedIterator for ChunkBy<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3322,10 +3323,10 @@ where } } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> FusedIterator for ChunkBy<'a, T, P> where P: FnMut(&T, &T) -> bool {} -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkBy<'a, T, P> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ChunkBy").field("slice", &self.slice).finish() @@ -3339,21 +3340,21 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkBy<'a, T, P> { /// /// [`chunk_by_mut`]: slice::chunk_by_mut /// [slices]: slice -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] #[must_use = "iterators are lazy and do nothing unless consumed"] pub struct ChunkByMut<'a, T: 'a, P> { slice: &'a mut [T], predicate: P, } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> ChunkByMut<'a, T, P> { pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self { ChunkByMut { slice, predicate } } } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> Iterator for ChunkByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3388,7 +3389,7 @@ where } } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> DoubleEndedIterator for ChunkByMut<'a, T, P> where P: FnMut(&T, &T) -> bool, @@ -3411,10 +3412,10 @@ where } } -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a, P> FusedIterator for ChunkByMut<'a, T, P> where P: FnMut(&T, &T) -> bool {} -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkByMut<'a, T, P> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ChunkByMut").field("slice", &self.slice).finish() diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 4ed22ede03a..73e92ed1dad 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -68,7 +68,7 @@ pub use iter::{ArrayChunks, ArrayChunksMut}; #[unstable(feature = "array_windows", issue = "75027")] pub use iter::ArrayWindows; -#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "slice_group_by", since = "1.77.0")] pub use iter::{ChunkBy, ChunkByMut}; #[stable(feature = "split_inclusive", since = "1.51.0")] @@ -334,8 +334,8 @@ impl<T> [T] { /// assert_eq!(Some(&[]), w.first_chunk::<0>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] pub const fn first_chunk<const N: usize>(&self) -> Option<&[T; N]> { if self.len() < N { None @@ -364,7 +364,7 @@ impl<T> [T] { /// assert_eq!(None, x.first_chunk_mut::<4>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn first_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> { if self.len() < N { @@ -394,8 +394,8 @@ impl<T> [T] { /// assert_eq!(None, x.split_first_chunk::<4>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] pub const fn split_first_chunk<const N: usize>(&self) -> Option<(&[T; N], &[T])> { if self.len() < N { None @@ -429,7 +429,7 @@ impl<T> [T] { /// assert_eq!(None, x.split_first_chunk_mut::<4>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn split_first_chunk_mut<const N: usize>( &mut self, @@ -464,8 +464,8 @@ impl<T> [T] { /// assert_eq!(None, x.split_last_chunk::<4>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] + #[rustc_const_stable(feature = "slice_first_last_chunk", since = "1.77.0")] pub const fn split_last_chunk<const N: usize>(&self) -> Option<(&[T], &[T; N])> { if self.len() < N { None @@ -499,7 +499,7 @@ impl<T> [T] { /// assert_eq!(None, x.split_last_chunk_mut::<4>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn split_last_chunk_mut<const N: usize>( &mut self, @@ -534,7 +534,7 @@ impl<T> [T] { /// assert_eq!(Some(&[]), w.last_chunk::<0>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn last_chunk<const N: usize>(&self) -> Option<&[T; N]> { if self.len() < N { @@ -568,7 +568,7 @@ impl<T> [T] { /// assert_eq!(None, x.last_chunk_mut::<4>()); /// ``` #[inline] - #[stable(feature = "slice_first_last_chunk", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_first_last_chunk", since = "1.77.0")] #[rustc_const_unstable(feature = "const_slice_first_last_chunk", issue = "111774")] pub const fn last_chunk_mut<const N: usize>(&mut self) -> Option<&mut [T; N]> { if self.len() < N { @@ -1777,7 +1777,7 @@ impl<T> [T] { /// assert_eq!(iter.next(), Some(&[2, 3, 4][..])); /// assert_eq!(iter.next(), None); /// ``` - #[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_group_by", since = "1.77.0")] #[inline] pub fn chunk_by<F>(&self, pred: F) -> ChunkBy<'_, T, F> where @@ -1818,7 +1818,7 @@ impl<T> [T] { /// assert_eq!(iter.next(), Some(&mut [2, 3, 4][..])); /// assert_eq!(iter.next(), None); /// ``` - #[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "slice_group_by", since = "1.77.0")] #[inline] pub fn chunk_by_mut<F>(&mut self, pred: F) -> ChunkByMut<'_, T, F> where @@ -1951,10 +1951,7 @@ impl<T> [T] { /// } /// ``` #[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")] - #[rustc_const_stable( - feature = "const_slice_split_at_unchecked", - since = "CURRENT_RUSTC_VERSION" - )] + #[rustc_const_stable(feature = "const_slice_split_at_unchecked", since = "1.77.0")] #[inline] #[must_use] pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 9cdf9b68afb..571abc3e999 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -4,6 +4,7 @@ use crate::array; use crate::intrinsics::{ assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size, }; +use crate::mem::{align_of, size_of}; use crate::ops::Range; use crate::ptr; @@ -96,8 +97,14 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] unsafe { assert_unsafe_precondition!( "slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", - [T](data: *const T, len: usize) => is_aligned_and_not_null(data) - && is_valid_allocation_size::<T>(len) + ( + data: *mut () = data as *mut (), + size: usize = size_of::<T>(), + align: usize = align_of::<T>(), + len: usize = len, + ) => + is_aligned_and_not_null(data, align) + && is_valid_allocation_size(size, len) ); &*ptr::slice_from_raw_parts(data, len) } @@ -143,8 +150,14 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m unsafe { assert_unsafe_precondition!( "slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`", - [T](data: *mut T, len: usize) => is_aligned_and_not_null(data) - && is_valid_allocation_size::<T>(len) + ( + data: *mut () = data as *mut (), + size: usize = size_of::<T>(), + align: usize = align_of::<T>(), + len: usize = len, + ) => + is_aligned_and_not_null(data, align) + && is_valid_allocation_size(size, len) ); &mut *ptr::slice_from_raw_parts_mut(data, len) } diff --git a/library/core/src/time.rs b/library/core/src/time.rs index b677776443f..e4f29942966 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -197,13 +197,18 @@ impl Duration { #[must_use] #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] pub const fn new(secs: u64, nanos: u32) -> Duration { - let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { - Some(secs) => secs, - None => panic!("overflow in Duration::new"), - }; - let nanos = nanos % NANOS_PER_SEC; - // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range - Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + if nanos < NANOS_PER_SEC { + // SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range + Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + } else { + let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { + Some(secs) => secs, + None => panic!("overflow in Duration::new"), + }; + let nanos = nanos % NANOS_PER_SEC; + // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range + Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } + } } /// Creates a new `Duration` from the specified number of whole seconds. diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs index 47e27bdc735..44fac589d4c 100644 --- a/library/core/src/tuple.rs +++ b/library/core/src/tuple.rs @@ -63,14 +63,6 @@ macro_rules! tuple_impls { maybe_tuple_doc! { $($T)+ @ - #[unstable(feature = "structural_match", issue = "31434")] - #[cfg(bootstrap)] - impl<$($T),+> crate::marker::StructuralEq for ($($T,)+) - {} - } - - maybe_tuple_doc! { - $($T)+ @ #[stable(feature = "rust1", since = "1.0.0")] impl<$($T: PartialOrd),+> PartialOrd for ($($T,)+) where diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 9a3b477c2d1..6deebc0d263 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -14,6 +14,7 @@ #![feature(const_cell_into_inner)] #![feature(const_hash)] #![feature(const_heap)] +#![feature(const_intrinsic_copy)] #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_nonnull_new)] #![feature(const_pointer_is_aligned)] @@ -58,7 +59,7 @@ #![feature(noop_waker)] #![feature(numfmt)] #![feature(num_midpoint)] -#![cfg_attr(not(bootstrap), feature(offset_of_nested))] +#![feature(offset_of_nested)] #![feature(isqrt)] #![feature(step_trait)] #![feature(str_internals)] @@ -111,7 +112,7 @@ #![feature(slice_flatten)] #![feature(error_generic_member_access)] #![feature(error_in_core)] -#![cfg_attr(not(bootstrap), feature(trait_upcasting))] +#![feature(trait_upcasting)] #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] #![feature(get_many_mut)] diff --git a/library/core/tests/macros.rs b/library/core/tests/macros.rs index eb886def164..09994fbcbdb 100644 --- a/library/core/tests/macros.rs +++ b/library/core/tests/macros.rs @@ -1,3 +1,4 @@ +#[allow(dead_code)] trait Trait { fn blah(&self); } diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index ccae406cc28..d3ba546d730 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -262,7 +262,7 @@ cfg_if::cfg_if! { } // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[cfg_attr(not(bootstrap), allow(static_mut_ref))] +#[allow(static_mut_ref)] pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { use core::intrinsics::atomic_store_seqcst; @@ -325,7 +325,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { } // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[cfg_attr(not(bootstrap), allow(static_mut_ref))] +#[allow(static_mut_ref)] pub unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send> { // A null payload here means that we got here from the catch (...) of // __rust_try. This happens when a non-Rust foreign exception is caught. diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs index 52a08cad911..9255c3abc8a 100644 --- a/library/proc_macro/src/bridge/client.rs +++ b/library/proc_macro/src/bridge/client.rs @@ -3,6 +3,7 @@ use super::*; use std::marker::PhantomData; +use std::sync::atomic::AtomicU32; macro_rules! define_handles { ( @@ -12,8 +13,8 @@ macro_rules! define_handles { #[repr(C)] #[allow(non_snake_case)] pub struct HandleCounters { - $($oty: AtomicUsize,)* - $($ity: AtomicUsize,)* + $($oty: AtomicU32,)* + $($ity: AtomicU32,)* } impl HandleCounters { @@ -21,8 +22,8 @@ macro_rules! define_handles { // a wrapper `fn` pointer, once `const fn` can reference `static`s. extern "C" fn get() -> &'static Self { static COUNTERS: HandleCounters = HandleCounters { - $($oty: AtomicUsize::new(1),)* - $($ity: AtomicUsize::new(1),)* + $($oty: AtomicU32::new(1),)* + $($ity: AtomicU32::new(1),)* }; &COUNTERS } diff --git a/library/proc_macro/src/bridge/handle.rs b/library/proc_macro/src/bridge/handle.rs index 00954107b77..b3a76306997 100644 --- a/library/proc_macro/src/bridge/handle.rs +++ b/library/proc_macro/src/bridge/handle.rs @@ -4,7 +4,7 @@ use std::collections::BTreeMap; use std::hash::Hash; use std::num::NonZeroU32; use std::ops::{Index, IndexMut}; -use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::atomic::{AtomicU32, Ordering}; use super::fxhash::FxHashMap; @@ -13,12 +13,12 @@ pub(super) type Handle = NonZeroU32; /// A store that associates values of type `T` with numeric handles. A value can /// be looked up using its handle. pub(super) struct OwnedStore<T: 'static> { - counter: &'static AtomicUsize, + counter: &'static AtomicU32, data: BTreeMap<Handle, T>, } impl<T> OwnedStore<T> { - pub(super) fn new(counter: &'static AtomicUsize) -> Self { + pub(super) fn new(counter: &'static AtomicU32) -> Self { // Ensure the handle counter isn't 0, which would panic later, // when `NonZeroU32::new` (aka `Handle::new`) is called in `alloc`. assert_ne!(counter.load(Ordering::SeqCst), 0); @@ -30,7 +30,7 @@ impl<T> OwnedStore<T> { impl<T> OwnedStore<T> { pub(super) fn alloc(&mut self, x: T) -> Handle { let counter = self.counter.fetch_add(1, Ordering::SeqCst); - let handle = Handle::new(counter as u32).expect("`proc_macro` handle counter overflowed"); + let handle = Handle::new(counter).expect("`proc_macro` handle counter overflowed"); assert!(self.data.insert(handle, x).is_none()); handle } @@ -60,7 +60,7 @@ pub(super) struct InternedStore<T: 'static> { } impl<T: Copy + Eq + Hash> InternedStore<T> { - pub(super) fn new(counter: &'static AtomicUsize) -> Self { + pub(super) fn new(counter: &'static AtomicU32) -> Self { InternedStore { owned: OwnedStore::new(counter), interner: FxHashMap::default() } } diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 75bf3329786..55e24b6491c 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -16,7 +16,6 @@ use std::mem; use std::ops::Bound; use std::ops::Range; use std::panic; -use std::sync::atomic::AtomicUsize; use std::sync::Once; use std::thread; diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 1b38ba72114..b60d7a72411 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -114,7 +114,7 @@ impl f32 { /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] - #[stable(feature = "round_ties_even", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "round_ties_even", since = "1.77.0")] #[inline] pub fn round_ties_even(self) -> f32 { unsafe { intrinsics::rintf32(self) } diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index f8fc84440ae..88f992b3957 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -114,7 +114,7 @@ impl f64 { /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] - #[stable(feature = "round_ties_even", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "round_ties_even", since = "1.77.0")] #[inline] pub fn round_ties_even(self) -> f64 { unsafe { intrinsics::rintf64(self) } diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 80d369eb067..3383a8cfa41 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -428,7 +428,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_create_new", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "file_create_new", since = "1.77.0")] pub fn create_new<P: AsRef<Path>>(path: P) -> io::Result<File> { OpenOptions::new().read(true).write(true).create_new(true).open(path.as_ref()) } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f98654e4d18..571e475c336 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -266,12 +266,12 @@ // // Language features: // tidy-alphabetical-start -#![cfg_attr(not(bootstrap), feature(cfg_sanitizer_cfi))] #![feature(alloc_error_handler)] #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] #![feature(c_unwind)] +#![feature(cfg_sanitizer_cfi)] #![feature(cfg_target_thread_local)] #![feature(cfi_encoding)] #![feature(concat_idents)] diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index c80f15d8a61..8294160b72c 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -338,7 +338,7 @@ pub mod panic_count { #[cfg(not(feature = "panic_immediate_abort"))] #[unstable(feature = "update_panic_count", issue = "none")] // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[cfg_attr(not(bootstrap), allow(static_mut_ref))] +#[allow(static_mut_ref)] pub mod panic_count { use crate::cell::Cell; use crate::sync::atomic::{AtomicUsize, Ordering}; diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index 184c406e326..920143b7ac7 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -404,7 +404,7 @@ impl<T: ?Sized> Mutex<T> { /// assert_eq!(*x, 1); /// ``` #[inline] - #[stable(feature = "mutex_unpoison", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "mutex_unpoison", since = "1.77.0")] pub fn clear_poison(&self) { self.poison.clear(); } diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 23d3dd0707a..c5d846b85aa 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -408,7 +408,7 @@ impl<T: ?Sized> RwLock<T> { /// assert_eq!(*guard, 1); /// ``` #[inline] - #[stable(feature = "mutex_unpoison", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "mutex_unpoison", since = "1.77.0")] pub fn clear_poison(&self) { self.poison.clear(); } diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index e03e98b18d2..fae21636897 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -7,6 +7,7 @@ mod personality; pub mod cmath; pub mod os_str; +pub mod path; // FIXME(117276): remove this, move feature implementations into individual // submodules. diff --git a/library/std/src/sys/pal/common/thread_local/fast_local.rs b/library/std/src/sys/pal/common/thread_local/fast_local.rs index 9206588be06..0fdca27852c 100644 --- a/library/std/src/sys/pal/common/thread_local/fast_local.rs +++ b/library/std/src/sys/pal/common/thread_local/fast_local.rs @@ -14,7 +14,7 @@ pub macro thread_local_inner { #[inline] #[deny(unsafe_op_in_unsafe_fn)] // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint - #[cfg_attr(not(bootstrap), allow(static_mut_ref))] + #[allow(static_mut_ref)] unsafe fn __getit( _init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { diff --git a/library/std/src/sys/pal/common/thread_local/static_local.rs b/library/std/src/sys/pal/common/thread_local/static_local.rs index 51cba66fad7..0dde78b14db 100644 --- a/library/std/src/sys/pal/common/thread_local/static_local.rs +++ b/library/std/src/sys/pal/common/thread_local/static_local.rs @@ -12,7 +12,7 @@ pub macro thread_local_inner { #[inline] // see comments below #[deny(unsafe_op_in_unsafe_fn)] // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint - #[cfg_attr(not(bootstrap), allow(static_mut_ref))] + #[allow(static_mut_ref)] unsafe fn __getit( _init: $crate::option::Option<&mut $crate::option::Option<$t>>, ) -> $crate::option::Option<&'static $t> { diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 3c83afa280b..57cc656e266 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -28,8 +28,6 @@ pub mod io; pub mod memchr; pub mod net; pub mod os; -#[path = "../unix/path.rs"] -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index a769fc1ef59..46f3e5b401d 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -22,7 +22,6 @@ pub mod io; pub mod memchr; pub mod net; pub mod os; -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index 46699e64169..be8e0033902 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -29,7 +29,6 @@ pub mod fs; pub mod io; pub mod net; pub mod os; -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index 95a5b97ea42..7953104486c 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -25,8 +25,6 @@ pub mod net; #[path = "../unsupported/once.rs"] pub mod once; pub mod os; -#[path = "../unix/path.rs"] -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index 9837cc89f2d..ba53ed88f37 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -146,3 +146,11 @@ pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> Option<NonNull<T> let system_handle = uefi::env::try_image_handle()?; open_protocol(system_handle, protocol_guid).ok() } + +/// Get RuntimeServices +pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>> { + let system_table: NonNull<r_efi::efi::SystemTable> = + crate::os::uefi::env::try_system_table()?.cast(); + let runtime_services = unsafe { (*system_table.as_ptr()).runtime_services }; + NonNull::new(runtime_services) +} diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 9ee753aa1a0..efa4ed67c50 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -26,7 +26,6 @@ pub mod net; #[path = "../unsupported/once.rs"] pub mod once; pub mod os; -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] @@ -38,7 +37,6 @@ pub mod thread; pub mod thread_local_key; #[path = "../unsupported/thread_parking.rs"] pub mod thread_parking; -#[path = "../unsupported/time.rs"] pub mod time; mod helpers; diff --git a/library/std/src/sys/pal/uefi/path.rs b/library/std/src/sys/pal/uefi/path.rs deleted file mode 100644 index 106682eee56..00000000000 --- a/library/std/src/sys/pal/uefi/path.rs +++ /dev/null @@ -1,25 +0,0 @@ -use super::unsupported; -use crate::ffi::OsStr; -use crate::io; -use crate::path::{Path, PathBuf, Prefix}; - -pub const MAIN_SEP_STR: &str = "\\"; -pub const MAIN_SEP: char = '\\'; - -#[inline] -pub fn is_sep_byte(b: u8) -> bool { - b == b'\\' -} - -#[inline] -pub fn is_verbatim_sep(b: u8) -> bool { - b == b'\\' -} - -pub fn parse_prefix(_p: &OsStr) -> Option<Prefix<'_>> { - None -} - -pub(crate) fn absolute(_path: &Path) -> io::Result<PathBuf> { - unsupported() -} diff --git a/library/std/src/sys/pal/uefi/tests.rs b/library/std/src/sys/pal/uefi/tests.rs index 8806eda3ac0..5eb36da922b 100644 --- a/library/std/src/sys/pal/uefi/tests.rs +++ b/library/std/src/sys/pal/uefi/tests.rs @@ -1,4 +1,6 @@ use super::alloc::*; +use super::time::*; +use crate::time::Duration; #[test] fn align() { @@ -19,3 +21,21 @@ fn align() { } } } + +#[test] +fn epoch() { + let t = r_efi::system::Time { + year: 1970, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + nanosecond: 0, + timezone: r_efi::efi::UNSPECIFIED_TIMEZONE, + daylight: 0, + pad1: 0, + pad2: 0, + }; + assert_eq!(system_time_internal::uefi_time_to_duration(t), Duration::new(0, 0)); +} diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs new file mode 100644 index 00000000000..68f428c38fb --- /dev/null +++ b/library/std/src/sys/pal/uefi/time.rs @@ -0,0 +1,105 @@ +use crate::time::Duration; + +const SECS_IN_MINUTE: u64 = 60; +const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; +const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct Instant(Duration); + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct SystemTime(Duration); + +pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); + +impl Instant { + pub fn now() -> Instant { + panic!("time not implemented on this platform") + } + + pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> { + self.0.checked_sub(other.0) + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> { + Some(Instant(self.0.checked_add(*other)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> { + Some(Instant(self.0.checked_sub(*other)?)) + } +} + +impl SystemTime { + pub fn now() -> SystemTime { + system_time_internal::now() + .unwrap_or_else(|| panic!("time not implemented on this platform")) + } + + pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> { + self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0) + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { + Some(SystemTime(self.0.checked_add(*other)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { + Some(SystemTime(self.0.checked_sub(*other)?)) + } +} + +pub(crate) mod system_time_internal { + use super::super::helpers; + use super::*; + use crate::mem::MaybeUninit; + use crate::ptr::NonNull; + use r_efi::efi::{RuntimeServices, Time}; + + pub fn now() -> Option<SystemTime> { + let runtime_services: NonNull<RuntimeServices> = helpers::runtime_services()?; + let mut t: MaybeUninit<Time> = MaybeUninit::uninit(); + let r = unsafe { + ((*runtime_services.as_ptr()).get_time)(t.as_mut_ptr(), crate::ptr::null_mut()) + }; + + if r.is_error() { + return None; + } + + let t = unsafe { t.assume_init() }; + + Some(SystemTime(uefi_time_to_duration(t))) + } + + // This algorithm is based on the one described in the post + // https://blog.reverberate.org/2020/05/12/optimizing-date-algorithms.html + pub const fn uefi_time_to_duration(t: r_efi::system::Time) -> Duration { + assert!(t.month <= 12); + assert!(t.month != 0); + + const YEAR_BASE: u32 = 4800; /* Before min year, multiple of 400. */ + + // Calculate the number of days since 1/1/1970 + // Use 1 March as the start + let (m_adj, overflow): (u32, bool) = (t.month as u32).overflowing_sub(3); + let (carry, adjust): (u32, u32) = if overflow { (1, 12) } else { (0, 0) }; + let y_adj: u32 = (t.year as u32) + YEAR_BASE - carry; + let month_days: u32 = (m_adj.wrapping_add(adjust) * 62719 + 769) / 2048; + let leap_days: u32 = y_adj / 4 - y_adj / 100 + y_adj / 400; + let days: u32 = y_adj * 365 + leap_days + month_days + (t.day as u32 - 1) - 2472632; + + let localtime_epoch: u64 = (days as u64) * SECS_IN_DAY + + (t.second as u64) + + (t.minute as u64) * SECS_IN_MINUTE + + (t.hour as u64) * SECS_IN_HOUR; + + let utc_epoch: u64 = if t.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE { + localtime_epoch + } else { + (localtime_epoch as i64 + (t.timezone as i64) * SECS_IN_MINUTE as i64) as u64 + }; + + Duration::new(utc_epoch, t.nanosecond) + } +} diff --git a/library/std/src/sys/pal/unix/locks/pthread_mutex.rs b/library/std/src/sys/pal/unix/locks/pthread_mutex.rs index 8a78bc1fd73..ee0794334fb 100644 --- a/library/std/src/sys/pal/unix/locks/pthread_mutex.rs +++ b/library/std/src/sys/pal/unix/locks/pthread_mutex.rs @@ -1,4 +1,5 @@ use crate::cell::UnsafeCell; +use crate::io::Error; use crate::mem::{forget, MaybeUninit}; use crate::sys::cvt_nz; use crate::sys_common::lazy_box::{LazyBox, LazyInit}; @@ -103,8 +104,24 @@ impl Mutex { #[inline] pub unsafe fn lock(&self) { + #[cold] + #[inline(never)] + fn fail(r: i32) -> ! { + let error = Error::from_raw_os_error(r); + panic!("failed to lock mutex: {error}"); + } + let r = libc::pthread_mutex_lock(raw(self)); - debug_assert_eq!(r, 0); + // As we set the mutex type to `PTHREAD_MUTEX_NORMAL` above, we expect + // the lock call to never fail. Unfortunately however, some platforms + // (Solaris) do not conform to the standard, and instead always provide + // deadlock detection. How kind of them! Unfortunately that means that + // we need to check the error code here. To save us from UB on other + // less well-behaved platforms in the future, we do it even on "good" + // platforms like macOS. See #120147 for more context. + if r != 0 { + fail(r) + } } #[inline] diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 43cb9d89be9..976a437c17f 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -27,7 +27,6 @@ pub mod net; #[cfg(target_os = "l4re")] pub use self::l4re::net; pub mod os; -pub mod path; pub mod pipe; pub mod process; pub mod rand; diff --git a/library/std/src/sys/pal/unix/thread_local_dtor.rs b/library/std/src/sys/pal/unix/thread_local_dtor.rs index 4bf8f20670d..8857f96501c 100644 --- a/library/std/src/sys/pal/unix/thread_local_dtor.rs +++ b/library/std/src/sys/pal/unix/thread_local_dtor.rs @@ -11,7 +11,6 @@ // Note, however, that we run on lots older linuxes, as well as cross // compiling from a newer linux to an older linux, so we also have a // fallback implementation to use as well. -#[cfg_attr(bootstrap, allow(unexpected_cfgs))] #[cfg(any( target_os = "linux", target_os = "android", diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index b56ded8579c..88f939cbab9 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -9,8 +9,6 @@ pub mod locks; pub mod net; pub mod once; pub mod os; -#[path = "../unix/path.rs"] -pub mod path; pub mod pipe; pub mod process; pub mod stdio; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 4ffc8ecdd67..116878ee996 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -30,8 +30,6 @@ pub mod io; pub mod net; pub mod os; -#[path = "../unix/path.rs"] -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 76306b618d8..567555118d7 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -28,8 +28,6 @@ pub mod io; pub mod net; #[path = "../unsupported/os.rs"] pub mod os; -#[path = "../unix/path.rs"] -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index 2bdd3d96fa4..b82a83ae7a3 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -16,8 +16,8 @@ use crate::sys::{c, cvt, Align8}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::thread; -use super::path::maybe_verbatim; use super::{api, to_u16s, IoResult}; +use crate::sys::path::maybe_verbatim; pub struct File { handle: Handle, diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 364521dba40..726a4509f28 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -23,7 +23,6 @@ pub mod locks; pub mod memchr; pub mod net; pub mod os; -pub mod path; pub mod pipe; pub mod process; pub mod rand; @@ -210,7 +209,7 @@ pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> { // Once the syscall has completed (errors bail out early) the second closure is // yielded the data which has been read from the syscall. The return value // from this closure is then the return value of the function. -fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> crate::io::Result<T> +pub fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> crate::io::Result<T> where F1: FnMut(*mut u16, c::DWORD) -> c::DWORD, F2: FnOnce(&[u16]) -> T, @@ -274,7 +273,7 @@ where } } -fn os2path(s: &[u16]) -> PathBuf { +pub fn os2path(s: &[u16]) -> PathBuf { PathBuf::from(OsString::from_wide(s)) } diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index b4948d7e583..c9bad4ef019 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -12,8 +12,6 @@ pub mod io; pub mod locks; pub mod net; pub mod os; -#[path = "../unix/path.rs"] -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 7f221dc4fd9..e859269831a 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -24,10 +24,6 @@ pub mod net; #[path = "../unsupported/once.rs"] pub mod once; pub mod os; -#[path = "../unix/os_str.rs"] -pub mod os_str; -#[path = "../unix/path.rs"] -pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; #[path = "../unsupported/process.rs"] diff --git a/library/std/src/sys/path/mod.rs b/library/std/src/sys/path/mod.rs new file mode 100644 index 00000000000..24a94ec7828 --- /dev/null +++ b/library/std/src/sys/path/mod.rs @@ -0,0 +1,18 @@ +cfg_if::cfg_if! { + if #[cfg(target_os = "windows")] { + mod windows; + pub use windows::*; + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { + mod sgx; + pub use sgx::*; + } else if #[cfg(any( + target_os = "uefi", + target_os = "solid_asp3", + ))] { + mod unsupported_backslash; + pub use unsupported_backslash::*; + } else { + mod unix; + pub use unix::*; + } +} diff --git a/library/std/src/sys/pal/sgx/path.rs b/library/std/src/sys/path/sgx.rs index c805c15e702..c805c15e702 100644 --- a/library/std/src/sys/pal/sgx/path.rs +++ b/library/std/src/sys/path/sgx.rs diff --git a/library/std/src/sys/pal/unix/path.rs b/library/std/src/sys/path/unix.rs index 837f68d3eaf..837f68d3eaf 100644 --- a/library/std/src/sys/pal/unix/path.rs +++ b/library/std/src/sys/path/unix.rs diff --git a/library/std/src/sys/pal/solid/path.rs b/library/std/src/sys/path/unsupported_backslash.rs index 7045c9be25b..7045c9be25b 100644 --- a/library/std/src/sys/pal/solid/path.rs +++ b/library/std/src/sys/path/unsupported_backslash.rs diff --git a/library/std/src/sys/pal/windows/path.rs b/library/std/src/sys/path/windows.rs index d9684f21753..cebc7910231 100644 --- a/library/std/src/sys/pal/windows/path.rs +++ b/library/std/src/sys/path/windows.rs @@ -1,8 +1,8 @@ -use super::{c, fill_utf16_buf, to_u16s}; use crate::ffi::{OsStr, OsString}; use crate::io; use crate::path::{Path, PathBuf, Prefix}; use crate::ptr; +use crate::sys::pal::{c, fill_utf16_buf, os2path, to_u16s}; #[cfg(test)] mod tests; @@ -339,6 +339,6 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> { // `lpfilename` is a pointer to a null terminated string that is not // invalidated until after `GetFullPathNameW` returns successfully. |buffer, size| unsafe { c::GetFullPathNameW(lpfilename, size, buffer, ptr::null_mut()) }, - super::os2path, + os2path, ) } diff --git a/library/std/src/sys/pal/windows/path/tests.rs b/library/std/src/sys/path/windows/tests.rs index 623c6236166..623c6236166 100644 --- a/library/std/src/sys/pal/windows/path/tests.rs +++ b/library/std/src/sys/path/windows/tests.rs diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index 851832a377c..01f83ecb414 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs @@ -59,12 +59,14 @@ cfg_if::cfg_if! { /// A trait for viewing representations from std types #[doc(hidden)] +#[allow(dead_code)] // not used on all platforms pub trait AsInner<Inner: ?Sized> { fn as_inner(&self) -> &Inner; } /// A trait for viewing representations from std types #[doc(hidden)] +#[allow(dead_code)] // not used on all platforms pub trait AsInnerMut<Inner: ?Sized> { fn as_inner_mut(&mut self) -> &mut Inner; } diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 2e13f433dcf..83d5d63556f 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -181,7 +181,7 @@ impl<T: 'static> fmt::Debug for LocalKey<T> { #[cfg_attr(not(test), rustc_diagnostic_item = "thread_local_macro")] #[allow_internal_unstable(thread_local_internals)] // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint -#[cfg_attr(not(bootstrap), allow(static_mut_ref))] +#[allow(static_mut_ref)] macro_rules! thread_local { // empty (base case for the recursion) () => {}; diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index ddbe18ab838..27b1d311864 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -97,6 +97,20 @@ impl Std { is_for_mir_opt_tests: false, } } + + fn copy_extra_objects( + &self, + builder: &Builder<'_>, + compiler: &Compiler, + target: TargetSelection, + ) -> Vec<(PathBuf, DependencyType)> { + let mut deps = Vec::new(); + if !self.is_for_mir_opt_tests { + deps.extend(copy_third_party_objects(builder, &compiler, target)); + deps.extend(copy_self_contained_objects(builder, &compiler, target)); + } + deps + } } impl Step for Std { @@ -159,8 +173,9 @@ impl Step for Std { { builder.info("WARNING: Using a potentially old libstd. This may not behave well."); - copy_third_party_objects(builder, &compiler, target); - copy_self_contained_objects(builder, &compiler, target); + builder.ensure(StartupObjects { compiler, target }); + + self.copy_extra_objects(builder, &compiler, target); builder.ensure(StdLink::from_std(self, compiler)); return; @@ -193,15 +208,13 @@ impl Step for Std { // Even if we're not building std this stage, the new sysroot must // still contain the third party objects needed by various targets. - copy_third_party_objects(builder, &compiler, target); - copy_self_contained_objects(builder, &compiler, target); + self.copy_extra_objects(builder, &compiler, target); builder.ensure(StdLink::from_std(self, compiler_to_use)); return; } - target_deps.extend(copy_third_party_objects(builder, &compiler, target)); - target_deps.extend(copy_self_contained_objects(builder, &compiler, target)); + target_deps.extend(self.copy_extra_objects(builder, &compiler, target)); // The LLD wrappers and `rust-lld` are self-contained linking components that can be // necessary to link the stdlib on some targets. We'll also need to copy these binaries to @@ -222,10 +235,13 @@ impl Step for Std { } } + // We build a sysroot for mir-opt tests using the same trick that Miri does: A check build + // with -Zalways-encode-mir. This frees us from the need to have a target linker, and the + // fact that this is a check build integrates nicely with run_cargo. let mut cargo = if self.is_for_mir_opt_tests { - let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustc"); - cargo.arg("-p").arg("std").arg("--crate-type=lib"); - std_cargo(builder, target, compiler.stage, &mut cargo); + let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "check"); + cargo.rustflag("-Zalways-encode-mir"); + cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml")); cargo } else { let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "build"); @@ -257,7 +273,7 @@ impl Step for Std { vec![], &libstd_stamp(builder, compiler, target), target_deps, - false, + self.is_for_mir_opt_tests, // is_check false, ); diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 4b2d3e9ab4b..afbbbb5bd26 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -98,7 +98,7 @@ pub fn prebuilt_llvm_config( let out_dir = builder.llvm_out(target); let mut llvm_config_ret_dir = builder.llvm_out(builder.config.build); - if !builder.config.build.is_msvc() || builder.ninja() { + if (!builder.config.build.is_msvc() || builder.ninja()) && !builder.config.llvm_from_ci { llvm_config_ret_dir.push("build"); } llvm_config_ret_dir.push("bin"); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 04728e2e00d..baf1b5a4a1a 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -25,7 +25,6 @@ use crate::core::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::flags::get_completion; use crate::core::config::flags::Subcommand; use crate::core::config::TargetSelection; -use crate::utils; use crate::utils::cache::{Interned, INTERNER}; use crate::utils::exec::BootstrapCommand; use crate::utils::helpers::{ @@ -38,23 +37,6 @@ use crate::{envify, CLang, DocTests, GitRepo, Mode}; const ADB_TEST_DIR: &str = "/data/local/tmp/work"; -// mir-opt tests have different variants depending on whether a target is 32bit or 64bit, and -// blessing them requires blessing with each target. To aid developers, when blessing the mir-opt -// test suite the corresponding target of the opposite pointer size is also blessed. -// -// This array serves as the known mappings between 32bit and 64bit targets. If you're developing on -// a target where a target with the opposite pointer size exists, feel free to add it here. -const MIR_OPT_BLESS_TARGET_MAPPING: &[(&str, &str)] = &[ - // (32bit, 64bit) - ("i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu"), - ("i686-unknown-linux-musl", "x86_64-unknown-linux-musl"), - ("i686-pc-windows-msvc", "x86_64-pc-windows-msvc"), - ("i686-pc-windows-gnu", "x86_64-pc-windows-gnu"), - // ARM Macs don't have a corresponding 32-bit target that they can (easily) - // build for, so there is no entry for "aarch64-apple-darwin" here. - // Likewise, i686 for macOS is no longer possible to build. -]; - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct CrateBootstrap { path: Interned<PathBuf>, @@ -1487,46 +1469,18 @@ impl Step for MirOpt { }) }; - // We use custom logic to bless the mir-opt suite: mir-opt tests have multiple variants - // (32bit vs 64bit, and panic=abort vs panic=unwind), and all of them needs to be blessed. - // When blessing, we try best-effort to also bless the other variants, to aid developers. if builder.config.cmd.bless() { - let targets = MIR_OPT_BLESS_TARGET_MAPPING - .iter() - .filter(|(target_32bit, target_64bit)| { - *target_32bit == &*self.target.triple || *target_64bit == &*self.target.triple - }) - .next() - .map(|(target_32bit, target_64bit)| { - let target_32bit = TargetSelection::from_user(target_32bit); - let target_64bit = TargetSelection::from_user(target_64bit); - - // Running compiletest requires a C compiler to be available, but it might not - // have been detected by bootstrap if the target we're testing wasn't in the - // --target flags. - if !builder.cc.borrow().contains_key(&target_32bit) { - utils::cc_detect::find_target(builder, target_32bit); - } - if !builder.cc.borrow().contains_key(&target_64bit) { - utils::cc_detect::find_target(builder, target_64bit); - } + // All that we really need to do is cover all combinations of 32/64-bit and unwind/abort, + // but while we're at it we might as well flex our cross-compilation support. This + // selection covers all our tier 1 operating systems and architectures using only tier + // 1 targets. - vec![target_32bit, target_64bit] - }) - .unwrap_or_else(|| { - eprintln!( - "\ -Note that not all variants of mir-opt tests are going to be blessed, as no mapping between -a 32bit and a 64bit target was found for {target}. -You can add that mapping by changing MIR_OPT_BLESS_TARGET_MAPPING in src/bootstrap/test.rs", - target = self.target, - ); - vec![self.target] - }); - - for target in targets { - run(target); + for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] { + run(TargetSelection::from_user(target)); + } + for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] { + let target = TargetSelection::from_user(target); let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget { compiler: self.compiler, base: target, @@ -1616,27 +1570,27 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the .ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target }); } - if suite == "mir-opt" { - builder.ensure(compile::Std::new_for_mir_opt_tests(compiler, target)); - } else { - builder.ensure(compile::Std::new(compiler, target)); - } + // Also provide `rust_test_helpers` for the host. + builder.ensure(TestHelpers { target: compiler.host }); // ensure that `libproc_macro` is available on the host. builder.ensure(compile::Std::new(compiler, compiler.host)); - // Also provide `rust_test_helpers` for the host. - builder.ensure(TestHelpers { target: compiler.host }); - // As well as the target, except for plain wasm32, which can't build it if suite != "mir-opt" && !target.contains("wasm") && !target.contains("emscripten") { builder.ensure(TestHelpers { target }); } - builder.ensure(RemoteCopyLibs { compiler, target }); - let mut cmd = builder.tool_cmd(Tool::Compiletest); + if suite == "mir-opt" { + builder.ensure(compile::Std::new_for_mir_opt_tests(compiler, target)); + } else { + builder.ensure(compile::Std::new(compiler, target)); + } + + builder.ensure(RemoteCopyLibs { compiler, target }); + // compiletest currently has... a lot of arguments, so let's just pass all // of them! @@ -1745,11 +1699,13 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests)); flags.extend(builder.config.cmd.rustc_args().iter().map(|s| s.to_string())); - if let Some(linker) = builder.linker(target) { - cmd.arg("--target-linker").arg(linker); - } - if let Some(linker) = builder.linker(compiler.host) { - cmd.arg("--host-linker").arg(linker); + if suite != "mir-opt" { + if let Some(linker) = builder.linker(target) { + cmd.arg("--target-linker").arg(linker); + } + if let Some(linker) = builder.linker(compiler.host) { + cmd.arg("--host-linker").arg(linker); + } } let mut hostflags = flags.clone(); @@ -1936,15 +1892,17 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient)); } - // Running a C compiler on MSVC requires a few env vars to be set, to be - // sure to set them here. - // - // Note that if we encounter `PATH` we make sure to append to our own `PATH` - // rather than stomp over it. - if !builder.config.dry_run() && target.is_msvc() { - for &(ref k, ref v) in builder.cc.borrow()[&target].env() { - if k != "PATH" { - cmd.env(k, v); + if suite != "mir-opt" { + // Running a C compiler on MSVC requires a few env vars to be set, to be + // sure to set them here. + // + // Note that if we encounter `PATH` we make sure to append to our own `PATH` + // rather than stomp over it. + if !builder.config.dry_run() && target.is_msvc() { + for &(ref k, ref v) in builder.cc.borrow()[&target].env() { + if k != "PATH" { + cmd.env(k, v); + } } } } diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index dac8393de6b..83485abfa56 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -732,7 +732,7 @@ impl<'a> Builder<'a> { check::Rls, check::Rustfmt, check::RustAnalyzer, - check::Bootstrap + check::Bootstrap, ), Kind::Test => describe!( crate::core::build_steps::toolstate::ToolStateCheck, @@ -866,7 +866,7 @@ impl<'a> Builder<'a> { install::Miri, install::LlvmTools, install::Src, - install::Rustc + install::Rustc, ), Kind::Run => describe!( run::ExpandYamlAnchors, @@ -1646,76 +1646,12 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_WRAPPER_REAL", existing_wrapper); } - // Dealing with rpath here is a little special, so let's go into some - // detail. First off, `-rpath` is a linker option on Unix platforms - // which adds to the runtime dynamic loader path when looking for - // dynamic libraries. We use this by default on Unix platforms to ensure - // that our nightlies behave the same on Windows, that is they work out - // of the box. This can be disabled by setting `rpath = false` in `[rust]` - // table of `config.toml` - // - // Ok, so the astute might be wondering "why isn't `-C rpath` used - // here?" and that is indeed a good question to ask. This codegen - // option is the compiler's current interface to generating an rpath. - // Unfortunately it doesn't quite suffice for us. The flag currently - // takes no value as an argument, so the compiler calculates what it - // should pass to the linker as `-rpath`. This unfortunately is based on - // the **compile time** directory structure which when building with - // Cargo will be very different than the runtime directory structure. - // - // All that's a really long winded way of saying that if we use - // `-Crpath` then the executables generated have the wrong rpath of - // something like `$ORIGIN/deps` when in fact the way we distribute - // rustc requires the rpath to be `$ORIGIN/../lib`. - // - // So, all in all, to set up the correct rpath we pass the linker - // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it - // fun to pass a flag to a tool to pass a flag to pass a flag to a tool - // to change a flag in a binary? - if self.config.rpath_enabled(target) && helpers::use_host_linker(target) { - let libdir = self.sysroot_libdir_relative(compiler).to_str().unwrap(); - let rpath = if target.contains("apple") { - // Note that we need to take one extra step on macOS to also pass - // `-Wl,-instal_name,@rpath/...` to get things to work right. To - // do that we pass a weird flag to the compiler to get it to do - // so. Note that this is definitely a hack, and we should likely - // flesh out rpath support more fully in the future. - rustflags.arg("-Zosx-rpath-install-name"); - Some(format!("-Wl,-rpath,@loader_path/../{libdir}")) - } else if !target.is_windows() && !target.contains("aix") && !target.contains("xous") { - rustflags.arg("-Clink-args=-Wl,-z,origin"); - Some(format!("-Wl,-rpath,$ORIGIN/../{libdir}")) - } else { - None - }; - if let Some(rpath) = rpath { - rustflags.arg(&format!("-Clink-args={rpath}")); - } - } - cargo.env(profile_var("STRIP"), self.config.rust_strip.to_string()); if let Some(stack_protector) = &self.config.rust_stack_protector { rustflags.arg(&format!("-Zstack-protector={stack_protector}")); } - for arg in linker_args(self, compiler.host, LldThreads::Yes) { - hostflags.arg(&arg); - } - - if let Some(target_linker) = self.linker(target) { - let target = crate::envify(&target.triple); - cargo.env(&format!("CARGO_TARGET_{target}_LINKER"), target_linker); - } - // We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not - // `linker_args` here. - for flag in linker_flags(self, target, LldThreads::Yes) { - rustflags.arg(&flag); - } - for arg in linker_args(self, target, LldThreads::Yes) { - rustdocflags.arg(&arg); - } - if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc { cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler)); } @@ -1731,10 +1667,6 @@ impl<'a> Builder<'a> { if let Some(opt_level) = &self.config.rust_optimize.get_opt_level() { cargo.env(profile_var("OPT_LEVEL"), opt_level); } - if !self.config.dry_run() && self.cc.borrow()[&target].args().iter().any(|arg| arg == "-gz") - { - rustflags.arg("-Clink-arg=-gz"); - } cargo.env( profile_var("DEBUG_ASSERTIONS"), if mode == Mode::Std { @@ -1940,55 +1872,15 @@ impl<'a> Builder<'a> { rustflags.arg("-Wrustc::internal"); } - // Throughout the build Cargo can execute a number of build scripts - // compiling C/C++ code and we need to pass compilers, archivers, flags, etc - // obtained previously to those build scripts. - // Build scripts use either the `cc` crate or `configure/make` so we pass - // the options through environment variables that are fetched and understood by both. - // - // FIXME: the guard against msvc shouldn't need to be here - if target.is_msvc() { - if let Some(ref cl) = self.config.llvm_clang_cl { - cargo.env("CC", cl).env("CXX", cl); - } - } else { - let ccache = self.config.ccache.as_ref(); - let ccacheify = |s: &Path| { - let ccache = match ccache { - Some(ref s) => s, - None => return s.display().to_string(), - }; - // FIXME: the cc-rs crate only recognizes the literal strings - // `ccache` and `sccache` when doing caching compilations, so we - // mirror that here. It should probably be fixed upstream to - // accept a new env var or otherwise work with custom ccache - // vars. - match &ccache[..] { - "ccache" | "sccache" => format!("{} {}", ccache, s.display()), - _ => s.display().to_string(), - } - }; - let triple_underscored = target.triple.replace("-", "_"); - let cc = ccacheify(&self.cc(target)); - cargo.env(format!("CC_{triple_underscored}"), &cc); - - let cflags = self.cflags(target, GitRepo::Rustc, CLang::C).join(" "); - cargo.env(format!("CFLAGS_{triple_underscored}"), &cflags); - - if let Some(ar) = self.ar(target) { - let ranlib = format!("{} s", ar.display()); - cargo - .env(format!("AR_{triple_underscored}"), ar) - .env(format!("RANLIB_{triple_underscored}"), ranlib); - } - - if let Ok(cxx) = self.cxx(target) { - let cxx = ccacheify(&cxx); - let cxxflags = self.cflags(target, GitRepo::Rustc, CLang::Cxx).join(" "); - cargo - .env(format!("CXX_{triple_underscored}"), &cxx) - .env(format!("CXXFLAGS_{triple_underscored}"), cxxflags); - } + if cmd != "check" { + self.configure_linker( + compiler, + target, + &mut cargo, + &mut rustflags, + &mut rustdocflags, + &mut hostflags, + ); } // If Control Flow Guard is enabled, pass the `control-flow-guard` flag to rustc @@ -2142,6 +2034,136 @@ impl<'a> Builder<'a> { Cargo { command: cargo, rustflags, rustdocflags, hostflags, allow_features } } + fn configure_linker( + &self, + compiler: Compiler, + target: TargetSelection, + cargo: &mut Command, + rustflags: &mut Rustflags, + rustdocflags: &mut Rustflags, + hostflags: &mut HostFlags, + ) { + // Dealing with rpath here is a little special, so let's go into some + // detail. First off, `-rpath` is a linker option on Unix platforms + // which adds to the runtime dynamic loader path when looking for + // dynamic libraries. We use this by default on Unix platforms to ensure + // that our nightlies behave the same on Windows, that is they work out + // of the box. This can be disabled by setting `rpath = false` in `[rust]` + // table of `config.toml` + // + // Ok, so the astute might be wondering "why isn't `-C rpath` used + // here?" and that is indeed a good question to ask. This codegen + // option is the compiler's current interface to generating an rpath. + // Unfortunately it doesn't quite suffice for us. The flag currently + // takes no value as an argument, so the compiler calculates what it + // should pass to the linker as `-rpath`. This unfortunately is based on + // the **compile time** directory structure which when building with + // Cargo will be very different than the runtime directory structure. + // + // All that's a really long winded way of saying that if we use + // `-Crpath` then the executables generated have the wrong rpath of + // something like `$ORIGIN/deps` when in fact the way we distribute + // rustc requires the rpath to be `$ORIGIN/../lib`. + // + // So, all in all, to set up the correct rpath we pass the linker + // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it + // fun to pass a flag to a tool to pass a flag to pass a flag to a tool + // to change a flag in a binary? + if self.config.rpath_enabled(target) && helpers::use_host_linker(target) { + let libdir = self.sysroot_libdir_relative(compiler).to_str().unwrap(); + let rpath = if target.contains("apple") { + // Note that we need to take one extra step on macOS to also pass + // `-Wl,-instal_name,@rpath/...` to get things to work right. To + // do that we pass a weird flag to the compiler to get it to do + // so. Note that this is definitely a hack, and we should likely + // flesh out rpath support more fully in the future. + rustflags.arg("-Zosx-rpath-install-name"); + Some(format!("-Wl,-rpath,@loader_path/../{libdir}")) + } else if !target.is_windows() && !target.contains("aix") && !target.contains("xous") { + rustflags.arg("-Clink-args=-Wl,-z,origin"); + Some(format!("-Wl,-rpath,$ORIGIN/../{libdir}")) + } else { + None + }; + if let Some(rpath) = rpath { + rustflags.arg(&format!("-Clink-args={rpath}")); + } + } + + for arg in linker_args(self, compiler.host, LldThreads::Yes) { + hostflags.arg(&arg); + } + + if let Some(target_linker) = self.linker(target) { + let target = crate::envify(&target.triple); + cargo.env(&format!("CARGO_TARGET_{target}_LINKER"), target_linker); + } + // We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not + // `linker_args` here. + for flag in linker_flags(self, target, LldThreads::Yes) { + rustflags.arg(&flag); + } + for arg in linker_args(self, target, LldThreads::Yes) { + rustdocflags.arg(&arg); + } + + if !self.config.dry_run() && self.cc.borrow()[&target].args().iter().any(|arg| arg == "-gz") + { + rustflags.arg("-Clink-arg=-gz"); + } + + // Throughout the build Cargo can execute a number of build scripts + // compiling C/C++ code and we need to pass compilers, archivers, flags, etc + // obtained previously to those build scripts. + // Build scripts use either the `cc` crate or `configure/make` so we pass + // the options through environment variables that are fetched and understood by both. + // + // FIXME: the guard against msvc shouldn't need to be here + if target.is_msvc() { + if let Some(ref cl) = self.config.llvm_clang_cl { + cargo.env("CC", cl).env("CXX", cl); + } + } else { + let ccache = self.config.ccache.as_ref(); + let ccacheify = |s: &Path| { + let ccache = match ccache { + Some(ref s) => s, + None => return s.display().to_string(), + }; + // FIXME: the cc-rs crate only recognizes the literal strings + // `ccache` and `sccache` when doing caching compilations, so we + // mirror that here. It should probably be fixed upstream to + // accept a new env var or otherwise work with custom ccache + // vars. + match &ccache[..] { + "ccache" | "sccache" => format!("{} {}", ccache, s.display()), + _ => s.display().to_string(), + } + }; + let triple_underscored = target.triple.replace("-", "_"); + let cc = ccacheify(&self.cc(target)); + cargo.env(format!("CC_{triple_underscored}"), &cc); + + let cflags = self.cflags(target, GitRepo::Rustc, CLang::C).join(" "); + cargo.env(format!("CFLAGS_{triple_underscored}"), &cflags); + + if let Some(ar) = self.ar(target) { + let ranlib = format!("{} s", ar.display()); + cargo + .env(format!("AR_{triple_underscored}"), ar) + .env(format!("RANLIB_{triple_underscored}"), ranlib); + } + + if let Ok(cxx) = self.cxx(target) { + let cxx = ccacheify(&cxx); + let cxxflags = self.cflags(target, GitRepo::Rustc, CLang::Cxx).join(" "); + cargo + .env(format!("CXX_{triple_underscored}"), &cxx) + .env(format!("CXXFLAGS_{triple_underscored}"), cxxflags); + } + } + } + /// Ensure that a given step is built, returning its output. This will /// cache the step, so it is safe (and good!) to call this as often as /// needed to ensure that all dependencies are built. diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 700ebcf5e37..2cbebbcf4e2 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -525,6 +525,23 @@ mod dist { } #[test] + fn llvm_out_behaviour() { + let mut config = configure(&["A"], &["B"]); + config.llvm_from_ci = true; + let build = Build::new(config.clone()); + + let target = TargetSelection::from_user("A"); + assert!(build.llvm_out(target).ends_with("ci-llvm")); + let target = TargetSelection::from_user("B"); + assert!(build.llvm_out(target).ends_with("llvm")); + + config.llvm_from_ci = false; + let build = Build::new(config.clone()); + let target = TargetSelection::from_user("A"); + assert!(build.llvm_out(target).ends_with("llvm")); + } + + #[test] fn build_with_empty_host() { let config = configure(&[], &["C"]); let build = Build::new(config); diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index ec404ab8580..e63d60feff1 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -720,8 +720,10 @@ download-rustc = false if !tarball.exists() { let help_on_error = "ERROR: failed to download llvm from ci - HELP: old builds get deleted after a certain time - HELP: if trying to compile an old commit of rustc, disable `download-ci-llvm` in config.toml: + HELP: There could be two reasons behind this: + 1) The host triple is not supported for `download-ci-llvm`. + 2) Old builds get deleted after a certain time. + HELP: In either case, disable `download-ci-llvm` in your config.toml: [llvm] download-ci-llvm = false diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 1336abf6c7a..36f9ee6aff6 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -90,10 +90,6 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[ /* Extra values not defined in the built-in targets yet, but used in std */ (Some(Mode::Std), "target_env", Some(&["libnx"])), // (Some(Mode::Std), "target_os", Some(&[])), - // #[cfg(bootstrap)] zkvm - (Some(Mode::Std), "target_os", Some(&["zkvm"])), - // #[cfg(bootstrap)] risc0 - (Some(Mode::Std), "target_vendor", Some(&["risc0"])), (Some(Mode::Std), "target_arch", Some(&["spirv", "nvptx", "xtensa"])), /* Extra names used by dependencies */ // FIXME: Used by serde_json, but we should not be triggering on external dependencies. @@ -796,12 +792,16 @@ impl Build { self.stage_out(compiler, mode).join(&*target.triple).join(self.cargo_dir()) } - /// Root output directory for LLVM compiled for `target` + /// Root output directory of LLVM for `target` /// /// Note that if LLVM is configured externally then the directory returned /// will likely be empty. fn llvm_out(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("llvm") + if self.config.llvm_from_ci && self.config.build == target { + self.config.ci_llvm_root() + } else { + self.out.join(&*target.triple).join("llvm") + } } fn lld_out(&self, target: TargetSelection) -> PathBuf { diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index cc0c658aabd..f5c426a717f 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -30,7 +30,7 @@ python3 "$X_PY" test --stage 2 src/tools/rustfmt # We set the GC interval to the shortest possible value (0 would be off) to increase the chance # that bugs which only surface when the GC runs at a specific time are more likely to cause CI to fail. # This significantly increases the runtime of our test suite, or we'd do this in PR CI too. -if [[ -z "${PR_CI_JOB:-}" ]]; then +if [ -z "${PR_CI_JOB:-}" ]; then MIRIFLAGS=-Zmiri-provenance-gc=1 python3 "$X_PY" test --stage 2 src/tools/miri else python3 "$X_PY" test --stage 2 src/tools/miri diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 0db61204f77..bd5447ac835 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -72,8 +72,12 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then # Include cache version. Can be used to manually bust the Docker cache. echo "2" >> $hash_key + echo "Image input" + cat $hash_key + cksum=$(sha512sum $hash_key | \ awk '{print $1}') + echo "Image input checksum ${cksum}" fi dockerfile="$docker_dir/$image/Dockerfile" @@ -84,9 +88,6 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then context="$script_dir" fi echo "::group::Building docker image for $image" - echo "Image input" - cat $hash_key - echo "Image input checksum ${cksum}" # Print docker version docker --version diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 1998b008dc8..1f9307203bc 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -26,6 +26,7 @@ - [armv4t-none-eabi](platform-support/armv4t-none-eabi.md) - [armv5te-none-eabi](platform-support/armv5te-none-eabi.md) - [armv7r-none-eabi](platform-support/armv7r-none-eabi.md) + - [armv8r-none-eabihf](platform-support/armv8r-none-eabihf.md) - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md) - [armv7-sony-vita-newlibeabihf](platform-support/armv7-sony-vita-newlibeabihf.md) - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index f648a60b6c4..80d9dc85f16 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -280,6 +280,7 @@ target | std | host | notes [`armv7a-none-eabihf`](platform-support/arm-none-eabi.md) | * | | Bare ARMv7-A, hardfloat [`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARMv7-A Apple WatchOS `armv7s-apple-ios` | ✓ | | ARMv7-A Apple-A6 Apple iOS +[`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Bare ARMv8-R, hardfloat `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md index 4f76d0d7bbc..6335a6405a1 100644 --- a/src/doc/rustc/src/platform-support/arm-none-eabi.md +++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md @@ -13,6 +13,7 @@ - [{arm,thumb}v4t-none-eabi](armv4t-none-eabi.md) - [{arm,thumb}v5te-none-eabi](armv5te-none-eabi.md) - armv7a-none-eabihf +- [armv8r-none-eabihf](armv8r-none-eabihf.md) Bare-metal target for 32-bit ARM CPUs. diff --git a/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md new file mode 100644 index 00000000000..588e5d7c994 --- /dev/null +++ b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md @@ -0,0 +1,40 @@ +# `armv8r-none-eabihf` + +**Tier: 3** + +Bare-metal target for CPUs in the ARMv8-R architecture family, supporting +dual ARM/Thumb mode, with ARM mode as the default. + +Processors in this family include the Arm [Cortex-R52][cortex-r52] +and [Cortex-R52+][cortex-r52-plus]. + +See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all +`arm-none-eabi` targets. + +[cortex-r52]: https://www.arm.com/products/silicon-ip-cpu/cortex-r/cortex-r52 +[cortex-r52-plus]: https://www.arm.com/products/silicon-ip-cpu/cortex-r/cortex-r52-plus + +## Target maintainers + +- [Chris Copeland](https://github.com/chrisnc), `chris@chrisnc.net` + +## Requirements + +The Cortex-R52 family always includes a floating-point unit, so there is no +non-`hf` version of this target. The floating-point features assumed by this +target are those of the single-precision-only config of the Cortex-R52, which +has 16 double-precision registers, accessible as 32 single-precision registers. +The other variant of Cortex-R52 includes double-precision, 32 double-precision +registers, and Advanced SIMD (Neon). + +The manual refers to this as the "Full Advanced SIMD config". To compile code +for this variant, use: `-C target-feature=+fp64,+d32,+neon`. See the [Advanced +SIMD and floating-point support][fpu] section of the Cortex-R52 Processor +Technical Reference Manual for more details. + +[fpu]: https://developer.arm.com/documentation/100026/0104/Advanced-SIMD-and-floating-point-support/About-the-Advanced-SIMD-and-floating-point-support + +## Cross-compilation toolchains and C code + +This target supports C code compiled with the `arm-none-eabi` target triple and +`-march=armv8-r` or a suitable `-mcpu` flag. diff --git a/src/doc/unstable-book/src/compiler-flags/direct-access-external-data.md b/src/doc/unstable-book/src/compiler-flags/direct-access-external-data.md new file mode 100644 index 00000000000..c72df437960 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/direct-access-external-data.md @@ -0,0 +1,16 @@ +# `direct_access_external_data` + +The tracking issue for this feature is: https://github.com/rust-lang/compiler-team/issues/707 + +------------------------ + +Option `-Z direct-access-external-data` controls how to access symbols of +external data. + +Supported values for this option are: + +- `yes` - Don't use GOT indirection to reference external data symbols. +- `no` - Use GOT indirection to reference external data symbols. + +If the option is not explicitly specified, different targets have different +default values. diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index aab974ad79e..7ca4392233e 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -191,15 +191,36 @@ pub(crate) fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> &'hir [ast: cx.tcx.get_attrs_unchecked(did) } +pub(crate) fn item_relative_path(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<Symbol> { + tcx.def_path(def_id) + .data + .into_iter() + .filter_map(|elem| { + // extern blocks (and a few others things) have an empty name. + match elem.data.get_opt_name() { + Some(s) if !s.is_empty() => Some(s), + _ => None, + } + }) + .collect() +} + /// Record an external fully qualified name in the external_paths cache. /// /// These names are used later on by HTML rendering to generate things like /// source links back to the original item. pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemType) { + if did.is_local() { + if cx.cache.exact_paths.contains_key(&did) { + return; + } + } else if cx.cache.external_paths.contains_key(&did) { + return; + } + let crate_name = cx.tcx.crate_name(did.krate); - let relative = - cx.tcx.def_path(did).data.into_iter().filter_map(|elem| elem.data.get_opt_name()); + let relative = item_relative_path(cx.tcx, did); let fqn = if let ItemType::Macro = kind { // Check to see if it is a macro 2.0 or built-in macro if matches!( @@ -210,7 +231,7 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT ) { once(crate_name).chain(relative).collect() } else { - vec![crate_name, relative.last().expect("relative was empty")] + vec![crate_name, *relative.last().expect("relative was empty")] } } else { once(crate_name).chain(relative).collect() diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3bac71dbc24..b8e0d75e7dc 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -82,7 +82,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< // but there's already an item with the same namespace and same name. Rust gives // priority to the not-imported one, so we should, too. items.extend(doc.items.values().flat_map(|(item, renamed, import_id)| { - // First, lower everything other than imports. + // First, lower everything other than glob imports. if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { return Vec::new(); } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 3f7f9270b2d..c46047aa0db 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -323,20 +323,20 @@ impl Options { early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches, args: Vec<String>, - ) -> Result<(Options, RenderOptions), i32> { + ) -> Option<(Options, RenderOptions)> { // Check for unstable options. nightly_options::check_nightly_options(early_dcx, matches, &opts()); if args.is_empty() || matches.opt_present("h") || matches.opt_present("help") { crate::usage("rustdoc"); - return Err(0); + return None; } else if matches.opt_present("version") { rustc_driver::version!(&early_dcx, "rustdoc", matches); - return Err(0); + return None; } if rustc_driver::describe_flag_categories(early_dcx, &matches) { - return Err(0); + return None; } let color = config::parse_color(early_dcx, matches); @@ -382,7 +382,7 @@ impl Options { } } - return Err(0); + return None; } let mut emit = Vec::new(); @@ -390,10 +390,7 @@ impl Options { for kind in list.split(',') { match kind.parse() { Ok(kind) => emit.push(kind), - Err(()) => { - dcx.err(format!("unrecognized emission type: {kind}")); - return Err(1); - } + Err(()) => dcx.fatal(format!("unrecognized emission type: {kind}")), } } } @@ -403,7 +400,7 @@ impl Options { && !matches.opt_present("show-coverage") && !nightly_options::is_unstable_enabled(matches) { - early_dcx.early_fatal( + dcx.fatal( "the -Z unstable-options flag must be passed to enable --output-format for documentation generation (see https://github.com/rust-lang/rust/issues/76578)", ); } @@ -420,10 +417,7 @@ impl Options { } let paths = match theme::load_css_paths(content) { Ok(p) => p, - Err(e) => { - dcx.err(e); - return Err(1); - } + Err(e) => dcx.fatal(e), }; let mut errors = 0; @@ -442,9 +436,9 @@ impl Options { } } if errors != 0 { - return Err(1); + dcx.fatal("[check-theme] one or more tests failed"); } - return Err(0); + return None; } let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches); @@ -452,11 +446,9 @@ impl Options { let input = PathBuf::from(if describe_lints { "" // dummy, this won't be used } else if matches.free.is_empty() { - dcx.err("missing file operand"); - return Err(1); + dcx.fatal("missing file operand"); } else if matches.free.len() > 1 { - dcx.err("too many file operands"); - return Err(1); + dcx.fatal("too many file operands"); } else { &matches.free[0] }); @@ -466,10 +458,7 @@ impl Options { let externs = parse_externs(early_dcx, matches, &unstable_opts); let extern_html_root_urls = match parse_extern_html_roots(matches) { Ok(ex) => ex, - Err(err) => { - dcx.err(err); - return Err(1); - } + Err(err) => dcx.fatal(err), }; let default_settings: Vec<Vec<(String, String)>> = vec![ @@ -526,16 +515,14 @@ impl Options { let no_run = matches.opt_present("no-run"); if !should_test && no_run { - dcx.err("the `--test` flag must be passed to enable `--no-run`"); - return Err(1); + dcx.fatal("the `--test` flag must be passed to enable `--no-run`"); } let out_dir = matches.opt_str("out-dir").map(|s| PathBuf::from(&s)); let output = matches.opt_str("output").map(|s| PathBuf::from(&s)); let output = match (out_dir, output) { (Some(_), Some(_)) => { - dcx.err("cannot use both 'out-dir' and 'output' at once"); - return Err(1); + dcx.fatal("cannot use both 'out-dir' and 'output' at once"); } (Some(out_dir), None) => out_dir, (None, Some(output)) => output, @@ -549,8 +536,7 @@ impl Options { if let Some(ref p) = extension_css { if !p.is_file() { - dcx.err("option --extend-css argument must be a file"); - return Err(1); + dcx.fatal("option --extend-css argument must be a file"); } } @@ -566,31 +552,25 @@ impl Options { } let paths = match theme::load_css_paths(content) { Ok(p) => p, - Err(e) => { - dcx.err(e); - return Err(1); - } + Err(e) => dcx.fatal(e), }; for (theme_file, theme_s) in matches.opt_strs("theme").iter().map(|s| (PathBuf::from(&s), s.to_owned())) { if !theme_file.is_file() { - dcx.struct_err(format!("invalid argument: \"{theme_s}\"")) + dcx.struct_fatal(format!("invalid argument: \"{theme_s}\"")) .with_help("arguments to --theme must be files") .emit(); - return Err(1); } if theme_file.extension() != Some(OsStr::new("css")) { - dcx.struct_err(format!("invalid argument: \"{theme_s}\"")) + dcx.struct_fatal(format!("invalid argument: \"{theme_s}\"")) .with_help("arguments to --theme must have a .css extension") .emit(); - return Err(1); } let (success, ret) = theme::test_theme_against(&theme_file, &paths, &dcx); if !success { - dcx.err(format!("error loading theme file: \"{theme_s}\"")); - return Err(1); + dcx.fatal(format!("error loading theme file: \"{theme_s}\"")); } else if !ret.is_empty() { dcx.struct_warn(format!( "theme file \"{theme_s}\" is missing CSS rules from the default theme", @@ -620,22 +600,18 @@ impl Options { edition, &None, ) else { - return Err(3); + dcx.fatal("`ExternalHtml::load` failed"); }; match matches.opt_str("r").as_deref() { Some("rust") | None => {} - Some(s) => { - dcx.err(format!("unknown input format: {s}")); - return Err(1); - } + Some(s) => dcx.fatal(format!("unknown input format: {s}")), } let index_page = matches.opt_str("index-page").map(|s| PathBuf::from(&s)); if let Some(ref index_page) = index_page { if !index_page.is_file() { - dcx.err("option `--index-page` argument must be a file"); - return Err(1); + dcx.fatal("option `--index-page` argument must be a file"); } } @@ -646,8 +622,7 @@ impl Options { let crate_types = match parse_crate_types_from_list(matches.opt_strs("crate-type")) { Ok(types) => types, Err(e) => { - dcx.err(format!("unknown crate type: {e}")); - return Err(1); + dcx.fatal(format!("unknown crate type: {e}")); } }; @@ -655,18 +630,13 @@ impl Options { Some(s) => match OutputFormat::try_from(s.as_str()) { Ok(out_fmt) => { if !out_fmt.is_json() && show_coverage { - dcx.struct_err( + dcx.fatal( "html output format isn't supported for the --show-coverage option", - ) - .emit(); - return Err(1); + ); } out_fmt } - Err(e) => { - dcx.err(e); - return Err(1); - } + Err(e) => dcx.fatal(e), }, None => OutputFormat::default(), }; @@ -709,16 +679,14 @@ impl Options { let html_no_source = matches.opt_present("html-no-source"); if generate_link_to_definition && (show_coverage || output_format != OutputFormat::Html) { - dcx.struct_err( + dcx.fatal( "--generate-link-to-definition option can only be used with HTML output format", - ) - .emit(); - return Err(1); + ); } - let scrape_examples_options = ScrapeExamplesOptions::new(matches, &dcx)?; + let scrape_examples_options = ScrapeExamplesOptions::new(matches, &dcx); let with_examples = matches.opt_strs("with-examples"); - let call_locations = crate::scrape_examples::load_call_locations(with_examples, &dcx)?; + let call_locations = crate::scrape_examples::load_call_locations(with_examples, &dcx); let unstable_features = rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref()); @@ -793,7 +761,7 @@ impl Options { no_emit_shared: false, html_no_source, }; - Ok((options, render_options)) + Some((options, render_options)) } /// Returns `true` if the file given as `self.input` is a Markdown file. diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index e80da46adb4..f10c829bf4e 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -4,7 +4,7 @@ use std::fmt; use serde::{Serialize, Serializer}; -use rustc_hir::def::DefKind; +use rustc_hir::def::{CtorOf, DefKind}; use rustc_span::hygiene::MacroKind; use crate::clean; @@ -115,7 +115,15 @@ impl<'a> From<&'a clean::Item> for ItemType { impl From<DefKind> for ItemType { fn from(other: DefKind) -> Self { - match other { + Self::from_def_kind(other, None) + } +} + +impl ItemType { + /// Depending on the parent kind, some variants have a different translation (like a `Method` + /// becoming a `TyMethod`). + pub(crate) fn from_def_kind(kind: DefKind, parent_kind: Option<DefKind>) -> Self { + match kind { DefKind::Enum => Self::Enum, DefKind::Fn => Self::Function, DefKind::Mod => Self::Module, @@ -131,30 +139,35 @@ impl From<DefKind> for ItemType { MacroKind::Attr => ItemType::ProcAttribute, MacroKind::Derive => ItemType::ProcDerive, }, - DefKind::ForeignTy - | DefKind::Variant - | DefKind::AssocTy - | DefKind::TyParam + DefKind::ForeignTy => Self::ForeignType, + DefKind::Variant => Self::Variant, + DefKind::Field => Self::StructField, + DefKind::AssocTy => Self::AssocType, + DefKind::AssocFn => { + if let Some(DefKind::Trait) = parent_kind { + Self::TyMethod + } else { + Self::Method + } + } + DefKind::Ctor(CtorOf::Struct, _) => Self::Struct, + DefKind::Ctor(CtorOf::Variant, _) => Self::Variant, + DefKind::AssocConst => Self::AssocConst, + DefKind::TyParam | DefKind::ConstParam - | DefKind::Ctor(..) - | DefKind::AssocFn - | DefKind::AssocConst | DefKind::ExternCrate | DefKind::Use | DefKind::ForeignMod | DefKind::AnonConst | DefKind::InlineConst | DefKind::OpaqueTy - | DefKind::Field | DefKind::LifetimeParam | DefKind::GlobalAsm | DefKind::Impl { .. } | DefKind::Closure => Self::ForeignType, } } -} -impl ItemType { pub(crate) fn as_str(&self) -> &'static str { match *self { ItemType::Module => "mod", diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 1923fc15119..4ba1665bdc9 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -32,6 +32,7 @@ use crate::clean::{ self, types::ExternalLocation, utils::find_nearest_parent_module, ExternalCrate, ItemId, PrimitiveType, }; +use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::escape::Escape; use crate::html::render::Context; @@ -581,22 +582,11 @@ fn generate_macro_def_id_path( cx: &Context<'_>, root_path: Option<&str>, ) -> Result<(String, ItemType, Vec<Symbol>), HrefError> { - let tcx = cx.shared.tcx; + let tcx = cx.tcx(); let crate_name = tcx.crate_name(def_id.krate); let cache = cx.cache(); - let fqp: Vec<Symbol> = tcx - .def_path(def_id) - .data - .into_iter() - .filter_map(|elem| { - // extern blocks (and a few others things) have an empty name. - match elem.data.get_opt_name() { - Some(s) if !s.is_empty() => Some(s), - _ => None, - } - }) - .collect(); + let fqp = clean::inline::item_relative_path(tcx, def_id); let mut relative = fqp.iter().copied(); let cstore = CStore::from_tcx(tcx); // We need this to prevent a `panic` when this function is used from intra doc links... @@ -651,92 +641,168 @@ fn generate_macro_def_id_path( Ok((url, ItemType::Macro, fqp)) } +fn generate_item_def_id_path( + mut def_id: DefId, + original_def_id: DefId, + cx: &Context<'_>, + root_path: Option<&str>, + original_def_kind: DefKind, +) -> Result<(String, ItemType, Vec<Symbol>), HrefError> { + use crate::rustc_trait_selection::infer::TyCtxtInferExt; + use crate::rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; + use rustc_middle::traits::ObligationCause; + + let tcx = cx.tcx(); + let crate_name = tcx.crate_name(def_id.krate); + + // No need to try to infer the actual parent item if it's not an associated item from the `impl` + // block. + if def_id != original_def_id && matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) { + let infcx = tcx.infer_ctxt().build(); + def_id = infcx + .at(&ObligationCause::dummy(), tcx.param_env(def_id)) + .query_normalize(ty::Binder::dummy(tcx.type_of(def_id).instantiate_identity())) + .map(|resolved| infcx.resolve_vars_if_possible(resolved.value)) + .ok() + .and_then(|normalized| normalized.skip_binder().ty_adt_def()) + .map(|adt| adt.did()) + .unwrap_or(def_id); + } + + let relative = clean::inline::item_relative_path(tcx, def_id); + let fqp: Vec<Symbol> = once(crate_name).chain(relative).collect(); + + let def_kind = tcx.def_kind(def_id); + let shortty = def_kind.into(); + let module_fqp = to_module_fqp(shortty, &fqp); + let mut is_remote = false; + + let url_parts = url_parts(cx.cache(), def_id, &module_fqp, &cx.current, &mut is_remote)?; + let (url_parts, shortty, fqp) = make_href(root_path, shortty, url_parts, &fqp, is_remote)?; + if def_id == original_def_id { + return Ok((url_parts, shortty, fqp)); + } + let kind = ItemType::from_def_kind(original_def_kind, Some(def_kind)); + Ok((format!("{url_parts}#{kind}.{}", tcx.item_name(original_def_id)), shortty, fqp)) +} + +fn to_module_fqp(shortty: ItemType, fqp: &[Symbol]) -> &[Symbol] { + if shortty == ItemType::Module { fqp } else { &fqp[..fqp.len() - 1] } +} + +fn url_parts( + cache: &Cache, + def_id: DefId, + module_fqp: &[Symbol], + relative_to: &[Symbol], + is_remote: &mut bool, +) -> Result<UrlPartsBuilder, HrefError> { + match cache.extern_locations[&def_id.krate] { + ExternalLocation::Remote(ref s) => { + *is_remote = true; + let s = s.trim_end_matches('/'); + let mut builder = UrlPartsBuilder::singleton(s); + builder.extend(module_fqp.iter().copied()); + Ok(builder) + } + ExternalLocation::Local => Ok(href_relative_parts(module_fqp, relative_to).collect()), + ExternalLocation::Unknown => Err(HrefError::DocumentationNotBuilt), + } +} + +fn make_href( + root_path: Option<&str>, + shortty: ItemType, + mut url_parts: UrlPartsBuilder, + fqp: &[Symbol], + is_remote: bool, +) -> Result<(String, ItemType, Vec<Symbol>), HrefError> { + if !is_remote && let Some(root_path) = root_path { + let root = root_path.trim_end_matches('/'); + url_parts.push_front(root); + } + debug!(?url_parts); + match shortty { + ItemType::Module => { + url_parts.push("index.html"); + } + _ => { + let prefix = shortty.as_str(); + let last = fqp.last().unwrap(); + url_parts.push_fmt(format_args!("{prefix}.{last}.html")); + } + } + Ok((url_parts.finish(), shortty, fqp.to_vec())) +} + pub(crate) fn href_with_root_path( - did: DefId, + original_did: DefId, cx: &Context<'_>, root_path: Option<&str>, ) -> Result<(String, ItemType, Vec<Symbol>), HrefError> { let tcx = cx.tcx(); - let def_kind = tcx.def_kind(did); + let def_kind = tcx.def_kind(original_did); let did = match def_kind { DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst | DefKind::Variant => { // documented on their parent's page - tcx.parent(did) + tcx.parent(original_did) } + // If this a constructor, we get the parent (either a struct or a variant) and then + // generate the link for this item. + DefKind::Ctor(..) => return href_with_root_path(tcx.parent(original_did), cx, root_path), DefKind::ExternCrate => { // Link to the crate itself, not the `extern crate` item. - if let Some(local_did) = did.as_local() { + if let Some(local_did) = original_did.as_local() { tcx.extern_mod_stmt_cnum(local_did).unwrap_or(LOCAL_CRATE).as_def_id() } else { - did + original_did } } - _ => did, + _ => original_did, }; let cache = cx.cache(); let relative_to = &cx.current; - fn to_module_fqp(shortty: ItemType, fqp: &[Symbol]) -> &[Symbol] { - if shortty == ItemType::Module { fqp } else { &fqp[..fqp.len() - 1] } - } - if !did.is_local() - && !cache.effective_visibilities.is_directly_public(tcx, did) - && !cache.document_private - && !cache.primitive_locations.values().any(|&id| id == did) - { - return Err(HrefError::Private); + if !original_did.is_local() { + // If we are generating an href for the "jump to def" feature, then the only case we want + // to ignore is if the item is `doc(hidden)` because we can't link to it. + if root_path.is_some() { + if tcx.is_doc_hidden(original_did) { + return Err(HrefError::Private); + } + } else if !cache.effective_visibilities.is_directly_public(tcx, did) + && !cache.document_private + && !cache.primitive_locations.values().any(|&id| id == did) + { + return Err(HrefError::Private); + } } let mut is_remote = false; - let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) { + let (fqp, shortty, url_parts) = match cache.paths.get(&did) { Some(&(ref fqp, shortty)) => (fqp, shortty, { let module_fqp = to_module_fqp(shortty, fqp.as_slice()); debug!(?fqp, ?shortty, ?module_fqp); href_relative_parts(module_fqp, relative_to).collect() }), None => { - if let Some(&(ref fqp, shortty)) = cache.external_paths.get(&did) { + // Associated items are handled differently with "jump to def". The anchor is generated + // directly here whereas for intra-doc links, we have some extra computation being + // performed there. + let def_id_to_get = if root_path.is_some() { original_did } else { did }; + if let Some(&(ref fqp, shortty)) = cache.external_paths.get(&def_id_to_get) { let module_fqp = to_module_fqp(shortty, fqp); - ( - fqp, - shortty, - match cache.extern_locations[&did.krate] { - ExternalLocation::Remote(ref s) => { - is_remote = true; - let s = s.trim_end_matches('/'); - let mut builder = UrlPartsBuilder::singleton(s); - builder.extend(module_fqp.iter().copied()); - builder - } - ExternalLocation::Local => { - href_relative_parts(module_fqp, relative_to).collect() - } - ExternalLocation::Unknown => return Err(HrefError::DocumentationNotBuilt), - }, - ) + (fqp, shortty, url_parts(cache, did, module_fqp, relative_to, &mut is_remote)?) } else if matches!(def_kind, DefKind::Macro(_)) { return generate_macro_def_id_path(did, cx, root_path); + } else if did.is_local() { + return Err(HrefError::Private); } else { - return Err(HrefError::NotInExternalCache); + return generate_item_def_id_path(did, original_did, cx, root_path, def_kind); } } }; - if !is_remote && let Some(root_path) = root_path { - let root = root_path.trim_end_matches('/'); - url_parts.push_front(root); - } - debug!(?url_parts); - match shortty { - ItemType::Module => { - url_parts.push("index.html"); - } - _ => { - let prefix = shortty.as_str(); - let last = fqp.last().unwrap(); - url_parts.push_fmt(format_args!("{prefix}.{last}.html")); - } - } - Ok((url_parts.finish(), shortty, fqp.to_vec())) + make_href(root_path, shortty, url_parts, fqp, is_remote) } pub(crate) fn href( diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index b055e355b78..8ee35db56f8 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -94,7 +94,7 @@ impl<'tcx> SpanMapVisitor<'tcx> { /// Used to generate links on items' definition to go to their documentation page. pub(crate) fn extract_info_from_hir_id(&mut self, hir_id: HirId) { - if let Some(Node::Item(item)) = self.tcx.opt_hir_node(hir_id) { + if let Node::Item(item) = self.tcx.hir_node(hir_id) { if let Some(span) = self.tcx.def_ident_span(item.owner_id) { let cspan = clean::Span::new(span); // If the span isn't from the current crate, we ignore it. @@ -199,7 +199,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { if !span.overlaps(m.spans.inner_span) { // Now that we confirmed it's a file import, we want to get the span for the module // name only and not all the "mod foo;". - if let Some(Node::Item(item)) = self.tcx.opt_hir_node(id) { + if let Node::Item(item) = self.tcx.hir_node(id) { self.matches.insert( item.ident.span, LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)), diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8c10f14116a..18ea49c5baf 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -18,7 +18,9 @@ #![recursion_limit = "256"] #![warn(rustc::internal)] #![allow(clippy::collapsible_if, clippy::collapsible_else_if)] +#![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::potential_query_instability)] +#![allow(rustc::untranslatable_diagnostic)] extern crate thin_vec; #[macro_use] @@ -177,13 +179,16 @@ pub fn main() { init_logging(&early_dcx); rustc_driver::init_logger(&early_dcx, rustc_log::LoggerConfig::from_env("RUSTDOC_LOG")); - let exit_code = rustc_driver::catch_with_exit_code(|| match get_args(&early_dcx) { - Some(args) => main_args(&mut early_dcx, &args, using_internal_features), - _ => - { - #[allow(deprecated)] - Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) - } + let exit_code = rustc_driver::catch_with_exit_code(|| { + let args = env::args_os() + .enumerate() + .map(|(i, arg)| { + arg.into_string().unwrap_or_else(|arg| { + early_dcx.early_fatal(format!("argument {i} is not valid Unicode: {arg:?}")) + }) + }) + .collect::<Vec<_>>(); + main_args(&mut early_dcx, &args, using_internal_features) }); process::exit(exit_code); } @@ -219,19 +224,6 @@ fn init_logging(early_dcx: &EarlyDiagCtxt) { tracing::subscriber::set_global_default(subscriber).unwrap(); } -fn get_args(early_dcx: &EarlyDiagCtxt) -> Option<Vec<String>> { - env::args_os() - .enumerate() - .map(|(i, arg)| { - arg.into_string() - .map_err(|arg| { - early_dcx.early_warn(format!("Argument {i} is not valid Unicode: {arg:?}")); - }) - .ok() - }) - .collect() -} - fn opts() -> Vec<RustcOptGroup> { let stable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::stable; let unstable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::unstable; @@ -730,15 +722,8 @@ fn main_args( // Note that we discard any distinction between different non-zero exit // codes from `from_matches` here. let (options, render_options) = match config::Options::from_matches(early_dcx, &matches, args) { - Ok(opts) => opts, - Err(code) => { - return if code == 0 { - Ok(()) - } else { - #[allow(deprecated)] - Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) - }; - } + Some(opts) => opts, + None => return Ok(()), }; let diag = diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index e73649c7224..6649894f9c2 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -156,7 +156,7 @@ impl Translate for BufferEmitter { } impl Emitter for BufferEmitter { - fn emit_diagnostic(&mut self, diag: &Diagnostic) { + fn emit_diagnostic(&mut self, diag: Diagnostic) { let mut buffer = self.buffer.borrow_mut(); let fluent_args = to_fluent_args(diag.args()); diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 9069098bf1a..f7bc5464707 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -7,6 +7,7 @@ use rustc_hir::def::{DefKind, DocLinkResMap, Namespace, Res}; use rustc_hir::HirId; use rustc_lint_defs::Applicability; use rustc_resolve::rustdoc::source_span_for_markdown_range; +use rustc_span::def_id::DefId; use rustc_span::Symbol; use crate::clean::utils::find_nearest_parent_module; @@ -33,17 +34,22 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { return; } - if item.link_names(&cx.cache).is_empty() { - // If there's no link names in this item, - // then we skip resolution querying to - // avoid from panicking. - return; + if let Some(item_id) = item.def_id() { + check_redundant_explicit_link_for_did(cx, item, item_id, hir_id, &doc); } + if let Some(item_id) = item.inline_stmt_id { + check_redundant_explicit_link_for_did(cx, item, item_id, hir_id, &doc); + } +} - let Some(item_id) = item.def_id() else { - return; - }; - let Some(local_item_id) = item_id.as_local() else { +fn check_redundant_explicit_link_for_did<'md>( + cx: &DocContext<'_>, + item: &Item, + did: DefId, + hir_id: HirId, + doc: &'md str, +) { + let Some(local_item_id) = did.as_local() else { return; }; @@ -53,12 +59,26 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { return; } let is_private = !cx.render_options.document_private - && !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item_id); + && !cx.cache.effective_visibilities.is_directly_public(cx.tcx, did); if is_private { return; } - check_redundant_explicit_link(cx, item, hir_id, &doc); + let module_id = match cx.tcx.def_kind(did) { + DefKind::Mod if item.inner_docs(cx.tcx) => did, + _ => find_nearest_parent_module(cx.tcx, did).unwrap(), + }; + + let Some(resolutions) = + cx.tcx.resolutions(()).doc_link_resolutions.get(&module_id.expect_local()) + else { + // If there's no resolutions in this module, + // then we skip resolution querying to + // avoid from panicking. + return; + }; + + check_redundant_explicit_link(cx, item, hir_id, &doc, &resolutions); } fn check_redundant_explicit_link<'md>( @@ -66,6 +86,7 @@ fn check_redundant_explicit_link<'md>( item: &Item, hir_id: HirId, doc: &'md str, + resolutions: &DocLinkResMap, ) -> Option<()> { let mut broken_line_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); let mut offset_iter = Parser::new_with_broken_link_callback( @@ -74,12 +95,6 @@ fn check_redundant_explicit_link<'md>( Some(&mut broken_line_callback), ) .into_offset_iter(); - let item_id = item.def_id()?; - let module_id = match cx.tcx.def_kind(item_id) { - DefKind::Mod if item.inner_docs(cx.tcx) => item_id, - _ => find_nearest_parent_module(cx.tcx, item_id).unwrap(), - }; - let resolutions = cx.tcx.doc_link_resolutions(module_id); while let Some((event, link_range)) = offset_iter.next() { match event { diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index b7d9c16f348..9c9b386edda 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -38,28 +38,23 @@ pub(crate) struct ScrapeExamplesOptions { } impl ScrapeExamplesOptions { - pub(crate) fn new( - matches: &getopts::Matches, - dcx: &rustc_errors::DiagCtxt, - ) -> Result<Option<Self>, i32> { + pub(crate) fn new(matches: &getopts::Matches, dcx: &rustc_errors::DiagCtxt) -> Option<Self> { let output_path = matches.opt_str("scrape-examples-output-path"); let target_crates = matches.opt_strs("scrape-examples-target-crate"); let scrape_tests = matches.opt_present("scrape-tests"); match (output_path, !target_crates.is_empty(), scrape_tests) { - (Some(output_path), true, _) => Ok(Some(ScrapeExamplesOptions { + (Some(output_path), true, _) => Some(ScrapeExamplesOptions { output_path: PathBuf::from(output_path), target_crates, scrape_tests, - })), + }), (Some(_), false, _) | (None, true, _) => { - dcx.err("must use --scrape-examples-output-path and --scrape-examples-target-crate together"); - Err(1) + dcx.fatal("must use --scrape-examples-output-path and --scrape-examples-target-crate together"); } (None, false, true) => { - dcx.err("must use --scrape-examples-output-path and --scrape-examples-target-crate with --scrape-tests"); - Err(1) + dcx.fatal("must use --scrape-examples-output-path and --scrape-examples-target-crate with --scrape-tests"); } - (None, false, false) => Ok(None), + (None, false, false) => None, } } } @@ -342,24 +337,20 @@ pub(crate) fn run( pub(crate) fn load_call_locations( with_examples: Vec<String>, dcx: &rustc_errors::DiagCtxt, -) -> Result<AllCallLocations, i32> { - let inner = || { - let mut all_calls: AllCallLocations = FxHashMap::default(); - for path in with_examples { - let bytes = fs::read(&path).map_err(|e| format!("{e} (for path {path})"))?; - let mut decoder = MemDecoder::new(&bytes, 0); - let calls = AllCallLocations::decode(&mut decoder); - - for (function, fn_calls) in calls.into_iter() { - all_calls.entry(function).or_default().extend(fn_calls.into_iter()); - } - } +) -> AllCallLocations { + let mut all_calls: AllCallLocations = FxHashMap::default(); + for path in with_examples { + let bytes = match fs::read(&path) { + Ok(bytes) => bytes, + Err(e) => dcx.fatal(format!("failed to load examples: {e}")), + }; + let mut decoder = MemDecoder::new(&bytes, 0); + let calls = AllCallLocations::decode(&mut decoder); - Ok(all_calls) - }; + for (function, fn_calls) in calls.into_iter() { + all_calls.entry(function).or_default().extend(fn_calls.into_iter()); + } + } - inner().map_err(|e: String| { - dcx.err(format!("failed to load examples: {e}")); - 1 - }) + all_calls } diff --git a/src/stage0.json b/src/stage0.json index 1297eb1f8ec..0b6d6e2a138 100644 --- a/src/stage0.json +++ b/src/stage0.json @@ -18,423 +18,423 @@ "tool is executed." ], "compiler": { - "date": "2023-12-22", + "date": "2024-02-04", "version": "beta" }, "rustfmt": { - "date": "2023-12-22", + "date": "2024-02-04", "version": "nightly" }, "checksums_sha256": { - "dist/2023-12-22/cargo-beta-aarch64-apple-darwin.tar.gz": "80a4c4d72f7f436105084047a5806c5665749ecb84ff06bb25e759b56049e610", - "dist/2023-12-22/cargo-beta-aarch64-apple-darwin.tar.xz": "0290ccea9da40123cb5ce9d8c22721e015de77525e267003faaca4a161179da0", - "dist/2023-12-22/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "85c79d51b2d8480343546a6164fea3f1992a4b8de3c6a45a4952b0eb2ee467ab", - "dist/2023-12-22/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "f9174eac9ee6dcd60c24ce5ac5341f16ebb5d704f79bef585e963576a7c7c624", - "dist/2023-12-22/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "76fdafa72f31538fe1747da8ff63a16af91affddc0564a8a3bc1d96bed242466", - "dist/2023-12-22/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "22ae3c0460073037beee67f0bd9d86af0b72c90d9ee6bf14bb6f09e9cbdf2471", - "dist/2023-12-22/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "8731388fe7335a9c31b33ed3bbd5a4e29402e0bfd0ee4b0842974a9416859c8b", - "dist/2023-12-22/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "38f8907aab9795465b8be1d0e38ad3b812ea6ea6e3672773b43e4312677916ea", - "dist/2023-12-22/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "19e329bd134d01c73dd74a10ee63e35782692cb54ee9dd81556b3920fc055b3b", - "dist/2023-12-22/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "b3f4fab444cb5bd462a36f8fb3d90a20042389a5f809bf431dc51645430b6dfa", - "dist/2023-12-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "cdc61bec25e556c6d0ef1150c1a01225eae4e325bce94bd49d43ff1d2b2f4049", - "dist/2023-12-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "082ed52b5bc4e8b4ac16e9a7af81ad774827e41af63532599ee41724b6907378", - "dist/2023-12-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "7624915c4adfb8af8d294f581a3ca4796d53a76f7ccb6546c858e0f785adb252", - "dist/2023-12-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "c224a28f4ffec2b820ac26e21e4bf1e6ecc67f47598e91d34a4e922c21cd967a", - "dist/2023-12-22/cargo-beta-i686-pc-windows-gnu.tar.gz": "d936b84681f2b5fd7da75c99eab6c40ae5464b1ac97733cf5774ae7783fad941", - "dist/2023-12-22/cargo-beta-i686-pc-windows-gnu.tar.xz": "fa2864c6cbbe940a81a497fcb307afbd7c6c0551346676daf2fa0b488dc72489", - "dist/2023-12-22/cargo-beta-i686-pc-windows-msvc.tar.gz": "1b6ed32c7f3b3c0b2f09e43ab04ecf62aa11c778911b860ee0a82cd22fa8ef0c", - "dist/2023-12-22/cargo-beta-i686-pc-windows-msvc.tar.xz": "35cf7cf47a49af4b68171264943adcee5c907d8d4fbb021a0716e10ba946655c", - "dist/2023-12-22/cargo-beta-i686-unknown-linux-gnu.tar.gz": "cc993cf80d125d5ac25210dee1706bd23aa94f949fb94aa22409f434bafe3c35", - "dist/2023-12-22/cargo-beta-i686-unknown-linux-gnu.tar.xz": "60e2bcf98f9969bae7f61987bc30e2358c832033ea98be6f8e08e8b95e8b2409", - "dist/2023-12-22/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz": "08dbad235465958534802c1609f881561767a63a3373033678caa29b7384e1af", - "dist/2023-12-22/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz": "cbb79d6e06e12b7bc278d6b3a220380e1d4e863c60eed3462ca4f310b25bf247", - "dist/2023-12-22/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "f25b99291e3d7ed8891ec1196a3bd747cfc755b3c0bb27cbef0fb1aabeecd950", - "dist/2023-12-22/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "0c496d22b1f641ea4bef847a1efe7b69737b0c1d7ca2920ae0a1e87ca99c00e1", - "dist/2023-12-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "9d9800913636d33b9976416fa128d6e734c98978c91fdb846a16c9f2b014a77e", - "dist/2023-12-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "668dda14116c4d54f43653efccdd2a4d211dfea1a08ae5fe02fd69d21b6d9783", - "dist/2023-12-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "ec8b813a83d0999a2181c3e026cc43c0004bcdef621ef07c9741b71ed60858a7", - "dist/2023-12-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "dda9fac6999682ad9bfbeca1cc26b4b083c99558c531e2137bca4b22331527a1", - "dist/2023-12-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "ff1153a92dbdf499e6cbcea37d6be513e1c844d303032f9f1f2c9af45dd43b26", - "dist/2023-12-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "3b8247891ac28674ff4d647da93e267e2400f948b60c870227683463466bc983", - "dist/2023-12-22/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "239486637406a61f1aa25925f82131a31d133972e7926dfa54152285ed83917f", - "dist/2023-12-22/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "7e9d66d61387aa45a1141187806bc181251b1164bbc48e6b52d8770d746507b6", - "dist/2023-12-22/cargo-beta-x86_64-apple-darwin.tar.gz": "3d47e067fedaa2f96cbb33b23315d52d7f5a3379cccca560db312e6cfbbcab39", - "dist/2023-12-22/cargo-beta-x86_64-apple-darwin.tar.xz": "7d7b2239cdf1e946ee97ee81ce69f2fe2f3695a82c0434a4a853218547ee58b3", - "dist/2023-12-22/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "34b195423b12f4253dbcb47fe9bd55e1bdb302c86096ee9f8248e65c218c5ebc", - "dist/2023-12-22/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "d7ebbe5c54ee55ee320e7a57e323d7277afe7c56ec31465fb8012cd436412ef4", - "dist/2023-12-22/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "41c1b391e8f132d8bb18d79e52cf2c7e0443417854943608383073cbb977b1ce", - "dist/2023-12-22/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "f75987c83543c4994dffc7dfb0bfb57390fbbdf79165360d94fd6513b3bf8abd", - "dist/2023-12-22/cargo-beta-x86_64-unknown-freebsd.tar.gz": "56d4ada9b370a6fb3b1a654aebd710194eab8e6a2f7f46df9f191a4ae2d75d9e", - "dist/2023-12-22/cargo-beta-x86_64-unknown-freebsd.tar.xz": "5337096841f04ba7337e8b35df5197fe078832fc417cbe7b4de454c45ae797bc", - "dist/2023-12-22/cargo-beta-x86_64-unknown-illumos.tar.gz": "e1ad1e2044a8b3329349a33a70400491cb79f5e7c847a626c96415f240e6720a", - "dist/2023-12-22/cargo-beta-x86_64-unknown-illumos.tar.xz": "f3546d9d207dc59c67dc8e13ccb0abc3fba14ca5feed4f75e0f3c28e31c9ad5f", - "dist/2023-12-22/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "0497f21e775ab847657c6815275d2a8cf03e4d9b4e75975eaa5eeef7fa84b62e", - "dist/2023-12-22/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "5fc2c06ff83063e7c992729f2dc5dc62771c5e0adeb04b0fb4e12f73b166d29c", - "dist/2023-12-22/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "ce5cdea30636dcb14385ead3ca2d31ded9d3f243234c82b3326551c0cf03d599", - "dist/2023-12-22/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "086662482440baad1b5cb738301a186de41ba6512bae1d77369d65e37c56d818", - "dist/2023-12-22/cargo-beta-x86_64-unknown-netbsd.tar.gz": "b59d49075a3a3fa2aaa8264d3a0c4444400dffe4780bb5efb350d9d558dfe5a9", - "dist/2023-12-22/cargo-beta-x86_64-unknown-netbsd.tar.xz": "bd940fc6505c603a2d0e4743af3aa1df6ef903676f31bf4f06083cf86ba0f4d4", - "dist/2023-12-22/clippy-beta-aarch64-apple-darwin.tar.gz": "42e4c7e85b516b54bc9a92fdcbaf31a280121a6264ffc00bc4330bb3f3d1ef09", - "dist/2023-12-22/clippy-beta-aarch64-apple-darwin.tar.xz": "1858bb5aa212dc68c694e044dd138f58a94ef236e29623b46c275cb9765d1433", - "dist/2023-12-22/clippy-beta-aarch64-pc-windows-msvc.tar.gz": "8ec1c0c20dd3381bb2177e3ff28c777a7de6aff5fa557cf3b4e7ebc6aee7de84", - "dist/2023-12-22/clippy-beta-aarch64-pc-windows-msvc.tar.xz": "cfa8fd15c5b0ff1570a99ea15004f88a8ddd50f6d367082cf6464523355666c1", - "dist/2023-12-22/clippy-beta-aarch64-unknown-linux-gnu.tar.gz": "eb81038f1cc56601719a6165da2ba71f357f00ea3380e46f0a1283174efaa9d2", - "dist/2023-12-22/clippy-beta-aarch64-unknown-linux-gnu.tar.xz": "dc4c69b81fd186e40b6df3900d0c555214b999f3c1ca5a2697d93503357c7194", - "dist/2023-12-22/clippy-beta-aarch64-unknown-linux-musl.tar.gz": "e2fde1d65c46011d3ce80e1e46e13dcf7b5673009398296cd4126b1e4a9b2cb0", - "dist/2023-12-22/clippy-beta-aarch64-unknown-linux-musl.tar.xz": "b6a422245e574c149b984655f023ca3721c1b5d5a08245292872d86e4b77980d", - "dist/2023-12-22/clippy-beta-arm-unknown-linux-gnueabi.tar.gz": "4b3ece564b22857b0741080ce20f190dedbd72fa8c7a284921e4c3c481fdd264", - "dist/2023-12-22/clippy-beta-arm-unknown-linux-gnueabi.tar.xz": "bab8dbbf290576dd9f77c9685f5f1bab114215c85c83512d87839a08a3adce6e", - "dist/2023-12-22/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz": "732adcc6849929efa239a8f5c638fd68324d8f05330b518b8b0804351ae6889a", - "dist/2023-12-22/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz": "5d726d8da3909f1ca58e1b5b50067205b90bf1a7689c516abce66a14b68fd524", - "dist/2023-12-22/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz": "c939f4d6675dfbe0ed0d0353fd9a26b0f96f53c0118257d306eb46c883438b8d", - "dist/2023-12-22/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz": "fa1a7abcdaa6f0347811849dd4dbdcd438d0e47824541b22b1c64fba8c6c1482", - "dist/2023-12-22/clippy-beta-i686-pc-windows-gnu.tar.gz": "c1b16be465960d03658eb10c6d65ba363ecb75d17eee49e2da0d055a97d1ebfc", - "dist/2023-12-22/clippy-beta-i686-pc-windows-gnu.tar.xz": "e5997892281f08da9445b53c564edd678b7b768624bd29ef55a0bfa6a2022cc6", - "dist/2023-12-22/clippy-beta-i686-pc-windows-msvc.tar.gz": "92400c8693ba05a186c6913f69e838cd6668eec60864e5ff857e1da2cd8469dd", - "dist/2023-12-22/clippy-beta-i686-pc-windows-msvc.tar.xz": "550430a61f5e17fc30207b843f99a0f56d6fa07c6c458ab560149027b69599cf", - "dist/2023-12-22/clippy-beta-i686-unknown-linux-gnu.tar.gz": "a99bd3961497a6266e3fc9d4109a0c1304a6759f6d7062a5175afb5459658346", - "dist/2023-12-22/clippy-beta-i686-unknown-linux-gnu.tar.xz": "b8471bfaaf94b61523ac88db9c91c20f67bf24a16367795b2c925abff783fab7", - "dist/2023-12-22/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz": "601760057229682f332e4b005441111eb1573c7c9a9e286f0699019df3b2d4fa", - "dist/2023-12-22/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz": "45b7f4d75ed4838d3de0ed8c70d2ce6a248881c609bc4b883a549f11d12067fa", - "dist/2023-12-22/clippy-beta-powerpc-unknown-linux-gnu.tar.gz": "6c4fd05f37c0e95046dc87c24734820920a3ec62f3507643f42691ba349f2418", - "dist/2023-12-22/clippy-beta-powerpc-unknown-linux-gnu.tar.xz": "0aab738f846ad507138c0a5d40823a0db7d89ff130f24e550f337e085dc3ea8e", - "dist/2023-12-22/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz": "007d761b7eb5d5ed5911090ac55af2288e9a97cc4affc5ca488ebde7cc3ab0e6", - "dist/2023-12-22/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz": "ba9ecc14573a882641685cd6570e515a31fa9f3a9973dcef58f3db809b932fa0", - "dist/2023-12-22/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz": "efcf9a7bc03f8e984c6ab3fa2bc269fa5387168992c9fd2b8ab09bbd7111c6c9", - "dist/2023-12-22/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz": "1df14e1f3cf785c9cf5477b584fdf11f1f7e12431a5092cc5cdf6c2878bf4275", - "dist/2023-12-22/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz": "8527bf2c96fba74c09d7b1051616631d0b4e6bace8fe44c8c76f295c9a4eb55e", - "dist/2023-12-22/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz": "cc58fbe8d4d7d0011045f64025bf75e2042b7967b7fb1f297cfe8a0175197258", - "dist/2023-12-22/clippy-beta-s390x-unknown-linux-gnu.tar.gz": "c1e41ba2a77f6c0d33751b12522310bed37a032fc01947b9d78e8492a2c74ca2", - "dist/2023-12-22/clippy-beta-s390x-unknown-linux-gnu.tar.xz": "a90903f78305533e5315b3dcb26218a91e1733cda5e2fadcada80fe06b3e1a17", - "dist/2023-12-22/clippy-beta-x86_64-apple-darwin.tar.gz": "73839c078dbc472a8c5d87686eb7e09db0030d567079359f9a750a52d1d300b8", - "dist/2023-12-22/clippy-beta-x86_64-apple-darwin.tar.xz": "fbc52b8be57b032d04e885b325deb3c2d61bce1773fdd68e7b0889a1ba9a167e", - "dist/2023-12-22/clippy-beta-x86_64-pc-windows-gnu.tar.gz": "5a618cf8c09bec0e593449648bced16153b6783f98e41d685e5912418710fff6", - "dist/2023-12-22/clippy-beta-x86_64-pc-windows-gnu.tar.xz": "f6a7c30cb183c8cecf22d95487250c121d5fe1cacf2bc4e64bc160b4c4cdd566", - "dist/2023-12-22/clippy-beta-x86_64-pc-windows-msvc.tar.gz": "58b5ae0e2f46d4f7e64491a4ffcc9180e8616cc82b095526546942b0c6e43583", - "dist/2023-12-22/clippy-beta-x86_64-pc-windows-msvc.tar.xz": "aa146f4c9357bd167e4aed6919a1dc780fb57ddb9e83a4332442cb779cc61e1c", - "dist/2023-12-22/clippy-beta-x86_64-unknown-freebsd.tar.gz": "56b1d7fbdc1e47e8a31243cbbac747b1980b61d45f2daf260d49362f1413f3e2", - "dist/2023-12-22/clippy-beta-x86_64-unknown-freebsd.tar.xz": "c0e5ca26067fbd0279a36c03f68e07757817aa2207a69250224f6cb44cb9711c", - "dist/2023-12-22/clippy-beta-x86_64-unknown-illumos.tar.gz": "404cb75b4ae6f2f0f456f77b4e639ddd692c3f47d6f32b168b275dcc999db4c3", - "dist/2023-12-22/clippy-beta-x86_64-unknown-illumos.tar.xz": "b6c156a01ce3f64fd781669c351df169c0c0485b0282ec33d1c541e7990e1ef7", - "dist/2023-12-22/clippy-beta-x86_64-unknown-linux-gnu.tar.gz": "6a2e75e81a2678cb97a47e695b74dbbf0737cf615bb94d1679318bcbe77a0fff", - "dist/2023-12-22/clippy-beta-x86_64-unknown-linux-gnu.tar.xz": "6273b5b834766a93c2f65a3cf2283bf1669c1dd9b9f1cbbab497ea250532ef43", - "dist/2023-12-22/clippy-beta-x86_64-unknown-linux-musl.tar.gz": "bf4ec57ca170ccb4ab3fc4d42907418011e5dce9ff3fbbfc341e70744e9f0c8e", - "dist/2023-12-22/clippy-beta-x86_64-unknown-linux-musl.tar.xz": "d875bfbdc53bcca521707e3d08fe3b2c2c2dfeab81634c285228ca91278fd659", - "dist/2023-12-22/clippy-beta-x86_64-unknown-netbsd.tar.gz": "43ae50703b81f0fdf726b4790afd539f2d5a1dc56507df2726bee693f121550b", - "dist/2023-12-22/clippy-beta-x86_64-unknown-netbsd.tar.xz": "894acb6cf32ef66d2b79f24ebdbf37dc8d51f36d9ec326a294cbf4be3128ce77", - "dist/2023-12-22/rust-std-beta-aarch64-apple-darwin.tar.gz": "81e9bbeea89702fa3843a5e6bed8b5d3d5bb035d94adb335dfa91d084842fe17", - "dist/2023-12-22/rust-std-beta-aarch64-apple-darwin.tar.xz": "1457fbc52b8e8e6c751b69b6b5b3401bbac86f5aed500885fd86128963e6f8ca", - "dist/2023-12-22/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "e2574432b2b7e8b056f8d9864142be20fb83ec516bd27f7f937c04c2d9648218", - "dist/2023-12-22/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "91fb8193d61c741ee39e1429c8c6e7dc51cb10d5ed1d5f63c4572dd1941f26e1", - "dist/2023-12-22/rust-std-beta-aarch64-apple-ios.tar.gz": "6a1b2b7d583e105daca8294fbd4e3f17bcf345ab536eb4e74962a2efc65c9eef", - "dist/2023-12-22/rust-std-beta-aarch64-apple-ios.tar.xz": "3c54c2a8b24186c5100898a33837141119d77cfd5363acbb8508630752198208", - "dist/2023-12-22/rust-std-beta-aarch64-linux-android.tar.gz": "c9534e00a3b99390a80f23fe580bcca0eb17b8bf5c0731158e8e719ab17bef74", - "dist/2023-12-22/rust-std-beta-aarch64-linux-android.tar.xz": "bbb5bdcd5c698d2b089cf57dc071814aa91e51e76fae5a321b0f3bee837dcbc1", - "dist/2023-12-22/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "c862de6118465dbc356c69c23d1a755243d86945522cb6a87bd25321a5cf1346", - "dist/2023-12-22/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "f8fe6f868c007b3a32b2e20fa397d2aeaa18c1af52bfbf90d181b0dede6235cb", - "dist/2023-12-22/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "3ef167b633f128d5e8b28480169fdaa559c742db7091445b33b7225dd0ab6b17", - "dist/2023-12-22/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "d6027f6826ee84962b4f516204c5e48c4d11a738349d20071d71eb249ab19294", - "dist/2023-12-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "2885ebe19250cc078804941bd33d71ac0ba52c8f55c03db0a9d2f7b4b86501b4", - "dist/2023-12-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "fe587aec91d8586f5ea93783541b3b1dc005cc9fa92d07a42e93c6cf3570224e", - "dist/2023-12-22/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "b2278c605233768efdbf272b6c1c64b5770330603f0d6ad2e9fc725790c65593", - "dist/2023-12-22/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "40cfe524fc6a97a894d8fab0bcab8a00b72781ed1f8c3273d26e784162959d1f", - "dist/2023-12-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "77d9010f59baee9e88fc883cc085f04282b731cdabaf2e3eeb4ccbb8e950c526", - "dist/2023-12-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "4b633e678448b03b868dcd038a2a2c4dc78cb600324283b38ed942ee439174cc", - "dist/2023-12-22/rust-std-beta-aarch64-unknown-none.tar.gz": "901d032bf3dac71e52c727264daf42c923adcb12c771f135aef0aaa7784a9c63", - "dist/2023-12-22/rust-std-beta-aarch64-unknown-none.tar.xz": "dd7856ab1d91d92c09f65c8e6fdcada0ffaf63890c656e9bf5e7fe1c5f83cf32", - "dist/2023-12-22/rust-std-beta-aarch64-unknown-uefi.tar.gz": "c64dbbdd967193c3ed53c58e0545a93411e63c83bf0274d40691d1c5e5c58a2c", - "dist/2023-12-22/rust-std-beta-aarch64-unknown-uefi.tar.xz": "bf28490141ed88753548a96615742e7dd13efb6bf7ed98e7cc548409a79100df", - "dist/2023-12-22/rust-std-beta-arm-linux-androideabi.tar.gz": "aa84489eaaf4ae64a56f64a4f7e2240d41ae77e6532bdaf35eb2163632afd051", - "dist/2023-12-22/rust-std-beta-arm-linux-androideabi.tar.xz": "a3cf5b44498c85fbd8f66a776e5947e9b552a8b8110b19b4611ff042d040294f", - "dist/2023-12-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "aa4f3fa1994f51228853c8abd1080ac0804d7fe782a2c9a533427555c1ed5db7", - "dist/2023-12-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "72340fd4f0110ef21cea8e7a54182cf65b616e6c4834624b7971ad8a9c00b4b2", - "dist/2023-12-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "5b0b9392fcf9673e69954141470bd4eca00867a303b4f24354f27cf09da1cb8c", - "dist/2023-12-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "326ea10b82742012a648cf5eb9eb7b6e09087a324e3ff9955df5031233f45d6d", - "dist/2023-12-22/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "a7b7a2cde45cfc3d4d74031c36dcb8ea8214f4517e96b5a09bc46f898faf967e", - "dist/2023-12-22/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "b178e41c2ad6089e3448209cab7808e93aba7700aa3571f062dcdab74e4753b9", - "dist/2023-12-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "0de36da3bec6c34a6e56162b92f88b42ed76e596459a6d1416748b9fa8e8225e", - "dist/2023-12-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "381006c411b222254b5bc55302096678a47fd085de06615558dce5085da47f22", - "dist/2023-12-22/rust-std-beta-armebv7r-none-eabi.tar.gz": "464271fe1c2fe699167afbfe9cdb2ed2bb3a38671d616f6f28d6b7fd4fc72cf4", - "dist/2023-12-22/rust-std-beta-armebv7r-none-eabi.tar.xz": "13dc946ac5dd45104c51010bc8a0bf5af64d549cf6b59f8b8b0ac9b06dc5d0f1", - "dist/2023-12-22/rust-std-beta-armebv7r-none-eabihf.tar.gz": "2e01997df04b9635d840ca177e4ef379232955cc586e2196c26ea1e18b66f883", - "dist/2023-12-22/rust-std-beta-armebv7r-none-eabihf.tar.xz": "a11c1e8c52ba653e5c58baf886b6b1383c622632959d09321ba1dddc2a91caf2", - "dist/2023-12-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "b036abe1c19e3f86b80ee670196194ccddf0bfa5261d4ba9fc7994aecb5a487d", - "dist/2023-12-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "a9b90e4b43353feba58dfab424ae36441077fbb6b8469bc071c058f0bd85aa81", - "dist/2023-12-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "0faac13a81d60fd9315c6ea6c929b1fcb9366b23119b658dc05f10a0b4b2e2b6", - "dist/2023-12-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "62023710833973795681275bf34c45a309327f6e76934603c58b07f204e67a20", - "dist/2023-12-22/rust-std-beta-armv7-linux-androideabi.tar.gz": "f48e6eb32ae56fb09a9860f529cb65ca4168d068b6bfa6b1b3164590628ef635", - "dist/2023-12-22/rust-std-beta-armv7-linux-androideabi.tar.xz": "dad3d32a6314f7c9de8003476f9667d19f452a331e6363bf25c2ed255a8b0063", - "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "b8d045889b709783387752e6275c6818c353431bb7b9599e9aa88c6e373072c8", - "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "4750a55e19b27b34e59daa2d1b0f6655ba9d8c491780c785a7adbcc160eda425", - "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "829c608b0f7f4f6bf73688a30e51d69228b69a9487137751e0bf641f7e8e227a", - "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "4e4d1b1d10b1b7931e2a801cc3d3edb68c91d5f58baaf99fa2f88b9174f2b294", - "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "cab9b7f30fd074005c59ab5dd4d59c498367671373f5662047c8e16c19236141", - "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "b281e7c3a32523de34c2f7ed646d19f4f32b1db905a222aa1301f8bc57e312f2", - "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "ebed7143f8cbbf5eb2b99328c6246ecdc51905a90c4c832a13d76f6467e2014a", - "dist/2023-12-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "6c06418750cabc38f46e434890c2422df9be5177ed1f4b04dc7f67e45cad307b", - "dist/2023-12-22/rust-std-beta-armv7a-none-eabi.tar.gz": "06d20a34ef000ab381025c0458bd327d3a2bb13a77f3485334cdb63e51a7354f", - "dist/2023-12-22/rust-std-beta-armv7a-none-eabi.tar.xz": "741edc509d401328adcf462aba08744614ad655fa42f89c9818aa1dc715e2d3e", - "dist/2023-12-22/rust-std-beta-armv7r-none-eabi.tar.gz": "0a5c38d1a7a9d653e32750a5f600f1887422d4e90360b6f1d98df45084436822", - "dist/2023-12-22/rust-std-beta-armv7r-none-eabi.tar.xz": "ae960df5549284a7976129da79916287d84f1d9dece2bb8ada6a3f3cc3246509", - "dist/2023-12-22/rust-std-beta-armv7r-none-eabihf.tar.gz": "9280fff8012234559ad644edbe9827c2ef6931d95fa96b5f6a4aa7321215f5d2", - "dist/2023-12-22/rust-std-beta-armv7r-none-eabihf.tar.xz": "3bed6d2a89baf609089c431e73d36b73417541f63c8f2bbb190bdf706cd85e93", - "dist/2023-12-22/rust-std-beta-i586-pc-windows-msvc.tar.gz": "b8bb7b950134f5e3ba3257ffc55d2b0e4b483955e74f6a146017c1c818359ab4", - "dist/2023-12-22/rust-std-beta-i586-pc-windows-msvc.tar.xz": "3c3b4771cd51159d35cf5de21e9bf625453972a53207ca3e6a027901b3eeb7c8", - "dist/2023-12-22/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "ed89e574db830d882f1f12f9b570bbc5f4c89776808ec05cbfcb498eb947e6d2", - "dist/2023-12-22/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "8c32678710cec0971aa6f740cbb525c0c174f6552d181466b7d49d5822d671c5", - "dist/2023-12-22/rust-std-beta-i586-unknown-linux-musl.tar.gz": "2ebc2381b980637844cca7be78a01d204472328897bb02c28b8b5c32bd8d20bc", - "dist/2023-12-22/rust-std-beta-i586-unknown-linux-musl.tar.xz": "df48e6af6cc9df2fba7af56b4cccd07e53a0030de964c11e83b7cdaff1bff4f1", - "dist/2023-12-22/rust-std-beta-i686-linux-android.tar.gz": "25e6cadd083ba7f02525e411677ebf8470bebae19c0f5fdba453140ddf97a3d1", - "dist/2023-12-22/rust-std-beta-i686-linux-android.tar.xz": "bdc722479c73b6fcc6ba401d6f747acbfbdebb074e911bd44a20c8c3ce8192b3", - "dist/2023-12-22/rust-std-beta-i686-pc-windows-gnu.tar.gz": "6a8b46606ecb46d16f2d45ae82faaf155ad617b1b81259eed93b77a267b5265c", - "dist/2023-12-22/rust-std-beta-i686-pc-windows-gnu.tar.xz": "97c58f4e4cee06dd38ad9e3a56ce505434ee77f0f0db30432d04739d301a194b", - "dist/2023-12-22/rust-std-beta-i686-pc-windows-msvc.tar.gz": "1012704d42aaaddbf0679013ea578245e88200afd55d1d510dbe58bdd14b8ef9", - "dist/2023-12-22/rust-std-beta-i686-pc-windows-msvc.tar.xz": "cdb291df9fc41e038b38a3a421b791a2c39be3bc9686c5d6e93cbaef95c2ff6b", - "dist/2023-12-22/rust-std-beta-i686-unknown-freebsd.tar.gz": "20df3466ef1a82ca986a3239efba9d984535c64d5663f2b3b92b9d6ec2972b25", - "dist/2023-12-22/rust-std-beta-i686-unknown-freebsd.tar.xz": "6a63dcb9f7312432c6bf290dc3fea10d56a17472cab65c7d82fde30c800d8b5e", - "dist/2023-12-22/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "8d3ae5e37ab866b93bee661773301956d8e6e2294910d0ff04f782f2c7271dd6", - "dist/2023-12-22/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "9963bba2883125aded9c6639dda498c3effd574fa032d2268455948df3243979", - "dist/2023-12-22/rust-std-beta-i686-unknown-linux-musl.tar.gz": "64e13948dc71571be5c3a4e367d961bcc0bc38167680e86a55b2d1357a45b7ba", - "dist/2023-12-22/rust-std-beta-i686-unknown-linux-musl.tar.xz": "ca54983531703de8f7350e00bad2cde13dc996d9de1c0ca1728b50a015dcb344", - "dist/2023-12-22/rust-std-beta-i686-unknown-uefi.tar.gz": "a4e3c395607d9ca189c130e371c49ba0a08d1974c56c656a23870d0ca08f0cf7", - "dist/2023-12-22/rust-std-beta-i686-unknown-uefi.tar.xz": "20e6ceea5246322840b3fc76b01b16ef32d829ae4e587a052512c39c3c3babca", - "dist/2023-12-22/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz": "6e4dd7fa56112a879917ea24bfbd45dca625ee812908867e427f23d56deb910b", - "dist/2023-12-22/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz": "23862a72211645d29557d3a1dda63948335d15a9796c139a0676124905e72906", - "dist/2023-12-22/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz": "6abd7c64f58bbcbf04b643a9787f0fef1fe80b89b82143b6251b57afa560cff0", - "dist/2023-12-22/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz": "53fa4d33241b73653523810e441bed53dcac8c3fb7b7de88c125cb8ab8eb66df", - "dist/2023-12-22/rust-std-beta-loongarch64-unknown-none.tar.gz": "bb94b1d2391e11f268c0e4c127c06b356e9d79aaa6c68862dd7f97a8fd756e61", - "dist/2023-12-22/rust-std-beta-loongarch64-unknown-none.tar.xz": "663d531002d8be8e61fe4b9353a53b3a44056056b18bbd76749762a40416f7fa", - "dist/2023-12-22/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "3a25dd389b4501e9fe76057b70cb120e1d1d3caacdce82abc834297c487e50ce", - "dist/2023-12-22/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "6be12fd4e79600805cd6d04a5bd1d236dd7f12832d4407d3fcd72ce6bd84101f", - "dist/2023-12-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "6edc5d7fb15d71cbd097a09eb264b92f5b1e55f7ef0426c5c8399731f4ebb70d", - "dist/2023-12-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "beb17c9ca9e789ced8c4046135cde5b613a0b41c9b5aeefb3b7ee5d25701add6", - "dist/2023-12-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "6f13eb2dac5f4d59dbe44a4d862f94f763fce0bf4ea0f128c0006c04b922f294", - "dist/2023-12-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "75e629ca2f90c7e8a78fc16d13cab337816feba3e30564e26b3d38f13b7dffd0", - "dist/2023-12-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "e2ffac9803e2c604c56649096e734cff0a53632883c05cb9f1fd79f6ce420162", - "dist/2023-12-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "85e0193a7bfa284ac4dae84f4079605ba5c2f7c7c2e4f57ac74721aff44d05b8", - "dist/2023-12-22/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "41c57fa6eafdc2bc4389da8257b57e48af4250377b02760d06ebc38c83086534", - "dist/2023-12-22/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "02d46a445f52d078982866ee9430f8020e15d82f58d8f1edfedcd2f0ade51f36", - "dist/2023-12-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "6fdfd4e5ce8dc13cbce7cfb1543dafb54e80ffee0ed40935c3734787519a9673", - "dist/2023-12-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "5a645c8703ba10256605770ffdbb8abbef62746171f19edbbc069d02be501529", - "dist/2023-12-22/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz": "0cdefa18bc524ef66ddabf83fa2efceced02ad1a5271c9d95f91ec01178055e7", - "dist/2023-12-22/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz": "388dc6fba431953f581388d95cd860224e2d1203811ec86e66aca391650ce053", - "dist/2023-12-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "b3f756e69c0c1f257869cfa6ef239368a512c81b59c18a69851b2e5a73ec484d", - "dist/2023-12-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "61d020bea165d8abc361335e393c2c3bb1e59b6fdb0f6f65326392ec7dc3ea35", - "dist/2023-12-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "94e83a4ba2d141e9fc0d824a6f5e077796fd53b7b32578a1bf6e63cda1f9ee4d", - "dist/2023-12-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "9679bfb1664e6d14882e68940fe8960773f56f4867904a3259189f9eb96952ca", - "dist/2023-12-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "807b24b0568e83cc807e29ae6062a766f72ef48e12f9f257d78f6db4b9ee5621", - "dist/2023-12-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "d3898d851c5f728a9894e7755d0b6ff06133823b1773e5c80b29155f6e1152a6", - "dist/2023-12-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "9ecdd32e65c85130f8a1c82c8fd9d613a4c59b1e4fafd01771089a052d4a481c", - "dist/2023-12-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "a6b5ef2065cd5cef17e48791dae08090b755c00caca4efc1aa5eac9c2783e92e", - "dist/2023-12-22/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "df756fb3868a3ed347a92df37fc4aac696560d645696d5d86a15d84bde257546", - "dist/2023-12-22/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "777dac6ecbefe1e266c7bfd04644f428ae25318e80137a36d404009442ea208e", - "dist/2023-12-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "6802baa472bbf3f766346f24cf7b001cf87ea7f974bd1e1abdcc56b4c2b39bdd", - "dist/2023-12-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "5db8e7c4904c55a5d362669375bf72482e27042b7a156bd8b9d1c322b2bf521a", - "dist/2023-12-22/rust-std-beta-sparcv9-sun-solaris.tar.gz": "0ddd12279d34cc6190e0b1e163cee51d94be809fefa4adf801fea0f217a3519a", - "dist/2023-12-22/rust-std-beta-sparcv9-sun-solaris.tar.xz": "96ed998c6f254c9a5fe560474480db553cd7428cca65ba9a7732136bce191e48", - "dist/2023-12-22/rust-std-beta-thumbv6m-none-eabi.tar.gz": "aa36baeedb2b567f75a0fa550f2ebb507f135d4fe784343a576216237a87d643", - "dist/2023-12-22/rust-std-beta-thumbv6m-none-eabi.tar.xz": "0792a2de23b8c8e552565bcf691ca604760d5201ae247ec14122df11d3819f30", - "dist/2023-12-22/rust-std-beta-thumbv7em-none-eabi.tar.gz": "93a045ef6b38b1de7347880d299dcaf6f721af301fc811e47388b0b94c6290a6", - "dist/2023-12-22/rust-std-beta-thumbv7em-none-eabi.tar.xz": "c6f13b394ad21bd6058fae6845543d5f265e8124fd43ce16885800c4bd62a370", - "dist/2023-12-22/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "8ee5dc194cfd20626671d6b7924b68246d4cc820ca669d8fa9778086b043c3dc", - "dist/2023-12-22/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "f702b3ece0c74a4391e4ce954456babba8d170a1ffff438222a9bfd22df139a3", - "dist/2023-12-22/rust-std-beta-thumbv7m-none-eabi.tar.gz": "3cd3bc99d559a56ac8795c3602c59652877bac85e0a847c981c9ec2b1a86039b", - "dist/2023-12-22/rust-std-beta-thumbv7m-none-eabi.tar.xz": "0d8132f6922844c017fa0c0c3ec463e4a55e3fed7603fb2e8374ecf5c1405e52", - "dist/2023-12-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "ab1bc71bd1b00c0d38a3a0a3be1e5fc5a494219d2d37181da53b042b3b896c67", - "dist/2023-12-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "5cd28af392967e42e43f51233637ff690a524d840c50a328d5d52c594977b316", - "dist/2023-12-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "647b9db01306e225ee1867e194531028215a9fdb02b3f8713c07c39dd41d0c85", - "dist/2023-12-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "9a6ee652c9e15708f2aab76a20918f414875a8a52323a49d727b58aacc22d1f0", - "dist/2023-12-22/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "c16e452e889c9d56d417c871ac4f9290275df11563d458e1abc52e4ac3db0414", - "dist/2023-12-22/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "23a74836c303dc91e6ed9fd2078e130184ac19ac230946bd95e59c53666534bf", - "dist/2023-12-22/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "c8d01ed9cfe9938ed078e3f14ef9f4fa5367534ebe115f243fee8095ef3c174f", - "dist/2023-12-22/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "a24e99a9d45b19db342d5c5f903ad90a27be9c996278b76823121fd09d5a298c", - "dist/2023-12-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "e417661f5c42593e75b09b4a3531965e46f5dbd631809d6364e59d47a894b1c3", - "dist/2023-12-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "081ec9d8504af85ce93bc60ae5f3eaad8bd06864b084a97911e126564720b3f7", - "dist/2023-12-22/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "1df5182c5103454eb69f05b3e6c9aefe1374e43659f3e4cf68f0ac07052670eb", - "dist/2023-12-22/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "863278bd1a5281e6b04232e35df48a1dac7e909d3b51922cb328304cb6db9af2", - "dist/2023-12-22/rust-std-beta-wasm32-unknown-unknown.tar.gz": "6d80b9f8875f677a8e472c431d6df15babba2a9af62622da5a073ca9da467f69", - "dist/2023-12-22/rust-std-beta-wasm32-unknown-unknown.tar.xz": "cc9bf2bd9db87859e17ffd0b9a3ffb8c073e521fc035b75639a7e77fd04a210b", - "dist/2023-12-22/rust-std-beta-wasm32-wasi-preview1-threads.tar.gz": "7b2db2cb1fb7b35cecee218780fdc223464522bf4e5ac0e3c3342396bea77755", - "dist/2023-12-22/rust-std-beta-wasm32-wasi-preview1-threads.tar.xz": "ed893747e7165c97b2a2abfe4793493056cda613040eb5783ba0c4a57560f42c", - "dist/2023-12-22/rust-std-beta-wasm32-wasi.tar.gz": "cfd98053e598d830055a35702de43866b6c94b48a36c63c1683a302482bc4cc4", - "dist/2023-12-22/rust-std-beta-wasm32-wasi.tar.xz": "f57bc02b197d8f4c0d119f4ecaed6c405cc85bac7d00a55f2dc39e97ebc8411b", - "dist/2023-12-22/rust-std-beta-x86_64-apple-darwin.tar.gz": "70405814aefa163d60eabc777b882233797d075ef5a3052285a6aa4acf7c9c0a", - "dist/2023-12-22/rust-std-beta-x86_64-apple-darwin.tar.xz": "c26043ff5bb98223083aa58f659f3ef069f5cc97e5f3c1a62664197e3d8bae66", - "dist/2023-12-22/rust-std-beta-x86_64-apple-ios.tar.gz": "37a2b083652163adfd848872c7b42570ad6fb365ec679a1c89a8248c517021a4", - "dist/2023-12-22/rust-std-beta-x86_64-apple-ios.tar.xz": "cbba44d048a5c48dd4162dced5414eca2416047f2387708e46a2045553a45fa4", - "dist/2023-12-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "17e93708f7c0b4328d24db2ad2a82c3001c1bc03def829b7e182e5407fe74b82", - "dist/2023-12-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "761b39d8ab6b9061c0afd4fa2faaa88c7cda6322d615e57863b51a5a2826d70e", - "dist/2023-12-22/rust-std-beta-x86_64-linux-android.tar.gz": "f45d09e9a6c383c6cf9cff99d0046639d26636be78e194354e951fa99388e479", - "dist/2023-12-22/rust-std-beta-x86_64-linux-android.tar.xz": "fe323b71cfbb300f881d05879d03491aca507a644b261c16f148690dbb20a01e", - "dist/2023-12-22/rust-std-beta-x86_64-pc-solaris.tar.gz": "0dce2b6572bde41461086c6394121de7b97329f8192562684954542baef1ff05", - "dist/2023-12-22/rust-std-beta-x86_64-pc-solaris.tar.xz": "164fa2c995df0d6446c218e037025de1b225d92a51155b5b54328f67493e8202", - "dist/2023-12-22/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "848e55f4583bd589ae457d37b8d7367adafc24b87c35a08065114b3acdd731f9", - "dist/2023-12-22/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "c900770454c026b80f9b80bb745a84381f91492d552fcc7ba013e5fd46b2a63d", - "dist/2023-12-22/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "577f8db6e8654e9f3d97c83bbfa2eaa89fb0fe8c9362b976b9796297d189b6a8", - "dist/2023-12-22/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "5d2523bb1b31b4b43c527b8307ac8e00ad7e957fa652fe0628cb8e6796404d20", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "5a185ac2058969ed6aedbd864cf7037fe999eacfb9e11eb21f89696d6341741c", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "7f6e73e0cc5fae9b9e9142427decf8c4d48289033412d452a40c1a345f4311a8", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "c1974528eeea3346e070192f3729fbcc4fc9d6bbdb0c0b9ba73763758a695124", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "b4da6ab7e3bef63c2f381f7506ff0f65f302e0ed14d4f78016968b0cff3a5f5f", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-illumos.tar.gz": "3f50aa342f03ad5235112560fe0f3c64f5139d09291e3ab6859d8169ff43d631", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-illumos.tar.xz": "799eeb21df5ff213c8ec1f6250497665924b865b34d9c1a5f914eed48255278c", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "ac88a7247dec36da73d30cb58c067cd1bd6c5bc70e5820d031963fced0907c28", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "3de39c55f71a295ff38bce9843965309a40dbfe1c888f13dbde3935d26ebdfc0", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "eeae5e12254e54c87ed818e8449c2489717d1c3c25858c6e8a1a7502e57172e0", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "0d54e6882ffce573f70954d98e1f0c9f0758c5d6262e546ed95c055798d26bef", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "da056f4b1d8544382b90cae7061be549b2e06e3e880feb9d788200c022ab297c", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "f340687b51519830a1e566c84c0114581c817ac32e80f90b8baf0fbe960fdd5d", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "6ea1fedb7db6f51b79164ad39246dc2c86f743346feb760f4835c870be3931b2", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "7fe78fc5dfcb2d85b521dba2c9640233615fab04a8a1b8b27a2e0efabc5b5b60", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-none.tar.gz": "8eb08022fd4b78b50784ab9671a81b69c899ff2e73d9ae08b6ea44ed018b2c8a", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-none.tar.xz": "6ab096ba0bad97de603be50a05e16a33bffbaf4a97853d9f838721075b18aab8", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-redox.tar.gz": "84632635271947ff93b1afdd35779e7c307182d964e3b2aff60e57c0ab02a9eb", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-redox.tar.xz": "b21150ef965377a699410a0350395e0daf57e3ab8a3d90654482b17960dfd26b", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-uefi.tar.gz": "7a703ac3b26a1ec21a64f6517f03938e458db5d46977f02f9359febe7e3e4a79", - "dist/2023-12-22/rust-std-beta-x86_64-unknown-uefi.tar.xz": "83607ae59dddf457d655a2e60ad6d7b500a144fec4d41a7f684555204754e2d2", - "dist/2023-12-22/rustc-beta-aarch64-apple-darwin.tar.gz": "4988d34a6c048ee278f0d675e05260a0ab7f635c09c8ac6964ea97dcd244b9a7", - "dist/2023-12-22/rustc-beta-aarch64-apple-darwin.tar.xz": "a5a218eea6a3edf9b8af70046525fa6259ebf391d6e91f0630f6ae441a227a82", - "dist/2023-12-22/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "0980f8dfdc522146433cab04f2b83378b0c5bdb632cd02e280469ddff02e8bbf", - "dist/2023-12-22/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "25cf2c04a79313040860831dcce67a123ee362e09bb185a16af171163ec8b087", - "dist/2023-12-22/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "e21656abc9b9111baf5fdf9aebbf29b4ac8123c163dfb979b5f047c530020f29", - "dist/2023-12-22/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "3087de6766ffa175dbf7c53153b24cbc29db1fccc06170fd70bd3dc3a97bae62", - "dist/2023-12-22/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "e2464b82f2e1c4450d4f9f6fca8c5d2315e6227651d7485cd487d39fbe7f940c", - "dist/2023-12-22/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "9d4909db94be068ef943eba3709195a028e3928198a87f38e72a6fe013e592db", - "dist/2023-12-22/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "9217ecb54faf8c2964476c3c7a9ec6955b276c4c5b89e5ff13d76fe4863ba8ef", - "dist/2023-12-22/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "fad7556560de459c4cbb59071a35746ee520ca15b5972e926039d46847a47888", - "dist/2023-12-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "69d94023fd5d8a48873ecde6892ee1be354fb56a91c9bc16b32d7b8bf090ad07", - "dist/2023-12-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "14ab98c13452b8b7e5ba8853b957355487c61f0a89d385c2ec8d16d8fec382aa", - "dist/2023-12-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "85190846421ade8edb5da369977598641bfac215754bdbdceccb181adf49d2b4", - "dist/2023-12-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "5b0de94607e7e1192463dd1c8615cf035040cf1a51ccf4d08459f659e14aebb4", - "dist/2023-12-22/rustc-beta-i686-pc-windows-gnu.tar.gz": "dfb48dd8d18099b63eab2e0f6e01dd520e6d137725596af611d68092f7d2228b", - "dist/2023-12-22/rustc-beta-i686-pc-windows-gnu.tar.xz": "f9bdb3dac14ded817c6f406767ef140838cedd74b9b2b6daed6419cf096245da", - "dist/2023-12-22/rustc-beta-i686-pc-windows-msvc.tar.gz": "a01af2a20955790992eb248a290161184429d43c8ddd65d8fd18dbb6499edd6f", - "dist/2023-12-22/rustc-beta-i686-pc-windows-msvc.tar.xz": "334b999f3e7c6c8deed7807e398338393f32c641989bd61c631a79a3a7441d67", - "dist/2023-12-22/rustc-beta-i686-unknown-linux-gnu.tar.gz": "334126bcfc14e8ffa5df43c4265b844db5a2b72458f5b3328f6863ea59580b12", - "dist/2023-12-22/rustc-beta-i686-unknown-linux-gnu.tar.xz": "aefe562ff063ab5eea83fdb58577e6ffbbf9cdf111e5390ee29640e5169c2c7c", - "dist/2023-12-22/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz": "1a9eea2e8fa598c438de05d33d0af4f7b648fc50ff25013b3926c6125dc75542", - "dist/2023-12-22/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz": "1f0d707a8d96071b1154ff1ffca518a9573d7c1d95835bd35bc3660a8a4d6cb8", - "dist/2023-12-22/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "6cf83e99462198dfd6fd4b7d5dc4ccffbbfc433d5e3b082028420ad7e2da6144", - "dist/2023-12-22/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "295e22e887c9b2d686628fc927d6560e0f71f2330517242d36d1d98159d43a6d", - "dist/2023-12-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "3b970b0cf7243e766a773c9f30557d8d20da668467b85c5cc60fd2f7e927cb09", - "dist/2023-12-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "dd4470357d4351081c9c1526c6a4c66642b11c88f8ac194ae7f0414593b2e561", - "dist/2023-12-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "7684ac7d4a96678d599bed67a11338531f09b500769d94b2b70cf1b1854a0e33", - "dist/2023-12-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "b9f98f6003605d179d298ca1080448784601f9648817e5c84371e54eaafcf36f", - "dist/2023-12-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "376b86e4cb259c5c85286203c00405570a77346441037e175c631b2753f4f421", - "dist/2023-12-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "d4d1b511f2ce2dd2dbbcdde760879b0ce87ac1c191f73d9b264403c328d3c505", - "dist/2023-12-22/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "b46bd2d835f98a293f259d90659334bd289cfff34d4fac544be2add0b4072014", - "dist/2023-12-22/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "6c3e19a3b0dd8deef825f9c6ecba405df6b8a390f6366991c1947f09401f7192", - "dist/2023-12-22/rustc-beta-x86_64-apple-darwin.tar.gz": "5c735a5d0ae69383db88bbc0d7ea5a6f2300c82ce81d1a4b4f987157ac03dd6f", - "dist/2023-12-22/rustc-beta-x86_64-apple-darwin.tar.xz": "5f483a58253a0d6fa58503bd5bf58f8a79c32e49228bb4645a7931c61465d27e", - "dist/2023-12-22/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "ef3db1dbcb14174dc39670810c417b6395e092a92622d49d9bcf4074a02bd32c", - "dist/2023-12-22/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "d73c50be69cc0a817273c75ca86ba094509c9168bd445cfe81690bac48a613a7", - "dist/2023-12-22/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "4476c15df06fdfaf90a426a438cc10e5c0afb4e15ff4394d501cd8f8202f95a5", - "dist/2023-12-22/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "8066766e26df9171bb66e07001c1f3d279f84f48e90ac7cd80ef0439e6de29bb", - "dist/2023-12-22/rustc-beta-x86_64-unknown-freebsd.tar.gz": "7128054459be36bf501225ef22c105edf599ed4732829bd35c20d6831278c799", - "dist/2023-12-22/rustc-beta-x86_64-unknown-freebsd.tar.xz": "a4d6429df3ea63c4f58af3311f3cb986546932a73ae363a768ea6cb630a9b59c", - "dist/2023-12-22/rustc-beta-x86_64-unknown-illumos.tar.gz": "adbb9d176605339353b9c84f53da7301c262966a43e9c25fb5dc408591a5e30e", - "dist/2023-12-22/rustc-beta-x86_64-unknown-illumos.tar.xz": "69bacc4bdb3466862ab86a524516e88e1af3e6379a6bd5b38a5d872534d7584b", - "dist/2023-12-22/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "49b58d45a5eeed663619b6976ef5a97d1d69ee6d1426046f5cf352ce2730aa81", - "dist/2023-12-22/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "9896fc9d8a363a1684abc892f70f71047f43a27eca362911cc39474582a3df7f", - "dist/2023-12-22/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "f5e9ea5090e1a1f1478c1b6c9f4c2975955630717d00304105e7c2b4d30b5793", - "dist/2023-12-22/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "121f57a07ac943c6d48d4519d863e873501edb57d04d8e2842c847510dff73e1", - "dist/2023-12-22/rustc-beta-x86_64-unknown-netbsd.tar.gz": "0ba119cb9e004e008daf53d6f2687ac48b5cadcea81c69f8b7a0f967be0939ae", - "dist/2023-12-22/rustc-beta-x86_64-unknown-netbsd.tar.xz": "81b8265afce99ba1fd7db811611da0f7296b066c2db0f4e65bababaad3f04ea6", - "dist/2023-12-22/rustc-nightly-aarch64-apple-darwin.tar.gz": "101130c9df70b39a6eb8b63ce1c457d8060c961d4ab845f4edb7b02e1b68e5e2", - "dist/2023-12-22/rustc-nightly-aarch64-apple-darwin.tar.xz": "ac84e13cc222d4bfc6670b2bec5407c77792ebf82c51e812ceb3bc972a9cfe24", - "dist/2023-12-22/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "8ca4faf6ccf792534c95b8091786d8b2b79ba99bfcd2537e2cb7fd97a3fc46ba", - "dist/2023-12-22/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "97db2f021e7aacdac1c81ab72264eede6cb72cd83f1c317ae84a3ff39b05584e", - "dist/2023-12-22/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "c274e2470c8cc801495f7a656a10250024173d5927b7ffa2e9251e0b776da5f4", - "dist/2023-12-22/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "024917a1f37a2db0bc8519dbcdecde7321c5d460886b76817791ea484595c44e", - "dist/2023-12-22/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "bcd861c8f6c7f7355f7d6196c405061e90a2907adbca52400b8dcea7bc9b42f1", - "dist/2023-12-22/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "19c52eecdf2dd4fb0b6a5c240c440c6d47148e7264d7efaa77ac484a8429802b", - "dist/2023-12-22/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "38fe3274425db7e9142530be734b473fb5742ea10d05deec24168730d8e65d0f", - "dist/2023-12-22/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "1fe18e92829eb2b87264dee5631329804a7da8177cb15043fcac27c1913a0b89", - "dist/2023-12-22/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "41a723fbfbcc9c003b59fe17e0bef28d69ed89f165c42afcd00e3617a7da6915", - "dist/2023-12-22/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "7f834044d638e8e15d8900c38b8ec1fc6e4ef98efddf3ab7342b24e59525c6a0", - "dist/2023-12-22/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "814402e50600573b6fd79ba3a84fb8c441d71eb2f3eff0257565fd514830ab10", - "dist/2023-12-22/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "2f2650f7ad3d86dd63bd887f6e5e5e5051ffdeef672ee8dbc96c738acde79e21", - "dist/2023-12-22/rustc-nightly-i686-pc-windows-gnu.tar.gz": "6cded96f43ea2aeb2c15ae5e58521301110d6a2f8e8870ff2d6e5e1d8d5d13ff", - "dist/2023-12-22/rustc-nightly-i686-pc-windows-gnu.tar.xz": "2682f11a1375b1b93a9f7110f121340a4994f736c263d37037fb29a5b6df69a1", - "dist/2023-12-22/rustc-nightly-i686-pc-windows-msvc.tar.gz": "9322ff47c86859ba405d6584407b3ad514e6ee1b7a47525a0e20a918875defca", - "dist/2023-12-22/rustc-nightly-i686-pc-windows-msvc.tar.xz": "1dd7be7fd7e51ee9e8c053b2c7c222031aa436497e591ad87a5ee2f2289022f5", - "dist/2023-12-22/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "35e96a4ff0436ed31bb62e06b8898e3048cf11d3ae85f1097741f6b6d2ac0304", - "dist/2023-12-22/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "a8d4be1c79031e6ae2ebf594929cc4cbdd2e0655110ce2a9983e1adee1474b3a", - "dist/2023-12-22/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz": "7a2b50a5309770784a47662b5616026e735cb12ebd785c578c3a16965167ca3b", - "dist/2023-12-22/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz": "8cf64de71cd3566683e487832c3f4143f306d4fe9658fa1e16b794d3ee25552b", - "dist/2023-12-22/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "f1890a35bb23fdc85736e18a7230eb4ac68f1d1772a8b1defde1c6fc53b547db", - "dist/2023-12-22/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "5a1cbf44eec83fe1172cef13a38c2f23c2cc2753847ad9577b4cbbc0793ba96b", - "dist/2023-12-22/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "b5e7b7d42a233010142806953ba10820f45be90574c885d9218d41865310d606", - "dist/2023-12-22/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "073c15e2528c30fc51e7964649cd84fc54ce7d6e71f32c4bd5e25028cfe66f01", - "dist/2023-12-22/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "0a579f70e0e6752e5ee257fcc2c77a4986d608262089427f3ae38ad1ff1d8864", - "dist/2023-12-22/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "d9491f667829d36df5db42ad40e0ee6bd0f5d53d854d8648462c357fcc709ca1", - "dist/2023-12-22/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "01bc45a98dc4791b14498d58681a894e3646ea0588fbaf23465dad1034cf7dc4", - "dist/2023-12-22/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "4eca6ca78604697090e48c262aab864a14cdd15607272699cfb9f93b0fb3b9e7", - "dist/2023-12-22/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "c77f35e12eb4e664c3f59575401c20071e3489de8a80e47601321823d1c79b09", - "dist/2023-12-22/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "61f3c129cfabbc5e814ea0ebb183d6674dafa593f56c017262aa60d241041983", - "dist/2023-12-22/rustc-nightly-x86_64-apple-darwin.tar.gz": "2ef95843d229f3b5d5efe1d2cd1cf9a5d2a5500b9f8d00a6ba5eef55a8689643", - "dist/2023-12-22/rustc-nightly-x86_64-apple-darwin.tar.xz": "ee3ac1b167da164384d1e3ac8b6fbde9668b68705afa1a047a1049e90b5bf66d", - "dist/2023-12-22/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "a98e2f3976a5b64f802616c045861571c61eef332c7206e0bfb10fca580c6bf6", - "dist/2023-12-22/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "549caf445a9b4886c47bdf82628e365afe8cea59739a3b41308c828c4eb9e7e0", - "dist/2023-12-22/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "db9bb6ae1770056cd787162ab24e54bad0dc2c8bd2861c8c3ded642f9e963643", - "dist/2023-12-22/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "bc410fb240404e3c193e39667485919660d58b7a5774301f9d0cb21ff744eaa1", - "dist/2023-12-22/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "e113660740b61a1e20d72813e7ef076b7a894f5db3576abae812f501eebec409", - "dist/2023-12-22/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "a0bacdf5523cbc5b59f49fbf99eaa571609faa4aa8765a09f9f091ba3f4f5686", - "dist/2023-12-22/rustc-nightly-x86_64-unknown-illumos.tar.gz": "29f8ee90239986050d96d1fbce42f0ec104653a44c49d050d5965ebbf8e94ff0", - "dist/2023-12-22/rustc-nightly-x86_64-unknown-illumos.tar.xz": "c4c04dc8d91f53db3420114a6020c76771b6dddf43f322ec0575c69a6bba7be8", - "dist/2023-12-22/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "f40e5ba829e2e731e44fa0452433cca7ca0f41d717f45809c32804d172ee3e7f", - "dist/2023-12-22/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "5ca6206e9c4c7274f988026dae50774cf0b197b016d81adf15ca29816f9177fc", - "dist/2023-12-22/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "40c913469dbe202d27fc4f3f9f8072c415d2d788d62773de486f0a429d17ac21", - "dist/2023-12-22/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "bde66e4076b615d14e3e799604c8904d4506854e03cf5ac2be39a5839721f1a1", - "dist/2023-12-22/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "5538e8852c23f7070af754e1b19b7c685857f57cf33ed9ec9263a92bf57a14f2", - "dist/2023-12-22/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "2d6558de20de87ce02de647115fee7bcce5f017baf2dc4593a1c91ae53281813", - "dist/2023-12-22/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "3d5878aac23fb995cb29aeaf2579b30ce96d5f3571f53e21e20094d4cad69800", - "dist/2023-12-22/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "80866c0ab8848d31a250c0904222ef0dd19ef45fd1f1a48ff381c914ef6c1ab6", - "dist/2023-12-22/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "4082f5613caab9091d4134dee83f5cfbe401d59a2a1b2000f28c7094584f08dc", - "dist/2023-12-22/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "94230b1d3582e83967306da3f869970d190fae1c22ce61fd5708f8591165d9c7", - "dist/2023-12-22/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "7d59a37a6fbf86c16376f593a54adcbbdf214aa8d49561fd7337d27f437e49dd", - "dist/2023-12-22/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "6c6be9be98fe01756c077cd3f6ef23104e681476e0a4de006223273f3f9a1fd3", - "dist/2023-12-22/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "706b95856289e67c29999ffa4e3afce266c017da8fc66db95695571ae4560ecc", - "dist/2023-12-22/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "9f768f3c40aa3f9d130c4725eff036e1503b372161f136878f4877db44e3600d", - "dist/2023-12-22/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "6e276261f45d28a2110d3de8ae3de4888d041c831d63960bc242e0b0b7765dd5", - "dist/2023-12-22/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "e9b4bfb081445a4506f10249c7441f2d0424778f3ac0fbf5b5ac3b87ba9ef66d", - "dist/2023-12-22/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "f1aec801b69d4b67a58ae93741ffa018d0a49943e593592139abb6b217561366", - "dist/2023-12-22/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "f23b01ec072adf8c29943846ff90f2a1ced0619dcf9c3d517f4cfad64d726e02", - "dist/2023-12-22/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "b61d903932f63625e4163f9a0b7e83606bfdfda4706e68d9387af62f611a32bc", - "dist/2023-12-22/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "21bbc61820a28141db13095dc778524dd4ba1981d6c66caee45b0b72f7267016", - "dist/2023-12-22/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "bf8307795424917a3975b1cf4b0b490cf80a17154d66df2a8d869d1a3291ca5e", - "dist/2023-12-22/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "b651f28f2dabc67abaf2ee7e17cac5508f400bab82f8267ef9ae2ce2399f5c5f", - "dist/2023-12-22/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "deacde8dd4f34e24d981a585061922708af11d4638733eb49dbc1087ffd901ea", - "dist/2023-12-22/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "cefc12a2fa8b66dd66265d159b3ee16cfc87a8c183d7a158e4e610fd747cecb7", - "dist/2023-12-22/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "4996bcacbf363fd93440ff18eaeb09081d1e9e510ddcebc5f84c2a3292d5d0fe", - "dist/2023-12-22/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "dd6b37586054ac9ab7714f0712e1cd833df33820fc661fa3ffa52cbcaa31073b", - "dist/2023-12-22/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz": "2fcfbc0448df994daa9a625bfc75e69054105a6c120beefa84c3843ab36dc4d7", - "dist/2023-12-22/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz": "94282e425b30fff90c9429e1f0d2aa5cc69094a147c8dd4521b30fa98eade494", - "dist/2023-12-22/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "25445ecbc332fd305e81075c18c27efdf2027fdb2d263f921eb716cc3ea60609", - "dist/2023-12-22/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "9a55fa07a1a9c3b0c31b00d9b33b0ff727046b4f322e6297ffa290e7741de015", - "dist/2023-12-22/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "01b05f33dbfd00aa3ae500db2204f08e5908a4833c3a26f0473bed9605003bb8", - "dist/2023-12-22/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "946bad6ff6d59ee175d7defcd1567b2aaf5c197bbca8985b04b91eb58f3e6277", - "dist/2023-12-22/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "bc2df359ed8ac189459139a0bcd3556484588bb053a4c2a0e1f7c8fedf39849f", - "dist/2023-12-22/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "a870d941baff83185c43bade890a8c87bfb16e0549fbc74cacfec561740a72c7", - "dist/2023-12-22/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "3fdd608ac91db883b2829f38bfbbb332ac327ab070570384d182e47f875bbecb", - "dist/2023-12-22/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "0a503de10365cc8eea4405e2db265e95d0d6a52556c95e3ca8e06735551ca0c6", - "dist/2023-12-22/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "82e85800015ada8c40c613eef01a4120feb60a35e069ace15d018dcd6603554b", - "dist/2023-12-22/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "21de46c078d31ac953cb41271b020817ef9c3cc55cde7b6b280f0425d8fc7400", - "dist/2023-12-22/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "5886fcf2485728376b7fe7c6a2cf9331f4bb0cab204efe5458ab2ef816e48b5c", - "dist/2023-12-22/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "6c775b5604ce3b3680d9cb6c074c97708d6804d40d44ab4d2abcaa8fd8fbc509", - "dist/2023-12-22/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "51bc618c6c7fa1086032655b6cf7c54b30c12ddf28949840e7695c0e65ff9f30", - "dist/2023-12-22/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "911b8becd12efbb1a46edaf55a383ab8c193e077aa08d1bec8c38a0168557dc2", - "dist/2023-12-22/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "27b84d5cfb60f11b03e26c882f20aa1e58fbba568cd6fc32f0970ab91cc9ed44", - "dist/2023-12-22/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "21f62ffdfd1497e5bd32cb43a9fd3c39672c429ef878e35c2019e167444afecd", - "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "1338e6d90b781578326816eda5b698ab38efa733387e1df84bb56c3ba5c9fdb4", - "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "9ce18c0e954100fedef63baceeac4a01fa0b0f810dd5175e5fe61070151c8161", - "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "8493b82ddec3ea06c8a1b9bb8357c47164ca85856ed538c96678cbaba3361afe", - "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "cf00b45f38ed847039f7c031e7c1a0a62cf7f00fad5acc05d47edb7e28a0e546", - "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "96480091ef8533959ba49e01922569a202c8fa2de174be553fab8478cb5c455c", - "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "c237e0c157dc09ef2c47583f34253ee92db92ead9f77fd8701ddee998acc0aee", - "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "73b731dbb70e872550e584fc4d3c67b6cbaa2d9a9a97b2ce11bcf6ab3ea5c5fa", - "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "141fe48890292de4d39547787f4ff44f672d3a5de35ed775cb80d7c3684bec73", - "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "52b2bab5830100dc4d4fc53ffcae560d7801382dcb4af19d2554e2551312fd0c", - "dist/2023-12-22/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "2071421241ed9e5e00fd5f877863a3a145616a8585db472b35ea902affaee4ee" + "dist/2024-02-04/cargo-beta-aarch64-apple-darwin.tar.gz": "f39e4ae0a2e69b1cc1bca0910287974025fa70398e278083d5be71a6397f6e7d", + "dist/2024-02-04/cargo-beta-aarch64-apple-darwin.tar.xz": "52f51e11e352d96e6350c0860576dc088681a135ded0bc04e943ba95421b52a4", + "dist/2024-02-04/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "60cd2c54379b2d0287072dfe7cff5b81bf51beb69ecb296d6f3036f2a2526f8b", + "dist/2024-02-04/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "cdc5d36196fa99c6c3641000e66ff68be9f2cc95bf00cafa87ae8386400b8ee0", + "dist/2024-02-04/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "e78c45f00e9a88647e8829fc248739aff1f0ed0ab6ec60a3da5ce6d2c1f02cbf", + "dist/2024-02-04/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "541754f83b39db95b62c5a0d2f9650b53212e0d6c2989429323c79a27d96d8c7", + "dist/2024-02-04/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "6ec7f1ee3284ae3e27da9667fe976d459262233bdf1a7692f8c72f467aeb5ff6", + "dist/2024-02-04/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "89c46d7e3826e6ca21cd2b992492c08e7a1d261ef347cf29f018480956fcaf98", + "dist/2024-02-04/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "9af1091ed9deee05e3c1b590dccc88e3834f47c43193acc29d5539ec7922a7f3", + "dist/2024-02-04/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "14a55b1aa26cc7ced03857a4848c91eb25bc1735b1e314b453efb8856b96105e", + "dist/2024-02-04/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "3104665d24262b8b7586777331e63ee1732fbf7656f05b7dd85a71534e7b47eb", + "dist/2024-02-04/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "610486cfcb5022c6f99494b9f58f3494438c7d9af4e0a949d0c5d366d13acd74", + "dist/2024-02-04/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "bdeeb3b50477fb57f5d02796af0543deeff9d274e6c12dcef1a11f7517dd2ceb", + "dist/2024-02-04/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "95a5beba76cf3ceb27378f1f2f9ab92359ff5627603ce2f6a8f86bed6ecf61d8", + "dist/2024-02-04/cargo-beta-i686-pc-windows-gnu.tar.gz": "65d4fecddca8b303f062fa119af9a7eb145c4c91adf5d5ec045325f2f48c906a", + "dist/2024-02-04/cargo-beta-i686-pc-windows-gnu.tar.xz": "38e766e4d90270c8a5f82cd4d0a50c1c143987201194c9132b86bf7a1a969036", + "dist/2024-02-04/cargo-beta-i686-pc-windows-msvc.tar.gz": "ed2ade2a28c469f9b488a675054494f4f26b4c3bde90c17eea34454562262d08", + "dist/2024-02-04/cargo-beta-i686-pc-windows-msvc.tar.xz": "05c6dcfe9e14bc2ede72863fef1814feceb063044af7a31baba5961e29aaf1d5", + "dist/2024-02-04/cargo-beta-i686-unknown-linux-gnu.tar.gz": "5954537bd942311649da6daf95ff60afc7e9b03fd3fae0d1a97244338309786e", + "dist/2024-02-04/cargo-beta-i686-unknown-linux-gnu.tar.xz": "9148aed468ae49b94b14786eaf58f963e2c58e2a99a93afa481be0a9244b86d4", + "dist/2024-02-04/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz": "213b7f752395db016555825664e3e4a3bd5da8943e8bd56ed5bd94380e92181a", + "dist/2024-02-04/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz": "8d146499b36f2d08389ff7888d74daa9f18a7e43cc2283c5410dd5c386c9caec", + "dist/2024-02-04/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "12a828172bb26f88c1a11a6d68aed6f87c3dc47961f74c8eeb6451b38c204b90", + "dist/2024-02-04/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "3905b493ee8ed0bd4961739b91a0dc14340082a811ec5be6e44dd8194ffaa38d", + "dist/2024-02-04/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "63eb2e4303af8f77ebd8d22c08fd7d6f209abec1dd9f19f5afd2c4b281e765cf", + "dist/2024-02-04/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "5be0627e2aeb33a7888c9a884e019d65d53a463e5b2dbb23a11ac5a89cc175c3", + "dist/2024-02-04/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "12bd938eab15063da78bda1b5f0918b567f55587c494c85fe8b11b36f305e397", + "dist/2024-02-04/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "0a6247ab66282beac406aa0c25affb51dc43a0b2a40fc71a1d98efc680a6f67b", + "dist/2024-02-04/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "6e9a6b49a58ef886bf668c9827c31d3f9beb2ee227b8c7a017071bff7e1efb6a", + "dist/2024-02-04/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "f56cab3cbbf6dc2e605124b8edd6c9a7d7592d001e9b2f4ea04af890b6fe6335", + "dist/2024-02-04/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "be35d6d6923da0a5c8599760a72b584cf9e131bf16effa184d79786e9613f8a6", + "dist/2024-02-04/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "81cd24ac13498570894a98a69ffc552ad282dfe4a076018841881f65ed387e09", + "dist/2024-02-04/cargo-beta-x86_64-apple-darwin.tar.gz": "e828aeffa6c832ff7a1e71ae12d275f75df9c3087aa08959dc0b93d0f37f9f76", + "dist/2024-02-04/cargo-beta-x86_64-apple-darwin.tar.xz": "546c56de1500061d5a133e05662d2659e3e96619f20757750ae8865498b71eb6", + "dist/2024-02-04/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "c10b9f15a31a05ba6f865d1a853ca3f9b178a3c886ab73b9577f8db0b870c592", + "dist/2024-02-04/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "65c5941965768e31abcba7c57e660cd6fcf909157b6aca1bf2ea0983e5a844da", + "dist/2024-02-04/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "14bf2ac915ba94f172bd2a569bb669101d877fbce5262071b5ebb8f8d81752a9", + "dist/2024-02-04/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "b2ce5dce49edc9a872ec63251b00ce4bc7c232984fee8b8ee534d8bc04f2084d", + "dist/2024-02-04/cargo-beta-x86_64-unknown-freebsd.tar.gz": "d408172c12e290bf27828a2e806670c750428182d0caa5f1aa88b9a4d3fe1bc9", + "dist/2024-02-04/cargo-beta-x86_64-unknown-freebsd.tar.xz": "46a7ce49382615f896276eb1966b7815353d19927a9e54feac902777fc7de10e", + "dist/2024-02-04/cargo-beta-x86_64-unknown-illumos.tar.gz": "a28eccf6cc23b580980fba900943c93a71594ed0a8120c239ce882e02c1f4a6e", + "dist/2024-02-04/cargo-beta-x86_64-unknown-illumos.tar.xz": "950a9a326bf80c65b0cb0073c5b712368a7358b993b8850cf4ae2bfc6644671c", + "dist/2024-02-04/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "0676c47123c0292b2e4f18592801383bf73ade1069cf6d160f27a39d86641b4c", + "dist/2024-02-04/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "a3dda924031f949cd7b5ada8e67b506efa94fbd4201e00d9c1e1e589223a039f", + "dist/2024-02-04/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "b00be1a9ea0d0ca1c81181d2e1263594c8654036d050e8417772bb10021a0018", + "dist/2024-02-04/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "bc464a4758ba8d585b2a6d7ba1f0f76c5bc8e21ffb699b4311cd54c702ab2295", + "dist/2024-02-04/cargo-beta-x86_64-unknown-netbsd.tar.gz": "4c165157f0fe6c96b3e54a73f795792cfc69aa979c71093eec918ddbce9a6c08", + "dist/2024-02-04/cargo-beta-x86_64-unknown-netbsd.tar.xz": "05cd0538b71c90f3e665b2feef453a0c4f4f6b1b68e4c8fe2339bd3d9c071af0", + "dist/2024-02-04/clippy-beta-aarch64-apple-darwin.tar.gz": "93cf112cfedead61356eb102bc55c811a23f67e13cf3933665de95f306c5a3ef", + "dist/2024-02-04/clippy-beta-aarch64-apple-darwin.tar.xz": "5389da6bb96c8928f18d018a25cd5d104d1c4ff9478ecf7c289434de3253d2cc", + "dist/2024-02-04/clippy-beta-aarch64-pc-windows-msvc.tar.gz": "5403e94f79d7295bf565b061b6fa9e5d500068005a7012c47dd1f0422cadcc99", + "dist/2024-02-04/clippy-beta-aarch64-pc-windows-msvc.tar.xz": "a285d22b4555524d94107292c45300129774448f2c1112e1744564e480ba07f1", + "dist/2024-02-04/clippy-beta-aarch64-unknown-linux-gnu.tar.gz": "4a6a2bc13f589b4de7a42d71517286740fc5670ad8247263338ebf13f021f5f1", + "dist/2024-02-04/clippy-beta-aarch64-unknown-linux-gnu.tar.xz": "6a007ff2a433dcd4a07efa6d55ae829cbbf4518dd5a5e52570bf70bee1876a22", + "dist/2024-02-04/clippy-beta-aarch64-unknown-linux-musl.tar.gz": "b4ff74cdef7ddbaa97ce031fce580ef235dc890c08a65f334b7f9bd61fa7fae5", + "dist/2024-02-04/clippy-beta-aarch64-unknown-linux-musl.tar.xz": "80bb641d57cd9077121640aa989a2a1b2c7ad802219b623d7b98527181061056", + "dist/2024-02-04/clippy-beta-arm-unknown-linux-gnueabi.tar.gz": "9f5a8c09e02bbfde36522f6b98ac19c6758f04a6fbb76cfafda357fabba20819", + "dist/2024-02-04/clippy-beta-arm-unknown-linux-gnueabi.tar.xz": "03aadb465c7761f000cb1515c98998afeb7557d1b20443c6b444949620290fc8", + "dist/2024-02-04/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz": "694c756a8df76057982652a6dd31406e52f46f1bb9af29e9e1221ee90b966713", + "dist/2024-02-04/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz": "224cdd5c675e68b5d0094a1b0d9cc08411b168dba5c3a8b6be15223ecce542e6", + "dist/2024-02-04/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz": "95c385adf93104d0ee31c59c10cdac2c7dbe073c40eec9a213d528109659e5e3", + "dist/2024-02-04/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz": "f649540bf91a48a9c8b58ed161b9665747a04054839bd21225d5d01d6abb6809", + "dist/2024-02-04/clippy-beta-i686-pc-windows-gnu.tar.gz": "b7597b2bf5e1a3b6041cc3e7773ef9385b3d1e0323411ee81eedad07ddec64a2", + "dist/2024-02-04/clippy-beta-i686-pc-windows-gnu.tar.xz": "a21cacbc47c6e9eb16e356e7724b1b71214a2b5fc513a50e8f4ce79060ddcd4d", + "dist/2024-02-04/clippy-beta-i686-pc-windows-msvc.tar.gz": "d71c3d482b328a01168f1cb8136f2ab76f5d55468984fad27039ea65f462fbfb", + "dist/2024-02-04/clippy-beta-i686-pc-windows-msvc.tar.xz": "e1f4ca9fa2dadc238126a995891da9bdb75dce196daf3f95a697653004fc2d4b", + "dist/2024-02-04/clippy-beta-i686-unknown-linux-gnu.tar.gz": "c2763fd5984be3105f649f5587cdb5af6ffd53fc3032ffce751730051a901e36", + "dist/2024-02-04/clippy-beta-i686-unknown-linux-gnu.tar.xz": "92a53f012b6770bf505082e27ccc182b20c0ae4954788c8ba51c140ec8981c8b", + "dist/2024-02-04/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz": "c39b59c5e347bbd169cd1c08c087db4f7ddf243416c9d0a144da620ffd99283e", + "dist/2024-02-04/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz": "1a973d60048b8a8541ab217cb00d5aa74fcb799b1f4f491666b07d4960aa8fa4", + "dist/2024-02-04/clippy-beta-powerpc-unknown-linux-gnu.tar.gz": "e40718072e3dde6e01bb9881a024a362057a8c22601d58273cbfa757999311e8", + "dist/2024-02-04/clippy-beta-powerpc-unknown-linux-gnu.tar.xz": "b47d5c9c7eb3351e7afc3648069e0e5d3eaf9f61b1ba2074f91f1b4a114cf6c0", + "dist/2024-02-04/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz": "ab30688d5eab3f7fdddf665ae00e23a168259da3bd9ef583e56c80800e20256c", + "dist/2024-02-04/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz": "4c08b61a36d8901e8c8fc397f7919b63264f9709b0b513683582da4378e4586c", + "dist/2024-02-04/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz": "88af713a59ad27e04a315a9887e0af3afaa118ef103b235a6874e7665e270f55", + "dist/2024-02-04/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz": "e6aac345a1a8c12168af05697379e885e896f1ecb51846a5183aff5f1efc321b", + "dist/2024-02-04/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz": "b57db645be80fe0ae5a8d3a496f4d00ff7af3bb0ff1032538a051da3b012cab7", + "dist/2024-02-04/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz": "be6d3d5cece8442b016be55ee46f4278797a7842d023af9d03edac6e528b6e8f", + "dist/2024-02-04/clippy-beta-s390x-unknown-linux-gnu.tar.gz": "5f58a7aec4c2b9311cba0c11c88879e60fa9bdf541324f08b203ad739d4dc8a7", + "dist/2024-02-04/clippy-beta-s390x-unknown-linux-gnu.tar.xz": "3b7e417060b91bd08e28d88f531947461c18a2aeeb3ceb7774171be7e55758c3", + "dist/2024-02-04/clippy-beta-x86_64-apple-darwin.tar.gz": "1806b225fd6b163ca5ff2fafe34b9fa085724f3c46133757b6a19fae3e253c69", + "dist/2024-02-04/clippy-beta-x86_64-apple-darwin.tar.xz": "bed30af2131873d94784ff69fedb51c80e0c0ffc5474c6ebb06d00292082d2b8", + "dist/2024-02-04/clippy-beta-x86_64-pc-windows-gnu.tar.gz": "7a7c7e2b67105712265e776086c9dcb8fc84c1ad64c6cd3175b8235ea85f1287", + "dist/2024-02-04/clippy-beta-x86_64-pc-windows-gnu.tar.xz": "9aa2a44e40c3221df88738db9fb9729989ce618c8a73e109f04ed758da044ef0", + "dist/2024-02-04/clippy-beta-x86_64-pc-windows-msvc.tar.gz": "32f2acc1fb292a7f8af43e7eaf0e5cc57f21ce51ddb209ee5d9c4db50bedfa17", + "dist/2024-02-04/clippy-beta-x86_64-pc-windows-msvc.tar.xz": "6e521228076657cdd451d924c3d0d48ae703f6a3ac1b6c64fc2b56553c924f11", + "dist/2024-02-04/clippy-beta-x86_64-unknown-freebsd.tar.gz": "cdf2ea498ea64ce119a861c4b4ed198f1971ff4562f239e1ae982a6bd50a8169", + "dist/2024-02-04/clippy-beta-x86_64-unknown-freebsd.tar.xz": "8716ccf9eb52a71fadfc177abd5dc75b1d9b1f14f7c523d12aefe5407d5380ee", + "dist/2024-02-04/clippy-beta-x86_64-unknown-illumos.tar.gz": "b845e1e8e0912abc1c165e757b28a569117ac7363282e691cad7dfbf2fbbebe9", + "dist/2024-02-04/clippy-beta-x86_64-unknown-illumos.tar.xz": "8a5577421bbcb6bf4ff052bfa0db9e22d65eeed578be3fb14946bddcf78aaf8d", + "dist/2024-02-04/clippy-beta-x86_64-unknown-linux-gnu.tar.gz": "730dced7639da52fe031ea9142012cd1c6f4a195312d99ce08f8b948ac317f78", + "dist/2024-02-04/clippy-beta-x86_64-unknown-linux-gnu.tar.xz": "4de9e4acf49f34cf7e99bee718d15081ea7e5b3cce56b1d180e125832126934e", + "dist/2024-02-04/clippy-beta-x86_64-unknown-linux-musl.tar.gz": "b5ce09b95d2a77ba605d2083573c1d4832fe42c8ff6b5bd8507f1ccddf87a10a", + "dist/2024-02-04/clippy-beta-x86_64-unknown-linux-musl.tar.xz": "fcf7c128a344f7b55481b82223b971fd5565db4023d443b315349a5ac5f5937d", + "dist/2024-02-04/clippy-beta-x86_64-unknown-netbsd.tar.gz": "8abaefeaf4d884e3214f657d8896bb440d93b3cd5f4e355fb8ae728d84713f40", + "dist/2024-02-04/clippy-beta-x86_64-unknown-netbsd.tar.xz": "a4b5e4b73c7a613f34ed592af4a73e50c4fe6f0f841f9749cab57530dea6033d", + "dist/2024-02-04/rust-std-beta-aarch64-apple-darwin.tar.gz": "54c24b06cf7b1cce6d74d0cf2ef38c0df0296e9b417116ef6bb340cf9a864f20", + "dist/2024-02-04/rust-std-beta-aarch64-apple-darwin.tar.xz": "17034b0eae96813fcfd0d8883fb7f4805b713404e15169e8c3de32801e4ca3bc", + "dist/2024-02-04/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "477879218f052b6f20b40d34b72a9fdb900a64fcd4a1392faa187eac44576456", + "dist/2024-02-04/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "5fae8e638f4c6b61683db07c0de485a1cb677e4384c593f32c089d77ea5dfbd9", + "dist/2024-02-04/rust-std-beta-aarch64-apple-ios.tar.gz": "4cc45742a06693a713d72820c6ee830ed8bd4f6f5ddd3be1e32bca4f5f88fd4d", + "dist/2024-02-04/rust-std-beta-aarch64-apple-ios.tar.xz": "7d9adce8808f0f5f7b9c65091791107afd63f26de02fe156821a6125486f2255", + "dist/2024-02-04/rust-std-beta-aarch64-linux-android.tar.gz": "893a0befa7f506cf3a07712d7a731ce551209c97708cd7f0ab12fa6ff3f1da39", + "dist/2024-02-04/rust-std-beta-aarch64-linux-android.tar.xz": "b647047d64f2fded2e393f226a7d131c96e84f2cb0ea6ed8259f25648b56bc6f", + "dist/2024-02-04/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "74917077da50bff4ceaad96a8acd1e90f9ccef32aea2b2f5f48406ebafff4c35", + "dist/2024-02-04/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "08210e2b802cda619854608e361a08388b51b9fce1551c13e5068ddc22d0773c", + "dist/2024-02-04/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "a51887dde95a5102eba99a754016900dd679e2cc6f65b7173a3d31c8d0f0148a", + "dist/2024-02-04/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "57f7120e830dcbe8c95be39f00342f2fbbd8ccdb20f431e8bc940eccc4002864", + "dist/2024-02-04/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "6a79090eae406437761523e43e5a72b0ed040deb97db82da62718ee502573770", + "dist/2024-02-04/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "00f3df2addefb8968d668200a890593481587536d0628e4d8def08b77e79caaa", + "dist/2024-02-04/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "42f0afcf90ffe70388c53d7642b035700af71b99e8382c5e95a94c6aec166e99", + "dist/2024-02-04/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "337984596f0d3cfc5776830cf7cb36ec8d564041761666fe340ecb0a62332348", + "dist/2024-02-04/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "913e2255837674cd672c4959d567ccd786242acdbe78fa76119ceb8ede9b9846", + "dist/2024-02-04/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "660f879a8a3e19686cb944766b0e70b19d0a9fd344047ceaf5e8959bc019f36c", + "dist/2024-02-04/rust-std-beta-aarch64-unknown-none.tar.gz": "4a210eefe84dbfe4e75fbc3a5475e58d86983e1f5c195e7c8b9f096e46ebfaeb", + "dist/2024-02-04/rust-std-beta-aarch64-unknown-none.tar.xz": "ad03045b5fe2b25806b4b44f5920e75008234954318cdc9cac8159782f6fc314", + "dist/2024-02-04/rust-std-beta-aarch64-unknown-uefi.tar.gz": "0c2988780468ff39ffe65cae5443bbdbb441aad18bf88312c14df76fefc748fd", + "dist/2024-02-04/rust-std-beta-aarch64-unknown-uefi.tar.xz": "0e4efbb711bd74cb280535ca424be4519f8e273b482eff4b5c4cfb7f0c142a74", + "dist/2024-02-04/rust-std-beta-arm-linux-androideabi.tar.gz": "6e6a0140c52670d962db55be6aa607618fbd4094828f27129cc94540ac94d893", + "dist/2024-02-04/rust-std-beta-arm-linux-androideabi.tar.xz": "fae70ac3c0be0a83c98eeac49e651c392c5962e10b4876120959d95209cff4ac", + "dist/2024-02-04/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "48f73e51726a7685cee917fbf42464c13b77e3c4c36730477ce8a5213d0c8068", + "dist/2024-02-04/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "03c4fdb9ab6737d48e9d1573188badf126acdfb96c4dd88c36d45fd7d61845c6", + "dist/2024-02-04/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "d17985406a6d241ae2e1f5c5571795ab712cc47fc2434fe78d69d3e581a768c8", + "dist/2024-02-04/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "ef29cc16781ad2422b78708634684f9310cf7783c2c88fef6cc378c1b21f86d1", + "dist/2024-02-04/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "df8bf07f5270c91bcdda1568fc870c128594a558d5fd26ebd8f4e9e1c7c026c8", + "dist/2024-02-04/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "114b42345f30ff26ac42044825209f7d1ae4b8b9a59c535ad199a78e8e2be1b8", + "dist/2024-02-04/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "5b05057ef84727d0d62a575b1a4d8f87ea7b06cf242d294912bf97b52137a0ca", + "dist/2024-02-04/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "a87b55c984fef378be2f50db63c0a66f715949e4365d467211b5c13839320cc3", + "dist/2024-02-04/rust-std-beta-armebv7r-none-eabi.tar.gz": "e8ac0f9c5f699c88a8da799b08111bee35719426ce6c0e2f53d0db14fb9b96d7", + "dist/2024-02-04/rust-std-beta-armebv7r-none-eabi.tar.xz": "7875d407748e983536bc0d3a385313a124de94390b780557d48fce9564a3754e", + "dist/2024-02-04/rust-std-beta-armebv7r-none-eabihf.tar.gz": "70415c0c7c4e9e53b12b1cbb0101398addb6b4aec59235011c2d73c059d0336e", + "dist/2024-02-04/rust-std-beta-armebv7r-none-eabihf.tar.xz": "2c9f18fc935938d5b9f9cb7915dab5aa6ca96032abf5a9e3313a63136c4cb11f", + "dist/2024-02-04/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "b00b34a021c2d80574bbb764b08e291ffd8db0f346b8c3486789c86f008b5d98", + "dist/2024-02-04/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "b47a6f55b44add99ca66d06fa910259c809c5f4f01feb809e2a6b8513626e3fb", + "dist/2024-02-04/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "caa8182c95035b62ba22e23d3989ba2733b90f599276a7c1f79b911e19d97850", + "dist/2024-02-04/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "1dd6c111f945d727eb28c9005efaa367ee2de8b15c771d27cbcb9709202f85b2", + "dist/2024-02-04/rust-std-beta-armv7-linux-androideabi.tar.gz": "b4176be56ab844c0f3d652d5023b927b672173f96319f685a85e57742b713102", + "dist/2024-02-04/rust-std-beta-armv7-linux-androideabi.tar.xz": "3d3d96f5cec355401e3eee94e5a9b68e070f441090f691f1de15a13d6194154e", + "dist/2024-02-04/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "ee5fcd9e0a661d08a1cb752cbfdce62b01faa4c4bbc607d09bb0d39a2c598899", + "dist/2024-02-04/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "a2e7ab719dee92b6c2132a902045c0bb2688851243fc530eed6b1fbe1a053333", + "dist/2024-02-04/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "59ca2bacdca9b46e6e0b1803813d4021b685f676e53393e18b4497853a452d85", + "dist/2024-02-04/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "f1b5b8843f804aef664a96896235384b1389de7084ba30be234c770dc9ab0517", + "dist/2024-02-04/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "3825bb169e5d7abc0981f6a5179b143e2a695e395d0baa7cf181e8b752988ac7", + "dist/2024-02-04/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "9aca61705d683d384e1d7e2392bdece52791d77edde6f45e2772bae766765434", + "dist/2024-02-04/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "46162ba65beed4d4ff70695870d02a39dba5ea4e1a71887140077e12847a3206", + "dist/2024-02-04/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "70841fa160053edb31d440eb47c54c58f4635bf4a95eac5624861b9d1e5dbbfe", + "dist/2024-02-04/rust-std-beta-armv7a-none-eabi.tar.gz": "ebc2f71d8486401144a193768cee0fdda3d43ec4ba7cb57434d3ec0ca9ee64dd", + "dist/2024-02-04/rust-std-beta-armv7a-none-eabi.tar.xz": "c8d54ac916b6c0651e8289deeee3dec76a06db7086957bca8c6039f4d10aef2a", + "dist/2024-02-04/rust-std-beta-armv7r-none-eabi.tar.gz": "b25ff694d355fafb41aaa7021c09c359b0af43a0217e1ee9d897f8f2e6ece91b", + "dist/2024-02-04/rust-std-beta-armv7r-none-eabi.tar.xz": "c22f40104c14a127d8df29f87fdb63db7aa919e11507c0bb8907dccd2d254f17", + "dist/2024-02-04/rust-std-beta-armv7r-none-eabihf.tar.gz": "3f73a17c6685760c30baed31cb746389b4b228704786a3a386ab432e933daae4", + "dist/2024-02-04/rust-std-beta-armv7r-none-eabihf.tar.xz": "fd8470f854538c8314d15d35b9a5159cf9b431ad7ccb79ea0542ba39d6e8a8dd", + "dist/2024-02-04/rust-std-beta-i586-pc-windows-msvc.tar.gz": "1377b2c1bc7a7066d7ae96316bc0a0339489cb71ef7f9f055731465df97ba8a0", + "dist/2024-02-04/rust-std-beta-i586-pc-windows-msvc.tar.xz": "77b22f2e94a3e1cefd057f051e568a6c8f4b17845272924dfbc193d8a290d96d", + "dist/2024-02-04/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "222337a479e3d680d95c5189026890bdb3cae7eca78000f231e6747b9b403f22", + "dist/2024-02-04/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "91447a0543f07bb36c71822ac4e8148e2e5982d1dd98fce7ba4171d7f418ff16", + "dist/2024-02-04/rust-std-beta-i586-unknown-linux-musl.tar.gz": "e2aa15ebd2a903f754fc9a46584b444b3fbbb9e42f2647ebe615f68711a0a27c", + "dist/2024-02-04/rust-std-beta-i586-unknown-linux-musl.tar.xz": "65f6975a8c06967f734bbd15589b14c5eb23951f10a79097f262083975654dd4", + "dist/2024-02-04/rust-std-beta-i686-linux-android.tar.gz": "073d7697a80e99cda4625f0bf1205744af9cab1a10456e44050fa8e6987007ab", + "dist/2024-02-04/rust-std-beta-i686-linux-android.tar.xz": "f142ffc490821bfc4bec5d69fb82c94aece9e379168f86b494b13289a597f23e", + "dist/2024-02-04/rust-std-beta-i686-pc-windows-gnu.tar.gz": "aaad81222f76855ffe5d2f6c5eadfe95562e9dfdf72a92531dd85b38568420f5", + "dist/2024-02-04/rust-std-beta-i686-pc-windows-gnu.tar.xz": "69923e0455f7b8f2cd28ef812118e359ce64789059d45e91ca5f8e382f1de1b8", + "dist/2024-02-04/rust-std-beta-i686-pc-windows-msvc.tar.gz": "1d66564ac675d5ca8c97ea7feb2b8e2fe606a560d27a137d996ce9814338cbba", + "dist/2024-02-04/rust-std-beta-i686-pc-windows-msvc.tar.xz": "8badfa48e9a654a48095026903e17392f7b4cae3501362579d345c541ddeb6bb", + "dist/2024-02-04/rust-std-beta-i686-unknown-freebsd.tar.gz": "3d45f7e407668cae7fae8cd8dc4e8ff8ca5f5a01baa4eb9401b81255d1e8947b", + "dist/2024-02-04/rust-std-beta-i686-unknown-freebsd.tar.xz": "c1788c7bbf8f4ee61c2d4623ed4efa8a8d15acc2963f3c146b48ed7d6f6010b7", + "dist/2024-02-04/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "2e4434cad302be51543916055c8ba76b8c0c072476f6c491754b1a750aac8800", + "dist/2024-02-04/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "5ac0bb47b9b6349a34ac1526f16714cdd580bd3aafcc3811001c69d8be21d0c4", + "dist/2024-02-04/rust-std-beta-i686-unknown-linux-musl.tar.gz": "21b1323043707f685bedd699a169e8acb189ca7431c1a3dc0ec7f56b27c2fec2", + "dist/2024-02-04/rust-std-beta-i686-unknown-linux-musl.tar.xz": "8fe2e260084c960bd29bede4be32371a34b1f801447628bbc32e7dae2d603784", + "dist/2024-02-04/rust-std-beta-i686-unknown-uefi.tar.gz": "4fc958f2c26ed27bd4537a31d2eee9a5b02bb5b0433402151e84756f470aebdc", + "dist/2024-02-04/rust-std-beta-i686-unknown-uefi.tar.xz": "a2c8235767448796d80f5408694d8ebbd6fa3b67d7c4fa03b7074836b4966114", + "dist/2024-02-04/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz": "a8689d5d7454dfe00acb84535813b47065cc09e17cc8006d5fc02da5f02f1cb0", + "dist/2024-02-04/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz": "d0eb4684222b53cac2eb84242a4e145f3f31ca855c296836b75340a0d432391e", + "dist/2024-02-04/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz": "6ee4ad6d9022bc69120709064dd93ff70cd3beb14ea28e82f3d4fed24ab07426", + "dist/2024-02-04/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz": "57ad740ec9ebf9b5bd3f082d89d63ff388523cb4d38e2cdf0b601bc7f07c6820", + "dist/2024-02-04/rust-std-beta-loongarch64-unknown-none.tar.gz": "a7400a7bbb873aac5c92339c8242966d1fa9553054f922193a2a8023b98a97ef", + "dist/2024-02-04/rust-std-beta-loongarch64-unknown-none.tar.xz": "7cd77b7c8a8b7c7c53d2ed454515766da3e02c7d6c63d880de9bc1c313f396a8", + "dist/2024-02-04/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "3b65431258133a690c976db006ad7b545cc980ff0352dcd03304741f5e82881e", + "dist/2024-02-04/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "87eaf905c3c189e9fca5a3f1dea6a0b53b7c4a84aa22c1ecf8b782c54c360a80", + "dist/2024-02-04/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "97c12900755f780e32facd9ee3641394a3a7e32fe6e6a1cadd342ee367c95b6d", + "dist/2024-02-04/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "a7c482e83c0ce07164921cc8ae48d02db9b795a5ea2e82c2948f598f68519289", + "dist/2024-02-04/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "9c1018fcdf362d891b6b1a63c36d5123917b2478bf010a0b32691c44480abcc7", + "dist/2024-02-04/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "fb93344ade418630bf610f9555babb0356ebbd369db73ea3edd88e96a48171f0", + "dist/2024-02-04/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "4c24f19b83a528af2ad0935d775106415708a03212092ba86bb271db38bd604e", + "dist/2024-02-04/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "804bc2c1c51570cdc102c80c1514b773d0a05a8f2fdeff9f789b525b042a5071", + "dist/2024-02-04/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "8ef9ed0ff32193e46617bf2aab368bbc4b268175acae604e26db8a1a92c15983", + "dist/2024-02-04/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "3b0450f332e258d1bbeee5c78628349cb1a6fad9d7058e0f2137709c46d90713", + "dist/2024-02-04/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "47cba66e90e6310139a511083eeac727a6c55e66533157a662cd613730df7123", + "dist/2024-02-04/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "ce19df99deffaf9002272d8c8b8c51f6d1dda93fc2babe8d786494add2607b27", + "dist/2024-02-04/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz": "fb8842df07fe5d0c782c9a4b260de7cf71835f7c4ca18f5241c9dc245c75bc7e", + "dist/2024-02-04/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz": "5b14d80923b4561c3147d5a6a45ad73f0c187f8ff38ce51c7f54a95f17d0e3f0", + "dist/2024-02-04/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "19f2c43070c2cd477a07d9ab2e0a9fe8e3d41aaff75e09b5bcb89e6dbf8d0d12", + "dist/2024-02-04/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "f5d413c8763e72aea96ca97a71927fd81fcd6341a8d7cacd070898b255f6d8ea", + "dist/2024-02-04/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "227a42a01e2bfe5089afb478f3c78385ee989fe70199110ae8e5fb8f7d9c899a", + "dist/2024-02-04/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "9a09c50ae0773469186754b6d14638a0d2d170f3cbac9dc36f4911a248480ea3", + "dist/2024-02-04/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "70b168b86fb960124e9b4ed510848f5420647dcb82d36cce887aacbb7bf2783e", + "dist/2024-02-04/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "db3a0c4e36a182926360317694053b9ee7e24d6f77f3c15eb9ff79482b3d129a", + "dist/2024-02-04/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "127cb67bac139a8621b87a475be07dda3fc92616f15068145ebebd7087230815", + "dist/2024-02-04/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "07e2ca92ade33338a800f3b9c0b8aad2ddc1c699247a3144bd70b3f2d93e84ec", + "dist/2024-02-04/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "6fc83881b97579aeb2c2873f18a5e63ac06a4b94889e0054a8515e2f23b8b1c7", + "dist/2024-02-04/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "b85f994c59b82db877fb42e2e06ac193de136e8b362284d211c66607a7272328", + "dist/2024-02-04/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "d3188ab7fc2cba5474cb6c1cb0edeffe20ab90beb05cb42e83c4eeaff3c66d9f", + "dist/2024-02-04/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "3e40bcf0c16e96fa81d814d81631e99069026d8b27b10c905ed22218d5842cbe", + "dist/2024-02-04/rust-std-beta-sparcv9-sun-solaris.tar.gz": "cde8e5c30725da66f9c6d6c67283e2d55cb22c1b65c4a0ac8157e3b7c79ae567", + "dist/2024-02-04/rust-std-beta-sparcv9-sun-solaris.tar.xz": "4832c0e385467bb0c5276971d5ecf4bf0e77247e54f90480be635a6a4a43ddb6", + "dist/2024-02-04/rust-std-beta-thumbv6m-none-eabi.tar.gz": "5ee43f29701f44060770a8be635708ace9143eb77926f6a6c946a3e02c56bf92", + "dist/2024-02-04/rust-std-beta-thumbv6m-none-eabi.tar.xz": "0af4c3a0270c53648b88a915466b592ab6a29aa959a014748fa95b9f511140e8", + "dist/2024-02-04/rust-std-beta-thumbv7em-none-eabi.tar.gz": "e57337af619b9e2de45d5268944d9ba3ea7ef19d8413a3e13a72c9ce08fe252b", + "dist/2024-02-04/rust-std-beta-thumbv7em-none-eabi.tar.xz": "26bbe4aa8ea10b4dbdd21da2f62118d42adbb852bd01bedab9cff47d79ac3887", + "dist/2024-02-04/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "ac22acf98402d2091d60e4d6e934ef474d0ca40882121d595f7a809fa575264a", + "dist/2024-02-04/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "3f0623d888b00d6ef243888322f9ef1781927c304e1ebd93b0d68457e0a551db", + "dist/2024-02-04/rust-std-beta-thumbv7m-none-eabi.tar.gz": "c23866c57b3781b12fa372d8a1a98626be669dfc86eb568aeafc9bbefe5c2fd5", + "dist/2024-02-04/rust-std-beta-thumbv7m-none-eabi.tar.xz": "64d2e9a717e0d6dc1bcdb3ba76937ced9d941ed1aa367fd2ebc9d6056b527a26", + "dist/2024-02-04/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "864689308f8f72faad3b1812dbb67de254f4f0acbbc28302665b29f8e6aec9c8", + "dist/2024-02-04/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "737ca7c2c4f8a1ec87ab0819676926a7d13ee4c074359530e02fdaa11a51cace", + "dist/2024-02-04/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "68f0aee311b2fa12686249a4ace1f1f1fe254e4ee9aafbe6e7f429c98fd024c9", + "dist/2024-02-04/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "cfe3bdbf666576340a7a6ba22422b88389356c21bccce60f31540a1a18095e74", + "dist/2024-02-04/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "bb0a27b78f4c006c5e9d04f7446433e13908837d947c8c73ede878219a189a52", + "dist/2024-02-04/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "271d1471e2ec7901582911bd341896e07d38ac7a762ee3000964cf8cc9f3d73e", + "dist/2024-02-04/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "e875ae5276bcf3bf112815ddcb8320d9b3e67f7d65ffda9bf194f54c49b55758", + "dist/2024-02-04/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "4f38da22bce7fdfd9cf0b0f24cce08b298af54dd2c20d8a6a10b888b66a5f120", + "dist/2024-02-04/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "28ec4144e3ac2fd74fb5f59844b29623b6286173893d5b487157c7103d0e59b9", + "dist/2024-02-04/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "c870d0ab781cffbf6bf7d0d0484b0a484eb4c4102d36f32d823b9c20c2886078", + "dist/2024-02-04/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "23f8c320114c329109f081a868e5ec464d766883fe947538b26c31757b6305b9", + "dist/2024-02-04/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "41c3cf36b6dab93202e792c4da186f5aef0ef5499d425a33ebafd1b4a7c5ff3f", + "dist/2024-02-04/rust-std-beta-wasm32-unknown-unknown.tar.gz": "09670117cb42829fcd871ed702652744d0599f715db8f1dd82ed462f01de87c0", + "dist/2024-02-04/rust-std-beta-wasm32-unknown-unknown.tar.xz": "5c04dc908e258dfce00306b6b6bdc5b5ee48031a6b5d602e7326e670f594fbd2", + "dist/2024-02-04/rust-std-beta-wasm32-wasi-preview1-threads.tar.gz": "09b5f40f1a449bb7cb6ef868bb3998f3ae4bd4f85ca594cca8b934166931a549", + "dist/2024-02-04/rust-std-beta-wasm32-wasi-preview1-threads.tar.xz": "b4de2d6ca31aafaa24871d15f4e0297064da72db884609223462232571df6ec2", + "dist/2024-02-04/rust-std-beta-wasm32-wasi.tar.gz": "194999685f52e9c489bd7e46cc1ab24fa2e37559a987d4fd90453b30b7e8b152", + "dist/2024-02-04/rust-std-beta-wasm32-wasi.tar.xz": "6f251f32b9959e7a602d6d9ddb89647970c79f129911084756550697c9e93893", + "dist/2024-02-04/rust-std-beta-x86_64-apple-darwin.tar.gz": "bc4f9b694c886df968db188f4687281d701f6fc4e19a1b59abaea247097dcd9d", + "dist/2024-02-04/rust-std-beta-x86_64-apple-darwin.tar.xz": "18530dddf369372f1f3543f8f7f34200c278cffbb2de148ec4016b07b96ae683", + "dist/2024-02-04/rust-std-beta-x86_64-apple-ios.tar.gz": "ac0ed15c9d62aaf8ae298def444cd5cd06a1701564fab564d4a4c767c294c1a1", + "dist/2024-02-04/rust-std-beta-x86_64-apple-ios.tar.xz": "57171af9b001f9b0ebd66c7643cb0a93e752320f188b6948b261abf27179360d", + "dist/2024-02-04/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "29efc21fac21062e5a0af8f2431be998cd949b12e1f73b569967e9aee68bcefa", + "dist/2024-02-04/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "d1d290ac8ddf7ec133fe1de3e5307855a86dd5780a434091198294d18194869b", + "dist/2024-02-04/rust-std-beta-x86_64-linux-android.tar.gz": "1f3a99d4d9f9283e62d9922145b63bb6ca58744eca51d3ba28277b6ae2581fdf", + "dist/2024-02-04/rust-std-beta-x86_64-linux-android.tar.xz": "34f8d2ef07c40b34d8893f93f42d9f06bde8d56c146ec1b6518a497fd68e6ca0", + "dist/2024-02-04/rust-std-beta-x86_64-pc-solaris.tar.gz": "e15b87f78925ee15b3c71c6f3cdc0cff12dd06369be53402d7115300c07e316d", + "dist/2024-02-04/rust-std-beta-x86_64-pc-solaris.tar.xz": "4f5a353057ec31568f3403c01d30d1d3aa22721be942c61928634c5e10332ce0", + "dist/2024-02-04/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "898e9bacfd9fc7f34a7543066304f4f5dd3596ef37d4a3b3bac5524ffd6ef236", + "dist/2024-02-04/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "3a4cf02b56049bb998aea963651c0c26e8084bb4232c2efa8be14740836c4da1", + "dist/2024-02-04/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "3d2d2896d535374396e3cd5b71b4135baf5a5ae2aaecc591981127dcb7717555", + "dist/2024-02-04/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "2b3a4329cd34ae5d61f0ce8712e5e73cfa9e11a6b861f7e796a2055533f8e1a1", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "a89890d16282ba9c030e32c5904117be8317c69fce09611bf8ebff440d13a1fb", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "a02a5962c65cbe60667a45d5ad5ec28f1dc86d18344c619fba00f9afd96519e1", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "1dc8c719ac47a37c47993b75e1b1280579504bb01bf3feb39b30a10b947b75ff", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "106c9d4fd1072dfbacb67674a2b0753c9742fb87e83ff32cf3ad3ce1f8d94874", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-illumos.tar.gz": "a004aab7ce4f922afa7248af5fa17fd1966a9e79b472ae4ea9496e7915bbf0f3", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-illumos.tar.xz": "0f3df2ea274c6bf201617c5b385b0e7752077e6497a3dd49f45f2431e3f2af38", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "b929350cb8aef37ac3a32f06c144cbd75884f60b26ec9316c1f675a472f1c522", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "20fffbd0d4e5bb19a428c2c808aa47f6d7a285291df204fe73a45f7d3720c3a4", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "383746f4d90d7dbca5297928bf5705d50f974ac3c97fe4dadd6ec33b5aa65059", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "60372cc7f84c6727272360ae1fdc316376ec12f632365a8deb9420f953cece2f", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "2fb0649206c57187b216464d6db86cbb4385e061098348181d654976570f74c4", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "6a22fa944f66afdc4af68d25f37b88f80dec10211e808965e0f9a41f7a5e18b6", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "3700739a966b4e9e12088518d22ff535065f666c6f8c74fc8384fb183f4e8fe5", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "b6561834aa28caad3b68248863834e8320ee43916488336f575a6860efb1a509", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-none.tar.gz": "7a56f666a6b42b666afc12555f3b82c0877c2c3beedba53037d8a66ea0ab2c8e", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-none.tar.xz": "3f8a61eb7a7015b639769d9cee9b78653b0efe4da1333b315a67982e88ed2f54", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-redox.tar.gz": "4b3aebbaced9a09de3d2b1d745d53feec2b927e0ae15ee822cc57b003f4cdb6b", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-redox.tar.xz": "69d286adaba6f18daf052156cf88e994bee40b3e8a9c467d51b3f7264e8c5882", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-uefi.tar.gz": "0dc258a276435d1a689d1067913573a4454d5b0e54e90304338f07b0cb6b7c68", + "dist/2024-02-04/rust-std-beta-x86_64-unknown-uefi.tar.xz": "ca131284758bfd1defac4e95b68dba9bdb496b2a1ed4312b05ce996308d870b1", + "dist/2024-02-04/rustc-beta-aarch64-apple-darwin.tar.gz": "f874ba6539750fc510fa67749f6a341c80497a0ea7ace5b8366849fb3a304973", + "dist/2024-02-04/rustc-beta-aarch64-apple-darwin.tar.xz": "8a1a9359e59c7057a39eeaaa6bbb180b61e00993d534b63b52ac447b31345886", + "dist/2024-02-04/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "449e0a684783ba2ad04e4aa18761da9ee4144333426335b0503526d7d0c23f3e", + "dist/2024-02-04/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "4075cbd97eceae6ba41a2862a6149f72c33ddd351c6cdf8e401de19b485ae3e2", + "dist/2024-02-04/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "99a1c8fcc434905b80086d276dbb162105d7803f8594a44b518245877320e387", + "dist/2024-02-04/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "32ab0d6814abbb16724ea6d7d422fea587fa8d4fb7e49d04c418e9f58c380464", + "dist/2024-02-04/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "04dec9fdfa8429ed3b53aac9445a54a4a486d1c4439d91e3c5214c62207163c8", + "dist/2024-02-04/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "797f8ed5112414d258de8b28f0d1d85661fa35ae0699ad89a868d7f16123e5e0", + "dist/2024-02-04/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "31c3ad00fd019cdda335630da3791633f28b79a84d847404e877efa1d963b700", + "dist/2024-02-04/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "265de8a5d1317fd686497ddcbd47adc96270b9318333296edbe57247907cea87", + "dist/2024-02-04/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "080f20064ce64e26b35d15c0bcefd20edc37f0f4627eec997fefb99932635687", + "dist/2024-02-04/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "aa144f7121a29087a6b6e057a646fa091ec7af5b48b2701c7bb514c698d510e4", + "dist/2024-02-04/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "bf1f0a9764e04d9d07702ba7563c93ec17ae527332d72b4e21d8de9bd176c4c5", + "dist/2024-02-04/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "17ed4d2cac212fcfbe1c75c482f195100ee2fabcdd85cedf78b5ea8f1355148b", + "dist/2024-02-04/rustc-beta-i686-pc-windows-gnu.tar.gz": "fa0e1ad64cf3b59682df001192c91c26edf1d41fda8f0fb3a6c535fa1597098f", + "dist/2024-02-04/rustc-beta-i686-pc-windows-gnu.tar.xz": "3f5eb74282649ed398d8a60bda4098ea8ec10b81a00cc48c65976f68d064ba6a", + "dist/2024-02-04/rustc-beta-i686-pc-windows-msvc.tar.gz": "188f1c8c1b38ece4b50db74422ab7d4b8dc40d5ee2f9a10ad2a797ea748f4ce0", + "dist/2024-02-04/rustc-beta-i686-pc-windows-msvc.tar.xz": "b9768ef55563ba4008b5886e6b20b7dfb81668452f264cf4cf9809e6fa3e1d84", + "dist/2024-02-04/rustc-beta-i686-unknown-linux-gnu.tar.gz": "c369728545e027cdaf9b92243f98979e66684d79159192ee7a22a62603905942", + "dist/2024-02-04/rustc-beta-i686-unknown-linux-gnu.tar.xz": "ec946c31d336a69912f6f0effa0986532dbdd915a1b268c419e5ba68365671fe", + "dist/2024-02-04/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz": "f49cac3db11d02f6b197354b25e2181ae7afd13837df3bccca8cda135373ae6d", + "dist/2024-02-04/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz": "b4ffc655994a64dd5644a30363e0518a2958337f187da7e4a9285658c899ab6b", + "dist/2024-02-04/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "b29c64744cc8154e1eb89ec525fbc92187b666d1f7d013523d0f7e6c089b5be9", + "dist/2024-02-04/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "5534dba963a2ae299f16b85c1fb76bfd62e94e4c9da16a97aaec26572b61f217", + "dist/2024-02-04/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "a432e73044ffa25fb6c104a82156048519f79faa6e1845e5e0d5ef448d1d682d", + "dist/2024-02-04/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "aa1688326584956677dd76c0e3620e34a3287c077b882b5b159e0d756cbf189b", + "dist/2024-02-04/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "8534f8087cbbf9f4f44f43cc8c276dba304aa0b5f9ea437cfa162d667aef1774", + "dist/2024-02-04/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "12bcba399fbff493b114bb4726a6b3fe32936a1f42134b1496b6ce44baea52dc", + "dist/2024-02-04/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "5ca25bc3c268c3df4de1740fd62f5dfb62482833be38180aa34bf220b9ec3021", + "dist/2024-02-04/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "e7187288ac175404c2a3e78776324e70c2a0d3b6fb673366eac881a48f11ab74", + "dist/2024-02-04/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "31735567bd85a94325af81e5029c652c8b1b2e5824c4f65fa48f864aca65393e", + "dist/2024-02-04/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "916afb19bb784d80093a372fa6316c72d2fa1aee3aa038554a3335ae3f62f773", + "dist/2024-02-04/rustc-beta-x86_64-apple-darwin.tar.gz": "d1445ab2c427e1e504521047c5e1e8d43b43dc4bb9dcf859e3d8b0110a6de257", + "dist/2024-02-04/rustc-beta-x86_64-apple-darwin.tar.xz": "cafb899caeec207a7e2842f03210b85d50d09f152468ab9ec1e53fa8c7511da1", + "dist/2024-02-04/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "eab3692edecd9957cbd0e2f8fe148ee81600ddde9d07e7693859bd2943784b49", + "dist/2024-02-04/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "4b711b2375c16990d9f22ca32baedf8b0d57073d914ea392028944a019a7e4cb", + "dist/2024-02-04/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "80de1f677bbf1d1c51fcabe130b81dd97cc49fcacc96bc9dbda94da1acf4d504", + "dist/2024-02-04/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "912e3ab500ed82ecca7688bbb7c5c40555cbb4d5ea9ec059a9287f69ca7241ab", + "dist/2024-02-04/rustc-beta-x86_64-unknown-freebsd.tar.gz": "632ba8e019403eddde89653cd4bf1864fd0b274603399371871cd1ded296d1d9", + "dist/2024-02-04/rustc-beta-x86_64-unknown-freebsd.tar.xz": "b5de56f1f686befd7d225c4fc0636132119a28e6ed22e56300347e8c8fd4388b", + "dist/2024-02-04/rustc-beta-x86_64-unknown-illumos.tar.gz": "f906f3492094d609d8d5fb5a563a8f2201dc21c65228c7d214a57ea795e8bca5", + "dist/2024-02-04/rustc-beta-x86_64-unknown-illumos.tar.xz": "4f29c6a41a993794dfdca0502c33ef77a3a888281c3b9e368f1befdfecc643e2", + "dist/2024-02-04/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "ce323665ebe9bc3d96e7016af21e18788e42e94c647ff1c08cdeb6ad9acc3b1c", + "dist/2024-02-04/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "6db29020afc7fb486f305e3508ee978c2ce44ce9b844ec6fe0102a16c798dc13", + "dist/2024-02-04/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "b5b5dd243653e8f1073542774c918152eeb73020859dcc3229045b1980d50bae", + "dist/2024-02-04/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "f8127a732817b1d5c091f7a508c3d5367b33e57ea6be023161be1bcc35b3b62d", + "dist/2024-02-04/rustc-beta-x86_64-unknown-netbsd.tar.gz": "73b19bc4dc2f44a04cae327ddc4740915bffb0a2182ff94438c614dce3b5ddf2", + "dist/2024-02-04/rustc-beta-x86_64-unknown-netbsd.tar.xz": "d72e53f0a99a897d5f36999957fee251d67030fbf711b1b8d554011ad0a7e559", + "dist/2024-02-04/rustc-nightly-aarch64-apple-darwin.tar.gz": "f81993a7d1c0677779a6a44ec1f475abb03e8c79ec493cb22ff194b0d6edfc2b", + "dist/2024-02-04/rustc-nightly-aarch64-apple-darwin.tar.xz": "a6247fae04e79529097f2ff5b9c8110ce4f015ba5f9503fbcd0c15c8ba84eb9e", + "dist/2024-02-04/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "012a0b1eff9a277c8b7dc01204346922f64099450269716dafe8c7d257bdc043", + "dist/2024-02-04/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "d16d3c5da39586678fa34932f597294277d1949ff57b99e67ce5b4dcfda9ffc6", + "dist/2024-02-04/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "defca5334cffc68e2b79917455ac7e8e210870794f23189ac0a8fdab7cfd7364", + "dist/2024-02-04/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "2c0af5b6a06fc2e539ad0774b95f021dfbd75730d900d13567ea8ee757f9ecb1", + "dist/2024-02-04/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "93bebac9baaf10f90b535a46f8a33abe55b2d468d7ec27ae53ac6ff31afe2833", + "dist/2024-02-04/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "937f84bf311714bccc88ef1e982e3261e04e5fc5419de098fbc65df15df3975c", + "dist/2024-02-04/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "87d8a6dc5ad4103eea1cf5ee76858b4e78188302fbb6e0ac846f284b388f8e7a", + "dist/2024-02-04/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "74878a2b70a1476588a5638b953711bd62c25027a9555d10e6fd4e5218a7d817", + "dist/2024-02-04/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "1fb50fa12f3c412e30df241ac6215a19bb600a04a1fb3332434f9c73bc7d2b74", + "dist/2024-02-04/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "85807b419b6f45493c60f3ab3f5d00fe7ffaca6366e6a0ec57227a30ffae2f22", + "dist/2024-02-04/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "63d233d9ac741f842c21762032ec4f0139a9b46cc8a4785bfc1b9ad6b586a128", + "dist/2024-02-04/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "199b00d4bb829f9688cbc9e8fa065d80ef4d20c1723c39f4b1a61ebfc544bc88", + "dist/2024-02-04/rustc-nightly-i686-pc-windows-gnu.tar.gz": "e66c39fbd427b6cfd027095110c954035e5a3d117b848c7cc072ca93f41bcbcb", + "dist/2024-02-04/rustc-nightly-i686-pc-windows-gnu.tar.xz": "9974067580a9d77f4722914c0d60dcb2e451cdb9c059514982bbf4721bd62ce5", + "dist/2024-02-04/rustc-nightly-i686-pc-windows-msvc.tar.gz": "e8189dd6c054dc1cba690a9805593d173de64009166b4542c30cd902cb82537a", + "dist/2024-02-04/rustc-nightly-i686-pc-windows-msvc.tar.xz": "5b9bc862dbf5bf00accf769fd70b9915c4a0faad7fc8ca648789aeefbb7f5ba6", + "dist/2024-02-04/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "b0eebf6d08c9f730458f444afd15d405465adbf2dffe93bf9a042f28d11851e4", + "dist/2024-02-04/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "248c1ecddaddee7dbdf3eabcb4a1b645005103b0ee0659d1bc71b5a59c1c9e4b", + "dist/2024-02-04/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz": "ea139b005b21e1baed7f79944af6cb2d8f24ac8c7bb009474e3a578250c6a65a", + "dist/2024-02-04/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz": "a3601a3bdc6bb998fe8a6a9ade212179addbbb684c0c47c46cb1c0632ab9fe41", + "dist/2024-02-04/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "d64bffffff505541789ab0395187506c916f5b239ef3d0875dbb0f0c79c575e8", + "dist/2024-02-04/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "5e1c528da9fa9818e5f581342346fa30b99d073dbce2241b4ebecfb7cf9674a7", + "dist/2024-02-04/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "0603be408a0bc368f669eb193c115bca687d7d6d1026fca6de5d317acb3597da", + "dist/2024-02-04/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "f61303e16f16c61f89e8dda24a5706808ef79f5fce7da8ee36b7aa3ec70f66f1", + "dist/2024-02-04/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "288e7b6b31aff284f06b14f1eb4ea0b2547aa019e8865d05710a64fe9993ddb2", + "dist/2024-02-04/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "885ef5324a55e78557b290bdf10501e27763daec209ad56f2e1840435a6e944b", + "dist/2024-02-04/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "3ccf5a674d290e1ede918516002d0b626828299edb7fe87dfc128cc9afa9770c", + "dist/2024-02-04/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "374a74c1b950f4be741f69d7f2670ac0d037a2a657361b94cd1c32892481edec", + "dist/2024-02-04/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "f21d304ea482d889319f285b5246f44461acdf6dabe288962065441bea82186b", + "dist/2024-02-04/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "d617d2b45de255f4588c2a9dc9686be554113b2683b8d8b149d1ce128da2dcc3", + "dist/2024-02-04/rustc-nightly-x86_64-apple-darwin.tar.gz": "26c662009b90638796c48a72de57e64e994491754112c5d6af0a65d24f4ef149", + "dist/2024-02-04/rustc-nightly-x86_64-apple-darwin.tar.xz": "811acb173348408b59b1ad63e0d2f8cbeccb91a86f13b432a6b70e8d6ebae937", + "dist/2024-02-04/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "3cd84e215365e8eba1aec1c6ed630e8899b1dcb36d04d52f1fbb713150eb60cd", + "dist/2024-02-04/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "454f0b75e6dd0bd893413dc7e2f36170d3af041e1e2b7d4792cc61f7cd7f27e2", + "dist/2024-02-04/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "512a0922ee16c4d5264b7ea398788651d04910dcdb3edd87bd8fc3914855c29c", + "dist/2024-02-04/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "e5a43c30c0016728aaff405ef3e28eefd8b60eb878fc31a5038aa056ae8cfb1f", + "dist/2024-02-04/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "0330724ffe7c0d4b3ed38514c303b1cbed3deb0e074e8d36f7de96c469c0c51d", + "dist/2024-02-04/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "5159bb4b9e32f64ed4712ab52dcc373e4838cec0f8e5bc16b281481a828dc84e", + "dist/2024-02-04/rustc-nightly-x86_64-unknown-illumos.tar.gz": "d8bdb12e09d76f4b4ebe9f089a6bc11f501e994ef23aefe7574b5c5a583fd2fc", + "dist/2024-02-04/rustc-nightly-x86_64-unknown-illumos.tar.xz": "301584763ea946532eca1e5be8ff7b7587ac9066c8f047f90598158e1ae6f5cf", + "dist/2024-02-04/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "3f4d36a06c74d62bb097e4b94b4ab1caf3d8d63650e0e4ef038748dab13c4413", + "dist/2024-02-04/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "33446798bf2f60451e31376286da2ad62372ef5ec048453900f6e6b3c4f0f0ee", + "dist/2024-02-04/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "9a1fc786d418a927a63ceae0999e641767de5cc8821fc57dbe0546f495d21600", + "dist/2024-02-04/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "0a36838259d73d577126cdee909b6446d62730d0d13655442312fca9cd13ce84", + "dist/2024-02-04/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "30e91ca5a0389898d9eea8a063b52dc4dd5e7f8cafba1024fbbf1d80ab28c590", + "dist/2024-02-04/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "49238b11b1626dcfc8bebf02912935922585bfdce777c8eb7bf5abfabe664af0", + "dist/2024-02-04/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "4e7d77d6a66ff3bf1de608913429e78a87ff80d8260e078d7e866a09b6ed74cc", + "dist/2024-02-04/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "ebb64953e7919ff371b1625e48cd7c9063fc7fc72f085603831ed7a1eef371d3", + "dist/2024-02-04/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "44bb652d0268e03bc333ccc90f96107e249ee3d96a688aac1f3a27161c62a176", + "dist/2024-02-04/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "e272d2633828e00ebf0a1708b807fa958cac2673b162637c4983a40f191574e7", + "dist/2024-02-04/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "aa9b56b48fda4844f56bd7a0073c91b5aa79215f61444346e9849036ba003252", + "dist/2024-02-04/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "b23367c99e79d2db72b16d9d77addd3790ddf0889987beb24c917e4e54bcf511", + "dist/2024-02-04/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "c001dba171255113d25c2e2743ca2b4cb36aa0a628da333911b92474ae8e6603", + "dist/2024-02-04/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "14a2b8a352b1fc0c6c993c5a51cf4d23ed50b6b14b092f78917808861dc4ac49", + "dist/2024-02-04/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "ec2e8f55671b1d9643d338530263feb47f99d81ff7c862ac46ad32b8459b6435", + "dist/2024-02-04/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "10b957fc066da91fa81eeeca66e2f7c97c7e7fc9d496471fd22b086a9e2bb62e", + "dist/2024-02-04/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "1dd859841cea9ac9d09a1521c57ddbe042bdc693c7df60ff34c876a8faca3745", + "dist/2024-02-04/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "b11ca576f29df7c81496c4b379435853a0bfee8ff838d2c57e1e3cded6f889eb", + "dist/2024-02-04/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "e0c53737686587010f4fd299430a0d48e47ad0f3d12e29a5d6810dceabd09b09", + "dist/2024-02-04/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "f70dc356985081a43f19c2cc6e599f2967d9c0a60b2d9be0a3939a04a88b768a", + "dist/2024-02-04/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "159c4a6ebbce05142bf6e844c4e6cfc9a90eb298f581db7521ea5fb1fd303731", + "dist/2024-02-04/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "8cb69a4ff1207c0b7944dd71e1af666e12be5c8ec0d0ec244b2e4d9b99535f29", + "dist/2024-02-04/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "0eb4218c6d271c194282ca11af2436e2ed2e51ee3b62725a04a995afb3bc6ff9", + "dist/2024-02-04/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "2f9e4d03968cf07b950d188135d231d1183d92520c76a4ded3973acb374bdefc", + "dist/2024-02-04/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "b6648b637564ffe5cf79da7c7eb73df377a2d0e0e0c66a05806af4fc87f61afa", + "dist/2024-02-04/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "09e2aae1c73f874ce4dbdb84d532264cc21d99444e0b7b1e9239a002fe0c2466", + "dist/2024-02-04/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz": "87bfeb0da3af4ad9f341482325b81d13691e749b73627eabe7c73ac5bcd126e3", + "dist/2024-02-04/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz": "2bf074d90957c17e3d8962dd8ab68d0a76f4deaf86f1104cce56d2748fc21b3a", + "dist/2024-02-04/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "7fe5ee7ce30a1fbe5c5c0f20ef311f5840eebc9466e7c4bb2082a12bad2d987c", + "dist/2024-02-04/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "43c3d64ed01e56c1961dbcde4d9c2c14a799d141d6c00ac72500ac84aafaf696", + "dist/2024-02-04/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "d6a54980ef61acb4f2422f0f621a6168055df95720fd864b58748884606e8a6b", + "dist/2024-02-04/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "d0d9fa1a65ef6dcf0d1fa1496d1682ca627cb978a8bf4a68ab3f27060daa37ed", + "dist/2024-02-04/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "fcd0539279be6ee5f2ed11f1ae0879596a29804d2415398a016b26aa1683f08a", + "dist/2024-02-04/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "cfceea6563230c64b4e77110e98dc41208c6d50b3d4bce3133abd7f66db5ce29", + "dist/2024-02-04/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "6559653ef0a9b2d52baa94f6fd14433769b3001401daac03536ad0d1528418c1", + "dist/2024-02-04/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "ac1c4f99a801e853c175735338a5485de2ad21ff633da75ced8b11ccd86ecd68", + "dist/2024-02-04/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "33835f14d65e2c21c1b69a45c70c89939a37b4d5b07660ef2acbba033c7bc8a1", + "dist/2024-02-04/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "46b8eb78bc1842b66e14e1995359cd85349ad2fd30a5b5c3a369de346dad8fa1", + "dist/2024-02-04/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "d7f0bb3f2e4d6cd6c68817cd99ef7cdd95ca274e86866edb9b76bfad071ccf37", + "dist/2024-02-04/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "7d86a0aeba42a5571b01ca7008c38854e17c067c53794c34d18ebc1cad536ae8", + "dist/2024-02-04/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "5b788121f69bc0e16dabb014d7efaef4855d20016d2d710e6bf0e35dfc16d5b0", + "dist/2024-02-04/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "b4b4ad7ecd280001aff71cf264f465e47effe52260c95fb23c884ab5fe4d51a8", + "dist/2024-02-04/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "6075688bb91902af0c114fe9619a0102f57641bf88b8902eb950f9d324bf5a25", + "dist/2024-02-04/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "908068a7088b20c1dc52eaefb9aa4314233536c40520b491e55a555283b243ce", + "dist/2024-02-04/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "5a9af3515b1b142127a9686b4f41d4c8050a496e0387a2a2703fe092bffaeb68", + "dist/2024-02-04/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "6796dbdeadd39bc66686bbdf9966fc488684543f806c25315c3a682c4c989c58", + "dist/2024-02-04/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "4f763f33318529e1d400d2058b8ff8de6d29e37de0744a8e0ae17ae677465c81", + "dist/2024-02-04/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "18aa04c9e8d00593f11b5e593a64875197e3db7de752215882d247a39c71ef0d", + "dist/2024-02-04/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "5be7c353d1e1f8445936f1572b5d99ca190a914c71341bb855048c5003c0cda2", + "dist/2024-02-04/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "1342bf737bba2e9787203da78d859f40739af4c57e9ec5bc0e07966e91388813", + "dist/2024-02-04/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "0776b76ae5338f186f631a1f0e6f755d03612892399d96f3c2d9c59ba9f094c3", + "dist/2024-02-04/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "36d491cc2eb35250536d3b053d180835c8041d9f6ed96f243c04e9644d040c96", + "dist/2024-02-04/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "185e2dee21941bc4c3e8edcf5f12d334b2c339f3f388f182a8ae519928e907e4", + "dist/2024-02-04/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "d770b13ad43852d6e91bea1747b6e82b1cddc716307f8df4dd95941df76a1355" } } diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 1ef8cf7de3c..808fb0c07ea 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -83,6 +83,7 @@ static TARGETS: &[&str] = &[ "armebv7r-none-eabihf", "armv7r-none-eabi", "armv7r-none-eabihf", + "armv8r-none-eabihf", "armv7s-apple-ios", "bpfeb-unknown-none", "bpfel-unknown-none", diff --git a/src/tools/cargo b/src/tools/cargo -Subproject cdf84b69d0416c57ac9dc3459af80dfb4883d27 +Subproject ccc84ccec4b7340eb916aefda1cb3e2fe17d8e7 diff --git a/src/tools/clippy/.github/driver.sh b/src/tools/clippy/.github/driver.sh index c05c6ecc115..40a2aad0f53 100644..100755 --- a/src/tools/clippy/.github/driver.sh +++ b/src/tools/clippy/.github/driver.sh @@ -11,9 +11,16 @@ if [[ ${OS} == "Windows" ]]; then else desired_sysroot=/tmp fi +# Set --sysroot in command line sysroot=$(./target/debug/clippy-driver --sysroot $desired_sysroot --print sysroot) test "$sysroot" = $desired_sysroot +# Set --sysroot in arg_file.txt and pass @arg_file.txt to command line +echo "--sysroot=$desired_sysroot" > arg_file.txt +sysroot=$(./target/debug/clippy-driver @arg_file.txt --print sysroot) +test "$sysroot" = $desired_sysroot + +# Setting SYSROOT in command line sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot) test "$sysroot" = $desired_sysroot @@ -24,6 +31,14 @@ test "$sysroot" = $desired_sysroot SYSROOT=/tmp RUSTFLAGS="--sysroot=$(rustc --print sysroot)" ../target/debug/cargo-clippy clippy --verbose ) +# Check that the --sysroot argument is only passed once via arg_file.txt (SYSROOT is ignored) +( + echo "fn main() {}" > target/driver_test.rs + echo "--sysroot="$(./target/debug/clippy-driver --print sysroot)"" > arg_file.txt + echo "--verbose" >> arg_file.txt + SYSROOT=/tmp ./target/debug/clippy-driver @arg_file.txt ./target/driver_test.rs +) + # Make sure this isn't set - clippy-driver should cope without it unset CARGO_MANIFEST_DIR diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 5fa45ceeb39..9b853567219 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -6,11 +6,65 @@ document. ## Unreleased / Beta / In Rust Nightly -[09ac14c9...master](https://github.com/rust-lang/rust-clippy/compare/09ac14c9...master) +[a859e5cc...master](https://github.com/rust-lang/rust-clippy/compare/a859e5cc...master) + +## Rust 1.76 + +Current stable, released 2024-02-08 + +[View all 85 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-11-02T20%3A23%3A40Z..2023-12-16T13%3A11%3A08Z+base%3Amaster) + +### New Lints + +- [`infinite_loop`] + [#11829](https://github.com/rust-lang/rust-clippy/pull/11829) +- [`ineffective_open_options`] + [#11902](https://github.com/rust-lang/rust-clippy/pull/11902) +- [`uninhabited_references`] + [#11878](https://github.com/rust-lang/rust-clippy/pull/11878) +- [`repeat_vec_with_capacity`] + [#11597](https://github.com/rust-lang/rust-clippy/pull/11597) +- [`test_attr_in_doctest`] + [#11872](https://github.com/rust-lang/rust-clippy/pull/11872) +- [`option_map_or_err_ok`] + [#11864](https://github.com/rust-lang/rust-clippy/pull/11864) +- [`join_absolute_paths`] + [#11453](https://github.com/rust-lang/rust-clippy/pull/11453) +- [`impl_hash_borrow_with_str_and_bytes`] + [#11781](https://github.com/rust-lang/rust-clippy/pull/11781) +- [`iter_over_hash_type`] + [#11791](https://github.com/rust-lang/rust-clippy/pull/11791) + +### Moves and Deprecations + +- Renamed `blocks_in_if_conditions` to [`blocks_in_conditions`] + [#11853](https://github.com/rust-lang/rust-clippy/pull/11853) +- Moved [`implied_bounds_in_impls`] to `complexity` (Now warn-by-default) + [#11867](https://github.com/rust-lang/rust-clippy/pull/11867) +- Moved [`if_same_then_else`] to `style` (Now warn-by-default) + [#11809](https://github.com/rust-lang/rust-clippy/pull/11809) + +### Enhancements + +- [`missing_safety_doc`], [`unnecessary_safety_doc`], [`missing_panics_doc`], [`missing_errors_doc`]: + Added the [`check-private-items`] configuration to enable lints on private items + [#11842](https://github.com/rust-lang/rust-clippy/pull/11842) + +### ICE Fixes + +- [`impl_trait_in_params`]: No longer crashes when a function has generics but no function parameters + [#11804](https://github.com/rust-lang/rust-clippy/pull/11804) +- [`unused_enumerate_index`]: No longer crashes on empty tuples + [#11756](https://github.com/rust-lang/rust-clippy/pull/11756) + +### Others + +- Clippy now respects the `CARGO` environment value + [#11944](https://github.com/rust-lang/rust-clippy/pull/11944) ## Rust 1.75 -Current stable, released 2023-12-28 +Released 2023-12-28 [View all 69 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2023-09-25T11%3A47%3A47Z..2023-11-02T16%3A41%3A59Z+base%3Amaster) @@ -5198,6 +5252,7 @@ Released 2018-09-13 [`implied_bounds_in_impls`]: https://rust-lang.github.io/rust-clippy/master/index.html#implied_bounds_in_impls [`impossible_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#impossible_comparisons [`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops +[`incompatible_msrv`]: https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv [`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping [`inconsistent_struct_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor [`incorrect_clone_impl_on_copy_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#incorrect_clone_impl_on_copy_type @@ -5276,6 +5331,7 @@ Released 2018-09-13 [`let_with_type_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_with_type_underscore [`lines_filter_map_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#lines_filter_map_ok [`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist +[`lint_groups_priority`]: https://rust-lang.github.io/rust-clippy/master/index.html#lint_groups_priority [`little_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#little_endian_bytes [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal @@ -5284,6 +5340,7 @@ Released 2018-09-13 [`manual_assert`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert [`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn [`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits +[`manual_c_str_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals [`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp [`manual_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter [`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map @@ -5523,6 +5580,7 @@ Released 2018-09-13 [`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing [`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes [`redundant_type_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_type_annotations +[`ref_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_as_ptr [`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref @@ -5622,6 +5680,7 @@ Released 2018-09-13 [`to_digit_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_digit_is_some [`to_string_in_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_display [`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_format_args +[`to_string_trait_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_trait_impl [`todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo [`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments [`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines @@ -5677,6 +5736,7 @@ Released 2018-09-13 [`unnecessary_mut_passed`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_mut_passed [`unnecessary_operation`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_operation [`unnecessary_owned_empty_strings`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_owned_empty_strings +[`unnecessary_result_map_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_result_map_or_else [`unnecessary_safety_comment`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_comment [`unnecessary_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_safety_doc [`unnecessary_self_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_self_imports @@ -5819,4 +5879,6 @@ Released 2018-09-13 [`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow [`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items [`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior +[`allow-comparison-to-zero`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-comparison-to-zero +[`allowed-wildcard-imports`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-wildcard-imports <!-- end autogenerated links to configuration documentation --> diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index eda20531e40..321424880d1 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.77" +version = "0.1.78" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index 7f7aff92bf1..f2357e2b5de 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -151,6 +151,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold) * [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one) * [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map) +* [`manual_c_str_literals`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_c_str_literals) ## `cognitive-complexity-threshold` @@ -828,3 +829,35 @@ exported visibility, or whether they are marked as "pub". * [`pub_underscore_fields`](https://rust-lang.github.io/rust-clippy/master/index.html#pub_underscore_fields) +## `allow-comparison-to-zero` +Don't lint when comparing the result of a modulo operation to zero. + +**Default Value:** `true` + +--- +**Affected lints:** +* [`modulo_arithmetic`](https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic) + + +## `allowed-wildcard-imports` +List of path segments allowed to have wildcard imports. + +#### Example + +```toml +allowed-wildcard-imports = [ "utils", "common" ] +``` + +#### Noteworthy + +1. This configuration has no effects if used with `warn_on_all_wildcard_imports = true`. +2. Paths with any segment that containing the word 'prelude' +are already allowed by default. + +**Default Value:** `[]` + +--- +**Affected lints:** +* [`wildcard_imports`](https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports) + + diff --git a/src/tools/clippy/clippy_config/Cargo.toml b/src/tools/clippy/clippy_config/Cargo.toml index 74b8e5eaa1c..2edc5ed592c 100644 --- a/src/tools/clippy/clippy_config/Cargo.toml +++ b/src/tools/clippy/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.77" +version = "0.1.78" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs index 4e9ddbf8259..9741b94d504 100644 --- a/src/tools/clippy/clippy_config/src/conf.rs +++ b/src/tools/clippy/clippy_config/src/conf.rs @@ -260,7 +260,7 @@ define_Conf! { /// /// Suppress lints whenever the suggested change would cause breakage for other crates. (avoid_breaking_exported_api: bool = true), - /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP. + /// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP, MANUAL_C_STR_LITERALS. /// /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` #[default_text = ""] @@ -567,6 +567,26 @@ define_Conf! { /// Lint "public" fields in a struct that are prefixed with an underscore based on their /// exported visibility, or whether they are marked as "pub". (pub_underscore_fields_behavior: PubUnderscoreFieldsBehaviour = PubUnderscoreFieldsBehaviour::PubliclyExported), + /// Lint: MODULO_ARITHMETIC. + /// + /// Don't lint when comparing the result of a modulo operation to zero. + (allow_comparison_to_zero: bool = true), + /// Lint: WILDCARD_IMPORTS. + /// + /// List of path segments allowed to have wildcard imports. + /// + /// #### Example + /// + /// ```toml + /// allowed-wildcard-imports = [ "utils", "common" ] + /// ``` + /// + /// #### Noteworthy + /// + /// 1. This configuration has no effects if used with `warn_on_all_wildcard_imports = true`. + /// 2. Paths with any segment that containing the word 'prelude' + /// are already allowed by default. + (allowed_wildcard_imports: FxHashSet<String> = FxHashSet::default()), } /// Search for the configuration file. diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs index 533e375a310..5449feed090 100644 --- a/src/tools/clippy/clippy_config/src/lib.rs +++ b/src/tools/clippy/clippy_config/src/lib.rs @@ -4,7 +4,9 @@ #![allow( clippy::must_use_candidate, clippy::missing_panics_doc, - rustc::untranslatable_diagnostic_trivial + rustc::diagnostic_outside_of_impl, + rustc::untranslatable_diagnostic, + rustc::untranslatable_diagnostic_trivial, )] extern crate rustc_ast; diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs index 72d5b9aff28..f4389db627d 100644 --- a/src/tools/clippy/clippy_config/src/msrvs.rs +++ b/src/tools/clippy/clippy_config/src/msrvs.rs @@ -3,6 +3,7 @@ use rustc_semver::RustcVersion; use rustc_session::Session; use rustc_span::{sym, Symbol}; use serde::Deserialize; +use std::fmt; macro_rules! msrv_aliases { ($($major:literal,$minor:literal,$patch:literal { @@ -16,6 +17,8 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,77,0 { C_STR_LITERALS } + 1,76,0 { PTR_FROM_REF } 1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE } 1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN } 1,68,0 { PATH_MAIN_SEPARATOR_STR } @@ -58,6 +61,16 @@ pub struct Msrv { stack: Vec<RustcVersion>, } +impl fmt::Display for Msrv { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(msrv) = self.current() { + write!(f, "{msrv}") + } else { + f.write_str("1.0.0") + } + } +} + impl<'de> Deserialize<'de> for Msrv { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml index 416e9a680dd..6e6e315bb65 100644 --- a/src/tools/clippy/clippy_lints/Cargo.toml +++ b/src/tools/clippy/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.77" +version = "0.1.78" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/src/tools/clippy/clippy_lints/src/absolute_paths.rs b/src/tools/clippy/clippy_lints/src/absolute_paths.rs index 3822b83b4bc..8ba661afeeb 100644 --- a/src/tools/clippy/clippy_lints/src/absolute_paths.rs +++ b/src/tools/clippy/clippy_lints/src/absolute_paths.rs @@ -62,7 +62,7 @@ impl LateLintPass<'_> for AbsolutePaths { } = self; if !path.span.from_expansion() - && let Some(node) = cx.tcx.opt_hir_node(hir_id) + && let node = cx.tcx.hir_node(hir_id) && !matches!(node, Node::Item(item) if matches!(item.kind, ItemKind::Use(_, _))) && let [first, rest @ ..] = path.segments // Handle `::std` diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs index e11f83f2260..2d1c250ace9 100644 --- a/src/tools/clippy/clippy_lints/src/booleans.rs +++ b/src/tools/clippy/clippy_lints/src/booleans.rs @@ -499,6 +499,7 @@ struct NotSimplificationVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx Expr<'_>) { if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind + && !expr.span.from_expansion() && !inner.span.from_expansion() && let Some(suggestion) = simplify_not(self.cx, inner) && self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow diff --git a/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs b/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs new file mode 100644 index 00000000000..a39b972b56a --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/cargo/lint_groups_priority.rs @@ -0,0 +1,168 @@ +use super::LINT_GROUPS_PRIORITY; +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::Applicability; +use rustc_lint::{unerased_lint_store, LateContext}; +use rustc_span::{BytePos, Pos, SourceFile, Span, SyntaxContext}; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; +use std::ops::Range; +use std::path::Path; +use toml::Spanned; + +#[derive(Deserialize, Serialize, Debug)] +struct LintConfigTable { + level: String, + priority: Option<i64>, +} + +#[derive(Deserialize, Debug)] +#[serde(untagged)] +enum LintConfig { + Level(String), + Table(LintConfigTable), +} + +impl LintConfig { + fn level(&self) -> &str { + match self { + LintConfig::Level(level) => level, + LintConfig::Table(table) => &table.level, + } + } + + fn priority(&self) -> i64 { + match self { + LintConfig::Level(_) => 0, + LintConfig::Table(table) => table.priority.unwrap_or(0), + } + } + + fn is_implicit(&self) -> bool { + if let LintConfig::Table(table) = self { + table.priority.is_none() + } else { + true + } + } +} + +type LintTable = BTreeMap<Spanned<String>, Spanned<LintConfig>>; + +#[derive(Deserialize, Debug)] +struct Lints { + #[serde(default)] + rust: LintTable, + #[serde(default)] + clippy: LintTable, +} + +#[derive(Deserialize, Debug)] +struct CargoToml { + lints: Lints, +} + +#[derive(Default, Debug)] +struct LintsAndGroups { + lints: Vec<Spanned<String>>, + groups: Vec<(Spanned<String>, Spanned<LintConfig>)>, +} + +fn toml_span(range: Range<usize>, file: &SourceFile) -> Span { + Span::new( + file.start_pos + BytePos::from_usize(range.start), + file.start_pos + BytePos::from_usize(range.end), + SyntaxContext::root(), + None, + ) +} + +fn check_table(cx: &LateContext<'_>, table: LintTable, groups: &FxHashSet<&str>, file: &SourceFile) { + let mut by_priority = BTreeMap::<_, LintsAndGroups>::new(); + for (name, config) in table { + let lints_and_groups = by_priority.entry(config.as_ref().priority()).or_default(); + if groups.contains(name.get_ref().as_str()) { + lints_and_groups.groups.push((name, config)); + } else { + lints_and_groups.lints.push(name); + } + } + let low_priority = by_priority + .iter() + .find(|(_, lints_and_groups)| !lints_and_groups.lints.is_empty()) + .map_or(-1, |(&lowest_lint_priority, _)| lowest_lint_priority - 1); + + for (priority, LintsAndGroups { lints, groups }) in by_priority { + let Some(last_lint_alphabetically) = lints.last() else { + continue; + }; + + for (group, config) in groups { + span_lint_and_then( + cx, + LINT_GROUPS_PRIORITY, + toml_span(group.span(), file), + &format!( + "lint group `{}` has the same priority ({priority}) as a lint", + group.as_ref() + ), + |diag| { + let config_span = toml_span(config.span(), file); + if config.as_ref().is_implicit() { + diag.span_label(config_span, "has an implicit priority of 0"); + } + // add the label to next lint after this group that has the same priority + let lint = lints + .iter() + .filter(|lint| lint.span().start > group.span().start) + .min_by_key(|lint| lint.span().start) + .unwrap_or(last_lint_alphabetically); + diag.span_label(toml_span(lint.span(), file), "has the same priority as this lint"); + diag.note("the order of the lints in the table is ignored by Cargo"); + let mut suggestion = String::new(); + Serialize::serialize( + &LintConfigTable { + level: config.as_ref().level().into(), + priority: Some(low_priority), + }, + toml::ser::ValueSerializer::new(&mut suggestion), + ) + .unwrap(); + diag.span_suggestion_verbose( + config_span, + format!( + "to have lints override the group set `{}` to a lower priority", + group.as_ref() + ), + suggestion, + Applicability::MaybeIncorrect, + ); + }, + ); + } + } +} + +pub fn check(cx: &LateContext<'_>) { + if let Ok(file) = cx.tcx.sess.source_map().load_file(Path::new("Cargo.toml")) + && let Some(src) = file.src.as_deref() + && let Ok(cargo_toml) = toml::from_str::<CargoToml>(src) + { + let mut rustc_groups = FxHashSet::default(); + let mut clippy_groups = FxHashSet::default(); + for (group, ..) in unerased_lint_store(cx.tcx.sess).get_lint_groups() { + match group.split_once("::") { + None => { + rustc_groups.insert(group); + }, + Some(("clippy", group)) => { + clippy_groups.insert(group); + }, + _ => {}, + } + } + + check_table(cx, cargo_toml.lints.rust, &rustc_groups, &file); + check_table(cx, cargo_toml.lints.clippy, &clippy_groups, &file); + } +} diff --git a/src/tools/clippy/clippy_lints/src/cargo/mod.rs b/src/tools/clippy/clippy_lints/src/cargo/mod.rs index d8107f61f37..95d5449781b 100644 --- a/src/tools/clippy/clippy_lints/src/cargo/mod.rs +++ b/src/tools/clippy/clippy_lints/src/cargo/mod.rs @@ -1,5 +1,6 @@ mod common_metadata; mod feature_name; +mod lint_groups_priority; mod multiple_crate_versions; mod wildcard_dependencies; @@ -165,6 +166,43 @@ declare_clippy_lint! { "wildcard dependencies being used" } +declare_clippy_lint! { + /// ### What it does + /// Checks for lint groups with the same priority as lints in the `Cargo.toml` + /// [`[lints]` table](https://doc.rust-lang.org/cargo/reference/manifest.html#the-lints-section). + /// + /// This lint will be removed once [cargo#12918](https://github.com/rust-lang/cargo/issues/12918) + /// is resolved. + /// + /// ### Why is this bad? + /// The order of lints in the `[lints]` is ignored, to have a lint override a group the + /// `priority` field needs to be used, otherwise the sort order is undefined. + /// + /// ### Known problems + /// Does not check lints inherited using `lints.workspace = true` + /// + /// ### Example + /// ```toml + /// # Passed as `--allow=clippy::similar_names --warn=clippy::pedantic` + /// # which results in `similar_names` being `warn` + /// [lints.clippy] + /// pedantic = "warn" + /// similar_names = "allow" + /// ``` + /// Use instead: + /// ```toml + /// # Passed as `--warn=clippy::pedantic --allow=clippy::similar_names` + /// # which results in `similar_names` being `allow` + /// [lints.clippy] + /// pedantic = { level = "warn", priority = -1 } + /// similar_names = "allow" + /// ``` + #[clippy::version = "1.76.0"] + pub LINT_GROUPS_PRIORITY, + correctness, + "a lint group in `Cargo.toml` at the same priority as a lint" +} + pub struct Cargo { pub allowed_duplicate_crates: FxHashSet<String>, pub ignore_publish: bool, @@ -175,7 +213,8 @@ impl_lint_pass!(Cargo => [ REDUNDANT_FEATURE_NAMES, NEGATIVE_FEATURE_NAMES, MULTIPLE_CRATE_VERSIONS, - WILDCARD_DEPENDENCIES + WILDCARD_DEPENDENCIES, + LINT_GROUPS_PRIORITY, ]); impl LateLintPass<'_> for Cargo { @@ -188,6 +227,8 @@ impl LateLintPass<'_> for Cargo { ]; static WITH_DEPS_LINTS: &[&Lint] = &[MULTIPLE_CRATE_VERSIONS]; + lint_groups_priority::check(cx); + if !NO_DEPS_LINTS .iter() .all(|&lint| is_lint_allowed(cx, lint, CRATE_HIR_ID)) diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs index 91bad8256ec..0f29743856a 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -68,9 +68,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let map = cx.tcx.hir(); - if let Some(parent_id) = map.opt_parent_id(expr.hir_id) - && let Some(parent) = cx.tcx.opt_hir_node(parent_id) - { + if let Some(parent_id) = map.opt_parent_id(expr.hir_id) { + let parent = cx.tcx.hir_node(parent_id); let expr = match parent { Node::Block(block) => { if let Some(parent_expr) = block.expr { diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs index e05b8f66d86..14f2f4a7f59 100644 --- a/src/tools/clippy/clippy_lints/src/casts/mod.rs +++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs @@ -18,6 +18,7 @@ mod fn_to_numeric_cast_any; mod fn_to_numeric_cast_with_truncation; mod ptr_as_ptr; mod ptr_cast_constness; +mod ref_as_ptr; mod unnecessary_cast; mod utils; mod zero_ptr; @@ -689,6 +690,30 @@ declare_clippy_lint! { "using `0 as *{const, mut} T`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for casts of references to pointer using `as` + /// and suggests `std::ptr::from_ref` and `std::ptr::from_mut` instead. + /// + /// ### Why is this bad? + /// Using `as` casts may result in silently changing mutability or type. + /// + /// ### Example + /// ```no_run + /// let a_ref = &1; + /// let a_ptr = a_ref as *const _; + /// ``` + /// Use instead: + /// ```no_run + /// let a_ref = &1; + /// let a_ptr = std::ptr::from_ref(a_ref); + /// ``` + #[clippy::version = "1.77.0"] + pub REF_AS_PTR, + pedantic, + "using `as` to cast a reference to pointer" +} + pub struct Casts { msrv: Msrv, } @@ -724,6 +749,7 @@ impl_lint_pass!(Casts => [ AS_PTR_CAST_MUT, CAST_NAN_TO_INT, ZERO_PTR, + REF_AS_PTR, ]); impl<'tcx> LateLintPass<'tcx> for Casts { @@ -771,7 +797,9 @@ impl<'tcx> LateLintPass<'tcx> for Casts { as_underscore::check(cx, expr, cast_to_hir); - if self.msrv.meets(msrvs::BORROW_AS_PTR) { + if self.msrv.meets(msrvs::PTR_FROM_REF) { + ref_as_ptr::check(cx, expr, cast_expr, cast_to_hir); + } else if self.msrv.meets(msrvs::BORROW_AS_PTR) { borrow_as_ptr::check(cx, expr, cast_expr, cast_to_hir); } } diff --git a/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs new file mode 100644 index 00000000000..d600d2aec1b --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs @@ -0,0 +1,55 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_no_std_crate; +use clippy_utils::source::snippet_with_applicability; +use clippy_utils::sugg::Sugg; +use rustc_errors::Applicability; +use rustc_hir::{Expr, Mutability, Ty, TyKind}; +use rustc_lint::LateContext; +use rustc_middle::ty::{self, TypeAndMut}; + +use super::REF_AS_PTR; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to_hir_ty: &Ty<'_>) { + let (cast_from, cast_to) = ( + cx.typeck_results().expr_ty(cast_expr), + cx.typeck_results().expr_ty(expr), + ); + + if matches!(cast_from.kind(), ty::Ref(..)) + && let ty::RawPtr(TypeAndMut { mutbl: to_mutbl, .. }) = cast_to.kind() + { + let core_or_std = if is_no_std_crate(cx) { "core" } else { "std" }; + let fn_name = match to_mutbl { + Mutability::Not => "from_ref", + Mutability::Mut => "from_mut", + }; + + let mut app = Applicability::MachineApplicable; + let turbofish = match &cast_to_hir_ty.kind { + TyKind::Infer => String::new(), + TyKind::Ptr(mut_ty) => { + if matches!(mut_ty.ty.kind, TyKind::Infer) { + String::new() + } else { + format!( + "::<{}>", + snippet_with_applicability(cx, mut_ty.ty.span, "/* type */", &mut app) + ) + } + }, + _ => return, + }; + + let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut app); + + span_lint_and_sugg( + cx, + REF_AS_PTR, + expr.span, + "reference as raw pointer", + "try", + format!("{core_or_std}::ptr::{fn_name}{turbofish}({cast_expr_sugg})"), + app, + ); + } +} diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index bb86b6f3075..81d0def4322 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -144,8 +144,7 @@ pub(super) fn check<'tcx>( if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) { if let Some(id) = path_to_local(cast_expr) - && let Some(span) = cx.tcx.hir().opt_span(id) - && !span.eq_ctxt(cast_expr.span) + && !cx.tcx.hir().span(id).eq_ctxt(cast_expr.span) { // Binding context is different than the identifiers context. // Weird macro wizardry could be involved here. diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 639edd8da30..0a5baabd973 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -71,6 +71,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::borrow_deref_ref::BORROW_DEREF_REF_INFO, crate::box_default::BOX_DEFAULT_INFO, crate::cargo::CARGO_COMMON_METADATA_INFO, + crate::cargo::LINT_GROUPS_PRIORITY_INFO, crate::cargo::MULTIPLE_CRATE_VERSIONS_INFO, crate::cargo::NEGATIVE_FEATURE_NAMES_INFO, crate::cargo::REDUNDANT_FEATURE_NAMES_INFO, @@ -96,6 +97,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION_INFO, crate::casts::PTR_AS_PTR_INFO, crate::casts::PTR_CAST_CONSTNESS_INFO, + crate::casts::REF_AS_PTR_INFO, crate::casts::UNNECESSARY_CAST_INFO, crate::casts::ZERO_PTR_INFO, crate::checked_conversions::CHECKED_CONVERSIONS_INFO, @@ -212,6 +214,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO, crate::implicit_saturating_sub::IMPLICIT_SATURATING_SUB_INFO, crate::implied_bounds_in_impls::IMPLIED_BOUNDS_IN_IMPLS_INFO, + crate::incompatible_msrv::INCOMPATIBLE_MSRV_INFO, crate::inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR_INFO, crate::index_refutable_slice::INDEX_REFUTABLE_SLICE_INFO, crate::indexing_slicing::INDEXING_SLICING_INFO, @@ -384,6 +387,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::ITER_SKIP_ZERO_INFO, crate::methods::ITER_WITH_DRAIN_INFO, crate::methods::JOIN_ABSOLUTE_PATHS_INFO, + crate::methods::MANUAL_C_STR_LITERALS_INFO, crate::methods::MANUAL_FILTER_MAP_INFO, crate::methods::MANUAL_FIND_MAP_INFO, crate::methods::MANUAL_IS_VARIANT_AND_INFO, @@ -452,6 +456,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::UNNECESSARY_JOIN_INFO, crate::methods::UNNECESSARY_LAZY_EVALUATIONS_INFO, crate::methods::UNNECESSARY_LITERAL_UNWRAP_INFO, + crate::methods::UNNECESSARY_RESULT_MAP_OR_ELSE_INFO, crate::methods::UNNECESSARY_SORT_BY_INFO, crate::methods::UNNECESSARY_TO_OWNED_INFO, crate::methods::UNWRAP_OR_DEFAULT_INFO, @@ -656,6 +661,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::tests_outside_test_module::TESTS_OUTSIDE_TEST_MODULE_INFO, crate::thread_local_initializer_can_be_made_const::THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST_INFO, crate::to_digit_is_some::TO_DIGIT_IS_SOME_INFO, + crate::to_string_trait_impl::TO_STRING_TRAIT_IMPL_INFO, crate::trailing_empty_array::TRAILING_EMPTY_ARRAY_INFO, crate::trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS_INFO, crate::trait_bounds::TYPE_REPETITION_IN_BOUNDS_INFO, diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs index 6b0423200d7..b0f46f5c646 100644 --- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs +++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs @@ -195,7 +195,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls { && let Some(def_id) = trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::Default, def_id) && let impl_item_hir = child.id.hir_id() - && let Some(Node::ImplItem(impl_item)) = cx.tcx.opt_hir_node(impl_item_hir) + && let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir) && let ImplItemKind::Fn(_, b) = &impl_item.kind && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b) && let &Adt(adt_def, args) = cx.tcx.type_of(item.owner_id).instantiate_identity().kind() diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index ba452775015..2b4ce6ddfaa 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -226,7 +226,7 @@ declare_clippy_lint! { /// unimplemented!(); /// } /// ``` - #[clippy::version = "1.40.0"] + #[clippy::version = "1.76.0"] pub TEST_ATTR_IN_DOCTEST, suspicious, "presence of `#[test]` in code examples" diff --git a/src/tools/clippy/clippy_lints/src/empty_drop.rs b/src/tools/clippy/clippy_lints/src/empty_drop.rs index 1d2b907b948..74db250b3ae 100644 --- a/src/tools/clippy/clippy_lints/src/empty_drop.rs +++ b/src/tools/clippy/clippy_lints/src/empty_drop.rs @@ -42,7 +42,7 @@ impl LateLintPass<'_> for EmptyDrop { }) = item.kind && trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait() && let impl_item_hir = child.id.hir_id() - && let Some(Node::ImplItem(impl_item)) = cx.tcx.opt_hir_node(impl_item_hir) + && let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir) && let ImplItemKind::Fn(_, b) = &impl_item.kind && let Body { value: func_expr, .. } = cx.tcx.hir().body(*b) && let func_expr = peel_blocks(func_expr) diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index b7776263060..218d7c6c01a 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -123,11 +123,11 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { // TODO: Replace with Map::is_argument(..) when it's fixed fn is_argument(tcx: TyCtxt<'_>, id: HirId) -> bool { - match tcx.opt_hir_node(id) { - Some(Node::Pat(Pat { + match tcx.hir_node(id) { + Node::Pat(Pat { kind: PatKind::Binding(..), .. - })) => (), + }) => (), _ => return false, } diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 450cee4007c..40be71a0e5d 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -3,15 +3,14 @@ use clippy_utils::higher::VecArgs; use clippy_utils::source::snippet_opt; use clippy_utils::ty::type_diagnostic_name; use clippy_utils::usage::{local_used_after_expr, local_used_in}; -use clippy_utils::{higher, is_adjusted, path_to_local, path_to_local_id}; +use clippy_utils::{get_path_from_caller_to_method_type, higher, is_adjusted, path_to_local, path_to_local_id}; use rustc_errors::Applicability; -use rustc_hir::def_id::DefId; use rustc_hir::{BindingAnnotation, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, TyKind, Unsafety}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{ - self, Binder, ClosureArgs, ClosureKind, EarlyBinder, FnSig, GenericArg, GenericArgKind, GenericArgsRef, - ImplPolarity, List, Region, RegionKind, Ty, TypeVisitableExt, TypeckResults, + self, Binder, ClosureArgs, ClosureKind, FnSig, GenericArg, GenericArgKind, ImplPolarity, List, Region, RegionKind, + Ty, TypeVisitableExt, TypeckResults, }; use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; @@ -21,8 +20,8 @@ use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; declare_clippy_lint! { /// ### What it does /// Checks for closures which just call another function where - /// the function can be called directly. `unsafe` functions or calls where types - /// get adjusted are ignored. + /// the function can be called directly. `unsafe` functions, calls where types + /// get adjusted or where the callee is marked `#[track_caller]` are ignored. /// /// ### Why is this bad? /// Needlessly creating a closure adds code for no benefit @@ -136,7 +135,14 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { .map_or(callee_ty, |a| a.target.peel_refs()); let sig = match callee_ty_adjusted.kind() { - ty::FnDef(def, _) => cx.tcx.fn_sig(def).skip_binder().skip_binder(), + ty::FnDef(def, _) => { + // Rewriting `x(|| f())` to `x(f)` where f is marked `#[track_caller]` moves the `Location` + if cx.tcx.has_attr(*def, sym::track_caller) { + return; + } + + cx.tcx.fn_sig(def).skip_binder().skip_binder() + }, ty::FnPtr(sig) => sig.skip_binder(), ty::Closure(_, subs) => cx .tcx @@ -186,6 +192,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { }, ExprKind::MethodCall(path, self_, args, _) if check_inputs(typeck, body.params, Some(self_), args) => { if let Some(method_def_id) = typeck.type_dependent_def_id(body.value.hir_id) + && !cx.tcx.has_attr(method_def_id, sym::track_caller) && check_sig(cx, closure, cx.tcx.fn_sig(method_def_id).skip_binder().skip_binder()) { span_lint_and_then( @@ -195,11 +202,12 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { "redundant closure", |diag| { let args = typeck.node_args(body.value.hir_id); - let name = get_ufcs_type_name(cx, method_def_id, args); + let caller = self_.hir_id.owner.def_id; + let type_name = get_path_from_caller_to_method_type(cx.tcx, caller, method_def_id, args); diag.span_suggestion( expr.span, "replace the closure with the method itself", - format!("{}::{}", name, path.ident.name), + format!("{}::{}", type_name, path.ident.name), Applicability::MachineApplicable, ); }, @@ -301,27 +309,3 @@ fn has_late_bound_to_non_late_bound_regions(from_sig: FnSig<'_>, to_sig: FnSig<' .zip(to_sig.inputs_and_output) .any(|(from_ty, to_ty)| check_ty(from_ty, to_ty)) } - -fn get_ufcs_type_name<'tcx>(cx: &LateContext<'tcx>, method_def_id: DefId, args: GenericArgsRef<'tcx>) -> String { - let assoc_item = cx.tcx.associated_item(method_def_id); - let def_id = assoc_item.container_id(cx.tcx); - match assoc_item.container { - ty::TraitContainer => cx.tcx.def_path_str(def_id), - ty::ImplContainer => { - let ty = cx.tcx.type_of(def_id).instantiate_identity(); - match ty.kind() { - ty::Adt(adt, _) => cx.tcx.def_path_str(adt.did()), - ty::Array(..) - | ty::Dynamic(..) - | ty::Never - | ty::RawPtr(_) - | ty::Ref(..) - | ty::Slice(_) - | ty::Tuple(_) => { - format!("<{}>", EarlyBinder::bind(ty).instantiate(cx.tcx, args)) - }, - _ => ty.to_string(), - } - }, - } -} diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs index e8c1e5db35e..de048fef5f2 100644 --- a/src/tools/clippy/clippy_lints/src/explicit_write.rs +++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs @@ -111,7 +111,7 @@ fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>) // Find id of the local that expr_end_of_block resolves to && let ExprKind::Path(QPath::Resolved(None, expr_path)) = expr_end_of_block.kind && let Res::Local(expr_res) = expr_path.res - && let Some(Node::Pat(res_pat)) = cx.tcx.opt_hir_node(expr_res) + && let Node::Pat(res_pat) = cx.tcx.hir_node(expr_res) // Find id of the local we found in the block && let PatKind::Binding(BindingAnnotation::NONE, local_hir_id, _ident, None) = local.pat.kind diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs new file mode 100644 index 00000000000..f2f0e7d4266 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs @@ -0,0 +1,133 @@ +use clippy_config::msrvs::Msrv; +use clippy_utils::diagnostics::span_lint; +use rustc_attr::{StabilityLevel, StableSince}; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::TyCtxt; +use rustc_semver::RustcVersion; +use rustc_session::impl_lint_pass; +use rustc_span::def_id::DefId; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// + /// This lint checks that no function newer than the defined MSRV (minimum + /// supported rust version) is used in the crate. + /// + /// ### Why is this bad? + /// + /// It would prevent the crate to be actually used with the specified MSRV. + /// + /// ### Example + /// ```no_run + /// // MSRV of 1.3.0 + /// use std::thread::sleep; + /// use std::time::Duration; + /// + /// // Sleep was defined in `1.4.0`. + /// sleep(Duration::new(1, 0)); + /// ``` + /// + /// To fix this problem, either increase your MSRV or use another item + /// available in your current MSRV. + #[clippy::version = "1.77.0"] + pub INCOMPATIBLE_MSRV, + suspicious, + "ensures that all items used in the crate are available for the current MSRV" +} + +pub struct IncompatibleMsrv { + msrv: Msrv, + is_above_msrv: FxHashMap<DefId, RustcVersion>, +} + +impl_lint_pass!(IncompatibleMsrv => [INCOMPATIBLE_MSRV]); + +impl IncompatibleMsrv { + pub fn new(msrv: Msrv) -> Self { + Self { + msrv, + is_above_msrv: FxHashMap::default(), + } + } + + #[allow(clippy::cast_lossless)] + fn get_def_id_version(&mut self, tcx: TyCtxt<'_>, def_id: DefId) -> RustcVersion { + if let Some(version) = self.is_above_msrv.get(&def_id) { + return *version; + } + let version = if let Some(version) = tcx + .lookup_stability(def_id) + .and_then(|stability| match stability.level { + StabilityLevel::Stable { + since: StableSince::Version(version), + .. + } => Some(RustcVersion::new( + version.major as _, + version.minor as _, + version.patch as _, + )), + _ => None, + }) { + version + } else if let Some(parent_def_id) = tcx.opt_parent(def_id) { + self.get_def_id_version(tcx, parent_def_id) + } else { + RustcVersion::new(1, 0, 0) + }; + self.is_above_msrv.insert(def_id, version); + version + } + + fn emit_lint_if_under_msrv(&mut self, cx: &LateContext<'_>, def_id: DefId, span: Span) { + if def_id.is_local() { + // We don't check local items since their MSRV is supposed to always be valid. + return; + } + let version = self.get_def_id_version(cx.tcx, def_id); + if self.msrv.meets(version) { + return; + } + self.emit_lint_for(cx, span, version); + } + + fn emit_lint_for(&self, cx: &LateContext<'_>, span: Span, version: RustcVersion) { + span_lint( + cx, + INCOMPATIBLE_MSRV, + span, + &format!( + "current MSRV (Minimum Supported Rust Version) is `{}` but this item is stable since `{version}`", + self.msrv + ), + ); + } +} + +impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv { + extract_msrv_attr!(LateContext); + + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if self.msrv.current().is_none() { + // If there is no MSRV, then no need to check anything... + return; + } + match expr.kind { + ExprKind::MethodCall(_, _, _, span) => { + if let Some(method_did) = cx.typeck_results().type_dependent_def_id(expr.hir_id) { + self.emit_lint_if_under_msrv(cx, method_did, span); + } + }, + ExprKind::Call(call, [_]) => { + if let ExprKind::Path(qpath) = call.kind + && let Some(path_def_id) = cx.qpath_res(&qpath, call.hir_id).opt_def_id() + { + self.emit_lint_if_under_msrv(cx, path_def_id, call.span); + } + }, + _ => {}, + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs index 5417c13d079..252be30c4e2 100644 --- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs +++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs @@ -248,7 +248,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> { // Checking for slice indexing && let parent_id = map.parent_id(expr.hir_id) - && let Some(hir::Node::Expr(parent_expr)) = cx.tcx.opt_hir_node(parent_id) + && let hir::Node::Expr(parent_expr) = cx.tcx.hir_node(parent_id) && let hir::ExprKind::Index(_, index_expr, _) = parent_expr.kind && let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr) && let Ok(index_value) = index_value.try_into() @@ -256,7 +256,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> { // Make sure that this slice index is read only && let maybe_addrof_id = map.parent_id(parent_id) - && let Some(hir::Node::Expr(maybe_addrof_expr)) = cx.tcx.opt_hir_node(maybe_addrof_id) + && let hir::Node::Expr(maybe_addrof_expr) = cx.tcx.hir_node(maybe_addrof_id) && let hir::ExprKind::AddrOf(_kind, hir::Mutability::Not, _inner_expr) = maybe_addrof_expr.kind { use_info.index_use.push((index_value, map.span(parent_expr.hir_id))); diff --git a/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs b/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs index 8110c1970d9..6c6eff9ba48 100644 --- a/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs +++ b/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs @@ -34,7 +34,7 @@ declare_clippy_lint! { /// let value = &my_map[key]; /// } /// ``` - #[clippy::version = "1.75.0"] + #[clippy::version = "1.76.0"] pub ITER_OVER_HASH_TYPE, restriction, "iterating over unordered hash-based types (`HashMap` and `HashSet`)" diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index c1ab020117c..27d85cde532 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -147,9 +147,9 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { && let Some(output) = parse_len_output(cx, cx.tcx.fn_sig(item.owner_id).instantiate_identity().skip_binder()) { - let (name, kind) = match cx.tcx.opt_hir_node(ty_hir_id) { - Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"), - Some(Node::Item(x)) => match x.kind { + let (name, kind) = match cx.tcx.hir_node(ty_hir_id) { + Node::ForeignItem(x) => (x.ident.name, "extern type"), + Node::Item(x) => match x.kind { ItemKind::Struct(..) => (x.ident.name, "struct"), ItemKind::Enum(..) => (x.ident.name, "enum"), ItemKind::Union(..) => (x.ident.name, "union"), diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index feb4d188f39..14bd82f9c97 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -10,7 +10,12 @@ #![feature(stmt_expr_attributes)] #![recursion_limit = "512"] #![cfg_attr(feature = "deny-warnings", deny(warnings))] -#![allow(clippy::missing_docs_in_private_items, clippy::must_use_candidate)] +#![allow( + clippy::missing_docs_in_private_items, + clippy::must_use_candidate, + rustc::diagnostic_outside_of_impl, + rustc::untranslatable_diagnostic, +)] #![warn(trivial_casts, trivial_numeric_casts)] // warn on lints, that are included in `rust-lang/rust`s bootstrap #![warn(rust_2018_idioms, unused_lifetimes)] @@ -26,6 +31,7 @@ extern crate rustc_abi; extern crate rustc_arena; extern crate rustc_ast; extern crate rustc_ast_pretty; +extern crate rustc_attr; extern crate rustc_data_structures; extern crate rustc_driver; extern crate rustc_errors; @@ -153,6 +159,7 @@ mod implicit_return; mod implicit_saturating_add; mod implicit_saturating_sub; mod implied_bounds_in_impls; +mod incompatible_msrv; mod inconsistent_struct_constructor; mod index_refutable_slice; mod indexing_slicing; @@ -325,6 +332,7 @@ mod temporary_assignment; mod tests_outside_test_module; mod thread_local_initializer_can_be_made_const; mod to_digit_is_some; +mod to_string_trait_impl; mod trailing_empty_array; mod trait_bounds; mod transmute; @@ -521,6 +529,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { ref allowed_dotfiles, ref allowed_idents_below_min_chars, ref allowed_scripts, + ref allowed_wildcard_imports, ref arithmetic_side_effects_allowed_binary, ref arithmetic_side_effects_allowed_unary, ref arithmetic_side_effects_allowed, @@ -575,6 +584,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { check_private_items, pub_underscore_fields_behavior, ref allowed_duplicate_crates, + allow_comparison_to_zero, blacklisted_names: _, cyclomatic_complexity_threshold: _, @@ -872,7 +882,12 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { )) }); store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap)); - store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports))); + store.register_late_pass(move |_| { + Box::new(wildcard_imports::WildcardImports::new( + warn_on_all_wildcard_imports, + allowed_wildcard_imports.clone(), + )) + }); store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default()); store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress)); store.register_late_pass(|_| Box::<dereference::Dereferencing<'_>>::default()); @@ -968,7 +983,12 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(default_instead_of_iter_empty::DefaultIterEmpty)); store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv()))); store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv()))); - store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold))); + store.register_late_pass(move |_| { + Box::new(operators::Operators::new( + verbose_bit_mask_threshold, + allow_comparison_to_zero, + )) + }); store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default()); store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv()))); store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone)); @@ -1094,6 +1114,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(move |_| { Box::new(thread_local_initializer_can_be_made_const::ThreadLocalInitializerCanBeMadeConst::new(msrv())) }); + store.register_late_pass(move |_| Box::new(incompatible_msrv::IncompatibleMsrv::new(msrv()))); + store.register_late_pass(|_| Box::new(to_string_trait_impl::ToStringTraitImpl)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index ffef84d1fad..f5636945f20 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -176,7 +176,7 @@ fn check_fn_inner<'tcx>( _ => None, }); for bound in lifetimes { - if !bound.is_static() && !bound.is_elided() { + if bound.res != LifetimeName::Static && !bound.is_elided() { return; } } diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs index 3c9bde86bb6..b5e39b33c6a 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mod.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs @@ -672,7 +672,7 @@ declare_clippy_lint! { /// } /// } /// ``` - #[clippy::version = "1.75.0"] + #[clippy::version = "1.76.0"] pub INFINITE_LOOP, restriction, "possibly unintended infinite loop" diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs index 62bc663191f..245a903f998 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -201,12 +201,12 @@ fn never_loop_expr<'tcx>( }) }) }, - ExprKind::Block(b, l) => { - if l.is_some() { + ExprKind::Block(b, _) => { + if b.targeted_by_break { local_labels.push((b.hir_id, false)); } let ret = never_loop_block(cx, b, local_labels, main_loop_id); - let jumped_to = l.is_some() && local_labels.pop().unwrap().1; + let jumped_to = b.targeted_by_break && local_labels.pop().unwrap().1; match ret { NeverLoopResult::Diverging if jumped_to => NeverLoopResult::Normal, _ => ret, diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs index 920a887a6fd..5f015db2b33 100644 --- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs +++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs @@ -63,7 +63,7 @@ pub(super) fn check<'tcx>( && let PatKind::Binding(bind_ann, ..) = pat.kind && !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut)) && let parent_node = cx.tcx.hir().parent_id(hir_id) - && let Some(Node::Local(parent_let_expr)) = cx.tcx.opt_hir_node(parent_node) + && let Node::Local(parent_let_expr) = cx.tcx.hir_node(parent_node) && let Some(init) = parent_let_expr.init { match init.kind { diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs index 71a83a68db9..e1768c6d976 100644 --- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs +++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs @@ -76,7 +76,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { // Also ensures the const is nonzero since zero can't be a divisor && const1 == const2 && const2 == const3 && let Some(hir_id) = path_to_local(expr3) - && let Some(Node::Pat(_)) = cx.tcx.opt_hir_node(hir_id) + && let Node::Pat(_) = cx.tcx.hir_node(hir_id) { // Apply only to params or locals with annotated types match cx.tcx.hir().find_parent(hir_id) { diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs index 1fe247dacb9..6f15fca089e 100644 --- a/src/tools/clippy/clippy_lints/src/manual_retain.rs +++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs @@ -11,6 +11,7 @@ use rustc_lint::{LateContext, LateLintPass}; use rustc_semver::RustcVersion; use rustc_session::impl_lint_pass; use rustc_span::symbol::sym; +use rustc_span::Span; const ACCEPTABLE_METHODS: [&[&str]; 5] = [ &paths::BINARYHEAP_ITER, @@ -28,6 +29,7 @@ const ACCEPTABLE_TYPES: [(rustc_span::Symbol, Option<RustcVersion>); 7] = [ (sym::Vec, None), (sym::VecDeque, None), ]; +const MAP_TYPES: [rustc_span::Symbol; 2] = [sym::BTreeMap, sym::HashMap]; declare_clippy_lint! { /// ### What it does @@ -44,6 +46,7 @@ declare_clippy_lint! { /// ```no_run /// let mut vec = vec![0, 1, 2]; /// vec.retain(|x| x % 2 == 0); + /// vec.retain(|x| x % 2 == 0); /// ``` #[clippy::version = "1.64.0"] pub MANUAL_RETAIN, @@ -74,9 +77,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualRetain { && let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id) && cx.tcx.is_diagnostic_item(sym::iterator_collect_fn, collect_def_id) { - check_into_iter(cx, parent_expr, left_expr, target_expr, &self.msrv); - check_iter(cx, parent_expr, left_expr, target_expr, &self.msrv); - check_to_owned(cx, parent_expr, left_expr, target_expr, &self.msrv); + check_into_iter(cx, left_expr, target_expr, parent_expr.span, &self.msrv); + check_iter(cx, left_expr, target_expr, parent_expr.span, &self.msrv); + check_to_owned(cx, left_expr, target_expr, parent_expr.span, &self.msrv); } } @@ -85,9 +88,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualRetain { fn check_into_iter( cx: &LateContext<'_>, - parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, target_expr: &hir::Expr<'_>, + parent_expr_span: Span, msrv: &Msrv, ) { if let hir::ExprKind::MethodCall(_, into_iter_expr, [_], _) = &target_expr.kind @@ -98,16 +101,39 @@ fn check_into_iter( && Some(into_iter_def_id) == cx.tcx.lang_items().into_iter_fn() && match_acceptable_type(cx, left_expr, msrv) && SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) + && let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = target_expr.kind + && let hir::ExprKind::Closure(closure) = closure_expr.kind + && let filter_body = cx.tcx.hir().body(closure.body) + && let [filter_params] = filter_body.params { - suggest(cx, parent_expr, left_expr, target_expr); + if match_map_type(cx, left_expr) { + if let hir::PatKind::Tuple([key_pat, value_pat], _) = filter_params.pat.kind { + if let Some(sugg) = make_sugg(cx, key_pat, value_pat, left_expr, filter_body) { + make_span_lint_and_sugg(cx, parent_expr_span, sugg); + } + } + // Cannot lint other cases because `retain` requires two parameters + } else { + // Can always move because `retain` and `filter` have the same bound on the predicate + // for other types + make_span_lint_and_sugg( + cx, + parent_expr_span, + format!( + "{}.retain({})", + snippet(cx, left_expr.span, ".."), + snippet(cx, closure_expr.span, "..") + ), + ); + } } } fn check_iter( cx: &LateContext<'_>, - parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, target_expr: &hir::Expr<'_>, + parent_expr_span: Span, msrv: &Msrv, ) { if let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind @@ -122,16 +148,50 @@ fn check_iter( && match_acceptable_def_path(cx, iter_expr_def_id) && match_acceptable_type(cx, left_expr, msrv) && SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) + && let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = filter_expr.kind + && let hir::ExprKind::Closure(closure) = closure_expr.kind + && let filter_body = cx.tcx.hir().body(closure.body) + && let [filter_params] = filter_body.params { - suggest(cx, parent_expr, left_expr, filter_expr); + match filter_params.pat.kind { + // hir::PatKind::Binding(_, _, _, None) => { + // // Be conservative now. Do nothing here. + // // TODO: Ideally, we can rewrite the lambda by stripping one level of reference + // }, + hir::PatKind::Tuple([_, _], _) => { + // the `&&` reference for the `filter` method will be auto derefed to `ref` + // so, we can directly use the lambda + // https://doc.rust-lang.org/reference/patterns.html#binding-modes + make_span_lint_and_sugg( + cx, + parent_expr_span, + format!( + "{}.retain({})", + snippet(cx, left_expr.span, ".."), + snippet(cx, closure_expr.span, "..") + ), + ); + }, + hir::PatKind::Ref(pat, _) => make_span_lint_and_sugg( + cx, + parent_expr_span, + format!( + "{}.retain(|{}| {})", + snippet(cx, left_expr.span, ".."), + snippet(cx, pat.span, ".."), + snippet(cx, filter_body.value.span, "..") + ), + ), + _ => {}, + } } } fn check_to_owned( cx: &LateContext<'_>, - parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, target_expr: &hir::Expr<'_>, + parent_expr_span: Span, msrv: &Msrv, ) { if msrv.meets(msrvs::STRING_RETAIN) @@ -147,43 +207,25 @@ fn check_to_owned( && let ty = cx.typeck_results().expr_ty(str_expr).peel_refs() && is_type_lang_item(cx, ty, hir::LangItem::String) && SpanlessEq::new(cx).eq_expr(left_expr, str_expr) - { - suggest(cx, parent_expr, left_expr, filter_expr); - } -} - -fn suggest(cx: &LateContext<'_>, parent_expr: &hir::Expr<'_>, left_expr: &hir::Expr<'_>, filter_expr: &hir::Expr<'_>) { - if let hir::ExprKind::MethodCall(_, _, [closure], _) = filter_expr.kind - && let hir::ExprKind::Closure(&hir::Closure { body, .. }) = closure.kind - && let filter_body = cx.tcx.hir().body(body) + && let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = filter_expr.kind + && let hir::ExprKind::Closure(closure) = closure_expr.kind + && let filter_body = cx.tcx.hir().body(closure.body) && let [filter_params] = filter_body.params - && let Some(sugg) = match filter_params.pat.kind { - hir::PatKind::Binding(_, _, filter_param_ident, None) => Some(format!( - "{}.retain(|{filter_param_ident}| {})", - snippet(cx, left_expr.span, ".."), - snippet(cx, filter_body.value.span, "..") - )), - hir::PatKind::Tuple([key_pat, value_pat], _) => make_sugg(cx, key_pat, value_pat, left_expr, filter_body), - hir::PatKind::Ref(pat, _) => match pat.kind { - hir::PatKind::Binding(_, _, filter_param_ident, None) => Some(format!( - "{}.retain(|{filter_param_ident}| {})", + { + if let hir::PatKind::Ref(pat, _) = filter_params.pat.kind { + make_span_lint_and_sugg( + cx, + parent_expr_span, + format!( + "{}.retain(|{}| {})", snippet(cx, left_expr.span, ".."), + snippet(cx, pat.span, ".."), snippet(cx, filter_body.value.span, "..") - )), - _ => None, - }, - _ => None, + ), + ); } - { - span_lint_and_sugg( - cx, - MANUAL_RETAIN, - parent_expr.span, - "this expression can be written more simply using `.retain()`", - "consider calling `.retain()` instead", - sugg, - Applicability::MachineApplicable, - ); + // Be conservative now. Do nothing for the `Binding` case. + // TODO: Ideally, we can rewrite the lambda by stripping one level of reference } } @@ -229,3 +271,20 @@ fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv && acceptable_msrv.map_or(true, |acceptable_msrv| msrv.meets(acceptable_msrv)) }) } + +fn match_map_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs(); + MAP_TYPES.iter().any(|ty| is_type_diagnostic_item(cx, expr_ty, *ty)) +} + +fn make_span_lint_and_sugg(cx: &LateContext<'_>, span: Span, sugg: String) { + span_lint_and_sugg( + cx, + MANUAL_RETAIN, + span, + "this expression can be written more simply using `.retain()`", + "consider calling `.retain()` instead", + sugg, + Applicability::MachineApplicable, + ); +} diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs index 9251130a305..7339362193e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs +++ b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs @@ -44,7 +44,7 @@ pub(super) fn check<'tcx>( // add note if not multi-line span_lint_and_then(cx, FILTER_NEXT, expr.span, msg, |diag| { let (applicability, pat) = if let Some(id) = path_to_local(recv) - && let Some(hir::Node::Pat(pat)) = cx.tcx.opt_hir_node(id) + && let hir::Node::Pat(pat) = cx.tcx.hir_node(id) && let hir::PatKind::Binding(BindingAnnotation(_, Mutability::Not), _, ident, _) = pat.kind { (Applicability::Unspecified, Some((pat.span, ident))) diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs b/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs new file mode 100644 index 00000000000..cb9fb373c10 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/manual_c_str_literals.rs @@ -0,0 +1,197 @@ +use clippy_config::msrvs::{self, Msrv}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::get_parent_expr; +use clippy_utils::source::snippet; +use rustc_ast::{LitKind, StrStyle}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, Node, QPath, TyKind}; +use rustc_lint::LateContext; +use rustc_span::{sym, Span, Symbol}; + +use super::MANUAL_C_STR_LITERALS; + +/// Checks: +/// - `b"...".as_ptr()` +/// - `b"...".as_ptr().cast()` +/// - `"...".as_ptr()` +/// - `"...".as_ptr().cast()` +/// +/// Iff the parent call of `.cast()` isn't `CStr::from_ptr`, to avoid linting twice. +pub(super) fn check_as_ptr<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + receiver: &'tcx Expr<'tcx>, + msrv: &Msrv, +) { + if let ExprKind::Lit(lit) = receiver.kind + && let LitKind::ByteStr(_, StrStyle::Cooked) | LitKind::Str(_, StrStyle::Cooked) = lit.node + && let casts_removed = peel_ptr_cast_ancestors(cx, expr) + && !get_parent_expr(cx, casts_removed).is_some_and( + |parent| matches!(parent.kind, ExprKind::Call(func, _) if is_c_str_function(cx, func).is_some()), + ) + && let Some(sugg) = rewrite_as_cstr(cx, lit.span) + && msrv.meets(msrvs::C_STR_LITERALS) + { + span_lint_and_sugg( + cx, + MANUAL_C_STR_LITERALS, + receiver.span, + "manually constructing a nul-terminated string", + r#"use a `c""` literal"#, + sugg, + // an additional cast may be needed, since the type of `CStr::as_ptr` and + // `"".as_ptr()` can differ and is platform dependent + Applicability::HasPlaceholders, + ); + } +} + +/// Checks if the callee is a "relevant" `CStr` function considered by this lint. +/// Returns the function name. +fn is_c_str_function(cx: &LateContext<'_>, func: &Expr<'_>) -> Option<Symbol> { + if let ExprKind::Path(QPath::TypeRelative(cstr, fn_name)) = &func.kind + && let TyKind::Path(QPath::Resolved(_, ty_path)) = &cstr.kind + && cx.tcx.lang_items().c_str() == ty_path.res.opt_def_id() + { + Some(fn_name.ident.name) + } else { + None + } +} + +/// Checks calls to the `CStr` constructor functions: +/// - `CStr::from_bytes_with_nul(..)` +/// - `CStr::from_bytes_with_nul_unchecked(..)` +/// - `CStr::from_ptr(..)` +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, func: &Expr<'_>, args: &[Expr<'_>], msrv: &Msrv) { + if let Some(fn_name) = is_c_str_function(cx, func) + && let [arg] = args + && msrv.meets(msrvs::C_STR_LITERALS) + { + match fn_name.as_str() { + name @ ("from_bytes_with_nul" | "from_bytes_with_nul_unchecked") + if !arg.span.from_expansion() + && let ExprKind::Lit(lit) = arg.kind + && let LitKind::ByteStr(_, StrStyle::Cooked) | LitKind::Str(_, StrStyle::Cooked) = lit.node => + { + check_from_bytes(cx, expr, arg, name); + }, + "from_ptr" => check_from_ptr(cx, expr, arg), + _ => {}, + } + } +} + +/// Checks `CStr::from_ptr(b"foo\0".as_ptr().cast())` +fn check_from_ptr(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>) { + if let ExprKind::MethodCall(method, lit, ..) = peel_ptr_cast(arg).kind + && method.ident.name == sym::as_ptr + && !lit.span.from_expansion() + && let ExprKind::Lit(lit) = lit.kind + && let LitKind::ByteStr(_, StrStyle::Cooked) = lit.node + && let Some(sugg) = rewrite_as_cstr(cx, lit.span) + { + span_lint_and_sugg( + cx, + MANUAL_C_STR_LITERALS, + expr.span, + "calling `CStr::from_ptr` with a byte string literal", + r#"use a `c""` literal"#, + sugg, + Applicability::MachineApplicable, + ); + } +} +/// Checks `CStr::from_bytes_with_nul(b"foo\0")` +fn check_from_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, method: &str) { + let (span, applicability) = if let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::MethodCall(method, ..) = parent.kind + && [sym::unwrap, sym::expect].contains(&method.ident.name) + { + (parent.span, Applicability::MachineApplicable) + } else if method == "from_bytes_with_nul_unchecked" { + // `*_unchecked` returns `&CStr` directly, nothing needs to be changed + (expr.span, Applicability::MachineApplicable) + } else { + // User needs to remove error handling, can't be machine applicable + (expr.span, Applicability::HasPlaceholders) + }; + + let Some(sugg) = rewrite_as_cstr(cx, arg.span) else { + return; + }; + + span_lint_and_sugg( + cx, + MANUAL_C_STR_LITERALS, + span, + "calling `CStr::new` with a byte string literal", + r#"use a `c""` literal"#, + sugg, + applicability, + ); +} + +/// Rewrites a byte string literal to a c-str literal. +/// `b"foo\0"` -> `c"foo"` +/// +/// Returns `None` if it doesn't end in a NUL byte. +fn rewrite_as_cstr(cx: &LateContext<'_>, span: Span) -> Option<String> { + let mut sugg = String::from("c") + snippet(cx, span.source_callsite(), "..").trim_start_matches('b'); + + // NUL byte should always be right before the closing quote. + if let Some(quote_pos) = sugg.rfind('"') { + // Possible values right before the quote: + // - literal NUL value + if sugg.as_bytes()[quote_pos - 1] == b'\0' { + sugg.remove(quote_pos - 1); + } + // - \x00 + else if sugg[..quote_pos].ends_with("\\x00") { + sugg.replace_range(quote_pos - 4..quote_pos, ""); + } + // - \0 + else if sugg[..quote_pos].ends_with("\\0") { + sugg.replace_range(quote_pos - 2..quote_pos, ""); + } + // No known suffix, so assume it's not a C-string. + else { + return None; + } + } + + Some(sugg) +} + +fn get_cast_target<'tcx>(e: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { + match &e.kind { + ExprKind::MethodCall(method, receiver, [], _) if method.ident.as_str() == "cast" => Some(receiver), + ExprKind::Cast(expr, _) => Some(expr), + _ => None, + } +} + +/// `x.cast()` -> `x` +/// `x as *const _` -> `x` +/// `x` -> `x` (returns the same expression for non-cast exprs) +fn peel_ptr_cast<'tcx>(e: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { + get_cast_target(e).map_or(e, peel_ptr_cast) +} + +/// Same as `peel_ptr_cast`, but the other way around, by walking up the ancestor cast expressions: +/// +/// `foo(x.cast() as *const _)` +/// ^ given this `x` expression, returns the `foo(...)` expression +fn peel_ptr_cast_ancestors<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { + let mut prev = e; + for (_, node) in cx.tcx.hir().parent_iter(e.hir_id) { + if let Node::Expr(e) = node + && get_cast_target(e).is_some() + { + prev = e; + } else { + break; + } + } + prev +} diff --git a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs index 52ea584a2c8..3226fa9cd3f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs @@ -21,7 +21,7 @@ pub(super) fn check<'tcx>( unwrap_arg: &'tcx hir::Expr<'_>, msrv: &Msrv, ) -> bool { - // lint if the caller of `map()` is an `Option` + // lint if the caller of `map()` is an `Option` or a `Result`. let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option); let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result); diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 03bcf108914..e8a7a321bf4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -51,6 +51,7 @@ mod iter_skip_zero; mod iter_with_drain; mod iterator_step_by_zero; mod join_absolute_paths; +mod manual_c_str_literals; mod manual_is_variant_and; mod manual_next_back; mod manual_ok_or; @@ -113,6 +114,7 @@ mod unnecessary_iter_cloned; mod unnecessary_join; mod unnecessary_lazy_eval; mod unnecessary_literal_unwrap; +mod unnecessary_result_map_or_else; mod unnecessary_sort_by; mod unnecessary_to_owned; mod unwrap_expect_used; @@ -3951,6 +3953,64 @@ declare_clippy_lint! { "cloning an `Option` via `as_ref().cloned()`" } +declare_clippy_lint! { + /// ### What it does + /// Checks for usage of `.map_or_else()` "map closure" for `Result` type. + /// + /// ### Why is this bad? + /// This can be written more concisely by using `unwrap_or_else()`. + /// + /// ### Example + /// ```no_run + /// # fn handle_error(_: ()) -> u32 { 0 } + /// let x: Result<u32, ()> = Ok(0); + /// let y = x.map_or_else(|err| handle_error(err), |n| n); + /// ``` + /// Use instead: + /// ```no_run + /// # fn handle_error(_: ()) -> u32 { 0 } + /// let x: Result<u32, ()> = Ok(0); + /// let y = x.unwrap_or_else(|err| handle_error(err)); + /// ``` + #[clippy::version = "1.77.0"] + pub UNNECESSARY_RESULT_MAP_OR_ELSE, + suspicious, + "making no use of the \"map closure\" when calling `.map_or_else(|err| handle_error(err), |n| n)`" +} + +declare_clippy_lint! { + /// Checks for the manual creation of C strings (a string with a `NUL` byte at the end), either + /// through one of the `CStr` constructor functions, or more plainly by calling `.as_ptr()` + /// on a (byte) string literal with a hardcoded `\0` byte at the end. + /// + /// ### Why is this bad? + /// This can be written more concisely using `c"str"` literals and is also less error-prone, + /// because the compiler checks for interior `NUL` bytes and the terminating `NUL` byte is inserted automatically. + /// + /// ### Example + /// ```no_run + /// # use std::ffi::CStr; + /// # mod libc { pub unsafe fn puts(_: *const i8) {} } + /// fn needs_cstr(_: &CStr) {} + /// + /// needs_cstr(CStr::from_bytes_with_nul(b"Hello\0").unwrap()); + /// unsafe { libc::puts("World\0".as_ptr().cast()) } + /// ``` + /// Use instead: + /// ```no_run + /// # use std::ffi::CStr; + /// # mod libc { pub unsafe fn puts(_: *const i8) {} } + /// fn needs_cstr(_: &CStr) {} + /// + /// needs_cstr(c"Hello"); + /// unsafe { libc::puts(c"World".as_ptr()) } + /// ``` + #[clippy::version = "1.76.0"] + pub MANUAL_C_STR_LITERALS, + pedantic, + r#"creating a `CStr` through functions when `c""` literals can be used"# +} + pub struct Methods { avoid_breaking_exported_api: bool, msrv: Msrv, @@ -4109,6 +4169,8 @@ impl_lint_pass!(Methods => [ MANUAL_IS_VARIANT_AND, STR_SPLIT_AT_NEWLINE, OPTION_AS_REF_CLONED, + UNNECESSARY_RESULT_MAP_OR_ELSE, + MANUAL_C_STR_LITERALS, ]); /// Extracts a method call name, args, and `Span` of the method name. @@ -4136,6 +4198,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { hir::ExprKind::Call(func, args) => { from_iter_instead_of_collect::check(cx, expr, args, func); unnecessary_fallible_conversions::check_function(cx, expr, func); + manual_c_str_literals::check(cx, expr, func, args, &self.msrv); }, hir::ExprKind::MethodCall(method_call, receiver, args, _) => { let method_span = method_call.ident.span; @@ -4354,6 +4417,7 @@ impl Methods { } }, ("as_mut", []) => useless_asref::check(cx, expr, "as_mut", recv), + ("as_ptr", []) => manual_c_str_literals::check_as_ptr(cx, expr, recv, &self.msrv), ("as_ref", []) => useless_asref::check(cx, expr, "as_ref", recv), ("assume_init", []) => uninit_assumed_init::check(cx, expr, recv), ("cloned", []) => { @@ -4592,6 +4656,7 @@ impl Methods { }, ("map_or_else", [def, map]) => { result_map_or_else_none::check(cx, expr, recv, def, map); + unnecessary_result_map_or_else::check(cx, expr, recv, def, map); }, ("next", []) => { if let Some((name2, recv2, args2, _, _)) = method_call(recv) { diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs index 624597ffca9..ab36f854fcb 100644 --- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -135,7 +135,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrapVisitor<'a, 'tcx> { fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) { if let Res::Local(local_id) = path.res - && let Some(Node::Pat(pat)) = self.cx.tcx.opt_hir_node(local_id) + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) && let PatKind::Binding(_, local_id, ..) = pat.kind { self.identifiers.insert(local_id); @@ -166,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReferenceVisitor<'a, 'tcx> { && let ExprKind::Path(ref path) = expr.kind && let QPath::Resolved(_, path) = path && let Res::Local(local_id) = path.res - && let Some(Node::Pat(pat)) = self.cx.tcx.opt_hir_node(local_id) + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) && let PatKind::Binding(_, local_id, ..) = pat.kind && self.identifiers.contains(&local_id) { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs index f3577ef6082..2046692bbd0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs @@ -99,7 +99,6 @@ fn check_fold_with_op( cx, UNNECESSARY_FOLD, fold_span.with_hi(expr.span.hi()), - // TODO #2371 don't suggest e.g., .any(|x| f(x)) if we can suggest .any(f) "this `.fold` can be written more succinctly using another method", "try", sugg, diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs new file mode 100644 index 00000000000..7b0cf48ac43 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs @@ -0,0 +1,95 @@ +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::peel_blocks; +use clippy_utils::source::snippet; +use clippy_utils::ty::is_type_diagnostic_item; +use rustc_errors::Applicability; +use rustc_hir as hir; +use rustc_hir::{Closure, Expr, ExprKind, HirId, QPath, Stmt, StmtKind}; +use rustc_lint::LateContext; +use rustc_span::symbol::sym; + +use super::UNNECESSARY_RESULT_MAP_OR_ELSE; + +fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &Expr<'_>) { + let msg = "unused \"map closure\" when calling `Result::map_or_else` value"; + let self_snippet = snippet(cx, recv.span, ".."); + let err_snippet = snippet(cx, def_arg.span, ".."); + span_lint_and_sugg( + cx, + UNNECESSARY_RESULT_MAP_OR_ELSE, + expr.span, + msg, + "consider using `unwrap_or_else`", + format!("{self_snippet}.unwrap_or_else({err_snippet})"), + Applicability::MachineApplicable, + ); +} + +fn get_last_chain_binding_hir_id(mut hir_id: HirId, statements: &[Stmt<'_>]) -> Option<HirId> { + for stmt in statements { + if let StmtKind::Local(local) = stmt.kind + && let Some(init) = local.init + && let ExprKind::Path(QPath::Resolved(_, path)) = init.kind + && let hir::def::Res::Local(local_hir_id) = path.res + && local_hir_id == hir_id + { + hir_id = local.pat.hir_id; + } else { + return None; + } + } + Some(hir_id) +} + +fn handle_qpath( + cx: &LateContext<'_>, + expr: &Expr<'_>, + recv: &Expr<'_>, + def_arg: &Expr<'_>, + expected_hir_id: HirId, + qpath: QPath<'_>, +) { + if let QPath::Resolved(_, path) = qpath + && let hir::def::Res::Local(hir_id) = path.res + && expected_hir_id == hir_id + { + emit_lint(cx, expr, recv, def_arg); + } +} + +/// lint use of `_.map_or_else(|err| err, |n| n)` for `Result`s. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + recv: &'tcx Expr<'_>, + def_arg: &'tcx Expr<'_>, + map_arg: &'tcx Expr<'_>, +) { + // lint if the caller of `map_or_else()` is a `Result` + if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result) + && let ExprKind::Closure(&Closure { body, .. }) = map_arg.kind + && let body = cx.tcx.hir().body(body) + && let Some(first_param) = body.params.first() + { + let body_expr = peel_blocks(body.value); + + match body_expr.kind { + ExprKind::Path(qpath) => { + handle_qpath(cx, expr, recv, def_arg, first_param.pat.hir_id, qpath); + }, + // If this is a block (that wasn't peeled off), then it means there are statements. + ExprKind::Block(block, _) => { + if let Some(block_expr) = block.expr + // First we ensure that this is a "binding chain" (each statement is a binding + // of the previous one) and that it is a binding of the closure argument. + && let Some(last_chain_binding_id) = + get_last_chain_binding_hir_id(first_param.pat.hir_id, block.stmts) + && let ExprKind::Path(qpath) = block_expr.kind + { + handle_qpath(cx, expr, recv, def_arg, last_chain_binding_id, qpath); + } + }, + _ => {}, + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs index 41168230752..70cc43e266c 100644 --- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs +++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs @@ -91,10 +91,10 @@ impl Visitor<'_> for IdentVisitor<'_, '_> { let node = if hir_id.local_id == ItemLocalId::from_u32(0) { // In this case, we can just use `find`, `Owner`'s `node` field is private anyway so we can't // reimplement it even if we wanted to - cx.tcx.opt_hir_node(hir_id) + Some(cx.tcx.hir_node(hir_id)) } else { let owner = cx.tcx.hir_owner_nodes(hir_id.owner); - owner.nodes.get(hir_id.local_id).copied().flatten().map(|p| p.node) + owner.nodes.get(hir_id.local_id).copied().map(|p| p.node) }; let Some(node) = node else { return; diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs index 195ce17629a..b593e48ae2e 100644 --- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs @@ -213,11 +213,8 @@ fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) { if parent_id == cur_id { break; } - let Some(parent_node) = vis.cx.tcx.opt_hir_node(parent_id) else { - break; - }; - let stop_early = match parent_node { + let stop_early = match vis.cx.tcx.hir_node(parent_id) { Node::Expr(expr) => check_expr(vis, expr), Node::Stmt(stmt) => check_stmt(vis, stmt), Node::Item(_) => { diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index 0d234f7f9b5..580160efeb7 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -357,7 +357,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Vec } }, ExprKind::Block(block, _) => { - if block.stmts.is_empty() { + if block.stmts.is_empty() && !block.targeted_by_break { block.expr.as_ref().and_then(|e| { match block.rules { BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) => None, diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index f8365deebd4..10ab380ba1b 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -453,7 +453,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { if parent_id == cur_expr.hir_id { break; } - if let Some(Node::Expr(parent_expr)) = cx.tcx.opt_hir_node(parent_id) { + if let Node::Expr(parent_expr) = cx.tcx.hir_node(parent_id) { match &parent_expr.kind { ExprKind::AddrOf(..) => { // `&e` => `e` must be referenced. diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs index d621051ef16..ae14016f482 100644 --- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs @@ -252,7 +252,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion { { ( trait_item_id, - FnKind::ImplTraitFn(cx.tcx.erase_regions(trait_ref.args) as *const _ as usize), + FnKind::ImplTraitFn(std::ptr::from_ref(cx.tcx.erase_regions(trait_ref.args)) as usize), usize::from(sig.decl.implicit_self.has_implicit_self()), ) } else { @@ -390,7 +390,6 @@ fn has_matching_args(kind: FnKind, args: GenericArgsRef<'_>) -> bool { GenericArgKind::Type(ty) => matches!(*ty.kind(), ty::Param(ty) if ty.index as usize == idx), GenericArgKind::Const(c) => matches!(c.kind(), ConstKind::Param(c) if c.index as usize == idx), }), - #[allow(trivial_casts)] - FnKind::ImplTraitFn(expected_args) => args as *const _ as usize == expected_args, + FnKind::ImplTraitFn(expected_args) => std::ptr::from_ref(args) as usize == expected_args, } } diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs index 4c09c4eea58..e002429e3a4 100644 --- a/src/tools/clippy/clippy_lints/src/operators/mod.rs +++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs @@ -771,6 +771,7 @@ declare_clippy_lint! { pub struct Operators { arithmetic_context: numeric_arithmetic::Context, verbose_bit_mask_threshold: u64, + modulo_arithmetic_allow_comparison_to_zero: bool, } impl_lint_pass!(Operators => [ ABSURD_EXTREME_COMPARISONS, @@ -801,10 +802,11 @@ impl_lint_pass!(Operators => [ SELF_ASSIGNMENT, ]); impl Operators { - pub fn new(verbose_bit_mask_threshold: u64) -> Self { + pub fn new(verbose_bit_mask_threshold: u64, modulo_arithmetic_allow_comparison_to_zero: bool) -> Self { Self { arithmetic_context: numeric_arithmetic::Context::default(), verbose_bit_mask_threshold, + modulo_arithmetic_allow_comparison_to_zero, } } } @@ -835,12 +837,19 @@ impl<'tcx> LateLintPass<'tcx> for Operators { cmp_owned::check(cx, op.node, lhs, rhs); float_cmp::check(cx, e, op.node, lhs, rhs); modulo_one::check(cx, e, op.node, rhs); - modulo_arithmetic::check(cx, e, op.node, lhs, rhs); + modulo_arithmetic::check( + cx, + e, + op.node, + lhs, + rhs, + self.modulo_arithmetic_allow_comparison_to_zero, + ); }, ExprKind::AssignOp(op, lhs, rhs) => { self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs); misrefactored_assign_op::check(cx, e, op.node, lhs, rhs); - modulo_arithmetic::check(cx, e, op.node, lhs, rhs); + modulo_arithmetic::check(cx, e, op.node, lhs, rhs, false); }, ExprKind::Assign(lhs, rhs, _) => { assign_op_pattern::check(cx, e, lhs, rhs); diff --git a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs index cb3916484c1..40d4a842bef 100644 --- a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs +++ b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs @@ -1,7 +1,7 @@ use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sext; -use rustc_hir::{BinOpKind, Expr}; +use rustc_hir::{BinOpKind, Expr, ExprKind, Node}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; use std::fmt::Display; @@ -14,8 +14,13 @@ pub(super) fn check<'tcx>( op: BinOpKind, lhs: &'tcx Expr<'_>, rhs: &'tcx Expr<'_>, + allow_comparison_to_zero: bool, ) { if op == BinOpKind::Rem { + if allow_comparison_to_zero && used_in_comparison_with_zero(cx, e) { + return; + } + let lhs_operand = analyze_operand(lhs, cx, e); let rhs_operand = analyze_operand(rhs, cx, e); if let Some(lhs_operand) = lhs_operand @@ -28,6 +33,26 @@ pub(super) fn check<'tcx>( }; } +fn used_in_comparison_with_zero(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + let Some(Node::Expr(parent_expr)) = cx.tcx.hir().find_parent(expr.hir_id) else { + return false; + }; + let ExprKind::Binary(op, lhs, rhs) = parent_expr.kind else { + return false; + }; + + if op.node == BinOpKind::Eq || op.node == BinOpKind::Ne { + if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), rhs) { + return true; + } + if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), lhs) { + return true; + } + } + + false +} + struct OperandInfo { string_representation: Option<String>, is_negative: bool, diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index 334e6770ae4..915da18aafe 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -2,6 +2,7 @@ use crate::rustc_lint::LintContext; use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::get_parent_expr; use clippy_utils::sugg::Sugg; +use hir::Param; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::{Visitor as HirVisitor, Visitor}; @@ -13,6 +14,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; use rustc_session::declare_lint_pass; +use rustc_span::ExpnKind; declare_clippy_lint! { /// ### What it does @@ -89,7 +91,12 @@ fn find_innermost_closure<'tcx>( cx: &LateContext<'tcx>, mut expr: &'tcx hir::Expr<'tcx>, mut steps: usize, -) -> Option<(&'tcx hir::Expr<'tcx>, &'tcx hir::FnDecl<'tcx>, ty::Asyncness)> { +) -> Option<( + &'tcx hir::Expr<'tcx>, + &'tcx hir::FnDecl<'tcx>, + ty::Asyncness, + &'tcx [Param<'tcx>], +)> { let mut data = None; while let hir::ExprKind::Closure(closure) = expr.kind @@ -110,6 +117,7 @@ fn find_innermost_closure<'tcx>( } else { ty::Asyncness::No }, + body.params, )); steps -= 1; } @@ -152,7 +160,9 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { // without this check, we'd end up linting twice. && !matches!(recv.kind, hir::ExprKind::Call(..)) && let (full_expr, call_depth) = get_parent_call_exprs(cx, expr) - && let Some((body, fn_decl, coroutine_kind)) = find_innermost_closure(cx, recv, call_depth) + && let Some((body, fn_decl, coroutine_kind, params)) = find_innermost_closure(cx, recv, call_depth) + // outside macros we lint properly. Inside macros, we lint only ||() style closures. + && (!matches!(expr.span.ctxt().outer_expn_data().kind, ExpnKind::Macro(_, _)) || params.is_empty()) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/redundant_locals.rs b/src/tools/clippy/clippy_lints/src/redundant_locals.rs index 2c511ee0bc0..700a5dd4a85 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_locals.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_locals.rs @@ -4,8 +4,10 @@ use clippy_utils::ty::needs_ordered_drop; use rustc_ast::Mutability; use rustc_hir::def::Res; use rustc_hir::{BindingAnnotation, ByRef, ExprKind, HirId, Local, Node, Pat, PatKind, QPath}; +use rustc_hir_typeck::expr_use_visitor::PlaceBase; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::UpvarCapture; use rustc_session::declare_lint_pass; use rustc_span::symbol::Ident; use rustc_span::DesugaringKind; @@ -69,6 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals { // the local is user-controlled && !in_external_macro(cx.sess(), local.span) && !is_from_proc_macro(cx, expr) + && !is_by_value_closure_capture(cx, local.hir_id, binding_id) { span_lint_and_help( cx, @@ -82,6 +85,29 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals { } } +/// Checks if the enclosing body is a closure and if the given local is captured by value. +/// +/// In those cases, the redefinition may be necessary to force a move: +/// ``` +/// fn assert_static<T: 'static>(_: T) {} +/// +/// let v = String::new(); +/// let closure = || { +/// let v = v; // <- removing this redefinition makes `closure` no longer `'static` +/// dbg!(&v); +/// }; +/// assert_static(closure); +/// ``` +fn is_by_value_closure_capture(cx: &LateContext<'_>, redefinition: HirId, root_variable: HirId) -> bool { + let closure_def_id = cx.tcx.hir().enclosing_body_owner(redefinition); + + cx.tcx.is_closure_or_coroutine(closure_def_id.to_def_id()) + && cx.tcx.closure_captures(closure_def_id).iter().any(|c| { + matches!(c.info.capture_kind, UpvarCapture::ByValue) + && matches!(c.place.base, PlaceBase::Upvar(upvar) if upvar.var_path.hir_id == root_variable) + }) +} + /// Find the annotation of a binding introduced by a pattern, or `None` if it's not introduced. fn find_binding(pat: &Pat<'_>, name: Ident) -> Option<BindingAnnotation> { let mut ret = None; diff --git a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs index 07fcb69afbc..c8352c05265 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs @@ -188,7 +188,6 @@ impl LateLintPass<'_> for RedundantTypeAnnotations { match init_lit.node { // In these cases the annotation is redundant LitKind::Str(..) - | LitKind::ByteStr(..) | LitKind::Byte(..) | LitKind::Char(..) | LitKind::Bool(..) @@ -202,6 +201,16 @@ impl LateLintPass<'_> for RedundantTypeAnnotations { } }, LitKind::Err => (), + LitKind::ByteStr(..) => { + // We only lint if the type annotation is an array type (e.g. &[u8; 4]). + // If instead it is a slice (e.g. &[u8]) it may not be redundant, so we + // don't lint. + if let hir::TyKind::Ref(_, mut_ty) = ty.kind + && matches!(mut_ty.ty.kind, hir::TyKind::Array(..)) + { + span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); + } + }, } }, _ => (), diff --git a/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs b/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs index 5a4933a3fce..fcb79f6d694 100644 --- a/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs +++ b/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs @@ -42,7 +42,7 @@ declare_clippy_lint! { /// // ^^^ this closure executes 123 times /// // and the vecs will have the expected capacity /// ``` - #[clippy::version = "1.74.0"] + #[clippy::version = "1.76.0"] pub REPEAT_VEC_WITH_CAPACITY, suspicious, "repeating a `Vec::with_capacity` expression which does not retain capacity" diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index e0175046587..2af466d3f51 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -2,10 +2,14 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then, span_lin use clippy_utils::source::{snippet_opt, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; use clippy_utils::visitors::{for_each_expr_with_closures, Descend}; -use clippy_utils::{fn_def_id, is_from_proc_macro, is_inside_let_else, path_to_local_id, span_find_starting_semi}; +use clippy_utils::{ + fn_def_id, is_from_proc_macro, is_inside_let_else, is_res_lang_ctor, path_res, path_to_local_id, + span_find_starting_semi, +}; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; +use rustc_hir::LangItem::ResultErr; use rustc_hir::{ Block, Body, Expr, ExprKind, FnDecl, HirId, ItemKind, LangItem, MatchSource, Node, OwnerNode, PatKind, QPath, Stmt, StmtKind, @@ -18,6 +22,7 @@ use rustc_session::declare_lint_pass; use rustc_span::def_id::LocalDefId; use rustc_span::{BytePos, Pos, Span}; use std::borrow::Cow; +use std::fmt::Display; declare_clippy_lint! { /// ### What it does @@ -146,14 +151,14 @@ impl<'tcx> RetReplacement<'tcx> { } } -impl<'tcx> ToString for RetReplacement<'tcx> { - fn to_string(&self) -> String { +impl<'tcx> Display for RetReplacement<'tcx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::Empty => String::new(), - Self::Block => "{}".to_string(), - Self::Unit => "()".to_string(), - Self::IfSequence(inner, _) => format!("({inner})"), - Self::Expr(inner, _) => inner.to_string(), + Self::Empty => write!(f, ""), + Self::Block => write!(f, "{{}}"), + Self::Unit => write!(f, "()"), + Self::IfSequence(inner, _) => write!(f, "({inner})"), + Self::Expr(inner, _) => write!(f, "{inner}"), } } } @@ -181,7 +186,15 @@ impl<'tcx> LateLintPass<'tcx> for Return { if !in_external_macro(cx.sess(), stmt.span) && let StmtKind::Semi(expr) = stmt.kind && let ExprKind::Ret(Some(ret)) = expr.kind - && let ExprKind::Match(.., MatchSource::TryDesugar(_)) = ret.kind + // return Err(...)? desugars to a match + // over a Err(...).branch() + // which breaks down to a branch call, with the callee being + // the constructor of the Err variant + && let ExprKind::Match(maybe_cons, _, MatchSource::TryDesugar(_)) = ret.kind + && let ExprKind::Call(_, [maybe_result_err]) = maybe_cons.kind + && let ExprKind::Call(maybe_constr, _) = maybe_result_err.kind + && is_res_lang_ctor(cx, path_res(cx, maybe_constr), ResultErr) + // Ensure this is not the final stmt, otherwise removing it would cause a compile error && let OwnerNode::Item(item) = cx.tcx.hir_owner_node(cx.tcx.hir().get_parent_item(expr.hir_id)) && let ItemKind::Fn(_, _, body) = item.kind diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs index 7a351dab2d4..07806b182f2 100644 --- a/src/tools/clippy/clippy_lints/src/same_name_method.rs +++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs @@ -76,8 +76,8 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { match of_trait { Some(trait_ref) => { let mut methods_in_trait: BTreeSet<Symbol> = - if let Some(Node::TraitRef(TraitRef { path, .. })) = - cx.tcx.opt_hir_node(trait_ref.hir_ref_id) + if let Node::TraitRef(TraitRef { path, .. }) = + cx.tcx.hir_node(trait_ref.hir_ref_id) && let Res::Def(DefKind::Trait, did) = path.res { // FIXME: if diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs index 98f3235af10..fc5a45dd56d 100644 --- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs +++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs @@ -73,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors { if let Some(self_def) = self_ty.ty_adt_def() && let Some(self_local_did) = self_def.did().as_local() && let self_id = cx.tcx.local_def_id_to_hir_id(self_local_did) - && let Some(Node::Item(x)) = cx.tcx.opt_hir_node(self_id) + && let Node::Item(x) = cx.tcx.hir_node(self_id) && let type_name = x.ident.name.as_str().to_lowercase() && (impl_item.ident.name.as_str() == type_name || impl_item.ident.name.as_str().replace('_', "") == type_name) diff --git a/src/tools/clippy/clippy_lints/src/to_string_trait_impl.rs b/src/tools/clippy/clippy_lints/src/to_string_trait_impl.rs new file mode 100644 index 00000000000..e1cea99085f --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/to_string_trait_impl.rs @@ -0,0 +1,67 @@ +use clippy_utils::diagnostics::span_lint_and_help; +use rustc_hir::{Impl, Item, ItemKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_lint_pass; +use rustc_span::sym; + +declare_clippy_lint! { + /// ### What it does + /// Checks for direct implementations of `ToString`. + /// ### Why is this bad? + /// This trait is automatically implemented for any type which implements the `Display` trait. + /// As such, `ToString` shouldn’t be implemented directly: `Display` should be implemented instead, + /// and you get the `ToString` implementation for free. + /// ### Example + /// ```no_run + /// struct Point { + /// x: usize, + /// y: usize, + /// } + /// + /// impl ToString for Point { + /// fn to_string(&self) -> String { + /// format!("({}, {})", self.x, self.y) + /// } + /// } + /// ``` + /// Use instead: + /// ```no_run + /// struct Point { + /// x: usize, + /// y: usize, + /// } + /// + /// impl std::fmt::Display for Point { + /// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + /// write!(f, "({}, {})", self.x, self.y) + /// } + /// } + /// ``` + #[clippy::version = "1.77.0"] + pub TO_STRING_TRAIT_IMPL, + style, + "check for direct implementations of `ToString`" +} + +declare_lint_pass!(ToStringTraitImpl => [TO_STRING_TRAIT_IMPL]); + +impl<'tcx> LateLintPass<'tcx> for ToStringTraitImpl { + fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'tcx>) { + if let ItemKind::Impl(Impl { + of_trait: Some(trait_ref), + .. + }) = it.kind + && let Some(trait_did) = trait_ref.trait_def_id() + && cx.tcx.is_diagnostic_item(sym::ToString, trait_did) + { + span_lint_and_help( + cx, + TO_STRING_TRAIT_IMPL, + it.span, + "direct implementation of `ToString`", + None, + "prefer implementing `Display` instead", + ); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs index 209035804e4..224ec475c51 100644 --- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -69,14 +69,6 @@ fn span_error(cx: &LateContext<'_>, method_span: Span, expr: &Expr<'_>) { ); } -fn get_ty_def_id(ty: Ty<'_>) -> Option<DefId> { - match ty.peel_refs().kind() { - ty::Adt(adt, _) => Some(adt.did()), - ty::Foreign(def_id) => Some(*def_id), - _ => None, - } -} - fn get_hir_ty_def_id<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: rustc_hir::Ty<'tcx>) -> Option<DefId> { let TyKind::Path(qpath) = hir_ty.kind else { return None }; match qpath { @@ -131,21 +123,49 @@ fn get_impl_trait_def_id(cx: &LateContext<'_>, method_def_id: LocalDefId) -> Opt } } -#[allow(clippy::unnecessary_def_path)] +/// When we have `x == y` where `x = &T` and `y = &T`, then that resolves to +/// `<&T as PartialEq<&T>>::eq`, which is not the same as `<T as PartialEq<T>>::eq`, +/// however we still would want to treat it the same, because we know that it's a blanket impl +/// that simply delegates to the `PartialEq` impl with one reference removed. +/// +/// Still, we can't just do `lty.peel_refs() == rty.peel_refs()` because when we have `x = &T` and +/// `y = &&T`, this is not necessarily the same as `<T as PartialEq<T>>::eq` +/// +/// So to avoid these FNs and FPs, we keep removing a layer of references from *both* sides +/// until both sides match the expected LHS and RHS type (or they don't). +fn matches_ty<'tcx>( + mut left: Ty<'tcx>, + mut right: Ty<'tcx>, + expected_left: Ty<'tcx>, + expected_right: Ty<'tcx>, +) -> bool { + while let (&ty::Ref(_, lty, _), &ty::Ref(_, rty, _)) = (left.kind(), right.kind()) { + if lty == expected_left && rty == expected_right { + return true; + } + left = lty; + right = rty; + } + false +} + fn check_partial_eq(cx: &LateContext<'_>, method_span: Span, method_def_id: LocalDefId, name: Ident, expr: &Expr<'_>) { - let args = cx - .tcx - .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(method_def_id).skip_binder()) - .inputs(); + let Some(sig) = cx + .typeck_results() + .liberated_fn_sigs() + .get(cx.tcx.local_def_id_to_hir_id(method_def_id)) + else { + return; + }; + // That has two arguments. - if let [self_arg, other_arg] = args - && let Some(self_arg) = get_ty_def_id(*self_arg) - && let Some(other_arg) = get_ty_def_id(*other_arg) + if let [self_arg, other_arg] = sig.inputs() + && let &ty::Ref(_, self_arg, _) = self_arg.kind() + && let &ty::Ref(_, other_arg, _) = other_arg.kind() // The two arguments are of the same type. - && self_arg == other_arg && let Some(trait_def_id) = get_impl_trait_def_id(cx, method_def_id) // The trait is `PartialEq`. - && Some(trait_def_id) == get_trait_def_id(cx, &["core", "cmp", "PartialEq"]) + && cx.tcx.is_diagnostic_item(sym::PartialEq, trait_def_id) { let to_check_op = if name.name == sym::eq { BinOpKind::Eq @@ -154,31 +174,19 @@ fn check_partial_eq(cx: &LateContext<'_>, method_span: Span, method_def_id: Loca }; let is_bad = match expr.kind { ExprKind::Binary(op, left, right) if op.node == to_check_op => { - // Then we check if the left-hand element is of the same type as `self`. - if let Some(left_ty) = cx.typeck_results().expr_ty_opt(left) - && let Some(left_id) = get_ty_def_id(left_ty) - && self_arg == left_id - && let Some(right_ty) = cx.typeck_results().expr_ty_opt(right) - && let Some(right_id) = get_ty_def_id(right_ty) - && other_arg == right_id - { - true - } else { - false - } + // Then we check if the LHS matches self_arg and RHS matches other_arg + let left_ty = cx.typeck_results().expr_ty_adjusted(left); + let right_ty = cx.typeck_results().expr_ty_adjusted(right); + matches_ty(left_ty, right_ty, self_arg, other_arg) }, - ExprKind::MethodCall(segment, receiver, &[_arg], _) if segment.ident.name == name.name => { - if let Some(ty) = cx.typeck_results().expr_ty_opt(receiver) - && let Some(ty_id) = get_ty_def_id(ty) - && self_arg != ty_id - { - // Since this called on a different type, the lint should not be - // triggered here. - return; - } + ExprKind::MethodCall(segment, receiver, [arg], _) if segment.ident.name == name.name => { + let receiver_ty = cx.typeck_results().expr_ty_adjusted(receiver); + let arg_ty = cx.typeck_results().expr_ty_adjusted(arg); + if let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) && let Some(trait_id) = cx.tcx.trait_of_item(fn_id) && trait_id == trait_def_id + && matches_ty(receiver_ty, arg_ty, self_arg, other_arg) { true } else { diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index adc66e15ff5..6b3ea7700b7 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::{is_res_lang_ctor, is_trait_method, match_trait_method, paths}; +use clippy_utils::macros::{is_panic, root_macro_call_first_node}; +use clippy_utils::{is_res_lang_ctor, is_trait_method, match_trait_method, paths, peel_blocks}; use hir::{ExprKind, PatKind}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; @@ -82,37 +83,72 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { } if let Some(exp) = block.expr - && matches!(exp.kind, hir::ExprKind::If(_, _, _) | hir::ExprKind::Match(_, _, _)) + && matches!( + exp.kind, + hir::ExprKind::If(_, _, _) | hir::ExprKind::Match(_, _, hir::MatchSource::Normal) + ) { check_expr(cx, exp); } } } +fn non_consuming_err_arm<'a>(cx: &LateContext<'a>, arm: &hir::Arm<'a>) -> bool { + // if there is a guard, we consider the result to be consumed + if arm.guard.is_some() { + return false; + } + if is_unreachable_or_panic(cx, arm.body) { + // if the body is unreachable or there is a panic, + // we consider the result to be consumed + return false; + } + + if let PatKind::TupleStruct(ref path, [inner_pat], _) = arm.pat.kind { + return is_res_lang_ctor(cx, cx.qpath_res(path, inner_pat.hir_id), hir::LangItem::ResultErr); + } + + false +} + +fn non_consuming_ok_arm<'a>(cx: &LateContext<'a>, arm: &hir::Arm<'a>) -> bool { + // if there is a guard, we consider the result to be consumed + if arm.guard.is_some() { + return false; + } + if is_unreachable_or_panic(cx, arm.body) { + // if the body is unreachable or there is a panic, + // we consider the result to be consumed + return false; + } + + if is_ok_wild_or_dotdot_pattern(cx, arm.pat) { + return true; + } + false +} + fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) { match expr.kind { hir::ExprKind::If(cond, _, _) if let ExprKind::Let(hir::Let { pat, init, .. }) = cond.kind - && pattern_is_ignored_ok(cx, pat) + && is_ok_wild_or_dotdot_pattern(cx, pat) && let Some(op) = should_lint(cx, init) => { emit_lint(cx, cond.span, op, &[pat.span]); }, - hir::ExprKind::Match(expr, arms, hir::MatchSource::Normal) if let Some(op) = should_lint(cx, expr) => { - let found_arms: Vec<_> = arms - .iter() - .filter_map(|arm| { - if pattern_is_ignored_ok(cx, arm.pat) { - Some(arm.span) - } else { - None - } - }) - .collect(); - if !found_arms.is_empty() { - emit_lint(cx, expr.span, op, found_arms.as_slice()); + // we will capture only the case where the match is Ok( ) or Err( ) + // prefer to match the minimum possible, and expand later if needed + // to avoid false positives on something as used as this + hir::ExprKind::Match(expr, [arm1, arm2], hir::MatchSource::Normal) if let Some(op) = should_lint(cx, expr) => { + if non_consuming_ok_arm(cx, arm1) && non_consuming_err_arm(cx, arm2) { + emit_lint(cx, expr.span, op, &[arm1.pat.span]); + } + if non_consuming_ok_arm(cx, arm2) && non_consuming_err_arm(cx, arm1) { + emit_lint(cx, expr.span, op, &[arm2.pat.span]); } }, + hir::ExprKind::Match(_, _, hir::MatchSource::Normal) => {}, _ if let Some(op) = should_lint(cx, expr) => { emit_lint(cx, expr.span, op, &[]); }, @@ -130,25 +166,40 @@ fn should_lint<'a>(cx: &LateContext<'a>, mut inner: &'a hir::Expr<'a>) -> Option check_io_mode(cx, inner) } -fn pattern_is_ignored_ok(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> bool { +fn is_ok_wild_or_dotdot_pattern<'a>(cx: &LateContext<'a>, pat: &hir::Pat<'a>) -> bool { // the if checks whether we are in a result Ok( ) pattern // and the return checks whether it is unhandled - if let PatKind::TupleStruct(ref path, inner_pat, ddp) = pat.kind + if let PatKind::TupleStruct(ref path, inner_pat, _) = pat.kind // we check against Result::Ok to avoid linting on Err(_) or something else. && is_res_lang_ctor(cx, cx.qpath_res(path, pat.hir_id), hir::LangItem::ResultOk) { - return match (inner_pat, ddp.as_opt_usize()) { - // Ok(_) pattern - ([inner_pat], None) if matches!(inner_pat.kind, PatKind::Wild) => true, - // Ok(..) pattern - ([], Some(0)) => true, - _ => false, - }; + if matches!(inner_pat, []) { + return true; + } + + if let [cons_pat] = inner_pat + && matches!(cons_pat.kind, PatKind::Wild) + { + return true; + } + return false; } false } +// this is partially taken from panic_unimplemented +fn is_unreachable_or_panic(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { + let expr = peel_blocks(expr); + let Some(macro_call) = root_macro_call_first_node(cx, expr) else { + return false; + }; + if is_panic(cx, macro_call.def_id) { + return !cx.tcx.hir().is_inside_const_context(expr.hir_id); + } + matches!(cx.tcx.item_name(macro_call.def_id).as_str(), "unreachable") +} + fn unpack_call_chain<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { while let hir::ExprKind::MethodCall(path, receiver, ..) = expr.kind { if matches!( diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 288df0fd663..29c67341a46 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -490,9 +490,9 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { format!("ClosureKind::Coroutine(CoroutineKind::Coroutine(Movability::{movability:?})") }, }, - ClosureKind::CoroutineClosure(desugaring) => format!( - "ClosureKind::CoroutineClosure(CoroutineDesugaring::{desugaring:?})" - ), + ClosureKind::CoroutineClosure(desugaring) => { + format!("ClosureKind::CoroutineClosure(CoroutineDesugaring::{desugaring:?})") + }, }; let ret_ty = match fn_decl.output { diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index b82bd1d7e7c..5410e8ac117 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_test_module_or_function; use clippy_utils::source::{snippet, snippet_with_applicability}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Item, ItemKind, PathSegment, UseKind}; @@ -100,13 +101,15 @@ declare_clippy_lint! { pub struct WildcardImports { warn_on_all: bool, test_modules_deep: u32, + allowed_segments: FxHashSet<String>, } impl WildcardImports { - pub fn new(warn_on_all: bool) -> Self { + pub fn new(warn_on_all: bool, allowed_wildcard_imports: FxHashSet<String>) -> Self { Self { warn_on_all, test_modules_deep: 0, + allowed_segments: allowed_wildcard_imports, } } } @@ -190,6 +193,7 @@ impl WildcardImports { item.span.from_expansion() || is_prelude_import(segments) || (is_super_only_import(segments) && self.test_modules_deep > 0) + || is_allowed_via_config(segments, &self.allowed_segments) } } @@ -198,10 +202,18 @@ impl WildcardImports { fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool { segments .iter() - .any(|ps| ps.ident.name.as_str().contains(sym::prelude.as_str())) + .any(|ps| ps.ident.as_str().contains(sym::prelude.as_str())) } // Allow "super::*" imports in tests. fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool { segments.len() == 1 && segments[0].ident.name == kw::Super } + +// Allow skipping imports containing user configured segments, +// i.e. "...::utils::...::*" if user put `allowed-wildcard-imports = ["utils"]` in `Clippy.toml` +fn is_allowed_via_config(segments: &[PathSegment<'_>], allowed_segments: &FxHashSet<String>) -> bool { + // segment matching need to be exact instead of using 'contains', in case user unintentionaly put + // a single character in the config thus skipping most of the warnings. + segments.iter().any(|seg| allowed_segments.contains(seg.ident.as_str())) +} diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml index b8869eedf52..c7454fa3328 100644 --- a/src/tools/clippy/clippy_utils/Cargo.toml +++ b/src/tools/clippy/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.77" +version = "0.1.78" edition = "2021" publish = false diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 4e499ff4cc6..6a33e11be46 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1,5 +1,6 @@ #![feature(array_chunks)] #![feature(box_patterns)] +#![feature(control_flow_enum)] #![feature(if_let_guard)] #![feature(let_chains)] #![feature(lint_reasons)] @@ -8,7 +9,13 @@ #![feature(assert_matches)] #![recursion_limit = "512"] #![cfg_attr(feature = "deny-warnings", deny(warnings))] -#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)] +#![allow( + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::must_use_candidate, + rustc::diagnostic_outside_of_impl, + rustc::untranslatable_diagnostic, +)] // warn on the same lints as `clippy_lints` #![warn(trivial_casts, trivial_numeric_casts)] // warn on lints, that are included in `rust-lang/rust`s bootstrap @@ -75,6 +82,7 @@ use core::mem; use core::ops::ControlFlow; use std::collections::hash_map::Entry; use std::hash::BuildHasherDefault; +use std::iter::{once, repeat}; use std::sync::{Mutex, MutexGuard, OnceLock}; use itertools::Itertools; @@ -84,6 +92,7 @@ use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnhashMap; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, LOCAL_CRATE}; +use rustc_hir::definitions::{DefPath, DefPathData}; use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; @@ -102,8 +111,8 @@ use rustc_middle::ty::binding::BindingMode; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ - self as rustc_ty, Binder, BorrowKind, ClosureKind, FloatTy, IntTy, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeAndMut, - TypeVisitableExt, UintTy, UpvarCapture, + self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, FloatTy, GenericArgsRef, IntTy, ParamEnv, + ParamEnvAnd, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, UintTy, UpvarCapture, }; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; @@ -114,10 +123,7 @@ use visitors::Visitable; use crate::consts::{constant, mir_to_const, Constant}; use crate::higher::Range; -use crate::ty::{ - adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, - ty_is_fn_once_param, -}; +use crate::ty::{adt_and_variant_of_res, can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type}; use crate::visitors::for_each_expr; use rustc_middle::hir::nested_filter; @@ -177,10 +183,10 @@ pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr /// canonical binding `HirId`. pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> { let hir = cx.tcx.hir(); - if let Some(Node::Pat(pat)) = cx.tcx.opt_hir_node(hir_id) + if let Node::Pat(pat) = cx.tcx.hir_node(hir_id) && matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..)) && let parent = hir.parent_id(hir_id) - && let Some(Node::Local(local)) = cx.tcx.opt_hir_node(parent) + && let Node::Local(local) = cx.tcx.hir_node(parent) { return local.init; } @@ -1327,7 +1333,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio let map = &cx.tcx.hir(); let enclosing_node = map .get_enclosing_scope(hir_id) - .and_then(|enclosing_id| cx.tcx.opt_hir_node(enclosing_id)); + .map(|enclosing_id| cx.tcx.hir_node(enclosing_id)); enclosing_node.and_then(|node| match node { Node::Block(block) => Some(block), Node::Item(&Item { @@ -1353,46 +1359,12 @@ pub fn get_enclosing_loop_or_multi_call_closure<'tcx>( for (_, node) in cx.tcx.hir().parent_iter(expr.hir_id) { match node { Node::Expr(e) => match e.kind { - ExprKind::Closure { .. } => { + ExprKind::Closure { .. } if let rustc_ty::Closure(_, subs) = cx.typeck_results().expr_ty(e).kind() - && subs.as_closure().kind() == ClosureKind::FnOnce - { - continue; - } - let is_once = walk_to_expr_usage(cx, e, |node, id| { - let Node::Expr(e) = node else { - return None; - }; - match e.kind { - ExprKind::Call(f, _) if f.hir_id == id => Some(()), - ExprKind::Call(f, args) => { - let i = args.iter().position(|arg| arg.hir_id == id)?; - let sig = expr_sig(cx, f)?; - let predicates = sig - .predicates_id() - .map_or(cx.param_env, |id| cx.tcx.param_env(id)) - .caller_bounds(); - sig.input(i).and_then(|ty| { - ty_is_fn_once_param(cx.tcx, ty.skip_binder(), predicates).then_some(()) - }) - }, - ExprKind::MethodCall(_, receiver, args, _) => { - let i = std::iter::once(receiver) - .chain(args.iter()) - .position(|arg| arg.hir_id == id)?; - let id = cx.typeck_results().type_dependent_def_id(e.hir_id)?; - let ty = cx.tcx.fn_sig(id).instantiate_identity().skip_binder().inputs()[i]; - ty_is_fn_once_param(cx.tcx, ty, cx.tcx.param_env(id).caller_bounds()).then_some(()) - }, - _ => None, - } - }) - .is_some(); - if !is_once { - return Some(e); - } - }, - ExprKind::Loop(..) => return Some(e), + && subs.as_closure().kind() == ClosureKind::FnOnce => {}, + + // Note: A closure's kind is determined by how it's used, not it's captures. + ExprKind::Closure { .. } | ExprKind::Loop(..) => return Some(e), _ => (), }, Node::Stmt(_) | Node::Block(_) | Node::Local(_) | Node::Arm(_) => (), @@ -2590,26 +2562,30 @@ pub fn is_test_module_or_function(tcx: TyCtxt<'_>, item: &Item<'_>) -> bool { && item.ident.name.as_str().split('_').any(|a| a == "test" || a == "tests") } -/// Walks the HIR tree from the given expression, up to the node where the value produced by the -/// expression is consumed. Calls the function for every node encountered this way until it returns -/// `Some`. +/// Walks up the HIR tree from the given expression in an attempt to find where the value is +/// consumed. +/// +/// Termination has three conditions: +/// - The given function returns `Break`. This function will return the value. +/// - The consuming node is found. This function will return `Continue(use_node, child_id)`. +/// - No further parent nodes are found. This will trigger a debug assert or return `None`. /// -/// This allows walking through `if`, `match`, `break`, block expressions to find where the value -/// produced by the expression is consumed. +/// This allows walking through `if`, `match`, `break`, and block expressions to find where the +/// value produced by the expression is consumed. pub fn walk_to_expr_usage<'tcx, T>( cx: &LateContext<'tcx>, e: &Expr<'tcx>, - mut f: impl FnMut(Node<'tcx>, HirId) -> Option<T>, -) -> Option<T> { + mut f: impl FnMut(HirId, Node<'tcx>, HirId) -> ControlFlow<T>, +) -> Option<ControlFlow<T, (Node<'tcx>, HirId)>> { let map = cx.tcx.hir(); let mut iter = map.parent_iter(e.hir_id); let mut child_id = e.hir_id; while let Some((parent_id, parent)) = iter.next() { - if let Some(x) = f(parent, child_id) { - return Some(x); + if let ControlFlow::Break(x) = f(parent_id, parent, child_id) { + return Some(ControlFlow::Break(x)); } - let parent = match parent { + let parent_expr = match parent { Node::Expr(e) => e, Node::Block(Block { expr: Some(body), .. }) | Node::Arm(Arm { body, .. }) if body.hir_id == child_id => { child_id = parent_id; @@ -2619,18 +2595,19 @@ pub fn walk_to_expr_usage<'tcx, T>( child_id = parent_id; continue; }, - _ => return None, + _ => return Some(ControlFlow::Continue((parent, child_id))), }; - match parent.kind { + match parent_expr.kind { ExprKind::If(child, ..) | ExprKind::Match(child, ..) if child.hir_id != child_id => child_id = parent_id, ExprKind::Break(Destination { target_id: Ok(id), .. }, _) => { child_id = id; iter = map.parent_iter(id); }, - ExprKind::Block(..) => child_id = parent_id, - _ => return None, + ExprKind::Block(..) | ExprKind::DropTemps(_) => child_id = parent_id, + _ => return Some(ControlFlow::Continue((parent, child_id))), } } + debug_assert!(false, "no parent node found for `{child_id:?}`"); None } @@ -2674,6 +2651,8 @@ pub enum ExprUseNode<'tcx> { Callee, /// Access of a field. FieldAccess(Ident), + Expr, + Other, } impl<'tcx> ExprUseNode<'tcx> { /// Checks if the value is returned from the function. @@ -2696,10 +2675,10 @@ impl<'tcx> ExprUseNode<'tcx> { )), Self::Return(id) => { let hir_id = cx.tcx.local_def_id_to_hir_id(id.def_id); - if let Some(Node::Expr(Expr { + if let Node::Expr(Expr { kind: ExprKind::Closure(c), .. - })) = cx.tcx.opt_hir_node(hir_id) + }) = cx.tcx.hir_node(hir_id) { match c.fn_decl.output { FnRetTy::DefaultReturn(_) => None, @@ -2750,144 +2729,104 @@ impl<'tcx> ExprUseNode<'tcx> { let sig = cx.tcx.fn_sig(id).skip_binder(); Some(DefinedTy::Mir(cx.tcx.param_env(id).and(sig.input(i)))) }, - Self::Local(_) | Self::FieldAccess(..) | Self::Callee => None, + Self::Local(_) | Self::FieldAccess(..) | Self::Callee | Self::Expr | Self::Other => None, } } } /// Gets the context an expression's value is used in. -#[expect(clippy::too_many_lines)] pub fn expr_use_ctxt<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> Option<ExprUseCtxt<'tcx>> { let mut adjustments = [].as_slice(); let mut is_ty_unified = false; let mut moved_before_use = false; let ctxt = e.span.ctxt(); - walk_to_expr_usage(cx, e, &mut |parent, child_id| { - // LocalTableInContext returns the wrong lifetime, so go use `expr_adjustments` instead. + walk_to_expr_usage(cx, e, &mut |parent_id, parent, child_id| { if adjustments.is_empty() && let Node::Expr(e) = cx.tcx.hir_node(child_id) { adjustments = cx.typeck_results().expr_adjustments(e); } - match parent { - Node::Local(l) if l.span.ctxt() == ctxt => Some(ExprUseCtxt { - node: ExprUseNode::Local(l), - adjustments, - is_ty_unified, - moved_before_use, - }), + if cx.tcx.hir().span(parent_id).ctxt() != ctxt { + return ControlFlow::Break(()); + } + if let Node::Expr(e) = parent { + match e.kind { + ExprKind::If(e, _, _) | ExprKind::Match(e, _, _) if e.hir_id != child_id => { + is_ty_unified = true; + moved_before_use = true; + }, + ExprKind::Block(_, Some(_)) | ExprKind::Break(..) => { + is_ty_unified = true; + moved_before_use = true; + }, + ExprKind::Block(..) => moved_before_use = true, + _ => {}, + } + } + ControlFlow::Continue(()) + })? + .continue_value() + .map(|(use_node, child_id)| { + let node = match use_node { + Node::Local(l) => ExprUseNode::Local(l), + Node::ExprField(field) => ExprUseNode::Field(field), + Node::Item(&Item { kind: ItemKind::Static(..) | ItemKind::Const(..), owner_id, - span, .. }) | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), owner_id, - span, .. }) | Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), owner_id, - span, .. - }) if span.ctxt() == ctxt => Some(ExprUseCtxt { - node: ExprUseNode::ConstStatic(owner_id), - adjustments, - is_ty_unified, - moved_before_use, - }), + }) => ExprUseNode::ConstStatic(owner_id), Node::Item(&Item { kind: ItemKind::Fn(..), owner_id, - span, .. }) | Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), owner_id, - span, .. }) | Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(..), owner_id, - span, .. - }) if span.ctxt() == ctxt => Some(ExprUseCtxt { - node: ExprUseNode::Return(owner_id), - adjustments, - is_ty_unified, - moved_before_use, - }), - - Node::ExprField(field) if field.span.ctxt() == ctxt => Some(ExprUseCtxt { - node: ExprUseNode::Field(field), - adjustments, - is_ty_unified, - moved_before_use, - }), + }) => ExprUseNode::Return(owner_id), - Node::Expr(parent) if parent.span.ctxt() == ctxt => match parent.kind { - ExprKind::Ret(_) => Some(ExprUseCtxt { - node: ExprUseNode::Return(OwnerId { - def_id: cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()), - }), - adjustments, - is_ty_unified, - moved_before_use, - }), - ExprKind::Closure(closure) => Some(ExprUseCtxt { - node: ExprUseNode::Return(OwnerId { def_id: closure.def_id }), - adjustments, - is_ty_unified, - moved_before_use, - }), - ExprKind::Call(func, args) => Some(ExprUseCtxt { - node: match args.iter().position(|arg| arg.hir_id == child_id) { - Some(i) => ExprUseNode::FnArg(func, i), - None => ExprUseNode::Callee, - }, - adjustments, - is_ty_unified, - moved_before_use, - }), - ExprKind::MethodCall(name, _, args, _) => Some(ExprUseCtxt { - node: ExprUseNode::MethodArg( - parent.hir_id, - name.args, - args.iter().position(|arg| arg.hir_id == child_id).map_or(0, |i| i + 1), - ), - adjustments, - is_ty_unified, - moved_before_use, - }), - ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(ExprUseCtxt { - node: ExprUseNode::FieldAccess(name), - adjustments, - is_ty_unified, - moved_before_use, + Node::Expr(use_expr) => match use_expr.kind { + ExprKind::Ret(_) => ExprUseNode::Return(OwnerId { + def_id: cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()), }), - ExprKind::If(e, _, _) | ExprKind::Match(e, _, _) if e.hir_id != child_id => { - is_ty_unified = true; - moved_before_use = true; - None - }, - ExprKind::Block(_, Some(_)) | ExprKind::Break(..) => { - is_ty_unified = true; - moved_before_use = true; - None + ExprKind::Closure(closure) => ExprUseNode::Return(OwnerId { def_id: closure.def_id }), + ExprKind::Call(func, args) => match args.iter().position(|arg| arg.hir_id == child_id) { + Some(i) => ExprUseNode::FnArg(func, i), + None => ExprUseNode::Callee, }, - ExprKind::Block(..) => { - moved_before_use = true; - None - }, - _ => None, + ExprKind::MethodCall(name, _, args, _) => ExprUseNode::MethodArg( + use_expr.hir_id, + name.args, + args.iter().position(|arg| arg.hir_id == child_id).map_or(0, |i| i + 1), + ), + ExprKind::Field(child, name) if child.hir_id == e.hir_id => ExprUseNode::FieldAccess(name), + _ => ExprUseNode::Expr, }, - _ => None, + _ => ExprUseNode::Other, + }; + ExprUseCtxt { + node, + adjustments, + is_ty_unified, + moved_before_use, } }) } @@ -3264,3 +3203,131 @@ pub fn is_never_expr<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option< }) } } + +/// Produces a path from a local caller to the type of the called method. Suitable for user +/// output/suggestions. +/// +/// Returned path can be either absolute (for methods defined non-locally), or relative (for local +/// methods). +pub fn get_path_from_caller_to_method_type<'tcx>( + tcx: TyCtxt<'tcx>, + from: LocalDefId, + method: DefId, + args: GenericArgsRef<'tcx>, +) -> String { + let assoc_item = tcx.associated_item(method); + let def_id = assoc_item.container_id(tcx); + match assoc_item.container { + rustc_ty::TraitContainer => get_path_to_callee(tcx, from, def_id), + rustc_ty::ImplContainer => { + let ty = tcx.type_of(def_id).instantiate_identity(); + get_path_to_ty(tcx, from, ty, args) + }, + } +} + +fn get_path_to_ty<'tcx>(tcx: TyCtxt<'tcx>, from: LocalDefId, ty: Ty<'tcx>, args: GenericArgsRef<'tcx>) -> String { + match ty.kind() { + rustc_ty::Adt(adt, _) => get_path_to_callee(tcx, from, adt.did()), + // TODO these types need to be recursively resolved as well + rustc_ty::Array(..) + | rustc_ty::Dynamic(..) + | rustc_ty::Never + | rustc_ty::RawPtr(_) + | rustc_ty::Ref(..) + | rustc_ty::Slice(_) + | rustc_ty::Tuple(_) => format!("<{}>", EarlyBinder::bind(ty).instantiate(tcx, args)), + _ => ty.to_string(), + } +} + +/// Produce a path from some local caller to the callee. Suitable for user output/suggestions. +fn get_path_to_callee(tcx: TyCtxt<'_>, from: LocalDefId, callee: DefId) -> String { + // only search for a relative path if the call is fully local + if callee.is_local() { + let callee_path = tcx.def_path(callee); + let caller_path = tcx.def_path(from.to_def_id()); + maybe_get_relative_path(&caller_path, &callee_path, 2) + } else { + tcx.def_path_str(callee) + } +} + +/// Tries to produce a relative path from `from` to `to`; if such a path would contain more than +/// `max_super` `super` items, produces an absolute path instead. Both `from` and `to` should be in +/// the local crate. +/// +/// Suitable for user output/suggestions. +/// +/// This ignores use items, and assumes that the target path is visible from the source +/// path (which _should_ be a reasonable assumption since we in order to be able to use an object of +/// certain type T, T is required to be visible). +/// +/// TODO make use of `use` items. Maybe we should have something more sophisticated like +/// rust-analyzer does? <https://docs.rs/ra_ap_hir_def/0.0.169/src/ra_ap_hir_def/find_path.rs.html#19-27> +fn maybe_get_relative_path(from: &DefPath, to: &DefPath, max_super: usize) -> String { + use itertools::EitherOrBoth::{Both, Left, Right}; + + // 1. skip the segments common for both paths (regardless of their type) + let unique_parts = to + .data + .iter() + .zip_longest(from.data.iter()) + .skip_while(|el| matches!(el, Both(l, r) if l == r)) + .map(|el| match el { + Both(l, r) => Both(l.data, r.data), + Left(l) => Left(l.data), + Right(r) => Right(r.data), + }); + + // 2. for the remaning segments, construct relative path using only mod names and `super` + let mut go_up_by = 0; + let mut path = Vec::new(); + for el in unique_parts { + match el { + Both(l, r) => { + // consider: + // a::b::sym:: :: refers to + // c::d::e ::f::sym + // result should be super::super::c::d::e::f + // + // alternatively: + // a::b::c ::d::sym refers to + // e::f::sym:: :: + // result should be super::super::super::super::e::f + if let DefPathData::TypeNs(s) = l { + path.push(s.to_string()); + } + if let DefPathData::TypeNs(_) = r { + go_up_by += 1; + } + }, + // consider: + // a::b::sym:: :: refers to + // c::d::e ::f::sym + // when looking at `f` + Left(DefPathData::TypeNs(sym)) => path.push(sym.to_string()), + // consider: + // a::b::c ::d::sym refers to + // e::f::sym:: :: + // when looking at `d` + Right(DefPathData::TypeNs(_)) => go_up_by += 1, + _ => {}, + } + } + + if go_up_by > max_super { + // `super` chain would be too long, just use the absolute path instead + once(String::from("crate")) + .chain(to.data.iter().filter_map(|el| { + if let DefPathData::TypeNs(sym) = el.data { + Some(sym.to_string()) + } else { + None + } + })) + .join("::") + } else { + repeat(String::from("super")).take(go_up_by).chain(path).join("::") + } +} diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 81f4fcc2133..8d5bcd665ad 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -174,7 +174,7 @@ fn check_rvalue<'tcx>( )) } }, - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) | Rvalue::ShallowInitBox(_, _) => { + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::DebugAssertions, _) | Rvalue::ShallowInitBox(_, _) => { Ok(()) }, Rvalue::UnaryOp(_, operand) => { diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 11bb16ff6c5..6762c883005 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -1000,35 +1000,6 @@ pub fn adt_and_variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option< } } -/// Checks if the type is a type parameter implementing `FnOnce`, but not `FnMut`. -pub fn ty_is_fn_once_param<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, predicates: &'tcx [ty::Clause<'_>]) -> bool { - let ty::Param(ty) = *ty.kind() else { - return false; - }; - let lang = tcx.lang_items(); - let (Some(fn_once_id), Some(fn_mut_id), Some(fn_id)) = (lang.fn_once_trait(), lang.fn_mut_trait(), lang.fn_trait()) - else { - return false; - }; - predicates - .iter() - .try_fold(false, |found, p| { - if let ty::ClauseKind::Trait(p) = p.kind().skip_binder() - && let ty::Param(self_ty) = p.trait_ref.self_ty().kind() - && ty.index == self_ty.index - { - // This should use `super_traits_of`, but that's a private function. - if p.trait_ref.def_id == fn_once_id { - return Some(true); - } else if p.trait_ref.def_id == fn_mut_id || p.trait_ref.def_id == fn_id { - return None; - } - } - Some(found) - }) - .unwrap_or(false) -} - /// Comes up with an "at least" guesstimate for the type's size, not taking into /// account the layout of type parameters. pub fn approx_ty_size<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> u64 { diff --git a/src/tools/clippy/declare_clippy_lint/Cargo.toml b/src/tools/clippy/declare_clippy_lint/Cargo.toml index 5aaafb41721..0f90cef5cdd 100644 --- a/src/tools/clippy/declare_clippy_lint/Cargo.toml +++ b/src/tools/clippy/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.77" +version = "0.1.78" edition = "2021" publish = false diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index d2d56e59ee3..fcf5c456270 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-01-25" +channel = "nightly-2024-02-08" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index b944a299256..bdf1cf0a224 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -1,3 +1,5 @@ +#![allow(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::untranslatable_diagnostic)] #![feature(rustc_private)] #![feature(let_chains)] #![feature(lazy_cell)] @@ -22,9 +24,11 @@ use rustc_session::EarlyDiagCtxt; use rustc_span::symbol::Symbol; use std::env; +use std::fs::read_to_string; use std::ops::Deref; use std::path::Path; use std::process::exit; +use std::string::ToString; use anstream::println; @@ -188,12 +192,31 @@ pub fn main() { exit(rustc_driver::catch_with_exit_code(move || { let mut orig_args: Vec<String> = env::args().collect(); - let has_sysroot_arg = arg_value(&orig_args, "--sysroot", |_| true).is_some(); + + let has_sysroot_arg = |args: &mut [String]| -> bool { + if arg_value(args, "--sysroot", |_| true).is_some() { + return true; + } + // https://doc.rust-lang.org/rustc/command-line-arguments.html#path-load-command-line-flags-from-a-path + // Beside checking for existence of `--sysroot` on the command line, we need to + // check for the arg files that are prefixed with @ as well to be consistent with rustc + for arg in args.iter() { + if let Some(arg_file_path) = arg.strip_prefix('@') { + if let Ok(arg_file) = read_to_string(arg_file_path) { + let split_arg_file: Vec<String> = arg_file.lines().map(ToString::to_string).collect(); + if arg_value(&split_arg_file, "--sysroot", |_| true).is_some() { + return true; + } + } + } + } + false + }; let sys_root_env = std::env::var("SYSROOT").ok(); let pass_sysroot_env_if_given = |args: &mut Vec<String>, sys_root_env| { if let Some(sys_root) = sys_root_env { - if !has_sysroot_arg { + if !has_sysroot_arg(args) { args.extend(vec!["--sysroot".into(), sys_root]); } }; diff --git a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr new file mode 100644 index 00000000000..103e60d8484 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr @@ -0,0 +1,45 @@ +error: lint group `rust_2018_idioms` has the same priority (0) as a lint + --> Cargo.toml:7:1 + | +7 | rust_2018_idioms = "warn" + | ^^^^^^^^^^^^^^^^ ------ has an implicit priority of 0 +8 | bare_trait_objects = "allow" + | ------------------ has the same priority as this lint + | + = note: the order of the lints in the table is ignored by Cargo + = note: `#[deny(clippy::lint_groups_priority)]` on by default +help: to have lints override the group set `rust_2018_idioms` to a lower priority + | +7 | rust_2018_idioms = { level = "warn", priority = -1 } + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: lint group `unused` has the same priority (0) as a lint + --> Cargo.toml:10:1 + | +10 | unused = { level = "deny" } + | ^^^^^^ ------------------ has an implicit priority of 0 +11 | unused_braces = { level = "allow", priority = 1 } +12 | unused_attributes = { level = "allow" } + | ----------------- has the same priority as this lint + | + = note: the order of the lints in the table is ignored by Cargo +help: to have lints override the group set `unused` to a lower priority + | +10 | unused = { level = "deny", priority = -1 } + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: lint group `pedantic` has the same priority (-1) as a lint + --> Cargo.toml:19:1 + | +19 | pedantic = { level = "warn", priority = -1 } + | ^^^^^^^^ +20 | similar_names = { level = "allow", priority = -1 } + | ------------- has the same priority as this lint + | + = note: the order of the lints in the table is ignored by Cargo +help: to have lints override the group set `pedantic` to a lower priority + | +19 | pedantic = { level = "warn", priority = -2 } + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: could not compile `fail` (lib) due to 3 previous errors diff --git a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml new file mode 100644 index 00000000000..4ce41f78171 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "fail" +version = "0.1.0" +publish = false + +[lints.rust] +rust_2018_idioms = "warn" +bare_trait_objects = "allow" + +unused = { level = "deny" } +unused_braces = { level = "allow", priority = 1 } +unused_attributes = { level = "allow" } + +# `warnings` is not a group so the order it is passed does not matter +warnings = "deny" +deprecated = "allow" + +[lints.clippy] +pedantic = { level = "warn", priority = -1 } +similar_names = { level = "allow", priority = -1 } diff --git a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/src/lib.rs b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/src/lib.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/fail/src/lib.rs @@ -0,0 +1 @@ + diff --git a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/pass/Cargo.toml b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/pass/Cargo.toml new file mode 100644 index 00000000000..e9fcf803d93 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/pass/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "pass" +version = "0.1.0" +publish = false + +[lints.clippy] +pedantic = { level = "warn", priority = -1 } +style = { level = "warn", priority = 1 } +similar_names = "allow" +dbg_macro = { level = "warn", priority = 2 } diff --git a/src/tools/clippy/tests/ui-cargo/lint_groups_priority/pass/src/lib.rs b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/pass/src/lib.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/src/tools/clippy/tests/ui-cargo/lint_groups_priority/pass/src/lib.rs @@ -0,0 +1 @@ + diff --git a/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.fixed b/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.fixed index 6c58e07d846..497f783087a 100644 --- a/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.fixed +++ b/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.fixed @@ -1,4 +1,4 @@ -#![allow(clippy::redundant_clone, clippy::unnecessary_operation)] +#![allow(clippy::redundant_clone, clippy::unnecessary_operation, clippy::incompatible_msrv)] #![warn(clippy::manual_non_exhaustive, clippy::borrow_as_ptr, clippy::manual_bits)] use std::mem::{size_of, size_of_val}; diff --git a/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs b/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs index e1dc3f4389c..6e7874108a3 100644 --- a/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs +++ b/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs @@ -1,4 +1,4 @@ -#![allow(clippy::redundant_clone, clippy::unnecessary_operation)] +#![allow(clippy::redundant_clone, clippy::unnecessary_operation, clippy::incompatible_msrv)] #![warn(clippy::manual_non_exhaustive, clippy::borrow_as_ptr, clippy::manual_bits)] use std::mem::{size_of, size_of_val}; diff --git a/src/tools/clippy/tests/ui-toml/modulo_arithmetic/clippy.toml b/src/tools/clippy/tests/ui-toml/modulo_arithmetic/clippy.toml new file mode 100644 index 00000000000..de80f4ae598 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/modulo_arithmetic/clippy.toml @@ -0,0 +1 @@ +allow-comparison-to-zero = false diff --git a/src/tools/clippy/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs b/src/tools/clippy/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs new file mode 100644 index 00000000000..27d27564baf --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.rs @@ -0,0 +1,10 @@ +#![warn(clippy::modulo_arithmetic)] + +fn main() { + let a = -1; + let b = 2; + let c = a % b == 0; + let c = a % b != 0; + let c = 0 == a % b; + let c = 0 != a % b; +} diff --git a/src/tools/clippy/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.stderr b/src/tools/clippy/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.stderr new file mode 100644 index 00000000000..da644b05a11 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/modulo_arithmetic/modulo_arithmetic.stderr @@ -0,0 +1,40 @@ +error: you are using modulo operator on types that might have different signs + --> $DIR/modulo_arithmetic.rs:6:13 + | +LL | let c = a % b == 0; + | ^^^^^ + | + = note: double check for expected result especially when interoperating with different languages + = note: or consider using `rem_euclid` or similar function + = note: `-D clippy::modulo-arithmetic` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::modulo_arithmetic)]` + +error: you are using modulo operator on types that might have different signs + --> $DIR/modulo_arithmetic.rs:7:13 + | +LL | let c = a % b != 0; + | ^^^^^ + | + = note: double check for expected result especially when interoperating with different languages + = note: or consider using `rem_euclid` or similar function + +error: you are using modulo operator on types that might have different signs + --> $DIR/modulo_arithmetic.rs:8:18 + | +LL | let c = 0 == a % b; + | ^^^^^ + | + = note: double check for expected result especially when interoperating with different languages + = note: or consider using `rem_euclid` or similar function + +error: you are using modulo operator on types that might have different signs + --> $DIR/modulo_arithmetic.rs:9:18 + | +LL | let c = 0 != a % b; + | ^^^^^ + | + = note: double check for expected result especially when interoperating with different languages + = note: or consider using `rem_euclid` or similar function + +error: aborting due to 4 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index fc683e514ba..f097d2503e1 100644 --- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -3,6 +3,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect absolute-paths-max-segments accept-comment-above-attributes accept-comment-above-statement + allow-comparison-to-zero allow-dbg-in-tests allow-expect-in-tests allow-mixed-uninlined-format-args @@ -14,6 +15,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect allowed-duplicate-crates allowed-idents-below-min-chars allowed-scripts + allowed-wildcard-imports arithmetic-side-effects-allowed arithmetic-side-effects-allowed-binary arithmetic-side-effects-allowed-unary @@ -80,6 +82,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect absolute-paths-max-segments accept-comment-above-attributes accept-comment-above-statement + allow-comparison-to-zero allow-dbg-in-tests allow-expect-in-tests allow-mixed-uninlined-format-args @@ -91,6 +94,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect allowed-duplicate-crates allowed-idents-below-min-chars allowed-scripts + allowed-wildcard-imports arithmetic-side-effects-allowed arithmetic-side-effects-allowed-binary arithmetic-side-effects-allowed-unary @@ -157,6 +161,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni absolute-paths-max-segments accept-comment-above-attributes accept-comment-above-statement + allow-comparison-to-zero allow-dbg-in-tests allow-expect-in-tests allow-mixed-uninlined-format-args @@ -168,6 +173,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni allowed-duplicate-crates allowed-idents-below-min-chars allowed-scripts + allowed-wildcard-imports arithmetic-side-effects-allowed arithmetic-side-effects-allowed-binary arithmetic-side-effects-allowed-unary diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/clippy.toml b/src/tools/clippy/tests/ui-toml/wildcard_imports/clippy.toml index 875aaeef6c9..68815c1756a 100644 --- a/src/tools/clippy/tests/ui-toml/wildcard_imports/clippy.toml +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/clippy.toml @@ -1 +1,4 @@ warn-on-all-wildcard-imports = true + +# This should be ignored since `warn-on-all-wildcard-imports` has higher precedence +allowed-wildcard-imports = ["utils"] diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed index 1752f48856c..af72d6be0e0 100644 --- a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.fixed @@ -3,9 +3,28 @@ mod prelude { pub const FOO: u8 = 1; } + +mod utils { + pub const BAR: u8 = 1; + pub fn print() {} +} + +mod my_crate { + pub mod utils { + pub fn my_util_fn() {} + } +} + +use utils::{BAR, print}; +//~^ ERROR: usage of wildcard import +use my_crate::utils::my_util_fn; +//~^ ERROR: usage of wildcard import use prelude::FOO; //~^ ERROR: usage of wildcard import fn main() { let _ = FOO; + let _ = BAR; + print(); + my_util_fn(); } diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs index 331c2c59c22..91009dd8835 100644 --- a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.rs @@ -3,9 +3,28 @@ mod prelude { pub const FOO: u8 = 1; } + +mod utils { + pub const BAR: u8 = 1; + pub fn print() {} +} + +mod my_crate { + pub mod utils { + pub fn my_util_fn() {} + } +} + +use utils::*; +//~^ ERROR: usage of wildcard import +use my_crate::utils::*; +//~^ ERROR: usage of wildcard import use prelude::*; //~^ ERROR: usage of wildcard import fn main() { let _ = FOO; + let _ = BAR; + print(); + my_util_fn(); } diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr index f11fda6a0c6..a733d786d0e 100644 --- a/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports/wildcard_imports.stderr @@ -1,11 +1,23 @@ error: usage of wildcard import - --> $DIR/wildcard_imports.rs:6:5 + --> $DIR/wildcard_imports.rs:18:5 | -LL | use prelude::*; - | ^^^^^^^^^^ help: try: `prelude::FOO` +LL | use utils::*; + | ^^^^^^^^ help: try: `utils::{BAR, print}` | = note: `-D clippy::wildcard-imports` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::wildcard_imports)]` -error: aborting due to 1 previous error +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:20:5 + | +LL | use my_crate::utils::*; + | ^^^^^^^^^^^^^^^^^^ help: try: `my_crate::utils::my_util_fn` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:22:5 + | +LL | use prelude::*; + | ^^^^^^^^^^ help: try: `prelude::FOO` + +error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports_whitelist/clippy.toml b/src/tools/clippy/tests/ui-toml/wildcard_imports_whitelist/clippy.toml new file mode 100644 index 00000000000..6b7882e64a8 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports_whitelist/clippy.toml @@ -0,0 +1 @@ +allowed-wildcard-imports = ["utils"] diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports_whitelist/wildcard_imports.fixed b/src/tools/clippy/tests/ui-toml/wildcard_imports_whitelist/wildcard_imports.fixed new file mode 100644 index 00000000000..d539525c45e --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports_whitelist/wildcard_imports.fixed @@ -0,0 +1,26 @@ +#![warn(clippy::wildcard_imports)] + +mod utils { + pub fn print() {} +} + +mod utils_plus { + pub fn do_something() {} +} + +mod my_crate { + pub mod utils { + pub fn my_util_fn() {} + } +} + +use my_crate::utils::*; +use utils::*; +use utils_plus::do_something; +//~^ ERROR: usage of wildcard import + +fn main() { + print(); + my_util_fn(); + do_something(); +} diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports_whitelist/wildcard_imports.rs b/src/tools/clippy/tests/ui-toml/wildcard_imports_whitelist/wildcard_imports.rs new file mode 100644 index 00000000000..9169d16a08b --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports_whitelist/wildcard_imports.rs @@ -0,0 +1,26 @@ +#![warn(clippy::wildcard_imports)] + +mod utils { + pub fn print() {} +} + +mod utils_plus { + pub fn do_something() {} +} + +mod my_crate { + pub mod utils { + pub fn my_util_fn() {} + } +} + +use my_crate::utils::*; +use utils::*; +use utils_plus::*; +//~^ ERROR: usage of wildcard import + +fn main() { + print(); + my_util_fn(); + do_something(); +} diff --git a/src/tools/clippy/tests/ui-toml/wildcard_imports_whitelist/wildcard_imports.stderr b/src/tools/clippy/tests/ui-toml/wildcard_imports_whitelist/wildcard_imports.stderr new file mode 100644 index 00000000000..12c2f9cbada --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/wildcard_imports_whitelist/wildcard_imports.stderr @@ -0,0 +1,11 @@ +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:19:5 + | +LL | use utils_plus::*; + | ^^^^^^^^^^^^^ help: try: `utils_plus::do_something` + | + = note: `-D clippy::wildcard-imports` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::wildcard_imports)]` + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr.fixed b/src/tools/clippy/tests/ui/borrow_as_ptr.fixed index 6c0de96d65e..289a5ef38b8 100644 --- a/src/tools/clippy/tests/ui/borrow_as_ptr.fixed +++ b/src/tools/clippy/tests/ui/borrow_as_ptr.fixed @@ -5,6 +5,7 @@ fn a() -> i32 { 0 } +#[clippy::msrv = "1.75"] fn main() { let val = 1; let _p = std::ptr::addr_of!(val); diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr.rs b/src/tools/clippy/tests/ui/borrow_as_ptr.rs index c37c5357c82..b5328cb22dc 100644 --- a/src/tools/clippy/tests/ui/borrow_as_ptr.rs +++ b/src/tools/clippy/tests/ui/borrow_as_ptr.rs @@ -5,6 +5,7 @@ fn a() -> i32 { 0 } +#[clippy::msrv = "1.75"] fn main() { let val = 1; let _p = &val as *const i32; diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr.stderr b/src/tools/clippy/tests/ui/borrow_as_ptr.stderr index 43a7a6bf5b5..b9861805905 100644 --- a/src/tools/clippy/tests/ui/borrow_as_ptr.stderr +++ b/src/tools/clippy/tests/ui/borrow_as_ptr.stderr @@ -1,5 +1,5 @@ error: borrow as raw pointer - --> $DIR/borrow_as_ptr.rs:10:14 + --> $DIR/borrow_as_ptr.rs:11:14 | LL | let _p = &val as *const i32; | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of!(val)` @@ -8,7 +8,7 @@ LL | let _p = &val as *const i32; = help: to override `-D warnings` add `#[allow(clippy::borrow_as_ptr)]` error: borrow as raw pointer - --> $DIR/borrow_as_ptr.rs:17:18 + --> $DIR/borrow_as_ptr.rs:18:18 | LL | let _p_mut = &mut val_mut as *mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of_mut!(val_mut)` diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed index a361a36474d..f66554de300 100644 --- a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed +++ b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed @@ -2,6 +2,7 @@ #![feature(lang_items, start, libc)] #![no_std] +#[clippy::msrv = "1.75"] #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { let val = 1; diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs index b3fe01442b7..1fc254aafa7 100644 --- a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs +++ b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs @@ -2,6 +2,7 @@ #![feature(lang_items, start, libc)] #![no_std] +#[clippy::msrv = "1.75"] #[start] fn main(_argc: isize, _argv: *const *const u8) -> isize { let val = 1; diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.stderr b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.stderr index 2f258bcf966..1ef0a948a32 100644 --- a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.stderr +++ b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.stderr @@ -1,5 +1,5 @@ error: borrow as raw pointer - --> $DIR/borrow_as_ptr_no_std.rs:8:14 + --> $DIR/borrow_as_ptr_no_std.rs:9:14 | LL | let _p = &val as *const i32; | ^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::addr_of!(val)` @@ -8,7 +8,7 @@ LL | let _p = &val as *const i32; = help: to override `-D warnings` add `#[allow(clippy::borrow_as_ptr)]` error: borrow as raw pointer - --> $DIR/borrow_as_ptr_no_std.rs:11:18 + --> $DIR/borrow_as_ptr_no_std.rs:12:18 | LL | let _p_mut = &mut val_mut as *mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::addr_of_mut!(val_mut)` diff --git a/src/tools/clippy/tests/ui/eta.fixed b/src/tools/clippy/tests/ui/eta.fixed index 32c7499bf73..da28ec2e653 100644 --- a/src/tools/clippy/tests/ui/eta.fixed +++ b/src/tools/clippy/tests/ui/eta.fixed @@ -346,6 +346,23 @@ fn angle_brackets_and_args() { dyn_opt.map(<dyn TestTrait>::method_on_dyn); } +// https://github.com/rust-lang/rust-clippy/issues/12199 +fn track_caller_fp() { + struct S; + impl S { + #[track_caller] + fn add_location(self) {} + } + + #[track_caller] + fn add_location() {} + + fn foo(_: fn()) {} + fn foo2(_: fn(S)) {} + foo(|| add_location()); + foo2(|s| s.add_location()); +} + fn _late_bound_to_early_bound_regions() { struct Foo<'a>(&'a u32); impl<'a> Foo<'a> { @@ -400,3 +417,57 @@ fn _closure_with_types() { let _ = f2(|x: u32| f(x)); let _ = f2(|x| -> u32 { f(x) }); } + +/// https://github.com/rust-lang/rust-clippy/issues/10854 +/// This is to verify that redundant_closure_for_method_calls resolves suggested paths to relative. +mod issue_10854 { + pub mod test_mod { + pub struct Test; + + impl Test { + pub fn method(self) -> i32 { + 0 + } + } + + pub fn calls_test(test: Option<Test>) -> Option<i32> { + test.map(Test::method) + } + + pub fn calls_outer(test: Option<super::Outer>) -> Option<i32> { + test.map(super::Outer::method) + } + } + + pub struct Outer; + + impl Outer { + pub fn method(self) -> i32 { + 0 + } + } + + pub fn calls_into_mod(test: Option<test_mod::Test>) -> Option<i32> { + test.map(test_mod::Test::method) + } + + mod a { + pub mod b { + pub mod c { + pub fn extreme_nesting(test: Option<super::super::super::d::Test>) -> Option<i32> { + test.map(crate::issue_10854::d::Test::method) + } + } + } + } + + mod d { + pub struct Test; + + impl Test { + pub fn method(self) -> i32 { + 0 + } + } + } +} diff --git a/src/tools/clippy/tests/ui/eta.rs b/src/tools/clippy/tests/ui/eta.rs index 25b7431ba8c..f924100f8f4 100644 --- a/src/tools/clippy/tests/ui/eta.rs +++ b/src/tools/clippy/tests/ui/eta.rs @@ -346,6 +346,23 @@ fn angle_brackets_and_args() { dyn_opt.map(|d| d.method_on_dyn()); } +// https://github.com/rust-lang/rust-clippy/issues/12199 +fn track_caller_fp() { + struct S; + impl S { + #[track_caller] + fn add_location(self) {} + } + + #[track_caller] + fn add_location() {} + + fn foo(_: fn()) {} + fn foo2(_: fn(S)) {} + foo(|| add_location()); + foo2(|s| s.add_location()); +} + fn _late_bound_to_early_bound_regions() { struct Foo<'a>(&'a u32); impl<'a> Foo<'a> { @@ -400,3 +417,57 @@ fn _closure_with_types() { let _ = f2(|x: u32| f(x)); let _ = f2(|x| -> u32 { f(x) }); } + +/// https://github.com/rust-lang/rust-clippy/issues/10854 +/// This is to verify that redundant_closure_for_method_calls resolves suggested paths to relative. +mod issue_10854 { + pub mod test_mod { + pub struct Test; + + impl Test { + pub fn method(self) -> i32 { + 0 + } + } + + pub fn calls_test(test: Option<Test>) -> Option<i32> { + test.map(|t| t.method()) + } + + pub fn calls_outer(test: Option<super::Outer>) -> Option<i32> { + test.map(|t| t.method()) + } + } + + pub struct Outer; + + impl Outer { + pub fn method(self) -> i32 { + 0 + } + } + + pub fn calls_into_mod(test: Option<test_mod::Test>) -> Option<i32> { + test.map(|t| t.method()) + } + + mod a { + pub mod b { + pub mod c { + pub fn extreme_nesting(test: Option<super::super::super::d::Test>) -> Option<i32> { + test.map(|t| t.method()) + } + } + } + } + + mod d { + pub struct Test; + + impl Test { + pub fn method(self) -> i32 { + 0 + } + } + } +} diff --git a/src/tools/clippy/tests/ui/eta.stderr b/src/tools/clippy/tests/ui/eta.stderr index 951e4ac749c..945de466d83 100644 --- a/src/tools/clippy/tests/ui/eta.stderr +++ b/src/tools/clippy/tests/ui/eta.stderr @@ -161,10 +161,34 @@ LL | dyn_opt.map(|d| d.method_on_dyn()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<dyn TestTrait>::method_on_dyn` error: redundant closure - --> $DIR/eta.rs:389:19 + --> $DIR/eta.rs:406:19 | LL | let _ = f(&0, |x, y| f2(x, y)); | ^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `f2` -error: aborting due to 27 previous errors +error: redundant closure + --> $DIR/eta.rs:434:22 + | +LL | test.map(|t| t.method()) + | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `Test::method` + +error: redundant closure + --> $DIR/eta.rs:438:22 + | +LL | test.map(|t| t.method()) + | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `super::Outer::method` + +error: redundant closure + --> $DIR/eta.rs:451:18 + | +LL | test.map(|t| t.method()) + | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `test_mod::Test::method` + +error: redundant closure + --> $DIR/eta.rs:458:30 + | +LL | test.map(|t| t.method()) + | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `crate::issue_10854::d::Test::method` + +error: aborting due to 31 previous errors diff --git a/src/tools/clippy/tests/ui/format_args.fixed b/src/tools/clippy/tests/ui/format_args.fixed index ddd5976c408..cab20b11e07 100644 --- a/src/tools/clippy/tests/ui/format_args.fixed +++ b/src/tools/clippy/tests/ui/format_args.fixed @@ -14,6 +14,7 @@ use std::panic::Location; struct Somewhere; +#[allow(clippy::to_string_trait_impl)] impl ToString for Somewhere { fn to_string(&self) -> String { String::from("somewhere") diff --git a/src/tools/clippy/tests/ui/format_args.rs b/src/tools/clippy/tests/ui/format_args.rs index 18e1bc1af67..bc3645cb2c2 100644 --- a/src/tools/clippy/tests/ui/format_args.rs +++ b/src/tools/clippy/tests/ui/format_args.rs @@ -14,6 +14,7 @@ use std::panic::Location; struct Somewhere; +#[allow(clippy::to_string_trait_impl)] impl ToString for Somewhere { fn to_string(&self) -> String { String::from("somewhere") diff --git a/src/tools/clippy/tests/ui/format_args.stderr b/src/tools/clippy/tests/ui/format_args.stderr index dcdfa668aff..2f1714296d6 100644 --- a/src/tools/clippy/tests/ui/format_args.stderr +++ b/src/tools/clippy/tests/ui/format_args.stderr @@ -1,5 +1,5 @@ error: `to_string` applied to a type that implements `Display` in `format!` args - --> $DIR/format_args.rs:76:72 + --> $DIR/format_args.rs:77:72 | LL | let _ = format!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this @@ -8,145 +8,145 @@ LL | let _ = format!("error: something failed at {}", Location::caller().to_ = help: to override `-D warnings` add `#[allow(clippy::to_string_in_format_args)]` error: `to_string` applied to a type that implements `Display` in `write!` args - --> $DIR/format_args.rs:80:27 + --> $DIR/format_args.rs:81:27 | LL | Location::caller().to_string() | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `writeln!` args - --> $DIR/format_args.rs:85:27 + --> $DIR/format_args.rs:86:27 | LL | Location::caller().to_string() | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `print!` args - --> $DIR/format_args.rs:87:63 + --> $DIR/format_args.rs:88:63 | LL | print!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/format_args.rs:88:65 + --> $DIR/format_args.rs:89:65 | LL | println!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `eprint!` args - --> $DIR/format_args.rs:89:64 + --> $DIR/format_args.rs:90:64 | LL | eprint!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `eprintln!` args - --> $DIR/format_args.rs:90:66 + --> $DIR/format_args.rs:91:66 | LL | eprintln!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `format_args!` args - --> $DIR/format_args.rs:91:77 + --> $DIR/format_args.rs:92:77 | LL | let _ = format_args!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `assert!` args - --> $DIR/format_args.rs:92:70 + --> $DIR/format_args.rs:93:70 | LL | assert!(true, "error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `assert_eq!` args - --> $DIR/format_args.rs:93:73 + --> $DIR/format_args.rs:94:73 | LL | assert_eq!(0, 0, "error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `assert_ne!` args - --> $DIR/format_args.rs:94:73 + --> $DIR/format_args.rs:95:73 | LL | assert_ne!(0, 0, "error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `panic!` args - --> $DIR/format_args.rs:95:63 + --> $DIR/format_args.rs:96:63 | LL | panic!("error: something failed at {}", Location::caller().to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/format_args.rs:96:20 + --> $DIR/format_args.rs:97:20 | LL | println!("{}", X(1).to_string()); | ^^^^^^^^^^^^^^^^ help: use this: `*X(1)` error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/format_args.rs:97:20 + --> $DIR/format_args.rs:98:20 | LL | println!("{}", Y(&X(1)).to_string()); | ^^^^^^^^^^^^^^^^^^^^ help: use this: `***Y(&X(1))` error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/format_args.rs:98:24 + --> $DIR/format_args.rs:99:24 | LL | println!("{}", Z(1).to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/format_args.rs:99:20 + --> $DIR/format_args.rs:100:20 | LL | println!("{}", x.to_string()); | ^^^^^^^^^^^^^ help: use this: `**x` error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/format_args.rs:100:20 + --> $DIR/format_args.rs:101:20 | LL | println!("{}", x_ref.to_string()); | ^^^^^^^^^^^^^^^^^ help: use this: `***x_ref` error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/format_args.rs:102:39 + --> $DIR/format_args.rs:103:39 | LL | println!("{foo}{bar}", foo = "foo".to_string(), bar = "bar"); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/format_args.rs:103:52 + --> $DIR/format_args.rs:104:52 | LL | println!("{foo}{bar}", foo = "foo", bar = "bar".to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/format_args.rs:104:39 + --> $DIR/format_args.rs:105:39 | LL | println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo"); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/format_args.rs:105:52 + --> $DIR/format_args.rs:106:52 | LL | println!("{foo}{bar}", bar = "bar", foo = "foo".to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `print!` args - --> $DIR/format_args.rs:117:37 + --> $DIR/format_args.rs:118:37 | LL | print!("{}", (Location::caller().to_string())); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `print!` args - --> $DIR/format_args.rs:118:39 + --> $DIR/format_args.rs:119:39 | LL | print!("{}", ((Location::caller()).to_string())); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `format!` args - --> $DIR/format_args.rs:146:38 + --> $DIR/format_args.rs:147:38 | LL | let x = format!("{} {}", a, b.to_string()); | ^^^^^^^^^^^^ help: remove this error: `to_string` applied to a type that implements `Display` in `println!` args - --> $DIR/format_args.rs:160:24 + --> $DIR/format_args.rs:161:24 | LL | println!("{}", original[..10].to_string()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use this: `&original[..10]` diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed b/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed index 707a0e76e4e..118f0b48895 100644 --- a/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed +++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.fixed @@ -1,6 +1,11 @@ //@aux-build:proc_macro_derive.rs #![warn(clippy::ignored_unit_patterns)] -#![allow(clippy::let_unit_value, clippy::redundant_pattern_matching, clippy::single_match)] +#![allow( + clippy::let_unit_value, + clippy::redundant_pattern_matching, + clippy::single_match, + clippy::needless_borrow +)] fn foo() -> Result<(), ()> { unimplemented!() diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.rs b/src/tools/clippy/tests/ui/ignored_unit_patterns.rs index 544f2b8f692..92feb9e6c28 100644 --- a/src/tools/clippy/tests/ui/ignored_unit_patterns.rs +++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.rs @@ -1,6 +1,11 @@ //@aux-build:proc_macro_derive.rs #![warn(clippy::ignored_unit_patterns)] -#![allow(clippy::let_unit_value, clippy::redundant_pattern_matching, clippy::single_match)] +#![allow( + clippy::let_unit_value, + clippy::redundant_pattern_matching, + clippy::single_match, + clippy::needless_borrow +)] fn foo() -> Result<(), ()> { unimplemented!() diff --git a/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr b/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr index 05c8f281e55..18ca7ebbcf2 100644 --- a/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr +++ b/src/tools/clippy/tests/ui/ignored_unit_patterns.stderr @@ -1,5 +1,5 @@ error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:11:12 + --> $DIR/ignored_unit_patterns.rs:16:12 | LL | Ok(_) => {}, | ^ help: use `()` instead of `_`: `()` @@ -8,49 +8,49 @@ LL | Ok(_) => {}, = help: to override `-D warnings` add `#[allow(clippy::ignored_unit_patterns)]` error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:12:13 + --> $DIR/ignored_unit_patterns.rs:17:13 | LL | Err(_) => {}, | ^ help: use `()` instead of `_`: `()` error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:14:15 + --> $DIR/ignored_unit_patterns.rs:19:15 | LL | if let Ok(_) = foo() {} | ^ help: use `()` instead of `_`: `()` error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:16:28 + --> $DIR/ignored_unit_patterns.rs:21:28 | LL | let _ = foo().map_err(|_| todo!()); | ^ help: use `()` instead of `_`: `()` error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:22:16 + --> $DIR/ignored_unit_patterns.rs:27:16 | LL | Ok(_) => {}, | ^ help: use `()` instead of `_`: `()` error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:24:17 + --> $DIR/ignored_unit_patterns.rs:29:17 | LL | Err(_) => {}, | ^ help: use `()` instead of `_`: `()` error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:36:9 + --> $DIR/ignored_unit_patterns.rs:41:9 | LL | let _ = foo().unwrap(); | ^ help: use `()` instead of `_`: `()` error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:45:13 + --> $DIR/ignored_unit_patterns.rs:50:13 | LL | (1, _) => unimplemented!(), | ^ help: use `()` instead of `_`: `()` error: matching over `()` is more explicit - --> $DIR/ignored_unit_patterns.rs:52:13 + --> $DIR/ignored_unit_patterns.rs:57:13 | LL | for (x, _) in v { | ^ help: use `()` instead of `_`: `()` diff --git a/src/tools/clippy/tests/ui/incompatible_msrv.rs b/src/tools/clippy/tests/ui/incompatible_msrv.rs new file mode 100644 index 00000000000..a92017fb0f6 --- /dev/null +++ b/src/tools/clippy/tests/ui/incompatible_msrv.rs @@ -0,0 +1,23 @@ +#![warn(clippy::incompatible_msrv)] +#![feature(custom_inner_attributes)] +#![clippy::msrv = "1.3.0"] + +use std::collections::hash_map::Entry; +use std::collections::HashMap; +use std::thread::sleep; +use std::time::Duration; + +fn foo() { + let mut map: HashMap<&str, u32> = HashMap::new(); + assert_eq!(map.entry("poneyland").key(), &"poneyland"); + //~^ ERROR: is `1.3.0` but this item is stable since `1.10.0` + if let Entry::Vacant(v) = map.entry("poneyland") { + v.into_key(); + //~^ ERROR: is `1.3.0` but this item is stable since `1.12.0` + } + // Should warn for `sleep` but not for `Duration` (which was added in `1.3.0`). + sleep(Duration::new(1, 0)); + //~^ ERROR: is `1.3.0` but this item is stable since `1.4.0` +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/incompatible_msrv.stderr b/src/tools/clippy/tests/ui/incompatible_msrv.stderr new file mode 100644 index 00000000000..bd5ecd6ed2f --- /dev/null +++ b/src/tools/clippy/tests/ui/incompatible_msrv.stderr @@ -0,0 +1,23 @@ +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.10.0` + --> $DIR/incompatible_msrv.rs:12:39 + | +LL | assert_eq!(map.entry("poneyland").key(), &"poneyland"); + | ^^^^^ + | + = note: `-D clippy::incompatible-msrv` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::incompatible_msrv)]` + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.12.0` + --> $DIR/incompatible_msrv.rs:15:11 + | +LL | v.into_key(); + | ^^^^^^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.4.0` + --> $DIR/incompatible_msrv.rs:19:5 + | +LL | sleep(Duration::new(1, 0)); + | ^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_c_str_literals.fixed b/src/tools/clippy/tests/ui/manual_c_str_literals.fixed new file mode 100644 index 00000000000..a24d7088c88 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_c_str_literals.fixed @@ -0,0 +1,60 @@ +#![warn(clippy::manual_c_str_literals)] +#![allow(clippy::no_effect)] + +use std::ffi::CStr; + +macro_rules! cstr { + ($s:literal) => { + CStr::from_bytes_with_nul(concat!($s, "\0").as_bytes()).unwrap() + }; +} + +macro_rules! macro_returns_c_str { + () => { + CStr::from_bytes_with_nul(b"foo\0").unwrap(); + }; +} + +macro_rules! macro_returns_byte_string { + () => { + b"foo\0" + }; +} + +#[clippy::msrv = "1.76.0"] +fn pre_stabilization() { + CStr::from_bytes_with_nul(b"foo\0"); +} + +#[clippy::msrv = "1.77.0"] +fn post_stabilization() { + c"foo"; +} + +fn main() { + c"foo"; + c"foo"; + c"foo"; + c"foo\\0sdsd"; + CStr::from_bytes_with_nul(br"foo\\0sdsd\0").unwrap(); + CStr::from_bytes_with_nul(br"foo\x00").unwrap(); + CStr::from_bytes_with_nul(br##"foo#a\0"##).unwrap(); + + unsafe { c"foo" }; + unsafe { c"foo" }; + let _: *const _ = c"foo".as_ptr(); + let _: *const _ = c"foo".as_ptr(); + let _: *const _ = "foo".as_ptr(); // not a C-string + let _: *const _ = "".as_ptr(); + let _: *const _ = c"foo".as_ptr().cast::<i8>(); + let _ = "电脑".as_ptr(); + let _ = "电脑\\".as_ptr(); + let _ = c"电脑\\".as_ptr(); + let _ = c"电脑".as_ptr(); + let _ = c"电脑".as_ptr(); + + // Macro cases, don't lint: + cstr!("foo"); + macro_returns_c_str!(); + CStr::from_bytes_with_nul(macro_returns_byte_string!()).unwrap(); +} diff --git a/src/tools/clippy/tests/ui/manual_c_str_literals.rs b/src/tools/clippy/tests/ui/manual_c_str_literals.rs new file mode 100644 index 00000000000..0a007786720 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_c_str_literals.rs @@ -0,0 +1,60 @@ +#![warn(clippy::manual_c_str_literals)] +#![allow(clippy::no_effect)] + +use std::ffi::CStr; + +macro_rules! cstr { + ($s:literal) => { + CStr::from_bytes_with_nul(concat!($s, "\0").as_bytes()).unwrap() + }; +} + +macro_rules! macro_returns_c_str { + () => { + CStr::from_bytes_with_nul(b"foo\0").unwrap(); + }; +} + +macro_rules! macro_returns_byte_string { + () => { + b"foo\0" + }; +} + +#[clippy::msrv = "1.76.0"] +fn pre_stabilization() { + CStr::from_bytes_with_nul(b"foo\0"); +} + +#[clippy::msrv = "1.77.0"] +fn post_stabilization() { + CStr::from_bytes_with_nul(b"foo\0"); +} + +fn main() { + CStr::from_bytes_with_nul(b"foo\0"); + CStr::from_bytes_with_nul(b"foo\x00"); + CStr::from_bytes_with_nul(b"foo\0").unwrap(); + CStr::from_bytes_with_nul(b"foo\\0sdsd\0").unwrap(); + CStr::from_bytes_with_nul(br"foo\\0sdsd\0").unwrap(); + CStr::from_bytes_with_nul(br"foo\x00").unwrap(); + CStr::from_bytes_with_nul(br##"foo#a\0"##).unwrap(); + + unsafe { CStr::from_ptr(b"foo\0".as_ptr().cast()) }; + unsafe { CStr::from_ptr(b"foo\0".as_ptr() as *const _) }; + let _: *const _ = b"foo\0".as_ptr(); + let _: *const _ = "foo\0".as_ptr(); + let _: *const _ = "foo".as_ptr(); // not a C-string + let _: *const _ = "".as_ptr(); + let _: *const _ = b"foo\0".as_ptr().cast::<i8>(); + let _ = "电脑".as_ptr(); + let _ = "电脑\\".as_ptr(); + let _ = "电脑\\\0".as_ptr(); + let _ = "电脑\0".as_ptr(); + let _ = "电脑\x00".as_ptr(); + + // Macro cases, don't lint: + cstr!("foo"); + macro_returns_c_str!(); + CStr::from_bytes_with_nul(macro_returns_byte_string!()).unwrap(); +} diff --git a/src/tools/clippy/tests/ui/manual_c_str_literals.stderr b/src/tools/clippy/tests/ui/manual_c_str_literals.stderr new file mode 100644 index 00000000000..8de4e16f010 --- /dev/null +++ b/src/tools/clippy/tests/ui/manual_c_str_literals.stderr @@ -0,0 +1,83 @@ +error: calling `CStr::new` with a byte string literal + --> $DIR/manual_c_str_literals.rs:31:5 + | +LL | CStr::from_bytes_with_nul(b"foo\0"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo"` + | + = note: `-D clippy::manual-c-str-literals` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_c_str_literals)]` + +error: calling `CStr::new` with a byte string literal + --> $DIR/manual_c_str_literals.rs:35:5 + | +LL | CStr::from_bytes_with_nul(b"foo\0"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo"` + +error: calling `CStr::new` with a byte string literal + --> $DIR/manual_c_str_literals.rs:36:5 + | +LL | CStr::from_bytes_with_nul(b"foo\x00"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo"` + +error: calling `CStr::new` with a byte string literal + --> $DIR/manual_c_str_literals.rs:37:5 + | +LL | CStr::from_bytes_with_nul(b"foo\0").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo"` + +error: calling `CStr::new` with a byte string literal + --> $DIR/manual_c_str_literals.rs:38:5 + | +LL | CStr::from_bytes_with_nul(b"foo\\0sdsd\0").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo\\0sdsd"` + +error: calling `CStr::from_ptr` with a byte string literal + --> $DIR/manual_c_str_literals.rs:43:14 + | +LL | unsafe { CStr::from_ptr(b"foo\0".as_ptr().cast()) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo"` + +error: calling `CStr::from_ptr` with a byte string literal + --> $DIR/manual_c_str_literals.rs:44:14 + | +LL | unsafe { CStr::from_ptr(b"foo\0".as_ptr() as *const _) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use a `c""` literal: `c"foo"` + +error: manually constructing a nul-terminated string + --> $DIR/manual_c_str_literals.rs:45:23 + | +LL | let _: *const _ = b"foo\0".as_ptr(); + | ^^^^^^^^ help: use a `c""` literal: `c"foo"` + +error: manually constructing a nul-terminated string + --> $DIR/manual_c_str_literals.rs:46:23 + | +LL | let _: *const _ = "foo\0".as_ptr(); + | ^^^^^^^ help: use a `c""` literal: `c"foo"` + +error: manually constructing a nul-terminated string + --> $DIR/manual_c_str_literals.rs:49:23 + | +LL | let _: *const _ = b"foo\0".as_ptr().cast::<i8>(); + | ^^^^^^^^ help: use a `c""` literal: `c"foo"` + +error: manually constructing a nul-terminated string + --> $DIR/manual_c_str_literals.rs:52:13 + | +LL | let _ = "电脑\\\0".as_ptr(); + | ^^^^^^^^^^ help: use a `c""` literal: `c"电脑\\"` + +error: manually constructing a nul-terminated string + --> $DIR/manual_c_str_literals.rs:53:13 + | +LL | let _ = "电脑\0".as_ptr(); + | ^^^^^^^^ help: use a `c""` literal: `c"电脑"` + +error: manually constructing a nul-terminated string + --> $DIR/manual_c_str_literals.rs:54:13 + | +LL | let _ = "电脑\x00".as_ptr(); + | ^^^^^^^^^^ help: use a `c""` literal: `c"电脑"` + +error: aborting due to 13 previous errors + diff --git a/src/tools/clippy/tests/ui/manual_retain.fixed b/src/tools/clippy/tests/ui/manual_retain.fixed index 4dea3e8bfe6..5540029bf6b 100644 --- a/src/tools/clippy/tests/ui/manual_retain.fixed +++ b/src/tools/clippy/tests/ui/manual_retain.fixed @@ -14,6 +14,9 @@ fn main() { _msrv_153(); _msrv_126(); _msrv_118(); + + issue_10393(); + issue_12081(); } fn binary_heap_retain() { @@ -23,6 +26,11 @@ fn binary_heap_retain() { binary_heap.retain(|x| x % 2 == 0); binary_heap.retain(|x| x % 2 == 0); + // Do lint, because we use pattern matching + let mut tuples = BinaryHeap::from([(0, 1), (1, 2), (2, 3)]); + tuples.retain(|(ref x, ref y)| *x == 0); + tuples.retain(|(x, y)| *x == 0); + // Do not lint, because type conversion is performed binary_heap = binary_heap .into_iter() @@ -55,6 +63,9 @@ fn btree_map_retain() { btree_map.retain(|_, &mut v| v % 2 == 0); btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0)); + // Do not lint, because the parameters are not matched in tuple pattern + btree_map = btree_map.into_iter().filter(|t| t.0 % 2 == 0).collect(); + // Do not lint. btree_map = btree_map .into_iter() @@ -76,6 +87,11 @@ fn btree_set_retain() { btree_set.retain(|x| x % 2 == 0); btree_set.retain(|x| x % 2 == 0); + // Do lint, because we use pattern matching + let mut tuples = BTreeSet::from([(0, 1), (1, 2), (2, 3)]); + tuples.retain(|(ref x, ref y)| *x == 0); + tuples.retain(|(x, y)| *x == 0); + // Do not lint, because type conversion is performed btree_set = btree_set .iter() @@ -108,6 +124,9 @@ fn hash_map_retain() { hash_map.retain(|_, &mut v| v % 2 == 0); hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0)); + // Do not lint, because the parameters are not matched in tuple pattern + hash_map = hash_map.into_iter().filter(|t| t.0 % 2 == 0).collect(); + // Do not lint. hash_map = hash_map .into_iter() @@ -128,6 +147,11 @@ fn hash_set_retain() { hash_set.retain(|x| x % 2 == 0); hash_set.retain(|x| x % 2 == 0); + // Do lint, because we use pattern matching + let mut tuples = HashSet::from([(0, 1), (1, 2), (2, 3)]); + tuples.retain(|(ref x, ref y)| *x == 0); + tuples.retain(|(x, y)| *x == 0); + // Do not lint, because type conversion is performed hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect::<HashSet<i8>>(); hash_set = hash_set @@ -171,6 +195,11 @@ fn vec_retain() { vec.retain(|x| x % 2 == 0); vec.retain(|x| x % 2 == 0); + // Do lint, because we use pattern matching + let mut tuples = vec![(0, 1), (1, 2), (2, 3)]; + tuples.retain(|(ref x, ref y)| *x == 0); + tuples.retain(|(x, y)| *x == 0); + // Do not lint, because type conversion is performed vec = vec.into_iter().filter(|x| x % 2 == 0).collect::<Vec<i8>>(); vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect::<Vec<i8>>(); @@ -246,3 +275,37 @@ fn _msrv_118() { let mut hash_map: HashMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect(); hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); } + +fn issue_10393() { + // Do lint + let mut vec = vec![(0, 1), (1, 2), (2, 3)]; + vec.retain(|(x, y)| *x == 0); + + // Do lint + let mut tuples = vec![(true, -2), (false, 3)]; + tuples.retain(|(_, n)| *n > 0); +} + +fn issue_11457() { + // Do not lint, as we need to modify the closure + let mut vals = vec![1, 2, 3, 4]; + vals = vals.iter().filter(|v| **v != 1).cloned().collect(); + + // Do not lint, as we need to modify the closure + let mut s = String::from("foobar"); + s = s.chars().filter(|c| *c != 'o').to_owned().collect(); +} + +fn issue_12081() { + let mut vec = vec![0, 1, 2]; + + // Do lint + vec.retain(|&x| x == 0); + vec.retain(|&x| x == 0); + vec.retain(|&x| x == 0); + + // Do lint + vec.retain(|x| *x == 0); + vec.retain(|x| *x == 0); + vec.retain(|x| *x == 0); +} diff --git a/src/tools/clippy/tests/ui/manual_retain.rs b/src/tools/clippy/tests/ui/manual_retain.rs index d839550f33a..cee641d9d65 100644 --- a/src/tools/clippy/tests/ui/manual_retain.rs +++ b/src/tools/clippy/tests/ui/manual_retain.rs @@ -14,6 +14,9 @@ fn main() { _msrv_153(); _msrv_126(); _msrv_118(); + + issue_10393(); + issue_12081(); } fn binary_heap_retain() { @@ -23,6 +26,11 @@ fn binary_heap_retain() { binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect(); binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect(); + // Do lint, because we use pattern matching + let mut tuples = BinaryHeap::from([(0, 1), (1, 2), (2, 3)]); + tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); + tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); + // Do not lint, because type conversion is performed binary_heap = binary_heap .into_iter() @@ -58,6 +66,9 @@ fn btree_map_retain() { .filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0)) .collect(); + // Do not lint, because the parameters are not matched in tuple pattern + btree_map = btree_map.into_iter().filter(|t| t.0 % 2 == 0).collect(); + // Do not lint. btree_map = btree_map .into_iter() @@ -79,6 +90,11 @@ fn btree_set_retain() { btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); + // Do lint, because we use pattern matching + let mut tuples = BTreeSet::from([(0, 1), (1, 2), (2, 3)]); + tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); + tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); + // Do not lint, because type conversion is performed btree_set = btree_set .iter() @@ -114,6 +130,9 @@ fn hash_map_retain() { .filter(|(k, v)| (k % 2 == 0) && (v % 2 == 0)) .collect(); + // Do not lint, because the parameters are not matched in tuple pattern + hash_map = hash_map.into_iter().filter(|t| t.0 % 2 == 0).collect(); + // Do not lint. hash_map = hash_map .into_iter() @@ -134,6 +153,11 @@ fn hash_set_retain() { hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); + // Do lint, because we use pattern matching + let mut tuples = HashSet::from([(0, 1), (1, 2), (2, 3)]); + tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); + tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); + // Do not lint, because type conversion is performed hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect::<HashSet<i8>>(); hash_set = hash_set @@ -177,6 +201,11 @@ fn vec_retain() { vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect(); vec = vec.into_iter().filter(|x| x % 2 == 0).collect(); + // Do lint, because we use pattern matching + let mut tuples = vec![(0, 1), (1, 2), (2, 3)]; + tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); + tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); + // Do not lint, because type conversion is performed vec = vec.into_iter().filter(|x| x % 2 == 0).collect::<Vec<i8>>(); vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect::<Vec<i8>>(); @@ -252,3 +281,37 @@ fn _msrv_118() { let mut hash_map: HashMap<i8, i8> = (0..8).map(|x| (x, x * 10)).collect(); hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); } + +fn issue_10393() { + // Do lint + let mut vec = vec![(0, 1), (1, 2), (2, 3)]; + vec = vec.into_iter().filter(|(x, y)| *x == 0).collect(); + + // Do lint + let mut tuples = vec![(true, -2), (false, 3)]; + tuples = tuples.into_iter().filter(|(_, n)| *n > 0).collect(); +} + +fn issue_11457() { + // Do not lint, as we need to modify the closure + let mut vals = vec![1, 2, 3, 4]; + vals = vals.iter().filter(|v| **v != 1).cloned().collect(); + + // Do not lint, as we need to modify the closure + let mut s = String::from("foobar"); + s = s.chars().filter(|c| *c != 'o').to_owned().collect(); +} + +fn issue_12081() { + let mut vec = vec![0, 1, 2]; + + // Do lint + vec = vec.iter().filter(|&&x| x == 0).copied().collect(); + vec = vec.iter().filter(|&&x| x == 0).cloned().collect(); + vec = vec.into_iter().filter(|&x| x == 0).collect(); + + // Do lint + vec = vec.iter().filter(|&x| *x == 0).copied().collect(); + vec = vec.iter().filter(|&x| *x == 0).cloned().collect(); + vec = vec.into_iter().filter(|x| *x == 0).collect(); +} diff --git a/src/tools/clippy/tests/ui/manual_retain.stderr b/src/tools/clippy/tests/ui/manual_retain.stderr index 0c5b1383b6a..2c872f3b430 100644 --- a/src/tools/clippy/tests/ui/manual_retain.stderr +++ b/src/tools/clippy/tests/ui/manual_retain.stderr @@ -1,5 +1,5 @@ error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:22:5 + --> $DIR/manual_retain.rs:25:5 | LL | binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` @@ -8,31 +8,43 @@ LL | binary_heap = binary_heap.into_iter().filter(|x| x % 2 == 0).collect(); = help: to override `-D warnings` add `#[allow(clippy::manual_retain)]` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:23:5 + --> $DIR/manual_retain.rs:26:5 | LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:24:5 + --> $DIR/manual_retain.rs:27:5 | LL | binary_heap = binary_heap.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `binary_heap.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:54:5 + --> $DIR/manual_retain.rs:31:5 + | +LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:32:5 + | +LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:62:5 | LL | btree_map = btree_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|k, _| k % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:55:5 + --> $DIR/manual_retain.rs:63:5 | LL | btree_map = btree_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_map.retain(|_, &mut v| v % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:56:5 + --> $DIR/manual_retain.rs:64:5 | LL | / btree_map = btree_map LL | | .into_iter() @@ -41,37 +53,49 @@ LL | | .collect(); | |__________________^ help: consider calling `.retain()` instead: `btree_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:78:5 + --> $DIR/manual_retain.rs:89:5 | LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:79:5 + --> $DIR/manual_retain.rs:90:5 | LL | btree_set = btree_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:80:5 + --> $DIR/manual_retain.rs:91:5 | LL | btree_set = btree_set.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `btree_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:110:5 + --> $DIR/manual_retain.rs:95:5 + | +LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:96:5 + | +LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:126:5 | LL | hash_map = hash_map.into_iter().filter(|(k, _)| k % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|k, _| k % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:111:5 + --> $DIR/manual_retain.rs:127:5 | LL | hash_map = hash_map.into_iter().filter(|(_, v)| v % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_map.retain(|_, &mut v| v % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:112:5 + --> $DIR/manual_retain.rs:128:5 | LL | / hash_map = hash_map LL | | .into_iter() @@ -80,64 +104,136 @@ LL | | .collect(); | |__________________^ help: consider calling `.retain()` instead: `hash_map.retain(|k, &mut v| (k % 2 == 0) && (v % 2 == 0))` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:133:5 + --> $DIR/manual_retain.rs:152:5 | LL | hash_set = hash_set.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:134:5 + --> $DIR/manual_retain.rs:153:5 | LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:135:5 + --> $DIR/manual_retain.rs:154:5 | LL | hash_set = hash_set.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `hash_set.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:164:5 + --> $DIR/manual_retain.rs:158:5 + | +LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:159:5 + | +LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:188:5 | LL | s = s.chars().filter(|&c| c != 'o').to_owned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `s.retain(|c| c != 'o')` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:176:5 + --> $DIR/manual_retain.rs:200:5 | LL | vec = vec.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:177:5 + --> $DIR/manual_retain.rs:201:5 | LL | vec = vec.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:178:5 + --> $DIR/manual_retain.rs:202:5 | LL | vec = vec.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:200:5 + --> $DIR/manual_retain.rs:206:5 + | +LL | tuples = tuples.iter().filter(|(ref x, ref y)| *x == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(ref x, ref y)| *x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:207:5 + | +LL | tuples = tuples.iter().filter(|(x, y)| *x == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(x, y)| *x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:229:5 | LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).copied().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:201:5 + --> $DIR/manual_retain.rs:230:5 | LL | vec_deque = vec_deque.iter().filter(|&x| x % 2 == 0).cloned().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` error: this expression can be written more simply using `.retain()` - --> $DIR/manual_retain.rs:202:5 + --> $DIR/manual_retain.rs:231:5 | LL | vec_deque = vec_deque.into_iter().filter(|x| x % 2 == 0).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec_deque.retain(|x| x % 2 == 0)` -error: aborting due to 22 previous errors +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:288:5 + | +LL | vec = vec.into_iter().filter(|(x, y)| *x == 0).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|(x, y)| *x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:292:5 + | +LL | tuples = tuples.into_iter().filter(|(_, n)| *n > 0).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `tuples.retain(|(_, n)| *n > 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:309:5 + | +LL | vec = vec.iter().filter(|&&x| x == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:310:5 + | +LL | vec = vec.iter().filter(|&&x| x == 0).cloned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:311:5 + | +LL | vec = vec.into_iter().filter(|&x| x == 0).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|&x| x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:314:5 + | +LL | vec = vec.iter().filter(|&x| *x == 0).copied().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:315:5 + | +LL | vec = vec.iter().filter(|&x| *x == 0).cloned().collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` + +error: this expression can be written more simply using `.retain()` + --> $DIR/manual_retain.rs:316:5 + | +LL | vec = vec.into_iter().filter(|x| *x == 0).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling `.retain()` instead: `vec.retain(|x| *x == 0)` + +error: aborting due to 38 previous errors diff --git a/src/tools/clippy/tests/ui/modulo_arithmetic_integral.rs b/src/tools/clippy/tests/ui/modulo_arithmetic_integral.rs index 4dbed24026c..c427b8580e1 100644 --- a/src/tools/clippy/tests/ui/modulo_arithmetic_integral.rs +++ b/src/tools/clippy/tests/ui/modulo_arithmetic_integral.rs @@ -114,4 +114,12 @@ fn main() { a_usize % b_usize; let mut a_usize: usize = 1; a_usize %= 2; + + // No lint when comparing to zero + let a = -1; + let mut b = 2; + let c = a % b == 0; + let c = 0 == a % b; + let c = a % b != 0; + let c = 0 != a % b; } diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed index ff1e2dc8875..23e8bf8a468 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.fixed +++ b/src/tools/clippy/tests/ui/needless_borrow.fixed @@ -131,6 +131,9 @@ fn main() { 0 } } + + // issue #11786 + let x: (&str,) = ("",); } #[allow(clippy::needless_borrowed_reference)] diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs index 597021539ac..27771a8f15b 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.rs +++ b/src/tools/clippy/tests/ui/needless_borrow.rs @@ -131,6 +131,9 @@ fn main() { 0 } } + + // issue #11786 + let x: (&str,) = (&"",); } #[allow(clippy::needless_borrowed_reference)] diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr index 44552ee6abe..a21ed8382c1 100644 --- a/src/tools/clippy/tests/ui/needless_borrow.stderr +++ b/src/tools/clippy/tests/ui/needless_borrow.stderr @@ -121,41 +121,47 @@ error: this expression creates a reference which is immediately dereferenced by LL | (&&5).foo(); | ^^^^^ help: change this to: `(&5)` +error: this expression creates a reference which is immediately dereferenced by the compiler + --> $DIR/needless_borrow.rs:136:23 + | +LL | let x: (&str,) = (&"",); + | ^^^ help: change this to: `""` + error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:175:13 + --> $DIR/needless_borrow.rs:178:13 | LL | (&self.f)() | ^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:184:13 + --> $DIR/needless_borrow.rs:187:13 | LL | (&mut self.f)() | ^^^^^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:221:22 + --> $DIR/needless_borrow.rs:224:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:228:22 + --> $DIR/needless_borrow.rs:231:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:232:22 + --> $DIR/needless_borrow.rs:235:22 | LL | let _ = &mut (&mut x.u).x; | ^^^^^^^^^^ help: change this to: `x.u` error: this expression borrows a value the compiler would automatically borrow - --> $DIR/needless_borrow.rs:233:22 + --> $DIR/needless_borrow.rs:236:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` -error: aborting due to 26 previous errors +error: aborting due to 27 previous errors diff --git a/src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed b/src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed index 0147c73a94b..9b7da852663 100644 --- a/src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed +++ b/src/tools/clippy/tests/ui/needless_return_with_question_mark.fixed @@ -77,3 +77,53 @@ fn issue11616() -> Result<(), ()> { }; Ok(()) } + +fn issue11982() { + mod bar { + pub struct Error; + pub fn foo(_: bool) -> Result<(), Error> { + Ok(()) + } + } + + pub struct Error; + + impl From<bar::Error> for Error { + fn from(_: bar::Error) -> Self { + Error + } + } + + fn foo(ok: bool) -> Result<(), Error> { + if !ok { + return bar::foo(ok).map(|_| Ok::<(), Error>(()))?; + }; + Ok(()) + } +} + +fn issue11982_no_conversion() { + mod bar { + pub struct Error; + pub fn foo(_: bool) -> Result<(), Error> { + Ok(()) + } + } + + fn foo(ok: bool) -> Result<(), bar::Error> { + if !ok { + return bar::foo(ok).map(|_| Ok::<(), bar::Error>(()))?; + }; + Ok(()) + } +} + +fn general_return() { + fn foo(ok: bool) -> Result<(), ()> { + let bar = Result::Ok(Result::<(), ()>::Ok(())); + if !ok { + return bar?; + }; + Ok(()) + } +} diff --git a/src/tools/clippy/tests/ui/needless_return_with_question_mark.rs b/src/tools/clippy/tests/ui/needless_return_with_question_mark.rs index 66e1f438f8c..68e76d2b640 100644 --- a/src/tools/clippy/tests/ui/needless_return_with_question_mark.rs +++ b/src/tools/clippy/tests/ui/needless_return_with_question_mark.rs @@ -77,3 +77,53 @@ fn issue11616() -> Result<(), ()> { }; Ok(()) } + +fn issue11982() { + mod bar { + pub struct Error; + pub fn foo(_: bool) -> Result<(), Error> { + Ok(()) + } + } + + pub struct Error; + + impl From<bar::Error> for Error { + fn from(_: bar::Error) -> Self { + Error + } + } + + fn foo(ok: bool) -> Result<(), Error> { + if !ok { + return bar::foo(ok).map(|_| Ok::<(), Error>(()))?; + }; + Ok(()) + } +} + +fn issue11982_no_conversion() { + mod bar { + pub struct Error; + pub fn foo(_: bool) -> Result<(), Error> { + Ok(()) + } + } + + fn foo(ok: bool) -> Result<(), bar::Error> { + if !ok { + return bar::foo(ok).map(|_| Ok::<(), bar::Error>(()))?; + }; + Ok(()) + } +} + +fn general_return() { + fn foo(ok: bool) -> Result<(), ()> { + let bar = Result::Ok(Result::<(), ()>::Ok(())); + if !ok { + return bar?; + }; + Ok(()) + } +} diff --git a/src/tools/clippy/tests/ui/never_loop.rs b/src/tools/clippy/tests/ui/never_loop.rs index c67a6d4494e..92f173d9db4 100644 --- a/src/tools/clippy/tests/ui/never_loop.rs +++ b/src/tools/clippy/tests/ui/never_loop.rs @@ -1,4 +1,4 @@ -#![feature(inline_const)] +#![feature(inline_const, try_blocks)] #![allow( clippy::eq_op, clippy::single_match, @@ -400,6 +400,15 @@ pub fn test32() { } } +pub fn issue12205() -> Option<()> { + loop { + let _: Option<_> = try { + None?; + return Some(()); + }; + } +} + fn main() { test1(); test2(); diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs index 4d48ef14d31..f7c3df7066f 100644 --- a/src/tools/clippy/tests/ui/nonminimal_bool.rs +++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs @@ -145,3 +145,14 @@ fn issue10836() { // Should not lint let _: bool = !!Foo(true); } + +fn issue11932() { + let x: i32 = unimplemented!(); + + #[allow(clippy::nonminimal_bool)] + let _ = x % 2 == 0 || { + // Should not lint + assert!(x > 0); + x % 3 == 0 + }; +} diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed index f272d8359a3..ce5c7f2600b 100644 --- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed +++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.fixed @@ -102,3 +102,12 @@ mod issue11707 { fn avoid_double_parens() { std::convert::identity(13_i32 + 36_i32).leading_zeros(); } + +fn fp_11274() { + macro_rules! m { + ($closure:expr) => { + $closure(1) + }; + } + m!(|x| println!("{x}")); +} diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs index f45db8c9cff..ac09390e6ea 100644 --- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs +++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.rs @@ -102,3 +102,12 @@ mod issue11707 { fn avoid_double_parens() { std::convert::identity((|| 13_i32 + 36_i32)()).leading_zeros(); } + +fn fp_11274() { + macro_rules! m { + ($closure:expr) => { + $closure(1) + }; + } + m!(|x| println!("{x}")); +} diff --git a/src/tools/clippy/tests/ui/redundant_locals.rs b/src/tools/clippy/tests/ui/redundant_locals.rs index 182d067a5e9..f6909828aa9 100644 --- a/src/tools/clippy/tests/ui/redundant_locals.rs +++ b/src/tools/clippy/tests/ui/redundant_locals.rs @@ -1,6 +1,7 @@ //@aux-build:proc_macros.rs #![allow(unused, clippy::no_effect, clippy::needless_pass_by_ref_mut)] #![warn(clippy::redundant_locals)] +#![feature(async_closure, coroutines)] extern crate proc_macros; use proc_macros::{external, with_span}; @@ -163,3 +164,48 @@ fn drop_compose() { let b = ComposeDrop { d: WithDrop(1) }; let a = a; } + +fn issue12225() { + fn assert_static<T: 'static>(_: T) {} + + let v1 = String::new(); + let v2 = String::new(); + let v3 = String::new(); + let v4 = String::new(); + let v5 = String::new(); + let v6 = String::new(); + + assert_static(|| { + let v1 = v1; + dbg!(&v1); + }); + assert_static(async { + let v2 = v2; + dbg!(&v2); + }); + assert_static(|| async { + let v3 = v3; + dbg!(&v3); + }); + assert_static(async || { + let v4 = v4; + dbg!(&v4); + }); + assert_static(static || { + let v5 = v5; + yield; + }); + assert_static(|| { + let v6 = v6; + yield; + }); + + fn foo(a: &str, b: &str) {} + + let do_not_move = String::new(); + let things_to_move = vec!["a".to_string(), "b".to_string()]; + let futures = things_to_move.into_iter().map(|move_me| async { + let move_me = move_me; + foo(&do_not_move, &move_me) + }); +} diff --git a/src/tools/clippy/tests/ui/redundant_locals.stderr b/src/tools/clippy/tests/ui/redundant_locals.stderr index 30ab4aa2ea9..610d587ddad 100644 --- a/src/tools/clippy/tests/ui/redundant_locals.stderr +++ b/src/tools/clippy/tests/ui/redundant_locals.stderr @@ -1,11 +1,11 @@ error: redundant redefinition of a binding `x` - --> $DIR/redundant_locals.rs:12:5 + --> $DIR/redundant_locals.rs:13:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> $DIR/redundant_locals.rs:11:9 + --> $DIR/redundant_locals.rs:12:9 | LL | let x = 1; | ^ @@ -13,157 +13,157 @@ LL | let x = 1; = help: to override `-D warnings` add `#[allow(clippy::redundant_locals)]` error: redundant redefinition of a binding `x` - --> $DIR/redundant_locals.rs:17:5 + --> $DIR/redundant_locals.rs:18:5 | LL | let mut x = x; | ^^^^^^^^^^^^^^ | help: `x` is initially defined here - --> $DIR/redundant_locals.rs:16:9 + --> $DIR/redundant_locals.rs:17:9 | LL | let mut x = 1; | ^^^^^ error: redundant redefinition of a binding `x` - --> $DIR/redundant_locals.rs:47:5 + --> $DIR/redundant_locals.rs:48:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> $DIR/redundant_locals.rs:46:14 + --> $DIR/redundant_locals.rs:47:14 | LL | fn parameter(x: i32) { | ^ error: redundant redefinition of a binding `x` - --> $DIR/redundant_locals.rs:52:5 + --> $DIR/redundant_locals.rs:53:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> $DIR/redundant_locals.rs:51:9 + --> $DIR/redundant_locals.rs:52:9 | LL | let x = 1; | ^ error: redundant redefinition of a binding `x` - --> $DIR/redundant_locals.rs:53:5 + --> $DIR/redundant_locals.rs:54:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> $DIR/redundant_locals.rs:52:9 + --> $DIR/redundant_locals.rs:53:9 | LL | let x = x; | ^ error: redundant redefinition of a binding `x` - --> $DIR/redundant_locals.rs:54:5 + --> $DIR/redundant_locals.rs:55:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> $DIR/redundant_locals.rs:53:9 + --> $DIR/redundant_locals.rs:54:9 | LL | let x = x; | ^ error: redundant redefinition of a binding `x` - --> $DIR/redundant_locals.rs:55:5 + --> $DIR/redundant_locals.rs:56:5 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> $DIR/redundant_locals.rs:54:9 + --> $DIR/redundant_locals.rs:55:9 | LL | let x = x; | ^ error: redundant redefinition of a binding `a` - --> $DIR/redundant_locals.rs:61:5 + --> $DIR/redundant_locals.rs:62:5 | LL | let a = a; | ^^^^^^^^^^ | help: `a` is initially defined here - --> $DIR/redundant_locals.rs:59:9 + --> $DIR/redundant_locals.rs:60:9 | LL | let a = 1; | ^ error: redundant redefinition of a binding `b` - --> $DIR/redundant_locals.rs:62:5 + --> $DIR/redundant_locals.rs:63:5 | LL | let b = b; | ^^^^^^^^^^ | help: `b` is initially defined here - --> $DIR/redundant_locals.rs:60:9 + --> $DIR/redundant_locals.rs:61:9 | LL | let b = 2; | ^ error: redundant redefinition of a binding `x` - --> $DIR/redundant_locals.rs:68:9 + --> $DIR/redundant_locals.rs:69:9 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> $DIR/redundant_locals.rs:67:13 + --> $DIR/redundant_locals.rs:68:13 | LL | let x = 1; | ^ error: redundant redefinition of a binding `x` - --> $DIR/redundant_locals.rs:75:9 + --> $DIR/redundant_locals.rs:76:9 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> $DIR/redundant_locals.rs:74:13 + --> $DIR/redundant_locals.rs:75:13 | LL | let x = 1; | ^ error: redundant redefinition of a binding `x` - --> $DIR/redundant_locals.rs:78:9 + --> $DIR/redundant_locals.rs:79:9 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> $DIR/redundant_locals.rs:77:6 + --> $DIR/redundant_locals.rs:78:6 | LL | |x: i32| { | ^ error: redundant redefinition of a binding `x` - --> $DIR/redundant_locals.rs:97:9 + --> $DIR/redundant_locals.rs:98:9 | LL | let x = x; | ^^^^^^^^^^ | help: `x` is initially defined here - --> $DIR/redundant_locals.rs:94:9 + --> $DIR/redundant_locals.rs:95:9 | LL | let x = 1; | ^ error: redundant redefinition of a binding `a` - --> $DIR/redundant_locals.rs:152:5 + --> $DIR/redundant_locals.rs:153:5 | LL | let a = a; | ^^^^^^^^^^ | help: `a` is initially defined here - --> $DIR/redundant_locals.rs:150:9 + --> $DIR/redundant_locals.rs:151:9 | LL | let a = WithoutDrop(1); | ^ diff --git a/src/tools/clippy/tests/ui/redundant_type_annotations.rs b/src/tools/clippy/tests/ui/redundant_type_annotations.rs index acf53fea2bb..dc9b073ffba 100644 --- a/src/tools/clippy/tests/ui/redundant_type_annotations.rs +++ b/src/tools/clippy/tests/ui/redundant_type_annotations.rs @@ -196,13 +196,18 @@ fn test_simple_types() { let _var: &str = "test"; //~^ ERROR: redundant type annotation - let _var: &[u8] = b"test"; + let _var: &[u8; 4] = b"test"; //~^ ERROR: redundant type annotation let _var: bool = false; //~^ ERROR: redundant type annotation } +fn issue12212() { + // This should not be linted + let _var: &[u8] = b"test"; +} + fn issue11190() {} fn main() {} diff --git a/src/tools/clippy/tests/ui/redundant_type_annotations.stderr b/src/tools/clippy/tests/ui/redundant_type_annotations.stderr index d1f26f1832e..48df465ad49 100644 --- a/src/tools/clippy/tests/ui/redundant_type_annotations.stderr +++ b/src/tools/clippy/tests/ui/redundant_type_annotations.stderr @@ -94,8 +94,8 @@ LL | let _var: &str = "test"; error: redundant type annotation --> $DIR/redundant_type_annotations.rs:199:5 | -LL | let _var: &[u8] = b"test"; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _var: &[u8; 4] = b"test"; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant type annotation --> $DIR/redundant_type_annotations.rs:202:5 diff --git a/src/tools/clippy/tests/ui/ref_as_ptr.fixed b/src/tools/clippy/tests/ui/ref_as_ptr.fixed new file mode 100644 index 00000000000..7a946393f25 --- /dev/null +++ b/src/tools/clippy/tests/ui/ref_as_ptr.fixed @@ -0,0 +1,110 @@ +#![warn(clippy::ref_as_ptr)] +#![allow(clippy::unnecessary_mut_passed)] + +fn main() { + let _ = std::ptr::from_ref(&1u8); + let _ = std::ptr::from_ref::<u32>(&2u32); + let _ = std::ptr::from_ref::<f64>(&3.0f64); + + let _ = std::ptr::from_ref(&4) as *const f32; + let _ = std::ptr::from_ref::<f32>(&5.0f32) as *const u32; + + let _ = std::ptr::from_ref(&mut 6u8); + let _ = std::ptr::from_ref::<u32>(&mut 7u32); + let _ = std::ptr::from_ref::<f64>(&mut 8.0f64); + + let _ = std::ptr::from_ref(&mut 9) as *const f32; + let _ = std::ptr::from_ref::<f32>(&mut 10.0f32) as *const u32; + + let _ = std::ptr::from_mut(&mut 11u8); + let _ = std::ptr::from_mut::<u32>(&mut 12u32); + let _ = std::ptr::from_mut::<f64>(&mut 13.0f64); + + let _ = std::ptr::from_mut(&mut 14) as *const f32; + let _ = std::ptr::from_mut::<f32>(&mut 15.0f32) as *const u32; + + let _ = std::ptr::from_ref(&1u8); + let _ = std::ptr::from_ref::<u32>(&2u32); + let _ = std::ptr::from_ref::<f64>(&3.0f64); + + let _ = std::ptr::from_ref(&4) as *const f32; + let _ = std::ptr::from_ref::<f32>(&5.0f32) as *const u32; + + let val = 1; + let _ = std::ptr::from_ref(&val); + let _ = std::ptr::from_ref::<i32>(&val); + + let _ = std::ptr::from_ref(&val) as *const f32; + let _ = std::ptr::from_ref::<i32>(&val) as *const f64; + + let mut val: u8 = 2; + let _ = std::ptr::from_mut::<u8>(&mut val); + let _ = std::ptr::from_mut(&mut val); + + let _ = std::ptr::from_ref::<u8>(&mut val); + let _ = std::ptr::from_ref(&mut val); + + let _ = std::ptr::from_ref::<u8>(&mut val) as *const f64; + let _: *const Option<u8> = std::ptr::from_ref(&mut val) as *const _; + + let _ = std::ptr::from_ref::<[usize; 7]>(&std::array::from_fn(|i| i * i)); + let _ = std::ptr::from_ref::<[usize; 8]>(&mut std::array::from_fn(|i| i * i)); + let _ = std::ptr::from_mut::<[usize; 9]>(&mut std::array::from_fn(|i| i * i)); +} + +#[clippy::msrv = "1.75"] +fn _msrv_1_75() { + let val = &42_i32; + let mut_val = &mut 42_i32; + + // `std::ptr::from_{ref, mut}` was stabilized in 1.76. Do not lint this + let _ = val as *const i32; + let _ = mut_val as *mut i32; +} + +#[clippy::msrv = "1.76"] +fn _msrv_1_76() { + let val = &42_i32; + let mut_val = &mut 42_i32; + + let _ = std::ptr::from_ref::<i32>(val); + let _ = std::ptr::from_mut::<i32>(mut_val); +} + +fn foo(val: &[u8]) { + let _ = std::ptr::from_ref(val); + let _ = std::ptr::from_ref::<[u8]>(val); +} + +fn bar(val: &mut str) { + let _ = std::ptr::from_mut(val); + let _ = std::ptr::from_mut::<str>(val); +} + +struct X<'a>(&'a i32); + +impl<'a> X<'a> { + fn foo(&self) -> *const i64 { + std::ptr::from_ref(self.0) as *const _ + } + + fn bar(&mut self) -> *const i64 { + std::ptr::from_ref(self.0) as *const _ + } +} + +struct Y<'a>(&'a mut i32); + +impl<'a> Y<'a> { + fn foo(&self) -> *const i64 { + std::ptr::from_ref(self.0) as *const _ + } + + fn bar(&mut self) -> *const i64 { + std::ptr::from_ref(self.0) as *const _ + } + + fn baz(&mut self) -> *const i64 { + std::ptr::from_mut(self.0) as *mut _ + } +} diff --git a/src/tools/clippy/tests/ui/ref_as_ptr.rs b/src/tools/clippy/tests/ui/ref_as_ptr.rs new file mode 100644 index 00000000000..6f745505b46 --- /dev/null +++ b/src/tools/clippy/tests/ui/ref_as_ptr.rs @@ -0,0 +1,110 @@ +#![warn(clippy::ref_as_ptr)] +#![allow(clippy::unnecessary_mut_passed)] + +fn main() { + let _ = &1u8 as *const _; + let _ = &2u32 as *const u32; + let _ = &3.0f64 as *const f64; + + let _ = &4 as *const _ as *const f32; + let _ = &5.0f32 as *const f32 as *const u32; + + let _ = &mut 6u8 as *const _; + let _ = &mut 7u32 as *const u32; + let _ = &mut 8.0f64 as *const f64; + + let _ = &mut 9 as *const _ as *const f32; + let _ = &mut 10.0f32 as *const f32 as *const u32; + + let _ = &mut 11u8 as *mut _; + let _ = &mut 12u32 as *mut u32; + let _ = &mut 13.0f64 as *mut f64; + + let _ = &mut 14 as *mut _ as *const f32; + let _ = &mut 15.0f32 as *mut f32 as *const u32; + + let _ = &1u8 as *const _; + let _ = &2u32 as *const u32; + let _ = &3.0f64 as *const f64; + + let _ = &4 as *const _ as *const f32; + let _ = &5.0f32 as *const f32 as *const u32; + + let val = 1; + let _ = &val as *const _; + let _ = &val as *const i32; + + let _ = &val as *const _ as *const f32; + let _ = &val as *const i32 as *const f64; + + let mut val: u8 = 2; + let _ = &mut val as *mut u8; + let _ = &mut val as *mut _; + + let _ = &mut val as *const u8; + let _ = &mut val as *const _; + + let _ = &mut val as *const u8 as *const f64; + let _: *const Option<u8> = &mut val as *const _ as *const _; + + let _ = &std::array::from_fn(|i| i * i) as *const [usize; 7]; + let _ = &mut std::array::from_fn(|i| i * i) as *const [usize; 8]; + let _ = &mut std::array::from_fn(|i| i * i) as *mut [usize; 9]; +} + +#[clippy::msrv = "1.75"] +fn _msrv_1_75() { + let val = &42_i32; + let mut_val = &mut 42_i32; + + // `std::ptr::from_{ref, mut}` was stabilized in 1.76. Do not lint this + let _ = val as *const i32; + let _ = mut_val as *mut i32; +} + +#[clippy::msrv = "1.76"] +fn _msrv_1_76() { + let val = &42_i32; + let mut_val = &mut 42_i32; + + let _ = val as *const i32; + let _ = mut_val as *mut i32; +} + +fn foo(val: &[u8]) { + let _ = val as *const _; + let _ = val as *const [u8]; +} + +fn bar(val: &mut str) { + let _ = val as *mut _; + let _ = val as *mut str; +} + +struct X<'a>(&'a i32); + +impl<'a> X<'a> { + fn foo(&self) -> *const i64 { + self.0 as *const _ as *const _ + } + + fn bar(&mut self) -> *const i64 { + self.0 as *const _ as *const _ + } +} + +struct Y<'a>(&'a mut i32); + +impl<'a> Y<'a> { + fn foo(&self) -> *const i64 { + self.0 as *const _ as *const _ + } + + fn bar(&mut self) -> *const i64 { + self.0 as *const _ as *const _ + } + + fn baz(&mut self) -> *const i64 { + self.0 as *mut _ as *mut _ + } +} diff --git a/src/tools/clippy/tests/ui/ref_as_ptr.stderr b/src/tools/clippy/tests/ui/ref_as_ptr.stderr new file mode 100644 index 00000000000..371d42df528 --- /dev/null +++ b/src/tools/clippy/tests/ui/ref_as_ptr.stderr @@ -0,0 +1,269 @@ +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:5:13 + | +LL | let _ = &1u8 as *const _; + | ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&1u8)` + | + = note: `-D clippy::ref-as-ptr` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::ref_as_ptr)]` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:6:13 + | +LL | let _ = &2u32 as *const u32; + | ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<u32>(&2u32)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:7:13 + | +LL | let _ = &3.0f64 as *const f64; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<f64>(&3.0f64)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:9:13 + | +LL | let _ = &4 as *const _ as *const f32; + | ^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&4)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:10:13 + | +LL | let _ = &5.0f32 as *const f32 as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<f32>(&5.0f32)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:12:13 + | +LL | let _ = &mut 6u8 as *const _; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&mut 6u8)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:13:13 + | +LL | let _ = &mut 7u32 as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<u32>(&mut 7u32)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:14:13 + | +LL | let _ = &mut 8.0f64 as *const f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<f64>(&mut 8.0f64)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:16:13 + | +LL | let _ = &mut 9 as *const _ as *const f32; + | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&mut 9)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:17:13 + | +LL | let _ = &mut 10.0f32 as *const f32 as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<f32>(&mut 10.0f32)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:19:13 + | +LL | let _ = &mut 11u8 as *mut _; + | ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(&mut 11u8)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:20:13 + | +LL | let _ = &mut 12u32 as *mut u32; + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<u32>(&mut 12u32)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:21:13 + | +LL | let _ = &mut 13.0f64 as *mut f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<f64>(&mut 13.0f64)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:23:13 + | +LL | let _ = &mut 14 as *mut _ as *const f32; + | ^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(&mut 14)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:24:13 + | +LL | let _ = &mut 15.0f32 as *mut f32 as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<f32>(&mut 15.0f32)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:26:13 + | +LL | let _ = &1u8 as *const _; + | ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&1u8)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:27:13 + | +LL | let _ = &2u32 as *const u32; + | ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<u32>(&2u32)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:28:13 + | +LL | let _ = &3.0f64 as *const f64; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<f64>(&3.0f64)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:30:13 + | +LL | let _ = &4 as *const _ as *const f32; + | ^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&4)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:31:13 + | +LL | let _ = &5.0f32 as *const f32 as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<f32>(&5.0f32)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:34:13 + | +LL | let _ = &val as *const _; + | ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:35:13 + | +LL | let _ = &val as *const i32; + | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<i32>(&val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:37:13 + | +LL | let _ = &val as *const _ as *const f32; + | ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:38:13 + | +LL | let _ = &val as *const i32 as *const f64; + | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<i32>(&val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:41:13 + | +LL | let _ = &mut val as *mut u8; + | ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<u8>(&mut val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:42:13 + | +LL | let _ = &mut val as *mut _; + | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(&mut val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:44:13 + | +LL | let _ = &mut val as *const u8; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<u8>(&mut val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:45:13 + | +LL | let _ = &mut val as *const _; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&mut val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:47:13 + | +LL | let _ = &mut val as *const u8 as *const f64; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<u8>(&mut val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:48:32 + | +LL | let _: *const Option<u8> = &mut val as *const _ as *const _; + | ^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(&mut val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:50:13 + | +LL | let _ = &std::array::from_fn(|i| i * i) as *const [usize; 7]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<[usize; 7]>(&std::array::from_fn(|i| i * i))` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:51:13 + | +LL | let _ = &mut std::array::from_fn(|i| i * i) as *const [usize; 8]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<[usize; 8]>(&mut std::array::from_fn(|i| i * i))` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:52:13 + | +LL | let _ = &mut std::array::from_fn(|i| i * i) as *mut [usize; 9]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<[usize; 9]>(&mut std::array::from_fn(|i| i * i))` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:70:13 + | +LL | let _ = val as *const i32; + | ^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<i32>(val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:71:13 + | +LL | let _ = mut_val as *mut i32; + | ^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<i32>(mut_val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:75:13 + | +LL | let _ = val as *const _; + | ^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:76:13 + | +LL | let _ = val as *const [u8]; + | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref::<[u8]>(val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:80:13 + | +LL | let _ = val as *mut _; + | ^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:81:13 + | +LL | let _ = val as *mut str; + | ^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut::<str>(val)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:88:9 + | +LL | self.0 as *const _ as *const _ + | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(self.0)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:92:9 + | +LL | self.0 as *const _ as *const _ + | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(self.0)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:100:9 + | +LL | self.0 as *const _ as *const _ + | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(self.0)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:104:9 + | +LL | self.0 as *const _ as *const _ + | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_ref(self.0)` + +error: reference as raw pointer + --> $DIR/ref_as_ptr.rs:108:9 + | +LL | self.0 as *mut _ as *mut _ + | ^^^^^^^^^^^^^^^^ help: try: `std::ptr::from_mut(self.0)` + +error: aborting due to 44 previous errors + diff --git a/src/tools/clippy/tests/ui/strlen_on_c_strings.fixed b/src/tools/clippy/tests/ui/strlen_on_c_strings.fixed index 8304e2afd8b..1e7d04ffb9d 100644 --- a/src/tools/clippy/tests/ui/strlen_on_c_strings.fixed +++ b/src/tools/clippy/tests/ui/strlen_on_c_strings.fixed @@ -1,5 +1,5 @@ #![warn(clippy::strlen_on_c_strings)] -#![allow(dead_code)] +#![allow(dead_code, clippy::manual_c_str_literals)] #![feature(rustc_private)] extern crate libc; diff --git a/src/tools/clippy/tests/ui/strlen_on_c_strings.rs b/src/tools/clippy/tests/ui/strlen_on_c_strings.rs index deba40a9ea5..c3ad03591d4 100644 --- a/src/tools/clippy/tests/ui/strlen_on_c_strings.rs +++ b/src/tools/clippy/tests/ui/strlen_on_c_strings.rs @@ -1,5 +1,5 @@ #![warn(clippy::strlen_on_c_strings)] -#![allow(dead_code)] +#![allow(dead_code, clippy::manual_c_str_literals)] #![feature(rustc_private)] extern crate libc; diff --git a/src/tools/clippy/tests/ui/to_string_trait_impl.rs b/src/tools/clippy/tests/ui/to_string_trait_impl.rs new file mode 100644 index 00000000000..b0731632d45 --- /dev/null +++ b/src/tools/clippy/tests/ui/to_string_trait_impl.rs @@ -0,0 +1,31 @@ +#![warn(clippy::to_string_trait_impl)] + +use std::fmt::{self, Display}; + +struct Point { + x: usize, + y: usize, +} + +impl ToString for Point { + fn to_string(&self) -> String { + format!("({}, {})", self.x, self.y) + } +} + +struct Foo; + +impl Display for Foo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Foo") + } +} + +struct Bar; + +impl Bar { + #[allow(clippy::inherent_to_string)] + fn to_string(&self) -> String { + String::from("Bar") + } +} diff --git a/src/tools/clippy/tests/ui/to_string_trait_impl.stderr b/src/tools/clippy/tests/ui/to_string_trait_impl.stderr new file mode 100644 index 00000000000..55fa9f12c0e --- /dev/null +++ b/src/tools/clippy/tests/ui/to_string_trait_impl.stderr @@ -0,0 +1,16 @@ +error: direct implementation of `ToString` + --> $DIR/to_string_trait_impl.rs:10:1 + | +LL | / impl ToString for Point { +LL | | fn to_string(&self) -> String { +LL | | format!("({}, {})", self.x, self.y) +LL | | } +LL | | } + | |_^ + | + = help: prefer implementing `Display` instead + = note: `-D clippy::to-string-trait-impl` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::to_string_trait_impl)]` + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui/unconditional_recursion.rs b/src/tools/clippy/tests/ui/unconditional_recursion.rs index 7b898a6e0e7..6ad3bde51cd 100644 --- a/src/tools/clippy/tests/ui/unconditional_recursion.rs +++ b/src/tools/clippy/tests/ui/unconditional_recursion.rs @@ -206,6 +206,7 @@ impl PartialEq for S8 { struct S9; +#[allow(clippy::to_string_trait_impl)] impl std::string::ToString for S9 { fn to_string(&self) -> String { //~^ ERROR: function cannot return without recursing @@ -215,6 +216,7 @@ impl std::string::ToString for S9 { struct S10; +#[allow(clippy::to_string_trait_impl)] impl std::string::ToString for S10 { fn to_string(&self) -> String { //~^ ERROR: function cannot return without recursing @@ -225,6 +227,7 @@ impl std::string::ToString for S10 { struct S11; +#[allow(clippy::to_string_trait_impl)] impl std::string::ToString for S11 { fn to_string(&self) -> String { //~^ ERROR: function cannot return without recursing @@ -288,4 +291,63 @@ impl PartialEq for S15<'_> { } } +mod issue12154 { + struct MyBox<T>(T); + + impl<T> std::ops::Deref for MyBox<T> { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } + } + + impl<T: PartialEq> PartialEq for MyBox<T> { + fn eq(&self, other: &Self) -> bool { + (**self).eq(&**other) + } + } + + // Not necessarily related to the issue but another FP from the http crate that was fixed with it: + // https://docs.rs/http/latest/src/http/header/name.rs.html#1424 + // We used to simply peel refs from the LHS and RHS, so we couldn't differentiate + // between `PartialEq<T> for &T` and `PartialEq<&T> for T` impls. + #[derive(PartialEq)] + struct HeaderName; + impl<'a> PartialEq<&'a HeaderName> for HeaderName { + fn eq(&self, other: &&'a HeaderName) -> bool { + *self == **other + } + } + + impl<'a> PartialEq<HeaderName> for &'a HeaderName { + fn eq(&self, other: &HeaderName) -> bool { + *other == *self + } + } + + // Issue #12181 but also fixed by the same PR + struct Foo; + + impl Foo { + fn as_str(&self) -> &str { + "Foo" + } + } + + impl PartialEq for Foo { + fn eq(&self, other: &Self) -> bool { + self.as_str().eq(other.as_str()) + } + } + + impl<T> PartialEq<T> for Foo + where + for<'a> &'a str: PartialEq<T>, + { + fn eq(&self, other: &T) -> bool { + (&self.as_str()).eq(other) + } + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/unconditional_recursion.stderr b/src/tools/clippy/tests/ui/unconditional_recursion.stderr index 094b80d4586..93a5eac91d8 100644 --- a/src/tools/clippy/tests/ui/unconditional_recursion.stderr +++ b/src/tools/clippy/tests/ui/unconditional_recursion.stderr @@ -23,7 +23,7 @@ LL | self.eq(other) = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> $DIR/unconditional_recursion.rs:210:5 + --> $DIR/unconditional_recursion.rs:211:5 | LL | fn to_string(&self) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -34,7 +34,7 @@ LL | self.to_string() = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> $DIR/unconditional_recursion.rs:219:5 + --> $DIR/unconditional_recursion.rs:221:5 | LL | fn to_string(&self) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -45,7 +45,7 @@ LL | x.to_string() = help: a `loop` may express intention better if this is on purpose error: function cannot return without recursing - --> $DIR/unconditional_recursion.rs:229:5 + --> $DIR/unconditional_recursion.rs:232:5 | LL | fn to_string(&self) -> String { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -326,7 +326,7 @@ LL | mine == theirs | ^^^^^^^^^^^^^^ error: function cannot return without recursing - --> $DIR/unconditional_recursion.rs:244:5 + --> $DIR/unconditional_recursion.rs:247:5 | LL | / fn new() -> Self { LL | | @@ -335,13 +335,13 @@ LL | | } | |_____^ | note: recursive call site - --> $DIR/unconditional_recursion.rs:246:9 + --> $DIR/unconditional_recursion.rs:249:9 | LL | Self::default() | ^^^^^^^^^^^^^^^ error: function cannot return without recursing - --> $DIR/unconditional_recursion.rs:283:5 + --> $DIR/unconditional_recursion.rs:286:5 | LL | / fn eq(&self, other: &Self) -> bool { LL | | @@ -352,7 +352,7 @@ LL | | } | |_____^ | note: recursive call site - --> $DIR/unconditional_recursion.rs:287:9 + --> $DIR/unconditional_recursion.rs:290:9 | LL | mine.eq(theirs) | ^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/unnecessary_fold.fixed b/src/tools/clippy/tests/ui/unnecessary_fold.fixed index c884d26eb61..c5bc11b55ab 100644 --- a/src/tools/clippy/tests/ui/unnecessary_fold.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_fold.fixed @@ -1,9 +1,15 @@ #![allow(dead_code)] +fn is_any(acc: bool, x: usize) -> bool { + acc || x > 2 +} + /// Calls which should trigger the `UNNECESSARY_FOLD` lint fn unnecessary_fold() { // Can be replaced by .any let _ = (0..3).any(|x| x > 2); + // Can be replaced by .any (checking suggestion) + let _ = (0..3).fold(false, is_any); // Can be replaced by .all let _ = (0..3).all(|x| x > 2); // Can be replaced by .sum diff --git a/src/tools/clippy/tests/ui/unnecessary_fold.rs b/src/tools/clippy/tests/ui/unnecessary_fold.rs index 2e6d6ba52eb..3a5136eeeae 100644 --- a/src/tools/clippy/tests/ui/unnecessary_fold.rs +++ b/src/tools/clippy/tests/ui/unnecessary_fold.rs @@ -1,9 +1,15 @@ #![allow(dead_code)] +fn is_any(acc: bool, x: usize) -> bool { + acc || x > 2 +} + /// Calls which should trigger the `UNNECESSARY_FOLD` lint fn unnecessary_fold() { // Can be replaced by .any let _ = (0..3).fold(false, |acc, x| acc || x > 2); + // Can be replaced by .any (checking suggestion) + let _ = (0..3).fold(false, |acc, x| is_any(acc, x)); // Can be replaced by .all let _ = (0..3).fold(true, |acc, x| acc && x > 2); // Can be replaced by .sum diff --git a/src/tools/clippy/tests/ui/unnecessary_fold.stderr b/src/tools/clippy/tests/ui/unnecessary_fold.stderr index f0d03963842..123d4a3be75 100644 --- a/src/tools/clippy/tests/ui/unnecessary_fold.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_fold.stderr @@ -1,5 +1,5 @@ error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:6:20 + --> $DIR/unnecessary_fold.rs:10:20 | LL | let _ = (0..3).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `any(|x| x > 2)` @@ -7,89 +7,98 @@ LL | let _ = (0..3).fold(false, |acc, x| acc || x > 2); = note: `-D clippy::unnecessary-fold` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_fold)]` +error: redundant closure + --> $DIR/unnecessary_fold.rs:12:32 + | +LL | let _ = (0..3).fold(false, |acc, x| is_any(acc, x)); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `is_any` + | + = note: `-D clippy::redundant-closure` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]` + error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:8:20 + --> $DIR/unnecessary_fold.rs:14:20 | LL | let _ = (0..3).fold(true, |acc, x| acc && x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `all(|x| x > 2)` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:10:25 + --> $DIR/unnecessary_fold.rs:16:25 | LL | let _: i32 = (0..3).fold(0, |acc, x| acc + x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:12:25 + --> $DIR/unnecessary_fold.rs:18:25 | LL | let _: i32 = (0..3).fold(1, |acc, x| acc * x); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:17:41 + --> $DIR/unnecessary_fold.rs:23:41 | LL | let _: bool = (0..3).map(|x| 2 * x).fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `any(|x| x > 2)` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:47:10 + --> $DIR/unnecessary_fold.rs:53:10 | LL | .fold(false, |acc, x| acc || x > 2); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `any(|x| x > 2)` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:58:33 + --> $DIR/unnecessary_fold.rs:64:33 | LL | assert_eq!(map.values().fold(0, |x, y| x + y), 0); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::<i32>()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:61:30 + --> $DIR/unnecessary_fold.rs:67:30 | LL | let _ = map.values().fold(0, |x, y| x + y); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::<i32>()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:62:30 + --> $DIR/unnecessary_fold.rs:68:30 | LL | let _ = map.values().fold(1, |x, y| x * y); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::<i32>()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:63:35 + --> $DIR/unnecessary_fold.rs:69:35 | LL | let _: i32 = map.values().fold(0, |x, y| x + y); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:64:35 + --> $DIR/unnecessary_fold.rs:70:35 | LL | let _: i32 = map.values().fold(1, |x, y| x * y); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:65:31 + --> $DIR/unnecessary_fold.rs:71:31 | LL | anything(map.values().fold(0, |x, y| x + y)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum::<i32>()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:66:31 + --> $DIR/unnecessary_fold.rs:72:31 | LL | anything(map.values().fold(1, |x, y| x * y)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product::<i32>()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:67:26 + --> $DIR/unnecessary_fold.rs:73:26 | LL | num(map.values().fold(0, |x, y| x + y)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `sum()` error: this `.fold` can be written more succinctly using another method - --> $DIR/unnecessary_fold.rs:68:26 + --> $DIR/unnecessary_fold.rs:74:26 | LL | num(map.values().fold(1, |x, y| x * y)); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `product()` -error: aborting due to 15 previous errors +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_operation.fixed b/src/tools/clippy/tests/ui/unnecessary_operation.fixed index 463412daec0..11761c6c90e 100644 --- a/src/tools/clippy/tests/ui/unnecessary_operation.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_operation.fixed @@ -106,4 +106,11 @@ fn main() { // Issue #11885 Cout << 16; + + // Issue #11575 + // Bad formatting is required to trigger the bug + #[rustfmt::skip] + 'label: { + break 'label + }; } diff --git a/src/tools/clippy/tests/ui/unnecessary_operation.rs b/src/tools/clippy/tests/ui/unnecessary_operation.rs index f0d28e28902..de0081289ac 100644 --- a/src/tools/clippy/tests/ui/unnecessary_operation.rs +++ b/src/tools/clippy/tests/ui/unnecessary_operation.rs @@ -110,4 +110,11 @@ fn main() { // Issue #11885 Cout << 16; + + // Issue #11575 + // Bad formatting is required to trigger the bug + #[rustfmt::skip] + 'label: { + break 'label + }; } diff --git a/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.fixed b/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.fixed new file mode 100644 index 00000000000..224e0b52d75 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.fixed @@ -0,0 +1,61 @@ +#![warn(clippy::unnecessary_result_map_or_else)] +#![allow(clippy::unnecessary_literal_unwrap, clippy::let_and_return, clippy::let_unit_value)] + +fn main() { + let x: Result<(), ()> = Ok(()); + x.unwrap_or_else(|err| err); //~ ERROR: unused "map closure" when calling + + // Type ascribtion. + let x: Result<(), ()> = Ok(()); + x.unwrap_or_else(|err: ()| err); //~ ERROR: unused "map closure" when calling + + // Auto-deref. + let y = String::new(); + let x: Result<&String, &String> = Ok(&y); + let y: &str = x.unwrap_or_else(|err| err); //~ ERROR: unused "map closure" when calling + + // Temporary variable. + let x: Result<(), ()> = Ok(()); + x.unwrap_or_else(|err| err); + + // Should not warn. + let x: Result<usize, usize> = Ok(0); + x.map_or_else(|err| err, |n| n + 1); + + // Should not warn. + let y = (); + let x: Result<(), ()> = Ok(()); + x.map_or_else(|err| err, |_| y); + + // Should not warn. + let y = (); + let x: Result<(), ()> = Ok(()); + x.map_or_else( + |err| err, + |_| { + let tmp = y; + tmp + }, + ); + + // Should not warn. + let x: Result<usize, usize> = Ok(1); + x.map_or_else( + |err| err, + |n| { + let tmp = n + 1; + tmp + }, + ); + + // Should not warn. + let y = 0; + let x: Result<usize, usize> = Ok(1); + x.map_or_else( + |err| err, + |n| { + let tmp = n; + y + }, + ); +} diff --git a/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.rs b/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.rs new file mode 100644 index 00000000000..4fe950a4cfa --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.rs @@ -0,0 +1,69 @@ +#![warn(clippy::unnecessary_result_map_or_else)] +#![allow(clippy::unnecessary_literal_unwrap, clippy::let_and_return, clippy::let_unit_value)] + +fn main() { + let x: Result<(), ()> = Ok(()); + x.map_or_else(|err| err, |n| n); //~ ERROR: unused "map closure" when calling + + // Type ascribtion. + let x: Result<(), ()> = Ok(()); + x.map_or_else(|err: ()| err, |n: ()| n); //~ ERROR: unused "map closure" when calling + + // Auto-deref. + let y = String::new(); + let x: Result<&String, &String> = Ok(&y); + let y: &str = x.map_or_else(|err| err, |n| n); //~ ERROR: unused "map closure" when calling + + // Temporary variable. + let x: Result<(), ()> = Ok(()); + x.map_or_else( + //~^ ERROR: unused "map closure" when calling + |err| err, + |n| { + let tmp = n; + let tmp2 = tmp; + tmp2 + }, + ); + + // Should not warn. + let x: Result<usize, usize> = Ok(0); + x.map_or_else(|err| err, |n| n + 1); + + // Should not warn. + let y = (); + let x: Result<(), ()> = Ok(()); + x.map_or_else(|err| err, |_| y); + + // Should not warn. + let y = (); + let x: Result<(), ()> = Ok(()); + x.map_or_else( + |err| err, + |_| { + let tmp = y; + tmp + }, + ); + + // Should not warn. + let x: Result<usize, usize> = Ok(1); + x.map_or_else( + |err| err, + |n| { + let tmp = n + 1; + tmp + }, + ); + + // Should not warn. + let y = 0; + let x: Result<usize, usize> = Ok(1); + x.map_or_else( + |err| err, + |n| { + let tmp = n; + y + }, + ); +} diff --git a/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.stderr b/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.stderr new file mode 100644 index 00000000000..0f83be5d556 --- /dev/null +++ b/src/tools/clippy/tests/ui/unnecessary_result_map_or_else.stderr @@ -0,0 +1,35 @@ +error: unused "map closure" when calling `Result::map_or_else` value + --> $DIR/unnecessary_result_map_or_else.rs:6:5 + | +LL | x.map_or_else(|err| err, |n| n); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err| err)` + | + = note: `-D clippy::unnecessary-result-map-or-else` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_result_map_or_else)]` + +error: unused "map closure" when calling `Result::map_or_else` value + --> $DIR/unnecessary_result_map_or_else.rs:10:5 + | +LL | x.map_or_else(|err: ()| err, |n: ()| n); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err: ()| err)` + +error: unused "map closure" when calling `Result::map_or_else` value + --> $DIR/unnecessary_result_map_or_else.rs:15:19 + | +LL | let y: &str = x.map_or_else(|err| err, |n| n); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err| err)` + +error: unused "map closure" when calling `Result::map_or_else` value + --> $DIR/unnecessary_result_map_or_else.rs:19:5 + | +LL | / x.map_or_else( +LL | | +LL | | |err| err, +LL | | |n| { +... | +LL | | }, +LL | | ); + | |_____^ help: consider using `unwrap_or_else`: `x.unwrap_or_else(|err| err)` + +error: aborting due to 4 previous errors + diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed index 2dd1d746626..7f01c981a93 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed @@ -27,6 +27,7 @@ impl AsRef<str> for X { } } +#[allow(clippy::to_string_trait_impl)] impl ToString for X { fn to_string(&self) -> String { self.0.to_string() @@ -265,6 +266,7 @@ mod issue_8507 { } } + #[allow(clippy::to_string_trait_impl)] impl ToString for Y { fn to_string(&self) -> String { self.0.to_string() @@ -338,6 +340,7 @@ mod issue_9317 { struct Bytes {} + #[allow(clippy::to_string_trait_impl)] impl ToString for Bytes { fn to_string(&self) -> String { "123".to_string() diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs index 17fad33402b..a270ed1e1c2 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs @@ -27,6 +27,7 @@ impl AsRef<str> for X { } } +#[allow(clippy::to_string_trait_impl)] impl ToString for X { fn to_string(&self) -> String { self.0.to_string() @@ -265,6 +266,7 @@ mod issue_8507 { } } + #[allow(clippy::to_string_trait_impl)] impl ToString for Y { fn to_string(&self) -> String { self.0.to_string() @@ -338,6 +340,7 @@ mod issue_9317 { struct Bytes {} + #[allow(clippy::to_string_trait_impl)] impl ToString for Bytes { fn to_string(&self) -> String { "123".to_string() diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr b/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr index ad6fa422b8c..95ff5f2ec2c 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr @@ -1,11 +1,11 @@ error: redundant clone - --> $DIR/unnecessary_to_owned.rs:154:64 + --> $DIR/unnecessary_to_owned.rs:155:64 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:154:20 + --> $DIR/unnecessary_to_owned.rs:155:20 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,55 +13,55 @@ LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()) = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]` error: redundant clone - --> $DIR/unnecessary_to_owned.rs:155:40 + --> $DIR/unnecessary_to_owned.rs:156:40 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:155:21 + --> $DIR/unnecessary_to_owned.rs:156:21 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/unnecessary_to_owned.rs:156:48 + --> $DIR/unnecessary_to_owned.rs:157:48 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:156:19 + --> $DIR/unnecessary_to_owned.rs:157:19 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/unnecessary_to_owned.rs:157:35 + --> $DIR/unnecessary_to_owned.rs:158:35 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:157:18 + --> $DIR/unnecessary_to_owned.rs:158:18 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/unnecessary_to_owned.rs:158:39 + --> $DIR/unnecessary_to_owned.rs:159:39 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/unnecessary_to_owned.rs:158:20 + --> $DIR/unnecessary_to_owned.rs:159:20 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^^^^^^^^^ error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:63:36 + --> $DIR/unnecessary_to_owned.rs:64:36 | LL | require_c_str(&Cow::from(c_str).into_owned()); | ^^^^^^^^^^^^^ help: remove this @@ -70,415 +70,415 @@ LL | require_c_str(&Cow::from(c_str).into_owned()); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_to_owned)]` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:64:19 + --> $DIR/unnecessary_to_owned.rs:65:19 | LL | require_c_str(&c_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_os_string` - --> $DIR/unnecessary_to_owned.rs:66:20 + --> $DIR/unnecessary_to_owned.rs:67:20 | LL | require_os_str(&os_str.to_os_string()); | ^^^^^^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:67:38 + --> $DIR/unnecessary_to_owned.rs:68:38 | LL | require_os_str(&Cow::from(os_str).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:68:20 + --> $DIR/unnecessary_to_owned.rs:69:20 | LL | require_os_str(&os_str.to_owned()); | ^^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_path_buf` - --> $DIR/unnecessary_to_owned.rs:70:18 + --> $DIR/unnecessary_to_owned.rs:71:18 | LL | require_path(&path.to_path_buf()); | ^^^^^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:71:34 + --> $DIR/unnecessary_to_owned.rs:72:34 | LL | require_path(&Cow::from(path).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:72:18 + --> $DIR/unnecessary_to_owned.rs:73:18 | LL | require_path(&path.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:74:17 + --> $DIR/unnecessary_to_owned.rs:75:17 | LL | require_str(&s.to_string()); | ^^^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:75:30 + --> $DIR/unnecessary_to_owned.rs:76:30 | LL | require_str(&Cow::from(s).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:76:17 + --> $DIR/unnecessary_to_owned.rs:77:17 | LL | require_str(&s.to_owned()); | ^^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:77:17 + --> $DIR/unnecessary_to_owned.rs:78:17 | LL | require_str(&x_ref.to_string()); | ^^^^^^^^^^^^^^^^^^ help: use: `x_ref.as_ref()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:79:19 + --> $DIR/unnecessary_to_owned.rs:80:19 | LL | require_slice(&slice.to_vec()); | ^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:80:36 + --> $DIR/unnecessary_to_owned.rs:81:36 | LL | require_slice(&Cow::from(slice).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:81:19 + --> $DIR/unnecessary_to_owned.rs:82:19 | LL | require_slice(&array.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `array.as_ref()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:82:19 + --> $DIR/unnecessary_to_owned.rs:83:19 | LL | require_slice(&array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref.as_ref()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:83:19 + --> $DIR/unnecessary_to_owned.rs:84:19 | LL | require_slice(&slice.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `into_owned` - --> $DIR/unnecessary_to_owned.rs:86:42 + --> $DIR/unnecessary_to_owned.rs:87:42 | LL | require_x(&Cow::<X>::Owned(x.clone()).into_owned()); | ^^^^^^^^^^^^^ help: remove this error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:89:25 + --> $DIR/unnecessary_to_owned.rs:90:25 | LL | require_deref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:90:26 + --> $DIR/unnecessary_to_owned.rs:91:26 | LL | require_deref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:91:24 + --> $DIR/unnecessary_to_owned.rs:92:24 | LL | require_deref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:92:23 + --> $DIR/unnecessary_to_owned.rs:93:23 | LL | require_deref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:93:25 + --> $DIR/unnecessary_to_owned.rs:94:25 | LL | require_deref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:95:30 + --> $DIR/unnecessary_to_owned.rs:96:30 | LL | require_impl_deref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:96:31 + --> $DIR/unnecessary_to_owned.rs:97:31 | LL | require_impl_deref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:97:29 + --> $DIR/unnecessary_to_owned.rs:98:29 | LL | require_impl_deref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:98:28 + --> $DIR/unnecessary_to_owned.rs:99:28 | LL | require_impl_deref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:99:30 + --> $DIR/unnecessary_to_owned.rs:100:30 | LL | require_impl_deref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:101:29 + --> $DIR/unnecessary_to_owned.rs:102:29 | LL | require_deref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:101:43 + --> $DIR/unnecessary_to_owned.rs:102:43 | LL | require_deref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:102:29 + --> $DIR/unnecessary_to_owned.rs:103:29 | LL | require_deref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:102:47 + --> $DIR/unnecessary_to_owned.rs:103:47 | LL | require_deref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:104:26 + --> $DIR/unnecessary_to_owned.rs:105:26 | LL | require_as_ref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:105:27 + --> $DIR/unnecessary_to_owned.rs:106:27 | LL | require_as_ref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:106:25 + --> $DIR/unnecessary_to_owned.rs:107:25 | LL | require_as_ref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:107:24 + --> $DIR/unnecessary_to_owned.rs:108:24 | LL | require_as_ref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:108:24 + --> $DIR/unnecessary_to_owned.rs:109:24 | LL | require_as_ref_str(x.to_owned()); | ^^^^^^^^^^^^ help: use: `&x` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:109:26 + --> $DIR/unnecessary_to_owned.rs:110:26 | LL | require_as_ref_slice(array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:110:26 + --> $DIR/unnecessary_to_owned.rs:111:26 | LL | require_as_ref_slice(array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:111:26 + --> $DIR/unnecessary_to_owned.rs:112:26 | LL | require_as_ref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:113:31 + --> $DIR/unnecessary_to_owned.rs:114:31 | LL | require_impl_as_ref_c_str(c_str.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `c_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:114:32 + --> $DIR/unnecessary_to_owned.rs:115:32 | LL | require_impl_as_ref_os_str(os_str.to_owned()); | ^^^^^^^^^^^^^^^^^ help: use: `os_str` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:115:30 + --> $DIR/unnecessary_to_owned.rs:116:30 | LL | require_impl_as_ref_path(path.to_owned()); | ^^^^^^^^^^^^^^^ help: use: `path` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:116:29 + --> $DIR/unnecessary_to_owned.rs:117:29 | LL | require_impl_as_ref_str(s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:117:29 + --> $DIR/unnecessary_to_owned.rs:118:29 | LL | require_impl_as_ref_str(x.to_owned()); | ^^^^^^^^^^^^ help: use: `&x` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:118:31 + --> $DIR/unnecessary_to_owned.rs:119:31 | LL | require_impl_as_ref_slice(array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:119:31 + --> $DIR/unnecessary_to_owned.rs:120:31 | LL | require_impl_as_ref_slice(array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:120:31 + --> $DIR/unnecessary_to_owned.rs:121:31 | LL | require_impl_as_ref_slice(slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:122:30 + --> $DIR/unnecessary_to_owned.rs:123:30 | LL | require_as_ref_str_slice(s.to_owned(), array.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:122:44 + --> $DIR/unnecessary_to_owned.rs:123:44 | LL | require_as_ref_str_slice(s.to_owned(), array.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:123:30 + --> $DIR/unnecessary_to_owned.rs:124:30 | LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:123:44 + --> $DIR/unnecessary_to_owned.rs:124:44 | LL | require_as_ref_str_slice(s.to_owned(), array_ref.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:124:30 + --> $DIR/unnecessary_to_owned.rs:125:30 | LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:124:44 + --> $DIR/unnecessary_to_owned.rs:125:44 | LL | require_as_ref_str_slice(s.to_owned(), slice.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:125:30 + --> $DIR/unnecessary_to_owned.rs:126:30 | LL | require_as_ref_slice_str(array.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `array` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:125:48 + --> $DIR/unnecessary_to_owned.rs:126:48 | LL | require_as_ref_slice_str(array.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:126:30 + --> $DIR/unnecessary_to_owned.rs:127:30 | LL | require_as_ref_slice_str(array_ref.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^^^^^ help: use: `array_ref` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:126:52 + --> $DIR/unnecessary_to_owned.rs:127:52 | LL | require_as_ref_slice_str(array_ref.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:127:30 + --> $DIR/unnecessary_to_owned.rs:128:30 | LL | require_as_ref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^^^^^ help: use: `slice` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:127:48 + --> $DIR/unnecessary_to_owned.rs:128:48 | LL | require_as_ref_slice_str(slice.to_owned(), s.to_owned()); | ^^^^^^^^^^^^ help: use: `s` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:129:20 + --> $DIR/unnecessary_to_owned.rs:130:20 | LL | let _ = x.join(&x_ref.to_string()); | ^^^^^^^^^^^^^^^^^^ help: use: `x_ref` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:131:13 + --> $DIR/unnecessary_to_owned.rs:132:13 | LL | let _ = slice.to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:132:13 + --> $DIR/unnecessary_to_owned.rs:133:13 | LL | let _ = slice.to_owned().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:133:13 + --> $DIR/unnecessary_to_owned.rs:134:13 | LL | let _ = [std::path::PathBuf::new()][..].to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:134:13 + --> $DIR/unnecessary_to_owned.rs:135:13 | LL | let _ = [std::path::PathBuf::new()][..].to_owned().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:136:13 + --> $DIR/unnecessary_to_owned.rs:137:13 | LL | let _ = IntoIterator::into_iter(slice.to_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:137:13 + --> $DIR/unnecessary_to_owned.rs:138:13 | LL | let _ = IntoIterator::into_iter(slice.to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:138:13 + --> $DIR/unnecessary_to_owned.rs:139:13 | LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned.rs:139:13 + --> $DIR/unnecessary_to_owned.rs:140:13 | LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:201:14 + --> $DIR/unnecessary_to_owned.rs:202:14 | LL | for t in file_types.to_vec() { | ^^^^^^^^^^^^^^^^^^^ @@ -494,31 +494,31 @@ LL + let path = match get_file_path(t) { | error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:224:14 + --> $DIR/unnecessary_to_owned.rs:225:14 | LL | let _ = &["x"][..].to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().cloned()` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:229:14 + --> $DIR/unnecessary_to_owned.rs:230:14 | LL | let _ = &["x"][..].to_vec().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().copied()` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:276:24 + --> $DIR/unnecessary_to_owned.rs:278:24 | LL | Box::new(build(y.to_string())) | ^^^^^^^^^^^^^ help: use: `y` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned.rs:384:12 + --> $DIR/unnecessary_to_owned.rs:387:12 | LL | id("abc".to_string()) | ^^^^^^^^^^^^^^^^^ help: use: `"abc"` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned.rs:527:37 + --> $DIR/unnecessary_to_owned.rs:530:37 | LL | IntoFuture::into_future(foo([].to_vec(), &0)); | ^^^^^^^^^^^ help: use: `[]` diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.fixed index f87c898f9b7..e0ba216f41b 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.fixed @@ -8,6 +8,7 @@ impl AsRef<str> for Issue12068 { } } +#[allow(clippy::to_string_trait_impl)] impl ToString for Issue12068 { fn to_string(&self) -> String { String::new() diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.rs index db5719e5880..70efc6ebba5 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.rs +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.rs @@ -8,6 +8,7 @@ impl AsRef<str> for Issue12068 { } } +#[allow(clippy::to_string_trait_impl)] impl ToString for Issue12068 { fn to_string(&self) -> String { String::new() diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.stderr b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.stderr index 4cfaeed3384..9aea15b48bf 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.stderr @@ -1,5 +1,5 @@ error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned_on_split.rs:18:13 + --> $DIR/unnecessary_to_owned_on_split.rs:19:13 | LL | let _ = "a".to_string().split('a').next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split('a')` @@ -8,49 +8,49 @@ LL | let _ = "a".to_string().split('a').next().unwrap(); = help: to override `-D warnings` add `#[allow(clippy::unnecessary_to_owned)]` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned_on_split.rs:20:13 + --> $DIR/unnecessary_to_owned_on_split.rs:21:13 | LL | let _ = "a".to_string().split("a").next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split("a")` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned_on_split.rs:22:13 + --> $DIR/unnecessary_to_owned_on_split.rs:23:13 | LL | let _ = "a".to_owned().split('a').next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split('a')` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned_on_split.rs:24:13 + --> $DIR/unnecessary_to_owned_on_split.rs:25:13 | LL | let _ = "a".to_owned().split("a").next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split("a")` error: unnecessary use of `to_string` - --> $DIR/unnecessary_to_owned_on_split.rs:26:13 + --> $DIR/unnecessary_to_owned_on_split.rs:27:13 | LL | let _ = Issue12068.to_string().split('a').next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Issue12068.as_ref().split('a')` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned_on_split.rs:29:13 + --> $DIR/unnecessary_to_owned_on_split.rs:30:13 | LL | let _ = [1].to_vec().split(|x| *x == 2).next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)` error: unnecessary use of `to_vec` - --> $DIR/unnecessary_to_owned_on_split.rs:31:13 + --> $DIR/unnecessary_to_owned_on_split.rs:32:13 | LL | let _ = [1].to_vec().split(|x| *x == 2).next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned_on_split.rs:33:13 + --> $DIR/unnecessary_to_owned_on_split.rs:34:13 | LL | let _ = [1].to_owned().split(|x| *x == 2).next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)` error: unnecessary use of `to_owned` - --> $DIR/unnecessary_to_owned_on_split.rs:35:13 + --> $DIR/unnecessary_to_owned_on_split.rs:36:13 | LL | let _ = [1].to_owned().split(|x| *x == 2).next().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)` diff --git a/src/tools/clippy/tests/ui/unused_io_amount.rs b/src/tools/clippy/tests/ui/unused_io_amount.rs index 9974600dad5..7e5a10c911b 100644 --- a/src/tools/clippy/tests/ui/unused_io_amount.rs +++ b/src/tools/clippy/tests/ui/unused_io_amount.rs @@ -229,4 +229,47 @@ fn on_return_should_not_raise<T: io::Read + io::Write>(s: &mut T) -> io::Result< s.read(&mut buf) } +pub fn unwrap_in_block(rdr: &mut dyn std::io::Read) -> std::io::Result<usize> { + let read = { rdr.read(&mut [0])? }; + Ok(read) +} + +pub fn consumed_example(rdr: &mut dyn std::io::Read) { + match rdr.read(&mut [0]) { + Ok(0) => println!("EOF"), + Ok(_) => println!("fully read"), + Err(_) => println!("fail"), + }; + match rdr.read(&mut [0]) { + Ok(0) => println!("EOF"), + Ok(_) => println!("fully read"), + Err(_) => println!("fail"), + } +} + +pub fn unreachable_or_panic(rdr: &mut dyn std::io::Read) { + { + match rdr.read(&mut [0]) { + Ok(_) => unreachable!(), + Err(_) => println!("expected"), + } + } + + { + match rdr.read(&mut [0]) { + Ok(_) => panic!(), + Err(_) => println!("expected"), + } + } +} + +pub fn wildcards(rdr: &mut dyn std::io::Read) { + { + match rdr.read(&mut [0]) { + Ok(1) => todo!(), + _ => todo!(), + } + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/unused_io_amount.stderr b/src/tools/clippy/tests/ui/unused_io_amount.stderr index 4af56d264bf..1aab56966a8 100644 --- a/src/tools/clippy/tests/ui/unused_io_amount.stderr +++ b/src/tools/clippy/tests/ui/unused_io_amount.stderr @@ -180,7 +180,7 @@ note: the result is consumed here, but the amount of I/O bytes remains unhandled --> $DIR/unused_io_amount.rs:149:9 | LL | Ok(_) => todo!(), - | ^^^^^^^^^^^^^^^^ + | ^^^^^ error: read amount is not handled --> $DIR/unused_io_amount.rs:155:11 @@ -193,7 +193,7 @@ note: the result is consumed here, but the amount of I/O bytes remains unhandled --> $DIR/unused_io_amount.rs:157:9 | LL | Ok(_) => todo!(), - | ^^^^^^^^^^^^^^^^ + | ^^^^^ error: read amount is not handled --> $DIR/unused_io_amount.rs:164:11 @@ -206,7 +206,7 @@ note: the result is consumed here, but the amount of I/O bytes remains unhandled --> $DIR/unused_io_amount.rs:166:9 | LL | Ok(_) => todo!(), - | ^^^^^^^^^^^^^^^^ + | ^^^^^ error: written amount is not handled --> $DIR/unused_io_amount.rs:173:11 @@ -219,7 +219,7 @@ note: the result is consumed here, but the amount of I/O bytes remains unhandled --> $DIR/unused_io_amount.rs:175:9 | LL | Ok(_) => todo!(), - | ^^^^^^^^^^^^^^^^ + | ^^^^^ error: read amount is not handled --> $DIR/unused_io_amount.rs:186:8 diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed index d628d2227b7..59b5c858d04 100644 --- a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed +++ b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed @@ -406,7 +406,7 @@ fn issue_8113() { fn fn_once_closure() { let mut it = 0..10; (|| { - for x in it { + for x in it.by_ref() { if x % 2 == 0 { break; } @@ -441,7 +441,19 @@ fn fn_once_closure() { break; } } - }) + }); + + trait MySpecialFnMut: FnOnce() {} + impl<T: FnOnce()> MySpecialFnMut for T {} + fn f4(_: impl MySpecialFnMut) {} + let mut it = 0..10; + f4(|| { + for x in it { + if x % 2 == 0 { + break; + } + } + }); } fn main() { diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.rs b/src/tools/clippy/tests/ui/while_let_on_iterator.rs index 525dbbaaab6..559513d5694 100644 --- a/src/tools/clippy/tests/ui/while_let_on_iterator.rs +++ b/src/tools/clippy/tests/ui/while_let_on_iterator.rs @@ -441,7 +441,19 @@ fn fn_once_closure() { break; } } - }) + }); + + trait MySpecialFnMut: FnOnce() {} + impl<T: FnOnce()> MySpecialFnMut for T {} + fn f4(_: impl MySpecialFnMut) {} + let mut it = 0..10; + f4(|| { + while let Some(x) = it.next() { + if x % 2 == 0 { + break; + } + } + }); } fn main() { diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr index cdc83b81667..7b9a9dc049a 100644 --- a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr +++ b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr @@ -131,7 +131,7 @@ error: this loop could be written as a `for` loop --> $DIR/while_let_on_iterator.rs:409:9 | LL | while let Some(x) = it.next() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()` error: this loop could be written as a `for` loop --> $DIR/while_let_on_iterator.rs:419:9 @@ -152,10 +152,16 @@ LL | while let Some(x) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:449:5 + --> $DIR/while_let_on_iterator.rs:451:9 + | +LL | while let Some(x) = it.next() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it` + +error: this loop could be written as a `for` loop + --> $DIR/while_let_on_iterator.rs:461:5 | LL | while let Some(..) = it.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it` -error: aborting due to 26 previous errors +error: aborting due to 27 previous errors diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 8be4def15de..ed1c559e1f6 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2467,6 +2467,7 @@ impl<'test> TestCx<'test> { "-Zvalidate-mir", "-Zlint-mir", "-Zdump-mir-exclude-pass-number", + "--crate-type=rlib", ]); if let Some(pass) = &self.props.mir_unit_test { rustc.args(&["-Zmir-opt-level=0", &format!("-Zmir-enable-passes=+{}", pass)]); diff --git a/src/tools/coverage-dump/src/covfun.rs b/src/tools/coverage-dump/src/covfun.rs index 3a5866dea3e..49e3a6ed583 100644 --- a/src/tools/coverage-dump/src/covfun.rs +++ b/src/tools/coverage-dump/src/covfun.rs @@ -219,7 +219,7 @@ impl CovTerm { enum MappingKind { Code(CovTerm), Gap(CovTerm), - Expansion(u32), + Expansion(#[allow(dead_code)] u32), Skip, // Using raw identifiers here makes the dump output a little bit nicer // (via the derived Debug), at the expense of making this tool's source diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index e8e10f64ad2..de7a4b79d26 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -2,7 +2,9 @@ #![allow( clippy::manual_range_contains, clippy::useless_format, - clippy::field_reassign_with_default + clippy::field_reassign_with_default, + rustc::diagnostic_outside_of_impl, + rustc::untranslatable_diagnostic, )] extern crate rustc_data_structures; diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 74ff6ed4e0a..46f96a715f1 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -383,7 +383,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // will never cause UB on the pointer itself. let (_, _, kind) = this.get_alloc_info(*alloc_id); if matches!(kind, AllocKind::LiveData) { - let alloc_extra = this.get_alloc_extra(*alloc_id).unwrap(); + let alloc_extra = this.get_alloc_extra(*alloc_id)?; // can still fail for `extern static` let alloc_borrow_tracker = &alloc_extra.borrow_tracker.as_ref().unwrap(); alloc_borrow_tracker.release_protector(&this.machine, borrow_tracker, *tag)?; } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 057b883a3bf..5a2bb84f3ef 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -10,7 +10,7 @@ #![feature(nonzero_ops)] #![feature(let_chains)] #![feature(lint_reasons)] -#![cfg_attr(not(bootstrap), feature(trait_upcasting))] +#![feature(trait_upcasting)] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, @@ -33,8 +33,10 @@ clippy::bool_to_int_with_if, clippy::box_default, clippy::needless_question_mark, + rustc::diagnostic_outside_of_impl, // We are not implementing queries here so it's fine - rustc::potential_query_instability + rustc::potential_query_instability, + rustc::untranslatable_diagnostic, )] #![warn( rust_2018_idioms, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 946887637ff..40d041c8fdb 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -2,7 +2,7 @@ //! `Machine` trait. use std::borrow::Cow; -use std::cell::{Cell, RefCell}; +use std::cell::RefCell; use std::collections::hash_map::Entry; use std::fmt; use std::path::Path; @@ -336,20 +336,11 @@ pub struct AllocExtra<'tcx> { /// if this allocation is leakable. The backtrace is not /// pruned yet; that should be done before printing it. pub backtrace: Option<Vec<FrameInfo<'tcx>>>, - /// An offset inside this allocation that was deemed aligned even for symbolic alignment checks. - /// Invariant: the promised alignment will never be less than the native alignment of this allocation. - pub symbolic_alignment: Cell<Option<(Size, Align)>>, } impl VisitProvenance for AllocExtra<'_> { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { - let AllocExtra { - borrow_tracker, - data_race, - weak_memory, - backtrace: _, - symbolic_alignment: _, - } = self; + let AllocExtra { borrow_tracker, data_race, weak_memory, backtrace: _ } = self; borrow_tracker.visit_provenance(visit); data_race.visit_provenance(visit); @@ -572,6 +563,14 @@ pub struct MiriMachine<'mir, 'tcx> { /// that is fixed per stack frame; this lets us have sometimes different results for the /// same const while ensuring consistent results within a single call. const_cache: RefCell<FxHashMap<(mir::Const<'tcx>, usize), OpTy<'tcx, Provenance>>>, + + /// For each allocation, an offset inside that allocation that was deemed aligned even for + /// symbolic alignment checks. This cannot be stored in `AllocExtra` since it needs to be + /// tracked for vtables and function allocations as well as regular allocations. + /// + /// Invariant: the promised alignment will never be less than the native alignment of the + /// allocation. + pub(crate) symbolic_alignment: RefCell<FxHashMap<AllocId, (Size, Align)>>, } impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { @@ -698,6 +697,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { collect_leak_backtraces: config.collect_leak_backtraces, allocation_spans: RefCell::new(FxHashMap::default()), const_cache: RefCell::new(FxHashMap::default()), + symbolic_alignment: RefCell::new(FxHashMap::default()), } } @@ -810,6 +810,7 @@ impl VisitProvenance for MiriMachine<'_, '_> { collect_leak_backtraces: _, allocation_spans: _, const_cache: _, + symbolic_alignment: _, } = self; threads.visit_provenance(visit); @@ -893,9 +894,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { return None; } // Let's see which alignment we have been promised for this allocation. - let alloc_info = ecx.get_alloc_extra(alloc_id).unwrap(); // cannot fail since the allocation is live - let (promised_offset, promised_align) = - alloc_info.symbolic_alignment.get().unwrap_or((Size::ZERO, alloc_align)); + let (promised_offset, promised_align) = ecx + .machine + .symbolic_alignment + .borrow() + .get(&alloc_id) + .copied() + .unwrap_or((Size::ZERO, alloc_align)); if promised_align < align { // Definitely not enough. Some(Misalignment { has: promised_align, required: align }) @@ -1132,7 +1137,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> { data_race: race_alloc, weak_memory: buffer_alloc, backtrace, - symbolic_alignment: Cell::new(None), }, |ptr| ecx.global_base_pointer(ptr), )?; diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs index ab178f82d9f..347951ce372 100644 --- a/src/tools/miri/src/provenance_gc.rs +++ b/src/tools/miri/src/provenance_gc.rs @@ -196,6 +196,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let allocs = LiveAllocs { ecx: this, collected: allocs }; this.machine.allocation_spans.borrow_mut().retain(|id, _| allocs.is_live(*id)); + this.machine.symbolic_alignment.borrow_mut().retain(|id, _| allocs.is_live(*id)); this.machine.intptrcast.borrow_mut().remove_unreachable_allocs(&allocs); if let Some(borrow_tracker) = &this.machine.borrow_tracker { borrow_tracker.borrow_mut().remove_unreachable_allocs(&allocs); diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index a002f2aad05..25654248db4 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -585,17 +585,17 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } if let Ok((alloc_id, offset, ..)) = this.ptr_try_get_alloc_id(ptr) { let (_size, alloc_align, _kind) = this.get_alloc_info(alloc_id); - // Not `get_alloc_extra_mut`, need to handle read-only allocations! - let alloc_extra = this.get_alloc_extra(alloc_id)?; // If the newly promised alignment is bigger than the native alignment of this // allocation, and bigger than the previously promised alignment, then set it. if align > alloc_align - && !alloc_extra + && !this + .machine .symbolic_alignment - .get() - .is_some_and(|(_, old_align)| align <= old_align) + .get_mut() + .get(&alloc_id) + .is_some_and(|&(_, old_align)| align <= old_align) { - alloc_extra.symbolic_alignment.set(Some((offset, align))); + this.machine.symbolic_alignment.get_mut().insert(alloc_id, (offset, align)); } } } diff --git a/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs b/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs index 0e7c3dbcc04..13f913454dc 100644 --- a/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs +++ b/src/tools/miri/tests/fail/dyn-call-trait-mismatch.rs @@ -1,4 +1,5 @@ trait T1 { + #[allow(dead_code)] fn method1(self: Box<Self>); } trait T2 { diff --git a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs index 648ac07c43e..982f33b0a31 100644 --- a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs +++ b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs @@ -2,30 +2,36 @@ #![allow(incomplete_features)] trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync { + #[allow(dead_code)] fn a(&self) -> i32 { 10 } + #[allow(dead_code)] fn z(&self) -> i32 { 11 } + #[allow(dead_code)] fn y(&self) -> i32 { 12 } } trait Bar: Foo { + #[allow(dead_code)] fn b(&self) -> i32 { 20 } + #[allow(dead_code)] fn w(&self) -> i32 { 21 } } trait Baz: Bar { + #[allow(dead_code)] fn c(&self) -> i32 { 30 } diff --git a/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.rs b/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.rs new file mode 100644 index 00000000000..44604074982 --- /dev/null +++ b/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.rs @@ -0,0 +1,12 @@ +//@compile-flags: -Zmiri-symbolic-alignment-check + +extern "C" { + static _dispatch_queue_attr_concurrent: [u8; 0]; +} + +static DISPATCH_QUEUE_CONCURRENT: &'static [u8; 0] = + unsafe { &_dispatch_queue_attr_concurrent }; + +fn main() { + let _val = *DISPATCH_QUEUE_CONCURRENT; //~ERROR: is not supported +} diff --git a/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.stderr b/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.stderr new file mode 100644 index 00000000000..a4249d2e881 --- /dev/null +++ b/src/tools/miri/tests/fail/issue-miri-3288-ice-symbolic-alignment-extern-static.stderr @@ -0,0 +1,14 @@ +error: unsupported operation: `extern` static `_dispatch_queue_attr_concurrent` from crate `issue_miri_3288_ice_symbolic_alignment_extern_static` is not supported by Miri + --> $DIR/issue-miri-3288-ice-symbolic-alignment-extern-static.rs:LL:CC + | +LL | let _val = *DISPATCH_QUEUE_CONCURRENT; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `extern` static `_dispatch_queue_attr_concurrent` from crate `issue_miri_3288_ice_symbolic_alignment_extern_static` is not supported by Miri + | + = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support + = note: BACKTRACE: + = note: inside `main` at $DIR/issue-miri-3288-ice-symbolic-alignment-extern-static.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/align_offset_symbolic.rs b/src/tools/miri/tests/pass/align_offset_symbolic.rs index 4df364bac7a..e96f11b1efa 100644 --- a/src/tools/miri/tests/pass/align_offset_symbolic.rs +++ b/src/tools/miri/tests/pass/align_offset_symbolic.rs @@ -1,6 +1,8 @@ //@compile-flags: -Zmiri-symbolic-alignment-check #![feature(strict_provenance)] +use std::mem; + fn test_align_to() { const N: usize = 4; let d = Box::new([0u32; N]); @@ -68,7 +70,7 @@ fn test_u64_array() { #[repr(align(8))] struct AlignToU64<T>(T); - const BYTE_LEN: usize = std::mem::size_of::<[u64; 4]>(); + const BYTE_LEN: usize = mem::size_of::<[u64; 4]>(); type Data = AlignToU64<[u8; BYTE_LEN]>; fn example(data: &Data) { @@ -101,10 +103,29 @@ fn huge_align() { let _ = std::ptr::invalid::<HugeSize>(SIZE).align_offset(SIZE); } +// This shows that we cannot store the promised alignment info in `AllocExtra`, +// since vtables do not have an `AllocExtra`. +fn vtable() { + #[cfg(target_pointer_width = "64")] + type TWOPTR = u128; + #[cfg(target_pointer_width = "32")] + type TWOPTR = u64; + + let ptr: &dyn Send = &0; + let parts: (*const (), *const u8) = unsafe { mem::transmute(ptr) }; + let vtable = parts.1 ; + let offset = vtable.align_offset(mem::align_of::<TWOPTR>()); + let _vtable_aligned = vtable.wrapping_add(offset) as *const [TWOPTR; 0]; + // FIXME: we can't actually do the access since vtable pointers act like zero-sized allocations. + // Enable the next line once https://github.com/rust-lang/rust/issues/117945 is implemented. + //let _place = unsafe { &*vtable_aligned }; +} + fn main() { test_align_to(); test_from_utf8(); test_u64_array(); test_cstr(); huge_align(); + vtable(); } diff --git a/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs b/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs index ccf96b99672..2491bda0917 100644 --- a/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs +++ b/src/tools/miri/tests/pass/cast-rfc0401-vtable-kinds.rs @@ -9,6 +9,7 @@ trait Foo<T> { } } +#[allow(dead_code)] trait Bar { fn bar(&self) { println!("Bar!"); diff --git a/src/tools/miri/tests/pass/dyn-upcast.rs b/src/tools/miri/tests/pass/dyn-upcast.rs index 8432012a9ba..529b9c471d4 100644 --- a/src/tools/miri/tests/pass/dyn-upcast.rs +++ b/src/tools/miri/tests/pass/dyn-upcast.rs @@ -383,14 +383,17 @@ fn struct_() { fn replace_vptr() { trait A { + #[allow(dead_code)] fn foo_a(&self); } trait B { + #[allow(dead_code)] fn foo_b(&self); } trait C: A + B { + #[allow(dead_code)] fn foo_c(&self); } diff --git a/src/tools/miri/tests/pass/weak_memory/weak.rs b/src/tools/miri/tests/pass/weak_memory/weak.rs index 4c3be6b3559..e10ccc277f6 100644 --- a/src/tools/miri/tests/pass/weak_memory/weak.rs +++ b/src/tools/miri/tests/pass/weak_memory/weak.rs @@ -11,6 +11,7 @@ use std::sync::atomic::Ordering::*; use std::sync::atomic::{fence, AtomicUsize}; use std::thread::spawn; +#[allow(dead_code)] #[derive(Copy, Clone)] struct EvilSend<T>(pub T); diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index 6dc3eac44d4..f0af401d3da 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -47,7 +47,7 @@ impl Emitter for SilentEmitter { None } - fn emit_diagnostic(&mut self, _db: &Diagnostic) {} + fn emit_diagnostic(&mut self, _db: Diagnostic) {} } fn silent_emitter() -> Box<DynEmitter> { @@ -64,7 +64,7 @@ struct SilentOnIgnoredFilesEmitter { } impl SilentOnIgnoredFilesEmitter { - fn handle_non_ignoreable_error(&mut self, db: &Diagnostic) { + fn handle_non_ignoreable_error(&mut self, db: Diagnostic) { self.has_non_ignorable_parser_errors = true; self.can_reset.store(false, Ordering::Release); self.emitter.emit_diagnostic(db); @@ -86,7 +86,7 @@ impl Emitter for SilentOnIgnoredFilesEmitter { None } - fn emit_diagnostic(&mut self, db: &Diagnostic) { + fn emit_diagnostic(&mut self, db: Diagnostic) { if db.level() == DiagnosticLevel::Fatal { return self.handle_non_ignoreable_error(db); } @@ -365,7 +365,7 @@ mod tests { None } - fn emit_diagnostic(&mut self, _db: &Diagnostic) { + fn emit_diagnostic(&mut self, _db: Diagnostic) { self.num_emitted_errors.fetch_add(1, Ordering::Release); } } @@ -424,7 +424,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, Some(span)); - emitter.emit_diagnostic(&fatal_diagnostic); + emitter.emit_diagnostic(fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } @@ -449,7 +449,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); - emitter.emit_diagnostic(&non_fatal_diagnostic); + emitter.emit_diagnostic(non_fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0); assert_eq!(can_reset_errors.load(Ordering::Acquire), true); } @@ -473,7 +473,7 @@ mod tests { ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); - emitter.emit_diagnostic(&non_fatal_diagnostic); + emitter.emit_diagnostic(non_fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } @@ -512,9 +512,9 @@ mod tests { let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span)); let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span)); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None); - emitter.emit_diagnostic(&bar_diagnostic); - emitter.emit_diagnostic(&foo_diagnostic); - emitter.emit_diagnostic(&fatal_diagnostic); + emitter.emit_diagnostic(bar_diagnostic); + emitter.emit_diagnostic(foo_diagnostic); + emitter.emit_diagnostic(fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 2); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); } diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 451276b5ac1..03f8a701627 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -13,7 +13,8 @@ use std::path::{Path, PathBuf}; // desirable, because large numbers of files are unwieldy in general. See issue // #73494. const ENTRY_LIMIT: usize = 900; -const ISSUES_ENTRY_LIMIT: usize = 1807; +// FIXME: The following limits should be reduced eventually. +const ISSUES_ENTRY_LIMIT: usize = 1794; const ROOT_ENTRY_LIMIT: usize = 870; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ diff --git a/tests/assembly/is_aligned.rs b/tests/assembly/is_aligned.rs index d152d200adf..c4a7823ce1a 100644 --- a/tests/assembly/is_aligned.rs +++ b/tests/assembly/is_aligned.rs @@ -2,8 +2,8 @@ // only-x86_64 // ignore-sgx // revisions: opt-speed opt-size -// [opt-speed] compile-flags: -Copt-level=1 -// [opt-size] compile-flags: -Copt-level=s +// [opt-speed] compile-flags: -Copt-level=2 -Cdebug-assertions=no +// [opt-size] compile-flags: -Copt-level=s -Cdebug-assertions=no #![crate_type="rlib"] #![feature(core_intrinsics)] diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index 41f5df0fba0..6105ea430dd 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -174,6 +174,9 @@ // revisions: armv7r_none_eabihf // [armv7r_none_eabihf] compile-flags: --target armv7r-none-eabihf // [armv7r_none_eabihf] needs-llvm-components: arm +// revisions: armv8r_none_eabihf +// [armv8r_none_eabihf] compile-flags: --target armv8r-none-eabihf +// [armv8r_none_eabihf] needs-llvm-components: arm // FIXME: disabled since it fails on CI saying the csky component is missing /* revisions: csky_unknown_linux_gnuabiv2 diff --git a/tests/codegen-units/item-collection/instantiation-through-vtable.rs b/tests/codegen-units/item-collection/instantiation-through-vtable.rs index e78226d4083..41edab7f879 100644 --- a/tests/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/tests/codegen-units/item-collection/instantiation-through-vtable.rs @@ -26,7 +26,9 @@ fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn std::ptr::drop_in_place::<Struct<u32>> - shim(None) @@ instantiation_through_vtable-cgu.0[Internal] //~ MONO_ITEM fn <Struct<u32> as Trait>::foo //~ MONO_ITEM fn <Struct<u32> as Trait>::bar - let _ = &s1 as &Trait; + let r1 = &s1 as &Trait; + r1.foo(); + r1.bar(); let s1 = Struct { _a: 0u64 }; //~ MONO_ITEM fn std::ptr::drop_in_place::<Struct<u64>> - shim(None) @@ instantiation_through_vtable-cgu.0[Internal] diff --git a/tests/codegen-units/item-collection/trait-method-default-impl.rs b/tests/codegen-units/item-collection/trait-method-default-impl.rs index d953582cce9..c8a4552b11a 100644 --- a/tests/codegen-units/item-collection/trait-method-default-impl.rs +++ b/tests/codegen-units/item-collection/trait-method-default-impl.rs @@ -57,5 +57,8 @@ fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn <u32 as SomeGenericTrait<i16>>::bar::<()> 0u32.bar(0i16, ()); + 0i8.foo(); + 0i32.foo(); + 0 } diff --git a/tests/codegen-units/item-collection/unsizing.rs b/tests/codegen-units/item-collection/unsizing.rs index 34f52ce4e61..f578b00f276 100644 --- a/tests/codegen-units/item-collection/unsizing.rs +++ b/tests/codegen-units/item-collection/unsizing.rs @@ -75,5 +75,7 @@ fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn <u32 as Trait>::foo let _wrapper_sized = wrapper_sized as Wrapper<Trait>; + false.foo(); + 0 } diff --git a/tests/codegen/async-closure-debug.rs b/tests/codegen/async-closure-debug.rs new file mode 100644 index 00000000000..6718d2b6627 --- /dev/null +++ b/tests/codegen/async-closure-debug.rs @@ -0,0 +1,21 @@ +// Just make sure that async closures don't ICE. +// +// compile-flags: -C debuginfo=2 --edition=2018 +// ignore-msvc + +// CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "async_closure_test" +// CHECK-DAG: [[CLOSURE:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: [[GEN_FN]] +// CHECK-DAG: [[UPVAR:!.*]] = !DIDerivedType(tag: DW_TAG_member, name: "upvar", scope: [[CLOSURE]] + +#![feature(async_closure)] + +fn async_closure_test(upvar: &str) -> impl async Fn() + '_ { + async move || { + let hello = String::from("hello"); + println!("{hello}, {upvar}"); + } +} + +fn main() { + let _async_closure = async_closure_test("world"); +} diff --git a/tests/codegen/cffi/ffi-returns-twice.rs b/tests/codegen/cffi/ffi-returns-twice.rs deleted file mode 100644 index 0fbe03f0bb6..00000000000 --- a/tests/codegen/cffi/ffi-returns-twice.rs +++ /dev/null @@ -1,11 +0,0 @@ -// compile-flags: -C no-prepopulate-passes -#![crate_type = "lib"] -#![feature(ffi_returns_twice)] - -pub fn bar() { unsafe { foo() } } - -extern "C" { - // CHECK: declare{{( dso_local)?}} void @foo(){{.*}}[[ATTRS:#[0-9]+]] - // CHECK: attributes [[ATTRS]] = { {{.*}}returns_twice{{.*}} } - #[ffi_returns_twice] pub fn foo(); -} diff --git a/tests/codegen/direct-access-external-data.rs b/tests/codegen/direct-access-external-data.rs new file mode 100644 index 00000000000..ec4bfc33518 --- /dev/null +++ b/tests/codegen/direct-access-external-data.rs @@ -0,0 +1,21 @@ +// only-loongarch64-unknown-linux-gnu + +// revisions: DEFAULT DIRECT INDIRECT +// [DEFAULT] compile-flags: -C relocation-model=static +// [DIRECT] compile-flags: -C relocation-model=static -Z direct-access-external-data=yes +// [INDIRECT] compile-flags: -C relocation-model=static -Z direct-access-external-data=no + +#![crate_type = "rlib"] + +// DEFAULT: @VAR = external {{.*}} global i32 +// DIRECT: @VAR = external dso_local {{.*}} global i32 +// INDIRECT: @VAR = external {{.*}} global i32 + +extern "C" { + static VAR: i32; +} + +#[no_mangle] +pub fn get() -> i32 { + unsafe { VAR } +} diff --git a/tests/incremental/const-generics/issue-62536.rs b/tests/incremental/const-generics/issue-62536.rs index 93c1dbf44e9..022376768f2 100644 --- a/tests/incremental/const-generics/issue-62536.rs +++ b/tests/incremental/const-generics/issue-62536.rs @@ -1,4 +1,7 @@ // revisions:cfail1 + +#![allow(unused_variables)] + struct S<T, const N: usize>([T; N]); fn f<T, const N: usize>(x: T) -> S<T, {N}> { panic!() } diff --git a/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs index 8262a2a211b..5c8af47ccbe 100644 --- a/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs +++ b/tests/incremental/const-generics/try_unify_abstract_const_regression_tests/issue-77708-1.rs @@ -1,6 +1,6 @@ // revisions: cfail #![feature(generic_const_exprs)] -#![allow(incomplete_features, unused_braces)] +#![allow(incomplete_features, unused_braces, unused_variables)] trait Delegates<T> {} diff --git a/tests/incremental/struct_change_field_name.rs b/tests/incremental/struct_change_field_name.rs index a7c79e9d751..bd952bcc1c8 100644 --- a/tests/incremental/struct_change_field_name.rs +++ b/tests/incremental/struct_change_field_name.rs @@ -6,6 +6,7 @@ // [cfail2] compile-flags: -Z query-dep-graph -Z assert-incr-state=loaded #![feature(rustc_attrs)] +#![allow(unused_variables)] #[cfg(rpass1)] pub struct X { diff --git a/tests/mir-opt/async_closure_shims.rs b/tests/mir-opt/async_closure_shims.rs index ef3bdaaa145..2c99a2dad37 100644 --- a/tests/mir-opt/async_closure_shims.rs +++ b/tests/mir-opt/async_closure_shims.rs @@ -33,7 +33,7 @@ async fn call_once(f: impl AsyncFnOnce(i32)) { // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_mut.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_mut.0.mir // EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.coroutine_by_move.0.mir -fn main() { +pub fn main() { block_on(async { let b = 2i32; let mut async_closure = async move |a: i32| { diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff index ffbd97bb545..94cfb4e63fc 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,30 +56,41 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff index 7b6dcf1972b..ee85287882b 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,34 +56,45 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff index ffbd97bb545..94cfb4e63fc 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,30 +56,41 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff index 7b6dcf1972b..ee85287882b 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -73,34 +56,45 @@ _7 = const 1_usize; _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); - _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { + _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); + _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff index df68ce496fd..4df38d6e61b 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,31 +58,43 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff index e16ea22091e..6aac30bcd17 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,35 +58,47 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff index df68ce496fd..4df38d6e61b 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,31 +58,43 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb3, otherwise: bb2]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind unreachable]; } - - bb1: { - StorageDead(_1); - return; - } } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff index e16ea22091e..6aac30bcd17 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff @@ -24,29 +24,11 @@ debug ptr => _6; scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) { debug ptr => _6; - let mut _8: *const [bool; 0]; - let mut _9: *mut [bool; 0]; + let mut _8: bool; + let _9: (); + let mut _10: *mut (); + let mut _11: *const [bool; 0]; scope 12 { - scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) { - debug ptr => _9; - scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) { - debug self => _9; - let mut _10: *mut u8; - scope 15 { - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _10; - scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _10; - scope 18 { - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _10; - } - } - } - } - } - } - } } } } @@ -66,6 +48,7 @@ StorageLive(_1); StorageLive(_2); StorageLive(_3); + StorageLive(_9); StorageLive(_4); StorageLive(_5); StorageLive(_6); @@ -75,35 +58,47 @@ + _7 = const 1_usize; + _6 = const {0x1 as *mut [bool; 0]}; StorageDead(_7); - StorageLive(_8); - StorageLive(_9); StorageLive(_10); -- _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); -+ _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); - _5 = NonNull::<[bool; 0]> { pointer: _8 }; - StorageDead(_10); - StorageDead(_9); + StorageLive(_11); + StorageLive(_8); + _8 = cfg!(debug_assertions); + switchInt(move _8) -> [0: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_1); + return; + } + + bb2 (cleanup): { + resume; + } + + bb3: { +- _10 = _6 as *mut () (PtrToPtr); ++ _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr); + _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable]; + } + + bb4: { StorageDead(_8); +- _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer)); ++ _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer)); + _5 = NonNull::<[bool; 0]> { pointer: _11 }; + StorageDead(_11); + StorageDead(_10); StorageDead(_6); _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> }; StorageDead(_5); _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize)); StorageDead(_4); _2 = Box::<[bool]>(_3, const std::alloc::Global); + StorageDead(_9); StorageDead(_3); _1 = A { foo: move _2 }; StorageDead(_2); _0 = const (); drop(_1) -> [return: bb1, unwind: bb2]; } - - bb1: { - StorageDead(_1); - return; - } - - bb2 (cleanup): { - resume; - } } diff --git a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff index 7a374c5675a..8b427cff677 100644 --- a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff @@ -51,13 +51,13 @@ - } - - bb3: { - StorageLive(_8); - _8 = (((_3.0: std::option::Option<u32>) as Some).0: u32); StorageLive(_9); _9 = (((_3.1: std::option::Option<u32>) as Some).0: u32); + StorageLive(_8); + _8 = (((_3.0: std::option::Option<u32>) as Some).0: u32); _0 = const 0_u32; - StorageDead(_9); StorageDead(_8); + StorageDead(_9); - goto -> bb4; + goto -> bb3; } diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff index 21f58a14a2b..b91a469225c 100644 --- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff @@ -58,13 +58,13 @@ - - bb4: { + bb2: { - StorageLive(_9); - _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); StorageLive(_10); _10 = (((_3.1: std::option::Option<u32>) as Some).0: u32); + StorageLive(_9); + _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); _0 = const 0_u32; - StorageDead(_10); StorageDead(_9); + StorageDead(_10); - goto -> bb6; + goto -> bb4; } diff --git a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff index e058c409cb5..cc16af721ca 100644 --- a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff @@ -51,13 +51,13 @@ - } - - bb3: { - StorageLive(_8); - _8 = (((_3.0: std::option::Option<u32>) as Some).0: u32); StorageLive(_9); _9 = (((_3.1: std::option::Option<bool>) as Some).0: bool); + StorageLive(_8); + _8 = (((_3.0: std::option::Option<u32>) as Some).0: u32); _0 = const 0_u32; - StorageDead(_9); StorageDead(_8); + StorageDead(_9); - goto -> bb4; + goto -> bb3; } diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff index f98d68e6ffc..eb8926d27ee 100644 --- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff @@ -69,16 +69,16 @@ - bb4: { + bb3: { - StorageLive(_11); - _11 = (((_4.0: std::option::Option<u32>) as Some).0: u32); - StorageLive(_12); - _12 = (((_4.1: std::option::Option<u32>) as Some).0: u32); StorageLive(_13); _13 = (((_4.2: std::option::Option<u32>) as Some).0: u32); + StorageLive(_12); + _12 = (((_4.1: std::option::Option<u32>) as Some).0: u32); + StorageLive(_11); + _11 = (((_4.0: std::option::Option<u32>) as Some).0: u32); _0 = const 0_u32; - StorageDead(_13); - StorageDead(_12); StorageDead(_11); + StorageDead(_12); + StorageDead(_13); - goto -> bb5; + goto -> bb4; } diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff index 0c94794fa3f..79cf1c0e34a 100644 --- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff @@ -116,12 +116,12 @@ } bb6: { - StorageLive(_12); - _39 = deref_copy (_4.0: &ViewportPercentageLength); - _12 = (((*_39) as Vw).0: f32); StorageLive(_13); - _40 = deref_copy (_4.1: &ViewportPercentageLength); - _13 = (((*_40) as Vw).0: f32); + _39 = deref_copy (_4.1: &ViewportPercentageLength); + _13 = (((*_39) as Vw).0: f32); + StorageLive(_12); + _40 = deref_copy (_4.0: &ViewportPercentageLength); + _12 = (((*_40) as Vw).0: f32); StorageLive(_14); StorageLive(_15); _15 = _12; @@ -132,18 +132,18 @@ StorageDead(_15); _3 = ViewportPercentageLength::Vw(move _14); StorageDead(_14); - StorageDead(_13); StorageDead(_12); + StorageDead(_13); goto -> bb10; } bb7: { - StorageLive(_17); - _41 = deref_copy (_4.0: &ViewportPercentageLength); - _17 = (((*_41) as Vh).0: f32); StorageLive(_18); - _42 = deref_copy (_4.1: &ViewportPercentageLength); - _18 = (((*_42) as Vh).0: f32); + _41 = deref_copy (_4.1: &ViewportPercentageLength); + _18 = (((*_41) as Vh).0: f32); + StorageLive(_17); + _42 = deref_copy (_4.0: &ViewportPercentageLength); + _17 = (((*_42) as Vh).0: f32); StorageLive(_19); StorageLive(_20); _20 = _17; @@ -154,18 +154,18 @@ StorageDead(_20); _3 = ViewportPercentageLength::Vh(move _19); StorageDead(_19); - StorageDead(_18); StorageDead(_17); + StorageDead(_18); goto -> bb10; } bb8: { - StorageLive(_22); - _43 = deref_copy (_4.0: &ViewportPercentageLength); - _22 = (((*_43) as Vmin).0: f32); StorageLive(_23); - _44 = deref_copy (_4.1: &ViewportPercentageLength); - _23 = (((*_44) as Vmin).0: f32); + _43 = deref_copy (_4.1: &ViewportPercentageLength); + _23 = (((*_43) as Vmin).0: f32); + StorageLive(_22); + _44 = deref_copy (_4.0: &ViewportPercentageLength); + _22 = (((*_44) as Vmin).0: f32); StorageLive(_24); StorageLive(_25); _25 = _22; @@ -176,18 +176,18 @@ StorageDead(_25); _3 = ViewportPercentageLength::Vmin(move _24); StorageDead(_24); - StorageDead(_23); StorageDead(_22); + StorageDead(_23); goto -> bb10; } bb9: { - StorageLive(_27); - _45 = deref_copy (_4.0: &ViewportPercentageLength); - _27 = (((*_45) as Vmax).0: f32); StorageLive(_28); - _46 = deref_copy (_4.1: &ViewportPercentageLength); - _28 = (((*_46) as Vmax).0: f32); + _45 = deref_copy (_4.1: &ViewportPercentageLength); + _28 = (((*_45) as Vmax).0: f32); + StorageLive(_27); + _46 = deref_copy (_4.0: &ViewportPercentageLength); + _27 = (((*_46) as Vmax).0: f32); StorageLive(_29); StorageLive(_30); _30 = _27; @@ -198,8 +198,8 @@ StorageDead(_30); _3 = ViewportPercentageLength::Vmax(move _29); StorageDead(_29); - StorageDead(_28); StorageDead(_27); + StorageDead(_28); goto -> bb10; } diff --git a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff index 09cdce71857..af0337d0a7e 100644 --- a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff +++ b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff @@ -59,13 +59,13 @@ } bb5: { - StorageLive(_9); - _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); StorageLive(_10); _10 = (((_3.1: std::option::Option<u32>) as Some).0: u32); + StorageLive(_9); + _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32); _0 = const 0_u32; - StorageDead(_10); StorageDead(_9); + StorageDead(_10); goto -> bb8; } diff --git a/tests/mir-opt/fn_ptr_shim.rs b/tests/mir-opt/fn_ptr_shim.rs index c82260baefe..2650cbf9704 100644 --- a/tests/mir-opt/fn_ptr_shim.rs +++ b/tests/mir-opt/fn_ptr_shim.rs @@ -5,7 +5,7 @@ // (as only `FnDef` and `FnPtr` callees are allowed in MIR). // EMIT_MIR core.ops-function-Fn-call.AddMovesForPackedDrops.before.mir -fn main() { +pub fn main() { call(noop as fn()); } diff --git a/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff b/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff new file mode 100644 index 00000000000..b12de636f58 --- /dev/null +++ b/tests/mir-opt/gvn_copy_moves.fn0.GVN.diff @@ -0,0 +1,27 @@ +- // MIR for `fn0` before GVN ++ // MIR for `fn0` after GVN + + fn fn0() -> () { + let mut _0: (); + let mut _1: usize; + let mut _2: [u128; 6]; + let mut _3: ([u128; 6],); + let mut _4: ([u128; 6],); + let mut _5: (); + + bb0: { + _1 = const 1_usize; + _2 = [const 42_u128; 6]; +- _2[_1] = const 1_u128; ++ _2[1 of 2] = const 1_u128; + _3 = (_2,); + _4 = _3; +- _5 = fn1(move (_3.0: [u128; 6]), _4) -> [return: bb1, unwind unreachable]; ++ _5 = fn1((_3.0: [u128; 6]), _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + return; + } + } + diff --git a/tests/mir-opt/gvn_copy_moves.rs b/tests/mir-opt/gvn_copy_moves.rs new file mode 100644 index 00000000000..d216825e5e6 --- /dev/null +++ b/tests/mir-opt/gvn_copy_moves.rs @@ -0,0 +1,46 @@ +// unit-test: GVN + +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime", phase = "initial")] +fn fn0() { + // CHECK-LABEL: fn fn0( + mir! { + let a: usize; + let b: [u128; 6]; + let c: ([u128; 6],); + let d: ([u128; 6],); + let x: (); + { + // CHECK: bb0: { + // CHECK-NEXT: _1 = const 1_usize; + // CHECK-NEXT: _2 = [const 42_u128; 6]; + // CHECK-NEXT: _2[1 of 2] = const 1_u128; + // CHECK-NEXT: _3 = (_2,); + // CHECK-NEXT: _4 = _3; + // CHECK-NEXT: _5 = fn1((_3.0: [u128; 6]), _3) + a = 1_usize; + b = [42; 6]; + b[a] = 1; + c = (b,); + d = c; + Call(x = fn1(Move(c.0), d), ReturnTo(bb1), UnwindUnreachable()) + } + bb1 = { + Return() + } + } +} + +#[inline(never)] +fn fn1(a: [u128; 6], mut b: ([u128; 6],)) { + b.0 = [0; 6]; +} + +fn main() { + fn0(); +} + +// EMIT_MIR gvn_copy_moves.fn0.GVN.diff diff --git a/tests/mir-opt/inline/cycle.g.Inline.panic-abort.diff b/tests/mir-opt/inline/cycle.g.Inline.panic-abort.diff index 8f2baf4a3b6..1be0a4f2d29 100644 --- a/tests/mir-opt/inline/cycle.g.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/cycle.g.Inline.panic-abort.diff @@ -4,35 +4,16 @@ fn g() -> () { let mut _0: (); let _1: (); -+ let mut _2: fn() {main}; -+ scope 1 (inlined f::<fn() {main}>) { -+ debug g => _2; -+ let mut _3: &fn() {main}; -+ let _4: (); -+ } bb0: { StorageLive(_1); -- _1 = f::<fn() {main}>(main) -> [return: bb1, unwind unreachable]; -+ StorageLive(_2); -+ _2 = main; -+ StorageLive(_4); -+ StorageLive(_3); -+ _3 = &_2; -+ _4 = <fn() {main} as Fn<()>>::call(move _3, const ()) -> [return: bb2, unwind unreachable]; + _1 = f::<fn() {main}>(main) -> [return: bb1, unwind unreachable]; } bb1: { -+ StorageDead(_4); -+ StorageDead(_2); StorageDead(_1); _0 = const (); return; -+ } -+ -+ bb2: { -+ StorageDead(_3); -+ drop(_2) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff index 1fd1014ba1d..da516220d50 100644 --- a/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/cycle.g.Inline.panic-unwind.diff @@ -4,43 +4,16 @@ fn g() -> () { let mut _0: (); let _1: (); -+ let mut _2: fn() {main}; -+ scope 1 (inlined f::<fn() {main}>) { -+ debug g => _2; -+ let mut _3: &fn() {main}; -+ let _4: (); -+ } bb0: { StorageLive(_1); -- _1 = f::<fn() {main}>(main) -> [return: bb1, unwind continue]; -+ StorageLive(_2); -+ _2 = main; -+ StorageLive(_4); -+ StorageLive(_3); -+ _3 = &_2; -+ _4 = <fn() {main} as Fn<()>>::call(move _3, const ()) -> [return: bb2, unwind: bb3]; + _1 = f::<fn() {main}>(main) -> [return: bb1, unwind continue]; } bb1: { -+ StorageDead(_4); -+ StorageDead(_2); StorageDead(_1); _0 = const (); return; -+ } -+ -+ bb2: { -+ StorageDead(_3); -+ drop(_2) -> [return: bb1, unwind continue]; -+ } -+ -+ bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate(cleanup)]; -+ } -+ -+ bb4 (cleanup): { -+ resume; } } diff --git a/tests/mir-opt/inline/cycle.rs b/tests/mir-opt/inline/cycle.rs index 350724235ba..c251226673d 100644 --- a/tests/mir-opt/inline/cycle.rs +++ b/tests/mir-opt/inline/cycle.rs @@ -13,9 +13,7 @@ fn f(g: impl Fn()) { #[inline(always)] fn g() { // CHECK-LABEL: fn g( - // CHECK-NOT: inlined - // CHECK: (inlined f::<fn() {main}>) - // CHECK-NOT: inlined + // CHECK-NOT: (inlined f::<fn() {main}>) f(main); } diff --git a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-abort.diff index d437dbf5763..142b9c56598 100644 --- a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-abort.diff @@ -7,6 +7,10 @@ + scope 1 (inlined <C as Call>::call) { + scope 2 (inlined <B<A> as Call>::call) { + scope 3 (inlined <A as Call>::call) { ++ scope 4 (inlined <B<C> as Call>::call) { ++ scope 5 (inlined <C as Call>::call) { ++ } ++ } + } + } + } @@ -14,7 +18,7 @@ bb0: { StorageLive(_1); - _1 = <C as Call>::call() -> [return: bb1, unwind unreachable]; -+ _1 = <B<C> as Call>::call() -> [return: bb1, unwind unreachable]; ++ _1 = <B<A> as Call>::call() -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff index 8314526ee04..193ada05f02 100644 --- a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.panic-unwind.diff @@ -7,6 +7,10 @@ + scope 1 (inlined <C as Call>::call) { + scope 2 (inlined <B<A> as Call>::call) { + scope 3 (inlined <A as Call>::call) { ++ scope 4 (inlined <B<C> as Call>::call) { ++ scope 5 (inlined <C as Call>::call) { ++ } ++ } + } + } + } @@ -14,7 +18,7 @@ bb0: { StorageLive(_1); - _1 = <C as Call>::call() -> [return: bb1, unwind continue]; -+ _1 = <B<C> as Call>::call() -> [return: bb1, unwind continue]; ++ _1 = <B<A> as Call>::call() -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/inline/unwrap_unchecked.rs b/tests/mir-opt/inline/unwrap_unchecked.rs index be133706e5c..1adf2224d97 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.rs +++ b/tests/mir-opt/inline/unwrap_unchecked.rs @@ -2,7 +2,7 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // ignore-debug: the debug assertions prevent the inlining we are testing for -// compile-flags: -Zmir-opt-level=2 -Zinline-mir +// compile-flags: -Zmir-opt-level=2 -Zinline-mir -Cdebug-assertions=no // EMIT_MIR unwrap_unchecked.unwrap_unchecked.Inline.diff // EMIT_MIR unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff index 2a36ad9230e..9358a64b4fa 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff @@ -7,41 +7,44 @@ let mut _2: std::option::Option<T>; + scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) { + debug self => _2; -+ let mut _3: &std::option::Option<T>; -+ let mut _4: isize; -+ let mut _5: bool; ++ let mut _3: isize; + scope 2 { + debug val => _0; + } + scope 3 { -+ scope 5 (inlined unreachable_unchecked) { -+ scope 6 { -+ scope 7 (inlined unreachable_unchecked::runtime) { -+ } ++ scope 4 (inlined unreachable_unchecked) { ++ let mut _4: bool; ++ let _5: (); ++ scope 5 { + } + } + } -+ scope 4 (inlined Option::<T>::is_some) { -+ debug self => _3; -+ } + } bb0: { StorageLive(_2); _2 = move _1; - _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable]; -- } -- -- bb1: { + StorageLive(_3); -+ StorageLive(_4); + StorageLive(_5); -+ _4 = discriminant(_2); -+ _5 = Eq(_4, const 1_isize); -+ assume(move _5); ++ _3 = discriminant(_2); ++ switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { ++ StorageLive(_4); ++ _4 = cfg!(debug_assertions); ++ assume(_4); ++ _5 = unreachable_unchecked::precondition_check() -> [return: bb2, unwind unreachable]; ++ } ++ ++ bb2: { ++ unreachable; ++ } ++ ++ bb3: { + _0 = move ((_2 as Some).0: T); + StorageDead(_5); -+ StorageDead(_4); + StorageDead(_3); StorageDead(_2); return; diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff index 14c8c671d3f..ac33c126155 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff @@ -7,48 +7,51 @@ let mut _2: std::option::Option<T>; + scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) { + debug self => _2; -+ let mut _3: &std::option::Option<T>; -+ let mut _4: isize; -+ let mut _5: bool; ++ let mut _3: isize; + scope 2 { + debug val => _0; + } + scope 3 { -+ scope 5 (inlined unreachable_unchecked) { -+ scope 6 { -+ scope 7 (inlined unreachable_unchecked::runtime) { -+ } ++ scope 4 (inlined unreachable_unchecked) { ++ let mut _4: bool; ++ let _5: (); ++ scope 5 { + } + } + } -+ scope 4 (inlined Option::<T>::is_some) { -+ debug self => _3; -+ } + } bb0: { StorageLive(_2); _2 = move _1; - _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2]; -- } -- -- bb1: { + StorageLive(_3); -+ StorageLive(_4); + StorageLive(_5); -+ _4 = discriminant(_2); -+ _5 = Eq(_4, const 1_isize); -+ assume(move _5); ++ _3 = discriminant(_2); ++ switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { +- StorageDead(_2); +- return; ++ StorageLive(_4); ++ _4 = cfg!(debug_assertions); ++ assume(_4); ++ _5 = unreachable_unchecked::precondition_check() -> [return: bb2, unwind unreachable]; + } + +- bb2 (cleanup): { +- resume; ++ bb2: { ++ unreachable; ++ } ++ ++ bb3: { + _0 = move ((_2 as Some).0: T); + StorageDead(_5); -+ StorageDead(_4); + StorageDead(_3); - StorageDead(_2); - return; -- } -- -- bb2 (cleanup): { -- resume; ++ StorageDead(_2); ++ return; } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir index d6a608476df..8ec65935c66 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir @@ -6,35 +6,39 @@ fn unwrap_unchecked(_1: Option<T>) -> T { scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) { debug self => _1; let mut _2: isize; - let mut _3: bool; - let mut _4: &std::option::Option<T>; scope 2 { debug val => _0; } scope 3 { - scope 5 (inlined unreachable_unchecked) { - scope 6 { - scope 7 (inlined unreachable_unchecked::runtime) { - } + scope 4 (inlined unreachable_unchecked) { + let mut _3: bool; + let _4: (); + scope 5 { } } } - scope 4 (inlined Option::<T>::is_some) { - debug self => _4; - } } bb0: { - StorageLive(_4); StorageLive(_2); - StorageLive(_3); _2 = discriminant(_1); - _3 = Eq(_2, const 1_isize); - assume(move _3); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { + StorageLive(_3); + _3 = cfg!(debug_assertions); + assume(_3); + _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable]; + } + + bb2: { _0 = ((_1 as Some).0: T); - StorageDead(_3); StorageDead(_2); - StorageDead(_4); return; } + + bb3: { + unreachable; + } } diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir index d6a608476df..8ec65935c66 100644 --- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir @@ -6,35 +6,39 @@ fn unwrap_unchecked(_1: Option<T>) -> T { scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) { debug self => _1; let mut _2: isize; - let mut _3: bool; - let mut _4: &std::option::Option<T>; scope 2 { debug val => _0; } scope 3 { - scope 5 (inlined unreachable_unchecked) { - scope 6 { - scope 7 (inlined unreachable_unchecked::runtime) { - } + scope 4 (inlined unreachable_unchecked) { + let mut _3: bool; + let _4: (); + scope 5 { } } } - scope 4 (inlined Option::<T>::is_some) { - debug self => _4; - } } bb0: { - StorageLive(_4); StorageLive(_2); - StorageLive(_3); _2 = discriminant(_1); - _3 = Eq(_2, const 1_isize); - assume(move _3); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { + StorageLive(_3); + _3 = cfg!(debug_assertions); + assume(_3); + _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable]; + } + + bb2: { _0 = ((_1 as Some).0: T); - StorageDead(_3); StorageDead(_2); - StorageDead(_4); return; } + + bb3: { + unreachable; + } } diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index ffb1aedd2ea..a10061ed941 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), args: [] }: &ReStatic [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &ReStatic [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index ffb1aedd2ea..a10061ed941 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -1,8 +1,8 @@ // MIR for `main` after built | User Type Annotations -| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[22bb]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[22bb]::main::{constant#1}), args: [] }: &ReStatic [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &ReStatic [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir index 0114309dbb5..7c038b0ee88 100644 --- a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir @@ -4,19 +4,31 @@ fn ub_if_b(_1: Thing) -> Thing { debug t => _1; let mut _0: Thing; let mut _2: isize; - let mut _3: bool; scope 1 (inlined unreachable_unchecked) { + let mut _3: bool; + let _4: (); scope 2 { - scope 3 (inlined unreachable_unchecked::runtime) { - } } } bb0: { _2 = discriminant(_1); - _3 = Eq(_2, const 0_isize); - assume(move _3); + switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3]; + } + + bb1: { _0 = move _1; return; } + + bb2: { + StorageLive(_3); + _3 = cfg!(debug_assertions); + assume(_3); + _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable]; + } + + bb3: { + unreachable; + } } diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir index 3ca24e152a4..3ca24e152a4 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir new file mode 100644 index 00000000000..3ca24e152a4 --- /dev/null +++ b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,16 @@ +// MIR for `manual_replace` after PreCodegen + +fn manual_replace(_1: &mut u32, _2: u32) -> u32 { + debug r => _1; + debug v => _2; + let mut _0: u32; + scope 1 { + debug temp => _0; + } + + bb0: { + _0 = (*_1); + (*_1) = _2; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir deleted file mode 100644 index f0cb4ca31fe..00000000000 --- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir +++ /dev/null @@ -1,66 +0,0 @@ -// MIR for `mem_replace` after PreCodegen - -fn mem_replace(_1: &mut u32, _2: u32) -> u32 { - debug r => _1; - debug v => _2; - let mut _0: u32; - scope 1 (inlined std::mem::replace::<u32>) { - debug dest => _1; - debug src => _2; - scope 2 { - scope 3 { - debug result => _0; - scope 16 (inlined std::ptr::write::<u32>) { - debug dst => _1; - debug src => _2; - scope 17 { - } - } - } - scope 4 (inlined std::ptr::read::<u32>) { - debug src => _1; - let mut _3: *const u32; - scope 5 { - scope 6 (inlined std::ptr::read::runtime::<u32>) { - debug src => _3; - scope 7 (inlined intrinsics::is_aligned_and_not_null::<u32>) { - debug ptr => _3; - scope 8 (inlined std::ptr::const_ptr::<impl *const u32>::is_null) { - debug self => _3; - let mut _4: *const u8; - scope 9 { - scope 10 (inlined std::ptr::const_ptr::<impl *const T>::is_null::runtime_impl) { - debug ptr => _4; - scope 11 (inlined std::ptr::const_ptr::<impl *const u8>::addr) { - debug self => _4; - scope 12 { - scope 13 (inlined std::ptr::const_ptr::<impl *const u8>::cast::<()>) { - debug self => _4; - } - } - } - } - } - } - scope 14 (inlined std::ptr::const_ptr::<impl *const u32>::is_aligned) { - debug self => _3; - scope 15 (inlined align_of::<u32>) { - } - } - } - } - } - } - } - } - - bb0: { - StorageLive(_3); - StorageLive(_4); - _0 = (*_1); - StorageDead(_4); - StorageDead(_3); - (*_1) = _2; - return; - } -} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir new file mode 100644 index 00000000000..26919dd98dd --- /dev/null +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir @@ -0,0 +1,33 @@ +// MIR for `mem_replace` after PreCodegen + +fn mem_replace(_1: &mut u32, _2: u32) -> u32 { + debug r => _1; + debug v => _2; + let mut _0: u32; + scope 1 (inlined std::mem::replace::<u32>) { + debug dest => _1; + debug src => _2; + scope 2 { + scope 3 { + debug result => _0; + scope 6 (inlined std::ptr::write::<u32>) { + debug dst => _1; + debug src => _2; + scope 7 { + } + } + } + scope 4 (inlined std::ptr::read::<u32>) { + debug src => _1; + scope 5 { + } + } + } + } + + bb0: { + _0 = (*_1); + (*_1) = _2; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir new file mode 100644 index 00000000000..26919dd98dd --- /dev/null +++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,33 @@ +// MIR for `mem_replace` after PreCodegen + +fn mem_replace(_1: &mut u32, _2: u32) -> u32 { + debug r => _1; + debug v => _2; + let mut _0: u32; + scope 1 (inlined std::mem::replace::<u32>) { + debug dest => _1; + debug src => _2; + scope 2 { + scope 3 { + debug result => _0; + scope 6 (inlined std::ptr::write::<u32>) { + debug dst => _1; + debug src => _2; + scope 7 { + } + } + } + scope 4 (inlined std::ptr::read::<u32>) { + debug src => _1; + scope 5 { + } + } + } + } + + bb0: { + _0 = (*_1); + (*_1) = _2; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/mem_replace.rs b/tests/mir-opt/pre-codegen/mem_replace.rs index 18c4653d4c6..551afea3ba5 100644 --- a/tests/mir-opt/pre-codegen/mem_replace.rs +++ b/tests/mir-opt/pre-codegen/mem_replace.rs @@ -1,7 +1,8 @@ // skip-filecheck -// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 +// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir // only-64bit // ignore-debug the standard library debug assertions leak into this test +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index 26b2663fa35..4906c86f8ed 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -4,171 +4,165 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>; - let mut _15: std::iter::Enumerate<std::slice::Iter<'_, T>>; - let mut _16: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>; - let mut _17: std::option::Option<(usize, &T)>; - let mut _18: isize; - let mut _21: &impl Fn(usize, &T); - let mut _22: (usize, &T); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Enumerate<std::slice::Iter<'_, T>>; + let mut _17: std::iter::Enumerate<std::slice::Iter<'_, T>>; + let mut _18: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>; + let mut _19: std::option::Option<(usize, &T)>; + let mut _20: isize; + let mut _23: &impl Fn(usize, &T); + let mut _24: (usize, &T); + let _25: (); scope 1 { - debug iter => _15; - let _19: usize; - let _20: &T; + debug iter => _17; + let _21: usize; + let _22: &T; scope 2 { - debug i => _19; - debug x => _20; + debug i => _21; + debug x => _22; } } scope 3 (inlined core::slice::<impl [T]>::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull<T>; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull<T>; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::<T>::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::<T>) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::<T>) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::<T>::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::<T>) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::<impl [T]>::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) { - debug self => _13; - scope 23 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) { - debug iter => _13; + scope 19 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) { + debug self => _15; + scope 20 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) { + debug iter => _15; } } - scope 24 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull::<T> { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull::<T> { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Enumerate::<std::slice::Iter<'_, T>> { iter: _13, count: const 0_usize }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Enumerate::<std::slice::Iter<'_, T>> { iter: _15, count: const 0_usize }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_17); - StorageLive(_16); - _16 = &mut _15; - _17 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _16) -> [return: bb5, unwind unreachable]; + StorageLive(_19); + StorageLive(_18); + _18 = &mut _17; + _19 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _18) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_18); + _20 = discriminant(_19); + switchInt(move _20) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_19); StorageDead(_17); - StorageDead(_15); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -177,19 +171,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _19 = (((_17 as Some).0: (usize, &T)).0: usize); - _20 = (((_17 as Some).0: (usize, &T)).1: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_19, _20); - _23 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _21, move _22) -> [return: bb9, unwind unreachable]; + _21 = (((_19 as Some).0: (usize, &T)).0: usize); + _22 = (((_19 as Some).0: (usize, &T)).1: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_21, _22); + _25 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _23, move _24) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_17); + StorageDead(_24); + StorageDead(_23); + StorageDead(_19); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index a055612bd5f..25a5ecdc6c3 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -4,171 +4,165 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>; - let mut _15: std::iter::Enumerate<std::slice::Iter<'_, T>>; - let mut _16: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>; - let mut _17: std::option::Option<(usize, &T)>; - let mut _18: isize; - let mut _21: &impl Fn(usize, &T); - let mut _22: (usize, &T); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Enumerate<std::slice::Iter<'_, T>>; + let mut _17: std::iter::Enumerate<std::slice::Iter<'_, T>>; + let mut _18: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>; + let mut _19: std::option::Option<(usize, &T)>; + let mut _20: isize; + let mut _23: &impl Fn(usize, &T); + let mut _24: (usize, &T); + let _25: (); scope 1 { - debug iter => _15; - let _19: usize; - let _20: &T; + debug iter => _17; + let _21: usize; + let _22: &T; scope 2 { - debug i => _19; - debug x => _20; + debug i => _21; + debug x => _22; } } scope 3 (inlined core::slice::<impl [T]>::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull<T>; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull<T>; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::<T>::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::<T>) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::<T>) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::<T>::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::<T>) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::<impl [T]>::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) { - debug self => _13; - scope 23 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) { - debug iter => _13; + scope 19 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) { + debug self => _15; + scope 20 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) { + debug iter => _15; } } - scope 24 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull::<T> { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull::<T> { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Enumerate::<std::slice::Iter<'_, T>> { iter: _13, count: const 0_usize }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Enumerate::<std::slice::Iter<'_, T>> { iter: _15, count: const 0_usize }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_17); - StorageLive(_16); - _16 = &mut _15; - _17 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _16) -> [return: bb5, unwind: bb11]; + StorageLive(_19); + StorageLive(_18); + _18 = &mut _17; + _19 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _18) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_16); - _18 = discriminant(_17); - switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_18); + _20 = discriminant(_19); + switchInt(move _20) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_19); StorageDead(_17); - StorageDead(_15); drop(_2) -> [return: bb7, unwind continue]; } @@ -177,19 +171,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _19 = (((_17 as Some).0: (usize, &T)).0: usize); - _20 = (((_17 as Some).0: (usize, &T)).1: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_19, _20); - _23 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11]; + _21 = (((_19 as Some).0: (usize, &T)).0: usize); + _22 = (((_19 as Some).0: (usize, &T)).1: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_21, _22); + _25 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _23, move _24) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_17); + StorageDead(_24); + StorageDead(_23); + StorageDead(_19); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 471491108e0..133d6f53fce 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -4,159 +4,153 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::slice::Iter<'_, T>; - let mut _15: &mut std::slice::Iter<'_, T>; - let mut _16: std::option::Option<&T>; - let mut _17: isize; - let mut _19: &impl Fn(&T); - let mut _20: (&T,); - let _21: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::slice::Iter<'_, T>; + let mut _17: &mut std::slice::Iter<'_, T>; + let mut _18: std::option::Option<&T>; + let mut _19: isize; + let mut _21: &impl Fn(&T); + let mut _22: (&T,); + let _23: (); scope 1 { - debug iter => _14; - let _18: &T; + debug iter => _16; + let _20: &T; scope 2 { - debug x => _18; + debug x => _20; } } scope 3 (inlined core::slice::<impl [T]>::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull<T>; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull<T>; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::<T>::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _22: *mut T; - scope 14 { - scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { - debug ptr => _22; - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) { - debug self => _22; - let mut _23: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _23; - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _23; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _23; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::<T>) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::<T>) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::<T>::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::<T>) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::<impl [T]>::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) { - debug self => _13; + scope 19 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) { + debug self => _15; } bb0: { - StorageLive(_4); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull::<T> { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_22); - StorageLive(_23); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull::<T> { pointer: _10 }; - StorageDead(_23); - StorageDead(_22); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); StorageLive(_14); _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); + StorageDead(_13); + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + StorageLive(_16); + _16 = _15; goto -> bb4; } bb4: { - StorageLive(_16); - StorageLive(_15); - _15 = &mut _14; - _16 = <std::slice::Iter<'_, T> as Iterator>::next(move _15) -> [return: bb5, unwind unreachable]; + StorageLive(_18); + StorageLive(_17); + _17 = &mut _16; + _18 = <std::slice::Iter<'_, T> as Iterator>::next(move _17) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_17); + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_18); StorageDead(_16); - StorageDead(_14); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -165,18 +159,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _18 = ((_16 as Some).0: &T); - StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (_18,); - _21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind unreachable]; + _20 = ((_18 as Some).0: &T); + StorageLive(_21); + _21 = &_2; + StorageLive(_22); + _22 = (_20,); + _23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_20); - StorageDead(_19); - StorageDead(_16); + StorageDead(_22); + StorageDead(_21); + StorageDead(_18); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index bbf38aba91f..4e74253e541 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -4,159 +4,153 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::slice::Iter<'_, T>; - let mut _15: &mut std::slice::Iter<'_, T>; - let mut _16: std::option::Option<&T>; - let mut _17: isize; - let mut _19: &impl Fn(&T); - let mut _20: (&T,); - let _21: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::slice::Iter<'_, T>; + let mut _17: &mut std::slice::Iter<'_, T>; + let mut _18: std::option::Option<&T>; + let mut _19: isize; + let mut _21: &impl Fn(&T); + let mut _22: (&T,); + let _23: (); scope 1 { - debug iter => _14; - let _18: &T; + debug iter => _16; + let _20: &T; scope 2 { - debug x => _18; + debug x => _20; } } scope 3 (inlined core::slice::<impl [T]>::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull<T>; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull<T>; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::<T>::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _22: *mut T; - scope 14 { - scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { - debug ptr => _22; - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) { - debug self => _22; - let mut _23: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _23; - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _23; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _23; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::<T>) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::<T>) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::<T>::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::<T>) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::<impl [T]>::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) { - debug self => _13; + scope 19 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) { + debug self => _15; } bb0: { - StorageLive(_4); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull::<T> { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_22); - StorageLive(_23); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull::<T> { pointer: _10 }; - StorageDead(_23); - StorageDead(_22); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); StorageLive(_14); _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); + StorageDead(_13); + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + StorageLive(_16); + _16 = _15; goto -> bb4; } bb4: { - StorageLive(_16); - StorageLive(_15); - _15 = &mut _14; - _16 = <std::slice::Iter<'_, T> as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; + StorageLive(_18); + StorageLive(_17); + _17 = &mut _16; + _18 = <std::slice::Iter<'_, T> as Iterator>::next(move _17) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_15); - _17 = discriminant(_16); - switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_17); + _19 = discriminant(_18); + switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { + StorageDead(_18); StorageDead(_16); - StorageDead(_14); drop(_2) -> [return: bb7, unwind continue]; } @@ -165,18 +159,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _18 = ((_16 as Some).0: &T); - StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (_18,); - _21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind: bb11]; + _20 = ((_18 as Some).0: &T); + StorageLive(_21); + _21 = &_2; + StorageLive(_22); + _22 = (_20,); + _23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_20); - StorageDead(_19); - StorageDead(_16); + StorageDead(_22); + StorageDead(_21); + StorageDead(_18); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index f9c8ab4db60..639e1a51430 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -4,174 +4,168 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>; - let mut _15: std::iter::Rev<std::slice::Iter<'_, T>>; - let mut _16: &mut std::iter::Rev<std::slice::Iter<'_, T>>; - let mut _18: std::option::Option<&T>; - let mut _19: isize; - let mut _21: &impl Fn(&T); - let mut _22: (&T,); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Rev<std::slice::Iter<'_, T>>; + let mut _17: std::iter::Rev<std::slice::Iter<'_, T>>; + let mut _18: &mut std::iter::Rev<std::slice::Iter<'_, T>>; + let mut _20: std::option::Option<&T>; + let mut _21: isize; + let mut _23: &impl Fn(&T); + let mut _24: (&T,); + let _25: (); scope 1 { - debug iter => _15; - let _20: &T; + debug iter => _17; + let _22: &T; scope 2 { - debug x => _20; + debug x => _22; } - scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { - debug self => _16; - let mut _17: &mut std::slice::Iter<'_, T>; + scope 22 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { + debug self => _18; + let mut _19: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::<impl [T]>::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull<T>; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull<T>; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::<T>::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::<T>) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::<T>) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::<T>::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::<T>) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::<impl [T]>::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) { - debug self => _13; - scope 23 (inlined Rev::<std::slice::Iter<'_, T>>::new) { - debug iter => _13; + scope 19 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) { + debug self => _15; + scope 20 (inlined Rev::<std::slice::Iter<'_, T>>::new) { + debug iter => _15; } } - scope 24 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull::<T> { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull::<T> { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Rev::<std::slice::Iter<'_, T>> { iter: _13 }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Rev::<std::slice::Iter<'_, T>> { iter: _15 }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_18); - _16 = &mut _15; - StorageLive(_17); - _17 = &mut (_15.0: std::slice::Iter<'_, T>); - _18 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind unreachable]; + StorageLive(_20); + _18 = &mut _17; + StorageLive(_19); + _19 = &mut (_17.0: std::slice::Iter<'_, T>); + _20 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _19) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_17); - _19 = discriminant(_18); - switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_19); + _21 = discriminant(_20); + switchInt(move _21) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_18); - StorageDead(_15); + StorageDead(_20); + StorageDead(_17); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -180,18 +174,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _20 = ((_18 as Some).0: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_20,); - _23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind unreachable]; + _22 = ((_20 as Some).0: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_22,); + _25 = <impl Fn(&T) as Fn<(&T,)>>::call(move _23, move _24) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_18); + StorageDead(_24); + StorageDead(_23); + StorageDead(_20); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 65f423ac326..2237fd7dbd1 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -4,174 +4,168 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _13: std::slice::Iter<'_, T>; - let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>; - let mut _15: std::iter::Rev<std::slice::Iter<'_, T>>; - let mut _16: &mut std::iter::Rev<std::slice::Iter<'_, T>>; - let mut _18: std::option::Option<&T>; - let mut _19: isize; - let mut _21: &impl Fn(&T); - let mut _22: (&T,); - let _23: (); + let mut _15: std::slice::Iter<'_, T>; + let mut _16: std::iter::Rev<std::slice::Iter<'_, T>>; + let mut _17: std::iter::Rev<std::slice::Iter<'_, T>>; + let mut _18: &mut std::iter::Rev<std::slice::Iter<'_, T>>; + let mut _20: std::option::Option<&T>; + let mut _21: isize; + let mut _23: &impl Fn(&T); + let mut _24: (&T,); + let _25: (); scope 1 { - debug iter => _15; - let _20: &T; + debug iter => _17; + let _22: &T; scope 2 { - debug x => _20; + debug x => _22; } - scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { - debug self => _16; - let mut _17: &mut std::slice::Iter<'_, T>; + scope 22 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { + debug self => _18; + let mut _19: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::<impl [T]>::iter) { debug self => _1; scope 4 (inlined std::slice::Iter::<'_, T>::new) { debug slice => _1; - let _4: *const T; - let mut _5: bool; - let mut _6: usize; - let mut _8: usize; - let mut _9: *mut T; - let mut _11: std::ptr::NonNull<T>; - let mut _12: *const T; + let _3: usize; + let mut _5: std::ptr::NonNull<[T]>; + let mut _10: bool; + let mut _11: *mut T; + let mut _12: *mut T; + let mut _14: *const T; scope 5 { - debug ptr => _4; + debug len => _3; + let _9: std::ptr::NonNull<T>; scope 6 { - let _7: *const T; + debug ptr => _9; scope 7 { - debug end_or_len => _7; - scope 13 (inlined NonNull::<T>::new_unchecked) { - debug ptr => _9; - let mut _10: *const T; - let mut _24: *mut T; - scope 14 { - scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { - debug ptr => _24; - scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) { - debug self => _24; - let mut _25: *mut u8; - scope 17 { - scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { - debug ptr => _25; - scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) { - debug self => _25; - scope 20 { - scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) { - debug self => _25; - } - } - } - } - } - } - } + let _13: *const T; + scope 8 { + debug end_or_len => _13; + } + scope 14 (inlined invalid::<T>) { + debug addr => _3; + scope 15 { } } - } - scope 9 (inlined invalid::<T>) { - debug addr => _8; - scope 10 { + scope 16 (inlined NonNull::<T>::as_ptr) { + debug self => _9; + } + scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) { + debug self => _11; + debug count => _3; + scope 18 { + } } } - scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) { - debug self => _4; - debug count => _6; - scope 12 { + } + scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) { + debug reference => _1; + let mut _4: *const [T]; + scope 10 { + } + } + scope 11 (inlined NonNull::<[T]>::cast::<T>) { + debug self => _5; + let mut _6: *mut [T]; + let mut _7: *mut T; + let mut _8: *const T; + scope 12 { + scope 13 (inlined NonNull::<[T]>::as_ptr) { + debug self => _5; } } } } - scope 8 (inlined core::slice::<impl [T]>::as_ptr) { - debug self => _1; - let mut _3: *const [T]; - } } } - scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) { - debug self => _13; - scope 23 (inlined Rev::<std::slice::Iter<'_, T>>::new) { - debug iter => _13; + scope 19 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) { + debug self => _15; + scope 20 (inlined Rev::<std::slice::Iter<'_, T>>::new) { + debug iter => _15; } } - scope 24 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { - debug self => _14; + scope 21 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { + debug self => _16; } bb0: { - StorageLive(_13); - StorageLive(_4); + StorageLive(_15); StorageLive(_3); - _3 = &raw const (*_1); - _4 = move _3 as *const T (PtrToPtr); - StorageDead(_3); - StorageLive(_7); + StorageLive(_9); + StorageLive(_4); + StorageLive(_8); + _3 = Len((*_1)); StorageLive(_5); - _5 = const _; - switchInt(move _5) -> [0: bb1, otherwise: bb2]; + _4 = &raw const (*_1); + _5 = NonNull::<[T]> { pointer: _4 }; + StorageLive(_7); + StorageLive(_6); + _6 = _4 as *mut [T] (PtrToPtr); + _7 = move _6 as *mut T (PtrToPtr); + _8 = move _7 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_6); + StorageDead(_7); + _9 = NonNull::<T> { pointer: _8 }; + StorageDead(_5); + StorageLive(_13); + StorageLive(_10); + _10 = const _; + switchInt(move _10) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_6); - _6 = Len((*_1)); - _7 = Offset(_4, _6); - StorageDead(_6); + StorageLive(_12); + StorageLive(_11); + _11 = _8 as *mut T (PtrToPtr); + _12 = Offset(_11, _3); + StorageDead(_11); + _13 = move _12 as *const T (PointerCoercion(MutToConstPointer)); + StorageDead(_12); goto -> bb3; } bb2: { - StorageLive(_8); - _8 = Len((*_1)); - _7 = _8 as *const T (Transmute); - StorageDead(_8); + _13 = _3 as *const T (Transmute); goto -> bb3; } bb3: { - StorageDead(_5); - StorageLive(_11); - StorageLive(_9); - _9 = _4 as *mut T (PtrToPtr); - StorageLive(_10); - StorageLive(_24); - StorageLive(_25); - _10 = _9 as *const T (PointerCoercion(MutToConstPointer)); - _11 = NonNull::<T> { pointer: _10 }; - StorageDead(_25); - StorageDead(_24); StorageDead(_10); - StorageDead(_9); - StorageLive(_12); - _12 = _7; - _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_12); - StorageDead(_11); - StorageDead(_7); - StorageDead(_4); - _14 = Rev::<std::slice::Iter<'_, T>> { iter: _13 }; + StorageLive(_14); + _14 = _13; + _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> }; + StorageDead(_14); StorageDead(_13); - StorageLive(_15); - _15 = _14; + StorageDead(_8); + StorageDead(_4); + StorageDead(_9); + StorageDead(_3); + _16 = Rev::<std::slice::Iter<'_, T>> { iter: _15 }; + StorageDead(_15); + StorageLive(_17); + _17 = _16; goto -> bb4; } bb4: { - StorageLive(_18); - _16 = &mut _15; - StorageLive(_17); - _17 = &mut (_15.0: std::slice::Iter<'_, T>); - _18 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind: bb11]; + StorageLive(_20); + _18 = &mut _17; + StorageLive(_19); + _19 = &mut (_17.0: std::slice::Iter<'_, T>); + _20 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _19) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_17); - _19 = discriminant(_18); - switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_19); + _21 = discriminant(_20); + switchInt(move _21) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_18); - StorageDead(_15); + StorageDead(_20); + StorageDead(_17); drop(_2) -> [return: bb7, unwind continue]; } @@ -180,18 +174,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _20 = ((_18 as Some).0: &T); - StorageLive(_21); - _21 = &_2; - StorageLive(_22); - _22 = (_20,); - _23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11]; + _22 = ((_20 as Some).0: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (_22,); + _25 = <impl Fn(&T) as Fn<(&T,)>>::call(move _23, move _24) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_22); - StorageDead(_21); - StorageDead(_18); + StorageDead(_24); + StorageDead(_23); + StorageDead(_20); goto -> bb4; } diff --git a/tests/mir-opt/remove_storage_markers.rs b/tests/mir-opt/remove_storage_markers.rs index 6666ff3b726..27661ab3254 100644 --- a/tests/mir-opt/remove_storage_markers.rs +++ b/tests/mir-opt/remove_storage_markers.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: RemoveStorageMarkers @@ -8,6 +7,10 @@ // EMIT_MIR remove_storage_markers.main.RemoveStorageMarkers.diff fn main() { + // CHECK-LABEL: fn main( + + // CHECK-NOT: StorageDead + // CHECK-NOT: StorageLive let mut sum = 0; for i in 0..10 { sum += i; diff --git a/tests/mir-opt/retag.rs b/tests/mir-opt/retag.rs index 1e4b017dad5..554b8ece90f 100644 --- a/tests/mir-opt/retag.rs +++ b/tests/mir-opt/retag.rs @@ -28,7 +28,7 @@ impl Drop for Test { // EMIT_MIR retag.main.SimplifyCfg-elaborate-drops.after.mir // EMIT_MIR retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir -fn main() { +pub fn main() { let mut x = 0; { let v = Test(0).foo(&mut x); // just making sure we do not panic when there is a tuple struct ctor diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index e7280f14837..d2731615284 100644 --- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff +++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff @@ -66,7 +66,7 @@ _5 = ((_2 as Break).0: std::result::Result<std::convert::Infallible, i32>); StorageLive(_6); _6 = _5; - _12 = move ((_5 as Err).0: i32); + _12 = ((_5 as Err).0: i32); _0 = Result::<i32, i32>::Err(_12); StorageDead(_6); StorageDead(_2); @@ -83,7 +83,7 @@ } bb4: { - _10 = move ((_1 as Err).0: i32); + _10 = ((_1 as Err).0: i32); StorageLive(_11); _11 = Result::<Infallible, i32>::Err(_10); _2 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _11); @@ -92,7 +92,7 @@ } bb5: { - _9 = move ((_1 as Ok).0: i32); + _9 = ((_1 as Ok).0: i32); _2 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(_9); goto -> bb3; } diff --git a/tests/mir-opt/simplify_if.rs b/tests/mir-opt/simplify_if.rs index 19b5806f720..f600c059581 100644 --- a/tests/mir-opt/simplify_if.rs +++ b/tests/mir-opt/simplify_if.rs @@ -1,10 +1,13 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY #[inline(never)] fn noop() {} // EMIT_MIR simplify_if.main.SimplifyConstCondition-after-const-prop.diff fn main() { + // CHECK-LABEL: fn main( + + // CHECK: bb0: { + // CHECK-NEXT: return; if false { noop(); } diff --git a/tests/mir-opt/slice_drop_shim.rs b/tests/mir-opt/slice_drop_shim.rs index cac0a349128..037e048b3b7 100644 --- a/tests/mir-opt/slice_drop_shim.rs +++ b/tests/mir-opt/slice_drop_shim.rs @@ -1,6 +1,8 @@ // skip-filecheck -// compile-flags: -Zmir-opt-level=0 - +// compile-flags: -Zmir-opt-level=0 -Clink-dead-code +// mir-opt tests are always built as rlibs so that they seamlessly cross-compile, +// so this test only produces MIR for the drop_in_place we're looking for +// if we use -Clink-dead-code. // EMIT_MIR core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir fn main() { diff --git a/tests/mir-opt/sroa/lifetimes.rs b/tests/mir-opt/sroa/lifetimes.rs index cc5c0c9bbcd..ea04fac1571 100644 --- a/tests/mir-opt/sroa/lifetimes.rs +++ b/tests/mir-opt/sroa/lifetimes.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: ScalarReplacementOfAggregates // compile-flags: -Cpanic=abort // no-prefer-dynamic @@ -16,6 +15,10 @@ struct Foo<T: Err> { // EMIT_MIR lifetimes.foo.ScalarReplacementOfAggregates.diff fn foo<T: Err>() { + // CHECK-LABEL: fn foo( + + // CHECK-NOT: [foo:_.*]: Foo + // CHECK-NOT: Box<dyn std::fmt::Display + 'static> let foo: Foo<T> = Foo { x: Ok(Box::new(5_u32)), y: 7_u32, diff --git a/tests/mir-opt/sroa/structs.rs b/tests/mir-opt/sroa/structs.rs index 73563e12c94..5ea3795b86e 100644 --- a/tests/mir-opt/sroa/structs.rs +++ b/tests/mir-opt/sroa/structs.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: ScalarReplacementOfAggregates // compile-flags: -Cpanic=abort // no-prefer-dynamic @@ -13,28 +12,68 @@ impl Drop for Tag { fn drop(&mut self) {} } +/// Check that SROA excludes structs with a `Drop` implementation. pub fn dropping() { + // CHECK-LABEL: fn dropping( + + // CHECK: [[aggregate:_[0-9]+]]: S; + + // CHECK: bb0: { + // CHECK: [[aggregate]] = S S(Tag(0), Tag(1), Tag(2)).1; } +/// Check that SROA excludes enums. pub fn enums(a: usize) -> usize { + // CHECK-LABEL: fn enums( + + // CHECK: [[enum:_[0-9]+]]: std::option::Option<usize>; + + // CHECK: bb0: { + // CHECK: [[enum]] = Option::<usize>::Some + // CHECK: _5 = (([[enum]] as Some).0: usize) + // CHECK: _0 = _5 if let Some(a) = Some(a) { a } else { 0 } } +/// Check that SROA destructures `U`. pub fn structs(a: f32) -> f32 { + // CHECK-LABEL: fn structs( struct U { _foo: usize, a: f32, } - + // CHECK: [[ret:_0]]: f32; + // CHECK: [[struct:_[0-9]+]]: structs::U; + // CHECK: [[a_tmp:_[0-9]+]]: f32; + // CHECK: [[foo:_[0-9]+]]: usize; + // CHECK: [[a_ret:_[0-9]+]]: f32; + + // CHECK: bb0: { + // CHECK-NOT: [[struct]] + // CHECK: [[a_tmp]] = _1; + // CHECK-NOT: [[struct]] + // CHECK: [[foo]] = const 0_usize; + // CHECK-NOT: [[struct]] + // CHECK: [[a_ret]] = move [[a_tmp]]; + // CHECK-NOT: [[struct]] + // CHECK: _0 = [[a_ret]]; + // CHECK-NOT: [[struct]] U { _foo: 0, a }.a } +/// Check that SROA excludes unions. pub fn unions(a: f32) -> u32 { + // CHECK-LABEL: fn unions( union Repr { f: f32, u: u32, } + // CHECK: [[union:_[0-9]+]]: unions::Repr; + + // CHECK: bb0: { + // CHECK: [[union]] = Repr { + // CHECK: _0 = ([[union]].1: u32) unsafe { Repr { f: a }.u } } @@ -46,11 +85,21 @@ struct Foo { d: Option<isize>, } -fn g() -> u32 { - 3 -} - +/// Check that non-escaping uses of a struct are destructured. pub fn flat() { + // CHECK-LABEL: fn flat( + + // CHECK: [[struct:_[0-9]+]]: Foo; + + // CHECK: bb0: { + // CHECK: [[init_unit:_[0-9]+]] = (); + // CHECK: [[init_opt_isize:_[0-9]+]] = Option::<isize>::Some + + // CHECK: [[destr_five:_[0-9]+]] = const 5_u8; + // CHECK: [[destr_unit:_[0-9]+]] = move [[init_unit]]; + // CHECK: [[destr_a:_[0-9]+]] = const "a"; + // CHECK: [[destr_opt_isize:_[0-9]+]] = move [[init_opt_isize]]; + let Foo { a, b, c, d } = Foo { a: 5, b: (), c: "a", d: Some(-4) }; let _ = a; let _ = b; @@ -65,6 +114,10 @@ struct Escaping { c: u32, } +fn g() -> u32 { + 3 +} + fn f(a: *const u32) { println!("{}", unsafe { *a.add(2) }); } @@ -76,10 +129,38 @@ fn f(a: *const u32) { // of them to `f`. However, this would lead to a miscompilation because `b` and `c` // might no longer appear right after `a` in memory. pub fn escaping() { + // CHECK-LABEL: fn escaping( + + // CHECK: [[ptr:_[0-9]+]]: *const u32; + // CHECK: [[ref:_[0-9]+]]: &u32; + // CHECK: [[struct:_[0-9]+]]: Escaping; + // CHECK: [[a:_[0-9]+]]: u32; + + // CHECK: bb0: { + // CHECK: [[struct]] = Escaping { + // CHECK: [[ref]] = &([[struct]].0 + // CHECK: [[ptr]] = &raw const (*[[ref]]); f(&Escaping { a: 1, b: 2, c: g() }.a); } +/// Check that copies from an internal struct are destructured and reassigned to +/// the original struct. fn copies(x: Foo) { + // CHECK-LABEL: fn copies( + + // CHECK: [[external:_[0-9]+]]: Foo) -> + // CHECK: [[internal:_[0-9]+]]: Foo; + // CHECK: [[byte:_[0-9]+]]: u8; + // CHECK: [[unit:_[0-9]+]]: (); + // CHECK: [[str:_[0-9]+]]: &str; + // CHECK: [[opt_isize:_[0-9]+]]: std::option::Option<isize>; + + // CHECK: bb0: { + // CHECK: [[byte]] = ([[external]].0 + // CHECK: [[unit]] = ([[external]].1 + // CHECK: [[str]] = ([[external]].2 + // CHECK: [[opt_isize]] = ([[external]].3 + let y = x; let t = y.a; let u = y.c; @@ -87,13 +168,44 @@ fn copies(x: Foo) { let a = z.b; } +/// Check that copies from an internal struct are destructured and reassigned to +/// the original struct. fn ref_copies(x: &Foo) { + // CHECK-LABEL: fn ref_copies( + + // CHECK: [[external:_[0-9]+]]: &Foo) -> + // CHECK: [[internal:_[0-9]+]]: Foo; + // CHECK: [[byte:_[0-9]+]]: u8; + // CHECK: [[unit:_[0-9]+]]: (); + // CHECK: [[str:_[0-9]+]]: &str; + // CHECK: [[opt_isize:_[0-9]+]]: std::option::Option<isize>; + + // CHECK: bb0: { + // CHECK: [[byte]] = ((*[[external]]).0 + // CHECK: [[unit]] = ((*[[external]]).1 + // CHECK: [[str]] = ((*[[external]]).2 + // CHECK: [[opt_isize]] = ((*[[external]]).3 + let y = *x; let t = y.a; let u = y.c; } +/// Check that deaggregated assignments from constants are placed after the constant's +/// assignment. Also check that copying field accesses from the copy of the constant are +/// reassigned to copy from the constant. fn constant() { + // CHECK-LABEL: constant( + + // CHECK: [[constant:_[0-9]+]]: (usize, u8); + // CHECK: [[t:_[0-9]+]]: usize; + // CHECK: [[u:_[0-9]+]]: u8; + + // CHECK: bb0: { + // CHECK-NOT: [[constant]] + // CHECK: [[constant]] = const + // CHECK: [[t]] = move ([[constant]].0: usize) + // CHECK: [[u]] = move ([[constant]].1: u8) const U: (usize, u8) = (5, 9); let y = U; let t = y.0; @@ -101,6 +213,7 @@ fn constant() { } fn main() { + // CHECK-LABEL: fn main( dropping(); enums(5); structs(5.); diff --git a/tests/mir-opt/unusual_item_types.rs b/tests/mir-opt/unusual_item_types.rs index 49b663b4f82..fa6ba515473 100644 --- a/tests/mir-opt/unusual_item_types.rs +++ b/tests/mir-opt/unusual_item_types.rs @@ -23,7 +23,7 @@ enum E { V = 5, } -fn main() { +pub fn main() { let f = Test::X as fn(usize) -> Test; // EMIT_MIR core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir let v = Vec::<i32>::new(); diff --git a/tests/rustdoc-ui/issues/issue-102986.stderr b/tests/rustdoc-ui/issues/issue-102986.stderr index 996eb41c492..d91f93f394a 100644 --- a/tests/rustdoc-ui/issues/issue-102986.stderr +++ b/tests/rustdoc-ui/issues/issue-102986.stderr @@ -6,8 +6,8 @@ LL | y: (typeof("hey"),), | help: consider replacing `typeof(...)` with an actual type | -LL | y: (&'static str,), - | ~~~~~~~~~~~~ +LL | y: (&str,), + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/issues/issue-120444-1.rs b/tests/rustdoc-ui/issues/issue-120444-1.rs new file mode 100644 index 00000000000..25d0111a7b7 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-1.rs @@ -0,0 +1,17 @@ +// compile-flags: --document-private-items + +#![deny(rustdoc::redundant_explicit_links)] + +mod webdavfs { + pub struct A; + pub struct B; +} + +/// [`Vfs`][crate::Vfs] +pub use webdavfs::A; +//~^^ error: redundant explicit link target + +/// [`Vfs`] +pub use webdavfs::B; + +pub struct Vfs; diff --git a/tests/rustdoc-ui/issues/issue-120444-1.stderr b/tests/rustdoc-ui/issues/issue-120444-1.stderr new file mode 100644 index 00000000000..7bc56b4263f --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-1.stderr @@ -0,0 +1,22 @@ +error: redundant explicit link target + --> $DIR/issue-120444-1.rs:10:13 + | +LL | /// [`Vfs`][crate::Vfs] + | ----- ^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +note: the lint level is defined here + --> $DIR/issue-120444-1.rs:3:9 + | +LL | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove explicit link target + | +LL | /// [`Vfs`] + | ~~~~~~~ + +error: aborting due to 1 previous error + diff --git a/tests/rustdoc-ui/issues/issue-120444-2.rs b/tests/rustdoc-ui/issues/issue-120444-2.rs new file mode 100644 index 00000000000..d13bf884624 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-2.rs @@ -0,0 +1,17 @@ +// compile-flags: --document-private-items + +#![deny(rustdoc::redundant_explicit_links)] + +pub mod webdavfs { + pub struct A; + pub struct B; +} + +/// [`Vfs`][crate::Vfs] +pub use webdavfs::A; +//~^^ error: redundant explicit link target + +/// [`Vfs`] +pub use webdavfs::B; + +pub struct Vfs; diff --git a/tests/rustdoc-ui/issues/issue-120444-2.stderr b/tests/rustdoc-ui/issues/issue-120444-2.stderr new file mode 100644 index 00000000000..310bf08e2b5 --- /dev/null +++ b/tests/rustdoc-ui/issues/issue-120444-2.stderr @@ -0,0 +1,22 @@ +error: redundant explicit link target + --> $DIR/issue-120444-2.rs:10:13 + | +LL | /// [`Vfs`][crate::Vfs] + | ----- ^^^^^^^^^^ explicit target is redundant + | | + | because label contains path that resolves to same destination + | + = note: when a link's destination is not specified, + the label is used to resolve intra-doc links +note: the lint level is defined here + --> $DIR/issue-120444-2.rs:3:9 + | +LL | #![deny(rustdoc::redundant_explicit_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove explicit link target + | +LL | /// [`Vfs`] + | ~~~~~~~ + +error: aborting due to 1 previous error + diff --git a/tests/rustdoc/jump-to-non-local-method.rs b/tests/rustdoc/jump-to-non-local-method.rs new file mode 100644 index 00000000000..7767b92fbe5 --- /dev/null +++ b/tests/rustdoc/jump-to-non-local-method.rs @@ -0,0 +1,48 @@ +// compile-flags: -Zunstable-options --generate-link-to-definition + +#![crate_name = "foo"] + +// @has 'src/foo/jump-to-non-local-method.rs.html' + +// @has - '//a[@href="{{channel}}/core/sync/atomic/struct.AtomicIsize.html"]' 'std::sync::atomic::AtomicIsize' +use std::sync::atomic::AtomicIsize; +// @has - '//a[@href="{{channel}}/std/io/trait.Read.html"]' 'std::io::Read' +use std::io::Read; +// @has - '//a[@href="{{channel}}/std/io/index.html"]' 'std::io' +use std::io; +// @has - '//a[@href="{{channel}}/std/process/fn.exit.html"]' 'std::process::exit' +use std::process::exit; +use std::cmp::Ordering; +use std::marker::PhantomData; + +pub fn bar2<T: Read>(readable: T) { + // @has - '//a[@href="{{channel}}/std/io/trait.Read.html#tymethod.read"]' 'read' + let _ = readable.read(&mut []); +} + +pub fn bar() { + // @has - '//a[@href="{{channel}}/core/sync/atomic/struct.AtomicIsize.html#method.new"]' 'AtomicIsize::new' + let _ = AtomicIsize::new(0); + // @has - '//a[@href="#48"]' 'local_private' + local_private(); +} + +pub fn extern_call() { + // @has - '//a[@href="{{channel}}/std/process/fn.exit.html"]' 'exit' + exit(0); +} + +pub fn macro_call() -> Result<(), ()> { + // @has - '//a[@href="{{channel}}/core/macro.try.html"]' 'try!' + try!(Err(())); + Ok(()) +} + +pub fn variant() { + // @has - '//a[@href="{{channel}}/core/cmp/enum.Ordering.html#variant.Less"]' 'Ordering::Less' + let _ = Ordering::Less; + // @has - '//a[@href="{{channel}}/core/marker/struct.PhantomData.html"]' 'PhantomData' + let _: PhantomData::<usize> = PhantomData; +} + +fn local_private() {} diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index ab42d3b8c1e..5a2099865d6 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -14,7 +14,7 @@ extern crate rustc_span; use rustc_errors::{ AddToDiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, DiagCtxt, - IntoDiagnostic, Level, SubdiagnosticMessage, + IntoDiagnostic, Level, SubdiagnosticMessageOp, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -55,9 +55,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for TranslatableInIntoDiagn pub struct UntranslatableInAddToDiagnostic; impl AddToDiagnostic for UntranslatableInAddToDiagnostic { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { diag.note("untranslatable diagnostic"); //~^ ERROR diagnostics should be created using translatable messages @@ -67,10 +65,7 @@ impl AddToDiagnostic for UntranslatableInAddToDiagnostic { pub struct TranslatableInAddToDiagnostic; impl AddToDiagnostic for TranslatableInAddToDiagnostic { - fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with<F: SubdiagnosticMessageOp>(self, diag: &mut Diagnostic, _: F) { diag.note(crate::fluent_generated::no_crate_note); } } diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr index f70240ecf17..108b7c8ea9c 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr @@ -11,13 +11,13 @@ LL | #![deny(rustc::untranslatable_diagnostic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:62:14 + --> $DIR/diagnostics.rs:60:14 | LL | diag.note("untranslatable diagnostic"); | ^^^^ error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls - --> $DIR/diagnostics.rs:79:21 + --> $DIR/diagnostics.rs:74:21 | LL | let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example); | ^^^^^^^^^^ @@ -29,13 +29,13 @@ LL | #![deny(rustc::diagnostic_outside_of_impl)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls - --> $DIR/diagnostics.rs:82:21 + --> $DIR/diagnostics.rs:77:21 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:82:21 + --> $DIR/diagnostics.rs:77:21 | LL | let _diag = dcx.struct_err("untranslatable diagnostic"); | ^^^^^^^^^^ diff --git a/tests/ui-fulldeps/rustc_encodable_hygiene.rs b/tests/ui-fulldeps/rustc_encodable_hygiene.rs index bec7930d462..36c684a131e 100644 --- a/tests/ui-fulldeps/rustc_encodable_hygiene.rs +++ b/tests/ui-fulldeps/rustc_encodable_hygiene.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(rustc_private)] diff --git a/tests/ui/anon-params/anon-params-deprecated.fixed b/tests/ui/anon-params/anon-params-deprecated.fixed index c09e2077084..8ec1d41a709 100644 --- a/tests/ui/anon-params/anon-params-deprecated.fixed +++ b/tests/ui/anon-params/anon-params-deprecated.fixed @@ -5,6 +5,7 @@ // edition:2015 // run-rustfix +#[allow(dead_code)] trait T { fn foo(_: i32); //~ WARNING anonymous parameters are deprecated //~| WARNING this is accepted in the current edition diff --git a/tests/ui/anon-params/anon-params-deprecated.rs b/tests/ui/anon-params/anon-params-deprecated.rs index 6f7385da040..108ba60a02f 100644 --- a/tests/ui/anon-params/anon-params-deprecated.rs +++ b/tests/ui/anon-params/anon-params-deprecated.rs @@ -5,6 +5,7 @@ // edition:2015 // run-rustfix +#[allow(dead_code)] trait T { fn foo(i32); //~ WARNING anonymous parameters are deprecated //~| WARNING this is accepted in the current edition diff --git a/tests/ui/anon-params/anon-params-deprecated.stderr b/tests/ui/anon-params/anon-params-deprecated.stderr index 691e2c79512..541cb004b5b 100644 --- a/tests/ui/anon-params/anon-params-deprecated.stderr +++ b/tests/ui/anon-params/anon-params-deprecated.stderr @@ -1,5 +1,5 @@ warning: anonymous parameters are deprecated and will be removed in the next edition - --> $DIR/anon-params-deprecated.rs:9:12 + --> $DIR/anon-params-deprecated.rs:10:12 | LL | fn foo(i32); | ^^^ help: try naming the parameter or explicitly ignoring it: `_: i32` @@ -13,7 +13,7 @@ LL | #![warn(anonymous_parameters)] | ^^^^^^^^^^^^^^^^^^^^ warning: anonymous parameters are deprecated and will be removed in the next edition - --> $DIR/anon-params-deprecated.rs:12:30 + --> $DIR/anon-params-deprecated.rs:13:30 | LL | fn bar_with_default_impl(String, String) {} | ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String` @@ -22,7 +22,7 @@ LL | fn bar_with_default_impl(String, String) {} = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686> warning: anonymous parameters are deprecated and will be removed in the next edition - --> $DIR/anon-params-deprecated.rs:12:38 + --> $DIR/anon-params-deprecated.rs:13:38 | LL | fn bar_with_default_impl(String, String) {} | ^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: String` diff --git a/tests/ui/asm/bad-template.aarch64.stderr b/tests/ui/asm/bad-template.aarch64.stderr index 4ffcd2303b7..b18946d7c6d 100644 --- a/tests/ui/asm/bad-template.aarch64.stderr +++ b/tests/ui/asm/bad-template.aarch64.stderr @@ -1,5 +1,5 @@ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:27:15 + --> $DIR/bad-template.rs:30:15 | LL | asm!("{}"); | ^^ from here @@ -7,7 +7,7 @@ LL | asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:29:15 + --> $DIR/bad-template.rs:32:15 | LL | asm!("{1}", in(reg) foo); | ^^^ from here @@ -15,7 +15,7 @@ LL | asm!("{1}", in(reg) foo); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:29:21 + --> $DIR/bad-template.rs:32:21 | LL | asm!("{1}", in(reg) foo); | ^^^^^^^^^^^ argument never used @@ -23,13 +23,13 @@ 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:32:16 + --> $DIR/bad-template.rs:35:16 | LL | asm!("{a}"); | ^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:34:15 + --> $DIR/bad-template.rs:37:15 | LL | asm!("{}", a = in(reg) foo); | ^^ --------------- named argument @@ -38,13 +38,13 @@ LL | asm!("{}", a = in(reg) foo); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:34:20 + --> $DIR/bad-template.rs:37:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:34:20 + --> $DIR/bad-template.rs:37:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -52,7 +52,7 @@ LL | asm!("{}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:37:15 + --> $DIR/bad-template.rs:40:15 | LL | asm!("{1}", a = in(reg) foo); | ^^^ from here @@ -60,7 +60,7 @@ LL | asm!("{1}", a = in(reg) foo); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:37:21 + --> $DIR/bad-template.rs:40:21 | LL | asm!("{1}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -68,7 +68,7 @@ LL | asm!("{1}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:44:15 + --> $DIR/bad-template.rs:47:15 | LL | asm!("{}", in("x0") foo); | ^^ ------------ explicit register argument @@ -77,24 +77,24 @@ LL | asm!("{}", in("x0") foo); | = note: no positional arguments were given note: explicit register arguments cannot be used in the asm template - --> $DIR/bad-template.rs:44:20 + --> $DIR/bad-template.rs:47:20 | LL | asm!("{}", in("x0") foo); | ^^^^^^^^^^^^ help: use the register name directly in the assembly code - --> $DIR/bad-template.rs:44:20 + --> $DIR/bad-template.rs:47:20 | LL | asm!("{}", in("x0") foo); | ^^^^^^^^^^^^ error: asm template modifier must be a single character - --> $DIR/bad-template.rs:46:17 + --> $DIR/bad-template.rs:49:17 | LL | asm!("{:foo}", in(reg) foo); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:49:18 + --> $DIR/bad-template.rs:52:18 | LL | asm!("", in(reg) 0, in(reg) 1); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -104,7 +104,7 @@ LL | asm!("", in(reg) 0, in(reg) 1); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:55:14 + --> $DIR/bad-template.rs:58:14 | LL | global_asm!("{}"); | ^^ from here @@ -112,7 +112,7 @@ LL | global_asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:57:14 + --> $DIR/bad-template.rs:60:14 | LL | global_asm!("{1}", const FOO); | ^^^ from here @@ -120,7 +120,7 @@ LL | global_asm!("{1}", const FOO); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:57:20 + --> $DIR/bad-template.rs:60:20 | LL | global_asm!("{1}", const FOO); | ^^^^^^^^^ argument never used @@ -128,13 +128,13 @@ 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:60:15 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); | ^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:62:14 + --> $DIR/bad-template.rs:65:14 | LL | global_asm!("{}", a = const FOO); | ^^ ------------- named argument @@ -143,13 +143,13 @@ LL | global_asm!("{}", a = const FOO); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:62:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:62:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -157,7 +157,7 @@ LL | global_asm!("{}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:65:14 + --> $DIR/bad-template.rs:68:14 | LL | global_asm!("{1}", a = const FOO); | ^^^ from here @@ -165,7 +165,7 @@ LL | global_asm!("{1}", a = const FOO); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:65:20 + --> $DIR/bad-template.rs:68:20 | LL | global_asm!("{1}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -173,13 +173,13 @@ LL | global_asm!("{1}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: asm template modifier must be a single character - --> $DIR/bad-template.rs:68:16 + --> $DIR/bad-template.rs:71:16 | LL | global_asm!("{:foo}", const FOO); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:70:17 + --> $DIR/bad-template.rs:73:17 | LL | global_asm!("", const FOO, const FOO); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -189,7 +189,7 @@ LL | global_asm!("", const FOO, const FOO); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` warning: formatting may not be suitable for sub-register argument - --> $DIR/bad-template.rs:46:15 + --> $DIR/bad-template.rs:49:15 | LL | asm!("{:foo}", in(reg) foo); | ^^^^^^ --- for this argument diff --git a/tests/ui/asm/bad-template.rs b/tests/ui/asm/bad-template.rs index a6a233a36ec..b70da4921c2 100644 --- a/tests/ui/asm/bad-template.rs +++ b/tests/ui/asm/bad-template.rs @@ -21,6 +21,9 @@ macro_rules! global_asm { #[lang = "sized"] trait Sized {} +#[lang = "copy"] +trait Copy {} + fn main() { let mut foo = 0; unsafe { diff --git a/tests/ui/asm/bad-template.x86_64.stderr b/tests/ui/asm/bad-template.x86_64.stderr index 52a7789b98c..2f584c30a32 100644 --- a/tests/ui/asm/bad-template.x86_64.stderr +++ b/tests/ui/asm/bad-template.x86_64.stderr @@ -1,5 +1,5 @@ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:27:15 + --> $DIR/bad-template.rs:30:15 | LL | asm!("{}"); | ^^ from here @@ -7,7 +7,7 @@ LL | asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:29:15 + --> $DIR/bad-template.rs:32:15 | LL | asm!("{1}", in(reg) foo); | ^^^ from here @@ -15,7 +15,7 @@ LL | asm!("{1}", in(reg) foo); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:29:21 + --> $DIR/bad-template.rs:32:21 | LL | asm!("{1}", in(reg) foo); | ^^^^^^^^^^^ argument never used @@ -23,13 +23,13 @@ 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:32:16 + --> $DIR/bad-template.rs:35:16 | LL | asm!("{a}"); | ^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:34:15 + --> $DIR/bad-template.rs:37:15 | LL | asm!("{}", a = in(reg) foo); | ^^ --------------- named argument @@ -38,13 +38,13 @@ LL | asm!("{}", a = in(reg) foo); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:34:20 + --> $DIR/bad-template.rs:37:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:34:20 + --> $DIR/bad-template.rs:37:20 | LL | asm!("{}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -52,7 +52,7 @@ LL | asm!("{}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:37:15 + --> $DIR/bad-template.rs:40:15 | LL | asm!("{1}", a = in(reg) foo); | ^^^ from here @@ -60,7 +60,7 @@ LL | asm!("{1}", a = in(reg) foo); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:37:21 + --> $DIR/bad-template.rs:40:21 | LL | asm!("{1}", a = in(reg) foo); | ^^^^^^^^^^^^^^^ named argument never used @@ -68,7 +68,7 @@ LL | asm!("{1}", a = in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:41:15 + --> $DIR/bad-template.rs:44:15 | LL | asm!("{}", in("eax") foo); | ^^ ------------- explicit register argument @@ -77,24 +77,24 @@ LL | asm!("{}", in("eax") foo); | = note: no positional arguments were given note: explicit register arguments cannot be used in the asm template - --> $DIR/bad-template.rs:41:20 + --> $DIR/bad-template.rs:44:20 | LL | asm!("{}", in("eax") foo); | ^^^^^^^^^^^^^ help: use the register name directly in the assembly code - --> $DIR/bad-template.rs:41:20 + --> $DIR/bad-template.rs:44:20 | LL | asm!("{}", in("eax") foo); | ^^^^^^^^^^^^^ error: asm template modifier must be a single character - --> $DIR/bad-template.rs:46:17 + --> $DIR/bad-template.rs:49:17 | LL | asm!("{:foo}", in(reg) foo); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:49:18 + --> $DIR/bad-template.rs:52:18 | LL | asm!("", in(reg) 0, in(reg) 1); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -104,7 +104,7 @@ LL | asm!("", in(reg) 0, in(reg) 1); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:55:14 + --> $DIR/bad-template.rs:58:14 | LL | global_asm!("{}"); | ^^ from here @@ -112,7 +112,7 @@ LL | global_asm!("{}"); = note: no arguments were given error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:57:14 + --> $DIR/bad-template.rs:60:14 | LL | global_asm!("{1}", const FOO); | ^^^ from here @@ -120,7 +120,7 @@ LL | global_asm!("{1}", const FOO); = note: there is 1 argument error: argument never used - --> $DIR/bad-template.rs:57:20 + --> $DIR/bad-template.rs:60:20 | LL | global_asm!("{1}", const FOO); | ^^^^^^^^^ argument never used @@ -128,13 +128,13 @@ 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:60:15 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); | ^ error: invalid reference to argument at index 0 - --> $DIR/bad-template.rs:62:14 + --> $DIR/bad-template.rs:65:14 | LL | global_asm!("{}", a = const FOO); | ^^ ------------- named argument @@ -143,13 +143,13 @@ LL | global_asm!("{}", a = const FOO); | = note: no positional arguments were given note: named arguments cannot be referenced by position - --> $DIR/bad-template.rs:62:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ error: named argument never used - --> $DIR/bad-template.rs:62:19 + --> $DIR/bad-template.rs:65:19 | LL | global_asm!("{}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -157,7 +157,7 @@ LL | global_asm!("{}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: invalid reference to argument at index 1 - --> $DIR/bad-template.rs:65:14 + --> $DIR/bad-template.rs:68:14 | LL | global_asm!("{1}", a = const FOO); | ^^^ from here @@ -165,7 +165,7 @@ LL | global_asm!("{1}", a = const FOO); = note: no positional arguments were given error: named argument never used - --> $DIR/bad-template.rs:65:20 + --> $DIR/bad-template.rs:68:20 | LL | global_asm!("{1}", a = const FOO); | ^^^^^^^^^^^^^ named argument never used @@ -173,13 +173,13 @@ LL | global_asm!("{1}", a = const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"` error: asm template modifier must be a single character - --> $DIR/bad-template.rs:68:16 + --> $DIR/bad-template.rs:71:16 | LL | global_asm!("{:foo}", const FOO); | ^^^ error: multiple unused asm arguments - --> $DIR/bad-template.rs:70:17 + --> $DIR/bad-template.rs:73:17 | LL | global_asm!("", const FOO, const FOO); | ^^^^^^^^^ ^^^^^^^^^ argument never used @@ -189,7 +189,7 @@ LL | global_asm!("", const FOO, const FOO); = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"` warning: formatting may not be suitable for sub-register argument - --> $DIR/bad-template.rs:46:15 + --> $DIR/bad-template.rs:49:15 | LL | asm!("{:foo}", in(reg) foo); | ^^^^^^ --- for this argument diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index 2f3716ca77f..b18d01730f2 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -81,13 +81,15 @@ pub extern "C" fn missing_assembly() { #[naked] pub extern "C" fn too_many_asm_blocks() { //~^ ERROR naked functions must contain a single asm block - asm!(""); - //~^ ERROR asm in naked functions must use `noreturn` option - asm!(""); - //~^ ERROR asm in naked functions must use `noreturn` option - asm!(""); - //~^ ERROR asm in naked functions must use `noreturn` option - asm!("", options(noreturn)); + unsafe { + asm!(""); + //~^ ERROR asm in naked functions must use `noreturn` option + asm!(""); + //~^ ERROR asm in naked functions must use `noreturn` option + asm!(""); + //~^ ERROR asm in naked functions must use `noreturn` option + asm!("", options(noreturn)); + } } pub fn outer(x: u32) -> extern "C" fn(usize) -> usize { diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr index f90967fbe6e..6613c3dfdba 100644 --- a/tests/ui/asm/naked-functions.stderr +++ b/tests/ui/asm/naked-functions.stderr @@ -1,23 +1,23 @@ error: asm with the `pure` option must have at least one output - --> $DIR/naked-functions.rs:111:14 + --> $DIR/naked-functions.rs:113:14 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:203:5 + --> $DIR/naked-functions.rs:205:5 | LL | compile_error!("this is a user specified error") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this is a user specified error - --> $DIR/naked-functions.rs:209:5 + --> $DIR/naked-functions.rs:211:5 | LL | compile_error!("this is a user specified error"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: asm template must be a string literal - --> $DIR/naked-functions.rs:216:10 + --> $DIR/naked-functions.rs:218:10 | LL | asm!(invalid_syntax) | ^^^^^^^^^^^^^^ @@ -142,37 +142,37 @@ LL | pub extern "C" fn missing_assembly() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:84:5 + --> $DIR/naked-functions.rs:85:9 | -LL | asm!(""); - | ^^^^^^^^ +LL | asm!(""); + | ^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn)); - | +++++++++++++++++++ +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:86:5 + --> $DIR/naked-functions.rs:87:9 | -LL | asm!(""); - | ^^^^^^^^ +LL | asm!(""); + | ^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn)); - | +++++++++++++++++++ +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:88:5 + --> $DIR/naked-functions.rs:89:9 | -LL | asm!(""); - | ^^^^^^^^ +LL | asm!(""); + | ^^^^^^^^ | help: consider specifying that the asm block is responsible for returning from the function | -LL | asm!("", options(noreturn)); - | +++++++++++++++++++ +LL | asm!("", options(noreturn)); + | +++++++++++++++++++ error[E0787]: naked functions must contain a single asm block --> $DIR/naked-functions.rs:82:1 @@ -180,17 +180,17 @@ error[E0787]: naked functions must contain a single asm block LL | pub extern "C" fn too_many_asm_blocks() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... -LL | asm!(""); - | -------- multiple asm blocks are unsupported in naked functions +LL | asm!(""); + | -------- multiple asm blocks are unsupported in naked functions LL | -LL | asm!(""); - | -------- multiple asm blocks are unsupported in naked functions +LL | asm!(""); + | -------- multiple asm blocks are unsupported in naked functions LL | -LL | asm!("", options(noreturn)); - | --------------------------- multiple asm blocks are unsupported in naked functions +LL | asm!("", options(noreturn)); + | --------------------------- multiple asm blocks are unsupported in naked functions error: referencing function parameters is not allowed in naked functions - --> $DIR/naked-functions.rs:97:11 + --> $DIR/naked-functions.rs:99:11 | LL | *&y | ^ @@ -198,7 +198,7 @@ LL | *&y = help: follow the calling convention in asm block to use parameters error[E0787]: naked functions must contain a single asm block - --> $DIR/naked-functions.rs:95:5 + --> $DIR/naked-functions.rs:97:5 | LL | pub extern "C" fn inner(y: usize) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -207,19 +207,19 @@ LL | *&y | --- non-asm is unsupported in naked functions error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags` - --> $DIR/naked-functions.rs:105:5 + --> $DIR/naked-functions.rs:107:5 | LL | asm!("", options(nomem, preserves_flags, noreturn)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly` - --> $DIR/naked-functions.rs:111:5 + --> $DIR/naked-functions.rs:113:5 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0787]: asm in naked functions must use `noreturn` option - --> $DIR/naked-functions.rs:111:5 + --> $DIR/naked-functions.rs:113:5 | LL | asm!("", options(readonly, nostack), options(pure)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -230,13 +230,13 @@ LL | asm!("", options(noreturn), options(readonly, nostack), options(pure)); | +++++++++++++++++++ error[E0787]: asm options unsupported in naked functions: `may_unwind` - --> $DIR/naked-functions.rs:119:5 + --> $DIR/naked-functions.rs:121:5 | LL | asm!("", options(noreturn, may_unwind)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:124:1 + --> $DIR/naked-functions.rs:126:1 | LL | pub unsafe fn default_abi() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -244,43 +244,43 @@ LL | pub unsafe fn default_abi() { = note: `#[warn(undefined_naked_function_abi)]` on by default warning: Rust ABI is unsupported in naked functions - --> $DIR/naked-functions.rs:130:1 + --> $DIR/naked-functions.rs:132:1 | LL | pub unsafe fn rust_abi() { | ^^^^^^^^^^^^^^^^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:170:1 + --> $DIR/naked-functions.rs:172:1 | LL | #[inline] | ^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:177:1 + --> $DIR/naked-functions.rs:179:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:184:1 + --> $DIR/naked-functions.rs:186:1 | LL | #[inline(never)] | ^^^^^^^^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:191:1 + --> $DIR/naked-functions.rs:193:1 | LL | #[inline] | ^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:193:1 + --> $DIR/naked-functions.rs:195:1 | LL | #[inline(always)] | ^^^^^^^^^^^^^^^^^ error: naked functions cannot be inlined - --> $DIR/naked-functions.rs:195:1 + --> $DIR/naked-functions.rs:197:1 | LL | #[inline(never)] | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/associated-consts/associated-const-outer-ty-refs.rs b/tests/ui/associated-consts/associated-const-outer-ty-refs.rs index f32ca0cccfc..d5e9a2bde00 100644 --- a/tests/ui/associated-consts/associated-const-outer-ty-refs.rs +++ b/tests/ui/associated-consts/associated-const-outer-ty-refs.rs @@ -1,4 +1,5 @@ -// run-pass +// check-pass + trait Lattice { const BOTTOM: Self; } diff --git a/tests/ui/associated-consts/associated-const-type-parameters.rs b/tests/ui/associated-consts/associated-const-type-parameters.rs index b62d47458be..a233b09ff89 100644 --- a/tests/ui/associated-consts/associated-const-type-parameters.rs +++ b/tests/ui/associated-consts/associated-const-type-parameters.rs @@ -27,7 +27,7 @@ fn sub<A: Foo, B: Foo>() -> i32 { A::X - B::X } -trait Bar: Foo { +trait Bar: Foo { //~ WARN trait `Bar` is never used const Y: i32 = Self::X; } diff --git a/tests/ui/associated-consts/associated-const-type-parameters.stderr b/tests/ui/associated-consts/associated-const-type-parameters.stderr new file mode 100644 index 00000000000..6ee2a5de1b6 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameters.stderr @@ -0,0 +1,10 @@ +warning: trait `Bar` is never used + --> $DIR/associated-const-type-parameters.rs:30:7 + | +LL | trait Bar: Foo { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-consts/issue-105330.rs b/tests/ui/associated-consts/issue-105330.rs index 285e89cce49..6c6dae864f3 100644 --- a/tests/ui/associated-consts/issue-105330.rs +++ b/tests/ui/associated-consts/issue-105330.rs @@ -14,5 +14,6 @@ fn foo<A: TraitWAssocConst<A=32>>() { //~ ERROR E0658 fn main<A: TraitWAssocConst<A=32>>() { //~^ ERROR E0658 + //~| ERROR E0131 foo::<Demo>(); } diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr index 452367bed12..b4c021d0f4f 100644 --- a/tests/ui/associated-consts/issue-105330.stderr +++ b/tests/ui/associated-consts/issue-105330.stderr @@ -43,7 +43,13 @@ LL | impl TraitWAssocConst for impl Demo { | = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error: aborting due to 5 previous errors +error[E0131]: `main` function is not allowed to have generic parameters + --> $DIR/issue-105330.rs:15:8 + | +LL | fn main<A: TraitWAssocConst<A=32>>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` cannot have generic parameters + +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0404, E0562, E0658. -For more information about an error, try `rustc --explain E0404`. +Some errors have detailed explanations: E0131, E0404, E0562, E0658. +For more information about an error, try `rustc --explain E0131`. diff --git a/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs b/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs index d180de9be3b..1c48aadecce 100644 --- a/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs +++ b/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.rs @@ -1,5 +1,4 @@ -// NOTE: rustc cannot currently handle bounds of the form `for<'a> <Foo as Bar<'a>>::Assoc: Baz`. -// This should hopefully be fixed with Chalk. +// check-pass #![feature(associated_type_bounds)] @@ -24,9 +23,6 @@ impl<'a, 'b> Lam<&'a &'b u8> for L2 { trait Case1 { type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>; - //~^ ERROR `<<Self as Case1>::C as Iterator>::Item` is not an iterator - //~| ERROR `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely - //~| ERROR `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely } pub struct S1; @@ -35,33 +31,17 @@ impl Case1 for S1 { } fn assume_case1<T: Case1>() { - fn assert_a<_0, A>() - where - A: Iterator<Item = _0>, - _0: Debug, - { - } - assert_a::<_, T::A>(); - - fn assert_b<_0, B>() - where - B: Iterator<Item = _0>, - _0: 'static, - { - } - assert_b::<_, T::B>(); - - fn assert_c<_0, _1, _2, C>() + fn assert_c<_1, _2, C>() where C: Clone + Iterator<Item = _2>, _2: Send + Iterator<Item = _1>, - _1: for<'a> Lam<&'a u8, App = _0>, - _0: Debug, + _1: for<'a> Lam<&'a u8>, + for<'a> <_1 as Lam<&'a u8>>::App: Debug, { } - assert_c::<_, _, _, T::C>(); + assert_c::<_, _, T::C>(); } fn main() { - assume_case1(S1); + assume_case1::<S1>(); } diff --git a/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr deleted file mode 100644 index c23e54594ee..00000000000 --- a/tests/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error[E0277]: `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely - --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:36 - | -LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>; - | ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be sent between threads safely - | - = help: the trait `Send` is not implemented for `<<Self as Case1>::C as Iterator>::Item` -help: consider further restricting the associated type - | -LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Send { - | ++++++++++++++++++++++++++++++++++++++++++++++++++ - -error[E0277]: `<<Self as Case1>::C as Iterator>::Item` is not an iterator - --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:43 - | -LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `<<Self as Case1>::C as Iterator>::Item` is not an iterator - | - = help: the trait `Iterator` is not implemented for `<<Self as Case1>::C as Iterator>::Item` -help: consider further restricting the associated type - | -LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Iterator { - | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -error[E0277]: `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely - --> $DIR/bad-bounds-on-assoc-in-trait.rs:26:93 - | -LL | type C: Clone + Iterator<Item: Send + Iterator<Item: for<'a> Lam<&'a u8, App: Debug>> + Sync>; - | ^^^^ `<<Self as Case1>::C as Iterator>::Item` cannot be shared between threads safely - | - = help: the trait `Sync` is not implemented for `<<Self as Case1>::C as Iterator>::Item` -help: consider further restricting the associated type - | -LL | trait Case1 where <<Self as Case1>::C as Iterator>::Item: Sync { - | ++++++++++++++++++++++++++++++++++++++++++++++++++ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs b/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs index 23be735010b..7bc2970ade9 100644 --- a/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs +++ b/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.rs @@ -1,3 +1,5 @@ +// check-pass + #![feature(associated_type_bounds)] use std::fmt::Debug; @@ -16,8 +18,6 @@ impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; } trait Case1 { type A: Iterator<Item: Debug>; - //~^ ERROR `<<Self as Case1>::A as Iterator>::Item` doesn't implement `Debug` - type B: Iterator<Item: 'static>; } @@ -33,7 +33,6 @@ impl Case1 for S1 { // bounds of `Out`, but trait selection can't find the bound since it applies // to a type other than `Self::Out`. pub trait Foo { type Out: Baz<Assoc: Default>; } -//~^ ERROR trait bound `<<Self as Foo>::Out as Baz>::Assoc: Default` is not satisfied pub trait Baz { type Assoc; } #[derive(Default)] diff --git a/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr b/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr deleted file mode 100644 index 4e2313bd4e4..00000000000 --- a/tests/ui/associated-type-bounds/bounds-on-assoc-in-trait.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0277]: `<<Self as Case1>::A as Iterator>::Item` doesn't implement `Debug` - --> $DIR/bounds-on-assoc-in-trait.rs:18:28 - | -LL | type A: Iterator<Item: Debug>; - | ^^^^^ `<<Self as Case1>::A as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = help: the trait `Debug` is not implemented for `<<Self as Case1>::A as Iterator>::Item` -help: consider further restricting the associated type - | -LL | trait Case1 where <<Self as Case1>::A as Iterator>::Item: Debug { - | +++++++++++++++++++++++++++++++++++++++++++++++++++ - -error[E0277]: the trait bound `<<Self as Foo>::Out as Baz>::Assoc: Default` is not satisfied - --> $DIR/bounds-on-assoc-in-trait.rs:35:38 - | -LL | pub trait Foo { type Out: Baz<Assoc: Default>; } - | ^^^^^^^ the trait `Default` is not implemented for `<<Self as Foo>::Out as Baz>::Assoc` - | -help: consider further restricting the associated type - | -LL | pub trait Foo where <<Self as Foo>::Out as Baz>::Assoc: Default { type Out: Baz<Assoc: Default>; } - | +++++++++++++++++++++++++++++++++++++++++++++++++ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-type-bounds/duplicate.rs b/tests/ui/associated-type-bounds/duplicate.rs index 160b524c881..036f8ede1b3 100644 --- a/tests/ui/associated-type-bounds/duplicate.rs +++ b/tests/ui/associated-type-bounds/duplicate.rs @@ -251,13 +251,10 @@ where trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] - //~| ERROR `<<Self as TRA1>::A as Iterator>::Item` cannot be sent between threads safely - //~| ERROR the trait bound `<<Self as TRA1>::A as Iterator>::Item: Copy` is not satisfied } trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719] - //~| ERROR the trait bound `<<Self as TRA2>::A as Iterator>::Item: Copy` is not satisfied } trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; diff --git a/tests/ui/associated-type-bounds/duplicate.stderr b/tests/ui/associated-type-bounds/duplicate.stderr index accb366dd15..bf6aab96dc7 100644 --- a/tests/ui/associated-type-bounds/duplicate.stderr +++ b/tests/ui/associated-type-bounds/duplicate.stderr @@ -7,7 +7,7 @@ LL | struct SI1<T: Iterator<Item: Copy, Item: Send>> { | `Item` bound here first error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:267:40 + --> $DIR/duplicate.rs:264:40 | LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; | ---------- ^^^^^^^^^^ re-bound here @@ -15,7 +15,7 @@ LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>; | `Item` bound here first error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:269:44 + --> $DIR/duplicate.rs:266:44 | LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; | ---------- ^^^^^^^^^^ re-bound here @@ -23,7 +23,7 @@ LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>; | `Item` bound here first error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:271:43 + --> $DIR/duplicate.rs:268:43 | LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -523,7 +523,7 @@ LL | type A: Iterator<Item: Copy, Item: Send>; | `Item` bound here first error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:258:34 + --> $DIR/duplicate.rs:256:34 | LL | type A: Iterator<Item: Copy, Item: Copy>; | ---------- ^^^^^^^^^^ re-bound here @@ -531,7 +531,7 @@ LL | type A: Iterator<Item: Copy, Item: Copy>; | `Item` bound here first error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified - --> $DIR/duplicate.rs:263:37 + --> $DIR/duplicate.rs:260:37 | LL | type A: Iterator<Item: 'static, Item: 'static>; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -631,41 +631,7 @@ LL | Self: Iterator<Item: 'static, Item: 'static>, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0277]: the trait bound `<<Self as TRA1>::A as Iterator>::Item: Copy` is not satisfied - --> $DIR/duplicate.rs:252:28 - | -LL | type A: Iterator<Item: Copy, Item: Send>; - | ^^^^ the trait `Copy` is not implemented for `<<Self as TRA1>::A as Iterator>::Item` - | -help: consider further restricting the associated type - | -LL | trait TRA1 where <<Self as TRA1>::A as Iterator>::Item: Copy { - | +++++++++++++++++++++++++++++++++++++++++++++++++ - -error[E0277]: `<<Self as TRA1>::A as Iterator>::Item` cannot be sent between threads safely - --> $DIR/duplicate.rs:252:40 - | -LL | type A: Iterator<Item: Copy, Item: Send>; - | ^^^^ `<<Self as TRA1>::A as Iterator>::Item` cannot be sent between threads safely - | - = help: the trait `Send` is not implemented for `<<Self as TRA1>::A as Iterator>::Item` -help: consider further restricting the associated type - | -LL | trait TRA1 where <<Self as TRA1>::A as Iterator>::Item: Send { - | +++++++++++++++++++++++++++++++++++++++++++++++++ - -error[E0277]: the trait bound `<<Self as TRA2>::A as Iterator>::Item: Copy` is not satisfied - --> $DIR/duplicate.rs:258:28 - | -LL | type A: Iterator<Item: Copy, Item: Copy>; - | ^^^^ the trait `Copy` is not implemented for `<<Self as TRA2>::A as Iterator>::Item` - | -help: consider further restricting the associated type - | -LL | trait TRA2 where <<Self as TRA2>::A as Iterator>::Item: Copy { - | +++++++++++++++++++++++++++++++++++++++++++++++++ - -error: aborting due to 78 previous errors +error: aborting due to 75 previous errors -Some errors have detailed explanations: E0277, E0282, E0719. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0282, E0719. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs b/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs index a3f4717791a..079c44b3a59 100644 --- a/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs +++ b/tests/ui/associated-type-bounds/dyn-impl-trait-type.rs @@ -5,7 +5,7 @@ use std::ops::Add; trait Tr1 { type As1; fn mk(&self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } +trait Tr2<'a> { fn tr2(self) -> &'a Self; } //~ WARN method `tr2` is never used fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; } fn assert_static<T: 'static>(_: T) {} diff --git a/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr b/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr new file mode 100644 index 00000000000..2e26a434f5d --- /dev/null +++ b/tests/ui/associated-type-bounds/dyn-impl-trait-type.stderr @@ -0,0 +1,12 @@ +warning: method `tr2` is never used + --> $DIR/dyn-impl-trait-type.rs:8:20 + | +LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs b/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs index 52199124ea3..49e5e72f225 100644 --- a/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs +++ b/tests/ui/associated-type-bounds/dyn-rpit-and-let.rs @@ -7,7 +7,7 @@ use std::ops::Add; trait Tr1 { type As1; fn mk(&self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } +trait Tr2<'a> { fn tr2(self) -> &'a Self; } //~ WARN method `tr2` is never used fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; } fn assert_static<T: 'static>(_: T) {} diff --git a/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr b/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr new file mode 100644 index 00000000000..9eddbe46284 --- /dev/null +++ b/tests/ui/associated-type-bounds/dyn-rpit-and-let.stderr @@ -0,0 +1,12 @@ +warning: method `tr2` is never used + --> $DIR/dyn-rpit-and-let.rs:10:20 + | +LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/higher-ranked.rs b/tests/ui/associated-type-bounds/higher-ranked.rs new file mode 100644 index 00000000000..2bd5f316811 --- /dev/null +++ b/tests/ui/associated-type-bounds/higher-ranked.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(associated_type_bounds)] + +trait A<'a> { + type Assoc: ?Sized; +} + +impl<'a> A<'a> for () { + type Assoc = &'a (); +} + +fn hello() -> impl for<'a> A<'a, Assoc: Sized> { + () +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/nested-bounds-dont-eliminate-alias-bounds.rs b/tests/ui/associated-type-bounds/nested-bounds-dont-eliminate-alias-bounds.rs new file mode 100644 index 00000000000..05e4e323d87 --- /dev/null +++ b/tests/ui/associated-type-bounds/nested-bounds-dont-eliminate-alias-bounds.rs @@ -0,0 +1,37 @@ +// check-pass + +#![feature(associated_type_bounds)] + +trait Trait1 { + type Assoc1: Bar; + + fn assoc(self) -> Self::Assoc1; +} + +impl Trait1 for () { + type Assoc1 = (); + fn assoc(self) {} +} + +trait Foo {} +impl Foo for () {} +trait Bar {} +impl Bar for () {} + +fn hello() -> impl Trait1<Assoc1: Foo> { + () +} + +fn world() { + // Tests that `Assoc1: Foo` bound in the RPIT doesn't disqualify + // the `Assoc1: Bar` bound in the item, as a nested RPIT desugaring + // would do. + + fn is_foo(_: impl Foo) {} + is_foo(hello().assoc()); + + fn is_bar(_: impl Bar) {} + is_bar(hello().assoc()); +} + +fn main() {} diff --git a/tests/ui/associated-type-bounds/rpit.rs b/tests/ui/associated-type-bounds/rpit.rs index 59c7733fbe4..557e63b5f71 100644 --- a/tests/ui/associated-type-bounds/rpit.rs +++ b/tests/ui/associated-type-bounds/rpit.rs @@ -5,7 +5,7 @@ use std::ops::Add; trait Tr1 { type As1; fn mk(self) -> Self::As1; } -trait Tr2<'a> { fn tr2(self) -> &'a Self; } +trait Tr2<'a> { fn tr2(self) -> &'a Self; } //~ WARN method `tr2` is never used fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; } fn assert_static<T: 'static>(_: T) {} diff --git a/tests/ui/associated-type-bounds/rpit.stderr b/tests/ui/associated-type-bounds/rpit.stderr new file mode 100644 index 00000000000..76bd75bd2ca --- /dev/null +++ b/tests/ui/associated-type-bounds/rpit.stderr @@ -0,0 +1,12 @@ +warning: method `tr2` is never used + --> $DIR/rpit.rs:8:20 + | +LL | trait Tr2<'a> { fn tr2(self) -> &'a Self; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed index b9f26a40219..128c7dfdda2 100644 --- a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait O { type M; } diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs index abff6af73e2..6b6478419b4 100644 --- a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait O { type M; } diff --git a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr index 7ca9aff4322..21bc37bb3ea 100644 --- a/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr +++ b/tests/ui/associated-type-bounds/suggest-contraining-assoc-type-because-of-assoc-const.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:12:21 + --> $DIR/suggest-contraining-assoc-type-because-of-assoc-const.rs:13:21 | LL | const N: C::M = 4u8; | ^^^ expected associated type, found `u8` diff --git a/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs b/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs index 93a44c01ce0..60088e443f3 100644 --- a/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs +++ b/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs @@ -1,5 +1,6 @@ // run-pass +#![allow(dead_code)] #![feature(associated_type_bounds)] #![feature(type_alias_impl_trait)] diff --git a/tests/ui/associated-types/associated-types-eq-hr.rs b/tests/ui/associated-types/associated-types-eq-hr.rs index dc653f7f2e9..b8a97b5c7dd 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.rs +++ b/tests/ui/associated-types/associated-types-eq-hr.rs @@ -94,10 +94,18 @@ pub fn call_bar() { pub fn call_tuple_one() { tuple_one::<Tuple>(); + //~^ ERROR not general enough + //~| ERROR not general enough + //~| ERROR not general enough + //~| ERROR not general enough } pub fn call_tuple_two() { tuple_two::<Tuple>(); + //~^ ERROR not general enough + //~| ERROR not general enough + //~| ERROR mismatched types + //~| ERROR mismatched types } pub fn call_tuple_three() { @@ -106,6 +114,8 @@ pub fn call_tuple_three() { pub fn call_tuple_four() { tuple_four::<Tuple>(); + //~^ ERROR not general enough + //~| ERROR not general enough } fn main() {} diff --git a/tests/ui/associated-types/associated-types-eq-hr.stderr b/tests/ui/associated-types/associated-types-eq-hr.stderr index 3e1142d5d95..3a70189dd9f 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.stderr +++ b/tests/ui/associated-types/associated-types-eq-hr.stderr @@ -42,6 +42,113 @@ LL | where LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, | ^^^^^^^^^^^^^ required by this bound in `bar` -error: aborting due to 2 previous errors +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 + | +LL | tuple_one::<Tuple>(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 + | +LL | tuple_one::<Tuple>(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 + | +LL | tuple_one::<Tuple>(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:96:5 + | +LL | tuple_one::<Tuple>(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:104:5 + | +LL | tuple_two::<Tuple>(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:104:5 + | +LL | tuple_two::<Tuple>(); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0308]: mismatched types + --> $DIR/associated-types-eq-hr.rs:104:5 + | +LL | tuple_two::<Tuple>(); + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected reference `&'x _` + found reference `&'y _` +note: the lifetime requirement is introduced here + --> $DIR/associated-types-eq-hr.rs:66:53 + | +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/associated-types-eq-hr.rs:104:5 + | +LL | tuple_two::<Tuple>(); + | ^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected reference `&'x _` + found reference `&'y _` +note: the lifetime requirement is introduced here + --> $DIR/associated-types-eq-hr.rs:66:53 + | +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:116:5 + | +LL | tuple_four::<Tuple>(); + | ^^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + +error: implementation of `TheTrait` is not general enough + --> $DIR/associated-types-eq-hr.rs:116:5 + | +LL | tuple_four::<Tuple>(); + | ^^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 12 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0271, E0308. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed b/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed index 80bbef17469..adfba994f32 100644 --- a/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #![allow(unused_variables)] trait Get { diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.rs b/tests/ui/associated-types/associated-types-for-unimpl-trait.rs index 0f6cea8e69f..50478171d86 100644 --- a/tests/ui/associated-types/associated-types-for-unimpl-trait.rs +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #![allow(unused_variables)] trait Get { diff --git a/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr b/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr index 17941b6bf1e..27014fa53d8 100644 --- a/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/tests/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-for-unimpl-trait.rs:10:40 + --> $DIR/associated-types-for-unimpl-trait.rs:11:40 | LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {} | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` diff --git a/tests/ui/associated-types/associated-types-in-bound-type-arg.rs b/tests/ui/associated-types/associated-types-in-bound-type-arg.rs index 88bb5fe0afe..05e66a168d9 100644 --- a/tests/ui/associated-types/associated-types-in-bound-type-arg.rs +++ b/tests/ui/associated-types/associated-types-in-bound-type-arg.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test the case where we resolve `C::Result` and the trait bound // itself includes a `Self::Item` shorthand. // diff --git a/tests/ui/associated-types/associated-types-issue-20220.rs b/tests/ui/associated-types/associated-types-issue-20220.rs index 19fa7a6085a..89efce19834 100644 --- a/tests/ui/associated-types/associated-types-issue-20220.rs +++ b/tests/ui/associated-types/associated-types-issue-20220.rs @@ -4,7 +4,7 @@ use std::vec; -trait IntoIteratorX { +trait IntoIteratorX { //~ WARN trait `IntoIteratorX` is never used type Item; type IntoIter: Iterator<Item=Self::Item>; diff --git a/tests/ui/associated-types/associated-types-issue-20220.stderr b/tests/ui/associated-types/associated-types-issue-20220.stderr new file mode 100644 index 00000000000..c682f46e140 --- /dev/null +++ b/tests/ui/associated-types/associated-types-issue-20220.stderr @@ -0,0 +1,10 @@ +warning: trait `IntoIteratorX` is never used + --> $DIR/associated-types-issue-20220.rs:7:7 + | +LL | trait IntoIteratorX { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-types/associated-types-issue-20371.rs b/tests/ui/associated-types/associated-types-issue-20371.rs index ae8a8767d27..cbec83d45b2 100644 --- a/tests/ui/associated-types/associated-types-issue-20371.rs +++ b/tests/ui/associated-types/associated-types-issue-20371.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that we are able to have an impl that defines an associated type // before the actual trait. diff --git a/tests/ui/associated-types/associated-types-nested-projections.rs b/tests/ui/associated-types/associated-types-nested-projections.rs index 76ba7496250..440f35c8bde 100644 --- a/tests/ui/associated-types/associated-types-nested-projections.rs +++ b/tests/ui/associated-types/associated-types-nested-projections.rs @@ -13,7 +13,7 @@ impl<'a> Bound for &'a i32 {} trait IntoIterator { type Iter: Iterator; - fn into_iter(self) -> Self::Iter; + fn into_iter(self) -> Self::Iter; //~ WARN method `into_iter` is never used } impl<'a, T> IntoIterator for &'a [T; 3] { diff --git a/tests/ui/associated-types/associated-types-nested-projections.stderr b/tests/ui/associated-types/associated-types-nested-projections.stderr new file mode 100644 index 00000000000..97d5a758573 --- /dev/null +++ b/tests/ui/associated-types/associated-types-nested-projections.stderr @@ -0,0 +1,13 @@ +warning: method `into_iter` is never used + --> $DIR/associated-types-nested-projections.rs:16:8 + | +LL | trait IntoIterator { + | ------------ method in this trait +... +LL | fn into_iter(self) -> Self::Iter; + | ^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs b/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs index e09aa3663c6..6612598b1b8 100644 --- a/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs +++ b/tests/ui/associated-types/associated-types-normalize-in-bounds-ufcs.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_variables)] // Test that we normalize associated types that appear in bounds; if // we didn't, the call to `self.split2()` fails to type check. diff --git a/tests/ui/associated-types/associated-types-normalize-in-bounds.rs b/tests/ui/associated-types/associated-types-normalize-in-bounds.rs index dcfae0f37e1..df0a82ee7ce 100644 --- a/tests/ui/associated-types/associated-types-normalize-in-bounds.rs +++ b/tests/ui/associated-types/associated-types-normalize-in-bounds.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_variables)] // Test that we normalize associated types that appear in bounds; if // we didn't, the call to `self.split2()` fails to type check. diff --git a/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs b/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs index 107e6b4ce0c..e99d0112ec4 100644 --- a/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs +++ b/tests/ui/associated-types/associated-types-projection-bound-in-supertraits.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_variables)] // Test that we correctly handle projection bounds appearing in the // supertrait list (and in conjunction with overloaded operators). In diff --git a/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs index a59c327be21..e172c6e5611 100644 --- a/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs +++ b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.rs @@ -6,7 +6,7 @@ trait Int { type T; - fn dummy(&self) { } + fn dummy(&self) { } //~ WARN method `dummy` is never used } trait NonZero diff --git a/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.stderr b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.stderr new file mode 100644 index 00000000000..c26ed79a026 --- /dev/null +++ b/tests/ui/associated-types/associated-types-projection-from-known-type-in-impl.stderr @@ -0,0 +1,13 @@ +warning: method `dummy` is never used + --> $DIR/associated-types-projection-from-known-type-in-impl.rs:9:8 + | +LL | trait Int + | --- method in this trait +... +LL | fn dummy(&self) { } + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed index 9bc308465eb..01f49d52ee2 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed @@ -2,6 +2,7 @@ // Check that we get an error when you use `<Self as Get>::Value` in // the trait definition even if there is no default method. +#![allow(dead_code)] trait Get { type Value; } diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs index 549fc8fc618..7068a754a12 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs @@ -2,6 +2,7 @@ // Check that we get an error when you use `<Self as Get>::Value` in // the trait definition even if there is no default method. +#![allow(dead_code)] trait Get { type Value; } diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index 64a88525af8..79200dc3acc 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40 + --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:11:40 | LL | fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value); | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` diff --git a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs index 3b8c8c019e5..a2d6c9ff5a4 100644 --- a/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs +++ b/tests/ui/associated-types/associated-types-projection-to-unrelated-trait.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Check that we do not get an error when you use `<Self as Get>::Value` in // the trait definition if there is no default method and for every impl, // `Self` does implement `Get`. diff --git a/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs b/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs index 3c830d37060..1768fd1687b 100644 --- a/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs +++ b/tests/ui/associated-types/associated-types-qualified-path-with-trait-with-type-parameters.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Foo<T> { diff --git a/tests/ui/associated-types/associated-types-resolve-lifetime.rs b/tests/ui/associated-types/associated-types-resolve-lifetime.rs index 52f2324d72a..563d0c11822 100644 --- a/tests/ui/associated-types/associated-types-resolve-lifetime.rs +++ b/tests/ui/associated-types/associated-types-resolve-lifetime.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Get<T> { diff --git a/tests/ui/associated-types/hr-associated-type-bound-object.stderr b/tests/ui/associated-types/hr-associated-type-bound-object.stderr index 8c91211b964..87a048d0a13 100644 --- a/tests/ui/associated-types/hr-associated-type-bound-object.stderr +++ b/tests/ui/associated-types/hr-associated-type-bound-object.stderr @@ -12,6 +12,10 @@ LL | trait X<'a> LL | where LL | for<'b> <Self as X<'b>>::U: Clone, | ^^^^^ required by this bound in `X` +help: consider further restricting the associated type + | +LL | fn f<'a, T: X<'a> + ?Sized>(x: &<T as X<'a>>::U) where for<'b> <T as X<'b>>::U: Clone { + | ++++++++++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/associated-types/impl-wf-cycle-5.fixed b/tests/ui/associated-types/impl-wf-cycle-5.fixed index bff6ca90975..2b8f1e0d865 100644 --- a/tests/ui/associated-types/impl-wf-cycle-5.fixed +++ b/tests/ui/associated-types/impl-wf-cycle-5.fixed @@ -1,9 +1,11 @@ // run-rustfix +#[allow(dead_code)] trait Baz {} impl Baz for () {} impl<T> Baz for (T,) {} +#[allow(dead_code)] trait Fiz {} impl Fiz for bool {} diff --git a/tests/ui/associated-types/impl-wf-cycle-5.rs b/tests/ui/associated-types/impl-wf-cycle-5.rs index a822e1fb008..e6de292ca5c 100644 --- a/tests/ui/associated-types/impl-wf-cycle-5.rs +++ b/tests/ui/associated-types/impl-wf-cycle-5.rs @@ -1,9 +1,11 @@ // run-rustfix +#[allow(dead_code)] trait Baz {} impl Baz for () {} impl<T> Baz for (T,) {} +#[allow(dead_code)] trait Fiz {} impl Fiz for bool {} diff --git a/tests/ui/associated-types/impl-wf-cycle-5.stderr b/tests/ui/associated-types/impl-wf-cycle-5.stderr index 284a50bb9a3..61edf18b43d 100644 --- a/tests/ui/associated-types/impl-wf-cycle-5.stderr +++ b/tests/ui/associated-types/impl-wf-cycle-5.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` - --> $DIR/impl-wf-cycle-5.rs:20:1 + --> $DIR/impl-wf-cycle-5.rs:22:1 | LL | / impl<T> Grault for (T,) LL | | @@ -12,7 +12,7 @@ LL | type A = (); | ------ associated type `<(T,) as Grault>::A` is specified here | note: required for `(T,)` to implement `Grault` - --> $DIR/impl-wf-cycle-5.rs:20:9 + --> $DIR/impl-wf-cycle-5.rs:22:9 | LL | impl<T> Grault for (T,) | ^^^^^^ ^^^^ diff --git a/tests/ui/associated-types/impl-wf-cycle-6.fixed b/tests/ui/associated-types/impl-wf-cycle-6.fixed index 73ed64f7ce3..5ddf1faefe0 100644 --- a/tests/ui/associated-types/impl-wf-cycle-6.fixed +++ b/tests/ui/associated-types/impl-wf-cycle-6.fixed @@ -1,9 +1,11 @@ // run-rustfix +#[allow(dead_code)] trait Baz {} impl Baz for () {} impl<T> Baz for (T,) {} +#[allow(dead_code)] trait Fiz {} impl Fiz for bool {} diff --git a/tests/ui/associated-types/impl-wf-cycle-6.rs b/tests/ui/associated-types/impl-wf-cycle-6.rs index 20d635cac5d..28f6deb77ce 100644 --- a/tests/ui/associated-types/impl-wf-cycle-6.rs +++ b/tests/ui/associated-types/impl-wf-cycle-6.rs @@ -1,9 +1,11 @@ // run-rustfix +#[allow(dead_code)] trait Baz {} impl Baz for () {} impl<T> Baz for (T,) {} +#[allow(dead_code)] trait Fiz {} impl Fiz for bool {} diff --git a/tests/ui/associated-types/impl-wf-cycle-6.stderr b/tests/ui/associated-types/impl-wf-cycle-6.stderr index c9b5d8060be..1c749503318 100644 --- a/tests/ui/associated-types/impl-wf-cycle-6.stderr +++ b/tests/ui/associated-types/impl-wf-cycle-6.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _` - --> $DIR/impl-wf-cycle-6.rs:20:1 + --> $DIR/impl-wf-cycle-6.rs:22:1 | LL | / impl<T: Grault> Grault for (T,) LL | | @@ -11,7 +11,7 @@ LL | type A = (); | ------ associated type `<(T,) as Grault>::A` is specified here | note: required for `(T,)` to implement `Grault` - --> $DIR/impl-wf-cycle-6.rs:20:17 + --> $DIR/impl-wf-cycle-6.rs:22:17 | LL | impl<T: Grault> Grault for (T,) | ^^^^^^ ^^^^ diff --git a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs index 8d7dc6a276b..897def791fe 100644 --- a/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs +++ b/tests/ui/async-await/async-closures/async-fn-mut-for-async-fn.rs @@ -2,20 +2,15 @@ // edition:2021 // run-pass -// FIXME(async_closures): When `fn_sig_for_fn_abi` is fixed, remove this. -// ignore-pass (test emits codegen-time warnings) - -#![feature(async_closure, async_fn_traits)] +#![feature(async_closure)] extern crate block_on; -use std::ops::AsyncFnMut; - fn main() { block_on::block_on(async { let x = async || {}; - async fn needs_async_fn_mut(mut x: impl AsyncFnMut()) { + async fn needs_async_fn_mut(mut x: impl async FnMut()) { x().await; } needs_async_fn_mut(x).await; diff --git a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs index 4afc43fe6bd..0e9b25e6d30 100644 --- a/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs +++ b/tests/ui/async-await/async-closures/async-fn-once-for-async-fn.rs @@ -2,20 +2,15 @@ // edition:2021 // run-pass -// FIXME(async_closures): When `fn_sig_for_fn_abi` is fixed, remove this. -// ignore-pass (test emits codegen-time warnings) - -#![feature(async_closure, async_fn_traits)] +#![feature(async_closure)] extern crate block_on; -use std::ops::AsyncFnOnce; - fn main() { block_on::block_on(async { let x = async || {}; - async fn needs_async_fn_once(x: impl AsyncFnOnce()) { + async fn needs_async_fn_once(x: impl async FnOnce()) { x().await; } needs_async_fn_once(x).await; diff --git a/tests/ui/async-await/async-closures/auxiliary/block-on.rs b/tests/ui/async-await/async-closures/auxiliary/block-on.rs index 3c27548b865..902e033cfe7 100644 --- a/tests/ui/async-await/async-closures/auxiliary/block-on.rs +++ b/tests/ui/async-await/async-closures/auxiliary/block-on.rs @@ -1,6 +1,6 @@ // edition: 2021 -#![feature(async_closure, noop_waker, async_fn_traits)] +#![feature(async_closure, noop_waker)] use std::future::Future; use std::pin::pin; diff --git a/tests/ui/async-await/async-closures/brand.rs b/tests/ui/async-await/async-closures/brand.rs index 3bda7737bb4..26d2ed5a6ef 100644 --- a/tests/ui/async-await/async-closures/brand.rs +++ b/tests/ui/async-await/async-closures/brand.rs @@ -2,19 +2,18 @@ // edition:2021 // build-pass -#![feature(async_closure, async_fn_traits)] +#![feature(async_closure)] extern crate block_on; use std::future::Future; use std::marker::PhantomData; -use std::ops::AsyncFn; struct S; struct B<'b>(PhantomData<&'b mut &'b mut ()>); impl S { - async fn q<F: AsyncFn(B<'_>)>(self, f: F) { + async fn q<F: async Fn(B<'_>)>(self, f: F) { f(B(PhantomData)).await; } } diff --git a/tests/ui/async-await/async-closures/drop.rs b/tests/ui/async-await/async-closures/drop.rs index 1b7f2f8a600..a243d20774d 100644 --- a/tests/ui/async-await/async-closures/drop.rs +++ b/tests/ui/async-await/async-closures/drop.rs @@ -3,13 +3,11 @@ // run-pass // check-run-results -#![feature(async_closure, async_fn_traits)] +#![feature(async_closure)] #![allow(unused)] extern crate block_on; -use std::ops::AsyncFnOnce; - struct DropMe(i32); impl Drop for DropMe { @@ -18,7 +16,7 @@ impl Drop for DropMe { } } -async fn call_once(f: impl AsyncFnOnce()) { +async fn call_once(f: impl async FnOnce()) { println!("before call"); let fut = Box::pin(f()); println!("after call"); diff --git a/tests/ui/async-await/async-closures/mangle.rs b/tests/ui/async-await/async-closures/mangle.rs index 98065c3c711..9d231d55176 100644 --- a/tests/ui/async-await/async-closures/mangle.rs +++ b/tests/ui/async-await/async-closures/mangle.rs @@ -8,20 +8,19 @@ // FIXME(async_closures): When `fn_sig_for_fn_abi` is fixed, remove this. // ignore-pass (test emits codegen-time warnings) -#![feature(async_closure, noop_waker, async_fn_traits)] +#![feature(async_closure, noop_waker)] extern crate block_on; use std::future::Future; -use std::ops::{AsyncFnMut, AsyncFnOnce}; use std::pin::pin; use std::task::*; -async fn call_mut(f: &mut impl AsyncFnMut()) { +async fn call_mut(f: &mut impl async FnMut()) { f().await; } -async fn call_once(f: impl AsyncFnOnce()) { +async fn call_once(f: impl async FnOnce()) { f().await; } diff --git a/tests/ui/async-await/async-closures/tainted-body.rs b/tests/ui/async-await/async-closures/tainted-body.rs new file mode 100644 index 00000000000..62c28e7e585 --- /dev/null +++ b/tests/ui/async-await/async-closures/tainted-body.rs @@ -0,0 +1,13 @@ +// edition:2021 + +#![feature(async_closure)] + +// Don't ICE in ByMove shim builder when MIR body is tainted by writeback errors + +fn main() { + let _ = async || { + used_fn(); + //~^ ERROR cannot find function `used_fn` in this scope + 0 + }; +} diff --git a/tests/ui/async-await/async-closures/tainted-body.stderr b/tests/ui/async-await/async-closures/tainted-body.stderr new file mode 100644 index 00000000000..b06a896b81f --- /dev/null +++ b/tests/ui/async-await/async-closures/tainted-body.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `used_fn` in this scope + --> $DIR/tainted-body.rs:9:9 + | +LL | used_fn(); + | ^^^^^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.rs b/tests/ui/async-await/async-closures/wrong-fn-kind.rs index 24828832531..f86cee3e070 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.rs +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.rs @@ -2,17 +2,15 @@ // FIXME(async_closures): This needs a better error message! -#![feature(async_closure, async_fn_traits)] - -use std::ops::AsyncFn; +#![feature(async_closure)] fn main() { - fn needs_async_fn(_: impl AsyncFn()) {} + fn needs_async_fn(_: impl async Fn()) {} let mut x = 1; needs_async_fn(async || { //~^ ERROR i16: ops::async_function::internal_implementation_detail::AsyncFnKindHelper<i8> - // FIXME: Should say "closure is AsyncFnMut but it needs AsyncFn" or sth. + // FIXME: Should say "closure is `async FnMut` but it needs `async Fn`" or sth. x += 1; }); } diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr index ef95e6a211c..4ef8484cc34 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr @@ -1,21 +1,21 @@ error[E0277]: the trait bound `i16: ops::async_function::internal_implementation_detail::AsyncFnKindHelper<i8>` is not satisfied - --> $DIR/wrong-fn-kind.rs:13:20 + --> $DIR/wrong-fn-kind.rs:11:20 | LL | needs_async_fn(async || { | _____--------------_^ | | | | | required by a bound introduced by this call LL | | -LL | | // FIXME: Should say "closure is AsyncFnMut but it needs AsyncFn" or sth. +LL | | // FIXME: Should say "closure is `async FnMut` but it needs `async Fn`" or sth. LL | | x += 1; LL | | }); | |_____^ the trait `ops::async_function::internal_implementation_detail::AsyncFnKindHelper<i8>` is not implemented for `i16` | note: required by a bound in `needs_async_fn` - --> $DIR/wrong-fn-kind.rs:10:31 + --> $DIR/wrong-fn-kind.rs:8:31 | -LL | fn needs_async_fn(_: impl AsyncFn()) {} - | ^^^^^^^^^ required by this bound in `needs_async_fn` +LL | fn needs_async_fn(_: impl async Fn()) {} + | ^^^^^^^^^^ required by this bound in `needs_async_fn` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs index c5a9841029e..69871d0dca0 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs @@ -1,15 +1,18 @@ // edition: 2021 +// check-pass use std::future::Future; use std::pin::Pin; -trait MyTrait { +#[allow(async_fn_in_trait)] +pub trait MyTrait { async fn foo(&self) -> i32; } impl MyTrait for i32 { + #[warn(refining_impl_trait)] fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> { - //~^ ERROR method `foo` should be async + //~^ WARN impl trait in impl method signature does not match trait method signature Box::pin(async { *self }) } } diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr index 1462c694e16..54aba77cc05 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -1,11 +1,22 @@ -error: method `foo` should be async because the method from the trait is async - --> $DIR/async-example-desugared-boxed.rs:11:5 +warning: impl trait in impl method signature does not match trait method signature + --> $DIR/async-example-desugared-boxed.rs:14:22 | LL | async fn foo(&self) -> i32; - | --------------------------- required because the trait method is async + | --------------------------- return type from trait method defined here ... LL | fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate +note: the lint level is defined here + --> $DIR/async-example-desugared-boxed.rs:13:12 + | +LL | #[warn(refining_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^ +help: replace the return type so that it matches the trait + | +LL | fn foo(&self) -> impl Future<Output = i32> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 1 previous error +warning: 1 warning emitted diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs index c287b9a5b84..c6e8f1ae906 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs @@ -1,13 +1,15 @@ // edition: 2021 +// check-pass use std::future::Future; use std::task::Poll; -trait MyTrait { +#[allow(async_fn_in_trait)] +pub trait MyTrait { async fn foo(&self) -> i32; } -struct MyFuture; +pub struct MyFuture; impl Future for MyFuture { type Output = i32; fn poll(self: std::pin::Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> { @@ -16,8 +18,9 @@ impl Future for MyFuture { } impl MyTrait for u32 { + #[warn(refining_impl_trait)] fn foo(&self) -> MyFuture { - //~^ ERROR method `foo` should be async + //~^ WARN impl trait in impl method signature does not match trait method signature MyFuture } } diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr index a2f1060e36f..d94afd92c56 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -1,11 +1,22 @@ -error: method `foo` should be async because the method from the trait is async - --> $DIR/async-example-desugared-manual.rs:19:5 +warning: impl trait in impl method signature does not match trait method signature + --> $DIR/async-example-desugared-manual.rs:22:22 | LL | async fn foo(&self) -> i32; - | --------------------------- required because the trait method is async + | --------------------------- return type from trait method defined here ... LL | fn foo(&self) -> MyFuture { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate +note: the lint level is defined here + --> $DIR/async-example-desugared-manual.rs:21:12 + | +LL | #[warn(refining_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^ +help: replace the return type so that it matches the trait + | +LL | fn foo(&self) -> impl Future<Output = i32> { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 1 previous error +warning: 1 warning emitted diff --git a/tests/ui/async-await/in-trait/auxiliary/bad-region.rs b/tests/ui/async-await/in-trait/auxiliary/bad-region.rs new file mode 100644 index 00000000000..02dc25aaa16 --- /dev/null +++ b/tests/ui/async-await/in-trait/auxiliary/bad-region.rs @@ -0,0 +1,7 @@ +// edition:2021 + +#[allow(async_fn_in_trait)] + +pub trait BleRadio<'a> { + async fn transmit(&mut self); +} diff --git a/tests/ui/async-await/in-trait/bad-region.rs b/tests/ui/async-await/in-trait/bad-region.rs new file mode 100644 index 00000000000..444368e21a4 --- /dev/null +++ b/tests/ui/async-await/in-trait/bad-region.rs @@ -0,0 +1,17 @@ +// aux-build:bad-region.rs +// edition:2021 + +#![allow(async_fn_in_trait)] + +extern crate bad_region as jewel; + +use jewel::BleRadio; + +pub struct Radio {} + +impl BleRadio for Radio { +//~^ ERROR implicit elided lifetime not allowed here + async fn transmit(&mut self) {} +} + +fn main() {} diff --git a/tests/ui/async-await/in-trait/bad-region.stderr b/tests/ui/async-await/in-trait/bad-region.stderr new file mode 100644 index 00000000000..9203fd790af --- /dev/null +++ b/tests/ui/async-await/in-trait/bad-region.stderr @@ -0,0 +1,14 @@ +error[E0726]: implicit elided lifetime not allowed here + --> $DIR/bad-region.rs:12:6 + | +LL | impl BleRadio for Radio { + | ^^^^^^^^ expected lifetime parameter + | +help: indicate the anonymous lifetime + | +LL | impl BleRadio<'_> for Radio { + | ++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0726`. diff --git a/tests/ui/async-await/in-trait/coherence-constrained.rs b/tests/ui/async-await/in-trait/coherence-constrained.rs index 8e62b3e0e90..82c8724ca3e 100644 --- a/tests/ui/async-await/in-trait/coherence-constrained.rs +++ b/tests/ui/async-await/in-trait/coherence-constrained.rs @@ -12,7 +12,6 @@ impl Foo for Bar { type T = (); async fn foo(&self) {} - //~^ ERROR type annotations needed: cannot satisfy `<Bar as Foo>::T == ()` } impl Foo for Bar { @@ -20,7 +19,6 @@ impl Foo for Bar { type T = (); async fn foo(&self) {} - //~^ ERROR type annotations needed: cannot satisfy `<Bar as Foo>::T == ()` } fn main() {} diff --git a/tests/ui/async-await/in-trait/coherence-constrained.stderr b/tests/ui/async-await/in-trait/coherence-constrained.stderr index 570a357ca8f..5c48a1fe98f 100644 --- a/tests/ui/async-await/in-trait/coherence-constrained.stderr +++ b/tests/ui/async-await/in-trait/coherence-constrained.stderr @@ -1,17 +1,5 @@ -error[E0284]: type annotations needed: cannot satisfy `<Bar as Foo>::T == ()` - --> $DIR/coherence-constrained.rs:14:5 - | -LL | async fn foo(&self) {} - | ^^^^^^^^^^^^^^^^^^^ cannot satisfy `<Bar as Foo>::T == ()` - -error[E0284]: type annotations needed: cannot satisfy `<Bar as Foo>::T == ()` - --> $DIR/coherence-constrained.rs:22:5 - | -LL | async fn foo(&self) {} - | ^^^^^^^^^^^^^^^^^^^ cannot satisfy `<Bar as Foo>::T == ()` - error[E0119]: conflicting implementations of trait `Foo` for type `Bar` - --> $DIR/coherence-constrained.rs:18:1 + --> $DIR/coherence-constrained.rs:17:1 | LL | impl Foo for Bar { | ---------------- first implementation here @@ -19,7 +7,6 @@ LL | impl Foo for Bar { LL | impl Foo for Bar { | ^^^^^^^^^^^^^^^^ conflicting implementation for `Bar` -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0119, E0284. -For more information about an error, try `rustc --explain E0119`. +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.rs b/tests/ui/async-await/in-trait/fn-not-async-err.rs index 60077a7e00c..ecd5737cf3c 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.rs +++ b/tests/ui/async-await/in-trait/fn-not-async-err.rs @@ -8,7 +8,7 @@ trait MyTrait { impl MyTrait for i32 { fn foo(&self) -> i32 { - //~^ ERROR: method `foo` should be async + //~^ ERROR: method should be `async` or return a future, but it is synchronous *self } } diff --git a/tests/ui/async-await/in-trait/fn-not-async-err.stderr b/tests/ui/async-await/in-trait/fn-not-async-err.stderr index f75ccb65d15..8260cd5271e 100644 --- a/tests/ui/async-await/in-trait/fn-not-async-err.stderr +++ b/tests/ui/async-await/in-trait/fn-not-async-err.stderr @@ -1,11 +1,14 @@ -error: method `foo` should be async because the method from the trait is async +error: method should be `async` or return a future, but it is synchronous --> $DIR/fn-not-async-err.rs:10:5 | -LL | async fn foo(&self) -> i32; - | --------------------------- required because the trait method is async -... LL | fn foo(&self) -> i32 { | ^^^^^^^^^^^^^^^^^^^^ + | +note: this method is `async` so it expects a future to be returned + --> $DIR/fn-not-async-err.rs:6:5 + | +LL | async fn foo(&self) -> i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr index d4266814a7c..d4266814a7c 100644 --- a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2015.stderr +++ b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2015.stderr diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr index fe104bfe445..fe104bfe445 100644 --- a/tests/ui/issues/issue-65634-raw-ident-suggestion.edition2018.stderr +++ b/tests/ui/async-await/issue-65634-raw-ident-suggestion.edition2018.stderr diff --git a/tests/ui/issues/issue-65634-raw-ident-suggestion.rs b/tests/ui/async-await/issue-65634-raw-ident-suggestion.rs index 03dd0340c9d..03dd0340c9d 100644 --- a/tests/ui/issues/issue-65634-raw-ident-suggestion.rs +++ b/tests/ui/async-await/issue-65634-raw-ident-suggestion.rs diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs index 4af73739584..81f6961840c 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.rs +++ b/tests/ui/async-await/issue-70935-complex-spans.rs @@ -14,6 +14,7 @@ async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> { fn foo(x: NotSync) -> impl Future + Send { //~^ ERROR `*mut ()` cannot be shared between threads safely + //~| ERROR `*mut ()` cannot be shared between threads safely async move { baz(|| async { foo(x.clone()); diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index 36e297ed884..8dc3f476ec8 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -4,7 +4,7 @@ error[E0277]: `*mut ()` cannot be shared between threads safely LL | fn foo(x: NotSync) -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely | - = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:17:5: 21:6}: Send` + = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 22:6}: Send` note: required because it appears within the type `PhantomData<*mut ()>` --> $SRC_DIR/core/src/marker.rs:LL:COL note: required because it appears within the type `NotSync` @@ -14,7 +14,7 @@ LL | struct NotSync(PhantomData<*mut ()>); | ^^^^^^^ = note: required for `&NotSync` to implement `Send` note: required because it's used within this closure - --> $DIR/issue-70935-complex-spans.rs:18:13 + --> $DIR/issue-70935-complex-spans.rs:19:13 | LL | baz(|| async { | ^^ @@ -27,7 +27,7 @@ LL | | } | |_^ = note: required because it captures the following types: `impl Future<Output = ()>` note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:17:5 + --> $DIR/issue-70935-complex-spans.rs:18:5 | LL | / async move { LL | | baz(|| async { @@ -36,6 +36,45 @@ LL | | }).await; LL | | } | |_____^ -error: aborting due to 1 previous error +error[E0277]: `*mut ()` cannot be shared between threads safely + --> $DIR/issue-70935-complex-spans.rs:15:23 + | +LL | fn foo(x: NotSync) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely + | + = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()`, which is required by `{async block@$DIR/issue-70935-complex-spans.rs:18:5: 22:6}: Send` +note: required because it appears within the type `PhantomData<*mut ()>` + --> $SRC_DIR/core/src/marker.rs:LL:COL +note: required because it appears within the type `NotSync` + --> $DIR/issue-70935-complex-spans.rs:9:8 + | +LL | struct NotSync(PhantomData<*mut ()>); + | ^^^^^^^ + = note: required for `&NotSync` to implement `Send` +note: required because it's used within this closure + --> $DIR/issue-70935-complex-spans.rs:19:13 + | +LL | baz(|| async { + | ^^ +note: required because it's used within this `async` fn body + --> $DIR/issue-70935-complex-spans.rs:12:67 + | +LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> { + | ___________________________________________________________________^ +LL | | } + | |_^ + = note: required because it captures the following types: `impl Future<Output = ()>` +note: required because it's used within this `async` block + --> $DIR/issue-70935-complex-spans.rs:18:5 + | +LL | / async move { +LL | | baz(|| async { +LL | | foo(x.clone()); +LL | | }).await; +LL | | } + | |_____^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr index d2db6abe313..2e82a3fcdb4 100644 --- a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr +++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr @@ -1,5 +1,5 @@ warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/normalizing-self-auto-trait-issue-109924.rs:7:12 + --> $DIR/normalizing-self-auto-trait-issue-109924.rs:6:12 | LL | #![feature(return_type_notation)] | ^^^^^^^^^^^^^^^^^^^^ @@ -7,29 +7,5 @@ LL | #![feature(return_type_notation)] = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: `impl Future<Output = ()> { <_ as Foo>::bar() }` cannot be sent between threads safely - --> $DIR/normalizing-self-auto-trait-issue-109924.rs:22:11 - | -LL | build(Bar); - | ----- ^^^ `impl Future<Output = ()> { <_ as Foo>::bar() }` cannot be sent between threads safely - | | - | required by a bound introduced by this call - | - = help: the trait `for<'a> Send` is not implemented for `impl Future<Output = ()> { <_ as Foo>::bar() }` -note: this is a known limitation of the trait solver that will be lifted in the future - --> $DIR/normalizing-self-auto-trait-issue-109924.rs:22:11 - | -LL | build(Bar); - | ------^^^- - | | | - | | the trait solver is unable to infer the generic types that should be inferred from this argument - | add turbofish arguments to this call to specify the types manually, even if it's redundant -note: required by a bound in `build` - --> $DIR/normalizing-self-auto-trait-issue-109924.rs:19:39 - | -LL | fn build<T>(_: T) where T: Foo<bar(): Send> {} - | ^^^^ required by this bound in `build` - -error: aborting due to 1 previous error; 1 warning emitted +warning: 1 warning emitted -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr index 4837815fad4..2e82a3fcdb4 100644 --- a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr +++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr @@ -1,5 +1,5 @@ warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/normalizing-self-auto-trait-issue-109924.rs:7:12 + --> $DIR/normalizing-self-auto-trait-issue-109924.rs:6:12 | LL | #![feature(return_type_notation)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs index 6097c7f1073..5341c39a975 100644 --- a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs +++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs @@ -1,11 +1,10 @@ +// check-pass // revisions: current next -//[current] known-bug: #109924 -//[next] check-pass //[next] compile-flags: -Znext-solver // edition:2021 #![feature(return_type_notation)] -//[next]~^ WARN the feature `return_type_notation` is incomplete +//~^ WARN the feature `return_type_notation` is incomplete trait Foo { async fn bar(&self); diff --git a/tests/ui/auto-traits/auto-trait-validation.fixed b/tests/ui/auto-traits/auto-trait-validation.fixed index da878ac6222..e37fed9faab 100644 --- a/tests/ui/auto-traits/auto-trait-validation.fixed +++ b/tests/ui/auto-traits/auto-trait-validation.fixed @@ -1,4 +1,5 @@ #![feature(auto_traits)] +#![allow(dead_code)] // run-rustfix diff --git a/tests/ui/auto-traits/auto-trait-validation.rs b/tests/ui/auto-traits/auto-trait-validation.rs index d43055e270b..e209aa13220 100644 --- a/tests/ui/auto-traits/auto-trait-validation.rs +++ b/tests/ui/auto-traits/auto-trait-validation.rs @@ -1,4 +1,5 @@ #![feature(auto_traits)] +#![allow(dead_code)] // run-rustfix diff --git a/tests/ui/auto-traits/auto-trait-validation.stderr b/tests/ui/auto-traits/auto-trait-validation.stderr index 89b63d23d4c..a6e5ac54869 100644 --- a/tests/ui/auto-traits/auto-trait-validation.stderr +++ b/tests/ui/auto-traits/auto-trait-validation.stderr @@ -1,5 +1,5 @@ error[E0567]: auto traits cannot have generic parameters - --> $DIR/auto-trait-validation.rs:5:19 + --> $DIR/auto-trait-validation.rs:6:19 | LL | auto trait Generic<T> {} | -------^^^ help: remove the parameters @@ -7,7 +7,7 @@ LL | auto trait Generic<T> {} | auto trait cannot have generic parameters error[E0568]: auto traits cannot have super traits or lifetime bounds - --> $DIR/auto-trait-validation.rs:7:17 + --> $DIR/auto-trait-validation.rs:8:17 | LL | auto trait Bound : Copy {} | -----^^^^^^^ help: remove the super traits or lifetime bounds @@ -15,7 +15,7 @@ LL | auto trait Bound : Copy {} | auto traits cannot have super traits or lifetime bounds error[E0568]: auto traits cannot have super traits or lifetime bounds - --> $DIR/auto-trait-validation.rs:9:25 + --> $DIR/auto-trait-validation.rs:10:25 | LL | auto trait LifetimeBound : 'static {} | -------------^^^^^^^^^^ help: remove the super traits or lifetime bounds @@ -23,7 +23,7 @@ LL | auto trait LifetimeBound : 'static {} | auto traits cannot have super traits or lifetime bounds error[E0380]: auto traits cannot have associated items - --> $DIR/auto-trait-validation.rs:11:25 + --> $DIR/auto-trait-validation.rs:12:25 | LL | auto trait MyTrait { fn foo() {} } | ------- ---^^^----- diff --git a/tests/ui/auto-traits/auto-traits.rs b/tests/ui/auto-traits/auto-traits.rs index 6d8e1a52ec1..1e0fbcc1fdf 100644 --- a/tests/ui/auto-traits/auto-traits.rs +++ b/tests/ui/auto-traits/auto-traits.rs @@ -19,8 +19,8 @@ fn take_auto_unsafe<T: AutoUnsafe>(_: T) {} fn main() { // Parse inside functions. - auto trait AutoInner {} - unsafe auto trait AutoUnsafeInner {} + auto trait AutoInner {} //~ WARN trait `AutoInner` is never used + unsafe auto trait AutoUnsafeInner {} //~ WARN trait `AutoUnsafeInner` is never used take_auto(0); take_auto(AutoBool(true)); diff --git a/tests/ui/auto-traits/auto-traits.stderr b/tests/ui/auto-traits/auto-traits.stderr new file mode 100644 index 00000000000..34be8d3f67b --- /dev/null +++ b/tests/ui/auto-traits/auto-traits.stderr @@ -0,0 +1,16 @@ +warning: trait `AutoInner` is never used + --> $DIR/auto-traits.rs:22:16 + | +LL | auto trait AutoInner {} + | ^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: trait `AutoUnsafeInner` is never used + --> $DIR/auto-traits.rs:23:23 + | +LL | unsafe auto trait AutoUnsafeInner {} + | ^^^^^^^^^^^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs index 98359ef51b7..c0ed1e00f3b 100644 --- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs @@ -6,6 +6,7 @@ auto trait Magic : Sized where Option<Self> : Magic {} //~ ERROR E0568 impl<T:Magic> Magic for T {} fn copy<T: Magic>(x: T) -> (T, T) { (x, x) } +//~^ ERROR: use of moved value #[derive(Debug)] struct NoClone; diff --git a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr index 547b4bb5448..dcf1c02bcee 100644 --- a/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr +++ b/tests/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr @@ -14,6 +14,21 @@ LL | auto trait Magic : Sized where Option<Self> : Magic {} | | | auto traits cannot have super traits or lifetime bounds -error: aborting due to 2 previous errors +error[E0382]: use of moved value: `x` + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:8:41 + | +LL | fn copy<T: Magic>(x: T) -> (T, T) { (x, x) } + | - - ^ value used here after move + | | | + | | value moved here + | move occurs because `x` has type `T`, which does not implement the `Copy` trait + | +help: consider further restricting this bound + | +LL | fn copy<T: Magic + Copy>(x: T) -> (T, T) { (x, x) } + | ++++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0568`. +Some errors have detailed explanations: E0382, E0568. +For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/binding/irrefutable-if-let-without-else.fixed b/tests/ui/binding/irrefutable-if-let-without-else.fixed new file mode 100644 index 00000000000..3d7f4695ca8 --- /dev/null +++ b/tests/ui/binding/irrefutable-if-let-without-else.fixed @@ -0,0 +1,25 @@ +// run-rustfix +enum Enum { + Variant(i32), +} +struct Struct(i32); + +fn foo(x: Enum) -> i32 { + let Enum::Variant(value) = x; + value +} +fn bar(x: Enum) -> i32 { + let Enum::Variant(value) = x; + let x = value + 1; + x +} +fn baz(x: Struct) -> i32 { + let Struct(value) = x; + let x = value + 1; + x +} +fn main() { + let _ = foo(Enum::Variant(42)); + let _ = bar(Enum::Variant(42)); + let _ = baz(Struct(42)); +} diff --git a/tests/ui/binding/irrefutable-if-let-without-else.rs b/tests/ui/binding/irrefutable-if-let-without-else.rs new file mode 100644 index 00000000000..5aaf4ace3f8 --- /dev/null +++ b/tests/ui/binding/irrefutable-if-let-without-else.rs @@ -0,0 +1,28 @@ +// run-rustfix +enum Enum { + Variant(i32), +} +struct Struct(i32); + +fn foo(x: Enum) -> i32 { + if let Enum::Variant(value) = x { //~ ERROR `if` may be missing an `else` clause + value + } +} +fn bar(x: Enum) -> i32 { + if let Enum::Variant(value) = x { //~ ERROR `if` may be missing an `else` clause + let x = value + 1; + x + } +} +fn baz(x: Struct) -> i32 { + if let Struct(value) = x { //~ ERROR `if` may be missing an `else` clause + let x = value + 1; + x + } +} +fn main() { + let _ = foo(Enum::Variant(42)); + let _ = bar(Enum::Variant(42)); + let _ = baz(Struct(42)); +} diff --git a/tests/ui/binding/irrefutable-if-let-without-else.stderr b/tests/ui/binding/irrefutable-if-let-without-else.stderr new file mode 100644 index 00000000000..e234cfdd945 --- /dev/null +++ b/tests/ui/binding/irrefutable-if-let-without-else.stderr @@ -0,0 +1,61 @@ +error[E0317]: `if` may be missing an `else` clause + --> $DIR/irrefutable-if-let-without-else.rs:8:5 + | +LL | fn foo(x: Enum) -> i32 { + | --- expected `i32` because of this return type +LL | / if let Enum::Variant(value) = x { +LL | | value +LL | | } + | |_____^ expected `i32`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type +help: consider using an irrefutable `let` binding instead + | +LL ~ let Enum::Variant(value) = x; +LL ~ value + | + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/irrefutable-if-let-without-else.rs:13:5 + | +LL | fn bar(x: Enum) -> i32 { + | --- expected `i32` because of this return type +LL | / if let Enum::Variant(value) = x { +LL | | let x = value + 1; +LL | | x +LL | | } + | |_____^ expected `i32`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type +help: consider using an irrefutable `let` binding instead + | +LL ~ let Enum::Variant(value) = x; +LL ~ let x = value + 1; +LL ~ x + | + +error[E0317]: `if` may be missing an `else` clause + --> $DIR/irrefutable-if-let-without-else.rs:19:5 + | +LL | fn baz(x: Struct) -> i32 { + | --- expected `i32` because of this return type +LL | / if let Struct(value) = x { +LL | | let x = value + 1; +LL | | x +LL | | } + | |_____^ expected `i32`, found `()` + | + = note: `if` expressions without `else` evaluate to `()` + = help: consider adding an `else` block that evaluates to the expected type +help: consider using an irrefutable `let` binding instead + | +LL ~ let Struct(value) = x; +LL ~ let x = value + 1; +LL ~ x + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0317`. diff --git a/tests/ui/issues/issue-62375.rs b/tests/ui/binop/issue-62375.rs index a2c8fe551bb..a2c8fe551bb 100644 --- a/tests/ui/issues/issue-62375.rs +++ b/tests/ui/binop/issue-62375.rs diff --git a/tests/ui/issues/issue-62375.stderr b/tests/ui/binop/issue-62375.stderr index faca94a03f0..faca94a03f0 100644 --- a/tests/ui/issues/issue-62375.stderr +++ b/tests/ui/binop/issue-62375.stderr diff --git a/tests/ui/binop/issue-77910-1.rs b/tests/ui/binop/issue-77910-1.rs index 95bbd6a60ec..4b7ee77b46d 100644 --- a/tests/ui/binop/issue-77910-1.rs +++ b/tests/ui/binop/issue-77910-1.rs @@ -1,6 +1,6 @@ fn foo(s: &i32) -> &i32 { let xs; - xs + xs //~ ERROR: isn't initialized } fn main() { let y; diff --git a/tests/ui/binop/issue-77910-1.stderr b/tests/ui/binop/issue-77910-1.stderr index 263a35d9829..6402e568188 100644 --- a/tests/ui/binop/issue-77910-1.stderr +++ b/tests/ui/binop/issue-77910-1.stderr @@ -22,7 +22,20 @@ LL | assert_eq!(foo, y); = help: use parentheses to call this function: `foo(/* &i32 */)` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 2 previous errors +error[E0381]: used binding `xs` isn't initialized + --> $DIR/issue-77910-1.rs:3:5 + | +LL | let xs; + | -- binding declared here but left uninitialized +LL | xs + | ^^ `xs` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let xs = todo!(); + | +++++++++ + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0277, E0369. +Some errors have detailed explanations: E0277, E0369, E0381. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/binop/issue-77910-2.rs b/tests/ui/binop/issue-77910-2.rs index 2bb48d36576..5ea03e82b2f 100644 --- a/tests/ui/binop/issue-77910-2.rs +++ b/tests/ui/binop/issue-77910-2.rs @@ -1,6 +1,6 @@ fn foo(s: &i32) -> &i32 { let xs; - xs + xs //~ ERROR: isn't initialized } fn main() { let y; diff --git a/tests/ui/binop/issue-77910-2.stderr b/tests/ui/binop/issue-77910-2.stderr index e58ae0fad9b..a14560ff188 100644 --- a/tests/ui/binop/issue-77910-2.stderr +++ b/tests/ui/binop/issue-77910-2.stderr @@ -11,6 +11,20 @@ help: use parentheses to call this function LL | if foo(/* &i32 */) == y {} | ++++++++++++ -error: aborting due to 1 previous error +error[E0381]: used binding `xs` isn't initialized + --> $DIR/issue-77910-2.rs:3:5 + | +LL | let xs; + | -- binding declared here but left uninitialized +LL | xs + | ^^ `xs` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let xs = todo!(); + | +++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0369`. +Some errors have detailed explanations: E0369, E0381. +For more information about an error, try `rustc --explain E0369`. diff --git a/tests/ui/box/unit/unique-object-noncopyable.stderr b/tests/ui/box/unit/unique-object-noncopyable.stderr index 49547872d1a..8ea6edb48a7 100644 --- a/tests/ui/box/unit/unique-object-noncopyable.stderr +++ b/tests/ui/box/unit/unique-object-noncopyable.stderr @@ -12,6 +12,9 @@ LL | let _z = y.clone(); which is required by `Box<dyn Foo>: Clone` `dyn Foo: Clone` which is required by `Box<dyn Foo>: Clone` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `clone`, perhaps you need to implement it: + candidate #1: `Clone` error: aborting due to 1 previous error diff --git a/tests/ui/box/unit/unique-pinned-nocopy.stderr b/tests/ui/box/unit/unique-pinned-nocopy.stderr index d2bf72249c4..69428604b19 100644 --- a/tests/ui/box/unit/unique-pinned-nocopy.stderr +++ b/tests/ui/box/unit/unique-pinned-nocopy.stderr @@ -10,9 +10,6 @@ LL | let _j = i.clone(); = note: the following trait bounds were not satisfied: `R: Clone` which is required by `Box<R>: Clone` - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `clone`, perhaps you need to implement it: - candidate #1: `Clone` help: consider annotating `R` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs index 2edc52c6f55..7e8820cb2c6 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs +++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata2.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_imports)] diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs b/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs index 8d247715784..50914b1de53 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs +++ b/tests/ui/builtin-superkinds/builtin-superkinds-simple2.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Simple test case of implementing a trait with super-builtin-kinds. // pretty-expanded FIXME #23616 diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs b/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs index f999dfff786..0577acc572a 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs +++ b/tests/ui/builtin-superkinds/builtin-superkinds-typaram.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Tests correct implementation of traits with super-builtin-kinds // using a bounded type parameter. diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs index 249481467e6..be6a6bb8b17 100644 --- a/tests/ui/cast/cast-rfc0401-vtable-kinds.rs +++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.rs @@ -8,7 +8,7 @@ trait Foo<T> { fn foo(&self, _: T) -> u32 { 42 } } -trait Bar { +trait Bar { //~ WARN trait `Bar` is never used fn bar(&self) { println!("Bar!"); } } diff --git a/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr b/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr new file mode 100644 index 00000000000..952687e98d0 --- /dev/null +++ b/tests/ui/cast/cast-rfc0401-vtable-kinds.stderr @@ -0,0 +1,10 @@ +warning: trait `Bar` is never used + --> $DIR/cast-rfc0401-vtable-kinds.rs:11:7 + | +LL | trait Bar { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/cast/enum-to-numeric-cast.rs b/tests/ui/cast/enum-to-numeric-cast.rs new file mode 100644 index 00000000000..d5ab2a6a1fe --- /dev/null +++ b/tests/ui/cast/enum-to-numeric-cast.rs @@ -0,0 +1,46 @@ +// Tests that `as` casts from enums to numeric types succeed +// only if the enum type is "unit-only" or "fieldless" as +// described here: https://doc.rust-lang.org/reference/items/enumerations.html#casting + +pub enum UnitOnly { + Foo, + Bar, + Baz, +} + +pub enum Fieldless { + Tuple(), + Struct{}, + Unit, +} + +pub enum NotUnitOnlyOrFieldless { + Foo, + Bar(u8), + Baz +} + +fn main() { + let unit_only = UnitOnly::Foo; + + let _ = unit_only as isize; + let _ = unit_only as i32; + let _ = unit_only as usize; + let _ = unit_only as u32; + + + let fieldless = Fieldless::Struct{}; + + let _ = fieldless as isize; + let _ = fieldless as i32; + let _ = fieldless as usize; + let _ = fieldless as u32; + + + let not_unit_only_or_fieldless = NotUnitOnlyOrFieldless::Foo; + + let _ = not_unit_only_or_fieldless as isize; //~ ERROR non-primitive cast: `NotUnitOnlyOrFieldless` as `isize` + let _ = not_unit_only_or_fieldless as i32; //~ ERROR non-primitive cast: `NotUnitOnlyOrFieldless` as `i32` + let _ = not_unit_only_or_fieldless as usize; //~ ERROR non-primitive cast: `NotUnitOnlyOrFieldless` as `usize` + let _ = not_unit_only_or_fieldless as u32; //~ ERROR non-primitive cast: `NotUnitOnlyOrFieldless` as `u32` +} diff --git a/tests/ui/cast/enum-to-numeric-cast.stderr b/tests/ui/cast/enum-to-numeric-cast.stderr new file mode 100644 index 00000000000..1a49cb97451 --- /dev/null +++ b/tests/ui/cast/enum-to-numeric-cast.stderr @@ -0,0 +1,35 @@ +error[E0605]: non-primitive cast: `NotUnitOnlyOrFieldless` as `isize` + --> $DIR/enum-to-numeric-cast.rs:42:13 + | +LL | let _ = not_unit_only_or_fieldless as isize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less + | + = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information + +error[E0605]: non-primitive cast: `NotUnitOnlyOrFieldless` as `i32` + --> $DIR/enum-to-numeric-cast.rs:43:13 + | +LL | let _ = not_unit_only_or_fieldless as i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less + | + = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information + +error[E0605]: non-primitive cast: `NotUnitOnlyOrFieldless` as `usize` + --> $DIR/enum-to-numeric-cast.rs:44:13 + | +LL | let _ = not_unit_only_or_fieldless as usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less + | + = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information + +error[E0605]: non-primitive cast: `NotUnitOnlyOrFieldless` as `u32` + --> $DIR/enum-to-numeric-cast.rs:45:13 + | +LL | let _ = not_unit_only_or_fieldless as u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less + | + = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/cast/fat-ptr-cast-rpass.rs b/tests/ui/cast/fat-ptr-cast-rpass.rs index f5747eb8b96..c79468caddd 100644 --- a/tests/ui/cast/fat-ptr-cast-rpass.rs +++ b/tests/ui/cast/fat-ptr-cast-rpass.rs @@ -3,7 +3,7 @@ #![feature(ptr_metadata)] trait Foo { - fn foo(&self) {} + fn foo(&self) {} //~ WARN method `foo` is never used } struct Bar; diff --git a/tests/ui/cast/fat-ptr-cast-rpass.stderr b/tests/ui/cast/fat-ptr-cast-rpass.stderr new file mode 100644 index 00000000000..d01688e0cc3 --- /dev/null +++ b/tests/ui/cast/fat-ptr-cast-rpass.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/fat-ptr-cast-rpass.rs:6:8 + | +LL | trait Foo { + | --- method in this trait +LL | fn foo(&self) {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/cast/issue-88621.stderr b/tests/ui/cast/issue-88621.stderr index 0459ce5eabd..201651a207a 100644 --- a/tests/ui/cast/issue-88621.stderr +++ b/tests/ui/cast/issue-88621.stderr @@ -2,7 +2,9 @@ error[E0605]: non-primitive cast: `Kind2` as `u8` --> $DIR/issue-88621.rs:9:13 | LL | let _ = Kind2::Foo() as u8; - | ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + | ^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less + | + = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information error: aborting due to 1 previous error diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs new file mode 100644 index 00000000000..a6e68e1b710 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs @@ -0,0 +1,12 @@ +// #120427 +// This test checks we won't suggest more than 3 span suggestions for cfg names +// +// check-pass +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg(foo,values("value")) --check-cfg=cfg(bar,values("value")) --check-cfg=cfg(bee,values("value")) --check-cfg=cfg(cow,values("value")) + +#[cfg(value)] +//~^ WARNING unexpected `cfg` condition name: `value` +fn x() {} + +fn main() {} diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr new file mode 100644 index 00000000000..82d471d715b --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr @@ -0,0 +1,13 @@ +warning: unexpected `cfg` condition name: `value` + --> $DIR/cfg-value-for-cfg-name-duplicate.rs:8:7 + | +LL | #[cfg(value)] + | ^^^^^ + | + = help: expected names are: `bar`, `bee`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: to expect this configuration use `--check-cfg=cfg(value)` + = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs new file mode 100644 index 00000000000..edde6244ed1 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs @@ -0,0 +1,12 @@ +// #120427 +// This test checks that when a single cfg has a value for user's specified name +// +// check-pass +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg(foo,values("my_value")) --check-cfg=cfg(bar,values("my_value")) + +#[cfg(my_value)] +//~^ WARNING unexpected `cfg` condition name: `my_value` +fn x() {} + +fn main() {} diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr new file mode 100644 index 00000000000..b88ee71a156 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr @@ -0,0 +1,21 @@ +warning: unexpected `cfg` condition name: `my_value` + --> $DIR/cfg-value-for-cfg-name-multiple.rs:8:7 + | +LL | #[cfg(my_value)] + | ^^^^^^^^ + | + = help: expected names are: `bar`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: to expect this configuration use `--check-cfg=cfg(my_value)` + = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default +help: found config with similar value + | +LL | #[cfg(foo = "my_value")] + | ~~~~~~~~~~~~~~~~ +help: found config with similar value + | +LL | #[cfg(bar = "my_value")] + | ~~~~~~~~~~~~~~~~ + +warning: 1 warning emitted + diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name.rs new file mode 100644 index 00000000000..7a0c345b7ca --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.rs @@ -0,0 +1,18 @@ +// #120427 +// This test checks that when a single cfg has a value for user's specified name +// suggest to use `#[cfg(target_os = "linux")]` instead of `#[cfg(linux)]` +// +// check-pass +// compile-flags: -Z unstable-options +// compile-flags: --check-cfg=cfg() + +#[cfg(linux)] +//~^ WARNING unexpected `cfg` condition name: `linux` +fn x() {} + +// will not suggest if the cfg has a value +#[cfg(linux = "os-name")] +//~^ WARNING unexpected `cfg` condition name: `linux` +fn y() {} + +fn main() {} diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr new file mode 100644 index 00000000000..c0447551424 --- /dev/null +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr @@ -0,0 +1,22 @@ +warning: unexpected `cfg` condition name: `linux` + --> $DIR/cfg-value-for-cfg-name.rs:9:7 + | +LL | #[cfg(linux)] + | ^^^^^ help: found config with similar value: `target_os = "linux"` + | + = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows` + = help: to expect this configuration use `--check-cfg=cfg(linux)` + = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: unexpected `cfg` condition name: `linux` + --> $DIR/cfg-value-for-cfg-name.rs:14:7 + | +LL | #[cfg(linux = "os-name")] + | ^^^^^^^^^^^^^^^^^ + | + = help: to expect this configuration use `--check-cfg=cfg(linux, values("os-name"))` + = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration + +warning: 2 warnings emitted + diff --git a/tests/ui/class-cast-to-trait.rs b/tests/ui/class-cast-to-trait.rs index 345d6efd2d9..ca98e4c9003 100644 --- a/tests/ui/class-cast-to-trait.rs +++ b/tests/ui/class-cast-to-trait.rs @@ -1,5 +1,5 @@ trait Noisy { - fn speak(&self); + fn speak(&mut self); } struct Cat { @@ -10,7 +10,7 @@ struct Cat { } impl Cat { - pub fn eat(&self) -> bool { + pub fn eat(&mut self) -> bool { if self.how_hungry > 0 { println!("OM NOM NOM"); self.how_hungry -= 2; @@ -24,12 +24,12 @@ impl Cat { } impl Noisy for Cat { - fn speak(&self) { self.meow(); } + fn speak(&mut self) { self.meow(); } } impl Cat { - fn meow(&self) { + fn meow(&mut self) { println!("Meow"); self.meows += 1; if self.meows % 5 == 0 { diff --git a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs index a2290d85020..16f7df1b363 100644 --- a/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs +++ b/tests/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs @@ -15,6 +15,6 @@ fn foo () -> impl FnMut()->() { c } fn main() { - let c = foo(); + let mut c = foo(); c(); } diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr index c83ba41976b..8a2aaade665 100644 --- a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr @@ -5,8 +5,19 @@ LL | NUMBER_POINTER => (), | ^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> = note: `#[warn(pointer_structural_match)]` on by default warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/match-edge-cases_1.rs:29:13 + | +LL | NUMBER_POINTER => (), + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr new file mode 100644 index 00000000000..b54341f82c7 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.min_exhaustive_patterns.stderr @@ -0,0 +1,11 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/multivariant.rs:7:46 + | +LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 <https://github.com/rust-lang/rust/issues/119612> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs index 72652ef6034..bc2386e5d23 100644 --- a/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs +++ b/tests/ui/closures/2229_closure_analysis/run_pass/multivariant.rs @@ -1,8 +1,11 @@ // Test precise capture of a multi-variant enum (when remaining variants are // visibly uninhabited). +// revisions: min_exhaustive_patterns exhaustive_patterns // edition:2021 // run-pass -#![feature(exhaustive_patterns)] +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![feature(never_type)] pub fn main() { diff --git a/tests/ui/closures/binder/implicit-stuff.rs b/tests/ui/closures/binder/implicit-stuff.rs index 09e4c747afe..c976c200b0c 100644 --- a/tests/ui/closures/binder/implicit-stuff.rs +++ b/tests/ui/closures/binder/implicit-stuff.rs @@ -24,4 +24,5 @@ fn main() { //~| ERROR `'_` cannot be used here let _ = for<'a> |x: &()| -> &'a () { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here let _ = for<'a> |x: &'a ()| -> &() { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here + //~^ ERROR: lifetime may not live long enough } diff --git a/tests/ui/closures/binder/implicit-stuff.stderr b/tests/ui/closures/binder/implicit-stuff.stderr index cec2a60ba28..330a05a79ba 100644 --- a/tests/ui/closures/binder/implicit-stuff.stderr +++ b/tests/ui/closures/binder/implicit-stuff.stderr @@ -102,6 +102,15 @@ LL | let _ = for<'a> |x: &'a _, y, z: _| -> &'a _ { | | | `for<...>` is here -error: aborting due to 15 previous errors +error: lifetime may not live long enough + --> $DIR/implicit-stuff.rs:26:42 + | +LL | let _ = for<'a> |x: &'a ()| -> &() { x }; + | -- - ^ returning this value requires that `'a` must outlive `'1` + | | | + | | let's call the lifetime of this reference `'1` + | lifetime `'a` defined here + +error: aborting due to 16 previous errors For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/closures/issue-109188.rs b/tests/ui/closures/issue-109188.rs index cae1ced9958..03c8b415774 100644 --- a/tests/ui/closures/issue-109188.rs +++ b/tests/ui/closures/issue-109188.rs @@ -7,13 +7,13 @@ struct X(Y); struct Y; -fn consume_fnmut(f: &dyn FnMut()) { +fn consume_fnmut(f: &mut dyn FnMut()) { f(); } fn move_into_fnmut() { let x = move_into_fnmut(); - consume_fnmut(&|| { + consume_fnmut(&mut || { let Either::One(_t) = x; //~ ERROR mismatched types let Either::Two(_t) = x; //~ ERROR mismatched types }); diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs index 6320d296373..72c14cd7a69 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs @@ -2,8 +2,11 @@ // needs-llvm-components: arm #![feature(cmse_nonsecure_entry, no_core, lang_items)] #![no_core] -#[lang="sized"] -trait Sized { } +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} #[no_mangle] #[cmse_nonsecure_entry] diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr index 4d34f0d7509..c3fae3d8bbb 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr @@ -1,5 +1,5 @@ error[E0776]: `#[cmse_nonsecure_entry]` requires C ABI - --> $DIR/wrong-abi.rs:9:1 + --> $DIR/wrong-abi.rs:12:1 | LL | #[cmse_nonsecure_entry] | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/issues/issue-82833-slice-miscompile.rs b/tests/ui/codegen/issue-82833-slice-miscompile.rs index 8cf6a3137e2..8cf6a3137e2 100644 --- a/tests/ui/issues/issue-82833-slice-miscompile.rs +++ b/tests/ui/codegen/issue-82833-slice-miscompile.rs diff --git a/tests/ui/coercion/issue-14589.rs b/tests/ui/coercion/issue-14589.rs index f92385f8d72..6f95b30be06 100644 --- a/tests/ui/coercion/issue-14589.rs +++ b/tests/ui/coercion/issue-14589.rs @@ -19,6 +19,6 @@ impl<T> Test<T> { fn send(&self, _: T) {} } -trait Foo { fn dummy(&self) { }} +trait Foo { fn dummy(&self) { }} //~ WARN method `dummy` is never used struct Output(#[allow(dead_code)] isize); impl Foo for Output {} diff --git a/tests/ui/coercion/issue-14589.stderr b/tests/ui/coercion/issue-14589.stderr new file mode 100644 index 00000000000..37b7fce7462 --- /dev/null +++ b/tests/ui/coercion/issue-14589.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-14589.rs:22:16 + | +LL | trait Foo { fn dummy(&self) { }} + | --- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-26905-rpass.rs b/tests/ui/coercion/issue-26905-rpass.rs index 2d5827f476b..2d5827f476b 100644 --- a/tests/ui/issues/issue-26905-rpass.rs +++ b/tests/ui/coercion/issue-26905-rpass.rs diff --git a/tests/ui/issues/issue-26905.rs b/tests/ui/coercion/issue-26905.rs index 4c5c67d58bc..4c5c67d58bc 100644 --- a/tests/ui/issues/issue-26905.rs +++ b/tests/ui/coercion/issue-26905.rs diff --git a/tests/ui/issues/issue-26905.stderr b/tests/ui/coercion/issue-26905.stderr index 86f6a14cd10..86f6a14cd10 100644 --- a/tests/ui/issues/issue-26905.stderr +++ b/tests/ui/coercion/issue-26905.stderr diff --git a/tests/ui/coherence/associated-type2.rs b/tests/ui/coherence/associated-type2.rs new file mode 100644 index 00000000000..2aadfb04af0 --- /dev/null +++ b/tests/ui/coherence/associated-type2.rs @@ -0,0 +1,20 @@ +//! A regression test for #120343. The overlap error was previously +//! silenced in coherence because projecting `<() as ToUnit>::Unit` +//! failed. Then then silenced the missing items error in the `ToUnit` +//! impl, causing us to not emit any errors and ICEing due to a +//! `span_delay_bug`. + +trait ToUnit { + type Unit; +} + +impl<T> ToUnit for *const T {} +//~^ ERROR: not all trait items implemented + +trait Overlap<T> {} + +impl<T> Overlap<T> for T {} + +impl<T> Overlap<<*const T as ToUnit>::Unit> for T {} + +fn main() {} diff --git a/tests/ui/coherence/associated-type2.stderr b/tests/ui/coherence/associated-type2.stderr new file mode 100644 index 00000000000..62d3d8b8ebd --- /dev/null +++ b/tests/ui/coherence/associated-type2.stderr @@ -0,0 +1,12 @@ +error[E0046]: not all trait items implemented, missing: `Unit` + --> $DIR/associated-type2.rs:11:1 + | +LL | type Unit; + | --------- `Unit` from trait +... +LL | impl<T> ToUnit for *const T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Unit` in implementation + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs index 6a9db217373..cdec81271d0 100644 --- a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.rs @@ -22,6 +22,7 @@ struct MyType { impl MyTrait<MyType> for MyType { //~^ ERROR E0119 fn get(&self) -> usize { (*self).clone() } + //~^ ERROR incompatible type } fn main() { } diff --git a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr index ddb7474c289..471dfe1cae7 100644 --- a/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr +++ b/tests/ui/coherence/coherence-blanket-conflicts-with-specific-multidispatch.stderr @@ -7,6 +7,24 @@ LL | impl<T> MyTrait<T> for T { LL | impl MyTrait<MyType> for MyType { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyType` -error: aborting due to 1 previous error +error[E0053]: method `get` has an incompatible type for trait + --> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:24:22 + | +LL | fn get(&self) -> usize { (*self).clone() } + | ^^^^^ + | | + | expected `MyType`, found `usize` + | help: change the output type to match the trait: `MyType` + | +note: type in trait + --> $DIR/coherence-blanket-conflicts-with-specific-multidispatch.rs:8:22 + | +LL | fn get(&self) -> T; + | ^ + = note: expected signature `fn(&MyType) -> MyType` + found signature `fn(&MyType) -> usize` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0053, E0119. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/coherence/coherence-multidispatch-tuple.rs b/tests/ui/coherence/coherence-multidispatch-tuple.rs index fa1d4bbb496..b04b2a296b5 100644 --- a/tests/ui/coherence/coherence-multidispatch-tuple.rs +++ b/tests/ui/coherence/coherence-multidispatch-tuple.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_imports)] // pretty-expanded FIXME #23616 diff --git a/tests/ui/coherence/coherence-orphan.rs b/tests/ui/coherence/coherence-orphan.rs index bed782203af..985cfe87161 100644 --- a/tests/ui/coherence/coherence-orphan.rs +++ b/tests/ui/coherence/coherence-orphan.rs @@ -9,10 +9,13 @@ struct TheType; impl TheTrait<usize> for isize { } //~^ ERROR E0117 +//~| ERROR not all trait items implemented impl TheTrait<TheType> for isize { } +//~^ ERROR not all trait items implemented impl TheTrait<isize> for TheType { } +//~^ ERROR not all trait items implemented impl !Send for Vec<isize> { } //~ ERROR E0117 //~^ WARNING diff --git a/tests/ui/coherence/coherence-orphan.stderr b/tests/ui/coherence/coherence-orphan.stderr index 9ec1d0dc32a..78fad837647 100644 --- a/tests/ui/coherence/coherence-orphan.stderr +++ b/tests/ui/coherence/coherence-orphan.stderr @@ -11,7 +11,7 @@ LL | impl TheTrait<usize> for isize { } = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate - --> $DIR/coherence-orphan.rs:17:1 + --> $DIR/coherence-orphan.rs:20:1 | LL | impl !Send for Vec<isize> { } | ^^^^^^^^^^^^^^^---------- @@ -22,7 +22,7 @@ LL | impl !Send for Vec<isize> { } = note: define and implement a trait or new type instead warning: cross-crate traits with a default impl, like `Send`, should not be specialized - --> $DIR/coherence-orphan.rs:17:1 + --> $DIR/coherence-orphan.rs:20:1 | LL | impl !Send for Vec<isize> { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,6 +34,31 @@ note: try using the same sequence of generic parameters as the struct definition --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL = note: `#[warn(suspicious_auto_trait_impls)]` on by default -error: aborting due to 2 previous errors; 1 warning emitted +error[E0046]: not all trait items implemented, missing: `the_fn` + --> $DIR/coherence-orphan.rs:10:1 + | +LL | impl TheTrait<usize> for isize { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation + | + = help: implement the missing item: `fn the_fn(&self) { todo!() }` + +error[E0046]: not all trait items implemented, missing: `the_fn` + --> $DIR/coherence-orphan.rs:14:1 + | +LL | impl TheTrait<TheType> for isize { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation + | + = help: implement the missing item: `fn the_fn(&self) { todo!() }` + +error[E0046]: not all trait items implemented, missing: `the_fn` + --> $DIR/coherence-orphan.rs:17:1 + | +LL | impl TheTrait<isize> for TheType { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `the_fn` in implementation + | + = help: implement the missing item: `fn the_fn(&self) { todo!() }` + +error: aborting due to 5 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0117`. +Some errors have detailed explanations: E0046, E0117. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/coherence/deep-bad-copy-reason.rs b/tests/ui/coherence/deep-bad-copy-reason.rs index 97fd3f719bf..f1c2698bad5 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.rs +++ b/tests/ui/coherence/deep-bad-copy-reason.rs @@ -5,12 +5,15 @@ extern "Rust" { } pub struct ListS<T> { + //~^ NOTE: required because it appears within the type len: usize, data: [T; 0], opaque: OpaqueListContents, } pub struct Interned<'a, T>(&'a T); +//~^ NOTE: required by an implicit `Sized` +//~| NOTE: required by the implicit `Sized` impl<'a, T> Clone for Interned<'a, T> { fn clone(&self) -> Self { @@ -23,6 +26,8 @@ impl<'a, T> Copy for Interned<'a, T> {} pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>); //~^ NOTE this field does not implement `Copy` //~| NOTE the `Copy` impl for `Interned<'tcx, ListS<T>>` requires that `OpaqueListContents: Sized` +//~| NOTE: doesn't have a size known at compile-time +//~| ERROR: cannot be known at compilation time impl<'tcx, T> Clone for List<'tcx, T> { fn clone(&self) -> Self { diff --git a/tests/ui/coherence/deep-bad-copy-reason.stderr b/tests/ui/coherence/deep-bad-copy-reason.stderr index e79abe35597..fe5ae9b08b4 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.stderr +++ b/tests/ui/coherence/deep-bad-copy-reason.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/deep-bad-copy-reason.rs:33:24 + --> $DIR/deep-bad-copy-reason.rs:38:24 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>); | ------------------------ this field does not implement `Copy` @@ -8,11 +8,34 @@ LL | impl<'tcx, T> Copy for List<'tcx, T> {} | ^^^^^^^^^^^^^ | note: the `Copy` impl for `Interned<'tcx, ListS<T>>` requires that `OpaqueListContents: Sized` - --> $DIR/deep-bad-copy-reason.rs:23:26 + --> $DIR/deep-bad-copy-reason.rs:26:26 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>); | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0277]: the size for values of type `OpaqueListContents` cannot be known at compilation time + --> $DIR/deep-bad-copy-reason.rs:26:26 + | +LL | pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>); + | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `ListS<T>`, the trait `Sized` is not implemented for `OpaqueListContents`, which is required by `ListS<T>: Sized` +note: required because it appears within the type `ListS<T>` + --> $DIR/deep-bad-copy-reason.rs:7:12 + | +LL | pub struct ListS<T> { + | ^^^^^ +note: required by an implicit `Sized` bound in `Interned` + --> $DIR/deep-bad-copy-reason.rs:14:25 + | +LL | pub struct Interned<'a, T>(&'a T); + | ^ required by the implicit `Sized` requirement on this type parameter in `Interned` +help: consider relaxing the implicit `Sized` restriction + | +LL | pub struct Interned<'a, T: ?Sized>(&'a T); + | ++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0204`. +Some errors have detailed explanations: E0204, E0277. +For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr index 428ee902ea5..4ad8257d2c1 100644 --- a/tests/ui/coherence/occurs-check/opaques.next.stderr +++ b/tests/ui/coherence/occurs-check/opaques.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait<Alias<_>>` for type `Alias<_>` - --> $DIR/opaques.rs:29:1 + --> $DIR/opaques.rs:30:1 | LL | impl<T> Trait<T> for T { | ---------------------- first implementation here @@ -7,6 +7,13 @@ LL | impl<T> Trait<T> for T { LL | impl<T> Trait<T> for defining_scope::Alias<T> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Alias<_>` -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/opaques.rs:13:20 + | +LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> { + | ^ cannot infer type for struct `Container<Alias<T>, T>` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0282. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs index 2fa9dcebfde..73cd42bf3f2 100644 --- a/tests/ui/coherence/occurs-check/opaques.rs +++ b/tests/ui/coherence/occurs-check/opaques.rs @@ -11,6 +11,7 @@ mod defining_scope { pub type Alias<T> = impl Sized; pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> { + //[next]~^ ERROR type annotations needed x } } diff --git a/tests/ui/const-generics/associated-type-bound.rs b/tests/ui/const-generics/associated-type-bound.rs index 3044736b47e..0a57352c10d 100644 --- a/tests/ui/const-generics/associated-type-bound.rs +++ b/tests/ui/const-generics/associated-type-bound.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass trait Bar<const N: usize> {} trait Foo<const N: usize> { diff --git a/tests/ui/const-generics/condition-in-trait-const-arg.rs b/tests/ui/const-generics/condition-in-trait-const-arg.rs index 6f85237cf0a..74a663a53ec 100644 --- a/tests/ui/const-generics/condition-in-trait-const-arg.rs +++ b/tests/ui/const-generics/condition-in-trait-const-arg.rs @@ -1,5 +1,5 @@ // Checks that `impl Trait<{anon_const}> for Type` evaluates successfully. -// run-pass +// check-pass // revisions: full min #![cfg_attr(full, feature(generic_const_exprs))] diff --git a/tests/ui/const-generics/dyn-supertraits.rs b/tests/ui/const-generics/dyn-supertraits.rs index 3dee326a186..bb492452982 100644 --- a/tests/ui/const-generics/dyn-supertraits.rs +++ b/tests/ui/const-generics/dyn-supertraits.rs @@ -4,7 +4,7 @@ trait Foo<const N: usize> { fn myfun(&self) -> usize; } trait Bar<const N: usize> : Foo<N> {} -trait Baz: Foo<3> {} +trait Baz: Foo<3> {} //~ WARN trait `Baz` is never used struct FooType<const N: usize>; struct BarType<const N: usize>; @@ -23,10 +23,10 @@ impl Foo<3> for BazType { impl Baz for BazType {} trait Foz {} -trait Boz: Foo<3> + Foz {} +trait Boz: Foo<3> + Foz {} //~ WARN trait `Boz` is never used trait Bok<const N: usize>: Foo<N> + Foz {} -struct FozType; +struct FozType; //~ WARN struct `FozType` is never constructed struct BozType; struct BokType<const N: usize>; diff --git a/tests/ui/const-generics/dyn-supertraits.stderr b/tests/ui/const-generics/dyn-supertraits.stderr new file mode 100644 index 00000000000..38b67ef4403 --- /dev/null +++ b/tests/ui/const-generics/dyn-supertraits.stderr @@ -0,0 +1,22 @@ +warning: trait `Baz` is never used + --> $DIR/dyn-supertraits.rs:7:7 + | +LL | trait Baz: Foo<3> {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: trait `Boz` is never used + --> $DIR/dyn-supertraits.rs:26:7 + | +LL | trait Boz: Foo<3> + Foz {} + | ^^^ + +warning: struct `FozType` is never constructed + --> $DIR/dyn-supertraits.rs:29:8 + | +LL | struct FozType; + | ^^^^^^^ + +warning: 3 warnings emitted + diff --git a/tests/ui/const-generics/issues/issue-69654-run-pass.rs b/tests/ui/const-generics/issues/issue-69654-run-pass.rs index 63d7fde78ac..21d6270b1fa 100644 --- a/tests/ui/const-generics/issues/issue-69654-run-pass.rs +++ b/tests/ui/const-generics/issues/issue-69654-run-pass.rs @@ -1,5 +1,5 @@ // run-pass -trait Bar<T> {} +trait Bar<T> {} //~ WARN trait `Bar` is never used impl<T> Bar<T> for [u8; 7] {} struct Foo<const N: usize> {} diff --git a/tests/ui/const-generics/issues/issue-69654-run-pass.stderr b/tests/ui/const-generics/issues/issue-69654-run-pass.stderr new file mode 100644 index 00000000000..7b3cd4f375f --- /dev/null +++ b/tests/ui/const-generics/issues/issue-69654-run-pass.stderr @@ -0,0 +1,10 @@ +warning: trait `Bar` is never used + --> $DIR/issue-69654-run-pass.rs:2:7 + | +LL | trait Bar<T> {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/const-generics/issues/issue-90318.rs b/tests/ui/const-generics/issues/issue-90318.rs index 909997340f3..cebc1ce2142 100644 --- a/tests/ui/const-generics/issues/issue-90318.rs +++ b/tests/ui/const-generics/issues/issue-90318.rs @@ -13,6 +13,7 @@ fn consume<T: 'static>(_val: T) where If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, //~^ overly complex generic constant + //~| ERROR: cannot call { } @@ -20,6 +21,7 @@ fn test<T: 'static>() where If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, //~^ overly complex generic constant + //~| ERROR: cannot call { } diff --git a/tests/ui/const-generics/issues/issue-90318.stderr b/tests/ui/const-generics/issues/issue-90318.stderr index f13fd795d7a..471a6660ce0 100644 --- a/tests/ui/const-generics/issues/issue-90318.stderr +++ b/tests/ui/const-generics/issues/issue-90318.stderr @@ -10,7 +10,7 @@ LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, = note: this operation may be supported in the future error: overly complex generic constant - --> $DIR/issue-90318.rs:21:8 + --> $DIR/issue-90318.rs:22:8 | LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, | ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,5 +20,28 @@ LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future -error: aborting due to 2 previous errors +error[E0015]: cannot call non-const operator in constants + --> $DIR/issue-90318.rs:14:10 + | +LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/any.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: cannot call non-const operator in constants + --> $DIR/issue-90318.rs:22:10 + | +LL | If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/any.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr b/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr index 1fe0109771c..e42bb6e8cc5 100644 --- a/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr +++ b/tests/ui/const-generics/late-bound-vars/late-bound-in-return-issue-77357.stderr @@ -13,5 +13,37 @@ LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { = help: consider moving this anonymous constant into a `const` function = note: this operation may be supported in the future -error: aborting due to 2 previous errors +error[E0391]: cycle detected when evaluating type-level constant + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `bug::{constant#0}`... + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires caching mir of `bug::{constant#0}` for CTFE... + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires elaborating drops for `bug::{constant#0}`... + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires borrow-checking `bug::{constant#0}`... + --> $DIR/late-bound-in-return-issue-77357.rs:9:46 + | +LL | fn bug<'a, T>() -> &'static dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which requires normalizing `Binder { value: ConstEvaluatable(UnevaluatedConst { def: DefId(0:8 ~ late_bound_in_return_issue_77357[9394]::bug::{constant#0}), args: [T/#0] }: usize), bound_vars: [] }`... + = note: ...which again requires evaluating type-level constant, completing the cycle + = note: cycle used when normalizing `&dyn MyTrait<[(); { |x: &'a u32| { x }; 4 }]>` + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/consts/const-block-item.rs b/tests/ui/consts/const-block-item.rs index cf0d4441d4a..a04f4db263b 100644 --- a/tests/ui/consts/const-block-item.rs +++ b/tests/ui/consts/const-block-item.rs @@ -2,7 +2,7 @@ #![allow(unused_imports)] mod foo { - pub trait Value { + pub trait Value { //~ WARN trait `Value` is never used fn value(&self) -> usize; } } diff --git a/tests/ui/consts/const-block-item.stderr b/tests/ui/consts/const-block-item.stderr new file mode 100644 index 00000000000..04658742b56 --- /dev/null +++ b/tests/ui/consts/const-block-item.stderr @@ -0,0 +1,10 @@ +warning: trait `Value` is never used + --> $DIR/const-block-item.rs:5:15 + | +LL | pub trait Value { + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.rs b/tests/ui/consts/const-eval/raw-pointer-ub.rs index 3341f3c78e0..47105de453c 100644 --- a/tests/ui/consts/const-eval/raw-pointer-ub.rs +++ b/tests/ui/consts/const-eval/raw-pointer-ub.rs @@ -1,4 +1,4 @@ -#![feature(const_mut_refs)] +#![feature(const_mut_refs, const_intrinsic_copy)] const MISALIGNED_LOAD: () = unsafe { diff --git a/tests/ui/consts/const-for-feature-gate.rs b/tests/ui/consts/const-for-feature-gate.rs index bec7b808905..c834046c5b0 100644 --- a/tests/ui/consts/const-for-feature-gate.rs +++ b/tests/ui/consts/const-for-feature-gate.rs @@ -3,6 +3,9 @@ const _: () = { for _ in 0..5 {} //~^ error: `for` is not allowed in a `const` + //~| ERROR: cannot convert + //~| ERROR: cannot call + //~| ERROR: mutable references }; fn main() {} diff --git a/tests/ui/consts/const-for-feature-gate.stderr b/tests/ui/consts/const-for-feature-gate.stderr index df79c00f024..413d144ca0a 100644 --- a/tests/ui/consts/const-for-feature-gate.stderr +++ b/tests/ui/consts/const-for-feature-gate.stderr @@ -8,6 +8,37 @@ LL | for _ in 0..5 {} = help: add `#![feature(const_for)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const-try-feature-gate.rs b/tests/ui/consts/const-try-feature-gate.rs index 0839c23a0b9..1cc045bf612 100644 --- a/tests/ui/consts/const-try-feature-gate.rs +++ b/tests/ui/consts/const-try-feature-gate.rs @@ -3,6 +3,8 @@ const fn t() -> Option<()> { Some(())?; //~^ error: `?` is not allowed in a `const fn` + //~| ERROR: cannot convert + //~| ERROR: cannot determine None } diff --git a/tests/ui/consts/const-try-feature-gate.stderr b/tests/ui/consts/const-try-feature-gate.stderr index c5aeed3317c..efa1fb107f6 100644 --- a/tests/ui/consts/const-try-feature-gate.stderr +++ b/tests/ui/consts/const-try-feature-gate.stderr @@ -8,6 +8,29 @@ LL | Some(())?; = help: add `#![feature(const_try)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions + --> $DIR/const-try-feature-gate.rs:4:5 + | +LL | Some(())?; + | ^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions + --> $DIR/const-try-feature-gate.rs:4:5 + | +LL | Some(())?; + | ^^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/const_in_pattern/accept_structural.rs b/tests/ui/consts/const_in_pattern/accept_structural.rs index 1f56f581c02..69b4e75c622 100644 --- a/tests/ui/consts/const_in_pattern/accept_structural.rs +++ b/tests/ui/consts/const_in_pattern/accept_structural.rs @@ -63,4 +63,18 @@ fn main() { const ADDR_OF: &OND = &None; match &None { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; + + // These ones are more subtle: the final value is fine, but statically analyzing the expression + // that computes the value would likely (incorrectly) have us conclude that this may match on + // values that do not have structural equality. + const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0]; + match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; + + const fn build() -> Option<NoDerive> { None } + const CALL: Option<NoDerive> = build(); + match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), }; + + impl NoDerive { const fn none() -> Option<NoDerive> { None } } + const METHOD_CALL: Option<NoDerive> = NoDerive::none(); + match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), }; } diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs b/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs index a38731ceb8a..ac89b7925ff 100644 --- a/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs +++ b/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs @@ -12,6 +12,7 @@ impl PartialEq for CustomEq { } #[derive(PartialEq, Eq)] +#[allow(unused)] enum Foo { Bar, Baz, @@ -21,7 +22,7 @@ enum Foo { const BAR_BAZ: Foo = if 42 == 42 { Foo::Bar } else { - Foo::Baz + Foo::Qux(CustomEq) // dead arm }; fn main() { diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs b/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs deleted file mode 100644 index 34b1422dfb3..00000000000 --- a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs +++ /dev/null @@ -1,38 +0,0 @@ -// check-pass - -struct CustomEq; - -impl Eq for CustomEq {} -impl PartialEq for CustomEq { - fn eq(&self, _: &Self) -> bool { - false - } -} - -#[derive(PartialEq, Eq)] -enum Foo { - Bar, - Baz, - Qux(CustomEq), -} - -// We know that `BAR_BAZ` will always be `Foo::Bar` and thus eligible for structural matching, but -// dataflow will be more conservative. -const BAR_BAZ: Foo = if 42 == 42 { - Foo::Bar -} else { - Foo::Qux(CustomEq) -}; - -fn main() { - match Foo::Qux(CustomEq) { - BAR_BAZ => panic!(), - //~^ WARN must be annotated with `#[derive(PartialEq)]` - //~| NOTE the traits must be derived - //~| NOTE StructuralPartialEq.html for details - //~| WARN this was previously accepted - //~| NOTE see issue #73448 - //~| NOTE `#[warn(nontrivial_structural_match)]` on by default - _ => {} - } -} diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr b/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr deleted file mode 100644 index c473c00f8db..00000000000 --- a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr +++ /dev/null @@ -1,14 +0,0 @@ -warning: to use a constant of type `CustomEq` in a pattern, the constant's initializer must be trivial or `CustomEq` must be annotated with `#[derive(PartialEq)]` - --> $DIR/custom-eq-branch-warn.rs:29:9 - | -LL | BAR_BAZ => panic!(), - | ^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448> - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - = note: `#[warn(nontrivial_structural_match)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr index 1546f23908c..bc1015c1734 100644 --- a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr +++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr @@ -5,7 +5,7 @@ LL | C => {} | ^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> note: the lint level is defined here --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 | @@ -19,7 +19,7 @@ LL | C_INNER => {} | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:30:9 @@ -28,7 +28,7 @@ LL | D => {} | ^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:36:9 @@ -37,7 +37,67 @@ LL | STR => {} | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> error: aborting due to 4 previous errors +Future incompatibility report: Future breakage diagnostic: +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:10:9 + | +LL | C => {} + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:18:9 + | +LL | C_INNER => {} + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:30:9 + | +LL | D => {} + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:36:9 + | +LL | STR => {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> +note: the lint level is defined here + --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9 + | +LL | #![deny(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/const_in_pattern/issue-44333.stderr b/tests/ui/consts/const_in_pattern/issue-44333.stderr index 441aeecbc6d..f5931f0cad0 100644 --- a/tests/ui/consts/const_in_pattern/issue-44333.stderr +++ b/tests/ui/consts/const_in_pattern/issue-44333.stderr @@ -5,7 +5,7 @@ LL | FOO => println!("foo"), | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> note: the lint level is defined here --> $DIR/issue-44333.rs:3:9 | @@ -19,7 +19,37 @@ LL | BAR => println!("bar"), | ^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: 2 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-44333.rs:19:9 + | +LL | FOO => println!("foo"), + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> +note: the lint level is defined here + --> $DIR/issue-44333.rs:3:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-44333.rs:21:9 + | +LL | BAR => println!("bar"), + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> +note: the lint level is defined here + --> $DIR/issue-44333.rs:3:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/const_in_pattern/issue-73431.stderr b/tests/ui/consts/const_in_pattern/issue-73431.stderr deleted file mode 100644 index c82dea4aa50..00000000000 --- a/tests/ui/consts/const_in_pattern/issue-73431.stderr +++ /dev/null @@ -1 +0,0 @@ -WARN rustc_mir_build::thir::pattern::const_to_pat MIR const-checker found novel structural match violation. See #73448. diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.rs b/tests/ui/consts/const_in_pattern/reject_non_structural.rs index 196930baed5..71d4138104d 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.rs +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.rs @@ -100,5 +100,5 @@ fn main() { //~| NOTE the traits must be derived //~| NOTE StructuralPartialEq.html for details //~| WARN previously accepted by the compiler but is being phased out - //~| NOTE for more information, see issue #62411 + //~| NOTE for more information, see } diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr index da32b6d698b..2c7aaf89aa7 100644 --- a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr +++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr @@ -86,7 +86,7 @@ LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops") | ^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -97,3 +97,20 @@ LL | #![warn(indirect_structural_match)] error: aborting due to 9 previous errors; 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/reject_non_structural.rs:98:29 + | +LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), }; + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/reject_non_structural.rs:14:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/const_in_pattern/warn_corner_cases.rs b/tests/ui/consts/const_in_pattern/warn_corner_cases.rs deleted file mode 100644 index 75f1965921c..00000000000 --- a/tests/ui/consts/const_in_pattern/warn_corner_cases.rs +++ /dev/null @@ -1,41 +0,0 @@ -// run-pass - -// This test is checking our logic for structural match checking by enumerating -// the different kinds of const expressions. This test is collecting cases where -// we have accepted the const expression as a pattern in the past but we want -// to begin warning the user that a future version of Rust may start rejecting -// such const expressions. - -// The specific corner cases we are exploring here are instances where the -// const-evaluator computes a value that *does* meet the conditions for -// structural-match, but the const expression itself has abstractions (like -// calls to const functions) that may fit better with a type-based analysis -// rather than a commitment to a specific value. - -#![warn(indirect_structural_match)] - -#[derive(Copy, Clone, Debug)] -struct NoDerive(#[allow(dead_code)] u32); - -// This impl makes `NoDerive` irreflexive. -impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } } -impl Eq for NoDerive { } - -fn main() { - const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0]; - match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; - //~^ WARN must be annotated with `#[derive(PartialEq)]` - //~| WARN this was previously accepted - - const fn build() -> Option<NoDerive> { None } - const CALL: Option<NoDerive> = build(); - match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), }; - //~^ WARN must be annotated with `#[derive(PartialEq)]` - //~| WARN this was previously accepted - - impl NoDerive { const fn none() -> Option<NoDerive> { None } } - const METHOD_CALL: Option<NoDerive> = NoDerive::none(); - match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), }; - //~^ WARN must be annotated with `#[derive(PartialEq)]` - //~| WARN this was previously accepted -} diff --git a/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr b/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr deleted file mode 100644 index 8ffd035ebec..00000000000 --- a/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr +++ /dev/null @@ -1,36 +0,0 @@ -warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/warn_corner_cases.rs:26:47 - | -LL | match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), }; - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448> - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - = note: `#[warn(nontrivial_structural_match)]` on by default - -warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/warn_corner_cases.rs:32:47 - | -LL | match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), }; - | ^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448> - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - -warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]` - --> $DIR/warn_corner_cases.rs:38:47 - | -LL | match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), }; - | ^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448> - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details - -warning: 3 warnings emitted - diff --git a/tests/ui/consts/control-flow/loop.rs b/tests/ui/consts/control-flow/loop.rs index 2b8561a2644..5b7f8d29df7 100644 --- a/tests/ui/consts/control-flow/loop.rs +++ b/tests/ui/consts/control-flow/loop.rs @@ -51,10 +51,16 @@ const _: i32 = { let mut x = 0; for i in 0..4 { //~ ERROR `for` is not allowed in a `const` + //~^ ERROR: cannot call + //~| ERROR: mutable references + //~| ERROR: cannot convert x += i; } for i in 0..4 { //~ ERROR `for` is not allowed in a `const` + //~^ ERROR: cannot call + //~| ERROR: mutable references + //~| ERROR: cannot convert x += i; } diff --git a/tests/ui/consts/control-flow/loop.stderr b/tests/ui/consts/control-flow/loop.stderr index 725adf72339..e162a404ace 100644 --- a/tests/ui/consts/control-flow/loop.stderr +++ b/tests/ui/consts/control-flow/loop.stderr @@ -2,6 +2,9 @@ error[E0658]: `for` is not allowed in a `const` --> $DIR/loop.rs:53:5 | LL | / for i in 0..4 { +LL | | +LL | | +LL | | LL | | x += i; LL | | } | |_____^ @@ -11,9 +14,12 @@ LL | | } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `for` is not allowed in a `const` - --> $DIR/loop.rs:57:5 + --> $DIR/loop.rs:60:5 | LL | / for i in 0..4 { +LL | | +LL | | +LL | | LL | | x += i; LL | | } | |_____^ @@ -22,6 +28,67 @@ LL | | } = help: add `#![feature(const_for)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants + --> $DIR/loop.rs:53:14 + | +LL | for i in 0..4 { + | ^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/loop.rs:53:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants + --> $DIR/loop.rs:53:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: cannot convert `std::ops::Range<i32>` into an iterator in constants + --> $DIR/loop.rs:60:14 + | +LL | for i in 0..4 { + | ^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/loop.rs:60:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants + --> $DIR/loop.rs:60:14 + | +LL | for i in 0..4 { + | ^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/control-flow/try.rs b/tests/ui/consts/control-flow/try.rs index 7d85a412b47..5c6957df405 100644 --- a/tests/ui/consts/control-flow/try.rs +++ b/tests/ui/consts/control-flow/try.rs @@ -4,6 +4,8 @@ const fn opt() -> Option<i32> { let x = Some(2); x?; //~ ERROR `?` is not allowed in a `const fn` + //~^ ERROR: cannot convert + //~| ERROR: cannot determine None } diff --git a/tests/ui/consts/control-flow/try.stderr b/tests/ui/consts/control-flow/try.stderr index f4b88de9dfa..f4c42c4d819 100644 --- a/tests/ui/consts/control-flow/try.stderr +++ b/tests/ui/consts/control-flow/try.stderr @@ -8,6 +8,29 @@ LL | x?; = help: add `#![feature(const_try)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0015]: `?` cannot determine the branch of `Option<i32>` in constant functions + --> $DIR/try.rs:6:5 + | +LL | x?; + | ^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0015]: `?` cannot convert from residual of `Option<i32>` in constant functions + --> $DIR/try.rs:6:5 + | +LL | x?; + | ^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0015, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index e6ea4108f40..afe89461f03 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -74,6 +74,100 @@ LL | T: ~const FnMut<()> + ~const Destruct, | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 11 previous errors +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/fn_trait_refs.rs:17:5 + | +LL | f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | T: ~const Fn<()> + ~const Destruct + ~const std::ops::Fn<()>, + | +++++++++++++++++++++++++ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/fn_trait_refs.rs:13:23 + | +LL | const fn tester_fn<T>(f: T) -> T::Output + | ^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/fn_trait_refs.rs:24:5 + | +LL | f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | T: ~const FnMut<()> + ~const Destruct + ~const std::ops::FnMut<()>, + | ++++++++++++++++++++++++++++ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/fn_trait_refs.rs:20:27 + | +LL | const fn tester_fn_mut<T>(mut f: T) -> T::Output + | ^^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/fn_trait_refs.rs:31:5 + | +LL | f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | T: ~const FnOnce<()> + ~const std::ops::FnOnce<()>, + | +++++++++++++++++++++++++++++ + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/fn_trait_refs.rs:34:21 + | +LL | const fn test_fn<T>(mut f: T) -> (T::Output, T::Output, T::Output) + | ^^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0493]: destructor of `T` cannot be evaluated at compile-time + --> $DIR/fn_trait_refs.rs:48:25 + | +LL | const fn test_fn_mut<T>(mut f: T) -> (T::Output, T::Output) + | ^^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0015]: cannot call non-const operator in constants + --> $DIR/fn_trait_refs.rs:72:17 + | +LL | assert!(test_one == (1, 1, 1)); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: cannot call non-const operator in constants + --> $DIR/fn_trait_refs.rs:75:17 + | +LL | assert!(test_two == (2, 2)); + | ^^^^^^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error: aborting due to 20 previous errors -For more information about this error, try `rustc --explain E0635`. +Some errors have detailed explanations: E0015, E0493, E0635. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-89088.stderr b/tests/ui/consts/issue-89088.stderr new file mode 100644 index 00000000000..d5c5f76b90a --- /dev/null +++ b/tests/ui/consts/issue-89088.stderr @@ -0,0 +1,17 @@ +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `Cow<'_, str>` in a pattern, `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]` + --> $DIR/issue-89088.rs:19:9 + | +LL | FOO => todo!(), + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/issue-89088.rs:5:10 + | +LL | #![allow(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/consts/promoted_const_call.stderr b/tests/ui/consts/promoted_const_call.stderr index 1f6abc0ce7c..ace449fae9c 100644 --- a/tests/ui/consts/promoted_const_call.stderr +++ b/tests/ui/consts/promoted_const_call.stderr @@ -7,26 +7,6 @@ LL | let _: &'static _ = &id(&Panic); | the destructor for this type cannot be evaluated in constants error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:11:26 - | -LL | let _: &'static _ = &id(&Panic); - | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use - | | - | type annotation requires that borrow lasts for `'static` -... -LL | }; - | - temporary value is freed at the end of this statement - -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call.rs:11:30 - | -LL | let _: &'static _ = &id(&Panic); - | ---------- ^^^^^ - temporary value is freed at the end of this statement - | | | - | | creates a temporary value which is freed while still in use - | type annotation requires that borrow lasts for `'static` - -error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_call.rs:17:26 | LL | let _: &'static _ = &id(&Panic); @@ -68,7 +48,7 @@ LL | let _: &'static _ = &&(Panic, 0).1; LL | } | - temporary value is freed at the end of this statement -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0493, E0716. For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/promoted_const_call3.rs b/tests/ui/consts/promoted_const_call3.rs index 6d68a2de70e..dc05a3b5844 100644 --- a/tests/ui/consts/promoted_const_call3.rs +++ b/tests/ui/consts/promoted_const_call3.rs @@ -2,13 +2,14 @@ pub const fn id<T>(x: T) -> T { x } pub const C: () = { let _: &'static _ = &String::new(); //~^ ERROR: destructor of `String` cannot be evaluated at compile-time - //~| ERROR: temporary value dropped while borrowed +}; +pub const _: () = { let _: &'static _ = &id(&String::new()); //~^ ERROR: destructor of `String` cannot be evaluated at compile-time - //~| ERROR: temporary value dropped while borrowed - //~| ERROR: temporary value dropped while borrowed +}; +pub const _: () = { let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); //~^ ERROR: temporary value dropped while borrowed }; diff --git a/tests/ui/consts/promoted_const_call3.stderr b/tests/ui/consts/promoted_const_call3.stderr index af17457a10a..34c833d5bb7 100644 --- a/tests/ui/consts/promoted_const_call3.stderr +++ b/tests/ui/consts/promoted_const_call3.stderr @@ -1,53 +1,22 @@ error[E0493]: destructor of `String` cannot be evaluated at compile-time - --> $DIR/promoted_const_call3.rs:7:30 - | -LL | let _: &'static _ = &id(&String::new()); - | ^^^^^^^^^^^^^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constants - -error[E0493]: destructor of `String` cannot be evaluated at compile-time --> $DIR/promoted_const_call3.rs:3:26 | LL | let _: &'static _ = &String::new(); | ^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants -... +LL | LL | }; | - value is dropped here -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:3:26 - | -LL | let _: &'static _ = &String::new(); - | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use - | | - | type annotation requires that borrow lasts for `'static` -... -LL | }; - | - temporary value is freed at the end of this statement - -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:7:26 - | -LL | let _: &'static _ = &id(&String::new()); - | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use - | | - | type annotation requires that borrow lasts for `'static` -... -LL | }; - | - temporary value is freed at the end of this statement - -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:7:30 +error[E0493]: destructor of `String` cannot be evaluated at compile-time + --> $DIR/promoted_const_call3.rs:8:30 | LL | let _: &'static _ = &id(&String::new()); - | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement - | | | - | | creates a temporary value which is freed while still in use - | type annotation requires that borrow lasts for `'static` + | ^^^^^^^^^^^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constants error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:12:26 + --> $DIR/promoted_const_call3.rs:13:26 | LL | let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -58,7 +27,7 @@ LL | }; | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:17:26 + --> $DIR/promoted_const_call3.rs:18:26 | LL | let _: &'static _ = &String::new(); | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -69,7 +38,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:20:26 + --> $DIR/promoted_const_call3.rs:21:26 | LL | let _: &'static _ = &id(&String::new()); | ---------- ^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -80,7 +49,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:20:30 + --> $DIR/promoted_const_call3.rs:21:30 | LL | let _: &'static _ = &id(&String::new()); | ---------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement @@ -89,7 +58,7 @@ LL | let _: &'static _ = &id(&String::new()); | type annotation requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call3.rs:24:26 + --> $DIR/promoted_const_call3.rs:25:26 | LL | let _: &'static _ = &std::mem::ManuallyDrop::new(String::new()); | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -99,7 +68,7 @@ LL | LL | } | - temporary value is freed at the end of this statement -error: aborting due to 10 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0493, E0716. For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/promoted_const_call5.rs b/tests/ui/consts/promoted_const_call5.rs index 3ac8d358ce4..41b3988949e 100644 --- a/tests/ui/consts/promoted_const_call5.rs +++ b/tests/ui/consts/promoted_const_call5.rs @@ -25,9 +25,9 @@ pub const fn new_manually_drop<T>(t: T) -> std::mem::ManuallyDrop<T> { const C: () = { let _: &'static _ = &id(&new_string()); //~^ ERROR destructor of `String` cannot be evaluated at compile-time - //~| ERROR: temporary value dropped while borrowed - //~| ERROR: temporary value dropped while borrowed +}; +const _: () = { let _: &'static _ = &new_manually_drop(new_string()); //~^ ERROR: temporary value dropped while borrowed }; diff --git a/tests/ui/consts/promoted_const_call5.stderr b/tests/ui/consts/promoted_const_call5.stderr index f736220b183..1b5fa435283 100644 --- a/tests/ui/consts/promoted_const_call5.stderr +++ b/tests/ui/consts/promoted_const_call5.stderr @@ -7,26 +7,6 @@ LL | let _: &'static _ = &id(&new_string()); | the destructor for this type cannot be evaluated in constants error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call5.rs:26:26 - | -LL | let _: &'static _ = &id(&new_string()); - | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use - | | - | type annotation requires that borrow lasts for `'static` -... -LL | }; - | - temporary value is freed at the end of this statement - -error[E0716]: temporary value dropped while borrowed - --> $DIR/promoted_const_call5.rs:26:30 - | -LL | let _: &'static _ = &id(&new_string()); - | ----^^^^^^^^^^^^-- temporary value is freed at the end of this statement - | | | - | | creates a temporary value which is freed while still in use - | argument requires that borrow lasts for `'static` - -error[E0716]: temporary value dropped while borrowed --> $DIR/promoted_const_call5.rs:31:26 | LL | let _: &'static _ = &new_manually_drop(new_string()); @@ -68,7 +48,7 @@ LL | LL | } | - temporary value is freed at the end of this statement -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0493, E0716. For more information about an error, try `rustc --explain E0493`. diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.rs b/tests/ui/consts/transmute-size-mismatch-before-typeck.rs index 852a5b3b46a..936931acbe2 100644 --- a/tests/ui/consts/transmute-size-mismatch-before-typeck.rs +++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.rs @@ -5,7 +5,7 @@ fn main() { match &b""[..] { - ZST => {} + ZST => {} //~ ERROR: could not evaluate constant pattern } } diff --git a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr index 6bc7e7203aa..e0d658db997 100644 --- a/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr +++ b/tests/ui/consts/transmute-size-mismatch-before-typeck.stderr @@ -7,6 +7,12 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; = note: source type: `usize` (word size) = note: target type: `&[u8]` (2 * word size) -error: aborting due to 1 previous error +error: could not evaluate constant pattern + --> $DIR/transmute-size-mismatch-before-typeck.rs:8:9 + | +LL | ZST => {} + | ^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0512`. diff --git a/tests/ui/consts/try-operator.stderr b/tests/ui/consts/try-operator.stderr index bb8f606edf8..c19d1a6199d 100644 --- a/tests/ui/consts/try-operator.stderr +++ b/tests/ui/consts/try-operator.stderr @@ -4,6 +4,51 @@ error[E0635]: unknown feature `const_convert` LL | #![feature(const_convert)] | ^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: `?` cannot determine the branch of `Result<(), ()>` in constant functions + --> $DIR/try-operator.rs:10:9 + | +LL | Err(())?; + | ^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/result.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: `?` cannot convert from residual of `Result<bool, ()>` in constant functions + --> $DIR/try-operator.rs:10:9 + | +LL | Err(())?; + | ^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/result.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: `?` cannot determine the branch of `Option<()>` in constant functions + --> $DIR/try-operator.rs:18:9 + | +LL | None?; + | ^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: `?` cannot convert from residual of `Option<()>` in constant functions + --> $DIR/try-operator.rs:18:9 + | +LL | None?; + | ^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/option.rs:LL:COL + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0635`. +Some errors have detailed explanations: E0015, E0635. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/underscore_const_names.rs b/tests/ui/consts/underscore_const_names.rs index d0e625bf199..e2ae5a9d53a 100644 --- a/tests/ui/consts/underscore_const_names.rs +++ b/tests/ui/consts/underscore_const_names.rs @@ -2,12 +2,12 @@ #![deny(unused)] -trait Trt {} +pub trait Trt {} pub struct Str {} impl Trt for Str {} macro_rules! check_impl { - ($struct:ident,$trait:ident) => { + ($struct:ident, $trait:ident) => { const _ : () = { use std::marker::PhantomData; struct ImplementsTrait<T: $trait>(PhantomData<T>); diff --git a/tests/ui/consts/unstable-const-fn-in-libcore.stderr b/tests/ui/consts/unstable-const-fn-in-libcore.stderr index 08147a4afaf..ee4a0f6a843 100644 --- a/tests/ui/consts/unstable-const-fn-in-libcore.stderr +++ b/tests/ui/consts/unstable-const-fn-in-libcore.stderr @@ -4,5 +4,38 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T { | ^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/unstable-const-fn-in-libcore.rs:24:26 + | +LL | Opt::None => f(), + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn unwrap_or_else<F: ~const FnOnce() -> T + ~const std::ops::FnOnce<()>>(self, f: F) -> T { + | +++++++++++++++++++++++++++++ + +error[E0493]: destructor of `F` cannot be evaluated at compile-time + --> $DIR/unstable-const-fn-in-libcore.rs:19:60 + | +LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T { + | ^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error[E0493]: destructor of `Opt<T>` cannot be evaluated at compile-time + --> $DIR/unstable-const-fn-in-libcore.rs:19:54 + | +LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T { + | ^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error: aborting due to 4 previous errors +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/coroutine/polymorphize-args.rs b/tests/ui/coroutine/polymorphize-args.rs new file mode 100644 index 00000000000..de44d667656 --- /dev/null +++ b/tests/ui/coroutine/polymorphize-args.rs @@ -0,0 +1,17 @@ +// compile-flags: -Zpolymorphize=on +// build-pass + +#![feature(coroutines, coroutine_trait)] + +use std::ops::Coroutine; +use std::pin::Pin; +use std::thread; + +fn main() { + let mut foo = || yield; + thread::spawn(move || match Pin::new(&mut foo).resume(()) { + s => panic!("bad state: {:?}", s), + }) + .join() + .unwrap(); +} diff --git a/tests/ui/default-method-parsing.rs b/tests/ui/default-method-parsing.rs index 9ffb8d94a59..5001d58f0a4 100644 --- a/tests/ui/default-method-parsing.rs +++ b/tests/ui/default-method-parsing.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Foo { diff --git a/tests/ui/delegation/target-expr-pass.rs b/tests/ui/delegation/target-expr-pass.rs index 56068dfce01..4ccb81c292a 100644 --- a/tests/ui/delegation/target-expr-pass.rs +++ b/tests/ui/delegation/target-expr-pass.rs @@ -14,14 +14,14 @@ reuse to_reuse::foo {{ x + self }} -trait Trait { +trait Trait { //~ WARN trait `Trait` is never used fn bar(&self, x: i32) -> i32 { x } } -struct F; +struct F; //~ WARN struct `F` is never constructed impl Trait for F {} -struct S(F); +struct S(F); //~ WARN struct `S` is never constructed impl Trait for S { reuse <F as Trait>::bar { #[allow(unused_imports)] diff --git a/tests/ui/delegation/target-expr-pass.stderr b/tests/ui/delegation/target-expr-pass.stderr index ea594f8a26a..dd1f3a14e0b 100644 --- a/tests/ui/delegation/target-expr-pass.stderr +++ b/tests/ui/delegation/target-expr-pass.stderr @@ -7,5 +7,25 @@ LL | #![feature(fn_delegation)] = note: see issue #118212 <https://github.com/rust-lang/rust/issues/118212> for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +warning: trait `Trait` is never used + --> $DIR/target-expr-pass.rs:17:7 + | +LL | trait Trait { + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: struct `F` is never constructed + --> $DIR/target-expr-pass.rs:21:8 + | +LL | struct F; + | ^ + +warning: struct `S` is never constructed + --> $DIR/target-expr-pass.rs:24:8 + | +LL | struct S(F); + | ^ + +warning: 4 warnings emitted diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index 61268ffc7f8..13ba80243a5 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -15,9 +15,6 @@ note: trait bound `NotClone: Clone` was not satisfied | LL | #[derive(Clone)] | ^^^^^ unsatisfied trait bound introduced in this `derive` macro - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `clone`, perhaps you need to implement it: - candidate #1: `Clone` help: consider annotating `NotClone` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/deriving/deriving-bounds.rs b/tests/ui/deriving/deriving-bounds.rs index f0b921d0e7c..f3e7cf99437 100644 --- a/tests/ui/deriving/deriving-bounds.rs +++ b/tests/ui/deriving/deriving-bounds.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #[derive(Copy, Clone)] struct Test; diff --git a/tests/ui/diagnostic-width/tabs-trimming.rs b/tests/ui/diagnostic-width/tabs-trimming.rs index ade21753b45..96babde33e9 100644 --- a/tests/ui/diagnostic-width/tabs-trimming.rs +++ b/tests/ui/diagnostic-width/tabs-trimming.rs @@ -8,6 +8,7 @@ match money { v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT //~^ ERROR variable `v` is not bound in all patterns + //~| ERROR possibly-uninitialized v => println!("Enough money {}", v), } } diff --git a/tests/ui/diagnostic-width/tabs-trimming.stderr b/tests/ui/diagnostic-width/tabs-trimming.stderr index 2aa4fc18c3d..85103fbf6f5 100644 --- a/tests/ui/diagnostic-width/tabs-trimming.stderr +++ b/tests/ui/diagnostic-width/tabs-trimming.stderr @@ -7,6 +7,18 @@ LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Lon | | pattern doesn't bind `v` | variable not in all patterns -error: aborting due to 1 previous error +error[E0381]: used binding `v` is possibly-uninitialized + --> $DIR/tabs-trimming.rs:9:67 + | +LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT... + | - ^ `v` used here but it is possibly-uninitialized + | | + | binding initialized here in some conditions + | binding declared here but left uninitialized + | + = note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0408`. +Some errors have detailed explanations: E0381, E0408. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/drop/drop-struct-as-object.rs b/tests/ui/drop/drop-struct-as-object.rs index 377027a4fc5..1aa68777042 100644 --- a/tests/ui/drop/drop-struct-as-object.rs +++ b/tests/ui/drop/drop-struct-as-object.rs @@ -12,7 +12,7 @@ struct Cat { } trait Dummy { - fn get(&self) -> usize; + fn get(&self) -> usize; //~ WARN method `get` is never used } impl Dummy for Cat { diff --git a/tests/ui/drop/drop-struct-as-object.stderr b/tests/ui/drop/drop-struct-as-object.stderr new file mode 100644 index 00000000000..10527c968ed --- /dev/null +++ b/tests/ui/drop/drop-struct-as-object.stderr @@ -0,0 +1,12 @@ +warning: method `get` is never used + --> $DIR/drop-struct-as-object.rs:15:8 + | +LL | trait Dummy { + | ----- method in this trait +LL | fn get(&self) -> usize; + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/drop/recursion-check-on-erroneous-impl.rs b/tests/ui/drop/recursion-check-on-erroneous-impl.rs new file mode 100644 index 00000000000..733c8b0b085 --- /dev/null +++ b/tests/ui/drop/recursion-check-on-erroneous-impl.rs @@ -0,0 +1,11 @@ +// can't use build-fail, because this also fails check-fail, but +// the ICE from #120787 only reproduces on build-fail. +// compile-flags: --emit=mir + +struct PrintOnDrop<'a>(&'a str); + +impl Drop for PrintOnDrop<'_> { + fn drop() {} //~ ERROR method `drop` has a `&mut self` declaration in the trait +} + +fn main() {} diff --git a/tests/ui/drop/recursion-check-on-erroneous-impl.stderr b/tests/ui/drop/recursion-check-on-erroneous-impl.stderr new file mode 100644 index 00000000000..831adb88cef --- /dev/null +++ b/tests/ui/drop/recursion-check-on-erroneous-impl.stderr @@ -0,0 +1,11 @@ +error[E0186]: method `drop` has a `&mut self` declaration in the trait, but not in the impl + --> $DIR/recursion-check-on-erroneous-impl.rs:8:5 + | +LL | fn drop() {} + | ^^^^^^^^^ expected `&mut self` in impl + | + = note: `drop` from trait: `fn(&mut Self)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0186`. diff --git a/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs b/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs index a074b5fa5f7..23ca36b71e0 100644 --- a/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs +++ b/tests/ui/dyn-keyword/dyn-2018-edition-lint.rs @@ -6,14 +6,6 @@ fn function(x: &SomeTrait, y: Box<SomeTrait>) { //~| WARN this is accepted in the current edition //~| ERROR trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition let _x: &SomeTrait = todo!(); //~^ ERROR trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition diff --git a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr index 93178667214..65d44604dc9 100644 --- a/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr +++ b/tests/ui/dyn-keyword/dyn-2018-edition-lint.stderr @@ -30,7 +30,7 @@ LL | fn function(x: &SomeTrait, y: Box<dyn SomeTrait>) { | +++ error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:17:14 + --> $DIR/dyn-2018-edition-lint.rs:9:14 | LL | let _x: &SomeTrait = todo!(); | ^^^^^^^^^ @@ -42,61 +42,5 @@ help: use `dyn` LL | let _x: &dyn SomeTrait = todo!(); | +++ -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:4:17 - | -LL | fn function(x: &SomeTrait, y: Box<SomeTrait>) { - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | fn function(x: &dyn SomeTrait, y: Box<SomeTrait>) { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:4:17 - | -LL | fn function(x: &SomeTrait, y: Box<SomeTrait>) { - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | fn function(x: &dyn SomeTrait, y: Box<SomeTrait>) { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:4:35 - | -LL | fn function(x: &SomeTrait, y: Box<SomeTrait>) { - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | fn function(x: &SomeTrait, y: Box<dyn SomeTrait>) { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/dyn-2018-edition-lint.rs:4:35 - | -LL | fn function(x: &SomeTrait, y: Box<SomeTrait>) { - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | fn function(x: &SomeTrait, y: Box<dyn SomeTrait>) { - | +++ - -error: aborting due to 7 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/dynamically-sized-types/dst-coercions.rs b/tests/ui/dynamically-sized-types/dst-coercions.rs index 66688e93fb8..1efdf1de0e6 100644 --- a/tests/ui/dynamically-sized-types/dst-coercions.rs +++ b/tests/ui/dynamically-sized-types/dst-coercions.rs @@ -5,7 +5,7 @@ // pretty-expanded FIXME #23616 struct S; -trait T { fn dummy(&self) { } } +trait T { fn dummy(&self) { } } //~ WARN method `dummy` is never used impl T for S {} pub fn main() { diff --git a/tests/ui/dynamically-sized-types/dst-coercions.stderr b/tests/ui/dynamically-sized-types/dst-coercions.stderr new file mode 100644 index 00000000000..e4721ce50a0 --- /dev/null +++ b/tests/ui/dynamically-sized-types/dst-coercions.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/dst-coercions.rs:8:14 + | +LL | trait T { fn dummy(&self) { } } + | - ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/empty-type-parameter-list.rs b/tests/ui/empty-type-parameter-list.rs index e168cd03b27..23d09fbf281 100644 --- a/tests/ui/empty-type-parameter-list.rs +++ b/tests/ui/empty-type-parameter-list.rs @@ -3,7 +3,7 @@ // no type parameters at all struct S<>; -trait T<> {} +trait T<> {} //~ WARN trait `T` is never used enum E<> { V } impl<> T<> for S<> {} impl T for E {} diff --git a/tests/ui/empty-type-parameter-list.stderr b/tests/ui/empty-type-parameter-list.stderr new file mode 100644 index 00000000000..31a5015e993 --- /dev/null +++ b/tests/ui/empty-type-parameter-list.stderr @@ -0,0 +1,10 @@ +warning: trait `T` is never used + --> $DIR/empty-type-parameter-list.rs:6:7 + | +LL | trait T<> {} + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/enum/enum-and-module-in-same-scope.rs b/tests/ui/enum/enum-and-module-in-same-scope.rs index cc6e199bd7c..8e69c89d792 100644 --- a/tests/ui/enum/enum-and-module-in-same-scope.rs +++ b/tests/ui/enum/enum-and-module-in-same-scope.rs @@ -5,6 +5,7 @@ enum Foo { mod Foo { //~ ERROR the name `Foo` is defined multiple times pub static X: isize = 42; fn f() { f() } // Check that this does not result in a resolution error + //~^ WARN cannot return without recursing } fn main() {} diff --git a/tests/ui/enum/enum-and-module-in-same-scope.stderr b/tests/ui/enum/enum-and-module-in-same-scope.stderr index 0293acd6201..f1c02af595f 100644 --- a/tests/ui/enum/enum-and-module-in-same-scope.stderr +++ b/tests/ui/enum/enum-and-module-in-same-scope.stderr @@ -9,6 +9,17 @@ LL | mod Foo { | = note: `Foo` must be defined only once in the type namespace of this module -error: aborting due to 1 previous error +warning: function cannot return without recursing + --> $DIR/enum-and-module-in-same-scope.rs:7:5 + | +LL | fn f() { f() } // Check that this does not result in a resolution error + | ^^^^^^ --- recursive call site + | | + | cannot return without recursing + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/error-codes/E0117.rs b/tests/ui/error-codes/E0117.rs index 406d24e3666..32b9863806c 100644 --- a/tests/ui/error-codes/E0117.rs +++ b/tests/ui/error-codes/E0117.rs @@ -1,4 +1,5 @@ impl Drop for u32 {} //~ ERROR E0117 //~| ERROR the `Drop` trait may only be implemented for local structs, enums, and unions +//~| ERROR not all trait items implemented fn main() {} diff --git a/tests/ui/error-codes/E0117.stderr b/tests/ui/error-codes/E0117.stderr index f144aa9f72c..058a64b20d1 100644 --- a/tests/ui/error-codes/E0117.stderr +++ b/tests/ui/error-codes/E0117.stderr @@ -15,7 +15,15 @@ error[E0120]: the `Drop` trait may only be implemented for local structs, enums, LL | impl Drop for u32 {} | ^^^ must be a struct, enum, or union in the current crate -error: aborting due to 2 previous errors +error[E0046]: not all trait items implemented, missing: `drop` + --> $DIR/E0117.rs:1:1 + | +LL | impl Drop for u32 {} + | ^^^^^^^^^^^^^^^^^ missing `drop` in implementation + | + = help: implement the missing item: `fn drop(&mut self) { todo!() }` + +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0117, E0120. -For more information about an error, try `rustc --explain E0117`. +Some errors have detailed explanations: E0046, E0117, E0120. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/error-codes/E0120.rs b/tests/ui/error-codes/E0120.rs index a0a301a06e2..35f544fddfb 100644 --- a/tests/ui/error-codes/E0120.rs +++ b/tests/ui/error-codes/E0120.rs @@ -3,6 +3,7 @@ trait MyTrait { fn foo() {} } impl Drop for dyn MyTrait { //~^ ERROR E0120 fn drop(&mut self) {} + } fn main() {} diff --git a/tests/ui/error-codes/E0374.rs b/tests/ui/error-codes/E0374.rs index 41fcedc328d..47b9bea978e 100644 --- a/tests/ui/error-codes/E0374.rs +++ b/tests/ui/error-codes/E0374.rs @@ -1,7 +1,7 @@ #![feature(coerce_unsized)] use std::ops::CoerceUnsized; -struct Foo<T: ?Sized> { +struct Foo<T: ?Sized> { //~ ERROR `T` is never used a: i32, } diff --git a/tests/ui/error-codes/E0374.stderr b/tests/ui/error-codes/E0374.stderr index 148fa1348ab..77f351b28ef 100644 --- a/tests/ui/error-codes/E0374.stderr +++ b/tests/ui/error-codes/E0374.stderr @@ -7,6 +7,15 @@ LL | | where T: CoerceUnsized<U> {} | = note: expected a single field to be coerced, none found -error: aborting due to 1 previous error +error[E0392]: type parameter `T` is never used + --> $DIR/E0374.rs:4:12 + | +LL | struct Foo<T: ?Sized> { + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0374`. +Some errors have detailed explanations: E0374, E0392. +For more information about an error, try `rustc --explain E0374`. diff --git a/tests/ui/error-codes/E0375.rs b/tests/ui/error-codes/E0375.rs index 0c03a8761df..eaf99dd3842 100644 --- a/tests/ui/error-codes/E0375.rs +++ b/tests/ui/error-codes/E0375.rs @@ -3,7 +3,7 @@ use std::ops::CoerceUnsized; struct Foo<T: ?Sized, U: ?Sized> { a: i32, - b: T, + b: T, //~ ERROR E0277 c: U, } diff --git a/tests/ui/error-codes/E0375.stderr b/tests/ui/error-codes/E0375.stderr index 0a5e4128ae9..d5340022d68 100644 --- a/tests/ui/error-codes/E0375.stderr +++ b/tests/ui/error-codes/E0375.stderr @@ -7,6 +7,32 @@ LL | impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {} = note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced = note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`) -error: aborting due to 1 previous error +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/E0375.rs:6:8 + | +LL | struct Foo<T: ?Sized, U: ?Sized> { + | - this type parameter needs to be `Sized` +LL | a: i32, +LL | b: T, + | ^ doesn't have a size known at compile-time + | + = note: only the last field of a struct may have a dynamically sized type + = help: change the field's type to have a statically known size +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - struct Foo<T: ?Sized, U: ?Sized> { +LL + struct Foo<T, U: ?Sized> { + | +help: borrowed types always have a statically known size + | +LL | b: &T, + | + +help: the `Box` type always has a statically known size and allocates its contents in the heap + | +LL | b: Box<T>, + | ++++ + + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0375`. +Some errors have detailed explanations: E0277, E0375. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/error-codes/E0401.stderr b/tests/ui/error-codes/E0401.stderr index d27fade487f..754867061c7 100644 --- a/tests/ui/error-codes/E0401.stderr +++ b/tests/ui/error-codes/E0401.stderr @@ -20,7 +20,7 @@ LL | fn baz<U, LL | (y: T) { | ^ use of generic parameter from outer item -error[E0401]: can't use generic parameters from outer item +error[E0401]: can't use `Self` from outer item --> $DIR/E0401.rs:24:25 | LL | impl<T> Iterator for A<T> { @@ -29,7 +29,7 @@ LL | impl<T> Iterator for A<T> { LL | fn helper(sel: &Self) -> u8 { | ^^^^ | | - | use of generic parameter from outer item + | use of `Self` from outer item | refer to the type directly here instead error[E0283]: type annotations needed diff --git a/tests/ui/error-codes/E0582.rs b/tests/ui/error-codes/E0582.rs index ff25012d0f9..b6513170b13 100644 --- a/tests/ui/error-codes/E0582.rs +++ b/tests/ui/error-codes/E0582.rs @@ -19,7 +19,7 @@ fn mk_unexpected_char_err<'a>() -> Option<&'a i32> { } fn foo<'a>(data: &mut Chars<'a>) { - bar(mk_unexpected_char_err) + bar(mk_unexpected_char_err) //~ ERROR mismatched types } fn bar<F>(t: F) diff --git a/tests/ui/error-codes/E0582.stderr b/tests/ui/error-codes/E0582.stderr index 81a2f004653..64b527cdcc2 100644 --- a/tests/ui/error-codes/E0582.stderr +++ b/tests/ui/error-codes/E0582.stderr @@ -10,6 +10,21 @@ error[E0582]: binding for associated type `Item` references lifetime `'a`, which LL | where F: for<'a> Iterator<Item=&'a i32> | ^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/E0582.rs:22:5 + | +LL | bar(mk_unexpected_char_err) + | ^^^ one type is more general than the other + | + = note: expected enum `Option<&_>` + found enum `Option<&'a _>` +note: the lifetime requirement is introduced here + --> $DIR/E0582.rs:28:30 + | +LL | where F: for<'a> Fn() -> Option<&'a i32> + | ^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0582`. +Some errors have detailed explanations: E0308, E0582. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/error-codes/E0637.rs b/tests/ui/error-codes/E0637.rs index 382ce3ed01f..e107ea9521b 100644 --- a/tests/ui/error-codes/E0637.rs +++ b/tests/ui/error-codes/E0637.rs @@ -2,9 +2,9 @@ fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { //~^ ERROR: `'_` cannot be used here [E0637] //~| ERROR: missing lifetime specifier if str1.len() > str2.len() { - str1 + str1 //~ ERROR: lifetime may not live long enough } else { - str2 + str2 //~ ERROR: lifetime may not live long enough } } diff --git a/tests/ui/error-codes/E0637.stderr b/tests/ui/error-codes/E0637.stderr index d9db89ddb0c..217881b8e7c 100644 --- a/tests/ui/error-codes/E0637.stderr +++ b/tests/ui/error-codes/E0637.stderr @@ -27,7 +27,25 @@ help: consider introducing a higher-ranked lifetime here LL | T: for<'a> Into<&'a u32>, | +++++++ ++ -error: aborting due to 3 previous errors +error: lifetime may not live long enough + --> $DIR/E0637.rs:5:9 + | +LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + | - let's call the lifetime of this reference `'1` +... +LL | str1 + | ^^^^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/E0637.rs:7:9 + | +LL | fn underscore_lifetime<'_>(str1: &'_ str, str2: &'_ str) -> &'_ str { + | - let's call the lifetime of this reference `'2` +... +LL | str2 + | ^^^^ returning this value requires that `'2` must outlive `'static` + +error: aborting due to 5 previous errors Some errors have detailed explanations: E0106, E0637. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/explicit-tail-calls/return-mismatches.rs b/tests/ui/explicit-tail-calls/return-mismatches.rs index 935a1a1d28b..8094a192913 100644 --- a/tests/ui/explicit-tail-calls/return-mismatches.rs +++ b/tests/ui/explicit-tail-calls/return-mismatches.rs @@ -13,7 +13,7 @@ fn _f1() { become _g1(); //~ error: mismatched types } -fn _g1() -> ! { +fn _g1() -> ! { //~ WARN: cannot return without recursing become _g1(); } diff --git a/tests/ui/explicit-tail-calls/return-mismatches.stderr b/tests/ui/explicit-tail-calls/return-mismatches.stderr index 1dcc35797c1..31c7a46ded9 100644 --- a/tests/ui/explicit-tail-calls/return-mismatches.stderr +++ b/tests/ui/explicit-tail-calls/return-mismatches.stderr @@ -22,6 +22,17 @@ error[E0308]: mismatched types LL | become _g2(); | ^^^^^^^^^^^^ expected `u32`, found `u16` -error: aborting due to 3 previous errors +warning: function cannot return without recursing + --> $DIR/return-mismatches.rs:16:1 + | +LL | fn _g1() -> ! { + | ^^^^^^^^^^^^^ cannot return without recursing +LL | become _g1(); + | ----- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: aborting due to 3 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed index bb093a4af4a..3c71587c8e3 100644 --- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] #![allow(dropping_references)] struct Foo { diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs index 1a9f89c054f..075d4cbe02b 100644 --- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] #![allow(dropping_references)] struct Foo { diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr b/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr index d2d69ce6daf..13b6ee9987e 100644 --- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr +++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.stderr @@ -1,5 +1,5 @@ error[E0040]: explicit use of destructor method - --> $DIR/explicit-call-to-supertrait-dtor.rs:22:14 + --> $DIR/explicit-call-to-supertrait-dtor.rs:23:14 | LL | self.drop(); | ^^^^ explicit destructor calls not allowed diff --git a/tests/ui/expr/if/if-no-match-bindings.rs b/tests/ui/expr/if/if-no-match-bindings.rs index ca3df0fdde4..d36a436397b 100644 --- a/tests/ui/expr/if/if-no-match-bindings.rs +++ b/tests/ui/expr/if/if-no-match-bindings.rs @@ -6,6 +6,7 @@ fn b_ref<'a>() -> &'a bool { &true } fn b_mut_ref<'a>() -> &'a mut bool { &mut true } +//~^ ERROR: cannot return reference to temporary fn main() { // This is OK: diff --git a/tests/ui/expr/if/if-no-match-bindings.stderr b/tests/ui/expr/if/if-no-match-bindings.stderr index 737a5d60448..18f3b6b168e 100644 --- a/tests/ui/expr/if/if-no-match-bindings.stderr +++ b/tests/ui/expr/if/if-no-match-bindings.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:18:8 + --> $DIR/if-no-match-bindings.rs:19:8 | LL | if b_ref() {} | ^^^^^^^ expected `bool`, found `&bool` @@ -10,7 +10,7 @@ LL | if *b_ref() {} | + error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:19:8 + --> $DIR/if-no-match-bindings.rs:20:8 | LL | if b_mut_ref() {} | ^^^^^^^^^^^ expected `bool`, found `&mut bool` @@ -21,7 +21,7 @@ LL | if *b_mut_ref() {} | + error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:20:8 + --> $DIR/if-no-match-bindings.rs:21:8 | LL | if &true {} | ^^^^^ expected `bool`, found `&bool` @@ -33,7 +33,7 @@ LL + if true {} | error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:21:8 + --> $DIR/if-no-match-bindings.rs:22:8 | LL | if &mut true {} | ^^^^^^^^^ expected `bool`, found `&mut bool` @@ -45,7 +45,7 @@ LL + if true {} | error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:24:11 + --> $DIR/if-no-match-bindings.rs:25:11 | LL | while b_ref() {} | ^^^^^^^ expected `bool`, found `&bool` @@ -56,7 +56,7 @@ LL | while *b_ref() {} | + error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:25:11 + --> $DIR/if-no-match-bindings.rs:26:11 | LL | while b_mut_ref() {} | ^^^^^^^^^^^ expected `bool`, found `&mut bool` @@ -67,7 +67,7 @@ LL | while *b_mut_ref() {} | + error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:26:11 + --> $DIR/if-no-match-bindings.rs:27:11 | LL | while &true {} | ^^^^^ expected `bool`, found `&bool` @@ -79,7 +79,7 @@ LL + while true {} | error[E0308]: mismatched types - --> $DIR/if-no-match-bindings.rs:27:11 + --> $DIR/if-no-match-bindings.rs:28:11 | LL | while &mut true {} | ^^^^^^^^^ expected `bool`, found `&mut bool` @@ -90,6 +90,16 @@ LL - while &mut true {} LL + while true {} | -error: aborting due to 8 previous errors +error[E0515]: cannot return reference to temporary value + --> $DIR/if-no-match-bindings.rs:8:38 + | +LL | fn b_mut_ref<'a>() -> &'a mut bool { &mut true } + | ^^^^^---- + | | | + | | temporary value created here + | returns a reference to data owned by the current function + +error: aborting due to 9 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0515. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr index 79efcc5d8b0..6ad3effe0e2 100644 --- a/tests/ui/extern-flag/empty-extern-arg.stderr +++ b/tests/ui/extern-flag/empty-extern-arg.stderr @@ -1,11 +1,6 @@ error: extern location for std does not exist: -error: `#[panic_handler]` function required, but not found +error: requires `sized` lang_item -error: unwinding panics are not supported without std - | - = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding - = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/extern-mod-syntax.rs b/tests/ui/extern-mod-syntax.rs deleted file mode 100644 index 65dfa6a0f57..00000000000 --- a/tests/ui/extern-mod-syntax.rs +++ /dev/null @@ -1,11 +0,0 @@ -// run-pass - -#![allow(unused_imports)] -#![no_std] - -extern crate std; -use std::ffi::c_void; - -pub fn main() { - std::println!("Hello world!"); -} diff --git a/tests/ui/issues/issue-16250.rs b/tests/ui/extern/issue-16250.rs index 436e2a6cee3..436e2a6cee3 100644 --- a/tests/ui/issues/issue-16250.rs +++ b/tests/ui/extern/issue-16250.rs diff --git a/tests/ui/issues/issue-16250.stderr b/tests/ui/extern/issue-16250.stderr index 9d3e8811461..9d3e8811461 100644 --- a/tests/ui/issues/issue-16250.stderr +++ b/tests/ui/extern/issue-16250.stderr diff --git a/tests/ui/issues/issue-47725.rs b/tests/ui/extern/issue-47725.rs index 9ec55be5872..9ec55be5872 100644 --- a/tests/ui/issues/issue-47725.rs +++ b/tests/ui/extern/issue-47725.rs diff --git a/tests/ui/issues/issue-47725.stderr b/tests/ui/extern/issue-47725.stderr index 0d3b77b4608..0d3b77b4608 100644 --- a/tests/ui/issues/issue-47725.stderr +++ b/tests/ui/extern/issue-47725.stderr diff --git a/tests/ui/extern/no-mangle-associated-fn.rs b/tests/ui/extern/no-mangle-associated-fn.rs index ecd44abbf26..56afd8b9092 100644 --- a/tests/ui/extern/no-mangle-associated-fn.rs +++ b/tests/ui/extern/no-mangle-associated-fn.rs @@ -12,7 +12,7 @@ impl Foo { } } -trait Bar { +trait Bar { //~ WARN trait `Bar` is never used fn qux() -> u8; } diff --git a/tests/ui/extern/no-mangle-associated-fn.stderr b/tests/ui/extern/no-mangle-associated-fn.stderr new file mode 100644 index 00000000000..772cbf6cf7d --- /dev/null +++ b/tests/ui/extern/no-mangle-associated-fn.stderr @@ -0,0 +1,10 @@ +warning: trait `Bar` is never used + --> $DIR/no-mangle-associated-fn.rs:15:7 + | +LL | trait Bar { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs index 073599edad7..f87d3aab635 100644 --- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs @@ -11,7 +11,6 @@ impl Tr1 for S1 { type As1 = S2; } trait _Tr3 { type A: Iterator<Item: Copy>; //~^ ERROR associated type bounds are unstable - //~| ERROR the trait bound `<<Self as _Tr3>::A as Iterator>::Item: Copy` is not satisfied type B: Iterator<Item: 'static>; //~^ ERROR associated type bounds are unstable diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr index efab91f25f0..855a29953f1 100644 --- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr @@ -9,7 +9,7 @@ LL | type A: Iterator<Item: Copy>; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:16:22 + --> $DIR/feature-gate-associated_type_bounds.rs:15:22 | LL | type B: Iterator<Item: 'static>; | ^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | type B: Iterator<Item: 'static>; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:20:20 + --> $DIR/feature-gate-associated_type_bounds.rs:19:20 | LL | struct _St1<T: Tr1<As1: Tr2>> { | ^^^^^^^^ @@ -29,7 +29,7 @@ LL | struct _St1<T: Tr1<As1: Tr2>> { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:27:18 + --> $DIR/feature-gate-associated_type_bounds.rs:26:18 | LL | enum _En1<T: Tr1<As1: Tr2>> { | ^^^^^^^^ @@ -39,7 +39,7 @@ LL | enum _En1<T: Tr1<As1: Tr2>> { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:34:19 + --> $DIR/feature-gate-associated_type_bounds.rs:33:19 | LL | union _Un1<T: Tr1<As1: Tr2>> { | ^^^^^^^^ @@ -49,7 +49,7 @@ LL | union _Un1<T: Tr1<As1: Tr2>> { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:41:37 + --> $DIR/feature-gate-associated_type_bounds.rs:40:37 | LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T; | ^^^^^^^^^^ @@ -59,7 +59,7 @@ LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:44:22 + --> $DIR/feature-gate-associated_type_bounds.rs:43:22 | LL | fn _apit(_: impl Tr1<As1: Copy>) {} | ^^^^^^^^^ @@ -69,7 +69,7 @@ LL | fn _apit(_: impl Tr1<As1: Copy>) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:46:26 + --> $DIR/feature-gate-associated_type_bounds.rs:45:26 | LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {} | ^^^^^^^^^ @@ -79,7 +79,7 @@ LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:49:24 + --> $DIR/feature-gate-associated_type_bounds.rs:48:24 | LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 } | ^^^^^^^^^ @@ -89,7 +89,7 @@ LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:52:31 + --> $DIR/feature-gate-associated_type_bounds.rs:51:31 | LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) } | ^^^^^^^^^ @@ -99,7 +99,7 @@ LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) } = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:55:23 + --> $DIR/feature-gate-associated_type_bounds.rs:54:23 | LL | const _cdef: impl Tr1<As1: Copy> = S1; | ^^^^^^^^^ @@ -109,7 +109,7 @@ LL | const _cdef: impl Tr1<As1: Copy> = S1; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:61:24 + --> $DIR/feature-gate-associated_type_bounds.rs:60:24 | LL | static _sdef: impl Tr1<As1: Copy> = S1; | ^^^^^^^^^ @@ -119,7 +119,7 @@ LL | static _sdef: impl Tr1<As1: Copy> = S1; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated type bounds are unstable - --> $DIR/feature-gate-associated_type_bounds.rs:68:21 + --> $DIR/feature-gate-associated_type_bounds.rs:67:21 | LL | let _: impl Tr1<As1: Copy> = S1; | ^^^^^^^^^ @@ -129,7 +129,7 @@ LL | let _: impl Tr1<As1: Copy> = S1; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in const types - --> $DIR/feature-gate-associated_type_bounds.rs:55:14 + --> $DIR/feature-gate-associated_type_bounds.rs:54:14 | LL | const _cdef: impl Tr1<As1: Copy> = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -137,7 +137,7 @@ LL | const _cdef: impl Tr1<As1: Copy> = S1; = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in static types - --> $DIR/feature-gate-associated_type_bounds.rs:61:15 + --> $DIR/feature-gate-associated_type_bounds.rs:60:15 | LL | static _sdef: impl Tr1<As1: Copy> = S1; | ^^^^^^^^^^^^^^^^^^^ @@ -145,25 +145,14 @@ LL | static _sdef: impl Tr1<As1: Copy> = S1; = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/feature-gate-associated_type_bounds.rs:68:12 + --> $DIR/feature-gate-associated_type_bounds.rs:67:12 | LL | let _: impl Tr1<As1: Copy> = S1; | ^^^^^^^^^^^^^^^^^^^ | = note: `impl Trait` is only allowed in arguments and return types of functions and methods -error[E0277]: the trait bound `<<Self as _Tr3>::A as Iterator>::Item: Copy` is not satisfied - --> $DIR/feature-gate-associated_type_bounds.rs:12:28 - | -LL | type A: Iterator<Item: Copy>; - | ^^^^ the trait `Copy` is not implemented for `<<Self as _Tr3>::A as Iterator>::Item` - | -help: consider further restricting the associated type - | -LL | trait _Tr3 where <<Self as _Tr3>::A as Iterator>::Item: Copy { - | +++++++++++++++++++++++++++++++++++++++++++++++++ - -error: aborting due to 17 previous errors +error: aborting due to 16 previous errors -Some errors have detailed explanations: E0277, E0562, E0658. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0562, E0658. +For more information about an error, try `rustc --explain E0562`. diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs index b600ad23eee..801956c3339 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs +++ b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.rs @@ -13,4 +13,5 @@ extern "C" { fn main() { assert_eq!(FOO, 3); + //~^ ERROR extern static is unsafe } diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr index 0e1fe5572a9..62b72e35059 100644 --- a/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr +++ b/tests/ui/feature-gates/feature-gate-cfg-target-thread-local.stderr @@ -8,6 +8,15 @@ LL | #[cfg_attr(target_thread_local, thread_local)] = help: add `#![feature(cfg_target_thread_local)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/feature-gate-cfg-target-thread-local.rs:15:16 + | +LL | assert_eq!(FOO, 3); + | ^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.rs b/tests/ui/feature-gates/feature-gate-custom_mir.rs index 0126dde2f7d..e100df08ee7 100644 --- a/tests/ui/feature-gates/feature-gate-custom_mir.rs +++ b/tests/ui/feature-gates/feature-gate-custom_mir.rs @@ -1,10 +1,15 @@ #![feature(core_intrinsics)] extern crate core; +use core::intrinsics::mir::*; //~ custom_mir #[custom_mir(dialect = "built")] //~ ERROR the `#[custom_mir]` attribute is just used for the Rust test suite pub fn foo(_x: i32) -> i32 { - 0 + mir! { + { + Return() //~ custom_mir + } + } } fn main() { diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.stderr b/tests/ui/feature-gates/feature-gate-custom_mir.stderr index 34899e5e66c..118eab144bf 100644 --- a/tests/ui/feature-gates/feature-gate-custom_mir.stderr +++ b/tests/ui/feature-gates/feature-gate-custom_mir.stderr @@ -1,5 +1,5 @@ error[E0658]: the `#[custom_mir]` attribute is just used for the Rust test suite - --> $DIR/feature-gate-custom_mir.rs:5:1 + --> $DIR/feature-gate-custom_mir.rs:6:1 | LL | #[custom_mir(dialect = "built")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,6 +7,24 @@ LL | #[custom_mir(dialect = "built")] = help: add `#![feature(custom_mir)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0658]: use of unstable library feature 'custom_mir': MIR is an implementation detail and extremely unstable + --> $DIR/feature-gate-custom_mir.rs:4:5 + | +LL | use core::intrinsics::mir::*; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(custom_mir)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature 'custom_mir': MIR is an implementation detail and extremely unstable + --> $DIR/feature-gate-custom_mir.rs:10:13 + | +LL | Return() + | ^^^^^^ + | + = help: add `#![feature(custom_mir)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs b/tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs deleted file mode 100644 index f354534356c..00000000000 --- a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![crate_type = "lib"] - -extern "C" { - #[ffi_returns_twice] //~ ERROR the `#[ffi_returns_twice]` attribute is an experimental feature - pub fn foo(); -} diff --git a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr b/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr deleted file mode 100644 index 8d19874c36a..00000000000 --- a/tests/ui/feature-gates/feature-gate-ffi_returns_twice.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: the `#[ffi_returns_twice]` attribute is an experimental feature - --> $DIR/feature-gate-ffi_returns_twice.rs:4:5 - | -LL | #[ffi_returns_twice] - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #58314 <https://github.com/rust-lang/rust/issues/58314> for more information - = help: add `#![feature(ffi_returns_twice)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.rs b/tests/ui/feature-gates/feature-gate-naked_functions.rs index 8e93b194174..dc561234809 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.rs +++ b/tests/ui/feature-gates/feature-gate-naked_functions.rs @@ -6,12 +6,14 @@ use std::arch::asm; //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked() { asm!("", options(noreturn)) + //~^ ERROR: requires unsafe } #[naked] //~^ the `#[naked]` attribute is an experimental feature extern "C" fn naked_2() -> isize { asm!("", options(noreturn)) + //~^ ERROR: requires unsafe } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.stderr b/tests/ui/feature-gates/feature-gate-naked_functions.stderr index e1b82658217..ffdf31e147a 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions.stderr +++ b/tests/ui/feature-gates/feature-gate-naked_functions.stderr @@ -9,7 +9,7 @@ LL | #[naked] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `#[naked]` attribute is an experimental feature - --> $DIR/feature-gate-naked_functions.rs:11:1 + --> $DIR/feature-gate-naked_functions.rs:12:1 | LL | #[naked] | ^^^^^^^^ @@ -18,6 +18,23 @@ LL | #[naked] = help: add `#![feature(naked_functions)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 2 previous errors +error[E0133]: use of inline assembly is unsafe and requires unsafe function or block + --> $DIR/feature-gate-naked_functions.rs:8:5 + | +LL | asm!("", options(noreturn)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of inline assembly + | + = note: inline assembly is entirely unchecked and can cause undefined behavior + +error[E0133]: use of inline assembly is unsafe and requires unsafe function or block + --> $DIR/feature-gate-naked_functions.rs:15:5 + | +LL | asm!("", options(noreturn)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of inline assembly + | + = note: inline assembly is entirely unchecked and can cause undefined behavior + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs index 1285cca6b8b..37b7d52fafc 100644 --- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs @@ -8,7 +8,7 @@ fn main() { extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change fn atomic_fence(); } - atomic_fence(); + atomic_fence(); //~ ERROR: is unsafe 42 }); } diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr index b0ed6e60760..3dc11b5612c 100644 --- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr +++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr @@ -7,6 +7,15 @@ LL | extern "rust-intrinsic" { = help: add `#![feature(intrinsics)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0133]: call to unsafe function `main::atomic_fence` is unsafe and requires unsafe function or block + --> $DIR/feature-gated-feature-in-macro-arg.rs:11:9 + | +LL | atomic_fence(); + | ^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/tests/ui/ffi_returns_twice.rs b/tests/ui/ffi_returns_twice.rs deleted file mode 100644 index 8195d0e4863..00000000000 --- a/tests/ui/ffi_returns_twice.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![feature(ffi_returns_twice)] -#![crate_type = "lib"] - -#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions -pub fn foo() {} - -#[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions -macro_rules! bar { - () => () -} - -extern "C" { - #[ffi_returns_twice] //~ ERROR `#[ffi_returns_twice]` may only be used on foreign functions - static INT: i32; -} diff --git a/tests/ui/ffi_returns_twice.stderr b/tests/ui/ffi_returns_twice.stderr deleted file mode 100644 index 0abe7613f14..00000000000 --- a/tests/ui/ffi_returns_twice.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions - --> $DIR/ffi_returns_twice.rs:4:1 - | -LL | #[ffi_returns_twice] - | ^^^^^^^^^^^^^^^^^^^^ - -error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions - --> $DIR/ffi_returns_twice.rs:7:1 - | -LL | #[ffi_returns_twice] - | ^^^^^^^^^^^^^^^^^^^^ - -error[E0724]: `#[ffi_returns_twice]` may only be used on foreign functions - --> $DIR/ffi_returns_twice.rs:13:5 - | -LL | #[ffi_returns_twice] - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0724`. diff --git a/tests/ui/fn/suggest-return-closure.rs b/tests/ui/fn/suggest-return-closure.rs index 33daa1ea0b4..81f20272867 100644 --- a/tests/ui/fn/suggest-return-closure.rs +++ b/tests/ui/fn/suggest-return-closure.rs @@ -17,10 +17,16 @@ fn fn_mut() -> _ { //~| SUGGESTION impl FnMut(char) //~| NOTE for more information on `Fn` traits and closure types let x = String::new(); - |c| { + //~^ HELP: consider changing this to be mutable + |c| { //~ NOTE: value captured here x.push(c); + //~^ ERROR: does not live long enough + //~| NOTE: does not live long enough + //~| NOTE: cannot borrow as mutable + //~| ERROR: not declared as mutable } -} +} //~ NOTE: borrow later used here +//~^ NOTE: dropped here fn fun() -> _ { //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] diff --git a/tests/ui/fn/suggest-return-closure.stderr b/tests/ui/fn/suggest-return-closure.stderr index 341044469ea..8e80a11fe1b 100644 --- a/tests/ui/fn/suggest-return-closure.stderr +++ b/tests/ui/fn/suggest-return-closure.stderr @@ -21,7 +21,7 @@ LL | fn fn_mut() -> _ { = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/suggest-return-closure.rs:25:13 + --> $DIR/suggest-return-closure.rs:31:13 | LL | fn fun() -> _ { | ^ @@ -31,6 +31,29 @@ LL | fn fun() -> _ { | = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html -error: aborting due to 3 previous errors +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/suggest-return-closure.rs:22:9 + | +LL | let x = String::new(); + | - help: consider changing this to be mutable: `mut x` +... +LL | x.push(c); + | ^ cannot borrow as mutable + +error[E0597]: `x` does not live long enough + --> $DIR/suggest-return-closure.rs:22:9 + | +LL | |c| { + | --- value captured here +LL | x.push(c); + | ^ borrowed value does not live long enough +... +LL | } + | -- borrow later used here + | | + | `x` dropped here while still borrowed + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0121`. +Some errors have detailed explanations: E0121, E0596, E0597. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/generic-associated-types/bugs/issue-88460.rs b/tests/ui/generic-associated-types/bugs/issue-88460.rs index 224e696ad2c..3d2b225f0cd 100644 --- a/tests/ui/generic-associated-types/bugs/issue-88460.rs +++ b/tests/ui/generic-associated-types/bugs/issue-88460.rs @@ -1,7 +1,4 @@ -// check-fail -// known-bug: #88460 - -// This should pass, but has a missed normalization due to HRTB. +// check-pass pub trait Marker {} diff --git a/tests/ui/generic-associated-types/bugs/issue-88460.stderr b/tests/ui/generic-associated-types/bugs/issue-88460.stderr deleted file mode 100644 index 74418a0c0bd..00000000000 --- a/tests/ui/generic-associated-types/bugs/issue-88460.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied - --> $DIR/issue-88460.rs:28:10 - | -LL | test(Foo); - | ---- ^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>` - | | - | required by a bound introduced by this call - | - = help: the trait `Marker` is implemented for `()` -note: this is a known limitation of the trait solver that will be lifted in the future - --> $DIR/issue-88460.rs:28:10 - | -LL | test(Foo); - | -----^^^- - | | | - | | the trait solver is unable to infer the generic types that should be inferred from this argument - | add turbofish arguments to this call to specify the types manually, even if it's redundant -note: required by a bound in `test` - --> $DIR/issue-88460.rs:15:27 - | -LL | fn test<T>(value: T) - | ---- required by a bound in this function -... -LL | for<'a> T::Assoc<'a>: Marker, - | ^^^^^^ required by this bound in `test` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr b/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr index 84210eeb1a6..b19280b45c2 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr +++ b/tests/ui/generic-associated-types/extended/lending_iterator.base.stderr @@ -7,6 +7,12 @@ LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self LL | fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self { | ^^^^^^^^^^^^ impl has extra requirement `I: 'x` -error: aborting due to 1 previous error +error: `Self` does not live long enough + --> $DIR/lending_iterator.rs:34:9 + | +LL | <B as FromLendingIterator<A>>::from_iter(self) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0276`. diff --git a/tests/ui/generic-associated-types/extended/lending_iterator.rs b/tests/ui/generic-associated-types/extended/lending_iterator.rs index 247761dd04b..8bec78d6ecd 100644 --- a/tests/ui/generic-associated-types/extended/lending_iterator.rs +++ b/tests/ui/generic-associated-types/extended/lending_iterator.rs @@ -32,6 +32,7 @@ pub trait LendingIterator { Self: for<'q> LendingIterator<Item<'q> = A>, { <B as FromLendingIterator<A>>::from_iter(self) + //[base]~^ ERROR: does not live long enough } } diff --git a/tests/ui/generic-associated-types/issue-70304.rs b/tests/ui/generic-associated-types/issue-70304.rs index 8898d4c7d13..935d3f7a4ba 100644 --- a/tests/ui/generic-associated-types/issue-70304.rs +++ b/tests/ui/generic-associated-types/issue-70304.rs @@ -52,4 +52,5 @@ fn create_doc() -> impl Document<Cursor<'_> = DocCursorImpl<'_>> { pub fn main() { let doc = create_doc(); let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); + //~^ ERROR: `doc` does not live long enough } diff --git a/tests/ui/generic-associated-types/issue-70304.stderr b/tests/ui/generic-associated-types/issue-70304.stderr index 9b02c1b0768..8e012cc6d93 100644 --- a/tests/ui/generic-associated-types/issue-70304.stderr +++ b/tests/ui/generic-associated-types/issue-70304.stderr @@ -27,7 +27,21 @@ LL | type Cursor<'a>: DocCursor<'a>; = note: this bound is currently required to ensure that impls have maximum flexibility = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information -error: aborting due to 3 previous errors +error[E0597]: `doc` does not live long enough + --> $DIR/issue-70304.rs:54:59 + | +LL | let doc = create_doc(); + | --- binding `doc` declared here +LL | let lexer: Lexer<'_, DocCursorImpl<'_>> = Lexer::from(&doc); + | ------------^^^^- + | | | + | | borrowed value does not live long enough + | argument requires that `doc` is borrowed for `'static` +LL | +LL | } + | - `doc` dropped here while still borrowed + +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0106, E0637. +Some errors have detailed explanations: E0106, E0597, E0637. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/generic-associated-types/issue-74684-2.rs b/tests/ui/generic-associated-types/issue-74684-2.rs index ff243af2cb3..96cdb01be3b 100644 --- a/tests/ui/generic-associated-types/issue-74684-2.rs +++ b/tests/ui/generic-associated-types/issue-74684-2.rs @@ -10,7 +10,7 @@ impl <T> Fun for T { fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> { let a = [0; 1]; - let x = T::identity(&a); + let x = T::identity(&a); //~ ERROR: does not live long enough todo!() } diff --git a/tests/ui/generic-associated-types/issue-74684-2.stderr b/tests/ui/generic-associated-types/issue-74684-2.stderr index e50e3df85b3..d39513ec523 100644 --- a/tests/ui/generic-associated-types/issue-74684-2.stderr +++ b/tests/ui/generic-associated-types/issue-74684-2.stderr @@ -17,6 +17,23 @@ note: required by a bound in `bug` LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> { | ^^^^^^^^^^^^ required by this bound in `bug` -error: aborting due to 1 previous error +error[E0597]: `a` does not live long enough + --> $DIR/issue-74684-2.rs:13:25 + | +LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> { + | -- lifetime `'a` defined here +LL | let a = [0; 1]; + | - binding `a` declared here +LL | let x = T::identity(&a); + | ------------^^- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'a` +LL | todo!() +LL | } + | - `a` dropped here while still borrowed + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0271, E0597. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/generic-associated-types/issue-80433.rs b/tests/ui/generic-associated-types/issue-80433.rs index bdba78c2ccd..6d23427f16f 100644 --- a/tests/ui/generic-associated-types/issue-80433.rs +++ b/tests/ui/generic-associated-types/issue-80433.rs @@ -22,11 +22,12 @@ fn test_simpler<'a>(dst: &'a mut impl TestMut<Output = &'a mut f32>) //~^ ERROR missing generics for associated type { for n in 0i16..100 { - *dst.test_mut() = n.into(); + *dst.test_mut() = n.into(); //~ ERROR: cannot borrow + //~^ ERROR: borrowed data escapes outside of function } } fn main() { let mut t1: E<f32> = Default::default(); - test_simpler(&mut t1); + test_simpler(&mut t1); //~ ERROR does not live long enough } diff --git a/tests/ui/generic-associated-types/issue-80433.stderr b/tests/ui/generic-associated-types/issue-80433.stderr index ab1fb794418..2bbf87ff1ff 100644 --- a/tests/ui/generic-associated-types/issue-80433.stderr +++ b/tests/ui/generic-associated-types/issue-80433.stderr @@ -25,6 +25,43 @@ LL | type Output<'a>; = note: this bound is currently required to ensure that impls have maximum flexibility = note: we are soliciting feedback, see issue #87479 <https://github.com/rust-lang/rust/issues/87479> for more information -error: aborting due to 2 previous errors +error[E0499]: cannot borrow `*dst` as mutable more than once at a time + --> $DIR/issue-80433.rs:25:10 + | +LL | *dst.test_mut() = n.into(); + | ^^^----------- + | | + | `*dst` was mutably borrowed here in the previous iteration of the loop + | argument requires that `*dst` is borrowed for `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/issue-80433.rs:25:10 + | +LL | fn test_simpler<'a>(dst: &'a mut impl TestMut<Output = &'a mut f32>) + | -- --- `dst` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +... +LL | *dst.test_mut() = n.into(); + | ^^^^^^^^^^^^^^ + | | + | `dst` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0597]: `t1` does not live long enough + --> $DIR/issue-80433.rs:32:18 + | +LL | let mut t1: E<f32> = Default::default(); + | ------ binding `t1` declared here +LL | test_simpler(&mut t1); + | -------------^^^^^^^- + | | | + | | borrowed value does not live long enough + | argument requires that `t1` is borrowed for `'static` +LL | } + | - `t1` dropped here while still borrowed + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0499, E0521, E0597. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-88360.fixed b/tests/ui/generic-associated-types/issue-88360.fixed index 3dea8bf7ac8..6fb1e2559c0 100644 --- a/tests/ui/generic-associated-types/issue-88360.fixed +++ b/tests/ui/generic-associated-types/issue-88360.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait GatTrait { type Gat<'a> where Self: 'a; diff --git a/tests/ui/generic-associated-types/issue-88360.rs b/tests/ui/generic-associated-types/issue-88360.rs index 4d4c7ea3180..c8f07955b61 100644 --- a/tests/ui/generic-associated-types/issue-88360.rs +++ b/tests/ui/generic-associated-types/issue-88360.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait GatTrait { type Gat<'a> where Self: 'a; diff --git a/tests/ui/generic-associated-types/issue-88360.stderr b/tests/ui/generic-associated-types/issue-88360.stderr index 49d36acadd6..488e50d2843 100644 --- a/tests/ui/generic-associated-types/issue-88360.stderr +++ b/tests/ui/generic-associated-types/issue-88360.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-88360.rs:15:9 + --> $DIR/issue-88360.rs:16:9 | LL | trait SuperTrait<T> | - found this type parameter diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs index add4d58f86a..92ce4a0970f 100644 --- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs +++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs @@ -5,7 +5,7 @@ trait X { type Y<T>; } -trait M { +trait M { //~ NOTE fn f(&self) {} } diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr index 1dd463f996c..61512dd4658 100644 --- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr +++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr @@ -14,6 +14,12 @@ LL | impl<T: X<Y<i32> = i32>> M for T {} | ^^^^^^^^^^^^ - - | | | unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `M` defines an item `f`, perhaps you need to implement it + --> $DIR/method-unsatisfied-assoc-type-predicate.rs:8:1 + | +LL | trait M { + | ^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/generics/generic-extern.rs b/tests/ui/generics/generic-extern.rs index 3690d6fd07d..36fa5eaafd6 100644 --- a/tests/ui/generics/generic-extern.rs +++ b/tests/ui/generics/generic-extern.rs @@ -3,5 +3,5 @@ extern "C" { } fn main() { - foo::<i32>(); + foo::<i32>(); //~ ERROR requires unsafe } diff --git a/tests/ui/generics/generic-extern.stderr b/tests/ui/generics/generic-extern.stderr index 4d9f6fedef1..a3f28825316 100644 --- a/tests/ui/generics/generic-extern.stderr +++ b/tests/ui/generics/generic-extern.stderr @@ -6,6 +6,15 @@ LL | fn foo<T>(); | = help: replace the type parameters with concrete types like `u32` -error: aborting due to 1 previous error +error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block + --> $DIR/generic-extern.rs:6:5 + | +LL | foo::<i32>(); + | ^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0044`. +Some errors have detailed explanations: E0044, E0133. +For more information about an error, try `rustc --explain E0044`. diff --git a/tests/ui/generics/generic-no-mangle.fixed b/tests/ui/generics/generic-no-mangle.fixed index aa6d6310f5f..f51040358c0 100644 --- a/tests/ui/generics/generic-no-mangle.fixed +++ b/tests/ui/generics/generic-no-mangle.fixed @@ -1,5 +1,5 @@ // run-rustfix - +#![allow(dead_code)] #![deny(no_mangle_generic_items)] diff --git a/tests/ui/generics/generic-no-mangle.rs b/tests/ui/generics/generic-no-mangle.rs index 8a59ca75aaf..02015331c57 100644 --- a/tests/ui/generics/generic-no-mangle.rs +++ b/tests/ui/generics/generic-no-mangle.rs @@ -1,5 +1,5 @@ // run-rustfix - +#![allow(dead_code)] #![deny(no_mangle_generic_items)] #[no_mangle] diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs index dac97347349..99de7845d7b 100644 --- a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs +++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs @@ -4,4 +4,5 @@ fn main() { let xs = [13, 1, 5, 2, 3, 1, 21, 8]; let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; //~^ `X..` patterns in slices are experimental + //~| ERROR: refutable pattern } diff --git a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr index 8ae8f052e5b..b011044f4dd 100644 --- a/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr +++ b/tests/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr @@ -8,6 +8,21 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0005]: refutable pattern in local binding + --> $DIR/feature-gate-half-open-range-patterns-in-slices.rs:5:9 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `[i32::MIN..=2_i32, ..]` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `[i32; 8]` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0005, E0658. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs index 526a797e9d6..33506a5c444 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs @@ -23,6 +23,7 @@ fn syntax2() { macro_rules! mac { ($e:expr) => { let ...$e; //~ ERROR range-to patterns with `...` are not allowed + //~^ ERROR refutable pattern in local binding } } diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr index ddffeaf9780..6832f21f25e 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr @@ -33,5 +33,24 @@ LL | mac!(0); | = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 5 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:25:17 + | +LL | let ...$e; + | ^^^^^ pattern `1_i32..=i32::MAX` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let ...$e; { todo!() } + | ++ +++++++++++ + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs index 30173b1b4be..cff0c42eb52 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.rs @@ -1,6 +1,9 @@ fn main() { let x = 42; match x { + //~^ ERROR: non-exhaustive patterns + //~| NOTE: not covered + //~| NOTE: matched value is of type 0..=73 => {}, 74..=> {}, //~^ ERROR unexpected `>` after inclusive range diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr index 8dfc46069f1..ecb43e83c70 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-match-arrow.stderr @@ -1,5 +1,5 @@ error: unexpected `>` after inclusive range - --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:5:14 + --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:8:14 | LL | 74..=> {}, | ---^ @@ -11,5 +11,19 @@ help: add a space between the pattern and `=>` LL | 74.. => {}, | + -error: aborting due to 1 previous error +error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` not covered + --> $DIR/half-open-range-pats-inclusive-match-arrow.rs:3:11 + | +LL | match x { + | ^ pattern `i32::MIN..=-1_i32` not covered + | + = note: the matched value is of type `i32` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ 74..=> {}, +LL ~ i32::MIN..=-1_i32 => todo!(), + | + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs index 6567c8cc67c..2f1ec658972 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs @@ -16,7 +16,9 @@ fn bar() { macro_rules! mac { ($e:expr) => { let $e...; //~ ERROR inclusive range with no end + //~^ ERROR: refutable pattern let $e..=; //~ ERROR inclusive range with no end + //~^ ERROR: refutable pattern } } diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr index 3ad84b0ef26..cb9e48e70e3 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr @@ -43,7 +43,7 @@ LL | mac!(0); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0586]: inclusive range with no end - --> $DIR/half-open-range-pats-inclusive-no-end.rs:19:19 + --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:19 | LL | let $e..=; | ^^^ help: use `..` instead @@ -54,6 +54,43 @@ LL | mac!(0); = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/half-open-range-pats-inclusive-no-end.rs:18:17 + | +LL | let $e...; + | ^^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e...; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:17 + | +LL | let $e..=; + | ^^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e..=; { todo!() } + | ++ +++++++++++ + +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0586`. +Some errors have detailed explanations: E0005, E0586. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs index c37af75b8fb..cd381544372 100644 --- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs @@ -5,4 +5,5 @@ fn main() { //~^ `X..` patterns in slices are experimental //~| exclusive range pattern syntax is experimental //~| exclusive range pattern syntax is experimental + //~| ERROR: refutable pattern } diff --git a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr index be8f3aa5051..fc549eb65c0 100644 --- a/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr +++ b/tests/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr @@ -30,6 +30,21 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = help: use an inclusive range pattern, like N..=M -error: aborting due to 3 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/slice_pattern_syntax_problem1.rs:4:9 + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `[i32::MIN..=2_i32, ..]` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `[i32; 8]` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0005, E0658. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs index bd4533e0433..dc865605ed3 100644 --- a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs +++ b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.rs @@ -12,10 +12,12 @@ fn hr_subtype<'c>(f: for<'a, 'b> fn(Inv<'a>, Inv<'a>)) { fn simple1<'c>(x: (&'c i32,)) { let _x: (&'static i32,) = x; + //~^ ERROR: lifetime may not live long enough } fn simple2<'c>(x: (&'c i32,)) { let _: (&'static i32,) = x; + //~^ ERROR: lifetime may not live long enough } fn main() { diff --git a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr index c6d6f508328..39d43181ed7 100644 --- a/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr +++ b/tests/ui/higher-ranked/subtype/placeholder-pattern-fail.stderr @@ -9,6 +9,22 @@ LL | let _: for<'a, 'b> fn(Inv<'a>, Inv<'b>) = sub; = note: expected fn pointer `for<'a, 'b> fn(Inv<'a>, Inv<'b>)` found fn pointer `for<'a> fn(Inv<'a>, Inv<'a>)` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/placeholder-pattern-fail.rs:14:13 + | +LL | fn simple1<'c>(x: (&'c i32,)) { + | -- lifetime `'c` defined here +LL | let _x: (&'static i32,) = x; + | ^^^^^^^^^^^^^^^ type annotation requires that `'c` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/placeholder-pattern-fail.rs:19:12 + | +LL | fn simple2<'c>(x: (&'c i32,)) { + | -- lifetime `'c` defined here +LL | let _: (&'static i32,) = x; + | ^^^^^^^^^^^^^^^ type annotation requires that `'c` must outlive `'static` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs index 48ebe5017aa..33e0ec4635b 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.rs @@ -18,7 +18,7 @@ fn want_foo_for_some_tcx<'x,F>(f: &'x F) want_foo_for_any_tcx(f); //~ ERROR not satisfied } -fn want_foo_for_any_tcx<F>(f: &F) +fn want_foo_for_any_tcx<F>(f: &F) //~ WARN cannot return without recursing where F : for<'tcx> Foo<'tcx> { want_foo_for_some_tcx(f); @@ -35,7 +35,7 @@ fn want_bar_for_some_ccx<'x,B>(b: &B) want_bar_for_any_ccx(b); //~ ERROR not satisfied } -fn want_bar_for_any_ccx<B>(b: &B) +fn want_bar_for_any_ccx<B>(b: &B) //~ WARN cannot return without recursing where B : for<'ccx> Bar<'ccx> { want_foo_for_some_tcx(b); diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr index 7f96909b6e7..f220ba6f338 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr @@ -38,6 +38,31 @@ help: consider further restricting this bound LL | where B : Bar<'x> + for<'ccx> Bar<'ccx> | +++++++++++++++++++++ -error: aborting due to 2 previous errors +warning: function cannot return without recursing + --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1 + | +LL | / fn want_foo_for_any_tcx<F>(f: &F) +LL | | where F : for<'tcx> Foo<'tcx> + | |_________________________________^ cannot return without recursing +... +LL | want_foo_for_any_tcx(f); + | ----------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +warning: function cannot return without recursing + --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1 + | +LL | / fn want_bar_for_any_ccx<B>(b: &B) +LL | | where B : for<'ccx> Bar<'ccx> + | |_________________________________^ cannot return without recursing +... +LL | want_bar_for_any_ccx(b); + | ----------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: aborting due to 2 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr index 73870703cfb..699a4ecc42b 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr @@ -15,6 +15,12 @@ note: the following trait bounds were not satisfied: | LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {} | --------- - ^^^^^^ unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `StreamExt` defines an item `filterx`, perhaps you need to implement it + --> $DIR/issue-30786.rs:66:1 + | +LL | pub trait StreamExt + | ^^^^^^^^^^^^^^^^^^^ error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, fn(&u64) -> &u64 {identity::<u64>}>, {closure@issue-30786.rs:131:30}>`, but its trait bounds were not satisfied --> $DIR/issue-30786.rs:132:24 @@ -33,6 +39,12 @@ note: the following trait bounds were not satisfied: | LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {} | --------- - ^^^^^^ unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `StreamExt` defines an item `countx`, perhaps you need to implement it + --> $DIR/issue-30786.rs:66:1 + | +LL | pub trait StreamExt + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs index ab9d9a7ce6f..7072f41066b 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.rs @@ -1,5 +1,4 @@ -// check-fail -// known-bug: #90950 +// check-pass trait Yokeable<'a>: 'static { type Output: 'a; diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr deleted file mode 100644 index 075e422e29c..00000000000 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-90950.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error[E0277]: the trait bound `for<'a> <_ as Yokeable<'a>>::Output: IsCovariant<'a>` is not satisfied - --> $DIR/issue-90950.rs:50:12 - | -LL | upcast(y) - | ------ ^ the trait `for<'a> IsCovariant<'a>` is not implemented for `<_ as Yokeable<'a>>::Output` - | | - | required by a bound introduced by this call - | - = help: the trait `IsCovariant<'a>` is implemented for `std::borrow::Cow<'a, T>` -note: this is a known limitation of the trait solver that will be lifted in the future - --> $DIR/issue-90950.rs:50:12 - | -LL | upcast(y) - | -------^- - | | | - | | the trait solver is unable to infer the generic types that should be inferred from this argument - | add turbofish arguments to this call to specify the types manually, even if it's redundant -note: required by a bound in `upcast` - --> $DIR/issue-90950.rs:27:42 - | -LL | fn upcast<Y>(x: Yoke<Y>) -> Yoke<Box<dyn IsCovariant<'static> + 'static>> where - | ------ required by a bound in this function -LL | Y: for<'a> Yokeable<'a>, -LL | for<'a> <Y as Yokeable<'a>>::Output: IsCovariant<'a> - | ^^^^^^^^^^^^^^^ required by this bound in `upcast` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs index 7693b118247..58ca5b0c187 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.rs @@ -1,5 +1,4 @@ -// check-fail -// known-bug: #89196 +// check-pass // Should pass, but we normalize and check bounds before we resolve the generics // of the function (which we know because of the return type). diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr deleted file mode 100644 index f42fc59536c..00000000000 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0277]: the trait bound `for<'a> <_ as Trait<'a>>::Out: Copy` is not satisfied - --> $DIR/norm-before-method-resolution.rs:22:17 - | -LL | let _: () = weird_bound(); - | ^^^^^^^^^^^^^ the trait `for<'a> Copy` is not implemented for `<_ as Trait<'a>>::Out` - | -note: this is a known limitation of the trait solver that will be lifted in the future - --> $DIR/norm-before-method-resolution.rs:22:17 - | -LL | let _: () = weird_bound(); - | ^^^^^^^^^^^^^ try adding turbofish arguments to this expression to specify the types manually, even if it's redundant -note: required by a bound in `weird_bound` - --> $DIR/norm-before-method-resolution.rs:18:40 - | -LL | fn weird_bound<X>() -> X - | ----------- required by a bound in this function -... -LL | for<'a> <X as Trait<'a>>::Out: Copy - | ^^^^ required by this bound in `weird_bound` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 5824ef31211..5c552411da7 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/alloc/src/raw_vec.rs:570:5: +thread 'main' panicked at library/alloc/src/raw_vec.rs:571:5: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace diff --git a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr index 1011fc4163b..0e3cd2ff060 100644 --- a/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr +++ b/tests/ui/impl-trait/equality-in-canonical-query.clone.stderr @@ -1,4 +1,4 @@ -note: no errors encountered even though `span_delayed_bug` issued +note: no errors encountered even though delayed bugs were created note: those delayed bugs will now be shown as internal compiler errors diff --git a/tests/ui/impl-trait/example-st.rs b/tests/ui/impl-trait/example-st.rs index 4e1aa3a0859..1e6ebc52365 100644 --- a/tests/ui/impl-trait/example-st.rs +++ b/tests/ui/impl-trait/example-st.rs @@ -3,7 +3,7 @@ struct State; type Error = (); -trait Bind<F> { +trait Bind<F> { //~ WARN trait `Bind` is never used type Output; fn bind(self, f: F) -> Self::Output; } diff --git a/tests/ui/impl-trait/example-st.stderr b/tests/ui/impl-trait/example-st.stderr new file mode 100644 index 00000000000..f722d7f6582 --- /dev/null +++ b/tests/ui/impl-trait/example-st.stderr @@ -0,0 +1,10 @@ +warning: trait `Bind` is never used + --> $DIR/example-st.rs:6:7 + | +LL | trait Bind<F> { + | ^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs index 57d68849251..e1aba8eda1b 100644 --- a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs +++ b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.rs @@ -4,10 +4,6 @@ fn ice() -> impl AsRef<Fn(&())> { //~^ WARN trait objects without an explicit `dyn` are deprecated - //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN trait objects without an explicit `dyn` are deprecated - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! Foo } diff --git a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr index d3c2d5d5b9f..84aaedf1838 100644 --- a/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr +++ b/tests/ui/impl-trait/fresh-lifetime-from-bare-trait-obj-114664.stderr @@ -12,33 +12,5 @@ help: use `dyn` LL | fn ice() -> impl AsRef<dyn Fn(&())> { | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/fresh-lifetime-from-bare-trait-obj-114664.rs:5:24 - | -LL | fn ice() -> impl AsRef<Fn(&())> { - | ^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | fn ice() -> impl AsRef<dyn Fn(&())> { - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/fresh-lifetime-from-bare-trait-obj-114664.rs:5:24 - | -LL | fn ice() -> impl AsRef<Fn(&())> { - | ^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | fn ice() -> impl AsRef<dyn Fn(&())> { - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed index 8dc8e045d47..ecc8488a152 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.fixed @@ -1,6 +1,7 @@ // edition:2021 // run-rustfix +#![allow(dead_code)] trait Trait { #[allow(async_fn_in_trait)] async fn foo(); diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs index 30b04d87b9a..860fea07df9 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.rs +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.rs @@ -1,6 +1,7 @@ // edition:2021 // run-rustfix +#![allow(dead_code)] trait Trait { #[allow(async_fn_in_trait)] async fn foo(); diff --git a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr index cf68ed87030..45fd79badb3 100644 --- a/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr +++ b/tests/ui/impl-trait/in-trait/suggest-missing-item.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `test`, `baz` - --> $DIR/suggest-missing-item.rs:19:1 + --> $DIR/suggest-missing-item.rs:20:1 | LL | async fn foo(); | --------------- `foo` from trait diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs b/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs index 18404f98603..9762ac98272 100644 --- a/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -16,12 +16,16 @@ fn foo<'a>(x: &i32) -> impl Copy + 'a { x } //~^ ERROR explicit lifetime required in the type of `x` fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) } +//~^ ERROR: lifetime may not live long enough fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) } +//~^ ERROR: lifetime may not live long enough fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) } +//~^ ERROR: lifetime may not live long enough fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) } +//~^ ERROR: lifetime may not live long enough fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } //~^ ERROR lifetime may not live long enough diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr index c60fe08c5d7..273f51ddbe3 100644 --- a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -67,7 +67,7 @@ LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x } | help: add explicit lifetime `'a` to the type of `x`: `&'a i32` error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:26:55 + --> $DIR/must_outlive_least_region_or_bound.rs:30:55 | LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug) { (Box::new(x), x) } | - ^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` @@ -84,7 +84,7 @@ LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) | ++++ error: lifetime may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:32:69 + --> $DIR/must_outlive_least_region_or_bound.rs:36:69 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static` @@ -99,12 +99,12 @@ LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x | ~~~~~~~~~~~~ error[E0700]: hidden type for `impl Fn(&'a u32)` captures lifetime that does not appear in bounds - --> $DIR/must_outlive_least_region_or_bound.rs:38:5 + --> $DIR/must_outlive_least_region_or_bound.rs:42:5 | LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { | -- ---------------- opaque type defined here | | - | hidden type `{closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13}` captures the lifetime `'b` as defined here + | hidden type `{closure@$DIR/must_outlive_least_region_or_bound.rs:42:5: 42:13}` captures the lifetime `'b` as defined here LL | move |_| println!("{}", y) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -114,7 +114,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32 | ++++ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/must_outlive_least_region_or_bound.rs:43:5 + --> $DIR/must_outlive_least_region_or_bound.rs:47:5 | LL | x | ^ @@ -127,7 +127,63 @@ help: consider adding an explicit lifetime bound LL | fn ty_param_wont_outlive_static<T:Debug + 'static>(x: T) -> impl Debug + 'static { | +++++++++ -error: aborting due to 9 previous errors +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:18:41 + | +LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) } + | - ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound + | +LL | fn elided3(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) } + | ++++ + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:21:50 + | +LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) } + | -- lifetime `'a` defined here ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | +help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound + | +LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) } + | ++++ + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:24:51 + | +LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) } + | - ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL | fn elided4(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) } + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn elided4(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) } + | ~~~~~~~~~~~~ + +error: lifetime may not live long enough + --> $DIR/must_outlive_least_region_or_bound.rs:27:60 + | +LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) } + | -- lifetime `'a` defined here ^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | +help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x` + | +LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) } + | ~~ +help: alternatively, add an explicit `'static` bound to this reference + | +LL | fn explicit4<'a>(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) } + | ~~~~~~~~~~~~ + +error: aborting due to 13 previous errors Some errors have detailed explanations: E0310, E0621, E0700. For more information about an error, try `rustc --explain E0310`. diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr index 7fd2ec57b14..f77b4bd517f 100644 --- a/tests/ui/impl-trait/normalize-tait-in-const.stderr +++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr @@ -4,5 +4,29 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { | ^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/normalize-tait-in-const.rs:26:5 + | +LL | fun(filter_positive()); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct + ~const std::ops::Fn<(&Alias<'_>,)>>(fun: F) { + | ++++++++++++++++++++++++++++++++++++ + +error[E0493]: destructor of `F` cannot be evaluated at compile-time + --> $DIR/normalize-tait-in-const.rs:25:79 + | +LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { + | ^^^ the destructor for this type cannot be evaluated in constant functions +LL | fun(filter_positive()); +LL | } + | - value is dropped here + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0015, E0493. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/impl-trait/type-alias-generic-param.rs b/tests/ui/impl-trait/type-alias-generic-param.rs index 1211625dac9..e4b2e412420 100644 --- a/tests/ui/impl-trait/type-alias-generic-param.rs +++ b/tests/ui/impl-trait/type-alias-generic-param.rs @@ -5,7 +5,7 @@ // run-pass #![feature(impl_trait_in_assoc_type)] -trait Meow { +trait Meow { //~ WARN trait `Meow` is never used type MeowType; fn meow(self) -> Self::MeowType; } diff --git a/tests/ui/impl-trait/type-alias-generic-param.stderr b/tests/ui/impl-trait/type-alias-generic-param.stderr new file mode 100644 index 00000000000..e4115dc1319 --- /dev/null +++ b/tests/ui/impl-trait/type-alias-generic-param.stderr @@ -0,0 +1,10 @@ +warning: trait `Meow` is never used + --> $DIR/type-alias-generic-param.rs:8:7 + | +LL | trait Meow { + | ^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/imports/empty-import-prefix-pass-2015.rs b/tests/ui/imports/empty-import-prefix-pass-2015.rs new file mode 100644 index 00000000000..a3278007c11 --- /dev/null +++ b/tests/ui/imports/empty-import-prefix-pass-2015.rs @@ -0,0 +1,10 @@ +// check-pass +// edition:2015 + +use {}; +use {{}}; + +use ::{}; +use {::{}}; + +fn main() {} diff --git a/tests/ui/imports/empty-import-prefix-pass.rs b/tests/ui/imports/empty-import-prefix-pass.rs new file mode 100644 index 00000000000..d76c0da4bd8 --- /dev/null +++ b/tests/ui/imports/empty-import-prefix-pass.rs @@ -0,0 +1,10 @@ +// check-pass +// edition:2018 + +use {}; +use {{}}; + +use ::{}; +use {::{}}; + +fn main() {} diff --git a/tests/ui/infinite/infinite-tag-type-recursion.rs b/tests/ui/infinite/infinite-tag-type-recursion.rs index 87a9e08dd38..1b5cb55b4e4 100644 --- a/tests/ui/infinite/infinite-tag-type-recursion.rs +++ b/tests/ui/infinite/infinite-tag-type-recursion.rs @@ -1,4 +1,5 @@ enum MList { Cons(isize, MList), Nil } //~^ ERROR recursive type `MList` has infinite size +//~| ERROR cycle fn main() { let a = MList::Cons(10, MList::Cons(11, MList::Nil)); } diff --git a/tests/ui/infinite/infinite-tag-type-recursion.stderr b/tests/ui/infinite/infinite-tag-type-recursion.stderr index 4ca408260b8..8745224a45e 100644 --- a/tests/ui/infinite/infinite-tag-type-recursion.stderr +++ b/tests/ui/infinite/infinite-tag-type-recursion.stderr @@ -9,6 +9,17 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum MList { Cons(isize, Box<MList>), Nil } | ++++ + -error: aborting due to 1 previous error +error[E0391]: cycle detected when computing when `MList` needs drop + --> $DIR/infinite-tag-type-recursion.rs:1:1 + | +LL | enum MList { Cons(isize, MList), Nil } + | ^^^^^^^^^^ + | + = note: ...which immediately requires computing when `MList` needs drop again + = note: cycle used when computing whether `MList` needs drop + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0072`. +Some errors have detailed explanations: E0072, E0391. +For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/inner-static-type-parameter.stderr b/tests/ui/inner-static-type-parameter.stderr index 6c7f1ffbe16..88d33b44c59 100644 --- a/tests/ui/inner-static-type-parameter.stderr +++ b/tests/ui/inner-static-type-parameter.stderr @@ -5,6 +5,8 @@ LL | fn foo<T>() { | - type parameter from outer item LL | static a: Bar<T> = Bar::What; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0392]: type parameter `T` is never used --> $DIR/inner-static-type-parameter.rs:3:10 diff --git a/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs index 06cf8c0f0f6..8ea4eac1a61 100644 --- a/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs +++ b/tests/ui/invalid/invalid_rustc_layout_scalar_valid_range.rs @@ -26,5 +26,7 @@ fn main() { let _ = A(0); let _ = B(0); let _ = C(0); - let _ = E::X; + unsafe { + let _ = E::X; + } } diff --git a/tests/ui/issues/issue-11374.rs b/tests/ui/issues/issue-11374.rs index 7519ba2826e..60ee256c65a 100644 --- a/tests/ui/issues/issue-11374.rs +++ b/tests/ui/issues/issue-11374.rs @@ -18,6 +18,7 @@ impl<'a> Container<'a> { pub fn for_stdin<'a>() -> Container<'a> { let mut r = io::stdin(); Container::wrap(&mut r as &mut dyn io::Read) + //~^ ERROR cannot return value referencing local variable } fn main() { diff --git a/tests/ui/issues/issue-11374.stderr b/tests/ui/issues/issue-11374.stderr index 275a0e6b5d7..3ae5cfc79f8 100644 --- a/tests/ui/issues/issue-11374.stderr +++ b/tests/ui/issues/issue-11374.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-11374.rs:26:15 + --> $DIR/issue-11374.rs:27:15 | LL | c.read_to(v); | ------- ^ expected `&mut [u8]`, found `Vec<_>` @@ -18,6 +18,16 @@ help: consider mutably borrowing here LL | c.read_to(&mut v); | ++++ -error: aborting due to 1 previous error +error[E0515]: cannot return value referencing local variable `r` + --> $DIR/issue-11374.rs:20:5 + | +LL | Container::wrap(&mut r as &mut dyn io::Read) + | ^^^^^^^^^^^^^^^^------^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | `r` is borrowed here + | returns a value referencing data owned by the current function + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0515. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-13497.rs b/tests/ui/issues/issue-13497.rs index 4b2795aa841..7f786a54b9f 100644 --- a/tests/ui/issues/issue-13497.rs +++ b/tests/ui/issues/issue-13497.rs @@ -3,6 +3,7 @@ fn read_lines_borrowed1() -> Vec< > { let rawLines: Vec<String> = vec!["foo ".to_string(), " bar".to_string()]; rawLines.iter().map(|l| l.trim()).collect() + //~^ ERROR: cannot return value referencing } fn main() {} diff --git a/tests/ui/issues/issue-13497.stderr b/tests/ui/issues/issue-13497.stderr index fb3de637a79..7630848f6a5 100644 --- a/tests/ui/issues/issue-13497.stderr +++ b/tests/ui/issues/issue-13497.stderr @@ -14,6 +14,16 @@ help: instead, you are more likely to want to return an owned value LL | String | ~~~~~~ -error: aborting due to 1 previous error +error[E0515]: cannot return value referencing local variable `rawLines` + --> $DIR/issue-13497.rs:5:5 + | +LL | rawLines.iter().map(|l| l.trim()).collect() + | --------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `rawLines` is borrowed here + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0515. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/issues/issue-14399.rs b/tests/ui/issues/issue-14399.rs index 7b32bf8e4cb..0c6c4d8dc6b 100644 --- a/tests/ui/issues/issue-14399.rs +++ b/tests/ui/issues/issue-14399.rs @@ -9,7 +9,7 @@ #[derive(Clone)] struct B1; -trait A { fn foo(&self) {} } +trait A { fn foo(&self) {} } //~ WARN method `foo` is never used impl A for B1 {} fn main() { diff --git a/tests/ui/issues/issue-14399.stderr b/tests/ui/issues/issue-14399.stderr new file mode 100644 index 00000000000..d226ece6fb0 --- /dev/null +++ b/tests/ui/issues/issue-14399.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/issue-14399.rs:12:14 + | +LL | trait A { fn foo(&self) {} } + | - ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-15858.rs b/tests/ui/issues/issue-15858.rs index 77941c07671..e3e3c293d7a 100644 --- a/tests/ui/issues/issue-15858.rs +++ b/tests/ui/issues/issue-15858.rs @@ -2,7 +2,7 @@ static mut DROP_RAN: bool = false; trait Bar { - fn do_something(&mut self); + fn do_something(&mut self); //~ WARN method `do_something` is never used } struct BarImpl; diff --git a/tests/ui/issues/issue-15858.stderr b/tests/ui/issues/issue-15858.stderr new file mode 100644 index 00000000000..f36bcc21bd7 --- /dev/null +++ b/tests/ui/issues/issue-15858.stderr @@ -0,0 +1,12 @@ +warning: method `do_something` is never used + --> $DIR/issue-15858.rs:5:8 + | +LL | trait Bar { + | --- method in this trait +LL | fn do_something(&mut self); + | ^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-17351.rs b/tests/ui/issues/issue-17351.rs index 62f6bcf15e3..12bb8a73b7b 100644 --- a/tests/ui/issues/issue-17351.rs +++ b/tests/ui/issues/issue-17351.rs @@ -1,7 +1,7 @@ // run-pass // pretty-expanded FIXME #23616 -trait Str { fn foo(&self) {} } +trait Str { fn foo(&self) {} } //~ WARN method `foo` is never used impl Str for str {} impl<'a, S: ?Sized> Str for &'a S where S: Str {} diff --git a/tests/ui/issues/issue-17351.stderr b/tests/ui/issues/issue-17351.stderr new file mode 100644 index 00000000000..3242d578dab --- /dev/null +++ b/tests/ui/issues/issue-17351.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/issue-17351.rs:4:16 + | +LL | trait Str { fn foo(&self) {} } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-18173.rs b/tests/ui/issues/issue-18173.rs index 11468040ee5..010efee9f8a 100644 --- a/tests/ui/issues/issue-18173.rs +++ b/tests/ui/issues/issue-18173.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass trait Foo { type T; } diff --git a/tests/ui/issues/issue-20055-box-trait.rs b/tests/ui/issues/issue-20055-box-trait.rs index 772cd9d7eda..36f597450ad 100644 --- a/tests/ui/issues/issue-20055-box-trait.rs +++ b/tests/ui/issues/issue-20055-box-trait.rs @@ -8,7 +8,7 @@ // statement surrounding the `match`. trait Boo { - fn dummy(&self) { } + fn dummy(&self) { } //~ WARN method `dummy` is never used } impl Boo for [i8; 1] { } diff --git a/tests/ui/issues/issue-20055-box-trait.stderr b/tests/ui/issues/issue-20055-box-trait.stderr new file mode 100644 index 00000000000..db9d359e225 --- /dev/null +++ b/tests/ui/issues/issue-20055-box-trait.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-20055-box-trait.rs:11:8 + | +LL | trait Boo { + | --- method in this trait +LL | fn dummy(&self) { } + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-21909.rs b/tests/ui/issues/issue-21909.rs index 7cb558d9a4f..6a6cdcfee15 100644 --- a/tests/ui/issues/issue-21909.rs +++ b/tests/ui/issues/issue-21909.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait A<X> { diff --git a/tests/ui/issues/issue-23485.rs b/tests/ui/issues/issue-23485.rs index 1dd3d9293bc..07ed0f1b00d 100644 --- a/tests/ui/issues/issue-23485.rs +++ b/tests/ui/issues/issue-23485.rs @@ -17,7 +17,7 @@ trait Iterator { fn next(&mut self) -> Option<Self::Item>; - fn clone_first(mut self) -> Option<<Self::Item as Deref>::Target> where + fn clone_first(mut self) -> Option<<Self::Item as Deref>::Target> where //~ WARN method `clone_first` is never used Self: Sized, Self::Item: Deref, <Self::Item as Deref>::Target: Clone, diff --git a/tests/ui/issues/issue-23485.stderr b/tests/ui/issues/issue-23485.stderr new file mode 100644 index 00000000000..ed2d2400d0d --- /dev/null +++ b/tests/ui/issues/issue-23485.stderr @@ -0,0 +1,13 @@ +warning: method `clone_first` is never used + --> $DIR/issue-23485.rs:20:8 + | +LL | trait Iterator { + | -------- method in this trait +... +LL | fn clone_first(mut self) -> Option<<Self::Item as Deref>::Target> where + | ^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-2848.rs b/tests/ui/issues/issue-2848.rs index e0049bf8fbb..34181acdd05 100644 --- a/tests/ui/issues/issue-2848.rs +++ b/tests/ui/issues/issue-2848.rs @@ -12,6 +12,7 @@ fn main() { use bar::foo::{alpha, charlie}; match alpha { alpha | beta => {} //~ ERROR variable `beta` is not bound in all patterns + //~^ ERROR: `beta` is named the same as one of the variants charlie => {} } } diff --git a/tests/ui/issues/issue-2848.stderr b/tests/ui/issues/issue-2848.stderr index 873f7efcd73..1cef27c3463 100644 --- a/tests/ui/issues/issue-2848.stderr +++ b/tests/ui/issues/issue-2848.stderr @@ -6,6 +6,15 @@ LL | alpha | beta => {} | | | pattern doesn't bind `beta` -error: aborting due to 1 previous error +error[E0170]: pattern binding `beta` is named the same as one of the variants of the type `bar::foo` + --> $DIR/issue-2848.rs:14:15 + | +LL | alpha | beta => {} + | ^^^^ help: to match on the variant, qualify the path: `bar::foo::beta` + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0408`. +Some errors have detailed explanations: E0170, E0408. +For more information about an error, try `rustc --explain E0170`. diff --git a/tests/ui/issues/issue-28971.rs b/tests/ui/issues/issue-28971.rs index f0a1e2d0061..8e7a2fe0ef2 100644 --- a/tests/ui/issues/issue-28971.rs +++ b/tests/ui/issues/issue-28971.rs @@ -13,4 +13,5 @@ fn main(){ fn foo<F>(f: F) where F: FnMut() { f(); + //~^ ERROR: cannot borrow } diff --git a/tests/ui/issues/issue-28971.stderr b/tests/ui/issues/issue-28971.stderr index 8fd3c7ffc30..26057cbc2d1 100644 --- a/tests/ui/issues/issue-28971.stderr +++ b/tests/ui/issues/issue-28971.stderr @@ -10,6 +10,18 @@ LL | Foo::Baz(..) => (), | variant or associated item not found in `Foo` | help: there is a variant with a similar name: `Bar` -error: aborting due to 1 previous error +error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable + --> $DIR/issue-28971.rs:15:5 + | +LL | f(); + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | fn foo<F>(mut f: F) where F: FnMut() { + | +++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0599`. +Some errors have detailed explanations: E0596, E0599. +For more information about an error, try `rustc --explain E0596`. diff --git a/tests/ui/issues/issue-2989.rs b/tests/ui/issues/issue-2989.rs index c0b67374370..a9586751407 100644 --- a/tests/ui/issues/issue-2989.rs +++ b/tests/ui/issues/issue-2989.rs @@ -1,8 +1,8 @@ // run-pass #![allow(non_camel_case_types)] -trait methods { - fn to_bytes(&self) -> Vec<u8> ; +trait methods { //~ WARN trait `methods` is never used + fn to_bytes(&self) -> Vec<u8>; } impl methods for () { diff --git a/tests/ui/issues/issue-2989.stderr b/tests/ui/issues/issue-2989.stderr new file mode 100644 index 00000000000..57181607cec --- /dev/null +++ b/tests/ui/issues/issue-2989.stderr @@ -0,0 +1,10 @@ +warning: trait `methods` is never used + --> $DIR/issue-2989.rs:4:7 + | +LL | trait methods { + | ^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-34074.rs b/tests/ui/issues/issue-34074.rs index 0600d3937c1..ca7d7b49a04 100644 --- a/tests/ui/issues/issue-34074.rs +++ b/tests/ui/issues/issue-34074.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Make sure several unnamed function parameters don't conflict with each other trait Tr { diff --git a/tests/ui/issues/issue-34503.rs b/tests/ui/issues/issue-34503.rs index 26e7358408f..d2c95d990ec 100644 --- a/tests/ui/issues/issue-34503.rs +++ b/tests/ui/issues/issue-34503.rs @@ -2,7 +2,7 @@ fn main() { struct X; trait Foo<T> { - fn foo(&self) where (T, Option<T>): Ord {} + fn foo(&self) where (T, Option<T>): Ord {} //~ WARN methods `foo` and `bar` are never used fn bar(&self, x: &Option<T>) -> bool where Option<T>: Ord { *x < *x } } diff --git a/tests/ui/issues/issue-34503.stderr b/tests/ui/issues/issue-34503.stderr new file mode 100644 index 00000000000..60d8d76a619 --- /dev/null +++ b/tests/ui/issues/issue-34503.stderr @@ -0,0 +1,14 @@ +warning: methods `foo` and `bar` are never used + --> $DIR/issue-34503.rs:5:12 + | +LL | trait Foo<T> { + | --- methods in this trait +LL | fn foo(&self) where (T, Option<T>): Ord {} + | ^^^ +LL | fn bar(&self, x: &Option<T>) -> bool + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-3563-3.rs b/tests/ui/issues/issue-3563-3.rs index bedfdab97d5..6346b82167c 100644 --- a/tests/ui/issues/issue-3563-3.rs +++ b/tests/ui/issues/issue-3563-3.rs @@ -112,7 +112,7 @@ trait Canvas { // Unlike interfaces traits support default implementations. // Got an ICE as soon as I added this method. - fn add_points(&mut self, shapes: &[Point]) { + fn add_points(&mut self, shapes: &[Point]) { //~ WARN method `add_points` is never used for pt in shapes {self.add_point(*pt)}; } } diff --git a/tests/ui/issues/issue-3563-3.stderr b/tests/ui/issues/issue-3563-3.stderr new file mode 100644 index 00000000000..bd65c1e3fd5 --- /dev/null +++ b/tests/ui/issues/issue-3563-3.stderr @@ -0,0 +1,13 @@ +warning: method `add_points` is never used + --> $DIR/issue-3563-3.rs:115:8 + | +LL | trait Canvas { + | ------ method in this trait +... +LL | fn add_points(&mut self, shapes: &[Point]) { + | ^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-3878.rs b/tests/ui/issues/issue-3878.rs deleted file mode 100644 index 6de3405af0d..00000000000 --- a/tests/ui/issues/issue-3878.rs +++ /dev/null @@ -1,9 +0,0 @@ -// run-pass -// pretty-expanded FIXME #23616 - -#![allow(path_statements)] - -pub fn main() { - let y: Box<_> = Box::new(1); - y; -} diff --git a/tests/ui/issues/issue-50571.fixed b/tests/ui/issues/issue-50571.fixed index 2f8c925b853..13c830cd0d4 100644 --- a/tests/ui/issues/issue-50571.fixed +++ b/tests/ui/issues/issue-50571.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] trait Foo { fn foo(_: [i32; 2]) {} //~^ ERROR: patterns aren't allowed in methods without bodies diff --git a/tests/ui/issues/issue-50571.rs b/tests/ui/issues/issue-50571.rs index 56f422e7d58..6fe13e3f707 100644 --- a/tests/ui/issues/issue-50571.rs +++ b/tests/ui/issues/issue-50571.rs @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] trait Foo { fn foo([a, b]: [i32; 2]) {} //~^ ERROR: patterns aren't allowed in methods without bodies diff --git a/tests/ui/issues/issue-50571.stderr b/tests/ui/issues/issue-50571.stderr index fe47790f1dd..12256ded1c0 100644 --- a/tests/ui/issues/issue-50571.stderr +++ b/tests/ui/issues/issue-50571.stderr @@ -1,5 +1,5 @@ error[E0642]: patterns aren't allowed in methods without bodies - --> $DIR/issue-50571.rs:4:12 + --> $DIR/issue-50571.rs:5:12 | LL | fn foo([a, b]: [i32; 2]) {} | ^^^^^^ diff --git a/tests/ui/issues/issue-67535.rs b/tests/ui/issues/issue-67535.rs index 24f50621310..153b95a1674 100644 --- a/tests/ui/issues/issue-67535.rs +++ b/tests/ui/issues/issue-67535.rs @@ -2,21 +2,21 @@ fn main() {} impl std::ops::AddAssign for () { //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types - fn add_assign(&self, other: ()) -> () { + fn add_assign(&self, other: ()) -> () { //~ ERROR incompatible type () } } impl std::ops::AddAssign for [(); 1] { //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types - fn add_assign(&self, other: [(); 1]) -> [(); 1] { + fn add_assign(&self, other: [(); 1]) -> [(); 1] { //~ ERROR incompatible type [()] } } impl std::ops::AddAssign for &[u8] { //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types - fn add_assign(&self, other: &[u8]) -> &[u8] { + fn add_assign(&self, other: &[u8]) -> &[u8] { //~ ERROR incompatible type self } } diff --git a/tests/ui/issues/issue-67535.stderr b/tests/ui/issues/issue-67535.stderr index 4d7a02a5096..c8bde2cb88c 100644 --- a/tests/ui/issues/issue-67535.stderr +++ b/tests/ui/issues/issue-67535.stderr @@ -34,6 +34,43 @@ LL | impl std::ops::AddAssign for &[u8] { | = note: define and implement a trait or new type instead -error: aborting due to 3 previous errors +error[E0053]: method `add_assign` has an incompatible type for trait + --> $DIR/issue-67535.rs:5:19 + | +LL | fn add_assign(&self, other: ()) -> () { + | ^^^^^ + | | + | types differ in mutability + | help: change the self-receiver type to match the trait: `&mut self` + | + = note: expected signature `fn(&mut (), ())` + found signature `fn(&(), ())` + +error[E0053]: method `add_assign` has an incompatible type for trait + --> $DIR/issue-67535.rs:12:19 + | +LL | fn add_assign(&self, other: [(); 1]) -> [(); 1] { + | ^^^^^ + | | + | types differ in mutability + | help: change the self-receiver type to match the trait: `&mut self` + | + = note: expected signature `fn(&mut _, _)` + found signature `fn(&_, _) -> [(); 1]` + +error[E0053]: method `add_assign` has an incompatible type for trait + --> $DIR/issue-67535.rs:19:19 + | +LL | fn add_assign(&self, other: &[u8]) -> &[u8] { + | ^^^^^ + | | + | types differ in mutability + | help: change the self-receiver type to match the trait: `&mut self` + | + = note: expected signature `fn(&mut &_, &_)` + found signature `fn(&&_, &_) -> &[u8]` + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0117`. +Some errors have detailed explanations: E0053, E0117. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/issues/issue-7575.rs b/tests/ui/issues/issue-7575.rs index ac69f2b1c80..0074f660c4e 100644 --- a/tests/ui/issues/issue-7575.rs +++ b/tests/ui/issues/issue-7575.rs @@ -1,6 +1,6 @@ // run-pass -trait Foo { +trait Foo { //~ WARN trait `Foo` is never used fn new() -> bool { false } fn dummy(&self) { } } diff --git a/tests/ui/issues/issue-7575.stderr b/tests/ui/issues/issue-7575.stderr new file mode 100644 index 00000000000..2f987d19c80 --- /dev/null +++ b/tests/ui/issues/issue-7575.stderr @@ -0,0 +1,10 @@ +warning: trait `Foo` is never used + --> $DIR/issue-7575.rs:3:7 + | +LL | trait Foo { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-7911.rs b/tests/ui/issues/issue-7911.rs index d4db3b0776b..114574b9009 100644 --- a/tests/ui/issues/issue-7911.rs +++ b/tests/ui/issues/issue-7911.rs @@ -4,7 +4,7 @@ #![allow(unused_variables)] // unused foobar_immut + foobar_mut trait FooBar { - fn dummy(&self) { } + fn dummy(&self) { } //~ WARN method `dummy` is never used } struct Bar(#[allow(dead_code)] i32); struct Foo { bar: Bar } diff --git a/tests/ui/issues/issue-7911.stderr b/tests/ui/issues/issue-7911.stderr new file mode 100644 index 00000000000..ead7ee191ac --- /dev/null +++ b/tests/ui/issues/issue-7911.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-7911.rs:7:8 + | +LL | trait FooBar { + | ------ method in this trait +LL | fn dummy(&self) { } + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-8248.rs b/tests/ui/issues/issue-8248.rs index 31a305c31be..94b1a5203b4 100644 --- a/tests/ui/issues/issue-8248.rs +++ b/tests/ui/issues/issue-8248.rs @@ -2,7 +2,7 @@ // pretty-expanded FIXME #23616 trait A { - fn dummy(&self) { } + fn dummy(&self) { } //~ WARN method `dummy` is never used } struct B; impl A for B {} diff --git a/tests/ui/issues/issue-8248.stderr b/tests/ui/issues/issue-8248.stderr new file mode 100644 index 00000000000..a0098bcb771 --- /dev/null +++ b/tests/ui/issues/issue-8248.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-8248.rs:5:8 + | +LL | trait A { + | - method in this trait +LL | fn dummy(&self) { } + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-9951.rs b/tests/ui/issues/issue-9951.rs index 2698a3b17c6..5db3f74efaa 100644 --- a/tests/ui/issues/issue-9951.rs +++ b/tests/ui/issues/issue-9951.rs @@ -4,7 +4,7 @@ #![allow(unused_variables)] trait Bar { - fn noop(&self); + fn noop(&self); //~ WARN method `noop` is never used } impl Bar for u8 { fn noop(&self) {} diff --git a/tests/ui/issues/issue-9951.stderr b/tests/ui/issues/issue-9951.stderr new file mode 100644 index 00000000000..475f2817914 --- /dev/null +++ b/tests/ui/issues/issue-9951.stderr @@ -0,0 +1,12 @@ +warning: method `noop` is never used + --> $DIR/issue-9951.rs:7:6 + | +LL | trait Bar { + | --- method in this trait +LL | fn noop(&self); + | ^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/kindck/kindck-impl-type-params.rs b/tests/ui/kindck/kindck-impl-type-params.rs index 72a6599c326..707c5dbaec3 100644 --- a/tests/ui/kindck/kindck-impl-type-params.rs +++ b/tests/ui/kindck/kindck-impl-type-params.rs @@ -28,6 +28,7 @@ fn g<T>(val: T) { fn foo<'a>() { let t: S<&'a isize> = S(marker::PhantomData); let a = &t as &dyn Gettable<&'a isize>; + //~^ ERROR: lifetime may not live long enough } fn foo2<'a>() { diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr index fe03ac422d2..aad020e4ec9 100644 --- a/tests/ui/kindck/kindck-impl-type-params.stderr +++ b/tests/ui/kindck/kindck-impl-type-params.stderr @@ -75,7 +75,7 @@ LL | fn g<T: std::marker::Copy>(val: T) { | +++++++++++++++++++ error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/kindck-impl-type-params.rs:35:13 + --> $DIR/kindck-impl-type-params.rs:36:13 | LL | let a = t as Box<dyn Gettable<String>>; | ^ the trait `Copy` is not implemented for `String`, which is required by `S<String>: Gettable<String>` @@ -91,7 +91,7 @@ LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {} = note: required for the cast from `Box<S<String>>` to `Box<dyn Gettable<String>>` error[E0277]: the trait bound `Foo: Copy` is not satisfied - --> $DIR/kindck-impl-type-params.rs:43:37 + --> $DIR/kindck-impl-type-params.rs:44:37 | LL | let a: Box<dyn Gettable<Foo>> = t; | ^ the trait `Copy` is not implemented for `Foo`, which is required by `S<Foo>: Gettable<Foo>` @@ -111,6 +111,15 @@ LL + #[derive(Copy)] LL | struct Foo; // does not impl Copy | -error: aborting due to 6 previous errors +error: lifetime may not live long enough + --> $DIR/kindck-impl-type-params.rs:30:13 + | +LL | fn foo<'a>() { + | -- lifetime `'a` defined here +LL | let t: S<&'a isize> = S(marker::PhantomData); +LL | let a = &t as &dyn Gettable<&'a isize>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/kindck/kindck-send-object1.rs b/tests/ui/kindck/kindck-send-object1.rs index 787d0f8f6cb..0ce3995dccc 100644 --- a/tests/ui/kindck/kindck-send-object1.rs +++ b/tests/ui/kindck/kindck-send-object1.rs @@ -12,6 +12,7 @@ fn test51<'a>() { } fn test52<'a>() { assert_send::<&'a (dyn Dummy + Sync)>(); + //~^ ERROR: lifetime may not live long enough } // ...unless they are properly bounded diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr index 771c54dce0d..39343b9993b 100644 --- a/tests/ui/kindck/kindck-send-object1.stderr +++ b/tests/ui/kindck/kindck-send-object1.stderr @@ -13,7 +13,7 @@ LL | fn assert_send<T:Send+'static>() { } | ^^^^ required by this bound in `assert_send` error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely - --> $DIR/kindck-send-object1.rs:28:19 + --> $DIR/kindck-send-object1.rs:29:19 | LL | assert_send::<Box<dyn Dummy + 'a>>(); | ^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely @@ -28,6 +28,14 @@ note: required by a bound in `assert_send` LL | fn assert_send<T:Send+'static>() { } | ^^^^ required by this bound in `assert_send` -error: aborting due to 2 previous errors +error: lifetime may not live long enough + --> $DIR/kindck-send-object1.rs:14:5 + | +LL | fn test52<'a>() { + | -- lifetime `'a` defined here +LL | assert_send::<&'a (dyn Dummy + Sync)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lifetimes/issue-17728.rs b/tests/ui/lifetimes/issue-17728.rs index 6aca159c47e..ff8783029ff 100644 --- a/tests/ui/lifetimes/issue-17728.rs +++ b/tests/ui/lifetimes/issue-17728.rs @@ -12,7 +12,7 @@ trait TraversesWorld { let direction = str_to_direction(directionStr); let maybe_room = room.direction_to_room.get(&direction); match maybe_room { - Some(entry) => Ok(entry), + Some(entry) => Ok(entry), //~ ERROR: lifetime may not live long enough _ => Err("Direction does not exist in room.") } } diff --git a/tests/ui/lifetimes/issue-17728.stderr b/tests/ui/lifetimes/issue-17728.stderr index fb1c7cf7ad3..23547f722a1 100644 --- a/tests/ui/lifetimes/issue-17728.stderr +++ b/tests/ui/lifetimes/issue-17728.stderr @@ -16,6 +16,22 @@ LL | | } = note: expected enum `RoomDirection` found enum `Option<_>` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/issue-17728.rs:15:28 + | +LL | fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +... +LL | Some(entry) => Ok(entry), + | ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | +help: consider introducing a named lifetime parameter + | +LL | fn attemptTraverse<'a>(&'a self, room: &'a Room, directionStr: &str) -> Result<&Room, &str> { + | ++++ ++ ++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs index d6c918843c7..56f89b70410 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs +++ b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.rs @@ -1,5 +1,7 @@ fn foo(x: &i32, y: &i32) -> &i32 { //~ ERROR missing lifetime if x > y { x } else { y } + //~^ ERROR: lifetime may not live long enough + //~| ERROR: lifetime may not live long enough } fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr index 62b0a8a04bf..db5b039d1c2 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -10,6 +10,22 @@ help: consider introducing a named lifetime parameter LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { | ++++ ++ ++ ++ -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/ex1b-return-no-names-if-else.rs:2:16 + | +LL | fn foo(x: &i32, y: &i32) -> &i32 { + | - let's call the lifetime of this reference `'1` +LL | if x > y { x } else { y } + | ^ returning this value requires that `'1` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/ex1b-return-no-names-if-else.rs:2:27 + | +LL | fn foo(x: &i32, y: &i32) -> &i32 { + | - let's call the lifetime of this reference `'2` +LL | if x > y { x } else { y } + | ^ returning this value requires that `'2` must outlive `'static` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/lint/dead-code/associated-type.rs b/tests/ui/lint/dead-code/associated-type.rs index 1cf66e75a95..25106a66e7e 100644 --- a/tests/ui/lint/dead-code/associated-type.rs +++ b/tests/ui/lint/dead-code/associated-type.rs @@ -15,5 +15,5 @@ impl Foo for Ex { } pub fn main() { - let _x = Ex; + let _x: &dyn Foo<Bar = <Ex as Foo>::Bar> = &Ex; } diff --git a/tests/ui/lint/dead-code/issue-41883.rs b/tests/ui/lint/dead-code/issue-41883.rs new file mode 100644 index 00000000000..e165861e893 --- /dev/null +++ b/tests/ui/lint/dead-code/issue-41883.rs @@ -0,0 +1,29 @@ +#![deny(dead_code)] + +enum Category { + Dead, //~ ERROR variant `Dead` is never constructed + Used, +} + +trait UnusedTrait { //~ ERROR trait `UnusedTrait` is never used + fn this_is_unused(&self) -> Category { + Category::Dead + } +} + +struct UnusedStruct; //~ ERROR struct `UnusedStruct` is never constructed + +impl UnusedTrait for UnusedStruct { + fn this_is_unused(&self) -> Category { + Category::Used + } +} + +mod private { + #[derive(Debug)] + struct UnusedStruct; //~ ERROR struct `UnusedStruct` is never constructed +} + +fn main() { + let _c = Category::Used; +} diff --git a/tests/ui/lint/dead-code/issue-41883.stderr b/tests/ui/lint/dead-code/issue-41883.stderr new file mode 100644 index 00000000000..cf079e4dda3 --- /dev/null +++ b/tests/ui/lint/dead-code/issue-41883.stderr @@ -0,0 +1,36 @@ +error: variant `Dead` is never constructed + --> $DIR/issue-41883.rs:4:5 + | +LL | enum Category { + | -------- variant in this enum +LL | Dead, + | ^^^^ + | +note: the lint level is defined here + --> $DIR/issue-41883.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: trait `UnusedTrait` is never used + --> $DIR/issue-41883.rs:8:7 + | +LL | trait UnusedTrait { + | ^^^^^^^^^^^ + +error: struct `UnusedStruct` is never constructed + --> $DIR/issue-41883.rs:14:8 + | +LL | struct UnusedStruct; + | ^^^^^^^^^^^^ + +error: struct `UnusedStruct` is never constructed + --> $DIR/issue-41883.rs:24:12 + | +LL | struct UnusedStruct; + | ^^^^^^^^^^^^ + | + = note: `UnusedStruct` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis + +error: aborting due to 4 previous errors + diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs index 942c5516500..2d6364aa0cd 100644 --- a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs +++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.rs @@ -17,7 +17,7 @@ struct Bar { // Issue 119267: this should not ICE. #[derive(Debug)] -struct Foo(usize, #[allow(unused)] usize); //~ WARN field `0` is never read +struct Foo(usize, #[allow(unused)] usize); //~ WARN struct `Foo` is never constructed fn main() { Bar { diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr index 06f9b229c18..b992005318f 100644 --- a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr +++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr @@ -51,19 +51,13 @@ note: the lint level is defined here LL | #[forbid(dead_code)] | ^^^^^^^^^ -warning: field `0` is never read - --> $DIR/multiple-dead-codes-in-the-same-struct.rs:20:12 +warning: struct `Foo` is never constructed + --> $DIR/multiple-dead-codes-in-the-same-struct.rs:20:8 | LL | struct Foo(usize, #[allow(unused)] usize); - | --- ^^^^^ - | | - | field in this struct + | ^^^ | = note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis -help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field - | -LL | struct Foo((), #[allow(unused)] usize); - | ~~ error: aborting due to 2 previous errors; 2 warnings emitted diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs index 631a8cb2f08..9b1edba41aa 100644 --- a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.rs @@ -10,9 +10,5 @@ pub trait SomeTrait {} pub fn function(_x: Box<SomeTrait>) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr index ecdc625015e..e9b7b248e61 100644 --- a/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr @@ -12,33 +12,5 @@ help: use `dyn` LL | pub fn function(_x: Box<dyn SomeTrait>) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/allowed-group-warn-by-default-lint.rs:10:25 - | -LL | pub fn function(_x: Box<SomeTrait>) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box<dyn SomeTrait>) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/allowed-group-warn-by-default-lint.rs:10:25 - | -LL | pub fn function(_x: Box<SomeTrait>) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box<dyn SomeTrait>) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/cap-lints-allow.rs b/tests/ui/lint/force-warn/cap-lints-allow.rs index fdba7f4105e..9609ea99431 100644 --- a/tests/ui/lint/force-warn/cap-lints-allow.rs +++ b/tests/ui/lint/force-warn/cap-lints-allow.rs @@ -8,9 +8,5 @@ pub trait SomeTrait {} pub fn function(_x: Box<SomeTrait>) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/cap-lints-allow.stderr b/tests/ui/lint/force-warn/cap-lints-allow.stderr index 5f5f2ff52b6..e569b2f9f1a 100644 --- a/tests/ui/lint/force-warn/cap-lints-allow.stderr +++ b/tests/ui/lint/force-warn/cap-lints-allow.stderr @@ -12,33 +12,5 @@ help: use `dyn` LL | pub fn function(_x: Box<dyn SomeTrait>) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/cap-lints-allow.rs:8:25 - | -LL | pub fn function(_x: Box<SomeTrait>) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box<dyn SomeTrait>) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/cap-lints-allow.rs:8:25 - | -LL | pub fn function(_x: Box<SomeTrait>) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box<dyn SomeTrait>) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs index 7ad7462ddc5..9736027452a 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.rs @@ -8,9 +8,5 @@ pub trait SomeTrait {} pub fn function(_x: Box<SomeTrait>) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr index 3a0b1201b0c..c971e4d0d4d 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr @@ -13,33 +13,5 @@ help: use `dyn` LL | pub fn function(_x: Box<dyn SomeTrait>) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-cli-warn-by-default-lint.rs:8:25 - | -LL | pub fn function(_x: Box<SomeTrait>) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box<dyn SomeTrait>) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-cli-warn-by-default-lint.rs:8:25 - | -LL | pub fn function(_x: Box<SomeTrait>) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box<dyn SomeTrait>) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs index ee5a18c3829..99cad614c25 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.rs @@ -10,9 +10,5 @@ pub trait SomeTrait {} pub fn function(_x: Box<SomeTrait>) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr index 92555eda2a7..97b8694984d 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-lint-group.stderr @@ -13,33 +13,5 @@ help: use `dyn` LL | pub fn function(_x: Box<dyn SomeTrait>) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-lint-group.rs:10:25 - | -LL | pub fn function(_x: Box<SomeTrait>) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box<dyn SomeTrait>) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-lint-group.rs:10:25 - | -LL | pub fn function(_x: Box<SomeTrait>) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box<dyn SomeTrait>) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs index 248aece6fe7..f0aacd77340 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.rs @@ -10,9 +10,5 @@ pub trait SomeTrait {} pub fn function(_x: Box<SomeTrait>) {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr index c14c7957a25..cd030cc1fcd 100644 --- a/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr +++ b/tests/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr @@ -13,33 +13,5 @@ help: use `dyn` LL | pub fn function(_x: Box<dyn SomeTrait>) {} | +++ -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-warn-by-default-lint.rs:10:25 - | -LL | pub fn function(_x: Box<SomeTrait>) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box<dyn SomeTrait>) {} - | +++ - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/lint-group-allowed-warn-by-default-lint.rs:10:25 - | -LL | pub fn function(_x: Box<SomeTrait>) {} - | ^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | pub fn function(_x: Box<dyn SomeTrait>) {} - | +++ - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/lint/future-incompat-json-test.stderr b/tests/ui/lint/future-incompat-json-test.stderr index c4ab5a00d16..18fc3f17f00 100644 --- a/tests/ui/lint/future-incompat-json-test.stderr +++ b/tests/ui/lint/future-incompat-json-test.stderr @@ -1,4 +1,4 @@ -{"$message_type":"future_incompat","future_incompat_report":[{"diagnostic":{"$message_type":"diagnostic","message":"unused variable: `x`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`-A unused-variables` implied by `-A unused`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"to override `-A unused` add `#[allow(unused_variables)]`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":"_x","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"warning: unused variable: `x` +{"$message_type":"future_incompat","future_incompat_report":[{"diagnostic":{"$message_type":"diagnostic","message":"unused variable: `x`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`-A unused-variables` implied by `-A unused`","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"to override `-A unused` add `#[allow(unused_variables)]`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"$DIR/future-incompat-json-test.rs","byte_start":338,"byte_end":339,"line_start":9,"line_end":9,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let x = 1;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":"_x","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"warning: unused variable: `x` --> $DIR/future-incompat-json-test.rs:9:9 | LL | let x = 1; diff --git a/tests/ui/lint/issue-20343.rs b/tests/ui/lint/issue-20343.rs index 000b6398442..f0f4eccc676 100644 --- a/tests/ui/lint/issue-20343.rs +++ b/tests/ui/lint/issue-20343.rs @@ -22,6 +22,8 @@ impl B { // test for unused code in generics fn baz<A: T<D>>() {} + + fn foz<A: T<D>>(a: A) { a.dummy(D); } } pub fn main() { @@ -29,4 +31,5 @@ pub fn main() { B::foo(b); B::bar(); B::baz::<()>(); + B::foz::<()>(()); } diff --git a/tests/ui/lint/lint-stability-deprecated.rs b/tests/ui/lint/lint-stability-deprecated.rs index a56a37228e5..80bc85ff557 100644 --- a/tests/ui/lint/lint-stability-deprecated.rs +++ b/tests/ui/lint/lint-stability-deprecated.rs @@ -96,13 +96,10 @@ mod cross_crate { struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable); struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); //~^ WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text type A = dyn TraitWithAssociatedTypes< TypeUnstable = u8, TypeDeprecated = u16, //~^ WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` - //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` - //~| WARN use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated` >; let _ = DeprecatedStruct { //~ WARN use of deprecated struct `lint_stability::DeprecatedStruct` diff --git a/tests/ui/lint/lint-stability-deprecated.stderr b/tests/ui/lint/lint-stability-deprecated.stderr index 609fc56a8ae..51205ff4340 100644 --- a/tests/ui/lint/lint-stability-deprecated.stderr +++ b/tests/ui/lint/lint-stability-deprecated.stderr @@ -77,241 +77,241 @@ LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedStruct`: text - --> $DIR/lint-stability-deprecated.rs:108:17 + --> $DIR/lint-stability-deprecated.rs:105:17 | LL | let _ = DeprecatedStruct { | ^^^^^^^^^^^^^^^^ warning: use of deprecated struct `lint_stability::DeprecatedUnstableStruct`: text - --> $DIR/lint-stability-deprecated.rs:111:17 + --> $DIR/lint-stability-deprecated.rs:108:17 | LL | let _ = DeprecatedUnstableStruct { | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit struct `lint_stability::DeprecatedUnitStruct`: text - --> $DIR/lint-stability-deprecated.rs:118:17 + --> $DIR/lint-stability-deprecated.rs:115:17 | LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit struct `lint_stability::DeprecatedUnstableUnitStruct`: text - --> $DIR/lint-stability-deprecated.rs:119:17 + --> $DIR/lint-stability-deprecated.rs:116:17 | LL | let _ = DeprecatedUnstableUnitStruct; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit variant `lint_stability::Enum::DeprecatedVariant`: text - --> $DIR/lint-stability-deprecated.rs:123:23 + --> $DIR/lint-stability-deprecated.rs:120:23 | LL | let _ = Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^ warning: use of deprecated unit variant `lint_stability::Enum::DeprecatedUnstableVariant`: text - --> $DIR/lint-stability-deprecated.rs:124:23 + --> $DIR/lint-stability-deprecated.rs:121:23 | LL | let _ = Enum::DeprecatedUnstableVariant; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `lint_stability::DeprecatedTupleStruct`: text - --> $DIR/lint-stability-deprecated.rs:128:17 + --> $DIR/lint-stability-deprecated.rs:125:17 | LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `lint_stability::DeprecatedUnstableTupleStruct`: text - --> $DIR/lint-stability-deprecated.rs:129:17 + --> $DIR/lint-stability-deprecated.rs:126:17 | LL | let _ = DeprecatedUnstableTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:138:25 + --> $DIR/lint-stability-deprecated.rs:135:25 | LL | macro_test_arg!(deprecated_text()); | ^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:139:25 + --> $DIR/lint-stability-deprecated.rs:136:25 | LL | macro_test_arg!(deprecated_unstable_text()); | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `lint_stability::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:140:41 + --> $DIR/lint-stability-deprecated.rs:137:41 | LL | macro_test_arg!(macro_test_arg!(deprecated_text())); | ^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:145:16 + --> $DIR/lint-stability-deprecated.rs:142:16 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:147:25 + --> $DIR/lint-stability-deprecated.rs:144:25 | LL | <Foo as Trait>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:149:16 + --> $DIR/lint-stability-deprecated.rs:146:16 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:151:25 + --> $DIR/lint-stability-deprecated.rs:148:25 | LL | <Foo as Trait>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:153:16 + --> $DIR/lint-stability-deprecated.rs:150:16 | LL | Trait::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:155:25 + --> $DIR/lint-stability-deprecated.rs:152:25 | LL | ... <Foo as Trait>::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:157:16 + --> $DIR/lint-stability-deprecated.rs:154:16 | LL | ... Trait::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:159:25 + --> $DIR/lint-stability-deprecated.rs:156:25 | LL | ... <Foo as Trait>::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:187:10 + --> $DIR/lint-stability-deprecated.rs:184:10 | LL | impl DeprecatedTrait for S {} | ^^^^^^^^^^^^^^^ warning: use of deprecated trait `lint_stability::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:189:25 + --> $DIR/lint-stability-deprecated.rs:186:25 | LL | trait LocalTrait2 : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ warning: use of deprecated function `inheritance::inherited_stability::unstable_mod::deprecated`: text - --> $DIR/lint-stability-deprecated.rs:208:23 + --> $DIR/lint-stability-deprecated.rs:205:23 | LL | unstable_mod::deprecated(); | ^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated`: text - --> $DIR/lint-stability-deprecated.rs:330:9 + --> $DIR/lint-stability-deprecated.rs:327:9 | LL | deprecated(); | ^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:335:16 + --> $DIR/lint-stability-deprecated.rs:332:16 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:337:25 + --> $DIR/lint-stability-deprecated.rs:334:25 | LL | <Foo as Trait>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:339:9 + --> $DIR/lint-stability-deprecated.rs:336:9 | LL | deprecated_text(); | ^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:344:16 + --> $DIR/lint-stability-deprecated.rs:341:16 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:346:25 + --> $DIR/lint-stability-deprecated.rs:343:25 | LL | <Foo as Trait>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated struct `this_crate::DeprecatedStruct`: text - --> $DIR/lint-stability-deprecated.rs:384:17 + --> $DIR/lint-stability-deprecated.rs:381:17 | LL | let _ = DeprecatedStruct { | ^^^^^^^^^^^^^^^^ warning: use of deprecated unit struct `this_crate::DeprecatedUnitStruct`: text - --> $DIR/lint-stability-deprecated.rs:391:17 + --> $DIR/lint-stability-deprecated.rs:388:17 | LL | let _ = DeprecatedUnitStruct; | ^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated unit variant `this_crate::Enum::DeprecatedVariant`: text - --> $DIR/lint-stability-deprecated.rs:395:23 + --> $DIR/lint-stability-deprecated.rs:392:23 | LL | let _ = Enum::DeprecatedVariant; | ^^^^^^^^^^^^^^^^^ warning: use of deprecated tuple struct `this_crate::DeprecatedTupleStruct`: text - --> $DIR/lint-stability-deprecated.rs:399:17 + --> $DIR/lint-stability-deprecated.rs:396:17 | LL | let _ = DeprecatedTupleStruct (1); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:406:16 + --> $DIR/lint-stability-deprecated.rs:403:16 | LL | Trait::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:408:25 + --> $DIR/lint-stability-deprecated.rs:405:25 | LL | <Foo as Trait>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:410:16 + --> $DIR/lint-stability-deprecated.rs:407:16 | LL | Trait::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:412:25 + --> $DIR/lint-stability-deprecated.rs:409:25 | LL | <Foo as Trait>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::test_fn_body::fn_in_body`: text - --> $DIR/lint-stability-deprecated.rs:439:9 + --> $DIR/lint-stability-deprecated.rs:436:9 | LL | fn_in_body(); | ^^^^^^^^^^ warning: use of deprecated trait `this_crate::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:459:10 + --> $DIR/lint-stability-deprecated.rs:456:10 | LL | impl DeprecatedTrait for S { } | ^^^^^^^^^^^^^^^ warning: use of deprecated trait `this_crate::DeprecatedTrait`: text - --> $DIR/lint-stability-deprecated.rs:461:24 + --> $DIR/lint-stability-deprecated.rs:458:24 | LL | trait LocalTrait : DeprecatedTrait { } | ^^^^^^^^^^^^^^^ warning: use of deprecated function `this_crate::MethodTester::test_method_body::fn_in_body`: text - --> $DIR/lint-stability-deprecated.rs:447:13 + --> $DIR/lint-stability-deprecated.rs:444:13 | LL | fn_in_body(); | ^^^^^^^^^^ @@ -323,7 +323,7 @@ LL | struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:102:13 + --> $DIR/lint-stability-deprecated.rs:101:13 | LL | TypeDeprecated = u16, | ^^^^^^^^^^^^^^^^^^^^ @@ -449,214 +449,190 @@ LL | ... <Foo>::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated field `lint_stability::DeprecatedStruct::i`: text - --> $DIR/lint-stability-deprecated.rs:109:13 + --> $DIR/lint-stability-deprecated.rs:106:13 | LL | i: 0 | ^^^^ warning: use of deprecated field `lint_stability::DeprecatedUnstableStruct::i`: text - --> $DIR/lint-stability-deprecated.rs:113:13 + --> $DIR/lint-stability-deprecated.rs:110:13 | LL | i: 0 | ^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:144:13 + --> $DIR/lint-stability-deprecated.rs:141:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:146:16 + --> $DIR/lint-stability-deprecated.rs:143:16 | LL | <Foo>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:148:13 + --> $DIR/lint-stability-deprecated.rs:145:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:150:16 + --> $DIR/lint-stability-deprecated.rs:147:16 | LL | <Foo>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:152:13 + --> $DIR/lint-stability-deprecated.rs:149:13 | LL | foo.trait_deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:154:16 + --> $DIR/lint-stability-deprecated.rs:151:16 | LL | <Foo>::trait_deprecated_unstable(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:156:13 + --> $DIR/lint-stability-deprecated.rs:153:13 | LL | ... foo.trait_deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:158:16 + --> $DIR/lint-stability-deprecated.rs:155:16 | LL | ... <Foo>::trait_deprecated_unstable_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:175:13 + --> $DIR/lint-stability-deprecated.rs:172:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:176:13 + --> $DIR/lint-stability-deprecated.rs:173:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable`: text - --> $DIR/lint-stability-deprecated.rs:177:13 + --> $DIR/lint-stability-deprecated.rs:174:13 | LL | foo.trait_deprecated_unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `lint_stability::Trait::trait_deprecated_unstable_text`: text - --> $DIR/lint-stability-deprecated.rs:178:13 + --> $DIR/lint-stability-deprecated.rs:175:13 | LL | ... foo.trait_deprecated_unstable_text(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:331:13 + --> $DIR/lint-stability-deprecated.rs:328:13 | LL | foo.method_deprecated(); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:332:14 + --> $DIR/lint-stability-deprecated.rs:329:14 | LL | Foo::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:333:16 + --> $DIR/lint-stability-deprecated.rs:330:16 | LL | <Foo>::method_deprecated(&foo); | ^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:334:13 + --> $DIR/lint-stability-deprecated.rs:331:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:336:16 + --> $DIR/lint-stability-deprecated.rs:333:16 | LL | <Foo>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:340:13 + --> $DIR/lint-stability-deprecated.rs:337:13 | LL | foo.method_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:341:14 + --> $DIR/lint-stability-deprecated.rs:338:14 | LL | Foo::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::MethodTester::method_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:342:16 + --> $DIR/lint-stability-deprecated.rs:339:16 | LL | <Foo>::method_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:343:13 + --> $DIR/lint-stability-deprecated.rs:340:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:345:16 + --> $DIR/lint-stability-deprecated.rs:342:16 | LL | <Foo>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated field `this_crate::DeprecatedStruct::i`: text - --> $DIR/lint-stability-deprecated.rs:386:13 + --> $DIR/lint-stability-deprecated.rs:383:13 | LL | i: 0 | ^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:405:13 + --> $DIR/lint-stability-deprecated.rs:402:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:407:16 + --> $DIR/lint-stability-deprecated.rs:404:16 | LL | <Foo>::trait_deprecated(&foo); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:409:13 + --> $DIR/lint-stability-deprecated.rs:406:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:411:16 + --> $DIR/lint-stability-deprecated.rs:408:16 | LL | <Foo>::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated`: text - --> $DIR/lint-stability-deprecated.rs:428:13 + --> $DIR/lint-stability-deprecated.rs:425:13 | LL | foo.trait_deprecated(); | ^^^^^^^^^^^^^^^^ warning: use of deprecated method `this_crate::Trait::trait_deprecated_text`: text - --> $DIR/lint-stability-deprecated.rs:429:13 + --> $DIR/lint-stability-deprecated.rs:426:13 | LL | foo.trait_deprecated_text(); | ^^^^^^^^^^^^^^^^^^^^^ -warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:97:48 - | -LL | struct S2<T: TraitWithAssociatedTypes>(T::TypeDeprecated); - | ^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:102:13 - | -LL | TypeDeprecated = u16, - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: use of deprecated associated type `lint_stability::TraitWithAssociatedTypes::TypeDeprecated`: text - --> $DIR/lint-stability-deprecated.rs:102:13 - | -LL | TypeDeprecated = u16, - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 108 warnings emitted +warning: 105 warnings emitted diff --git a/tests/ui/liveness/liveness-forgot-ret.rs b/tests/ui/liveness/liveness-forgot-ret.rs index b8c2bc73438..3ba2f2d276e 100644 --- a/tests/ui/liveness/liveness-forgot-ret.rs +++ b/tests/ui/liveness/liveness-forgot-ret.rs @@ -1,4 +1,5 @@ fn god_exists(a: isize) -> bool { return god_exists(a); } +//~^ WARN function cannot return without recursing fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } //~^ ERROR mismatched types diff --git a/tests/ui/liveness/liveness-forgot-ret.stderr b/tests/ui/liveness/liveness-forgot-ret.stderr index a5adadca26e..f72a30fc4e9 100644 --- a/tests/ui/liveness/liveness-forgot-ret.stderr +++ b/tests/ui/liveness/liveness-forgot-ret.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/liveness-forgot-ret.rs:3:19 + --> $DIR/liveness-forgot-ret.rs:4:19 | LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; } | - ^^^^^ expected `isize`, found `()` @@ -11,6 +11,17 @@ help: consider returning the local binding `a` LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; a } | + -error: aborting due to 1 previous error +warning: function cannot return without recursing + --> $DIR/liveness-forgot-ret.rs:1:1 + | +LL | fn god_exists(a: isize) -> bool { return god_exists(a); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------- recursive call site + | | + | cannot return without recursing + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/loops/loop-else-break-with-value.rs b/tests/ui/loops/loop-else-break-with-value.rs index 670d8a145c0..7ccf71b2edf 100644 --- a/tests/ui/loops/loop-else-break-with-value.rs +++ b/tests/ui/loops/loop-else-break-with-value.rs @@ -1,6 +1,11 @@ fn main() { let Some(1) = loop { //~^ NOTE `else` is attached to this loop + //~| ERROR refutable pattern in local binding + //~| NOTE not covered + //~| NOTE for more information + //~| NOTE matched value is of type + //~| NOTE require an "irrefutable pattern" break Some(1) } else { //~^ ERROR `loop...else` loops are not supported diff --git a/tests/ui/loops/loop-else-break-with-value.stderr b/tests/ui/loops/loop-else-break-with-value.stderr index c933e0d0cd8..13d4c5faf73 100644 --- a/tests/ui/loops/loop-else-break-with-value.stderr +++ b/tests/ui/loops/loop-else-break-with-value.stderr @@ -1,5 +1,5 @@ error: `loop...else` loops are not supported - --> $DIR/loop-else-break-with-value.rs:5:7 + --> $DIR/loop-else-break-with-value.rs:10:7 | LL | let Some(1) = loop { | ---- `else` is attached to this loop @@ -14,5 +14,24 @@ LL | | }; | = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run -error: aborting due to 1 previous error +error[E0005]: refutable pattern in local binding + --> $DIR/loop-else-break-with-value.rs:2:9 + | +LL | let Some(1) = loop { + | ^^^^^^^ pattern `None` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Option<i32>` +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL ~ if let Some(1) = loop { +LL | + ... +LL | return; +LL ~ } { todo!() }; + | + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/auxiliary/hello_macro.rs b/tests/ui/macros/auxiliary/hello_macro.rs index a05b8d54dc1..a05b8d54dc1 100644 --- a/tests/ui/auxiliary/hello_macro.rs +++ b/tests/ui/macros/auxiliary/hello_macro.rs diff --git a/tests/ui/macros/issue-22463.rs b/tests/ui/macros/issue-22463.rs index fdf5a2fca72..8f7b27cb9a0 100644 --- a/tests/ui/macros/issue-22463.rs +++ b/tests/ui/macros/issue-22463.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass macro_rules! items { () => { type A = (); diff --git a/tests/ui/issues/issue-46438.rs b/tests/ui/macros/issue-46438.rs index d78b958463f..d78b958463f 100644 --- a/tests/ui/issues/issue-46438.rs +++ b/tests/ui/macros/issue-46438.rs diff --git a/tests/ui/issues/issue-46438.stderr b/tests/ui/macros/issue-46438.stderr index aff2d77a0c8..aff2d77a0c8 100644 --- a/tests/ui/issues/issue-46438.stderr +++ b/tests/ui/macros/issue-46438.stderr diff --git a/tests/ui/macro-quote-test.rs b/tests/ui/macros/macro-quote-test.rs index 2ba61acadcb..2ba61acadcb 100644 --- a/tests/ui/macro-quote-test.rs +++ b/tests/ui/macros/macro-quote-test.rs diff --git a/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs b/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs index 5376fc89d4f..d91a8055aa1 100644 --- a/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs +++ b/tests/ui/marker_trait_attr/override-item-on-marker-trait.rs @@ -3,7 +3,9 @@ #[marker] trait Marker { const N: usize = 0; + //~^ ERROR marker traits cannot have associated items fn do_something() {} + //~^ ERROR marker traits cannot have associated items } struct OverrideConst; diff --git a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr index 1d30c6d5667..92a54cff7f5 100644 --- a/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr +++ b/tests/ui/marker_trait_attr/override-item-on-marker-trait.stderr @@ -1,15 +1,28 @@ error[E0715]: impls for marker traits cannot contain items - --> $DIR/override-item-on-marker-trait.rs:10:1 + --> $DIR/override-item-on-marker-trait.rs:12:1 | LL | impl Marker for OverrideConst { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0715]: impls for marker traits cannot contain items - --> $DIR/override-item-on-marker-trait.rs:16:1 + --> $DIR/override-item-on-marker-trait.rs:18:1 | LL | impl Marker for OverrideFn { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error[E0714]: marker traits cannot have associated items + --> $DIR/override-item-on-marker-trait.rs:5:5 + | +LL | const N: usize = 0; + | ^^^^^^^^^^^^^^ + +error[E0714]: marker traits cannot have associated items + --> $DIR/override-item-on-marker-trait.rs:7:5 + | +LL | fn do_something() {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0715`. +Some errors have detailed explanations: E0714, E0715. +For more information about an error, try `rustc --explain E0714`. diff --git a/tests/ui/methods/assign-to-method.rs b/tests/ui/methods/assign-to-method.rs index 71e40759c84..58dcca77e62 100644 --- a/tests/ui/methods/assign-to-method.rs +++ b/tests/ui/methods/assign-to-method.rs @@ -6,7 +6,7 @@ struct Cat { } impl Cat { - pub fn speak(&self) { self.meows += 1; } + pub fn speak(&mut self) { self.meows += 1; } } fn cat(in_x : usize, in_y : isize) -> Cat { diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr index f4310857454..6df49e432a1 100644 --- a/tests/ui/methods/method-call-err-msg.stderr +++ b/tests/ui/methods/method-call-err-msg.stderr @@ -63,8 +63,9 @@ LL | | .take() note: the trait `Iterator` must be implemented --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `take`, perhaps you need to implement it: - candidate #1: `Iterator` + = note: the following traits define an item `take`, perhaps you need to implement one of them: + candidate #1: `std::io::Read` + candidate #2: `Iterator` error[E0061]: this method takes 3 arguments but 0 arguments were supplied --> $DIR/method-call-err-msg.rs:21:7 diff --git a/tests/ui/methods/method-lookup-order.rs b/tests/ui/methods/method-lookup-order.rs index 986fe103cdc..5a46cf35dec 100644 --- a/tests/ui/methods/method-lookup-order.rs +++ b/tests/ui/methods/method-lookup-order.rs @@ -1,6 +1,7 @@ // ignore-tidy-linelength // run-pass +#![allow(dead_code)] // There are five cfg's below. I explored the set of all non-empty combinations // of the below five cfg's, which is 2^5 - 1 = 31 combinations. diff --git a/tests/ui/methods/method-recursive-blanket-impl.rs b/tests/ui/methods/method-recursive-blanket-impl.rs index a2db75b4e85..e7e83cbec77 100644 --- a/tests/ui/methods/method-recursive-blanket-impl.rs +++ b/tests/ui/methods/method-recursive-blanket-impl.rs @@ -11,7 +11,7 @@ use std::marker::Sized; // Note: this must be generic for the problem to show up -trait Foo<A> { +trait Foo<A> { //~ WARN trait `Foo` is never used fn foo(&self, a: A); } diff --git a/tests/ui/methods/method-recursive-blanket-impl.stderr b/tests/ui/methods/method-recursive-blanket-impl.stderr new file mode 100644 index 00000000000..9797a8f6c83 --- /dev/null +++ b/tests/ui/methods/method-recursive-blanket-impl.stderr @@ -0,0 +1,10 @@ +warning: trait `Foo` is never used + --> $DIR/method-recursive-blanket-impl.rs:14:7 + | +LL | trait Foo<A> { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/methods/method-two-trait-defer-resolution-2.rs b/tests/ui/methods/method-two-trait-defer-resolution-2.rs index fc5766da971..d6076126732 100644 --- a/tests/ui/methods/method-two-trait-defer-resolution-2.rs +++ b/tests/ui/methods/method-two-trait-defer-resolution-2.rs @@ -14,7 +14,7 @@ trait Foo { fn foo(&self) -> isize; } -trait MyCopy { fn foo(&self) { } } +trait MyCopy { fn foo(&self) { } } //~ WARN method `foo` is never used impl MyCopy for i32 { } impl<T:MyCopy> Foo for Vec<T> { diff --git a/tests/ui/methods/method-two-trait-defer-resolution-2.stderr b/tests/ui/methods/method-two-trait-defer-resolution-2.stderr new file mode 100644 index 00000000000..4501ea5d243 --- /dev/null +++ b/tests/ui/methods/method-two-trait-defer-resolution-2.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/method-two-trait-defer-resolution-2.rs:17:19 + | +LL | trait MyCopy { fn foo(&self) { } } + | ------ ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs index d820d2ad08a..2fd6c3bfab8 100644 --- a/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs +++ b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.rs @@ -4,7 +4,7 @@ // pretty-expanded FIXME #23616 -trait A { +trait A { //~ WARN trait `A` is never used fn foo(self); } diff --git a/tests/ui/methods/method-two-traits-distinguished-via-where-clause.stderr b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.stderr new file mode 100644 index 00000000000..0a60c6242bb --- /dev/null +++ b/tests/ui/methods/method-two-traits-distinguished-via-where-clause.stderr @@ -0,0 +1,10 @@ +warning: trait `A` is never used + --> $DIR/method-two-traits-distinguished-via-where-clause.rs:7:7 + | +LL | trait A { + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/mir/drop-elaboration-after-borrowck-error.rs b/tests/ui/mir/drop-elaboration-after-borrowck-error.rs index 624b464ecef..cbca3eebf19 100644 --- a/tests/ui/mir/drop-elaboration-after-borrowck-error.rs +++ b/tests/ui/mir/drop-elaboration-after-borrowck-error.rs @@ -6,7 +6,6 @@ static A: () = { //~^ ERROR destructor of a[0] = String::new(); //~^ ERROR destructor of - //~| ERROR binding `a` isn't initialized }; struct B<T>([T; 1]); @@ -17,7 +16,6 @@ impl<T> B<T> { //~^ ERROR destructor of self.0[0] = other; //~^ ERROR destructor of - //~| ERROR use of moved value self } } diff --git a/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr b/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr index d961061729d..22d05fa4dda 100644 --- a/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr +++ b/tests/ui/mir/drop-elaboration-after-borrowck-error.stderr @@ -16,22 +16,8 @@ LL | let a: [String; 1]; LL | }; | - value is dropped here -error[E0381]: used binding `a` isn't initialized - --> $DIR/drop-elaboration-after-borrowck-error.rs:7:5 - | -LL | let a: [String; 1]; - | - binding declared here but left uninitialized -LL | -LL | a[0] = String::new(); - | ^^^^ `a` used here but it isn't initialized - | -help: consider assigning a value - | -LL | let a: [String; 1] = todo!(); - | +++++++++ - error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 + --> $DIR/drop-elaboration-after-borrowck-error.rs:17:9 | LL | self.0[0] = other; | ^^^^^^^^^ @@ -40,7 +26,7 @@ LL | self.0[0] = other; | value is dropped here error[E0493]: destructor of `B<T>` cannot be evaluated at compile-time - --> $DIR/drop-elaboration-after-borrowck-error.rs:16:13 + --> $DIR/drop-elaboration-after-borrowck-error.rs:15:13 | LL | let _this = self; | ^^^^^ the destructor for this type cannot be evaluated in constant functions @@ -48,18 +34,6 @@ LL | let _this = self; LL | } | - value is dropped here -error[E0382]: use of moved value: `self.0` - --> $DIR/drop-elaboration-after-borrowck-error.rs:18:9 - | -LL | pub const fn f(mut self, other: T) -> Self { - | -------- move occurs because `self` has type `B<T>`, which does not implement the `Copy` trait -LL | let _this = self; - | ---- value moved here -LL | -LL | self.0[0] = other; - | ^^^^^^^^^ value used here after move - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0381, E0382, E0493. -For more information about an error, try `rustc --explain E0381`. +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/mir/mir_raw_fat_ptr.rs b/tests/ui/mir/mir_raw_fat_ptr.rs index 8e5a2043dc6..e141aa03aa9 100644 --- a/tests/ui/mir/mir_raw_fat_ptr.rs +++ b/tests/ui/mir/mir_raw_fat_ptr.rs @@ -98,7 +98,7 @@ fn assert_inorder<T: Copy>(a: &[T], } } -trait Foo { fn foo(&self) -> usize; } +trait Foo { fn foo(&self) -> usize; } //~ WARN method `foo` is never used impl<T> Foo for T { fn foo(&self) -> usize { mem::size_of::<T>() diff --git a/tests/ui/mir/mir_raw_fat_ptr.stderr b/tests/ui/mir/mir_raw_fat_ptr.stderr new file mode 100644 index 00000000000..a9e9dd66ebd --- /dev/null +++ b/tests/ui/mir/mir_raw_fat_ptr.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/mir_raw_fat_ptr.rs:101:16 + | +LL | trait Foo { fn foo(&self) -> usize; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/mir/validate/error-body.rs b/tests/ui/mir/validate/error-body.rs new file mode 100644 index 00000000000..5b2fbb0b046 --- /dev/null +++ b/tests/ui/mir/validate/error-body.rs @@ -0,0 +1,9 @@ +// compile-flags: -Zvalidate-mir + +fn _test() { + let x = || 45; + missing(); + //~^ ERROR cannot find function `missing` in this scope +} + +fn main() {} diff --git a/tests/ui/mir/validate/error-body.stderr b/tests/ui/mir/validate/error-body.stderr new file mode 100644 index 00000000000..1dfeaf0b7e2 --- /dev/null +++ b/tests/ui/mir/validate/error-body.stderr @@ -0,0 +1,9 @@ +error[E0425]: cannot find function `missing` in this scope + --> $DIR/error-body.rs:5:5 + | +LL | missing(); + | ^^^^^^^ not found in this scope + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch.rs index 98abb0ba979..e73a33dfded 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -8,4 +8,7 @@ fn main() { fn baz<F: Fn(*mut &u32)>(_: F) {} fn _test<'a>(f: fn(*mut &'a u32)) { baz(f); + //~^ ERROR: mismatched types + //~| ERROR: borrowed data escapes + //~| ERROR: not general enough } diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr index e9808b86991..e63d3f6a075 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -41,6 +41,52 @@ LL | a.iter().map(|_: (u16, u16)| 45); note: required by a bound in `map` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error: aborting due to 3 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | fn _test<'a>(f: fn(*mut &'a u32)) { + | -- - `f` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | baz(f); + | ^^^^^^ + | | + | `f` escapes the function body here + | argument requires that `'a` must outlive `'static` + | + = note: requirement occurs because of a mutable pointer to `&u32` + = note: mutable pointers are invariant over their type parameter + = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz<F: Fn(*mut &u32)>(_: F) {} + | ^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^^^^ one type is more general than the other + | + = note: expected trait `for<'a> Fn(*mut &'a u32)` + found trait `Fn(*mut &u32)` +note: the lifetime requirement is introduced here + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz<F: Fn(*mut &u32)>(_: F) {} + | ^^^^^^^^^^^^^ + +error: implementation of `FnOnce` is not general enough + --> $DIR/closure-arg-type-mismatch.rs:10:5 + | +LL | baz(f); + | ^^^^^^ implementation of `FnOnce` is not general enough + | + = note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0631`. +Some errors have detailed explanations: E0308, E0521, E0631. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/moves/issue-22536-copy-mustnt-zero.rs b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs index 017f36484c1..b3fc1a56f88 100644 --- a/tests/ui/moves/issue-22536-copy-mustnt-zero.rs +++ b/tests/ui/moves/issue-22536-copy-mustnt-zero.rs @@ -5,7 +5,7 @@ trait Resources { type Buffer: Copy; - fn foo(&self) {} + fn foo(&self) {} //~ WARN method `foo` is never used } struct BufferHandle<R: Resources> { diff --git a/tests/ui/moves/issue-22536-copy-mustnt-zero.stderr b/tests/ui/moves/issue-22536-copy-mustnt-zero.stderr new file mode 100644 index 00000000000..b1fcdfa44c3 --- /dev/null +++ b/tests/ui/moves/issue-22536-copy-mustnt-zero.stderr @@ -0,0 +1,13 @@ +warning: method `foo` is never used + --> $DIR/issue-22536-copy-mustnt-zero.rs:8:8 + | +LL | trait Resources { + | --------- method in this trait +LL | type Buffer: Copy; +LL | fn foo(&self) {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/nll/continue-after-missing-main.rs b/tests/ui/nll/continue-after-missing-main.rs index 778639158d7..59683648789 100644 --- a/tests/ui/nll/continue-after-missing-main.rs +++ b/tests/ui/nll/continue-after-missing-main.rs @@ -26,4 +26,6 @@ fn create_and_solve_subproblems<'data_provider, 'original_data, MP>( tableau: Tableau<'data_provider, AdaptedMatrixProvider<'original_data, MP>>, ) { let _: AdaptedMatrixProvider<'original_data, MP> = tableau.provider().clone_with_extra_bound(); + //~^ ERROR: lifetime may not live long enough + //~| ERROR: `tableau` does not live long enough } //~ ERROR `main` function not found in crate diff --git a/tests/ui/nll/continue-after-missing-main.stderr b/tests/ui/nll/continue-after-missing-main.stderr index 960503e8fd5..5178d1b7ee2 100644 --- a/tests/ui/nll/continue-after-missing-main.stderr +++ b/tests/ui/nll/continue-after-missing-main.stderr @@ -1,9 +1,39 @@ error[E0601]: `main` function not found in crate `continue_after_missing_main` - --> $DIR/continue-after-missing-main.rs:29:2 + --> $DIR/continue-after-missing-main.rs:31:2 | LL | } | ^ consider adding a `main` function to `$DIR/continue-after-missing-main.rs` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/continue-after-missing-main.rs:28:12 + | +LL | fn create_and_solve_subproblems<'data_provider, 'original_data, MP>( + | -------------- -------------- lifetime `'original_data` defined here + | | + | lifetime `'data_provider` defined here +... +LL | let _: AdaptedMatrixProvider<'original_data, MP> = tableau.provider().clone_with_extra_bound(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'data_provider` must outlive `'original_data` + | + = help: consider adding the following bound: `'data_provider: 'original_data` + +error[E0597]: `tableau` does not live long enough + --> $DIR/continue-after-missing-main.rs:28:56 + | +LL | fn create_and_solve_subproblems<'data_provider, 'original_data, MP>( + | -------------- lifetime `'original_data` defined here +LL | tableau: Tableau<'data_provider, AdaptedMatrixProvider<'original_data, MP>>, + | ------- binding `tableau` declared here +LL | ) { +LL | let _: AdaptedMatrixProvider<'original_data, MP> = tableau.provider().clone_with_extra_bound(); + | ----------------------------------------- ^^^^^^^ borrowed value does not live long enough + | | + | type annotation requires that `tableau` is borrowed for `'original_data` +... +LL | } + | - `tableau` dropped here while still borrowed + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0601`. +Some errors have detailed explanations: E0597, E0601. +For more information about an error, try `rustc --explain E0597`. diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed index 45c7e07a264..52046a8ab69 100644 --- a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed +++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait TraitWithAType { type Item: ?Sized; } diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs index c3e958f4983..96620c0abda 100644 --- a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs +++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait TraitWithAType { type Item; } diff --git a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr index cd2aa9fdbe3..9bb770ce431 100644 --- a/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr +++ b/tests/ui/object-safety/assoc_type_bounds_implicit_sized.stderr @@ -1,12 +1,12 @@ error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/assoc_type_bounds_implicit_sized.rs:8:17 + --> $DIR/assoc_type_bounds_implicit_sized.rs:9:17 | LL | type Item = dyn Trait; | ^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `(dyn Trait + 'static)` note: required by a bound in `TraitWithAType::Item` - --> $DIR/assoc_type_bounds_implicit_sized.rs:3:5 + --> $DIR/assoc_type_bounds_implicit_sized.rs:4:5 | LL | type Item; | ^^^^^^^^^^ required by this bound in `TraitWithAType::Item` diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs index 800624e3124..34daa81e48e 100644 --- a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs +++ b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.rs @@ -8,8 +8,6 @@ trait Foo { fn foo(_: &dyn Foo<Bar = ()>) {} //~^ WARN: unnecessary associated type bound for not object safe associated type -//~| WARN: unnecessary associated type bound for not object safe associated type -//~| WARN: unnecessary associated type bound for not object safe associated type #[allow(unused_associated_type_bounds)] fn bar(_: &dyn Foo<Bar = ()>) {} diff --git a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr index 659679e4440..f2bc8bd8400 100644 --- a/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr +++ b/tests/ui/object-safety/assoc_type_bounds_sized_unnecessary.stderr @@ -7,23 +7,5 @@ LL | fn foo(_: &dyn Foo<Bar = ()>) {} = note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. = note: `#[warn(unused_associated_type_bounds)]` on by default -warning: unnecessary associated type bound for not object safe associated type - --> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20 - | -LL | fn foo(_: &dyn Foo<Bar = ()>) {} - | ^^^^^^^^ help: remove this bound - | - = note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: unnecessary associated type bound for not object safe associated type - --> $DIR/assoc_type_bounds_sized_unnecessary.rs:9:20 - | -LL | fn foo(_: &dyn Foo<Bar = ()>) {} - | ^^^^^^^^ help: remove this bound - | - = note: this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`. - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 3 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/or-patterns/missing-bindings.rs b/tests/ui/or-patterns/missing-bindings.rs index 7c26012c0e9..20844c17ec1 100644 --- a/tests/ui/or-patterns/missing-bindings.rs +++ b/tests/ui/or-patterns/missing-bindings.rs @@ -17,8 +17,10 @@ fn check_handling_of_paths() { use bar::foo::{alpha, charlie}; let (alpha | beta | charlie) = alpha; //~ ERROR variable `beta` is not bound in all patterns - match Some(alpha) { + //~^ ERROR: `beta` is named the same as one of the variants + match Some(alpha) { //~ ERROR `None` not covered Some(alpha | beta) => {} //~ ERROR variable `beta` is not bound in all patterns + //~^ ERROR: `beta` is named the same as one of the variants } } diff --git a/tests/ui/or-patterns/missing-bindings.stderr b/tests/ui/or-patterns/missing-bindings.stderr index 7f182a85787..677b40a7f0d 100644 --- a/tests/ui/or-patterns/missing-bindings.stderr +++ b/tests/ui/or-patterns/missing-bindings.stderr @@ -8,7 +8,7 @@ LL | let (alpha | beta | charlie) = alpha; | pattern doesn't bind `beta` error[E0408]: variable `beta` is not bound in all patterns - --> $DIR/missing-bindings.rs:21:14 + --> $DIR/missing-bindings.rs:22:14 | LL | Some(alpha | beta) => {} | ^^^^^ ---- variable not in all patterns @@ -16,7 +16,7 @@ LL | Some(alpha | beta) => {} | pattern doesn't bind `beta` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:33:20 + --> $DIR/missing-bindings.rs:35:20 | LL | let (A(a, _) | _) = X; | - ^ pattern doesn't bind `a` @@ -24,7 +24,7 @@ LL | let (A(a, _) | _) = X; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:34:10 + --> $DIR/missing-bindings.rs:36:10 | LL | let (_ | B(a)) = X; | ^ - variable not in all patterns @@ -32,7 +32,7 @@ LL | let (_ | B(a)) = X; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:35:10 + --> $DIR/missing-bindings.rs:37:10 | LL | let (A(..) | B(a)) = X; | ^^^^^ - variable not in all patterns @@ -40,7 +40,7 @@ LL | let (A(..) | B(a)) = X; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:36:20 + --> $DIR/missing-bindings.rs:38:20 | LL | let (A(a, _) | B(_)) = X; | - ^^^^ pattern doesn't bind `a` @@ -48,7 +48,7 @@ LL | let (A(a, _) | B(_)) = X; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:37:20 + --> $DIR/missing-bindings.rs:39:20 | LL | let (A(_, a) | B(_)) = X; | - ^^^^ pattern doesn't bind `a` @@ -56,7 +56,7 @@ LL | let (A(_, a) | B(_)) = X; | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:38:20 + --> $DIR/missing-bindings.rs:40:20 | LL | let (A(a, b) | B(a)) = X; | - ^^^^ pattern doesn't bind `b` @@ -64,7 +64,7 @@ LL | let (A(a, b) | B(a)) = X; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:42:10 + --> $DIR/missing-bindings.rs:44:10 | LL | let (A(A(..) | B(_), _) | B(a)) = Y; | ^^^^^^^^^^^^^^^^^^ - variable not in all patterns @@ -72,7 +72,7 @@ LL | let (A(A(..) | B(_), _) | B(a)) = Y; | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:43:12 + --> $DIR/missing-bindings.rs:45:12 | LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; | ^^^^^ - variable not in all patterns @@ -80,7 +80,7 @@ LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; | pattern doesn't bind `a` error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:12 + --> $DIR/missing-bindings.rs:47:12 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | ^^^^^^^ - variable not in all patterns @@ -88,7 +88,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | pattern doesn't bind `c` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:22 + --> $DIR/missing-bindings.rs:47:22 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `a` @@ -96,7 +96,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:22 + --> $DIR/missing-bindings.rs:47:22 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `b` @@ -104,7 +104,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `e` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:10 + --> $DIR/missing-bindings.rs:47:10 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns @@ -112,7 +112,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | pattern doesn't bind `e` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 + --> $DIR/missing-bindings.rs:47:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `a` @@ -120,7 +120,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 + --> $DIR/missing-bindings.rs:47:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `b` @@ -128,7 +128,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 + --> $DIR/missing-bindings.rs:47:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `c` @@ -136,7 +136,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `d` is not bound in all patterns - --> $DIR/missing-bindings.rs:45:33 + --> $DIR/missing-bindings.rs:47:33 | LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | - ^^^^ pattern doesn't bind `d` @@ -144,7 +144,7 @@ LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:61:29 + --> $DIR/missing-bindings.rs:63:29 | LL | Ok(a) | Err(_), | - ^^^^^^ pattern doesn't bind `a` @@ -152,7 +152,7 @@ LL | Ok(a) | Err(_), | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:68:21 + --> $DIR/missing-bindings.rs:70:21 | LL | A(_, a) | | ^^^^^^^ pattern doesn't bind `b` @@ -160,7 +160,7 @@ LL | B(b), | - variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:69:21 + --> $DIR/missing-bindings.rs:71:21 | LL | A(_, a) | | - variable not in all patterns @@ -168,7 +168,7 @@ LL | B(b), | ^^^^ pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:72:17 + --> $DIR/missing-bindings.rs:74:17 | LL | A(_, a) | | - variable not in all patterns @@ -177,7 +177,7 @@ LL | B(_) | ^^^^ pattern doesn't bind `a` error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:72:17 + --> $DIR/missing-bindings.rs:74:17 | LL | B(b), | - variable not in all patterns @@ -186,7 +186,7 @@ LL | B(_) | ^^^^ pattern doesn't bind `b` error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:57:13 + --> $DIR/missing-bindings.rs:59:13 | LL | / V1( LL | | @@ -204,7 +204,7 @@ LL | V3(c), | ^^^^^ pattern doesn't bind `b` error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:57:13 + --> $DIR/missing-bindings.rs:59:13 | LL | / V1( LL | | @@ -226,7 +226,7 @@ LL | V3(c), | - variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:76:13 + --> $DIR/missing-bindings.rs:78:13 | LL | B(Ok(a) | Err(a)) | - variable not in all patterns @@ -237,6 +237,38 @@ LL | A(_, a) | LL | V3(c), | ^^^^^ pattern doesn't bind `a` -error: aborting due to 26 previous errors +error[E0170]: pattern binding `beta` is named the same as one of the variants of the type `check_handling_of_paths::bar::foo` + --> $DIR/missing-bindings.rs:19:18 + | +LL | let (alpha | beta | charlie) = alpha; + | ^^^^ + | + = note: `#[deny(bindings_with_variant_name)]` on by default + +error[E0170]: pattern binding `beta` is named the same as one of the variants of the type `check_handling_of_paths::bar::foo` + --> $DIR/missing-bindings.rs:22:22 + | +LL | Some(alpha | beta) => {} + | ^^^^ help: to match on the variant, qualify the path: `check_handling_of_paths::bar::foo::beta` + +error[E0004]: non-exhaustive patterns: `None` not covered + --> $DIR/missing-bindings.rs:21:11 + | +LL | match Some(alpha) { + | ^^^^^^^^^^^ pattern `None` not covered + | +note: `Option<foo>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<foo>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | Some(alpha | beta) => {}, None => todo!() + | +++++++++++++++++ + +error: aborting due to 29 previous errors -For more information about this error, try `rustc --explain E0408`. +Some errors have detailed explanations: E0004, E0170, E0408. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/overloaded/issue-14958.rs b/tests/ui/overloaded/issue-14958.rs index a12564ca9c0..80abf5e4e76 100644 --- a/tests/ui/overloaded/issue-14958.rs +++ b/tests/ui/overloaded/issue-14958.rs @@ -3,7 +3,7 @@ #![feature(fn_traits, unboxed_closures)] -trait Foo { fn dummy(&self) { }} +trait Foo { fn dummy(&self) { }} //~ WARN method `dummy` is never used struct Bar; diff --git a/tests/ui/overloaded/issue-14958.stderr b/tests/ui/overloaded/issue-14958.stderr new file mode 100644 index 00000000000..cc97730239c --- /dev/null +++ b/tests/ui/overloaded/issue-14958.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/issue-14958.rs:6:16 + | +LL | trait Foo { fn dummy(&self) { }} + | --- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/overloaded/overloaded-index-in-field.rs b/tests/ui/overloaded/overloaded-index-in-field.rs index 8a1fa7deb99..0dc45ea8ca2 100644 --- a/tests/ui/overloaded/overloaded-index-in-field.rs +++ b/tests/ui/overloaded/overloaded-index-in-field.rs @@ -27,7 +27,7 @@ impl Index<isize> for Foo { trait Int { fn get(self) -> isize; - fn get_from_ref(&self) -> isize; + fn get_from_ref(&self) -> isize; //~ WARN methods `get_from_ref` and `inc` are never used fn inc(&mut self); } diff --git a/tests/ui/overloaded/overloaded-index-in-field.stderr b/tests/ui/overloaded/overloaded-index-in-field.stderr new file mode 100644 index 00000000000..10c0a3faeb5 --- /dev/null +++ b/tests/ui/overloaded/overloaded-index-in-field.stderr @@ -0,0 +1,15 @@ +warning: methods `get_from_ref` and `inc` are never used + --> $DIR/overloaded-index-in-field.rs:30:8 + | +LL | trait Int { + | --- methods in this trait +LL | fn get(self) -> isize; +LL | fn get_from_ref(&self) -> isize; + | ^^^^^^^^^^^^ +LL | fn inc(&mut self); + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs new file mode 100644 index 00000000000..148a59240f9 --- /dev/null +++ b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs @@ -0,0 +1,16 @@ +// compile-flags: -Z threads=16 +// build-fail + +#![crate_type="rlib"] +#![allow(warnings)] + +#[export_name="fail"] +pub fn a() { +} + +#[export_name="fail"] +pub fn b() { +//~^ Error symbol `fail` is already defined +} + +fn main() {} diff --git a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr new file mode 100644 index 00000000000..7963165e31b --- /dev/null +++ b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr @@ -0,0 +1,8 @@ +error: symbol `fail` is already defined + --> $DIR/cache-after-waiting-issue-111528.rs:12:1 + | +LL | pub fn b() { + | ^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs new file mode 100644 index 00000000000..8240b249018 --- /dev/null +++ b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs @@ -0,0 +1,7 @@ +// compile-flags:-C extra-filename=-1 -Z threads=16 +// no-prefer-dynamic +// build-pass +#![crate_name = "crateresolve1"] +#![crate_type = "lib"] + +pub fn f() -> isize { 10 } diff --git a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs new file mode 100644 index 00000000000..691c36cfc9e --- /dev/null +++ b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs @@ -0,0 +1,22 @@ +// compile-flags: -Z threads=16 +// build-pass + +pub static GLOBAL: isize = 3; + +static GLOBAL0: isize = 4; + +pub static GLOBAL2: &'static isize = &GLOBAL0; + +pub fn verify_same(a: &'static isize) { + let a = a as *const isize as usize; + let b = &GLOBAL as *const isize as usize; + assert_eq!(a, b); +} + +pub fn verify_same2(a: &'static isize) { + let a = a as *const isize as usize; + let b = GLOBAL2 as *const isize as usize; + assert_eq!(a, b); +} + +fn main() {} diff --git a/tests/ui/parallel-rustc/hello_world.rs b/tests/ui/parallel-rustc/hello_world.rs new file mode 100644 index 00000000000..53e95c890ef --- /dev/null +++ b/tests/ui/parallel-rustc/hello_world.rs @@ -0,0 +1,6 @@ +// compile-flags: -Z threads=8 +// run-pass + +fn main() { + println!("Hello world!"); +} diff --git a/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs b/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs new file mode 100644 index 00000000000..1907348cf09 --- /dev/null +++ b/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z threads=16 +// run-pass + +#[repr(transparent)] +struct Sched { + i: i32, +} +impl Sched { + extern "C" fn get(self) -> i32 { self.i } +} + +fn main() { + let s = Sched { i: 4 }; + let f = || -> i32 { + s.get() + }; + println!("f: {}", f()); +} diff --git a/tests/ui/parser/bad-let-else-statement.rs b/tests/ui/parser/bad-let-else-statement.rs index a42e8c41c2e..c3126a493e5 100644 --- a/tests/ui/parser/bad-let-else-statement.rs +++ b/tests/ui/parser/bad-let-else-statement.rs @@ -5,6 +5,7 @@ fn a() { let foo = { + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -23,6 +24,7 @@ fn b() { fn c() { let foo = if true { + //~^ WARN irrefutable `let...else` pattern 1 } else { 0 @@ -43,6 +45,7 @@ fn d() { fn e() { let foo = match true { + //~^ WARN irrefutable `let...else` pattern true => 1, false => 0 } else { @@ -54,6 +57,7 @@ fn e() { struct X {a: i32} fn f() { let foo = X { + //~^ WARN irrefutable `let...else` pattern a: 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -72,6 +76,7 @@ fn g() { fn h() { let foo = const { + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -81,6 +86,7 @@ fn h() { fn i() { let foo = &{ + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -90,7 +96,8 @@ fn i() { fn j() { let bar = 0; - let foo = bar = { + let foo = bar = { //~ ERROR: cannot assign twice + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -100,6 +107,7 @@ fn j() { fn k() { let foo = 1 + { + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -109,6 +117,7 @@ fn k() { fn l() { let foo = 1..{ + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -118,6 +127,7 @@ fn l() { fn m() { let foo = return { + //~^ WARN irrefutable `let...else` pattern () } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -127,6 +137,7 @@ fn m() { fn n() { let foo = -{ + //~^ WARN irrefutable `let...else` pattern 1 } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -136,6 +147,7 @@ fn n() { fn o() -> Result<(), ()> { let foo = do yeet { + //~^ WARN irrefutable `let...else` pattern () } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -145,6 +157,7 @@ fn o() -> Result<(), ()> { fn p() { let foo = become { + //~^ WARN irrefutable `let...else` pattern () } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -154,6 +167,7 @@ fn p() { fn q() { let foo = |x: i32| { + //~^ WARN irrefutable `let...else` pattern x } else { //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed @@ -163,14 +177,18 @@ fn q() { fn r() { let ok = format_args!("") else { return; }; + //~^ WARN irrefutable `let...else` pattern let bad = format_args! {""} else { return; }; //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed + //~| WARN irrefutable `let...else` pattern } fn s() { macro_rules! a { () => { {} } + //~^ WARN irrefutable `let...else` pattern + //~| WARN irrefutable `let...else` pattern } macro_rules! b { diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 887455913d8..12df8f849ab 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -1,5 +1,5 @@ error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:9:5 + --> $DIR/bad-let-else-statement.rs:10:5 | LL | } else { | ^ @@ -7,12 +7,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = ({ +LL | LL | 1 LL ~ }) else { | error: `for...else` loops are not supported - --> $DIR/bad-let-else-statement.rs:18:7 + --> $DIR/bad-let-else-statement.rs:19:7 | LL | let foo = for i in 1..2 { | --- `else` is attached to this loop @@ -27,7 +28,7 @@ LL | | }; = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:29:5 + --> $DIR/bad-let-else-statement.rs:31:5 | LL | } else { | ^ @@ -35,14 +36,14 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = (if true { -LL | 1 -LL | } else { +LL | + ... LL | 0 LL ~ }) else { | error: `loop...else` loops are not supported - --> $DIR/bad-let-else-statement.rs:38:7 + --> $DIR/bad-let-else-statement.rs:40:7 | LL | let foo = loop { | ---- `else` is attached to this loop @@ -57,7 +58,7 @@ LL | | }; = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:48:5 + --> $DIR/bad-let-else-statement.rs:51:5 | LL | } else { | ^ @@ -65,13 +66,14 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = (match true { +LL | LL | true => 1, LL | false => 0 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:58:5 + --> $DIR/bad-let-else-statement.rs:62:5 | LL | } else { | ^ @@ -79,12 +81,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = (X { +LL | LL | a: 1 LL ~ }) else { | error: `while...else` loops are not supported - --> $DIR/bad-let-else-statement.rs:67:7 + --> $DIR/bad-let-else-statement.rs:71:7 | LL | let foo = while false { | ----- `else` is attached to this loop @@ -99,7 +102,7 @@ LL | | }; = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:76:5 + --> $DIR/bad-let-else-statement.rs:81:5 | LL | } else { | ^ @@ -107,12 +110,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = (const { +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:85:5 + --> $DIR/bad-let-else-statement.rs:91:5 | LL | } else { | ^ @@ -120,12 +124,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = &({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:95:5 + --> $DIR/bad-let-else-statement.rs:102:5 | LL | } else { | ^ @@ -133,12 +138,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = bar = ({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:104:5 + --> $DIR/bad-let-else-statement.rs:112:5 | LL | } else { | ^ @@ -146,12 +152,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = 1 + ({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:113:5 + --> $DIR/bad-let-else-statement.rs:122:5 | LL | } else { | ^ @@ -159,12 +166,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = 1..({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:122:5 + --> $DIR/bad-let-else-statement.rs:132:5 | LL | } else { | ^ @@ -172,12 +180,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = return ({ +LL | LL | () LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:131:5 + --> $DIR/bad-let-else-statement.rs:142:5 | LL | } else { | ^ @@ -185,12 +194,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = -({ +LL | LL | 1 LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:140:5 + --> $DIR/bad-let-else-statement.rs:152:5 | LL | } else { | ^ @@ -198,12 +208,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = do yeet ({ +LL | LL | () LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:149:5 + --> $DIR/bad-let-else-statement.rs:162:5 | LL | } else { | ^ @@ -211,12 +222,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = become ({ +LL | LL | () LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:158:5 + --> $DIR/bad-let-else-statement.rs:172:5 | LL | } else { | ^ @@ -224,12 +236,13 @@ LL | } else { help: wrap the expression in parentheses | LL ~ let foo = |x: i32| ({ +LL | LL | x LL ~ }) else { | error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:167:31 + --> $DIR/bad-let-else-statement.rs:182:31 | LL | let bad = format_args! {""} else { return; }; | ^ @@ -240,7 +253,7 @@ LL | let bad = format_args! ("") else { return; }; | ~ ~ error: right curly brace `}` before `else` in a `let...else` statement not allowed - --> $DIR/bad-let-else-statement.rs:181:25 + --> $DIR/bad-let-else-statement.rs:199:25 | LL | let x = a! {} else { return; }; | ^ @@ -254,5 +267,251 @@ help: use parentheses instead of braces for this macro LL | let x = a! () else { return; }; | ~~ -error: aborting due to 19 previous errors +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:7:5 + | +LL | / let foo = { +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + = note: `#[warn(irrefutable_let_patterns)]` on by default + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:26:5 + | +LL | / let foo = if true { +LL | | +LL | | 1 +LL | | } else { +LL | | 0 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:47:5 + | +LL | / let foo = match true { +LL | | +LL | | true => 1, +LL | | false => 0 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:59:5 + | +LL | / let foo = X { +LL | | +LL | | a: 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:78:5 + | +LL | / let foo = const { +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:88:5 + | +LL | / let foo = &{ +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:99:5 + | +LL | / let foo = bar = { +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +error[E0384]: cannot assign twice to immutable variable `bar` + --> $DIR/bad-let-else-statement.rs:99:15 + | +LL | let bar = 0; + | --- + | | + | first assignment to `bar` + | help: consider making this binding mutable: `mut bar` +LL | let foo = bar = { + | _______________^ +LL | | +LL | | 1 +LL | | } else { + | |_____^ cannot assign twice to immutable variable + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:109:5 + | +LL | / let foo = 1 + { +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:119:5 + | +LL | / let foo = 1..{ +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:129:5 + | +LL | / let foo = return { +LL | | +LL | | () +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:139:5 + | +LL | / let foo = -{ +LL | | +LL | | 1 +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:149:5 + | +LL | / let foo = do yeet { +LL | | +LL | | () +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:159:5 + | +LL | / let foo = become { +LL | | +LL | | () +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:169:5 + | +LL | / let foo = |x: i32| { +LL | | +LL | | x +LL | | } else { + | |_____^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:179:5 + | +LL | let ok = format_args!("") else { return; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:182:5 + | +LL | let bad = format_args! {""} else { return; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:189:19 + | +LL | () => { {} } + | ___________________^ +LL | | +LL | | +LL | | } +... | +LL | | (1) => { +LL | | let x = a!() else { return; }; + | |____________^ +... +LL | b!(1); b!(2); + | ----- in this macro invocation + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + = note: this warning originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) + +warning: irrefutable `let...else` pattern + --> $DIR/bad-let-else-statement.rs:189:19 + | +LL | () => { {} } + | ___________________^ +LL | | +LL | | +LL | | } +... | +LL | | (2) => { +LL | | let x = a! {} else { return; }; + | |____________^ +... +LL | b!(1); b!(2); + | ----- in this macro invocation + | + = note: this pattern will always match, so the `else` clause is useless + = help: consider removing the `else` clause + = note: this warning originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 20 previous errors; 18 warnings emitted +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs b/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs index 3d110adef3e..c1c847d92d0 100644 --- a/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs +++ b/tests/ui/parser/issues/issue-35813-postfix-after-cast.rs @@ -129,6 +129,7 @@ pub fn inside_block() { static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); //~^ ERROR: cast cannot be followed by indexing +//~| ERROR: cannot call non-const operator in statics static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); //~^ ERROR: expected one of diff --git a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr index d313c888e51..6a8cbd9389b 100644 --- a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr +++ b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr @@ -235,13 +235,13 @@ LL | static bar: &[i32] = &((&[1,2,3] as &[i32])[0..1]); | + + error: expected one of `)`, `,`, `.`, `?`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:133:36 + --> $DIR/issue-35813-postfix-after-cast.rs:134:36 | LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); | ^ expected one of `)`, `,`, `.`, `?`, or an operator error: cast cannot be followed by `?` - --> $DIR/issue-35813-postfix-after-cast.rs:138:5 + --> $DIR/issue-35813-postfix-after-cast.rs:139:5 | LL | Err(0u64) as Result<u64,u64>?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -252,13 +252,13 @@ LL | (Err(0u64) as Result<u64,u64>)?; | + + error: expected one of `.`, `;`, `?`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:140:14 + --> $DIR/issue-35813-postfix-after-cast.rs:141:14 | LL | Err(0u64): Result<u64,u64>?; | ^ expected one of `.`, `;`, `?`, `}`, or an operator error: expected identifier, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:152:13 + --> $DIR/issue-35813-postfix-after-cast.rs:153:13 | LL | drop_ptr: F(); | ^ expected identifier @@ -266,13 +266,13 @@ LL | drop_ptr: F(); = note: type ascription syntax has been removed, see issue #101728 <https://github.com/rust-lang/rust/issues/101728> error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:159:13 + --> $DIR/issue-35813-postfix-after-cast.rs:160:13 | LL | drop_ptr: fn(u8); | ^ expected one of 8 possible tokens error: cast cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:165:5 + --> $DIR/issue-35813-postfix-after-cast.rs:166:5 | LL | drop as fn(u8)(0); | ^^^^^^^^^^^^^^ @@ -283,13 +283,13 @@ LL | (drop as fn(u8))(0); | + + error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:167:13 + --> $DIR/issue-35813-postfix-after-cast.rs:168:13 | LL | drop_ptr: fn(u8)(0); | ^ expected one of 8 possible tokens error: cast cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:172:5 + --> $DIR/issue-35813-postfix-after-cast.rs:173:5 | LL | Box::pin(noop()) as Pin<Box<dyn Future<Output = ()>>>.await; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -300,13 +300,13 @@ LL | (Box::pin(noop()) as Pin<Box<dyn Future<Output = ()>>>).await; | + + error: expected one of `.`, `;`, `?`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:175:21 + --> $DIR/issue-35813-postfix-after-cast.rs:176:21 | LL | Box::pin(noop()): Pin<Box<_>>.await; | ^ expected one of `.`, `;`, `?`, `}`, or an operator error: cast cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:187:5 + --> $DIR/issue-35813-postfix-after-cast.rs:188:5 | LL | Foo::default() as Foo.bar; | ^^^^^^^^^^^^^^^^^^^^^ @@ -317,7 +317,7 @@ LL | (Foo::default() as Foo).bar; | + + error: expected one of `.`, `;`, `?`, `}`, or an operator, found `:` - --> $DIR/issue-35813-postfix-after-cast.rs:189:19 + --> $DIR/issue-35813-postfix-after-cast.rs:190:19 | LL | Foo::default(): Foo.bar; | ^ expected one of `.`, `;`, `?`, `}`, or an operator @@ -340,11 +340,22 @@ LL | if true { 33 } else { 44 }: i32.max(0) | ^ expected one of `,`, `.`, `?`, or an operator error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:150:13 + --> $DIR/issue-35813-postfix-after-cast.rs:151:13 | LL | drop as F(); | ^^^ only `Fn` traits may use parentheses -error: aborting due to 39 previous errors +error[E0015]: cannot call non-const operator in statics + --> $DIR/issue-35813-postfix-after-cast.rs:130:42 + | +LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); + | ^^^^^^ + | + = note: calls in statics are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell + +error: aborting due to 40 previous errors -For more information about this error, try `rustc --explain E0214`. +Some errors have detailed explanations: E0015, E0214. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs index e1ea38f2795..d081c06044f 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.rs +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.rs @@ -37,9 +37,10 @@ fn g1() { //~| HELP: maybe write a path separator here _ => {} } - if let Foo:Bar = f() { + if let Foo:Bar = f() { //~ WARN: irrefutable `if let` pattern //~^ ERROR: expected one of //~| HELP: maybe write a path separator here + //~| HELP: consider replacing the `if let` with a `let` } } diff --git a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr index 63b072ac4cd..b6e24faf5da 100644 --- a/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr +++ b/tests/ui/parser/issues/issue-87086-colon-path-sep.stderr @@ -64,7 +64,7 @@ LL | if let Foo::Bar = f() { | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:48:16 + --> $DIR/issue-87086-colon-path-sep.rs:49:16 | LL | ref qux: Foo::Baz => {} | ^ -------- specifying the type of a pattern isn't supported @@ -77,7 +77,7 @@ LL | ref qux::Foo::Baz => {} | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:57:16 + --> $DIR/issue-87086-colon-path-sep.rs:58:16 | LL | mut qux: Foo::Baz => {} | ^ -------- specifying the type of a pattern isn't supported @@ -90,7 +90,7 @@ LL | mut qux::Foo::Baz => {} | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:68:12 + --> $DIR/issue-87086-colon-path-sep.rs:69:12 | LL | Foo:Bar::Baz => {} | ^-------- specifying the type of a pattern isn't supported @@ -103,7 +103,7 @@ LL | Foo::Bar::Baz => {} | ~~ error: expected one of `@` or `|`, found `:` - --> $DIR/issue-87086-colon-path-sep.rs:74:12 + --> $DIR/issue-87086-colon-path-sep.rs:75:12 | LL | Foo:Bar => {} | ^--- specifying the type of a pattern isn't supported @@ -115,5 +115,15 @@ help: maybe write a path separator here LL | Foo::Bar => {} | ~~ -error: aborting due to 9 previous errors +warning: irrefutable `if let` pattern + --> $DIR/issue-87086-colon-path-sep.rs:40:8 + | +LL | if let Foo:Bar = f() { + | ^^^^^^^^^^^^^^^^^ + | + = note: this pattern will always match, so the `if let` is useless + = help: consider replacing the `if let` with a `let` + = note: `#[warn(irrefutable_let_patterns)]` on by default + +error: aborting due to 9 previous errors; 1 warning emitted diff --git a/tests/ui/parser/parse-assoc-type-lt.rs b/tests/ui/parser/parse-assoc-type-lt.rs index d3fe6079a5d..913fcd920bd 100644 --- a/tests/ui/parser/parse-assoc-type-lt.rs +++ b/tests/ui/parser/parse-assoc-type-lt.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Foo { diff --git a/tests/ui/parser/recover/recover-range-pats.rs b/tests/ui/parser/recover/recover-range-pats.rs index 156c7ad94d3..3dc525cd6e1 100644 --- a/tests/ui/parser/recover/recover-range-pats.rs +++ b/tests/ui/parser/recover/recover-range-pats.rs @@ -134,10 +134,13 @@ fn with_macro_expr_var() { macro_rules! mac2 { ($e1:expr, $e2:expr) => { let $e1..$e2; + //~^ ERROR refutable pattern in local binding let $e1...$e2; //~^ ERROR `...` range patterns are deprecated //~| WARN this is accepted in the current edition + //~| ERROR refutable pattern in local binding let $e1..=$e2; + //~^ ERROR refutable pattern in local binding } } @@ -146,12 +149,18 @@ fn with_macro_expr_var() { macro_rules! mac { ($e:expr) => { let ..$e; + //~^ ERROR refutable pattern in local binding let ...$e; //~^ ERROR range-to patterns with `...` are not allowed + //~| ERROR refutable pattern in local binding let ..=$e; + //~^ ERROR refutable pattern in local binding let $e..; + //~^ ERROR refutable pattern in local binding let $e...; //~ ERROR inclusive range with no end + //~^ ERROR refutable pattern in local binding let $e..=; //~ ERROR inclusive range with no end + //~^ ERROR refutable pattern in local binding } } diff --git a/tests/ui/parser/recover/recover-range-pats.stderr b/tests/ui/parser/recover/recover-range-pats.stderr index 5b69ca5cd6d..7c5cc4777b6 100644 --- a/tests/ui/parser/recover/recover-range-pats.stderr +++ b/tests/ui/parser/recover/recover-range-pats.stderr @@ -159,7 +159,7 @@ LL | if let ....3 = 0 {} | ^^^ help: use `..=` instead error: range-to patterns with `...` are not allowed - --> $DIR/recover-range-pats.rs:149:17 + --> $DIR/recover-range-pats.rs:153:17 | LL | let ...$e; | ^^^ help: use `..=` instead @@ -170,7 +170,7 @@ LL | mac!(0); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0586]: inclusive range with no end - --> $DIR/recover-range-pats.rs:153:19 + --> $DIR/recover-range-pats.rs:160:19 | LL | let $e...; | ^^^ help: use `..` instead @@ -182,7 +182,7 @@ LL | mac!(0); = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0586]: inclusive range with no end - --> $DIR/recover-range-pats.rs:154:19 + --> $DIR/recover-range-pats.rs:162:19 | LL | let $e..=; | ^^^ help: use `..` instead @@ -271,7 +271,7 @@ LL | if let X... .0 = 0 {} = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> error: `...` range patterns are deprecated - --> $DIR/recover-range-pats.rs:137:20 + --> $DIR/recover-range-pats.rs:138:20 | LL | let $e1...$e2; | ^^^ help: use `..=` for an inclusive range @@ -478,7 +478,169 @@ LL | if let ....3 = 0 {} | | | expected integer, found floating-point number -error: aborting due to 60 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:136:17 + | +LL | let $e1..$e2; + | ^^^^^^^^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered +... +LL | mac2!(0, 1); + | ----------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let $e1..$e2; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:138:17 + | +LL | let $e1...$e2; + | ^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `2_i32..=i32::MAX` not covered +... +LL | mac2!(0, 1); + | ----------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let $e1...$e2; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:142:17 + | +LL | let $e1..=$e2; + | ^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `2_i32..=i32::MAX` not covered +... +LL | mac2!(0, 1); + | ----------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let $e1..=$e2; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:151:17 + | +LL | let ..$e; + | ^^^^ pattern `0_i32..=i32::MAX` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let ..$e; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:153:17 + | +LL | let ...$e; + | ^^^^^ pattern `1_i32..=i32::MAX` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let ...$e; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:156:17 + | +LL | let ..=$e; + | ^^^^^ pattern `1_i32..=i32::MAX` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let ..=$e; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:158:17 + | +LL | let $e..; + | ^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e..; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:160:17 + | +LL | let $e...; + | ^^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e...; { todo!() } + | ++ +++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/recover-range-pats.rs:162:17 + | +LL | let $e..=; + | ^^^^^ pattern `i32::MIN..=-1_i32` not covered +... +LL | mac!(0); + | ------- in this macro invocation + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `i32` + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let $e..=; { todo!() } + | ++ +++++++++++ + +error: aborting due to 69 previous errors -Some errors have detailed explanations: E0029, E0308, E0586. -For more information about an error, try `rustc --explain E0029`. +Some errors have detailed explanations: E0005, E0029, E0308, E0586. +For more information about an error, try `rustc --explain E0005`. diff --git a/tests/ui/parser/suggest-assoc-const.fixed b/tests/ui/parser/suggest-assoc-const.fixed index 259f37b23a5..4229135ebb2 100644 --- a/tests/ui/parser/suggest-assoc-const.fixed +++ b/tests/ui/parser/suggest-assoc-const.fixed @@ -1,5 +1,6 @@ // Issue: 101797, Suggest associated const for incorrect use of let in traits // run-rustfix +#![allow(dead_code)] trait Trait { const _X: i32; //~^ ERROR non-item in item list diff --git a/tests/ui/parser/suggest-assoc-const.rs b/tests/ui/parser/suggest-assoc-const.rs index c7be712ec07..0cf695bd40a 100644 --- a/tests/ui/parser/suggest-assoc-const.rs +++ b/tests/ui/parser/suggest-assoc-const.rs @@ -1,5 +1,6 @@ // Issue: 101797, Suggest associated const for incorrect use of let in traits // run-rustfix +#![allow(dead_code)] trait Trait { let _X: i32; //~^ ERROR non-item in item list diff --git a/tests/ui/parser/suggest-assoc-const.stderr b/tests/ui/parser/suggest-assoc-const.stderr index 7ba1dbdff7e..6e29fad98d4 100644 --- a/tests/ui/parser/suggest-assoc-const.stderr +++ b/tests/ui/parser/suggest-assoc-const.stderr @@ -1,5 +1,5 @@ error: non-item in item list - --> $DIR/suggest-assoc-const.rs:4:5 + --> $DIR/suggest-assoc-const.rs:5:5 | LL | let _X: i32; | ^^^ help: consider using `const` instead of `let` for associated const: `const` diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed index 63704735490..81ee6cdf0a7 100644 --- a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait Foo { fn bar() {} //~ ERROR non-item in item list diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs index 4650b05e20c..c8f525fc4f0 100644 --- a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait Foo { fn bar() {}; //~ ERROR non-item in item list diff --git a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr index c716d5908ea..396c76ac85f 100644 --- a/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr +++ b/tests/ui/parser/suggest-removing-semicolon-after-impl-trait-items.stderr @@ -1,5 +1,5 @@ error: non-item in item list - --> $DIR/suggest-removing-semicolon-after-impl-trait-items.rs:4:16 + --> $DIR/suggest-removing-semicolon-after-impl-trait-items.rs:5:16 | LL | trait Foo { | - item list starts here diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs index b173e23e7a1..a2d2388ff50 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs @@ -34,10 +34,12 @@ extern "C" fn f3_3(..., x: isize) {} const unsafe extern "C" fn f4_1(x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic +//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time const extern "C" fn f4_2(x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic //~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic +//~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time const extern "C" fn f4_3(..., x: isize, ...) {} //~^ ERROR functions cannot be both `const` and C-variadic @@ -48,7 +50,7 @@ extern "C" { fn e_f1(...); //~^ ERROR C-variadic function must be declared with at least one named argument fn e_f2(..., x: isize); -//~^ ERROR `...` must be the last argument of a C-variadic function + //~^ ERROR `...` must be the last argument of a C-variadic function } struct X; @@ -68,6 +70,7 @@ impl X { const fn i_f5(x: isize, ...) {} //~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic //~| ERROR functions cannot be both `const` and C-variadic + //~| ERROR destructor of `VaListImpl<'_>` cannot be evaluated at compile-time } trait T { diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr index 18526080e4c..6a65ed79d4f 100644 --- a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr +++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr @@ -83,25 +83,25 @@ LL | const unsafe extern "C" fn f4_1(x: isize, ...) {} | ^^^^^ `const` because of this ^^^ C-variadic because of this error: functions cannot be both `const` and C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:38:1 + --> $DIR/variadic-ffi-semantic-restrictions.rs:39:1 | LL | const extern "C" fn f4_2(x: isize, ...) {} | ^^^^^ `const` because of this ^^^ C-variadic because of this error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:38:36 + --> $DIR/variadic-ffi-semantic-restrictions.rs:39:36 | LL | const extern "C" fn f4_2(x: isize, ...) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:42:26 + --> $DIR/variadic-ffi-semantic-restrictions.rs:44:26 | LL | const extern "C" fn f4_3(..., x: isize, ...) {} | ^^^ error: functions cannot be both `const` and C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:42:1 + --> $DIR/variadic-ffi-semantic-restrictions.rs:44:1 | LL | const extern "C" fn f4_3(..., x: isize, ...) {} | ^^^^^ ^^^ ^^^ C-variadic because of this @@ -110,67 +110,67 @@ LL | const extern "C" fn f4_3(..., x: isize, ...) {} | `const` because of this error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:42:26 + --> $DIR/variadic-ffi-semantic-restrictions.rs:44:26 | LL | const extern "C" fn f4_3(..., x: isize, ...) {} | ^^^ ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:48:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13 | LL | fn e_f1(...); | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:50:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:52:13 | LL | fn e_f2(..., x: isize); | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:57:23 + --> $DIR/variadic-ffi-semantic-restrictions.rs:59:23 | LL | fn i_f1(x: isize, ...) {} | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:59:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:61:13 | LL | fn i_f2(...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:59:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:61:13 | LL | fn i_f2(...) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:62:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 | LL | fn i_f3(..., x: isize, ...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:62:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:64:13 | LL | fn i_f3(..., x: isize, ...) {} | ^^^ ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 | LL | fn i_f4(..., x: isize, ...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:65:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:67:13 | LL | fn i_f4(..., x: isize, ...) {} | ^^^ ^^^ error: functions cannot be both `const` and C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:68:5 + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:5 | LL | const fn i_f5(x: isize, ...) {} | ^^^^^ ^^^ C-variadic because of this @@ -178,70 +178,95 @@ LL | const fn i_f5(x: isize, ...) {} | `const` because of this error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:68:29 + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:29 | LL | const fn i_f5(x: isize, ...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:74:23 + --> $DIR/variadic-ffi-semantic-restrictions.rs:77:23 | LL | fn t_f1(x: isize, ...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:76:23 + --> $DIR/variadic-ffi-semantic-restrictions.rs:79:23 | LL | fn t_f2(x: isize, ...); | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:78:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13 | LL | fn t_f3(...) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:78:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13 | LL | fn t_f3(...) {} | ^^^ error: C-variadic function must be declared with at least one named argument - --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13 | LL | fn t_f4(...); | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:81:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13 | LL | fn t_f4(...); | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13 | LL | fn t_f5(..., x: isize) {} | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:84:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13 | LL | fn t_f5(..., x: isize) {} | ^^^ error: `...` must be the last argument of a C-variadic function - --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:90:13 | LL | fn t_f6(..., x: isize); | ^^^ error: only foreign or `unsafe extern "C"` functions may be C-variadic - --> $DIR/variadic-ffi-semantic-restrictions.rs:87:13 + --> $DIR/variadic-ffi-semantic-restrictions.rs:90:13 | LL | fn t_f6(..., x: isize); | ^^^ -error: aborting due to 40 previous errors +error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time + --> $DIR/variadic-ffi-semantic-restrictions.rs:35:43 + | +LL | const unsafe extern "C" fn f4_1(x: isize, ...) {} + | ^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time + --> $DIR/variadic-ffi-semantic-restrictions.rs:39:36 + | +LL | const extern "C" fn f4_2(x: isize, ...) {} + | ^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error[E0493]: destructor of `VaListImpl<'_>` cannot be evaluated at compile-time + --> $DIR/variadic-ffi-semantic-restrictions.rs:70:29 + | +LL | const fn i_f5(x: isize, ...) {} + | ^^^ - value is dropped here + | | + | the destructor for this type cannot be evaluated in constant functions + +error: aborting due to 43 previous errors +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/pattern/bindings-after-at/bind-by-copy.rs b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs index 2b349f0ed5f..253b2d88901 100644 --- a/tests/ui/pattern/bindings-after-at/bind-by-copy.rs +++ b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs @@ -1,13 +1,30 @@ // run-pass +#![allow(unused)] // Test copy -struct A { a: i32, b: i32 } -struct B { a: i32, b: C } -struct D { a: i32, d: C } -#[derive(Copy,Clone)] -struct C { c: i32 } +struct A { + a: i32, + b: i32, +} +struct B { + a: i32, + b: C, +} +struct D { + a: i32, + d: C, +} +#[derive(Copy, Clone)] +struct C { + c: i32, +} +enum E { + E { a: i32, e: C }, + NotE, +} +#[rustfmt::skip] pub fn main() { match (A {a: 10, b: 20}) { x@A {a, b: 20} => { assert!(x.a == 10); assert!(a == 10); } @@ -23,6 +40,23 @@ pub fn main() { y.d.c = 30; assert_eq!(d.c, 20); + match (E::E { a: 10, e: C { c: 20 } }) { + x @ E::E{ a, e: C { c } } => { + assert!(matches!(x, E::E { a: 10, e: C { c: 20 } })); + assert!(a == 10); + assert!(c == 20); + } + _ => panic!(), + } + match (E::E { a: 10, e: C { c: 20 } }) { + mut x @ E::E{ a, e: C { mut c } } => { + x = E::NotE; + c += 30; + assert_eq!(c, 50); + } + _ => panic!(), + } + let some_b = Some(B { a: 10, b: C { c: 20 } }); // in irrefutable pattern diff --git a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs index a61d6821524..bfb3c3b20d6 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs @@ -15,8 +15,8 @@ fn main() { let a @ (b, c) = (u(), u()); //~ ERROR use of partially moved value match Ok(U) { - a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of moved value - //~^ ERROR use of moved value + a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of partially moved value + //~^ ERROR use of partially moved value } fn fun(a @ b: U) {} //~ ERROR use of moved value diff --git a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr index 32489715112..ba0622090bb 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr @@ -40,35 +40,33 @@ help: borrow this binding in the pattern to avoid moving the value LL | let ref a @ (b, ref c) = (u(), u()); | +++ +++ -error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:18:16 +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:18:9 | -LL | match Ok(U) { - | ----- move occurs because value has type `Result<U, U>`, which does not implement the `Copy` trait LL | a @ Ok(b) | a @ Err(b) => {} - | - ^ value used here after move + | ^ - value partially moved here | | - | value moved here + | value used here after partial move | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait help: borrow this binding in the pattern to avoid moving the value | -LL | ref a @ Ok(b) | a @ Err(b) => {} - | +++ +LL | ref a @ Ok(ref b) | a @ Err(b) => {} + | +++ +++ -error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:18:29 +error[E0382]: use of partially moved value + --> $DIR/borrowck-move-and-move.rs:18:21 | -LL | match Ok(U) { - | ----- move occurs because value has type `Result<U, U>`, which does not implement the `Copy` trait LL | a @ Ok(b) | a @ Err(b) => {} - | - ^ value used here after move + | ^ - value partially moved here | | - | value moved here + | value used here after partial move | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait help: borrow this binding in the pattern to avoid moving the value | -LL | a @ Ok(b) | ref a @ Err(b) => {} - | +++ +LL | a @ Ok(b) | ref a @ Err(ref b) => {} + | +++ +++ error[E0382]: use of partially moved value --> $DIR/borrowck-move-and-move.rs:25:9 diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs index 06dc6e1c4da..ac57838f029 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs @@ -48,19 +48,17 @@ fn main() { //~^ ERROR borrow of moved value //~| ERROR borrow of moved value //~| ERROR borrow of moved value - //~| ERROR use of moved value + //~| ERROR use of partially moved value None => {} } match Some([U, U]) { mut a @ Some([ref b, ref mut c]) => {} //~^ ERROR borrow of moved value - //~| ERROR borrow of moved value None => {} } match Some(u()) { a @ Some(ref b) => {} //~^ ERROR borrow of moved value - //~| ERROR borrow of moved value None => {} } match Some((u(), u())) { @@ -68,13 +66,12 @@ fn main() { //~^ ERROR borrow of moved value //~| ERROR borrow of moved value //~| ERROR borrow of moved value - //~| ERROR use of moved value + //~| ERROR use of partially moved value None => {} } match Some([u(), u()]) { mut a @ Some([ref b, ref mut c]) => {} //~^ ERROR borrow of moved value - //~| ERROR borrow of moved value None => {} } } diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr index 1ed019f0a69..fd7a51388bc 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr @@ -215,7 +215,7 @@ LL | ref mut a @ Some([ref b, ref mut c]) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:9 | LL | a @ Some(ref b) => {} | ^ ----- value borrowed here after move @@ -229,7 +229,7 @@ LL | ref a @ Some(ref b) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:9 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:9 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | ^ --------- ----- value borrowed here after move @@ -244,7 +244,7 @@ LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:19 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:19 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | ^^^^^ --------- value borrowed here after move @@ -258,7 +258,7 @@ LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:38 | LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | ^ ----- value borrowed here after move @@ -272,7 +272,7 @@ LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} | +++ error: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:9 + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:73:9 | LL | mut a @ Some([ref b, ref mut c]) => {} | ^^^^^ ----- --------- value borrowed here after move @@ -314,66 +314,33 @@ help: borrow this binding in the pattern to avoid moving the value LL | let ref a @ (mut b @ ref mut c, ref d @ ref e) = (u(), u()); | +++ +++ -error[E0382]: use of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38 +error[E0382]: use of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:9 | -LL | match Some((U, U)) { - | ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | - value moved here ^ value used here after move - | -help: borrow this binding in the pattern to avoid moving the value - | -LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | +++ - -error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:30 - | -LL | match Some([U, U]) { - | ------------ move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait -LL | mut a @ Some([ref b, ref mut c]) => {} - | ----- ^^^^^^^^^ value borrowed here after move - | | - | value moved here - -error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:18 - | -LL | match Some(u()) { - | --------- move occurs because value has type `Option<U>`, which does not implement the `Copy` trait -LL | a @ Some(ref b) => {} - | - ^^^^^ value borrowed here after move + | ^ - value partially moved here | | - | value moved here + | value used here after partial move | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait help: borrow this binding in the pattern to avoid moving the value | -LL | ref a @ Some(ref b) => {} - | +++ +LL | ref a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | +++ +++ -error[E0382]: use of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38 +error[E0382]: use of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:9 | -LL | match Some((u(), u())) { - | ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | - value moved here ^ value used here after move + | ^ - value partially moved here + | | + | value used here after partial move | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait help: borrow this binding in the pattern to avoid moving the value | -LL | ref a @ Some((mut b @ ref mut c, d @ ref e)) => {} - | +++ - -error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:30 - | -LL | match Some([u(), u()]) { - | ---------------- move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait -LL | mut a @ Some([ref b, ref mut c]) => {} - | ----- ^^^^^^^^^ value borrowed here after move - | | - | value moved here +LL | ref a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | +++ +++ error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11 @@ -457,6 +424,6 @@ help: borrow this binding in the pattern to avoid moving the value LL | fn f3(ref a @ [ref mut b, ref c]: [U; 2]) {} | +++ -error: aborting due to 33 previous errors +error: aborting due to 30 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs index 0b0a7801049..095c871e8d2 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs @@ -58,11 +58,13 @@ fn main() { match Some([U, U]) { ref mut a @ Some([b, mut c]) => {} //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value None => {} } match Some(u()) { ref a @ Some(b) => {} //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value None => {} } match Some((u(), u())) { @@ -77,6 +79,7 @@ fn main() { match Some([u(), u()]) { ref mut a @ Some([b, mut c]) => {} //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of partially moved value None => {} } } diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr index c8c4d9b8fdb..45ada8fd516 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr @@ -125,7 +125,7 @@ LL | ref mut a @ Some([b, mut c]) => {} | value is mutably borrowed by `a` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:64:9 + --> $DIR/borrowck-pat-by-move-and-ref.rs:65:9 | LL | ref a @ Some(b) => {} | ^^^^^ - value is moved into `b` here @@ -133,7 +133,7 @@ LL | ref a @ Some(b) => {} | value is borrowed by `a` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:9 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:9 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ ----- - value is moved into `e` here @@ -142,7 +142,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | value is borrowed by `a` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:23 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ ----- value is moved into `c` here @@ -150,7 +150,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | value is borrowed by `b` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:38 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ - value is moved into `e` here @@ -158,7 +158,7 @@ LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | value is borrowed by `d` here error: cannot move out of value because it is borrowed - --> $DIR/borrowck-pat-by-move-and-ref.rs:78:9 + --> $DIR/borrowck-pat-by-move-and-ref.rs:80:9 | LL | ref mut a @ Some([b, mut c]) => {} | ^^^^^^^^^ - ----- value is moved into `c` here @@ -236,8 +236,36 @@ help: borrow this binding in the pattern to avoid moving the value LL | let ref mut a @ [b, ref mut c] = [u(), u()]; | +++ +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:59:9 + | +LL | ref mut a @ Some([b, mut c]) => {} + | ^^^^^^^^^ ----- value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref mut a @ Some([b, ref mut c]) => {} + | +++ + +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:65:9 + | +LL | ref a @ Some(b) => {} + | ^^^^^ - value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref a @ Some(ref b) => {} + | +++ + error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:23 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ ----- value moved here @@ -251,7 +279,7 @@ LL | ref a @ Some((ref b @ ref mut c, ref d @ e)) => {} | +++ error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38 + --> $DIR/borrowck-pat-by-move-and-ref.rs:71:38 | LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} | ^^^^^ - value moved here @@ -264,6 +292,20 @@ help: borrow this binding in the pattern to avoid moving the value LL | ref a @ Some((ref b @ mut c, ref d @ ref e)) => {} | +++ +error[E0382]: borrow of partially moved value + --> $DIR/borrowck-pat-by-move-and-ref.rs:80:9 + | +LL | ref mut a @ Some([b, mut c]) => {} + | ^^^^^^^^^ ----- value partially moved here + | | + | value borrowed here after partial move + | + = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait +help: borrow this binding in the pattern to avoid moving the value + | +LL | ref mut a @ Some([b, ref mut c]) => {} + | +++ + error: cannot move out of value because it is borrowed --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11 | @@ -345,6 +387,6 @@ LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {} | = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait -error: aborting due to 36 previous errors +error: aborting due to 39 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs index 6bc0d346c11..98f316dd74b 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs @@ -7,7 +7,7 @@ fn main() { match &mut Some(1) { ref mut z @ &mut Some(ref a) => { //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable **z = None; println!("{}", *a); } @@ -76,8 +76,8 @@ fn main() { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable *b = U; drop(a); } @@ -87,6 +87,8 @@ fn main() { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot assign to `*b`, as it is immutable for the pattern guard _ => {} } @@ -101,6 +103,8 @@ fn main() { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot move out of `b` in pattern guard //~| ERROR cannot move out of `b` in pattern guard _ => {} diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr index 0b432487615..9359244c6eb 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr @@ -138,7 +138,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -146,7 +146,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa | value is mutably borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -154,7 +154,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^^^^^ --------- value is mutably borrowed by `b` here @@ -162,7 +162,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^^^^^ --------- value is mutably borrowed by `b` here @@ -170,7 +170,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -178,7 +178,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false | value is mutably borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^^^^^^^^^ ----- value is borrowed by `b` here @@ -186,7 +186,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false | value is mutably borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- --------- value is mutably borrowed by `c` here @@ -195,7 +195,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- --------- value is mutably borrowed by `c` here @@ -204,7 +204,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | value is borrowed by `a` here error: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- --------- value is mutably borrowed by `c` here @@ -213,7 +213,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | value is borrowed by `a` here error: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:134:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:138:9 | LL | let ref mut a @ (ref b, ref c) = (U, U); | ^^^^^^^^^ ----- ----- value is borrowed by `c` here @@ -221,16 +221,16 @@ LL | let ref mut a @ (ref b, ref c) = (U, U); | | value is borrowed by `b` here | value is mutably borrowed by `a` here -error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:31 +error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:9 | LL | ref mut z @ &mut Some(ref a) => { - | --------- ^^^^^ immutable borrow occurs here + | ^^^^^^^^^ ----- immutable borrow occurs here | | | mutable borrow occurs here ... -LL | **z = None; - | ---------- mutable borrow later used here +LL | println!("{}", *a); + | -- immutable borrow later used here error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable --> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9 @@ -254,27 +254,44 @@ LL | let ref a @ ref mut b = u(); LL | *b = u(); | -------- mutable borrow later used here -error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:20 +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { - | ----- ^^^^^^^^^ mutable borrow occurs here + | ^^^^^ --------- mutable borrow occurs here | | | immutable borrow occurs here ... -LL | drop(a); - | - immutable borrow later used here +LL | *b = U; + | ------ mutable borrow later used here -error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:45 +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { - | ----- ^^^^^^^^^ mutable borrow occurs here + | ^^^^^ --------- mutable borrow occurs here | | | immutable borrow occurs here ... -LL | drop(a); - | - immutable borrow later used here +LL | *b = U; + | ------ mutable borrow later used here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:9 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + | ^^^^^ --------- mutable borrow occurs here ------ mutable borrow later used here + | | + | immutable borrow occurs here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:33 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} + | ^^^^^ --------- ------ mutable borrow later used here + | | | + | | mutable borrow occurs here + | immutable borrow occurs here error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:61 @@ -285,15 +302,32 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } = note: variables bound in patterns are immutable until the end of the pattern guard error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:61 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:61 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ^^^^^^^^^^^ cannot assign | = note: variables bound in patterns are immutable until the end of the pattern guard +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:9 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | ^^^^^ --------- mutable borrow occurs here - mutable borrow later used here + | | + | immutable borrow occurs here + +error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:33 + | +LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} + | ^^^^^ --------- - mutable borrow later used here + | | | + | | mutable borrow occurs here + | immutable borrow occurs here + error[E0507]: cannot move out of `b` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait @@ -301,7 +335,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0507]: cannot move out of `b` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait @@ -310,7 +344,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0507]: cannot move out of `a` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:66 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^ move occurs because `a` has type `&mut Result<U, U>`, which does not implement the `Copy` trait @@ -318,7 +352,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0507]: cannot move out of `a` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:66 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^ move occurs because `a` has type `&mut Result<U, U>`, which does not implement the `Copy` trait @@ -327,7 +361,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- mutable borrow occurs here @@ -338,7 +372,7 @@ LL | *b = U; | ------ mutable borrow later used here error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- mutable borrow occurs here @@ -349,7 +383,7 @@ LL | *b = U; | ------ mutable borrow later used here error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ^^^^^ --------- mutable borrow occurs here @@ -409,7 +443,7 @@ LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} | | value borrowed here after move | move occurs because value has type `U`, which does not implement the `Copy` trait -error: aborting due to 47 previous errors +error: aborting due to 51 previous errors Some errors have detailed explanations: E0382, E0502, E0507, E0594. For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs index 99739c7bce0..5f86a6a0ca9 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs @@ -82,6 +82,8 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time *b = U; } } @@ -89,8 +91,6 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow value as mutable more than once at a time *a = Err(U); // FIXME: The binding name value used above makes for problematic diagnostics. @@ -101,8 +101,6 @@ fn main() { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow value as mutable more than once at a time - //~| ERROR cannot borrow value as mutable more than once at a time drop(a); } } diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr index c634ea470c5..3446148d2b1 100644 --- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr +++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr @@ -163,7 +163,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:89:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:91:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ^^^^^^^^^ --------- value is mutably borrowed by `b` here @@ -171,7 +171,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | value is mutably borrowed by `a` here error: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:89:37 + --> $DIR/borrowck-pat-ref-mut-twice.rs:91:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ^^^^^^^^^ --------- value is mutably borrowed by `b` here @@ -217,48 +217,26 @@ LL | *b = U; | ------ first borrow later used here error[E0499]: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:89:24 - | -LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | --------- ^^^^^^^^^ second mutable borrow occurs here - | | - | first mutable borrow occurs here -... -LL | *a = Err(U); - | ----------- first borrow later used here - -error[E0499]: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:89:53 - | -LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | --------- ^^^^^^^^^ second mutable borrow occurs here - | | - | first mutable borrow occurs here -... -LL | *a = Err(U); - | ----------- first borrow later used here - -error[E0499]: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:101:24 + --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | --------- ^^^^^^^^^ second mutable borrow occurs here + | ^^^^^^^^^ --------- first mutable borrow occurs here | | - | first mutable borrow occurs here + | second mutable borrow occurs here ... -LL | drop(a); - | - first borrow later used here +LL | *b = U; + | ------ first borrow later used here error[E0499]: cannot borrow value as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:101:53 + --> $DIR/borrowck-pat-ref-mut-twice.rs:82:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - | --------- ^^^^^^^^^ second mutable borrow occurs here + | ^^^^^^^^^ --------- first mutable borrow occurs here | | - | first mutable borrow occurs here + | second mutable borrow occurs here ... -LL | drop(a); - | - first borrow later used here +LL | *b = U; + | ------ first borrow later used here error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:8:11 @@ -313,7 +291,7 @@ LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} | | value borrowed here after move | move occurs because value has type `U`, which does not implement the `Copy` trait -error: aborting due to 31 previous errors +error: aborting due to 29 previous errors Some errors have detailed explanations: E0382, E0499. For more information about an error, try `rustc --explain E0382`. diff --git a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs index f167a3952ee..f0f512bef52 100644 --- a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs +++ b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.rs @@ -10,7 +10,7 @@ fn main() { match Ok(0) { Ok(a @ b @ a) //~^ ERROR identifier `a` is bound more than once in the same pattern - | Err(a @ b @ a) + | Err(a @ b @ a) //~ ERROR cannot assign twice to immutable variable `a` //~^ ERROR identifier `a` is bound more than once in the same pattern => {} } @@ -20,7 +20,7 @@ fn main() { //~| ERROR identifier `a` is bound more than once in the same pattern let ref a @ ref a = (); //~^ ERROR identifier `a` is bound more than once in the same pattern - let ref mut a @ ref mut a = (); + let ref mut a @ ref mut a = (); //~ ERROR cannot borrow value as mutable more than once at a time //~^ ERROR identifier `a` is bound more than once in the same pattern let a @ (Ok(a) | Err(a)) = Ok(()); diff --git a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr index a165549f6b4..e25c30cd492 100644 --- a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr +++ b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr @@ -58,7 +58,27 @@ error[E0416]: identifier `a` is bound more than once in the same pattern LL | let a @ (Ok(a) | Err(a)) = Ok(()); | ^ used in a pattern more than once -error: aborting due to 10 previous errors +error: cannot borrow value as mutable more than once at a time + --> $DIR/pat-at-same-name-both.rs:23:9 + | +LL | let ref mut a @ ref mut a = (); + | ^^^^^^^^^ --------- value is mutably borrowed by `a` here + | | + | value is mutably borrowed by `a` here + +error[E0384]: cannot assign twice to immutable variable `a` + --> $DIR/pat-at-same-name-both.rs:13:15 + | +LL | Ok(a @ b @ a) + | - + | | + | first assignment to `a` + | help: consider making this binding mutable: `mut a` +LL | +LL | | Err(a @ b @ a) + | ^ cannot assign twice to immutable variable + +error: aborting due to 12 previous errors -Some errors have detailed explanations: E0415, E0416. -For more information about an error, try `rustc --explain E0415`. +Some errors have detailed explanations: E0384, E0415, E0416. +For more information about an error, try `rustc --explain E0384`. diff --git a/tests/ui/pattern/issue-22546.rs b/tests/ui/pattern/issue-22546.rs index c26e457f9e4..8a0f51d0b84 100644 --- a/tests/ui/pattern/issue-22546.rs +++ b/tests/ui/pattern/issue-22546.rs @@ -15,7 +15,7 @@ impl<T: ::std::fmt::Display> Foo<T> { } } -trait Tr { +trait Tr { //~ WARN trait `Tr` is never used type U; } diff --git a/tests/ui/pattern/issue-22546.stderr b/tests/ui/pattern/issue-22546.stderr new file mode 100644 index 00000000000..e067a95e422 --- /dev/null +++ b/tests/ui/pattern/issue-22546.stderr @@ -0,0 +1,10 @@ +warning: trait `Tr` is never used + --> $DIR/issue-22546.rs:18:7 + | +LL | trait Tr { + | ^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-28992-empty.rs b/tests/ui/pattern/issue-28992-empty.rs index 74cfeb6db8e..74cfeb6db8e 100644 --- a/tests/ui/issues/issue-28992-empty.rs +++ b/tests/ui/pattern/issue-28992-empty.rs diff --git a/tests/ui/issues/issue-28992-empty.stderr b/tests/ui/pattern/issue-28992-empty.stderr index f69773b8c2b..f69773b8c2b 100644 --- a/tests/ui/issues/issue-28992-empty.stderr +++ b/tests/ui/pattern/issue-28992-empty.stderr diff --git a/tests/ui/pattern/pattern-binding-disambiguation.rs b/tests/ui/pattern/pattern-binding-disambiguation.rs index ce1d8c6c047..8be70f65d0e 100644 --- a/tests/ui/pattern/pattern-binding-disambiguation.rs +++ b/tests/ui/pattern/pattern-binding-disambiguation.rs @@ -26,7 +26,7 @@ fn main() { match doesnt_matter { BracedStruct => {} // OK, `BracedStruct` is a fresh binding } - match UnitVariant { + match UnitVariant { //~ ERROR: `E::TupleVariant` and `E::BracedVariant { }` not covered UnitVariant => {} // OK, `UnitVariant` is a unit variant pattern } match doesnt_matter { @@ -48,7 +48,7 @@ fn main() { let UnitStruct = UnitStruct; // OK, `UnitStruct` is a unit struct pattern let TupleStruct = doesnt_matter; //~ ERROR let bindings cannot shadow tuple structs let BracedStruct = doesnt_matter; // OK, `BracedStruct` is a fresh binding - let UnitVariant = UnitVariant; // OK, `UnitVariant` is a unit variant pattern + let UnitVariant = UnitVariant; //~ ERROR: refutable pattern in local binding let TupleVariant = doesnt_matter; //~ ERROR let bindings cannot shadow tuple variants let BracedVariant = doesnt_matter; // OK, `BracedVariant` is a fresh binding let CONST = CONST; // OK, `CONST` is a const pattern diff --git a/tests/ui/pattern/pattern-binding-disambiguation.stderr b/tests/ui/pattern/pattern-binding-disambiguation.stderr index d54467b3c0c..61c32b6a17b 100644 --- a/tests/ui/pattern/pattern-binding-disambiguation.stderr +++ b/tests/ui/pattern/pattern-binding-disambiguation.stderr @@ -58,6 +58,53 @@ LL | static STATIC: () = (); LL | let STATIC = doesnt_matter; | ^^^^^^ cannot be named the same as a static -error: aborting due to 6 previous errors +error[E0004]: non-exhaustive patterns: `E::TupleVariant` and `E::BracedVariant { }` not covered + --> $DIR/pattern-binding-disambiguation.rs:29:11 + | +LL | match UnitVariant { + | ^^^^^^^^^^^ patterns `E::TupleVariant` and `E::BracedVariant { }` not covered + | +note: `E` defined here + --> $DIR/pattern-binding-disambiguation.rs:5:6 + | +LL | enum E { + | ^ +LL | UnitVariant, +LL | TupleVariant(), + | ------------ not covered +LL | BracedVariant{}, + | ------------- not covered + = note: the matched value is of type `E` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL | UnitVariant => {}, E::TupleVariant | E::BracedVariant { } => todo!() // OK, `UnitVariant` is a unit variant pattern + | ++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/pattern-binding-disambiguation.rs:51:9 + | +LL | let UnitVariant = UnitVariant; + | ^^^^^^^^^^^ patterns `E::TupleVariant` and `E::BracedVariant { }` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `E` defined here + --> $DIR/pattern-binding-disambiguation.rs:5:6 + | +LL | enum E { + | ^ +LL | UnitVariant, +LL | TupleVariant(), + | ------------ not covered +LL | BracedVariant{}, + | ------------- not covered + = note: the matched value is of type `E` +help: you might want to use `if let` to ignore the variants that aren't matched + | +LL | if let UnitVariant = UnitVariant { todo!() }; + | ++ +++++++++++ + +error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0530`. +Some errors have detailed explanations: E0004, E0005, E0530. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs index a619fcafc86..1eba7aeb4d6 100644 --- a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs +++ b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs @@ -1,9 +1,23 @@ fn main() { match &[1, 2, 3][..] { - [1, rest..] => println!("{rest:?}"), + [1, rest..] => println!("{rest}"), //~^ ERROR cannot find value `rest` in this scope //~| ERROR cannot find value `rest` in this scope //~| ERROR `X..` patterns in slices are experimental _ => {} } + match &[4, 5, 6][..] { + [] => {} + [_, ..tail] => println!("{tail}"), + //~^ ERROR cannot find value `tail` in this scope + //~| ERROR cannot find value `tail` in this scope + //~| ERROR exclusive range pattern syntax is experimental + } + match &[7, 8, 9][..] { + [] => {} + [_, ...tail] => println!("{tail}"), + //~^ ERROR cannot find value `tail` in this scope + //~| ERROR cannot find value `tail` in this scope + //~| ERROR range-to patterns with `...` are not allowed + } } diff --git a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr index c3c9131b63e..3a19517c85b 100644 --- a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr +++ b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr @@ -1,31 +1,82 @@ +error: range-to patterns with `...` are not allowed + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:13 + | +LL | [_, ...tail] => println!("{tail}"), + | ^^^ help: use `..=` instead + error[E0425]: cannot find value `rest` in this scope --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13 | -LL | [1, rest..] => println!("{rest:?}"), +LL | [1, rest..] => println!("{rest}"), | ^^^^ not found in this scope | help: if you meant to collect the rest of the slice in `rest`, use the at operator | -LL | [1, rest @ ..] => println!("{rest:?}"), +LL | [1, rest @ ..] => println!("{rest}"), | + error[E0425]: cannot find value `rest` in this scope --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:35 | -LL | [1, rest..] => println!("{rest:?}"), +LL | [1, rest..] => println!("{rest}"), + | ^^^^ not found in this scope + +error[E0425]: cannot find value `tail` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:15 + | +LL | [_, ..tail] => println!("{tail}"), + | ^^^^ not found in this scope + | +help: if you meant to collect the rest of the slice in `tail`, use the at operator + | +LL | [_, tail @ ..] => println!("{tail}"), + | ~~~~~~~~~ + +error[E0425]: cannot find value `tail` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:35 + | +LL | [_, ..tail] => println!("{tail}"), | ^^^^ not found in this scope +error[E0425]: cannot find value `tail` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:16 + | +LL | [_, ...tail] => println!("{tail}"), + | ^^^^ not found in this scope + | +help: if you meant to collect the rest of the slice in `tail`, use the at operator + | +LL | [_, tail @ ..] => println!("{tail}"), + | ~~~~~~~~~ + +error[E0425]: cannot find value `tail` in this scope + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:36 + | +LL | [_, ...tail] => println!("{tail}"), + | ^^^^ not found in this scope + error[E0658]: `X..` patterns in slices are experimental --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13 | -LL | [1, rest..] => println!("{rest:?}"), +LL | [1, rest..] => println!("{rest}"), | ^^^^^^ | = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 3 previous errors +error[E0658]: exclusive range pattern syntax is experimental + --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:13 + | +LL | [_, ..tail] => println!("{tail}"), + | ^^^^^^ + | + = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information + = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = help: use an inclusive range pattern, like N..=M + +error: aborting due to 9 previous errors Some errors have detailed explanations: E0425, E0658. For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr index cd5c283f9fd..553daff2d96 100644 --- a/tests/ui/pattern/usefulness/always-inhabited-union-ref.stderr +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: type `&!` is non-empty - --> $DIR/always-inhabited-union-ref.rs:23:11 + --> $DIR/always-inhabited-union-ref.rs:26:11 | LL | match uninhab_ref() { | ^^^^^^^^^^^^^ @@ -14,13 +14,13 @@ LL + } | error[E0004]: non-exhaustive patterns: type `Foo` is non-empty - --> $DIR/always-inhabited-union-ref.rs:27:11 + --> $DIR/always-inhabited-union-ref.rs:30:11 | LL | match uninhab_union() { | ^^^^^^^^^^^^^^^ | note: `Foo` defined here - --> $DIR/always-inhabited-union-ref.rs:10:11 + --> $DIR/always-inhabited-union-ref.rs:13:11 | LL | pub union Foo { | ^^^ diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr new file mode 100644 index 00000000000..a1d8002c648 --- /dev/null +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.min_exhaustive_patterns.stderr @@ -0,0 +1,46 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/always-inhabited-union-ref.rs:7:46 + | +LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 <https://github.com/rust-lang/rust/issues/119612> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0004]: non-exhaustive patterns: type `&!` is non-empty + --> $DIR/always-inhabited-union-ref.rs:26:11 + | +LL | match uninhab_ref() { + | ^^^^^^^^^^^^^ + | + = note: the matched value is of type `&!` + = note: references are always considered inhabited +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match uninhab_ref() { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: type `Foo` is non-empty + --> $DIR/always-inhabited-union-ref.rs:30:11 + | +LL | match uninhab_union() { + | ^^^^^^^^^^^^^^^ + | +note: `Foo` defined here + --> $DIR/always-inhabited-union-ref.rs:13:11 + | +LL | pub union Foo { + | ^^^ + = note: the matched value is of type `Foo` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match uninhab_union() { +LL + _ => todo!(), +LL + } + | + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs index 7d1cac8a442..247b7f21f68 100644 --- a/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs +++ b/tests/ui/pattern/usefulness/always-inhabited-union-ref.rs @@ -1,9 +1,12 @@ +// revisions: min_exhaustive_patterns exhaustive_patterns + // The precise semantics of inhabitedness with respect to unions and references is currently // undecided. This test file currently checks a conservative choice. -#![feature(exhaustive_patterns)] +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![feature(never_type)] - #![allow(dead_code)] #![allow(unreachable_code)] diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr index 0b4d9972758..59b454d3981 100644 --- a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr +++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr @@ -9,3 +9,21 @@ LL | if let CONSTANT = &&MyType { error: aborting due to 1 previous error +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `MyType` in a pattern, `MyType` must be annotated with `#[derive(PartialEq)]` + --> $DIR/const-partial_eq-fallback-ice.rs:14:12 + | +LL | if let CONSTANT = &&MyType { + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/const-partial_eq-fallback-ice.rs:1:10 + | +LL | #![allow(warnings)] + | ^^^^^^^^ + = note: `#[allow(indirect_structural_match)]` implied by `#[allow(warnings)]` + diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr index 0b1a2e2736e..6a5bd185e39 100644 --- a/tests/ui/pattern/usefulness/consts-opaque.stderr +++ b/tests/ui/pattern/usefulness/consts-opaque.stderr @@ -5,7 +5,7 @@ LL | QUUX => {} | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> = note: `#[warn(pointer_structural_match)]` on by default warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. @@ -15,7 +15,7 @@ LL | QUUX => {} | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:108:9 @@ -24,7 +24,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:110:9 @@ -33,7 +33,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:117:9 @@ -42,7 +42,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:127:9 @@ -51,7 +51,7 @@ LL | WRAPQUUX => {} | ^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:139:9 @@ -60,7 +60,7 @@ LL | WHOKNOWSQUUX => {} | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/consts-opaque.rs:142:9 @@ -69,7 +69,7 @@ LL | WHOKNOWSQUUX => {} | ^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> error: unreachable pattern --> $DIR/consts-opaque.rs:48:9 @@ -166,3 +166,91 @@ LL | WRAPQUUX => {}, Wrap(_) => todo!() error: aborting due to 10 previous errors; 8 warnings emitted For more information about this error, try `rustc --explain E0004`. +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:96:9 + | +LL | QUUX => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:98:9 + | +LL | QUUX => {} + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:108:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:110:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:117:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:127:9 + | +LL | WRAPQUUX => {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:139:9 + | +LL | WHOKNOWSQUUX => {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/consts-opaque.rs:142:9 + | +LL | WHOKNOWSQUUX => {} + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr index 304435cb21e..4c434192431 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr @@ -43,18 +43,18 @@ help: you might want to use `if let` to ignore the variant that isn't matched LL | if let None = x { todo!() }; | ++ +++++++++++ -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered --> $DIR/empty-match-check-notes.rs:45:11 | LL | match 0u8 { - | ^^^ pattern `_` not covered + | ^^^ pattern `0_u8..=u8::MAX` not covered | = note: the matched value is of type `u8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, -LL + _ => todo!() +LL + 0_u8..=u8::MAX => todo!() | error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr index 40494b726f0..45f715dc7b2 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr @@ -42,18 +42,18 @@ help: you might want to use `if let` to ignore the variant that isn't matched LL | if let None = x { todo!() }; | ++ +++++++++++ -error[E0004]: non-exhaustive patterns: `_` not covered +error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered --> $DIR/empty-match-check-notes.rs:45:11 | LL | match 0u8 { - | ^^^ pattern `_` not covered + | ^^^ pattern `0_u8..=u8::MAX` not covered | = note: the matched value is of type `u8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, -LL + _ => todo!() +LL + 0_u8..=u8::MAX => todo!() | error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.rs b/tests/ui/pattern/usefulness/empty-match-check-notes.rs index ee9ff3dcf90..c30cdfc2e4f 100644 --- a/tests/ui/pattern/usefulness/empty-match-check-notes.rs +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.rs @@ -43,10 +43,10 @@ fn empty_foreign_enum_private(x: Option<empty::SecretlyUninhabitedForeignStruct> fn main() { match 0u8 { - //~^ ERROR `_` not covered + //~^ ERROR not covered //~| NOTE the matched value is of type //~| NOTE match arms with guards don't count towards exhaustivity - //~| NOTE pattern `_` not covered + //~| NOTE not covered _ if false => {} } } diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index 9c3bebd7797..5f895fab0fb 100644 --- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -7,9 +7,36 @@ LL | match_no_arms!(0u8); = note: the matched value is of type `u8` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern -error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty +error[E0004]: non-exhaustive patterns: type `i8` is non-empty --> $DIR/empty-match.rs:47:20 | +LL | match_no_arms!(0i8); + | ^^^ + | + = note: the matched value is of type `i8` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `usize` is non-empty + --> $DIR/empty-match.rs:48:20 + | +LL | match_no_arms!(0usize); + | ^^^^^^ + | + = note: the matched value is of type `usize` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `isize` is non-empty + --> $DIR/empty-match.rs:49:20 + | +LL | match_no_arms!(0isize); + | ^^^^^^ + | + = note: the matched value is of type `isize` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty + --> $DIR/empty-match.rs:50:20 + | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ | @@ -22,7 +49,7 @@ LL | struct NonEmptyStruct1; = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:48:20 + --> $DIR/empty-match.rs:51:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +63,7 @@ LL | struct NonEmptyStruct2(bool); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:49:20 + --> $DIR/empty-match.rs:52:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +77,7 @@ LL | union NonEmptyUnion1 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:50:20 + --> $DIR/empty-match.rs:53:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +91,7 @@ LL | union NonEmptyUnion2 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:51:20 + --> $DIR/empty-match.rs:54:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -80,7 +107,7 @@ LL | Foo(bool), = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:52:20 + --> $DIR/empty-match.rs:55:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -98,7 +125,7 @@ LL | Bar, = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:53:20 + --> $DIR/empty-match.rs:56:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -121,22 +148,64 @@ LL | V5, = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms -error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:55:24 +error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered + --> $DIR/empty-match.rs:58:24 | LL | match_guarded_arm!(0u8); - | ^^^ pattern `_` not covered + | ^^^ pattern `0_u8..=u8::MAX` not covered | = note: the matched value is of type `u8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, +LL + 0_u8..=u8::MAX => todo!() + | + +error[E0004]: non-exhaustive patterns: `i8::MIN..=i8::MAX` not covered + --> $DIR/empty-match.rs:59:24 + | +LL | match_guarded_arm!(0i8); + | ^^^ pattern `i8::MIN..=i8::MAX` not covered + | + = note: the matched value is of type `i8` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + i8::MIN..=i8::MAX => todo!() + | + +error[E0004]: non-exhaustive patterns: `0_usize..` not covered + --> $DIR/empty-match.rs:60:24 + | +LL | match_guarded_arm!(0usize); + | ^^^^^^ pattern `0_usize..` not covered + | + = note: the matched value is of type `usize` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + 0_usize.. => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:61:24 + | +LL | match_guarded_arm!(0isize); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:56:24 + --> $DIR/empty-match.rs:62:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered @@ -155,7 +224,7 @@ LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:57:24 + --> $DIR/empty-match.rs:63:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered @@ -174,7 +243,7 @@ LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:58:24 + --> $DIR/empty-match.rs:64:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered @@ -193,7 +262,7 @@ LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:59:24 + --> $DIR/empty-match.rs:65:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered @@ -212,7 +281,7 @@ LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:60:24 + --> $DIR/empty-match.rs:66:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -233,7 +302,7 @@ LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:61:24 + --> $DIR/empty-match.rs:67:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -256,7 +325,7 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:62:24 + --> $DIR/empty-match.rs:68:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -284,6 +353,6 @@ LL ~ _ if false => {}, LL + _ => todo!() | -error: aborting due to 16 previous errors +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr index 9c3bebd7797..5f895fab0fb 100644 --- a/tests/ui/pattern/usefulness/empty-match.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -7,9 +7,36 @@ LL | match_no_arms!(0u8); = note: the matched value is of type `u8` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern -error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty +error[E0004]: non-exhaustive patterns: type `i8` is non-empty --> $DIR/empty-match.rs:47:20 | +LL | match_no_arms!(0i8); + | ^^^ + | + = note: the matched value is of type `i8` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `usize` is non-empty + --> $DIR/empty-match.rs:48:20 + | +LL | match_no_arms!(0usize); + | ^^^^^^ + | + = note: the matched value is of type `usize` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `isize` is non-empty + --> $DIR/empty-match.rs:49:20 + | +LL | match_no_arms!(0isize); + | ^^^^^^ + | + = note: the matched value is of type `isize` + = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern + +error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty + --> $DIR/empty-match.rs:50:20 + | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ | @@ -22,7 +49,7 @@ LL | struct NonEmptyStruct1; = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:48:20 + --> $DIR/empty-match.rs:51:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ @@ -36,7 +63,7 @@ LL | struct NonEmptyStruct2(bool); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:49:20 + --> $DIR/empty-match.rs:52:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +77,7 @@ LL | union NonEmptyUnion1 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:50:20 + --> $DIR/empty-match.rs:53:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +91,7 @@ LL | union NonEmptyUnion2 { = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:51:20 + --> $DIR/empty-match.rs:54:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -80,7 +107,7 @@ LL | Foo(bool), = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:52:20 + --> $DIR/empty-match.rs:55:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -98,7 +125,7 @@ LL | Bar, = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:53:20 + --> $DIR/empty-match.rs:56:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -121,22 +148,64 @@ LL | V5, = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms -error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:55:24 +error[E0004]: non-exhaustive patterns: `0_u8..=u8::MAX` not covered + --> $DIR/empty-match.rs:58:24 | LL | match_guarded_arm!(0u8); - | ^^^ pattern `_` not covered + | ^^^ pattern `0_u8..=u8::MAX` not covered | = note: the matched value is of type `u8` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ _ if false => {}, +LL + 0_u8..=u8::MAX => todo!() + | + +error[E0004]: non-exhaustive patterns: `i8::MIN..=i8::MAX` not covered + --> $DIR/empty-match.rs:59:24 + | +LL | match_guarded_arm!(0i8); + | ^^^ pattern `i8::MIN..=i8::MAX` not covered + | + = note: the matched value is of type `i8` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + i8::MIN..=i8::MAX => todo!() + | + +error[E0004]: non-exhaustive patterns: `0_usize..` not covered + --> $DIR/empty-match.rs:60:24 + | +LL | match_guarded_arm!(0usize); + | ^^^^^^ pattern `0_usize..` not covered + | + = note: the matched value is of type `usize` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + 0_usize.. => todo!() + | + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match.rs:61:24 + | +LL | match_guarded_arm!(0isize); + | ^^^^^^ pattern `_` not covered + | + = note: the matched value is of type `isize` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:56:24 + --> $DIR/empty-match.rs:62:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered @@ -155,7 +224,7 @@ LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:57:24 + --> $DIR/empty-match.rs:63:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered @@ -174,7 +243,7 @@ LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:58:24 + --> $DIR/empty-match.rs:64:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered @@ -193,7 +262,7 @@ LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:59:24 + --> $DIR/empty-match.rs:65:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered @@ -212,7 +281,7 @@ LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:60:24 + --> $DIR/empty-match.rs:66:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered @@ -233,7 +302,7 @@ LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:61:24 + --> $DIR/empty-match.rs:67:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered @@ -256,7 +325,7 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:62:24 + --> $DIR/empty-match.rs:68:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered @@ -284,6 +353,6 @@ LL ~ _ if false => {}, LL + _ => todo!() | -error: aborting due to 16 previous errors +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs index 321f24adc46..20ab702c9c8 100644 --- a/tests/ui/pattern/usefulness/empty-match.rs +++ b/tests/ui/pattern/usefulness/empty-match.rs @@ -44,6 +44,9 @@ fn nonempty() { } match_no_arms!(0u8); //~ ERROR type `u8` is non-empty + match_no_arms!(0i8); //~ ERROR type `i8` is non-empty + match_no_arms!(0usize); //~ ERROR type `usize` is non-empty + match_no_arms!(0isize); //~ ERROR type `isize` is non-empty match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty @@ -52,7 +55,10 @@ fn nonempty() { match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - match_guarded_arm!(0u8); //~ ERROR `_` not covered + match_guarded_arm!(0u8); //~ ERROR `0_u8..=u8::MAX` not covered + match_guarded_arm!(0i8); //~ ERROR `i8::MIN..=i8::MAX` not covered + match_guarded_arm!(0usize); //~ ERROR `0_usize..` not covered + match_guarded_arm!(0isize); //~ ERROR `_` not covered match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered diff --git a/tests/ui/pattern/usefulness/match-privately-empty.stderr b/tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr index d760790dff6..708a1511244 100644 --- a/tests/ui/pattern/usefulness/match-privately-empty.stderr +++ b/tests/ui/pattern/usefulness/match-privately-empty.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered - --> $DIR/match-privately-empty.rs:13:11 + --> $DIR/match-privately-empty.rs:16:11 | LL | match private::DATA { | ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered @@ -12,7 +12,7 @@ note: `Option<Private>` defined here = note: the matched value is of type `Option<Private>` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ }) => {}, +LL ~ Some(private::Private { misc: false, .. }) => {}, LL + Some(Private { misc: true, .. }) => todo!() | diff --git a/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr new file mode 100644 index 00000000000..a6ce02c0c3c --- /dev/null +++ b/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr @@ -0,0 +1,30 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/match-privately-empty.rs:3:46 + | +LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 <https://github.com/rust-lang/rust/issues/119612> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered + --> $DIR/match-privately-empty.rs:16:11 + | +LL | match private::DATA { + | ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered + | +note: `Option<Private>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<Private>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Some(private::Private { misc: false, .. }) => {}, +LL + Some(Private { misc: true, .. }) => todo!() + | + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/match-privately-empty.rs b/tests/ui/pattern/usefulness/match-privately-empty.rs index 315eb03d165..67a9aa2e916 100644 --- a/tests/ui/pattern/usefulness/match-privately-empty.rs +++ b/tests/ui/pattern/usefulness/match-privately-empty.rs @@ -1,5 +1,8 @@ +// revisions: min_exhaustive_patterns exhaustive_patterns +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![feature(never_type)] -#![feature(exhaustive_patterns)] mod private { pub struct Private { @@ -11,11 +14,8 @@ mod private { fn main() { match private::DATA { - //~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered + //~^ ERROR non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered None => {} - Some(private::Private { - misc: false, - .. - }) => {} + Some(private::Private { misc: false, .. }) => {} } } diff --git a/tests/ui/pattern/usefulness/slice_of_empty.stderr b/tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr index d56360d4cec..9770f680b2d 100644 --- a/tests/ui/pattern/usefulness/slice_of_empty.stderr +++ b/tests/ui/pattern/usefulness/slice_of_empty.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/slice_of_empty.rs:18:11 + --> $DIR/slice_of_empty.rs:22:11 | LL | match nevers { | ^^^^^^ pattern `&[]` not covered diff --git a/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr new file mode 100644 index 00000000000..3b9e71f50d5 --- /dev/null +++ b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr @@ -0,0 +1,38 @@ +warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/slice_of_empty.rs:3:46 + | +LL | #![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #119612 <https://github.com/rust-lang/rust/issues/119612> for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered + --> $DIR/slice_of_empty.rs:11:11 + | +LL | match nevers { + | ^^^^^^ pattern `&[_, ..]` not covered + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ &[] => (), +LL ~ &[_, ..] => todo!(), + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered + --> $DIR/slice_of_empty.rs:22:11 + | +LL | match nevers { + | ^^^^^^ patterns `&[]` and `&[_, _, ..]` not covered + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ &[_] => (), +LL ~ &[] | &[_, _, ..] => todo!(), + | + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/slice_of_empty.rs b/tests/ui/pattern/usefulness/slice_of_empty.rs index 3cbd0eba57f..5f64dd3fecc 100644 --- a/tests/ui/pattern/usefulness/slice_of_empty.rs +++ b/tests/ui/pattern/usefulness/slice_of_empty.rs @@ -1,11 +1,15 @@ +// revisions: min_exhaustive_patterns exhaustive_patterns +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +//[min_exhaustive_patterns]~^ WARN the feature `min_exhaustive_patterns` is incomplete #![feature(never_type)] -#![feature(exhaustive_patterns)] #![deny(unreachable_patterns)] fn main() {} fn foo(nevers: &[!]) { match nevers { + //[min_exhaustive_patterns]~^ ERROR non-exhaustive patterns: `&[_, ..]` not covered &[] => (), }; @@ -16,7 +20,8 @@ fn foo(nevers: &[!]) { }; match nevers { - //~^ ERROR non-exhaustive patterns: `&[]` not covered + //[exhaustive_patterns]~^ ERROR non-exhaustive patterns: `&[]` not covered + //[min_exhaustive_patterns]~^^ ERROR non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered &[_] => (), }; } diff --git a/tests/ui/precondition-checks/misaligned-slice.rs b/tests/ui/precondition-checks/misaligned-slice.rs new file mode 100644 index 00000000000..c961c800352 --- /dev/null +++ b/tests/ui/precondition-checks/misaligned-slice.rs @@ -0,0 +1,11 @@ +// run-fail +// compile-flags: -Copt-level=3 -Cdebug-assertions=yes +// error-pattern: unsafe precondition(s) violated: slice::from_raw_parts +// ignore-debug +// ignore-wasm32-bare no panic messages + +fn main() { + unsafe { + let _s: &[u64] = std::slice::from_raw_parts(1usize as *const u64, 0); + } +} diff --git a/tests/ui/precondition-checks/null-slice.rs b/tests/ui/precondition-checks/null-slice.rs new file mode 100644 index 00000000000..1e67e7f5fb1 --- /dev/null +++ b/tests/ui/precondition-checks/null-slice.rs @@ -0,0 +1,11 @@ +// run-fail +// compile-flags: -Copt-level=3 -Cdebug-assertions=yes +// error-pattern: unsafe precondition(s) violated: slice::from_raw_parts +// ignore-debug +// ignore-wasm32-bare no panic messages + +fn main() { + unsafe { + let _s: &[u8] = std::slice::from_raw_parts(std::ptr::null(), 0); + } +} diff --git a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs new file mode 100644 index 00000000000..1366ba28f1c --- /dev/null +++ b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs @@ -0,0 +1,12 @@ +// run-fail +// compile-flags: -Copt-level=3 -Cdebug-assertions=yes +// error-pattern: unsafe precondition(s) violated: hint::assert_unchecked +// ignore-debug +// ignore-wasm32-bare no panic messages + +fn main() { + unsafe { + let sli: &[u8] = &[0]; + sli.get_unchecked(1); + } +} diff --git a/tests/ui/print_type_sizes/niche-filling.rs b/tests/ui/print_type_sizes/niche-filling.rs index 5ee5085ddc8..feb9643850d 100644 --- a/tests/ui/print_type_sizes/niche-filling.rs +++ b/tests/ui/print_type_sizes/niche-filling.rs @@ -1,5 +1,5 @@ -// compile-flags: -Z print-type-sizes --crate-type=lib -// ignore-debug debug assertions will print more types +// compile-flags: -Z print-type-sizes --crate-type lib +// ignore-debug: debug assertions will print more types // build-pass // ignore-pass // ^-- needed because `--pass check` does not emit the output needed. diff --git a/tests/ui/print_type_sizes/niche-filling.stdout b/tests/ui/print_type_sizes/niche-filling.stdout index b53b8936603..53a58ccc4ee 100644 --- a/tests/ui/print_type_sizes/niche-filling.stdout +++ b/tests/ui/print_type_sizes/niche-filling.stdout @@ -70,6 +70,10 @@ print-type-size field `.a`: 4 bytes print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes print-type-size type: `std::num::NonZero<u32>`: 4 bytes, alignment: 4 bytes print-type-size field `.0`: 4 bytes +print-type-size type: `std::option::Option<std::num::NonZero<u32>>`: 4 bytes, alignment: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes print-type-size type: `Enum4<(), (), (), MyOption<u8>>`: 2 bytes, alignment: 1 bytes print-type-size variant `Four`: 2 bytes print-type-size field `.0`: 2 bytes diff --git a/tests/ui/privacy/associated-item-privacy-trait.stderr b/tests/ui/privacy/associated-item-privacy-trait.stderr index 4e9dfa4a835..f79c4cff72f 100644 --- a/tests/ui/privacy/associated-item-privacy-trait.stderr +++ b/tests/ui/privacy/associated-item-privacy-trait.stderr @@ -75,17 +75,6 @@ LL | priv_trait::mac!(); | = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: trait `PrivTr` is private - --> $DIR/associated-item-privacy-trait.rs:29:14 - | -LL | impl PrivTr for u8 {} - | ^^^^^^ private trait -... -LL | priv_trait::mac!(); - | ------------------ in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) - error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-trait.rs:46:21 | @@ -328,5 +317,16 @@ LL | priv_parent_substs::mac!(); | = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) +error: trait `PrivTr` is private + --> $DIR/associated-item-privacy-trait.rs:29:14 + | +LL | impl PrivTr for u8 {} + | ^^^^^^ private trait +... +LL | priv_trait::mac!(); + | ------------------ in this macro invocation + | + = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) + error: aborting due to 30 previous errors diff --git a/tests/ui/privacy/associated-item-privacy-type-binding.stderr b/tests/ui/privacy/associated-item-privacy-type-binding.stderr index de9893816fa..52bfa3c2ab8 100644 --- a/tests/ui/privacy/associated-item-privacy-type-binding.stderr +++ b/tests/ui/privacy/associated-item-privacy-type-binding.stderr @@ -32,10 +32,10 @@ LL | priv_trait::mac1!(); = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private - --> $DIR/associated-item-privacy-type-binding.rs:16:31 + --> $DIR/associated-item-privacy-type-binding.rs:16:37 | LL | trait InSignatureTr2: PubTr<AssocTy = u8> {} - | ^^^^^^^^^^^^^^^^^^^ private trait + | ^^^^^^^^^^^^ private trait ... LL | priv_trait::mac1!(); | ------------------- in this macro invocation @@ -164,10 +164,10 @@ LL | priv_parent_substs::mac!(); = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `Priv` is private - --> $DIR/associated-item-privacy-type-binding.rs:56:31 + --> $DIR/associated-item-privacy-type-binding.rs:56:37 | LL | trait InSignatureTr2: PubTr<AssocTy = u8> {} - | ^^^^^^^^^^^^^^^^^^^ private type + | ^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation diff --git a/tests/ui/issues/auxiliary/private-trait-xc.rs b/tests/ui/privacy/auxiliary/private-trait-xc.rs index 481a48a7cd8..481a48a7cd8 100644 --- a/tests/ui/issues/auxiliary/private-trait-xc.rs +++ b/tests/ui/privacy/auxiliary/private-trait-xc.rs diff --git a/tests/ui/issues/issue-11593.rs b/tests/ui/privacy/issue-11593.rs index 8bf034e8203..8bf034e8203 100644 --- a/tests/ui/issues/issue-11593.rs +++ b/tests/ui/privacy/issue-11593.rs diff --git a/tests/ui/issues/issue-11593.stderr b/tests/ui/privacy/issue-11593.stderr index 8262bc9321a..8262bc9321a 100644 --- a/tests/ui/issues/issue-11593.stderr +++ b/tests/ui/privacy/issue-11593.stderr diff --git a/tests/ui/privacy/private-type-in-interface.stderr b/tests/ui/privacy/private-type-in-interface.stderr index a5e80d6962d..091cae42dea 100644 --- a/tests/ui/privacy/private-type-in-interface.stderr +++ b/tests/ui/privacy/private-type-in-interface.stderr @@ -47,10 +47,10 @@ LL | fn g() -> impl Tr2<m::Alias> { 0 } | ^^^^^^^^^^^^^^^^^^ private type error: type `Priv` is private - --> $DIR/private-type-in-interface.rs:28:16 + --> $DIR/private-type-in-interface.rs:28:11 | LL | fn g() -> impl Tr2<m::Alias> { 0 } - | ^^^^^^^^^^^^^ private type + | ^^^^^^^^^^^^^^^^^^ private type error: type `ext::Priv` is private --> $DIR/private-type-in-interface.rs:30:15 @@ -59,10 +59,10 @@ LL | fn g_ext() -> impl Tr2<ext::Alias> { 0 } | ^^^^^^^^^^^^^^^^^^^^ private type error: type `ext::Priv` is private - --> $DIR/private-type-in-interface.rs:30:20 + --> $DIR/private-type-in-interface.rs:30:15 | LL | fn g_ext() -> impl Tr2<ext::Alias> { 0 } - | ^^^^^^^^^^^^^^^ private type + | ^^^^^^^^^^^^^^^^^^^^ private type error: aborting due to 11 previous errors diff --git a/tests/ui/privacy/projections.rs b/tests/ui/privacy/projections.rs new file mode 100644 index 00000000000..0e6590de4f5 --- /dev/null +++ b/tests/ui/privacy/projections.rs @@ -0,0 +1,60 @@ +mod m { + struct Priv; + pub type Leak = Priv; //~ WARN: `Priv` is more private than the item `Leak` +} + +trait Trait { + type A<T>; +} + +impl Trait for u8 { + type A<T> = u8; +} + +fn check() -> <u8 as Trait>::A<m::Leak> { + //~^ ERROR: `Priv` is private + 0 +} + +trait Trait2 { + type A<T>; +} + +impl Trait2 for u8 { + type A<T> = m::Leak; + //~^ ERROR: `Priv` is private + //~| ERROR: private type `Priv` in public interface +} + +fn check2() -> <u8 as Trait2>::A<u32> { + //~^ ERROR: `Priv` is private + todo!() +} + +trait Trait3 { + type A<T: Trait>; +} + +impl Trait3 for u8 { + type A<T: Trait> = T::A<m::Leak>; + //~^ ERROR: `Priv` is private + //~| ERROR: private type `Priv` in public interface +} + +fn check3() -> <u8 as Trait3>::A<u8> { + todo!() +} + +trait Trait4 { + type A<T: Trait3>; +} + +impl Trait4 for u8 { + type A<T: Trait3> = T::A<u8>; +} + +fn check4() -> <u8 as Trait4>::A<u8> { + todo!() +} + +fn main() {} diff --git a/tests/ui/privacy/projections.stderr b/tests/ui/privacy/projections.stderr new file mode 100644 index 00000000000..010d77998e3 --- /dev/null +++ b/tests/ui/privacy/projections.stderr @@ -0,0 +1,62 @@ +warning: type `Priv` is more private than the item `Leak` + --> $DIR/projections.rs:3:5 + | +LL | pub type Leak = Priv; + | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` + | +note: but type `Priv` is only usable at visibility `pub(self)` + --> $DIR/projections.rs:2:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + +error[E0446]: private type `Priv` in public interface + --> $DIR/projections.rs:24:5 + | +LL | struct Priv; + | ----------- `Priv` declared as private +... +LL | type A<T> = m::Leak; + | ^^^^^^^^^ can't leak private type + +error[E0446]: private type `Priv` in public interface + --> $DIR/projections.rs:39:5 + | +LL | struct Priv; + | ----------- `Priv` declared as private +... +LL | type A<T: Trait> = T::A<m::Leak>; + | ^^^^^^^^^^^^^^^^ can't leak private type + +error: type `Priv` is private + --> $DIR/projections.rs:14:15 + | +LL | fn check() -> <u8 as Trait>::A<m::Leak> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/projections.rs:29:39 + | +LL | fn check2() -> <u8 as Trait2>::A<u32> { + | _______________________________________^ +LL | | +LL | | todo!() +LL | | } + | |_^ private type + +error: type `Priv` is private + --> $DIR/projections.rs:24:17 + | +LL | type A<T> = m::Leak; + | ^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/projections.rs:39:24 + | +LL | type A<T: Trait> = T::A<m::Leak>; + | ^^^^^^^^^^^^^ private type + +error: aborting due to 6 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/projections2.rs b/tests/ui/privacy/projections2.rs new file mode 100644 index 00000000000..1afbf6d196e --- /dev/null +++ b/tests/ui/privacy/projections2.rs @@ -0,0 +1,38 @@ +mod m { + use super::*; + struct Priv; + pub type Leak = Priv; //~ WARN: `Priv` is more private than the item `Leak` + + trait Trait3 { + type A<T: Trait>; + } + + impl Trait3 for u8 { + type A<T: Trait> = T::A<Leak>; + } + + pub trait Trait4 { + type A<T: Trait>; + } + + impl Trait4 for u8 { + type A<T: Trait> = <u8 as Trait3>::A<T>; + //~^ ERROR: private associated type `Trait3::A` in public interface + //~| ERROR: private trait `Trait3` in public interface + } +} + +pub trait Trait { + type A<T>; +} + +impl Trait for u8 { + type A<T> = u8; +} +use m::*; + +fn check4() -> <u8 as Trait4>::A<u8> { + todo!() +} + +fn main() {} diff --git a/tests/ui/privacy/projections2.stderr b/tests/ui/privacy/projections2.stderr new file mode 100644 index 00000000000..6eae9643c5a --- /dev/null +++ b/tests/ui/privacy/projections2.stderr @@ -0,0 +1,34 @@ +warning: type `Priv` is more private than the item `Leak` + --> $DIR/projections2.rs:4:5 + | +LL | pub type Leak = Priv; + | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` + | +note: but type `Priv` is only usable at visibility `pub(self)` + --> $DIR/projections2.rs:3:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + +error[E0446]: private associated type `Trait3::A` in public interface + --> $DIR/projections2.rs:19:9 + | +LL | type A<T: Trait>; + | ---------------- `Trait3::A` declared as private +... +LL | type A<T: Trait> = <u8 as Trait3>::A<T>; + | ^^^^^^^^^^^^^^^^ can't leak private associated type + +error[E0446]: private trait `Trait3` in public interface + --> $DIR/projections2.rs:19:9 + | +LL | trait Trait3 { + | ------------ `Trait3` declared as private +... +LL | type A<T: Trait> = <u8 as Trait3>::A<T>; + | ^^^^^^^^^^^^^^^^ can't leak private trait + +error: aborting due to 2 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.fixed b/tests/ui/privacy/sealed-traits/re-exported-trait.fixed index 79b6a6516ab..6de7b865a99 100644 --- a/tests/ui/privacy/sealed-traits/re-exported-trait.fixed +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] pub mod a { pub use self::b::Trait; diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.rs b/tests/ui/privacy/sealed-traits/re-exported-trait.rs index 5f96dfdcbd6..bf07d666dff 100644 --- a/tests/ui/privacy/sealed-traits/re-exported-trait.rs +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] pub mod a { pub use self::b::Trait; diff --git a/tests/ui/privacy/sealed-traits/re-exported-trait.stderr b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr index 9f2291e6825..6e2f36e3f38 100644 --- a/tests/ui/privacy/sealed-traits/re-exported-trait.stderr +++ b/tests/ui/privacy/sealed-traits/re-exported-trait.stderr @@ -1,11 +1,11 @@ error[E0603]: module `b` is private - --> $DIR/re-exported-trait.rs:11:9 + --> $DIR/re-exported-trait.rs:12:9 | LL | impl a::b::Trait for S {} | ^ private module | note: the module `b` is defined here - --> $DIR/re-exported-trait.rs:5:5 + --> $DIR/re-exported-trait.rs:6:5 | LL | mod b { | ^^^^^ diff --git a/tests/ui/privacy/struct-field-type.rs b/tests/ui/privacy/struct-field-type.rs new file mode 100644 index 00000000000..6a4a19297e1 --- /dev/null +++ b/tests/ui/privacy/struct-field-type.rs @@ -0,0 +1,10 @@ +mod m { + struct Priv; + pub type Leak = Priv; //~ WARN: `Priv` is more private than the item `Leak` +} + +struct S { + field: m::Leak, //~ ERROR: `Priv` is private +} + +fn main() {} diff --git a/tests/ui/privacy/struct-field-type.stderr b/tests/ui/privacy/struct-field-type.stderr new file mode 100644 index 00000000000..854ff6a98a4 --- /dev/null +++ b/tests/ui/privacy/struct-field-type.stderr @@ -0,0 +1,21 @@ +warning: type `Priv` is more private than the item `Leak` + --> $DIR/struct-field-type.rs:3:5 + | +LL | pub type Leak = Priv; + | ^^^^^^^^^^^^^ type alias `Leak` is reachable at visibility `pub(crate)` + | +note: but type `Priv` is only usable at visibility `pub(self)` + --> $DIR/struct-field-type.rs:2:5 + | +LL | struct Priv; + | ^^^^^^^^^^^ + = note: `#[warn(private_interfaces)]` on by default + +error: type `Priv` is private + --> $DIR/struct-field-type.rs:7:5 + | +LL | field: m::Leak, + | ^^^^^ private type + +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed index ae5f9f86726..a61c868ed0a 100644 --- a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed +++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.fixed @@ -1,6 +1,7 @@ // run-rustfix #[derive(Debug)] //~ ERROR `derive` attribute cannot be used at crate level +#[allow(dead_code)] struct Test {} fn main() {} diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs index 639c64f8827..403f4470de7 100644 --- a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs +++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.rs @@ -1,6 +1,7 @@ // run-rustfix #![derive(Debug)] //~ ERROR `derive` attribute cannot be used at crate level +#[allow(dead_code)] struct Test {} fn main() {} diff --git a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr index f62cdd14b87..09908160542 100644 --- a/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr +++ b/tests/ui/proc-macro/issue-89566-suggest-fix-invalid-top-level-macro-attr.stderr @@ -3,6 +3,7 @@ error: `derive` attribute cannot be used at crate level | LL | #![derive(Debug)] | ^^^^^^^^^^^^^^^^^ +LL | #[allow(dead_code)] LL | struct Test {} | ---- the inner attribute doesn't annotate this struct | diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs index d364c467714..2aa390bfd39 100644 --- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs +++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.rs @@ -5,13 +5,13 @@ fn a<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) where 'b: 'a { fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { // Illegal now because there is no `'b:'a` declaration. - *x = *y; + *x = *y; //~ ERROR: lifetime may not live long enough } fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { // Here we try to call `foo` but do not know that `'a` and `'b` are // related as required. - a(x, y); + a(x, y); //~ ERROR: lifetime may not live long enough } fn d() { diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index d8269514bef..5a02d01b4e1 100644 --- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -9,6 +9,35 @@ LL | let _: fn(&mut &isize, &mut &isize) = a; = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `&isize` + = note: mutable references are invariant over their type parameter + = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs index 60dafdd528c..baf1693b0cc 100644 --- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs +++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.rs @@ -6,14 +6,14 @@ fn a<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) where fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { // Illegal now because there is no `'b:'a` declaration. - *x = *y; + *x = *y; //~ ERROR: lifetime may not live long enough *z = *y; } fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { // Here we try to call `foo` but do not know that `'a` and `'b` are // related as required. - a(x, y, z); + a(x, y, z); //~ ERROR: lifetime may not live long enough } fn d() { diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index e383f352b9e..063ff46bb6c 100644 --- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -9,6 +9,35 @@ LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b _, &'c mut &'d _, &'e mut &'f _)` found fn item `for<'a, 'b, 'c> fn(&'a mut &_, &'b mut &_, &'c mut &_) {a::<'_, '_, '_>}` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:5 + | +LL | fn b<'a, 'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:16:5 + | +LL | fn c<'a,'b, 'c>(x: &mut &'a isize, y: &mut &'b isize, z: &mut &'c isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y, z); + | ^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `&isize` + = note: mutable references are invariant over their type parameter + = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.rs b/tests/ui/regions/regions-lifetime-bounds-on-fns.rs index 177f52fa72d..c7b7b52d50d 100644 --- a/tests/ui/regions/regions-lifetime-bounds-on-fns.rs +++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.rs @@ -5,13 +5,13 @@ fn a<'a, 'b:'a>(x: &mut &'a isize, y: &mut &'b isize) { fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { // Illegal now because there is no `'b:'a` declaration. - *x = *y; + *x = *y; //~ ERROR: lifetime may not live long enough } fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { // Here we try to call `foo` but do not know that `'a` and `'b` are // related as required. - a(x, y); + a(x, y); //~ ERROR: lifetime may not live long enough } fn d() { diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr index 989e91c702b..830a61a21f9 100644 --- a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -9,6 +9,35 @@ LL | let _: fn(&mut &isize, &mut &isize) = a; = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:8:5 + | +LL | fn b<'a, 'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | // Illegal now because there is no `'b:'a` declaration. +LL | *x = *y; + | ^^^^^^^ assignment requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/regions-lifetime-bounds-on-fns.rs:14:5 + | +LL | fn c<'a,'b>(x: &mut &'a isize, y: &mut &'b isize) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | a(x, y); + | ^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `&isize` + = note: mutable references are invariant over their type parameter + = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/regions/regions-no-variance-from-fn-generics.rs b/tests/ui/regions/regions-no-variance-from-fn-generics.rs index 76706a82781..a455d4efd71 100644 --- a/tests/ui/regions/regions-no-variance-from-fn-generics.rs +++ b/tests/ui/regions/regions-no-variance-from-fn-generics.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_variables)] // Issue #12856: a lifetime formal binding introduced by a generic fn // should not upset the variance inference for actual occurrences of diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr index 4f853829279..fbb9ede8aa1 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.default.stderr @@ -5,6 +5,8 @@ LL | fn outer<T: Tr>() { // outer function | - type parameter from outer item LL | const K: u32 = T::C; | ^^^^ use of generic parameter from outer item + | + = note: a `const` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24 @@ -14,6 +16,8 @@ LL | impl<T> Tr for T { // outer impl block LL | const C: u32 = { LL | const I: u32 = T::C; | ^^^^ use of generic parameter from outer item + | + = note: a `const` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20 @@ -22,6 +26,8 @@ LL | struct S<T: Tr>(U32<{ // outer struct | - type parameter from outer item LL | const _: u32 = T::C; | ^^^^ use of generic parameter from outer item + | + = note: a `const` is a separate item from the item that contains it error: aborting due to 3 previous errors diff --git a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr index 1cb55842bc6..60aa94038c3 100644 --- a/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr +++ b/tests/ui/resolve/generic-params-from-outer-item-in-const-item.generic_const_items.stderr @@ -7,6 +7,8 @@ LL | const K: u32 = T::C; | - ^^^^ use of generic parameter from outer item | | | help: try introducing a local generic parameter here: `<T>` + | + = note: a `const` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/generic-params-from-outer-item-in-const-item.rs:19:24 @@ -18,6 +20,8 @@ LL | const I: u32 = T::C; | - ^^^^ use of generic parameter from outer item | | | help: try introducing a local generic parameter here: `<T>` + | + = note: a `const` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/generic-params-from-outer-item-in-const-item.rs:27:20 @@ -28,6 +32,8 @@ LL | const _: u32 = T::C; | - ^^^^ use of generic parameter from outer item | | | help: try introducing a local generic parameter here: `<T>` + | + = note: a `const` is a separate item from the item that contains it error: aborting due to 3 previous errors diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed index e730f94660b..a7ab88fe993 100644 --- a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] #![deny(unused_qualifications)] #![feature(unsized_fn_params)] diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs index 641c892e3de..05936b191ff 100644 --- a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs @@ -1,5 +1,6 @@ // run-rustfix +#![allow(dead_code)] #![deny(unused_qualifications)] #![feature(unsized_fn_params)] diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr index d9c7fd21871..bcda7210712 100644 --- a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr @@ -1,11 +1,11 @@ error: unnecessary qualification - --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:12:6 + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:13:6 | LL | impl ops::Index<str> for A { | ^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:3:9 + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:4:9 | LL | #![deny(unused_qualifications)] | ^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL + impl Index<str> for A { | error: unnecessary qualification - --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:28:6 + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:29:6 | LL | impl inner::Trait<u8> for () {} | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/resolve/issue-12796.rs b/tests/ui/resolve/issue-12796.rs index de3e73437f0..e5dcf964345 100644 --- a/tests/ui/resolve/issue-12796.rs +++ b/tests/ui/resolve/issue-12796.rs @@ -1,7 +1,7 @@ trait Trait { fn outer(&self) { fn inner(_: &Self) { - //~^ ERROR can't use generic parameters from outer item + //~^ ERROR can't use `Self` from outer item } } } diff --git a/tests/ui/resolve/issue-12796.stderr b/tests/ui/resolve/issue-12796.stderr index 6809fd50f74..2305971303a 100644 --- a/tests/ui/resolve/issue-12796.stderr +++ b/tests/ui/resolve/issue-12796.stderr @@ -1,10 +1,10 @@ -error[E0401]: can't use generic parameters from outer item +error[E0401]: can't use `Self` from outer item --> $DIR/issue-12796.rs:3:22 | LL | fn inner(_: &Self) { | ^^^^ | | - | use of generic parameter from outer item + | use of `Self` from outer item | can't use `Self` here error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr index 363bb556478..ca32147d197 100644 --- a/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr +++ b/tests/ui/resolve/issue-65025-extern-static-parent-generics.stderr @@ -6,6 +6,8 @@ LL | unsafe fn foo<A>() { LL | extern "C" { LL | static baz: *const A; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr index f1fe1a6002c..98ffb4567f1 100644 --- a/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr +++ b/tests/ui/resolve/issue-65035-static-with-parent-generics.stderr @@ -6,6 +6,8 @@ LL | fn f<T>() { LL | extern "C" { LL | static a: *const T; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:9:22 @@ -14,6 +16,8 @@ LL | fn g<T: Default>() { | - type parameter from outer item LL | static a: *const T = Default::default(); | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:15:24 @@ -23,6 +27,8 @@ LL | fn h<const N: usize>() { LL | extern "C" { LL | static a: [u8; N]; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:21:20 @@ -31,6 +37,8 @@ LL | fn i<const N: usize>() { | - const parameter from outer item LL | static a: [u8; N] = [0; N]; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error[E0401]: can't use generic parameters from outer item --> $DIR/issue-65035-static-with-parent-generics.rs:21:29 @@ -39,6 +47,8 @@ LL | fn i<const N: usize>() { | - const parameter from outer item LL | static a: [u8; N] = [0; N]; | ^ use of generic parameter from outer item + | + = note: a `static` is a separate item from the item that contains it error: aborting due to 5 previous errors diff --git a/tests/ui/resolve/use-self-in-inner-fn.rs b/tests/ui/resolve/use-self-in-inner-fn.rs index f4dfa4c40ab..62f9dc5664f 100644 --- a/tests/ui/resolve/use-self-in-inner-fn.rs +++ b/tests/ui/resolve/use-self-in-inner-fn.rs @@ -4,8 +4,8 @@ impl A { //~^ NOTE `Self` type implicitly declared here, by this `impl` fn banana(&mut self) { fn peach(this: &Self) { - //~^ ERROR can't use generic parameters from outer item - //~| NOTE use of generic parameter from outer item + //~^ ERROR can't use `Self` from outer item + //~| NOTE use of `Self` from outer item //~| NOTE refer to the type directly here instead } } diff --git a/tests/ui/resolve/use-self-in-inner-fn.stderr b/tests/ui/resolve/use-self-in-inner-fn.stderr index 165e100bf2f..9c388df8bc2 100644 --- a/tests/ui/resolve/use-self-in-inner-fn.stderr +++ b/tests/ui/resolve/use-self-in-inner-fn.stderr @@ -1,4 +1,4 @@ -error[E0401]: can't use generic parameters from outer item +error[E0401]: can't use `Self` from outer item --> $DIR/use-self-in-inner-fn.rs:6:25 | LL | impl A { @@ -7,7 +7,7 @@ LL | impl A { LL | fn peach(this: &Self) { | ^^^^ | | - | use of generic parameter from outer item + | use of `Self` from outer item | refer to the type directly here instead error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.rs b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.rs index 2490909b6a5..715f5874b2c 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.rs @@ -3,8 +3,9 @@ fn main() {} fn attr_in_guard() { match None::<u32> { Some(!) //~ ERROR `!` patterns are experimental + //~^ ERROR: mismatched types if #[deny(unused_mut)] //~ ERROR attributes on expressions are experimental false //~ ERROR a guard on a never pattern will never be run } - match false {} + match false {} //~ ERROR: `bool` is non-empty } diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr index a456b686e56..f16f5e5be87 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-119271-never-arm-attr-in-guard.stderr @@ -1,5 +1,5 @@ error[E0658]: attributes on expressions are experimental - --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:6:16 + --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:7:16 | LL | if #[deny(unused_mut)] | ^^^^^^^^^^^^^^^^^^^ @@ -19,11 +19,34 @@ LL | Some(!) = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: a guard on a never pattern will never be run - --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:7:13 + --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:8:13 | LL | false | ^^^^^ help: remove this guard -error: aborting due to 3 previous errors +error: mismatched types + --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:5:14 + | +LL | Some(!) + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `u32` + +error[E0004]: non-exhaustive patterns: type `bool` is non-empty + --> $DIR/ICE-119271-never-arm-attr-in-guard.rs:10:11 + | +LL | match false {} + | ^^^^^ + | + = note: the matched value is of type `bool` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match false { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0004, E0658. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs index f2e238ecb13..11489ccaacd 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.rs @@ -1,6 +1,7 @@ #![feature(never_patterns)] #![allow(incomplete_features)] +#[derive(Copy, Clone)] enum Void {} fn main() { diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr index b69ba80af88..d9c0f67335c 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/bindings.stderr @@ -1,47 +1,47 @@ error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:16:15 + --> $DIR/bindings.rs:17:15 | LL | Err(&(_a, _b, !)), | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:16:19 + --> $DIR/bindings.rs:17:19 | LL | Err(&(_a, _b, !)), | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:21:25 + --> $DIR/bindings.rs:22:25 | LL | Ok(_ok) | Err(&(_a, _b, !)) => {} | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:21:29 + --> $DIR/bindings.rs:22:29 | LL | Ok(_ok) | Err(&(_a, _b, !)) => {} | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:34:10 + --> $DIR/bindings.rs:35:10 | LL | let (_a, (! | !)) = (true, void); | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:38:9 + --> $DIR/bindings.rs:39:9 | LL | let _a @ ! = void; | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:41:10 + --> $DIR/bindings.rs:42:10 | LL | let (_a @ (), !) = ((), void); | ^^ help: use a wildcard `_` instead error: never patterns cannot contain variable bindings - --> $DIR/bindings.rs:44:14 + --> $DIR/bindings.rs:45:14 | LL | (_b @ (_, !))) = (true, void); | ^^ help: use a wildcard `_` instead diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs index e298112244a..b6da0c20e07 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs @@ -15,18 +15,18 @@ fn no_arms_or_guards(x: Void) { //~^ ERROR a never pattern is always unreachable None => {} } - match None::<Void> { + match None::<Void> { //~ ERROR: `Some(_)` not covered Some(!) if true, //~^ ERROR guard on a never pattern None => {} } - match None::<Void> { + match None::<Void> { //~ ERROR: `Some(_)` not covered Some(!) if true => {} //~^ ERROR a never pattern is always unreachable None => {} } match None::<Void> { - Some(never!()) => {}, + Some(never!()) => {} //~^ ERROR a never pattern is always unreachable None => {} } diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr index bfbc7a1b534..5497252890f 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr @@ -25,11 +25,48 @@ LL | Some(!) if true => {} error: a never pattern is always unreachable --> $DIR/check.rs:29:27 | -LL | Some(never!()) => {}, +LL | Some(never!()) => {} | ^^ | | | this will never be executed | help: remove this expression -error: aborting due to 4 previous errors +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/check.rs:18:11 + | +LL | match None::<Void> { + | ^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option<Void>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<Void>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/check.rs:23:11 + | +LL | match None::<Void> { + | ^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option<Void>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<Void>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs index 31a23fa002c..72ee4d24bb6 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs @@ -2,7 +2,7 @@ //[pass] check-pass //[fail] check-fail #![feature(never_patterns)] -#![feature(exhaustive_patterns)] +#![feature(min_exhaustive_patterns)] #![allow(incomplete_features)] #[derive(Copy, Clone)] @@ -107,7 +107,7 @@ fn never_pattern_typeck_pass(void: Void) { } match (&[] as &[Void]) { [] => {} - [!], + [!, ..], } // Accept on a composite empty type. match None::<&(u32, Void)> { diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs index df8e22abf62..0374cbdbc1f 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs +++ b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.rs @@ -2,7 +2,7 @@ //[normal] check-pass #![feature(never_patterns)] #![allow(incomplete_features)] -#![cfg_attr(exh_pats, feature(exhaustive_patterns))] +#![cfg_attr(exh_pats, feature(min_exhaustive_patterns))] #![allow(dead_code, unreachable_code)] #![deny(unreachable_patterns)] diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr index 910d491baaf..9945041113d 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr @@ -5,7 +5,7 @@ LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLIN | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:24:9 + | +LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr index cadd9be023c..6ac261ae814 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr @@ -5,7 +5,7 @@ LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/cant-hide-behind-doubly-indirect-param.rs:24:9 + | +LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/cant-hide-behind-doubly-indirect-param.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr index e4321cc6a4c..41616fb90fe 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr @@ -5,7 +5,7 @@ LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itse | ^^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:24:9 + | +LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); } + | ^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr index decc29ad67c..99dea5171d1 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr @@ -5,7 +5,7 @@ LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself | ^^^^^^^^^^^^^^^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here @@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)] warning: 1 warning emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]` + --> $DIR/cant-hide-behind-indirect-struct-param.rs:24:9 + | +LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); } + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/cant-hide-behind-indirect-struct-param.rs:7:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr index 080bf5885ba..11163ba70ec 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr @@ -5,7 +5,7 @@ LL | Wrap(CFN1) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> = note: `#[warn(pointer_structural_match)]` on by default warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. @@ -15,7 +15,7 @@ LL | Wrap(CFN2) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:61:14 @@ -24,7 +24,7 @@ LL | Wrap(CFN3) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:70:14 @@ -33,7 +33,7 @@ LL | Wrap(CFN4) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:79:14 @@ -42,7 +42,7 @@ LL | Wrap(CFN5) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:88:14 @@ -51,7 +51,7 @@ LL | Wrap(CFN6) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:97:14 @@ -60,7 +60,7 @@ LL | Wrap(CFN7) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:106:14 @@ -69,7 +69,7 @@ LL | Wrap(CFN8) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:115:14 @@ -78,7 +78,7 @@ LL | Wrap(CFN9) => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. --> $DIR/fn-ptr-is-structurally-matchable.rs:138:9 @@ -87,7 +87,117 @@ LL | CFOO => count += 1, | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: 10 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:43:14 + | +LL | Wrap(CFN1) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:52:14 + | +LL | Wrap(CFN2) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:61:14 + | +LL | Wrap(CFN3) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:70:14 + | +LL | Wrap(CFN4) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:79:14 + | +LL | Wrap(CFN5) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:88:14 + | +LL | Wrap(CFN6) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:97:14 + | +LL | Wrap(CFN7) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:106:14 + | +LL | Wrap(CFN8) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:115:14 + | +LL | Wrap(CFN9) => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/fn-ptr-is-structurally-matchable.rs:138:9 + | +LL | CFOO => count += 1, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: `#[warn(pointer_structural_match)]` on by default + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs index fdb67bcf2d8..374e5d5acd0 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs @@ -10,7 +10,7 @@ // Issue 62307 pointed out a case where the structural-match checking // was too shallow. -#![warn(indirect_structural_match, nontrivial_structural_match)] +#![warn(indirect_structural_match)] // run-pass #[derive(Debug)] diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr index d0f2b820afa..d4ab1ce3ba2 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr @@ -5,13 +5,13 @@ LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details note: the lint level is defined here --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9 | -LL | #![warn(indirect_structural_match, nontrivial_structural_match)] +LL | #![warn(indirect_structural_match)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` @@ -21,9 +21,43 @@ LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> = note: the traits must be derived, manual `impl`s are not sufficient = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details warning: 2 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:31:9 + | +LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); } + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]` + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:38:9 + | +LL | RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); } + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> + = note: the traits must be derived, manual `impl`s are not sufficient + = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details +note: the lint level is defined here + --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9 + | +LL | #![warn(indirect_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr index 4fdfce60bb8..0edcf44c4d7 100644 --- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr +++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr @@ -5,7 +5,7 @@ LL | B(TEST) => println!("matched"), | ^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> note: the lint level is defined here --> $DIR/issue-63479-match-fnptr.rs:8:9 | @@ -19,7 +19,37 @@ LL | TEST2 => println!("matched"), | ^^^^^ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861> + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> warning: 2 warnings emitted +Future incompatibility report: Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:36:7 + | +LL | B(TEST) => println!("matched"), + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> +note: the lint level is defined here + --> $DIR/issue-63479-match-fnptr.rs:8:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +Future breakage diagnostic: +warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details. + --> $DIR/issue-63479-match-fnptr.rs:42:5 + | +LL | TEST2 => println!("matched"), + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362> +note: the lint level is defined here + --> $DIR/issue-63479-match-fnptr.rs:8:9 + | +LL | #![warn(pointer_structural_match)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr new file mode 100644 index 00000000000..4a219ff8b55 --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr @@ -0,0 +1,15 @@ +warning: methods `good_virt` and `good_indirect` are never used + --> $DIR/manual-self-impl-for-unsafe-obj.rs:22:8 + | +LL | trait Good { + | ---- methods in this trait +LL | fn good_virt(&self) -> char { + | ^^^^^^^^^ +... +LL | fn good_indirect(&self) -> char { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr new file mode 100644 index 00000000000..4a219ff8b55 --- /dev/null +++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr @@ -0,0 +1,15 @@ +warning: methods `good_virt` and `good_indirect` are never used + --> $DIR/manual-self-impl-for-unsafe-obj.rs:22:8 + | +LL | trait Good { + | ---- methods in this trait +LL | fn good_virt(&self) -> char { + | ^^^^^^^^^ +... +LL | fn good_indirect(&self) -> char { + | ^^^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs index c7665affb99..c8eee9835fe 100644 --- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs +++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs @@ -19,7 +19,7 @@ trait Bad { } trait Good { - fn good_virt(&self) -> char { + fn good_virt(&self) -> char { //~ WARN methods `good_virt` and `good_indirect` are never used panic!() } fn good_indirect(&self) -> char { diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs index 43e33cbb120..351438a5470 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.rs @@ -7,7 +7,9 @@ use std::arch::asm; //~^ ERROR `#[track_caller]` requires Rust ABI #[naked] extern "C" fn f() { - asm!("", options(noreturn)); + unsafe { + asm!("", options(noreturn)); + } } struct S; @@ -17,7 +19,9 @@ impl S { //~^ ERROR `#[track_caller]` requires Rust ABI #[naked] extern "C" fn g() { - asm!("", options(noreturn)); + unsafe { + asm!("", options(noreturn)); + } } } diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr index 3f7d0df42a0..04c5c649d7f 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr @@ -5,7 +5,7 @@ LL | #[track_caller] | ^^^^^^^^^^^^^^^ error[E0736]: cannot use `#[track_caller]` with `#[naked]` - --> $DIR/error-with-naked.rs:16:5 + --> $DIR/error-with-naked.rs:18:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | #[track_caller] | ^^^^^^^^^^^^^^^ error[E0737]: `#[track_caller]` requires Rust ABI - --> $DIR/error-with-naked.rs:16:5 + --> $DIR/error-with-naked.rs:18:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs index 1374ad935a3..a032a2ca052 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs @@ -12,7 +12,7 @@ fn call(f: impl Fn()) { f() } -fn call_mut(f: impl FnMut()) { +fn call_mut(mut f: impl FnMut()) { f() } diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index 100f2048269..67bfaa4c98c 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -27,10 +27,10 @@ LL | call_mut(foo); = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` - --> $DIR/fn-traits.rs:15:21 + --> $DIR/fn-traits.rs:15:25 | -LL | fn call_mut(f: impl FnMut()) { - | ^^^^^^^ required by this bound in `call_mut` +LL | fn call_mut(mut f: impl FnMut()) { + | ^^^^^^^ required by this bound in `call_mut` error[E0277]: expected a `FnOnce()` closure, found `fn() {foo}` --> $DIR/fn-traits.rs:26:15 @@ -80,10 +80,10 @@ LL | call_mut(foo_unsafe); = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` - --> $DIR/fn-traits.rs:15:21 + --> $DIR/fn-traits.rs:15:25 | -LL | fn call_mut(f: impl FnMut()) { - | ^^^^^^^ required by this bound in `call_mut` +LL | fn call_mut(mut f: impl FnMut()) { + | ^^^^^^^ required by this bound in `call_mut` error[E0277]: expected a `FnOnce()` closure, found `unsafe fn() {foo_unsafe}` --> $DIR/fn-traits.rs:32:15 diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr index d70b0d66177..14c41f3e01d 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method-fail.stderr @@ -4,5 +4,19 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 { | ^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closure-trait-method-fail.rs:15:5 + | +LL | x(()) + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 { + | ++++++++++++++++++++++++++++++++ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr index 1642de78692..8fe11fffbf9 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closure-trait-method.stderr @@ -4,5 +4,19 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 { | ^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closure-trait-method.rs:15:5 + | +LL | x(()) + | ^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 { + | ++++++++++++++++++++++++++++++++ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr index 2e448c64d7a..b66b27ad2bd 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-closures.stderr @@ -22,5 +22,45 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 { | ^^^^^^^^^^ -error: aborting due to 4 previous errors +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:12:5 + | +LL | f() * 7 + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | F: ~const FnOnce() -> u8 + ~const std::ops::Fn<()>, + | +++++++++++++++++++++++++ + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:24:5 + | +LL | f() + f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn answer<F: ~const Fn() -> u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 { + | +++++++++++++++++++++++++ + +error[E0015]: cannot call non-const closure in constant functions + --> $DIR/const-closures.rs:24:11 + | +LL | f() + f() + | ^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable +help: consider further restricting this bound + | +LL | const fn answer<F: ~const Fn() -> u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 { + | +++++++++++++++++++++++++ + +error: aborting due to 7 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs index b3977e6cede..2468d51cfdd 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.rs @@ -30,8 +30,7 @@ fn non_const_context() { #[unstable(feature = "none", issue = "none")] const fn const_context() { Unstable::func(); - // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is - // not const-stable. + //[stable]~^ ERROR not yet stable as a const fn Foo::func(); //[unstable]~^ ERROR not yet stable as a const fn // ^ fails, because the `foo` feature is not active @@ -42,8 +41,7 @@ const fn const_context() { pub const fn const_context_not_const_stable() { //[stable]~^ ERROR function has missing const stability attribute Unstable::func(); - // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is - // not const-stable. + //[stable]~^ ERROR not yet stable as a const fn Foo::func(); //[unstable]~^ ERROR not yet stable as a const fn // ^ fails, because the `foo` feature is not active @@ -53,7 +51,7 @@ pub const fn const_context_not_const_stable() { #[rustc_const_stable(feature = "cheese", since = "1.0.0")] const fn stable_const_context() { Unstable::func(); - //[unstable]~^ ERROR not yet stable as a const fn + //~^ ERROR not yet stable as a const fn Foo::func(); //[unstable]~^ ERROR not yet stable as a const fn const_context_not_const_stable() diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr index a1aca762ef4..95129539770 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.stable.stderr @@ -10,16 +10,40 @@ LL | | } = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information error: function has missing const stability attribute - --> $DIR/staged-api.rs:42:1 + --> $DIR/staged-api.rs:41:1 | LL | / pub const fn const_context_not_const_stable() { LL | | LL | | Unstable::func(); -LL | | // ^ This is okay regardless of whether the `unstable` feature is enabled, as this function is +LL | | ... | LL | | // ^ fails, because the `foo` feature is not active LL | | } | |_^ -error: aborting due to 2 previous errors +error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:32:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + +error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:43:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(unstable)]` to the crate attributes to enable + +error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn + --> $DIR/staged-api.rs:53:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | + = help: const-stable functions can only call other const-stable functions + +error: aborting due to 5 previous errors diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr index c38d1a81ae7..c9ca15d5b56 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/staged-api.unstable.stderr @@ -1,5 +1,5 @@ error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:35:5 + --> $DIR/staged-api.rs:34:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | Foo::func(); = help: add `#![feature(foo)]` to the crate attributes to enable error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:47:5 + --> $DIR/staged-api.rs:45:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | Foo::func(); = help: add `#![feature(foo)]` to the crate attributes to enable error: `<staged_api::Unstable as staged_api::MyTrait>::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:55:5 + --> $DIR/staged-api.rs:53:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | Unstable::func(); = help: const-stable functions can only call other const-stable functions error: `<Foo as staged_api::MyTrait>::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:57:5 + --> $DIR/staged-api.rs:55:5 | LL | Foo::func(); | ^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | Foo::func(); = help: const-stable functions can only call other const-stable functions error: `const_context_not_const_stable` is not yet stable as a const fn - --> $DIR/staged-api.rs:59:5 + --> $DIR/staged-api.rs:57:5 | LL | const_context_not_const_stable() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr index bf53b995bb6..e51ff148339 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/std-impl-gate.gated.stderr @@ -4,6 +4,16 @@ error[E0635]: unknown feature `const_default_impls` LL | #![cfg_attr(gated, feature(const_trait_impl, const_default_impls))] | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error[E0015]: cannot call non-const fn `<Vec<usize> as Default>::default` in constant functions + --> $DIR/std-impl-gate.rs:13:5 + | +LL | Default::default() + | ^^^^^^^^^^^^^^^^^^ + | + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0635`. +Some errors have detailed explanations: E0015, E0635. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rust-2018/issue-51008-1.rs b/tests/ui/rust-2018/issue-51008-1.rs index da7b8ef65c5..67dfbf64601 100644 --- a/tests/ui/rust-2018/issue-51008-1.rs +++ b/tests/ui/rust-2018/issue-51008-1.rs @@ -2,7 +2,7 @@ // being incorrectly considered part of the "elided lifetimes" from // the impl. // -// run-pass +// check-pass trait A { diff --git a/tests/ui/rust-2018/issue-51008.rs b/tests/ui/rust-2018/issue-51008.rs index 56517b9adee..f9e4bc14ec8 100644 --- a/tests/ui/rust-2018/issue-51008.rs +++ b/tests/ui/rust-2018/issue-51008.rs @@ -2,7 +2,7 @@ // being incorrectly considered part of the "elided lifetimes" from // the impl. // -// run-pass +// check-pass trait A { diff --git a/tests/ui/sized/coinductive-2.rs b/tests/ui/sized/coinductive-2.rs index 212274d2e4b..43a5a28f710 100644 --- a/tests/ui/sized/coinductive-2.rs +++ b/tests/ui/sized/coinductive-2.rs @@ -11,7 +11,7 @@ impl<T> CollectionFactory<T> for Vec<()> { type Collection = Vec<T>; } -trait Collection<T>: Sized { +trait Collection<T>: Sized { //~ WARN trait `Collection` is never used fn push(&mut self, v: T); } diff --git a/tests/ui/sized/coinductive-2.stderr b/tests/ui/sized/coinductive-2.stderr new file mode 100644 index 00000000000..1390b1f8d7b --- /dev/null +++ b/tests/ui/sized/coinductive-2.stderr @@ -0,0 +1,10 @@ +warning: trait `Collection` is never used + --> $DIR/coinductive-2.rs:14:7 + | +LL | trait Collection<T>: Sized { + | ^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/span/issue-23827.rs b/tests/ui/span/issue-23827.rs index 6b065bf6cbf..81037771389 100644 --- a/tests/ui/span/issue-23827.rs +++ b/tests/ui/span/issue-23827.rs @@ -2,6 +2,7 @@ #![feature(fn_traits, unboxed_closures)] +#[derive(Copy, Clone)] pub struct Prototype { pub target: u32 } diff --git a/tests/ui/span/issue-23827.stderr b/tests/ui/span/issue-23827.stderr index fe7c7794c9c..56f449ab08b 100644 --- a/tests/ui/span/issue-23827.stderr +++ b/tests/ui/span/issue-23827.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `Output` - --> $DIR/issue-23827.rs:26:1 + --> $DIR/issue-23827.rs:27:1 | LL | impl<C: Component> FnOnce<(C,)> for Prototype { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Output` in implementation diff --git a/tests/ui/span/issue-39698.rs b/tests/ui/span/issue-39698.rs index 1079bae2c06..9799e67e521 100644 --- a/tests/ui/span/issue-39698.rs +++ b/tests/ui/span/issue-39698.rs @@ -12,5 +12,6 @@ fn main() { //~| ERROR is not bound in all patterns //~| ERROR is not bound in all patterns //~| ERROR is not bound in all patterns + //~| ERROR `a` is possibly-uninitialized } } diff --git a/tests/ui/span/issue-39698.stderr b/tests/ui/span/issue-39698.stderr index 50008083211..73fcc5c8477 100644 --- a/tests/ui/span/issue-39698.stderr +++ b/tests/ui/span/issue-39698.stderr @@ -38,6 +38,19 @@ LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?} | | variable not in all patterns | variable not in all patterns -error: aborting due to 4 previous errors +error[E0381]: used binding `a` is possibly-uninitialized + --> $DIR/issue-39698.rs:10:79 + | +LL | T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); } + | - - ^ `a` used here but it is possibly-uninitialized + | | | + | | binding initialized here in some conditions + | binding initialized here in some conditions + | binding declared here but left uninitialized + | + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0408`. +Some errors have detailed explanations: E0381, E0408. +For more information about an error, try `rustc --explain E0381`. diff --git a/tests/ui/specialization/assoc-ty-graph-cycle.rs b/tests/ui/specialization/assoc-ty-graph-cycle.rs index fc39b553a61..bec8cc187b4 100644 --- a/tests/ui/specialization/assoc-ty-graph-cycle.rs +++ b/tests/ui/specialization/assoc-ty-graph-cycle.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Make sure we don't crash with a cycle error during coherence. diff --git a/tests/ui/specialization/const_trait_impl.stderr b/tests/ui/specialization/const_trait_impl.stderr index 913d51875cd..187049e623c 100644 --- a/tests/ui/specialization/const_trait_impl.stderr +++ b/tests/ui/specialization/const_trait_impl.stderr @@ -16,5 +16,33 @@ error: `~const` can only be applied to `#[const_trait]` traits LL | impl<T: ~const Default + ~const Sub> const A for T { | ^^^^^^^ -error: aborting due to 3 previous errors +error[E0015]: cannot call non-const fn `<() as A>::a` in constants + --> $DIR/const_trait_impl.rs:52:23 + | +LL | const _: () = assert!(<()>::a() == 42); + | ^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: cannot call non-const fn `<u8 as A>::a` in constants + --> $DIR/const_trait_impl.rs:53:23 + | +LL | const _: () = assert!(<u8>::a() == 3); + | ^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error[E0015]: cannot call non-const fn `<u16 as A>::a` in constants + --> $DIR/const_trait_impl.rs:54:23 + | +LL | const _: () = assert!(<u16>::a() == 2); + | ^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(effects)]` to the crate attributes to enable + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/specialization/defaultimpl/out-of-order.rs b/tests/ui/specialization/defaultimpl/out-of-order.rs index 13258ac8c9f..94b3905178f 100644 --- a/tests/ui/specialization/defaultimpl/out-of-order.rs +++ b/tests/ui/specialization/defaultimpl/out-of-order.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that you can list the more specific impl before the more general one. diff --git a/tests/ui/specialization/defaultimpl/overlap-projection.rs b/tests/ui/specialization/defaultimpl/overlap-projection.rs index 0add4d5516c..46f54c466a8 100644 --- a/tests/ui/specialization/defaultimpl/overlap-projection.rs +++ b/tests/ui/specialization/defaultimpl/overlap-projection.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that impls on projected self types can resolve overlap, even when the // projections involve specialization, so long as the associated type is diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr index e9498a00317..78d77a78e0e 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr @@ -7,6 +7,13 @@ LL | impl Overlap for u32 { LL | impl Overlap for <u32 as Default>::Id { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` -error: aborting due to 1 previous error +error[E0282]: type annotations needed + --> $DIR/specialization-default-items-drop-coherence.rs:18:23 + | +LL | default type Id = T; + | ^ cannot infer type for associated type `<T as Default>::Id` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0282. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.rs b/tests/ui/specialization/specialization-default-items-drop-coherence.rs index 37903c21071..87eb5d90def 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.rs +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.rs @@ -11,25 +11,25 @@ #![allow(incomplete_features)] trait Default { - type Id; + type Id; } impl<T> Default for T { - default type Id = T; + default type Id = T; //[next]~ ERROR type annotations needed } trait Overlap { - type Assoc; + type Assoc; } impl Overlap for u32 { - type Assoc = usize; + type Assoc = usize; } impl Overlap for <u32 as Default>::Id { - //[coherence]~^ ERROR conflicting implementations of trait `Overlap` for type `u32` - //[next]~^^ ERROR conflicting implementations of trait `Overlap` for type `u32` - type Assoc = Box<usize>; + //[coherence]~^ ERROR conflicting implementations of trait `Overlap` for type `u32` + //[next]~^^ ERROR conflicting implementations of trait `Overlap` for type `u32` + type Assoc = Box<usize>; } fn main() {} diff --git a/tests/ui/specialization/specialization-out-of-order.rs b/tests/ui/specialization/specialization-out-of-order.rs index cb7563e2760..66e6c3c9eab 100644 --- a/tests/ui/specialization/specialization-out-of-order.rs +++ b/tests/ui/specialization/specialization-out-of-order.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that you can list the more specific impl before the more general one. diff --git a/tests/ui/specialization/specialization-overlap-projection.rs b/tests/ui/specialization/specialization-overlap-projection.rs index b07efb2a5c1..cd21eab24c0 100644 --- a/tests/ui/specialization/specialization-overlap-projection.rs +++ b/tests/ui/specialization/specialization-overlap-projection.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Test that impls on projected self types can resolve overlap, even when the // projections involve specialization, so long as the associated type is diff --git a/tests/ui/specialization/specialization-supertraits.rs b/tests/ui/specialization/specialization-supertraits.rs index fb85d801921..d0c9dbb1d40 100644 --- a/tests/ui/specialization/specialization-supertraits.rs +++ b/tests/ui/specialization/specialization-supertraits.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(specialization)] //~ WARN the feature `specialization` is incomplete diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs index 6d6d793c62b..4089ec72885 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs @@ -14,3 +14,4 @@ pub const fn foobar() -> u32 { } const VAR: u32 = foobar(); +//~^ ERROR: `foobar` is not yet stable as a const fn diff --git a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr index 232de41c769..918d6ebf992 100644 --- a/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr +++ b/tests/ui/stability-attribute/const-stability-attribute-implies-missing.stderr @@ -4,5 +4,13 @@ error: feature `const_bar` implying `const_foobar` does not exist LL | #[rustc_const_unstable(feature = "const_foobar", issue = "1", implied_by = "const_bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: `foobar` is not yet stable as a const fn + --> $DIR/const-stability-attribute-implies-missing.rs:16:18 + | +LL | const VAR: u32 = foobar(); + | ^^^^^^^^ + | + = help: add `#![feature(const_foobar)]` to the crate attributes to enable + +error: aborting due to 2 previous errors diff --git a/tests/ui/static/static-drop-scope.rs b/tests/ui/static/static-drop-scope.rs index 34afa9873a3..74b224c9be0 100644 --- a/tests/ui/static/static-drop-scope.rs +++ b/tests/ui/static/static-drop-scope.rs @@ -6,11 +6,9 @@ impl Drop for WithDtor { static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); //~^ ERROR destructor of -//~| ERROR temporary value dropped while borrowed const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); //~^ ERROR destructor of -//~| ERROR temporary value dropped while borrowed static EARLY_DROP_S: i32 = (WithDtor, 0).1; //~^ ERROR destructor of diff --git a/tests/ui/static/static-drop-scope.stderr b/tests/ui/static/static-drop-scope.stderr index cedcb736794..2c55161628f 100644 --- a/tests/ui/static/static-drop-scope.stderr +++ b/tests/ui/static/static-drop-scope.stderr @@ -6,36 +6,16 @@ LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); | | | the destructor for this type cannot be evaluated in statics -error[E0716]: temporary value dropped while borrowed - --> $DIR/static-drop-scope.rs:7:60 - | -LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); - | ------^^^^^^^^- - | | | | - | | | temporary value is freed at the end of this statement - | | creates a temporary value which is freed while still in use - | using this value as a static requires that borrow lasts for `'static` - error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:11:59 + --> $DIR/static-drop-scope.rs:10:59 | LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); | ^^^^^^^^- value is dropped here | | | the destructor for this type cannot be evaluated in constants -error[E0716]: temporary value dropped while borrowed - --> $DIR/static-drop-scope.rs:11:59 - | -LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); - | ------^^^^^^^^- - | | | | - | | | temporary value is freed at the end of this statement - | | creates a temporary value which is freed while still in use - | using this value as a constant requires that borrow lasts for `'static` - error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:15:28 + --> $DIR/static-drop-scope.rs:13:28 | LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; | ^^^^^^^^^^^^^ - value is dropped here @@ -43,7 +23,7 @@ LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; | the destructor for this type cannot be evaluated in statics error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:18:27 + --> $DIR/static-drop-scope.rs:16:27 | LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; | ^^^^^^^^^^^^^ - value is dropped here @@ -51,7 +31,7 @@ LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; | the destructor for this type cannot be evaluated in constants error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:21:24 + --> $DIR/static-drop-scope.rs:19:24 | LL | const fn const_drop<T>(_: T) {} | ^ - value is dropped here @@ -59,7 +39,7 @@ LL | const fn const_drop<T>(_: T) {} | the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `(T, ())` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:25:5 + --> $DIR/static-drop-scope.rs:23:5 | LL | (x, ()).1 | ^^^^^^^ the destructor for this type cannot be evaluated in constant functions @@ -68,7 +48,7 @@ LL | } | - value is dropped here error[E0493]: destructor of `(Option<WithDtor>, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:29:34 + --> $DIR/static-drop-scope.rs:27:34 | LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; | ^^^^^^^^^^^^^^^^^^^ - value is dropped here @@ -76,14 +56,13 @@ LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; | the destructor for this type cannot be evaluated in constants error[E0493]: destructor of `(Option<WithDtor>, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:34:43 + --> $DIR/static-drop-scope.rs:32:43 | LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; | ^^^^^^^^^^^ - value is dropped here | | | the destructor for this type cannot be evaluated in constants -error: aborting due to 10 previous errors +error: aborting due to 8 previous errors -Some errors have detailed explanations: E0493, E0716. -For more information about an error, try `rustc --explain E0493`. +For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/statics/static-impl.rs b/tests/ui/statics/static-impl.rs index e7bdb38ee62..9e2db7e0caf 100644 --- a/tests/ui/statics/static-impl.rs +++ b/tests/ui/statics/static-impl.rs @@ -35,7 +35,7 @@ impl uint_utils for usize { trait vec_utils<T> { fn length_(&self, ) -> usize; - fn iter_<F>(&self, f: F) where F: FnMut(&T); + fn iter_<F>(&self, f: F) where F: FnMut(&T); //~ WARN method `iter_` is never used fn map_<U, F>(&self, f: F) -> Vec<U> where F: FnMut(&T) -> U; } diff --git a/tests/ui/statics/static-impl.stderr b/tests/ui/statics/static-impl.stderr new file mode 100644 index 00000000000..83c3ffbefe1 --- /dev/null +++ b/tests/ui/statics/static-impl.stderr @@ -0,0 +1,13 @@ +warning: method `iter_` is never used + --> $DIR/static-impl.rs:38:8 + | +LL | trait vec_utils<T> { + | --------- method in this trait +LL | fn length_(&self, ) -> usize; +LL | fn iter_<F>(&self, f: F) where F: FnMut(&T); + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs b/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs index 0f535523dcc..4a8289cb242 100644 --- a/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs +++ b/tests/ui/stdlib-unit-tests/raw-fat-ptr.rs @@ -32,7 +32,7 @@ fn assert_inorder<T: PartialEq + PartialOrd>(a: &[T]) { } } -trait Foo { fn foo(&self) -> usize; } +trait Foo { fn foo(&self) -> usize; } //~ WARN method `foo` is never used impl<T> Foo for T { fn foo(&self) -> usize { mem::size_of::<T>() diff --git a/tests/ui/stdlib-unit-tests/raw-fat-ptr.stderr b/tests/ui/stdlib-unit-tests/raw-fat-ptr.stderr new file mode 100644 index 00000000000..670fa5bb922 --- /dev/null +++ b/tests/ui/stdlib-unit-tests/raw-fat-ptr.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/raw-fat-ptr.rs:35:16 + | +LL | trait Foo { fn foo(&self) -> usize; } + | --- ^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/structs-enums/enum-null-pointer-opt.rs b/tests/ui/structs-enums/enum-null-pointer-opt.rs index 356f8a6dd36..21564eeec29 100644 --- a/tests/ui/structs-enums/enum-null-pointer-opt.rs +++ b/tests/ui/structs-enums/enum-null-pointer-opt.rs @@ -7,7 +7,7 @@ use std::ptr::NonNull; use std::rc::Rc; use std::sync::Arc; -trait Trait { fn dummy(&self) { } } +trait Trait { fn dummy(&self) { } } //~ WARN method `dummy` is never used trait Mirror { type Image; } impl<T> Mirror for T { type Image = T; } struct ParamTypeStruct<T>(#[allow(dead_code)] T); diff --git a/tests/ui/structs-enums/enum-null-pointer-opt.stderr b/tests/ui/structs-enums/enum-null-pointer-opt.stderr new file mode 100644 index 00000000000..64e93ffaffd --- /dev/null +++ b/tests/ui/structs-enums/enum-null-pointer-opt.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/enum-null-pointer-opt.rs:10:18 + | +LL | trait Trait { fn dummy(&self) { } } + | ----- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs index b7e49873da8..20231dc83db 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs @@ -1,7 +1,10 @@ +// ignore-macos: cycle error does not appear on apple + use std::sync::Mutex; enum Foo { X(Mutex<Option<Foo>>) } //~^ ERROR recursive type `Foo` has infinite size +//~| ERROR cycle detected impl Foo { fn bar(self) {} } diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr index e34eb04bc04..22f8519d0ef 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr @@ -1,5 +1,5 @@ error[E0072]: recursive type `Foo` has infinite size - --> $DIR/issue-17431-6.rs:3:1 + --> $DIR/issue-17431-6.rs:5:1 | LL | enum Foo { X(Mutex<Option<Foo>>) } | ^^^^^^^^ --- recursive without indirection @@ -9,6 +9,17 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum Foo { X(Mutex<Option<Box<Foo>>>) } | ++++ + -error: aborting due to 1 previous error +error[E0391]: cycle detected when computing when `Foo` needs drop + --> $DIR/issue-17431-6.rs:5:1 + | +LL | enum Foo { X(Mutex<Option<Foo>>) } + | ^^^^^^^^ + | + = note: ...which immediately requires computing when `Foo` needs drop again + = note: cycle used when computing whether `Foo` needs drop + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0072`. +Some errors have detailed explanations: E0072, E0391. +For more information about an error, try `rustc --explain E0072`. diff --git a/tests/ui/suggestions/bound-suggestions.fixed b/tests/ui/suggestions/bound-suggestions.fixed index 17a019c6984..ef61fb9ad32 100644 --- a/tests/ui/suggestions/bound-suggestions.fixed +++ b/tests/ui/suggestions/bound-suggestions.fixed @@ -40,26 +40,31 @@ fn test_many_bounds_where<X>(x: X) where X: Sized + std::fmt::Debug, X: Sized { //~^ ERROR doesn't implement } +#[allow(dead_code)] trait Foo<T>: Sized { const SIZE: usize = core::mem::size_of::<Self>(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Bar: std::fmt::Display + Sized { const SIZE: usize = core::mem::size_of::<Self>(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Baz: Sized where Self: std::fmt::Display { const SIZE: usize = core::mem::size_of::<Self>(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Qux<T>: Sized where Self: std::fmt::Display { const SIZE: usize = core::mem::size_of::<Self>(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Bat<T>: std::fmt::Display + Sized { const SIZE: usize = core::mem::size_of::<Self>(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time diff --git a/tests/ui/suggestions/bound-suggestions.rs b/tests/ui/suggestions/bound-suggestions.rs index 86f708d42f5..6d17fae6a08 100644 --- a/tests/ui/suggestions/bound-suggestions.rs +++ b/tests/ui/suggestions/bound-suggestions.rs @@ -40,26 +40,31 @@ fn test_many_bounds_where<X>(x: X) where X: Sized, X: Sized { //~^ ERROR doesn't implement } +#[allow(dead_code)] trait Foo<T> { const SIZE: usize = core::mem::size_of::<Self>(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Bar: std::fmt::Display { const SIZE: usize = core::mem::size_of::<Self>(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Baz where Self: std::fmt::Display { const SIZE: usize = core::mem::size_of::<Self>(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Qux<T> where Self: std::fmt::Display { const SIZE: usize = core::mem::size_of::<Self>(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time } +#[allow(dead_code)] trait Bat<T>: std::fmt::Display { const SIZE: usize = core::mem::size_of::<Self>(); //~^ ERROR the size for values of type `Self` cannot be known at compilation time diff --git a/tests/ui/suggestions/bound-suggestions.stderr b/tests/ui/suggestions/bound-suggestions.stderr index 7e58ccd461d..4965e7439f8 100644 --- a/tests/ui/suggestions/bound-suggestions.stderr +++ b/tests/ui/suggestions/bound-suggestions.stderr @@ -71,7 +71,7 @@ LL | fn test_many_bounds_where<X>(x: X) where X: Sized + std::fmt::Debug, X: Siz | +++++++++++++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:44:46 + --> $DIR/bound-suggestions.rs:45:46 | LL | const SIZE: usize = core::mem::size_of::<Self>(); | ^^^^ doesn't have a size known at compile-time @@ -84,7 +84,7 @@ LL | trait Foo<T>: Sized { | +++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:49:46 + --> $DIR/bound-suggestions.rs:51:46 | LL | const SIZE: usize = core::mem::size_of::<Self>(); | ^^^^ doesn't have a size known at compile-time @@ -97,7 +97,7 @@ LL | trait Bar: std::fmt::Display + Sized { | +++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:54:46 + --> $DIR/bound-suggestions.rs:57:46 | LL | const SIZE: usize = core::mem::size_of::<Self>(); | ^^^^ doesn't have a size known at compile-time @@ -110,7 +110,7 @@ LL | trait Baz: Sized where Self: std::fmt::Display { | +++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:59:46 + --> $DIR/bound-suggestions.rs:63:46 | LL | const SIZE: usize = core::mem::size_of::<Self>(); | ^^^^ doesn't have a size known at compile-time @@ -123,7 +123,7 @@ LL | trait Qux<T>: Sized where Self: std::fmt::Display { | +++++++ error[E0277]: the size for values of type `Self` cannot be known at compilation time - --> $DIR/bound-suggestions.rs:64:46 + --> $DIR/bound-suggestions.rs:69:46 | LL | const SIZE: usize = core::mem::size_of::<Self>(); | ^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/suggestions/constrain-trait.fixed b/tests/ui/suggestions/constrain-trait.fixed index f292f27f0f3..f7360efe4c5 100644 --- a/tests/ui/suggestions/constrain-trait.fixed +++ b/tests/ui/suggestions/constrain-trait.fixed @@ -1,5 +1,6 @@ // run-rustfix // check-only +#![allow(dead_code)] #[derive(Debug)] struct Demo { diff --git a/tests/ui/suggestions/constrain-trait.rs b/tests/ui/suggestions/constrain-trait.rs index 99ccf7a7f3b..799100669b6 100644 --- a/tests/ui/suggestions/constrain-trait.rs +++ b/tests/ui/suggestions/constrain-trait.rs @@ -1,5 +1,6 @@ // run-rustfix // check-only +#![allow(dead_code)] #[derive(Debug)] struct Demo { diff --git a/tests/ui/suggestions/constrain-trait.stderr b/tests/ui/suggestions/constrain-trait.stderr index a26f86917bc..b28972ecde0 100644 --- a/tests/ui/suggestions/constrain-trait.stderr +++ b/tests/ui/suggestions/constrain-trait.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `get_a` found for reference `&Self` in the current scope - --> $DIR/constrain-trait.rs:15:31 + --> $DIR/constrain-trait.rs:16:31 | LL | println!("{:?}", self.get_a()); | ^^^^^ method not found in `&Self` @@ -11,7 +11,7 @@ LL | trait UseString: std::fmt::Debug + GetString { | +++++++++++ error[E0599]: no method named `get_a` found for reference `&Self` in the current scope - --> $DIR/constrain-trait.rs:21:31 + --> $DIR/constrain-trait.rs:22:31 | LL | println!("{:?}", self.get_a()); | ^^^^^ method not found in `&Self` diff --git a/tests/ui/suggestions/derive-trait-for-method-call.rs b/tests/ui/suggestions/derive-trait-for-method-call.rs index 25043da52aa..b5ce0078c9b 100644 --- a/tests/ui/suggestions/derive-trait-for-method-call.rs +++ b/tests/ui/suggestions/derive-trait-for-method-call.rs @@ -19,7 +19,7 @@ struct CloneStruct { struct Foo<X, Y> (X, Y); impl<X: Clone + Default + , Y: Clone + Default> Foo<X, Y> { fn test(&self) -> (X, Y) { - (self.0, self.1) + (self.0.clone(), self.1.clone()) } } diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs index 255cab06070..c24672816ac 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs @@ -64,6 +64,8 @@ mod bay { fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () { val.use_self() + //~^ ERROR: cannot return value referencing function parameter `val` + //~| ERROR: borrowed data escapes outside of function } } @@ -86,6 +88,7 @@ mod bax { fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () { val.use_self() + //~^ ERROR: cannot return value referencing function parameter `val` } } diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr index a7e03f491b9..505765d2b41 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr @@ -17,7 +17,7 @@ LL | val.use_self() | `val` is borrowed here error[E0515]: cannot return value referencing function parameter `val` - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:109:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:112:9 | LL | val.use_self() | ---^^^^^^^^^^^ @@ -25,6 +25,50 @@ LL | val.use_self() | returns a value referencing data owned by the current function | `val` is borrowed here -error: aborting due to 3 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 + | +LL | fn use_it<'a>(val: Box<dyn ObjectTrait<Assoc = i32> + 'a>) -> &'a () { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:60:30 + | +LL | impl MyTrait for Box<dyn ObjectTrait<Assoc = i32>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s `'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for Box<dyn ObjectTrait<Assoc = i32> + '_> { + | ++++ + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:90:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0515`. +Some errors have detailed explanations: E0515, E0521. +For more information about an error, try `rustc --explain E0515`. diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs index ae3cd315c83..574aea9cc6e 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.rs @@ -36,6 +36,7 @@ mod bar { fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { val.use_self() + //~^ ERROR: borrowed data escapes } } @@ -53,6 +54,7 @@ mod baz { fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () { val.use_self() + //~^ ERROR: borrowed data escapes } } diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index da72c8ebf19..6effaf61099 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -24,7 +24,7 @@ LL | impl<T> MyTrait<T> for dyn ObjectTrait<T> + '_ { | ++++ error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:70:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:72:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { | -- --- `val` is a reference that is only valid in the function body @@ -37,7 +37,7 @@ LL | val.use_self() | argument requires that `'a` must outlive `'static` | note: the used `impl` has a `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:65:14 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:67:14 | LL | impl dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement @@ -49,7 +49,7 @@ LL | impl dyn ObjectTrait + '_ { | ++++ error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:90:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:92:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { | -- --- `val` is a reference that is only valid in the function body @@ -62,7 +62,7 @@ LL | val.use_self() | argument requires that `'a` must outlive `'static` | note: the used `impl` has a `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:26 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:89:26 | LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement @@ -75,7 +75,7 @@ LL | impl MyTrait for dyn ObjectTrait + '_ {} | ++++ error[E0521]: borrowed data escapes outside of function - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:110:9 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:112:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { | -- --- `val` is a reference that is only valid in the function body @@ -88,7 +88,7 @@ LL | MyTrait::use_self(val) | argument requires that `'a` must outlive `'static` | note: the used `impl` has a `'static` requirement - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:106:26 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:26 | LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement @@ -100,6 +100,56 @@ help: consider relaxing the implicit `'static` requirement LL | impl MyTrait for dyn ObjectTrait + '_ {} | ++++ -error: aborting due to 4 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:38:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:32:26 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s `'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ { + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:56:9 + | +LL | fn use_it<'a>(val: &'a Box<dyn ObjectTrait + 'a>) -> &'a () { + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:50:30 + | +LL | impl MyTrait for Box<dyn ObjectTrait> { + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +LL | fn use_self(&self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s `'static` requirement +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for Box<dyn ObjectTrait + '_> { + | ++++ + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.rs b/tests/ui/suggestions/impl-trait-missing-lifetime.rs index 6f7c912d707..b03d6161493 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime.rs +++ b/tests/ui/suggestions/impl-trait-missing-lifetime.rs @@ -8,6 +8,7 @@ fn f(_: impl Iterator<Item = &'_ ()>) {} // But that lifetime does not participate in resolution. fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } //~^ ERROR missing lifetime specifier +//~| ERROR lifetime may not live long enough // This is understood as `fn foo<'_1>(_: impl Iterator<Item = &'_1 ()>) {}`. async fn h(_: impl Iterator<Item = &'_ ()>) {} diff --git a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr index c1dbaae0649..70998b67c04 100644 --- a/tests/ui/suggestions/impl-trait-missing-lifetime.stderr +++ b/tests/ui/suggestions/impl-trait-missing-lifetime.stderr @@ -20,7 +20,7 @@ LL + fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() } | error[E0106]: missing lifetime specifier - --> $DIR/impl-trait-missing-lifetime.rs:16:60 + --> $DIR/impl-trait-missing-lifetime.rs:17:60 | LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } | ^^ expected named lifetime parameter @@ -41,13 +41,19 @@ LL + async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<()> { x.next() } | error: lifetime may not live long enough - --> $DIR/impl-trait-missing-lifetime.rs:16:69 + --> $DIR/impl-trait-missing-lifetime.rs:17:69 | LL | async fn i(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } | ----------------------------------------------------------------- ^^^^^^^^ returning this value requires that `'1` must outlive `'static` | | | return type `impl Future<Output = Option<&'static ()>>` contains a lifetime `'1` -error: aborting due to 3 previous errors +error: lifetime may not live long enough + --> $DIR/impl-trait-missing-lifetime.rs:9:63 + | +LL | fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() } + | ----- has type `x` ^^^^^^^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/invalid-bin-op.stderr b/tests/ui/suggestions/invalid-bin-op.stderr index 2bd745c645a..018250c8c1b 100644 --- a/tests/ui/suggestions/invalid-bin-op.stderr +++ b/tests/ui/suggestions/invalid-bin-op.stderr @@ -16,6 +16,10 @@ help: consider annotating `S<T>` with `#[derive(PartialEq)]` LL + #[derive(PartialEq)] LL | struct S<T>(T); | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | pub fn foo<T>(s: S<T>, t: S<T>) where S<T>: PartialEq { + | +++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-102892.rs b/tests/ui/suggestions/issue-102892.rs index c1a791d8d85..ac7f16f8c65 100644 --- a/tests/ui/suggestions/issue-102892.rs +++ b/tests/ui/suggestions/issue-102892.rs @@ -9,6 +9,7 @@ struct B; fn process_without_annot(arc: &Arc<(A, B)>) { let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! + //~^ ERROR: cannot move out of an `Arc` } fn process_with_annot(arc: &Arc<(A, B)>) { diff --git a/tests/ui/suggestions/issue-102892.stderr b/tests/ui/suggestions/issue-102892.stderr index e64a89ffe33..38f19b33218 100644 --- a/tests/ui/suggestions/issue-102892.stderr +++ b/tests/ui/suggestions/issue-102892.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-102892.rs:15:26 + --> $DIR/issue-102892.rs:16:26 | LL | let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too | ------ ^^^^^^ expected `(A, B)`, found `&(A, B)` @@ -19,7 +19,7 @@ LL | let (a, b): &(A, B) = &**arc; // suggests putting `&**arc` here too | + error[E0308]: mismatched types - --> $DIR/issue-102892.rs:20:32 + --> $DIR/issue-102892.rs:21:32 | LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too | ^^^^^^^^^^^^^^ expected `(A, B)`, found `&mut (A, B)` @@ -37,7 +37,7 @@ LL | let (a, b): (&mut (A, B), A) = (&mut *mutation, &(**arc).0); // suggest | ++++ error[E0308]: mismatched types - --> $DIR/issue-102892.rs:20:48 + --> $DIR/issue-102892.rs:21:48 | LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too | ^^^^^^^^^^ expected `A`, found `&A` @@ -52,6 +52,23 @@ help: alternatively, consider changing the type annotation LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too | + -error: aborting due to 3 previous errors +error[E0507]: cannot move out of an `Arc` + --> $DIR/issue-102892.rs:11:18 + | +LL | let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! + | - - ^^^^^ + | | | + | | ...and here + | data moved here + | + = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider removing the dereference here + | +LL - let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed! +LL + let (a, b) = *arc; // suggests putting `&**arc` here; with that, fixed! + | + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0507. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/suggestions/issue-109195.rs b/tests/ui/suggestions/issue-109195.rs new file mode 100644 index 00000000000..cc499b0d776 --- /dev/null +++ b/tests/ui/suggestions/issue-109195.rs @@ -0,0 +1,20 @@ +fn main() { + String::from::utf8; + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `from_utf8` + String::from::utf8(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `from_utf8` + String::from::utf16(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `from_utf16` + String::from::method_that_doesnt_exist(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP if there were a trait named `Example` with associated type `from` + str::from::utf8(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP if there were a trait named `Example` with associated type `from` + str::from::utf8_mut(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP if there were a trait named `Example` with associated type `from` +} diff --git a/tests/ui/suggestions/issue-109195.stderr b/tests/ui/suggestions/issue-109195.stderr new file mode 100644 index 00000000000..10cf9cfd28c --- /dev/null +++ b/tests/ui/suggestions/issue-109195.stderr @@ -0,0 +1,69 @@ +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:2:5 + | +LL | String::from::utf8; + | ^^^^^^^^^^^^ + | +help: there is an associated function with a similar name: `from_utf8` + | +LL | String::from_utf8; + | ~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:5:5 + | +LL | String::from::utf8(); + | ^^^^^^^^^^^^ + | +help: there is an associated function with a similar name: `from_utf8` + | +LL | String::from_utf8(); + | ~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:8:5 + | +LL | String::from::utf16(); + | ^^^^^^^^^^^^ + | +help: there is an associated function with a similar name: `from_utf16` + | +LL | String::from_utf16(); + | ~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:11:5 + | +LL | String::from::method_that_doesnt_exist(); + | ^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `from` implemented for `String`, you could use the fully-qualified path + | +LL | <String as Example>::from::method_that_doesnt_exist(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:14:5 + | +LL | str::from::utf8(); + | ^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path + | +LL | <str as Example>::from::utf8(); + | ~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/issue-109195.rs:17:5 + | +LL | str::from::utf8_mut(); + | ^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path + | +LL | <str as Example>::from::utf8_mut(); + | ~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/suggestions/issue-61963.rs b/tests/ui/suggestions/issue-61963.rs index a27c3845253..d31ed01b191 100644 --- a/tests/ui/suggestions/issue-61963.rs +++ b/tests/ui/suggestions/issue-61963.rs @@ -18,20 +18,10 @@ pub struct Qux<T>(T); pub struct Foo { //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition qux: Qux<Qux<Baz>>, bar: Box<Bar>, //~^ ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition - //~| ERROR trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition } fn main() {} diff --git a/tests/ui/suggestions/issue-61963.stderr b/tests/ui/suggestions/issue-61963.stderr index ec62153b0a7..754d02b1c02 100644 --- a/tests/ui/suggestions/issue-61963.stderr +++ b/tests/ui/suggestions/issue-61963.stderr @@ -1,5 +1,5 @@ error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:28:14 + --> $DIR/issue-61963.rs:22:14 | LL | bar: Box<Bar>, | ^^^ @@ -29,75 +29,5 @@ help: use `dyn` LL | dyn pub struct Foo { | +++ -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:28:14 - | -LL | bar: Box<Bar>, - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | bar: Box<dyn Bar>, - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:28:14 - | -LL | bar: Box<Bar>, - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | bar: Box<dyn Bar>, - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:18:1 - | -LL | pub struct Foo { - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | dyn pub struct Foo { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:18:1 - | -LL | pub struct Foo { - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | dyn pub struct Foo { - | +++ - -error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:18:1 - | -LL | pub struct Foo { - | ^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use `dyn` - | -LL | dyn pub struct Foo { - | +++ - -error: aborting due to 7 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/issue-86667.rs b/tests/ui/suggestions/issue-86667.rs index 366787df1b4..b1a7e6e9665 100644 --- a/tests/ui/suggestions/issue-86667.rs +++ b/tests/ui/suggestions/issue-86667.rs @@ -4,14 +4,15 @@ // compile-flags: --edition 2018 async fn a(s1: &str, s2: &str) -> &str { -//~^ ERROR: missing lifetime specifier [E0106] + //~^ ERROR: missing lifetime specifier [E0106] s1 -//~^ ERROR: lifetime may not live long enough + //~^ ERROR: lifetime may not live long enough } fn b(s1: &str, s2: &str) -> &str { -//~^ ERROR: missing lifetime specifier [E0106] + //~^ ERROR: missing lifetime specifier [E0106] s1 + //~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/tests/ui/suggestions/issue-86667.stderr b/tests/ui/suggestions/issue-86667.stderr index 8d611641626..e3d673ff233 100644 --- a/tests/ui/suggestions/issue-86667.stderr +++ b/tests/ui/suggestions/issue-86667.stderr @@ -31,6 +31,15 @@ LL | LL | s1 | ^^ returning this value requires that `'1` must outlive `'static` -error: aborting due to 3 previous errors +error: lifetime may not live long enough + --> $DIR/issue-86667.rs:14:5 + | +LL | fn b(s1: &str, s2: &str) -> &str { + | - let's call the lifetime of this reference `'1` +LL | +LL | s1 + | ^^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed b/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed index 3257ea04c69..d4a8381fcb1 100644 --- a/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed +++ b/tests/ui/suggestions/lifetimes/type-param-bound-scope.fixed @@ -1,6 +1,7 @@ // Make sure we suggest the bound `T: 'a` in the correct scope: // trait, impl or associated fn. // run-rustfix +#![allow(dead_code)] struct Inv<'a>(#[allow(dead_code)] Option<*mut &'a u8>); diff --git a/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs b/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs index fcc13aad996..dc43e2df6dd 100644 --- a/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs +++ b/tests/ui/suggestions/lifetimes/type-param-bound-scope.rs @@ -1,6 +1,7 @@ // Make sure we suggest the bound `T: 'a` in the correct scope: // trait, impl or associated fn. // run-rustfix +#![allow(dead_code)] struct Inv<'a>(#[allow(dead_code)] Option<*mut &'a u8>); diff --git a/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr b/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr index d3ca2cc1162..91054472c04 100644 --- a/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr +++ b/tests/ui/suggestions/lifetimes/type-param-bound-scope.stderr @@ -1,5 +1,5 @@ error[E0309]: the parameter type `Self` may not live long enough - --> $DIR/type-param-bound-scope.rs:11:9 + --> $DIR/type-param-bound-scope.rs:12:9 | LL | trait Trait1<'a>: Sized { | -- the parameter type `Self` must be valid for the lifetime `'a` as defined here... @@ -13,7 +13,7 @@ LL | trait Trait1<'a>: Sized where Self: 'a { | ++++++++++++++ error[E0309]: the parameter type `Self` may not live long enough - --> $DIR/type-param-bound-scope.rs:18:9 + --> $DIR/type-param-bound-scope.rs:19:9 | LL | fn foo<'a>(self, lt: Inv<'a>) { | -- the parameter type `Self` must be valid for the lifetime `'a` as defined here... @@ -26,7 +26,7 @@ LL | fn foo<'a>(self, lt: Inv<'a>) where Self: 'a { | ++++++++++++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/type-param-bound-scope.rs:25:9 + --> $DIR/type-param-bound-scope.rs:26:9 | LL | fn foo<'a>(arg: T, lt: Inv<'a>) { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... @@ -39,7 +39,7 @@ LL | fn foo<'a>(arg: T, lt: Inv<'a>) where T: 'a { | +++++++++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/type-param-bound-scope.rs:32:9 + --> $DIR/type-param-bound-scope.rs:33:9 | LL | trait Trait4<'a> { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... @@ -53,7 +53,7 @@ LL | fn foo<T: 'a>(arg: T, lt: Inv<'a>) { | ++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/type-param-bound-scope.rs:42:9 + --> $DIR/type-param-bound-scope.rs:43:9 | LL | impl<'a, T> Trait5<'a> for T { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed index 47b35b412c0..53476ee8c59 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed @@ -8,8 +8,8 @@ pub struct Vector2<T: Debug + Copy + Clone>{ } #[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB<K: Copy + Debug>{ - pub loc: Vector2<K>, +pub struct AABB<K: Copy + Debug + std::fmt::Debug>{ + pub loc: Vector2<K>, //~ ERROR `K` doesn't implement `Debug` pub size: Vector2<K> } diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs index 771e9105c62..08c4f344e4e 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs @@ -9,7 +9,7 @@ pub struct Vector2<T: Debug + Copy + Clone>{ #[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type pub struct AABB<K: Copy>{ - pub loc: Vector2<K>, + pub loc: Vector2<K>, //~ ERROR `K` doesn't implement `Debug` pub size: Vector2<K> } diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index ed1bde5f83e..bfb96b4076b 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -18,6 +18,23 @@ help: consider further restricting this bound LL | pub struct AABB<K: Copy + Debug>{ | +++++++ -error: aborting due to 1 previous error +error[E0277]: `K` doesn't implement `Debug` + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:12:14 + | +LL | pub loc: Vector2<K>, + | ^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +note: required by a bound in `Vector2` + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:5:23 + | +LL | pub struct Vector2<T: Debug + Copy + Clone>{ + | ^^^^^ required by this bound in `Vector2` +help: consider further restricting this bound + | +LL | pub struct AABB<K: Copy + std::fmt::Debug>{ + | +++++++++++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0204`. +Some errors have detailed explanations: E0204, E0277. +For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs index 9c7b7ba099c..2f1ebc1f133 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs @@ -9,6 +9,8 @@ pub struct Vector2<T: Debug + Copy + Clone>{ #[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type pub struct AABB<K>{ pub loc: Vector2<K>, + //~^ ERROR doesn't implement `Debug` + //~| ERROR `K: Copy` is not satisfied pub size: Vector2<K> } diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 03db737fa87..f3213e1a4c8 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -18,6 +18,39 @@ help: consider restricting type parameter `K` LL | pub struct AABB<K: Debug>{ | +++++++ -error: aborting due to 1 previous error +error[E0277]: `K` doesn't implement `Debug` + --> $DIR/missing-bound-in-derive-copy-impl.rs:11:14 + | +LL | pub loc: Vector2<K>, + | ^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | +note: required by a bound in `Vector2` + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:23 + | +LL | pub struct Vector2<T: Debug + Copy + Clone>{ + | ^^^^^ required by this bound in `Vector2` +help: consider restricting type parameter `K` + | +LL | pub struct AABB<K: std::fmt::Debug>{ + | +++++++++++++++++ + +error[E0277]: the trait bound `K: Copy` is not satisfied + --> $DIR/missing-bound-in-derive-copy-impl.rs:11:14 + | +LL | pub loc: Vector2<K>, + | ^^^^^^^^^^ the trait `Copy` is not implemented for `K` + | +note: required by a bound in `Vector2` + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:31 + | +LL | pub struct Vector2<T: Debug + Copy + Clone>{ + | ^^^^ required by this bound in `Vector2` +help: consider restricting type parameter `K` + | +LL | pub struct AABB<K: std::marker::Copy>{ + | +++++++++++++++++++ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0204`. +Some errors have detailed explanations: E0204, E0277. +For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed index f32c61a99bb..90bc10d34c6 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #[derive(Clone)] struct Wrapper<T>(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs index d7725f4a374..34673852a9b 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #[derive(Clone)] struct Wrapper<T>(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr index 6dc512223d1..23a75154f20 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:18 + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:17:18 | LL | struct Wrapper<T>(T); | - this field does not implement `Copy` @@ -8,7 +8,7 @@ LL | impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the `Copy` impl for `OnlyCopyIfDisplay<S>` requires that `S: std::fmt::Display` - --> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19 + --> $DIR/missing-bound-in-manual-copy-impl-2.rs:5:19 | LL | struct Wrapper<T>(T); | ^ diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed index 1139b315313..ff84e42c947 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #[derive(Clone)] struct Wrapper<T>(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs index 19549248efc..35d0a9dda79 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] #[derive(Clone)] struct Wrapper<T>(T); diff --git a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr index fd38d4c64b4..c9f277fb350 100644 --- a/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-manual-copy-impl.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-manual-copy-impl.rs:6:18 + --> $DIR/missing-bound-in-manual-copy-impl.rs:7:18 | LL | struct Wrapper<T>(T); | - this field does not implement `Copy` diff --git a/tests/ui/suggestions/missing-lifetime-specifier.rs b/tests/ui/suggestions/missing-lifetime-specifier.rs index 01dcc94f747..85dd6a5635a 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.rs +++ b/tests/ui/suggestions/missing-lifetime-specifier.rs @@ -1,4 +1,6 @@ // different number of duplicated diagnostics on different targets +// only-x86_64 +// only-linux // compile-flags: -Zdeduplicate-diagnostics=yes #![allow(bare_trait_objects)] @@ -18,21 +20,31 @@ pub union Qux<'t, 'k, I> { trait Tar<'t, 'k, I> {} thread_local! { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers //~| ERROR missing lifetime specifiers } thread_local! { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers //~| ERROR missing lifetime specifiers } thread_local! { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers //~| ERROR missing lifetime specifiers } thread_local! { + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); //~^ ERROR missing lifetime specifiers //~| ERROR missing lifetime specifiers diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr index 7a7ef47c35b..62eca162148 100644 --- a/tests/ui/suggestions/missing-lifetime-specifier.stderr +++ b/tests/ui/suggestions/missing-lifetime-specifier.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:21:44 + --> $DIR/missing-lifetime-specifier.rs:25:44 | LL | static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new()); | ^^^ expected 2 lifetime parameters @@ -11,9 +11,11 @@ LL | static a: RefCell<HashMap<i32, Vec<Vec<Foo<'static, 'static>>>>> = RefC | ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:21:44 + --> $DIR/missing-lifetime-specifier.rs:25:44 | LL | / thread_local! { +LL | | +LL | | LL | | static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new()); | | ^^^ expected 2 lifetime parameters LL | | @@ -24,7 +26,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:26:44 + --> $DIR/missing-lifetime-specifier.rs:33:44 | LL | static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new()); | ^^^^ expected 2 lifetime parameters @@ -38,9 +40,12 @@ LL | static b: RefCell<HashMap<i32, Vec<Vec<&'static Bar<'static, 'static>>> | +++++++ ++++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:26:44 + --> $DIR/missing-lifetime-specifier.rs:33:44 | LL | / thread_local! { +LL | | +LL | | +LL | | LL | | static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new()); | | ^^^^ expected 2 lifetime parameters | | | @@ -53,7 +58,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:31:47 + --> $DIR/missing-lifetime-specifier.rs:40:47 | LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new()); | ^ expected 2 lifetime parameters @@ -65,9 +70,11 @@ LL | static c: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = | +++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:31:47 + --> $DIR/missing-lifetime-specifier.rs:40:47 | LL | / thread_local! { +LL | | +LL | | LL | | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new()); | | ^ expected 2 lifetime parameters LL | | @@ -78,7 +85,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:36:44 + --> $DIR/missing-lifetime-specifier.rs:48:44 | LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); | ^ ^ expected 2 lifetime parameters @@ -92,9 +99,12 @@ LL | static d: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, 'static, i | +++++++ +++++++++++++++++ error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:36:44 + --> $DIR/missing-lifetime-specifier.rs:48:44 | LL | / thread_local! { +LL | | +LL | | +LL | | LL | | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); | | ^ ^ expected 2 lifetime parameters | | | @@ -107,7 +117,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 4 lifetimes it is borrowed from error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:46:44 + --> $DIR/missing-lifetime-specifier.rs:58:44 | LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^ expected named lifetime parameter @@ -119,7 +129,7 @@ LL | static f: RefCell<HashMap<i32, Vec<Vec<&'static Tar<'static, i32>>>>> = | +++++++ error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:46:44 + --> $DIR/missing-lifetime-specifier.rs:58:44 | LL | / thread_local! { LL | | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); @@ -133,7 +143,7 @@ LL | | } = help: this function's return type contains a borrowed value, but the signature does not say which one of `init`'s 3 lifetimes it is borrowed from error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:42:44 + --> $DIR/missing-lifetime-specifier.rs:54:44 | LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -141,7 +151,7 @@ LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, i32>>>>> = RefCell: | expected 2 lifetime arguments | note: union defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:14:11 + --> $DIR/missing-lifetime-specifier.rs:16:11 | LL | pub union Qux<'t, 'k, I> { | ^^^ -- -- @@ -151,7 +161,7 @@ LL | static e: RefCell<HashMap<i32, Vec<Vec<Qux<'static, 'static, i32>>>>> = | +++++++++ error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:46:45 + --> $DIR/missing-lifetime-specifier.rs:58:45 | LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell::new(HashMap::new()); | ^^^ ------- supplied 1 lifetime argument @@ -159,7 +169,7 @@ LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, i32>>>>> = RefCell | expected 2 lifetime arguments | note: trait defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:18:7 + --> $DIR/missing-lifetime-specifier.rs:20:7 | LL | trait Tar<'t, 'k, I> {} | ^^^ -- -- @@ -168,7 +178,199 @@ help: add missing lifetime argument LL | static f: RefCell<HashMap<i32, Vec<Vec<&Tar<'static, 'static, i32>>>>> = RefCell::new(HashMap::new()); | +++++++++ -error: aborting due to 12 previous errors +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:22:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new()); +LL | | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option<RefCell<HashMap<i32, Vec<Vec<Foo<'1, '_>>>>>>>` + | returning this value requires that `'1` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:22:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | static a: RefCell<HashMap<i32, Vec<Vec<Foo>>>> = RefCell::new(HashMap::new()); +LL | | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option<RefCell<HashMap<i32, Vec<Vec<Foo<'_, '2>>>>>>>` + | returning this value requires that `'2` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:29:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +LL | | static b: RefCell<HashMap<i32, Vec<Vec<&Bar>>>> = RefCell::new(HashMap::new()); + | | - let's call the lifetime of this reference `'1` +LL | | +LL | | +LL | | } + | |_^ returning this value requires that `'1` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static b: RefCell<HashMap<i32, Vec<Vec<&Bar + '_>>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:29:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option<RefCell<HashMap<i32, Vec<Vec<&dyn Bar<'2, '_>>>>>>>` + | returning this value requires that `'2` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static b: RefCell<HashMap<i32, Vec<Vec<&Bar + '_>>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:29:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option<RefCell<HashMap<i32, Vec<Vec<&dyn Bar<'_, '3>>>>>>>` + | returning this value requires that `'3` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static b: RefCell<HashMap<i32, Vec<Vec<&Bar + '_>>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:37:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new()); +LL | | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option<RefCell<HashMap<i32, Vec<Vec<Qux<'1, '_, i32>>>>>>>` + | returning this value requires that `'1` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:37:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | static c: RefCell<HashMap<i32, Vec<Vec<Qux<i32>>>>> = RefCell::new(HashMap::new()); +LL | | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option<RefCell<HashMap<i32, Vec<Vec<Qux<'_, '2, i32>>>>>>>` + | returning this value requires that `'2` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:44:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +LL | | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32>>>>> = RefCell::new(HashMap::new()); + | | - let's call the lifetime of this reference `'1` +LL | | +LL | | +LL | | } + | |_^ returning this value requires that `'1` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32> + '_>>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:44:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option<RefCell<HashMap<i32, Vec<Vec<&dyn Tar<'2, '_, i32>>>>>>>` + | returning this value requires that `'2` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32> + '_>>>> = RefCell::new(HashMap::new()); + | ++++ + +error: lifetime may not live long enough + --> $DIR/missing-lifetime-specifier.rs:44:1 + | +LL | / thread_local! { +LL | | +LL | | +LL | | +... | +LL | | +LL | | } + | | ^ + | | | + | |_has type `Option<&mut Option<RefCell<HashMap<i32, Vec<Vec<&dyn Tar<'_, '3, i32>>>>>>>` + | returning this value requires that `'3` must outlive `'static` + | + = note: this error originates in the macro `$crate::thread::local_impl::thread_local_inner` which comes from the expansion of the macro `thread_local` (in Nightly builds, run with -Z macro-backtrace for more info) +help: to declare that the trait object captures data from argument `init`, you can add an explicit `'_` lifetime bound + | +LL | static d: RefCell<HashMap<i32, Vec<Vec<&Tar<i32> + '_>>>> = RefCell::new(HashMap::new()); + | ++++ + +error: aborting due to 22 previous errors Some errors have detailed explanations: E0106, E0107. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/missing-lt-for-hrtb.rs b/tests/ui/suggestions/missing-lt-for-hrtb.rs index 04ea3d831c9..a48c5665d67 100644 --- a/tests/ui/suggestions/missing-lt-for-hrtb.rs +++ b/tests/ui/suggestions/missing-lt-for-hrtb.rs @@ -8,6 +8,8 @@ fn main() { let x = S(&|x| { println!("hi"); x + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough }); x.0(&X(&())); } diff --git a/tests/ui/suggestions/missing-lt-for-hrtb.stderr b/tests/ui/suggestions/missing-lt-for-hrtb.stderr index fa515644431..e8c536ac47d 100644 --- a/tests/ui/suggestions/missing-lt-for-hrtb.stderr +++ b/tests/ui/suggestions/missing-lt-for-hrtb.stderr @@ -31,6 +31,28 @@ help: consider using one of the available lifetimes here LL | struct V<'a>(&'a dyn for<'b> Fn(&X) -> &'lifetime X<'lifetime>); | +++++++++ +++++++++++ -error: aborting due to 2 previous errors +error: lifetime may not live long enough + --> $DIR/missing-lt-for-hrtb.rs:10:9 + | +LL | let x = S(&|x| { + | -- return type of closure is &'2 X<'_> + | | + | has type `&'1 X<'_>` +LL | println!("hi"); +LL | x + | ^ returning this value requires that `'1` must outlive `'2` + +error: lifetime may not live long enough + --> $DIR/missing-lt-for-hrtb.rs:10:9 + | +LL | let x = S(&|x| { + | -- return type of closure is &X<'4> + | | + | has type `&X<'3>` +LL | println!("hi"); +LL | x + | ^ returning this value requires that `'3` must outlive `'4` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0106`. diff --git a/tests/ui/suggestions/missing-trait-item.fixed b/tests/ui/suggestions/missing-trait-item.fixed index a1cf359ec91..ded4ec19760 100644 --- a/tests/ui/suggestions/missing-trait-item.fixed +++ b/tests/ui/suggestions/missing-trait-item.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait T { unsafe fn foo(a: &usize, b: &usize) -> usize; diff --git a/tests/ui/suggestions/missing-trait-item.rs b/tests/ui/suggestions/missing-trait-item.rs index b4fca25ba2f..de8974037ac 100644 --- a/tests/ui/suggestions/missing-trait-item.rs +++ b/tests/ui/suggestions/missing-trait-item.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait T { unsafe fn foo(a: &usize, b: &usize) -> usize; diff --git a/tests/ui/suggestions/missing-trait-item.stderr b/tests/ui/suggestions/missing-trait-item.stderr index 4a9d7b472c9..298d0d16438 100644 --- a/tests/ui/suggestions/missing-trait-item.stderr +++ b/tests/ui/suggestions/missing-trait-item.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `foo`, `bar` - --> $DIR/missing-trait-item.rs:10:5 + --> $DIR/missing-trait-item.rs:11:5 | LL | unsafe fn foo(a: &usize, b: &usize) -> usize; | --------------------------------------------- `foo` from trait @@ -10,7 +10,7 @@ LL | impl T for () {} | ^^^^^^^^^^^^^ missing `foo`, `bar` in implementation error[E0046]: not all trait items implemented, missing: `foo`, `bar` - --> $DIR/missing-trait-item.rs:12:5 + --> $DIR/missing-trait-item.rs:13:5 | LL | unsafe fn foo(a: &usize, b: &usize) -> usize; | --------------------------------------------- `foo` from trait diff --git a/tests/ui/tag-variant-cast-non-nullary.stderr b/tests/ui/tag-variant-cast-non-nullary.stderr index 560dd7e8164..2e1dde27d0f 100644 --- a/tests/ui/tag-variant-cast-non-nullary.stderr +++ b/tests/ui/tag-variant-cast-non-nullary.stderr @@ -4,7 +4,8 @@ error[E0605]: non-primitive cast: `NonNullary` as `isize` LL | let val = v as isize; | ^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(v)` | - = note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + = note: an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less + = note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information error: aborting due to 1 previous error diff --git a/tests/ui/threads-sendsync/sync-send-atomics.rs b/tests/ui/threads-sendsync/sync-send-atomics.rs index 0466f4f0e9d..6b260311a50 100644 --- a/tests/ui/threads-sendsync/sync-send-atomics.rs +++ b/tests/ui/threads-sendsync/sync-send-atomics.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 diff --git a/tests/ui/traits/alias/bounds.rs b/tests/ui/traits/alias/bounds.rs index b97eb38c5af..7b1920bc8f2 100644 --- a/tests/ui/traits/alias/bounds.rs +++ b/tests/ui/traits/alias/bounds.rs @@ -4,7 +4,7 @@ use std::marker::PhantomData; -trait Empty {} +trait Empty {} //~ WARN trait `Empty` is never used trait EmptyAlias = Empty; trait CloneDefault = Clone + Default; trait SendSyncAlias = Send + Sync; diff --git a/tests/ui/traits/alias/bounds.stderr b/tests/ui/traits/alias/bounds.stderr new file mode 100644 index 00000000000..7fb8e918da3 --- /dev/null +++ b/tests/ui/traits/alias/bounds.stderr @@ -0,0 +1,10 @@ +warning: trait `Empty` is never used + --> $DIR/bounds.rs:7:7 + | +LL | trait Empty {} + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/alias/syntax.rs b/tests/ui/traits/alias/syntax.rs index 17557a51aa7..50c77d33c6b 100644 --- a/tests/ui/traits/alias/syntax.rs +++ b/tests/ui/traits/alias/syntax.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(trait_alias)] diff --git a/tests/ui/traits/bound/impl-comparison-duplicates.rs b/tests/ui/traits/bound/impl-comparison-duplicates.rs index de6c2afa2bb..a59662c2797 100644 --- a/tests/ui/traits/bound/impl-comparison-duplicates.rs +++ b/tests/ui/traits/bound/impl-comparison-duplicates.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Tests that type parameter bounds on an implementation need not match the // trait exactly, as long as the implementation doesn't demand *more* bounds // than the trait. diff --git a/tests/ui/traits/bound/recursion.rs b/tests/ui/traits/bound/recursion.rs index 0023ff654e8..767040dff3f 100644 --- a/tests/ui/traits/bound/recursion.rs +++ b/tests/ui/traits/bound/recursion.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait I { fn i(&self) -> Self; } diff --git a/tests/ui/traits/composition-trivial.rs b/tests/ui/traits/composition-trivial.rs index 90e5dcd68e8..41e6a556074 100644 --- a/tests/ui/traits/composition-trivial.rs +++ b/tests/ui/traits/composition-trivial.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Foo { diff --git a/tests/ui/traits/cycle-generic-bound.rs b/tests/ui/traits/cycle-generic-bound.rs index 9241f3789d7..77685c26da2 100644 --- a/tests/ui/traits/cycle-generic-bound.rs +++ b/tests/ui/traits/cycle-generic-bound.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Regression test for #15477. This test just needs to compile. // pretty-expanded FIXME #23616 diff --git a/tests/ui/traits/default-method/bound-subst4.rs b/tests/ui/traits/default-method/bound-subst4.rs index ef133064582..6bc4cf0ef80 100644 --- a/tests/ui/traits/default-method/bound-subst4.rs +++ b/tests/ui/traits/default-method/bound-subst4.rs @@ -4,7 +4,7 @@ trait A<T> { fn g(&self, x: usize) -> usize { x } - fn h(&self, x: T) { } + fn h(&self, x: T) { } //~ WARN method `h` is never used } impl<T> A<T> for isize { } diff --git a/tests/ui/traits/default-method/bound-subst4.stderr b/tests/ui/traits/default-method/bound-subst4.stderr new file mode 100644 index 00000000000..548c46f1233 --- /dev/null +++ b/tests/ui/traits/default-method/bound-subst4.stderr @@ -0,0 +1,13 @@ +warning: method `h` is never used + --> $DIR/bound-subst4.rs:7:8 + | +LL | trait A<T> { + | - method in this trait +LL | fn g(&self, x: usize) -> usize { x } +LL | fn h(&self, x: T) { } + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/default-method/mut.rs b/tests/ui/traits/default-method/mut.rs index 5f8e983b09c..3294b96561f 100644 --- a/tests/ui/traits/default-method/mut.rs +++ b/tests/ui/traits/default-method/mut.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(unused_assignments)] // pretty-expanded FIXME #23616 diff --git a/tests/ui/traits/impl-inherent-prefer-over-trait.rs b/tests/ui/traits/impl-inherent-prefer-over-trait.rs index 82760788897..f03e730d091 100644 --- a/tests/ui/traits/impl-inherent-prefer-over-trait.rs +++ b/tests/ui/traits/impl-inherent-prefer-over-trait.rs @@ -3,7 +3,7 @@ struct Foo; trait Trait { - fn bar(&self); + fn bar(&self); //~ WARN method `bar` is never used } // Inherent impls should be preferred over trait ones. diff --git a/tests/ui/traits/impl-inherent-prefer-over-trait.stderr b/tests/ui/traits/impl-inherent-prefer-over-trait.stderr new file mode 100644 index 00000000000..f0bb21402d8 --- /dev/null +++ b/tests/ui/traits/impl-inherent-prefer-over-trait.stderr @@ -0,0 +1,12 @@ +warning: method `bar` is never used + --> $DIR/impl-inherent-prefer-over-trait.rs:6:8 + | +LL | trait Trait { + | ----- method in this trait +LL | fn bar(&self); + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/impl-object-overlap-issue-23853.rs b/tests/ui/traits/impl-object-overlap-issue-23853.rs index e490967b690..c0d3af11443 100644 --- a/tests/ui/traits/impl-object-overlap-issue-23853.rs +++ b/tests/ui/traits/impl-object-overlap-issue-23853.rs @@ -5,7 +5,7 @@ // including `Bar`, but the object type `Bar` also implicitly supplies // this context. -trait Foo { fn dummy(&self) { } } +trait Foo { fn dummy(&self) { } } //~ WARN method `dummy` is never used trait Bar: Foo { } diff --git a/tests/ui/traits/impl-object-overlap-issue-23853.stderr b/tests/ui/traits/impl-object-overlap-issue-23853.stderr new file mode 100644 index 00000000000..9fa7a36816e --- /dev/null +++ b/tests/ui/traits/impl-object-overlap-issue-23853.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/impl-object-overlap-issue-23853.rs:8:16 + | +LL | trait Foo { fn dummy(&self) { } } + | --- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/impl.rs b/tests/ui/traits/impl.rs index f512d91ebeb..7bec1b6c9ff 100644 --- a/tests/ui/traits/impl.rs +++ b/tests/ui/traits/impl.rs @@ -9,7 +9,7 @@ use traitimpl::Bar; static mut COUNT: usize = 1; trait T { - fn t(&self) {} + fn t(&self) {} //~ WARN method `t` is never used } impl<'a> dyn T+'a { diff --git a/tests/ui/traits/impl.stderr b/tests/ui/traits/impl.stderr new file mode 100644 index 00000000000..98b6fb03d83 --- /dev/null +++ b/tests/ui/traits/impl.stderr @@ -0,0 +1,12 @@ +warning: method `t` is never used + --> $DIR/impl.rs:12:8 + | +LL | trait T { + | - method in this trait +LL | fn t(&self) {} + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-33096.rs b/tests/ui/traits/issue-33096.rs index f0b472e2fe8..f0b472e2fe8 100644 --- a/tests/ui/issues/issue-33096.rs +++ b/tests/ui/traits/issue-33096.rs diff --git a/tests/ui/traits/issue-38033.rs b/tests/ui/traits/issue-38033.rs index 16b867ec88f..4d76df1e8d5 100644 --- a/tests/ui/traits/issue-38033.rs +++ b/tests/ui/traits/issue-38033.rs @@ -19,7 +19,7 @@ trait IntoFuture { type Item; type Error; - fn into_future(self) -> Self::Future; + fn into_future(self) -> Self::Future; //~ WARN method `into_future` is never used } impl<F: Future> IntoFuture for F { diff --git a/tests/ui/traits/issue-38033.stderr b/tests/ui/traits/issue-38033.stderr new file mode 100644 index 00000000000..05385e8cf4d --- /dev/null +++ b/tests/ui/traits/issue-38033.stderr @@ -0,0 +1,13 @@ +warning: method `into_future` is never used + --> $DIR/issue-38033.rs:22:8 + | +LL | trait IntoFuture { + | ---------- method in this trait +... +LL | fn into_future(self) -> Self::Future; + | ^^^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/issues/issue-40085.rs b/tests/ui/traits/issue-40085.rs index 132044cfd6d..132044cfd6d 100644 --- a/tests/ui/issues/issue-40085.rs +++ b/tests/ui/traits/issue-40085.rs diff --git a/tests/ui/traits/issue-50480.rs b/tests/ui/traits/issue-50480.rs index 683a85a32c1..cc7ea32eb3a 100644 --- a/tests/ui/traits/issue-50480.rs +++ b/tests/ui/traits/issue-50480.rs @@ -5,11 +5,13 @@ struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); //~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR cannot find type `N` in this scope +//~| ERROR `i32` is not an iterator #[derive(Clone, Copy)] //~^ ERROR the trait `Copy` cannot be implemented for this type struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); //~^ ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope +//~| ERROR `i32` is not an iterator fn main() {} diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index 4f72db60a16..68d3d5c80d0 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -38,7 +38,7 @@ LL | struct Foo<NotDefined>(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, St | ++++++++++++ error[E0412]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:11:18 + --> $DIR/issue-50480.rs:12:18 | LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); | - ^ @@ -55,7 +55,7 @@ LL | struct Bar<T, N>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, Strin | +++ error[E0412]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:11:21 + --> $DIR/issue-50480.rs:12:21 | LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); | ^^^^^^^^^^ not found in this scope @@ -74,7 +74,7 @@ LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-50480.rs:9:17 + --> $DIR/issue-50480.rs:10:17 | LL | #[derive(Clone, Copy)] | ^^^^ @@ -86,7 +86,25 @@ LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); | = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 8 previous errors +error[E0277]: `i32` is not an iterator + --> $DIR/issue-50480.rs:3:27 + | +LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + +error[E0277]: `i32` is not an iterator + --> $DIR/issue-50480.rs:12:33 + | +LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); + | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + +error: aborting due to 10 previous errors -Some errors have detailed explanations: E0204, E0412. +Some errors have detailed explanations: E0204, E0277, E0412. For more information about an error, try `rustc --explain E0204`. diff --git a/tests/ui/traits/issue-56488.rs b/tests/ui/traits/issue-56488.rs index e2f3996927b..8b68f314c04 100644 --- a/tests/ui/traits/issue-56488.rs +++ b/tests/ui/traits/issue-56488.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(trait_alias)] diff --git a/tests/ui/issues/issue-58344.rs b/tests/ui/traits/issue-58344.rs index 0cb04dcb22a..0cb04dcb22a 100644 --- a/tests/ui/issues/issue-58344.rs +++ b/tests/ui/traits/issue-58344.rs diff --git a/tests/ui/traits/issue-59029-2.rs b/tests/ui/traits/issue-59029-2.rs index 2bdb128d8c4..fca9f1f13c9 100644 --- a/tests/ui/traits/issue-59029-2.rs +++ b/tests/ui/traits/issue-59029-2.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(trait_alias)] trait Svc<Req> { type Res; } diff --git a/tests/ui/traits/issue-6128.rs b/tests/ui/traits/issue-6128.rs index 07d92f8f8a0..f5fa0de809a 100644 --- a/tests/ui/traits/issue-6128.rs +++ b/tests/ui/traits/issue-6128.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; trait Graph<Node, Edge> { - fn f(&self, _: Edge); + fn f(&self, _: Edge); //~ WARN methods `f` and `g` are never used fn g(&self, _: Node); } diff --git a/tests/ui/traits/issue-6128.stderr b/tests/ui/traits/issue-6128.stderr new file mode 100644 index 00000000000..c9518ea41ea --- /dev/null +++ b/tests/ui/traits/issue-6128.stderr @@ -0,0 +1,14 @@ +warning: methods `f` and `g` are never used + --> $DIR/issue-6128.rs:6:8 + | +LL | trait Graph<Node, Edge> { + | ----- methods in this trait +LL | fn f(&self, _: Edge); + | ^ +LL | fn g(&self, _: Node); + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/issue-78372.rs b/tests/ui/traits/issue-78372.rs index 92f9f4b467a..143325c097c 100644 --- a/tests/ui/traits/issue-78372.rs +++ b/tests/ui/traits/issue-78372.rs @@ -6,8 +6,9 @@ impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} //~ ERROR cannot find type `U` //~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures trait Foo: X<u32> {} trait X<T> { - fn foo(self: Smaht<Self, T>); + fn foo(self: Smaht<Self, T>); //~ ERROR: invalid `self` } trait Marker {} impl Marker for dyn Foo {} +//~^ ERROR cannot be made into an object fn main() {} diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr index 44a62988daf..edb07957c44 100644 --- a/tests/ui/traits/issue-78372.stderr +++ b/tests/ui/traits/issue-78372.stderr @@ -61,7 +61,34 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/issue-78372.rs:12:17 + | +LL | fn foo(self: Smaht<Self, T>); + | -------------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` +... +LL | impl Marker for dyn Foo {} + | ^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/issue-78372.rs:9:18 + | +LL | trait Foo: X<u32> {} + | --- this trait cannot be made into an object... +LL | trait X<T> { +LL | fn foo(self: Smaht<Self, T>); + | ^^^^^^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on -Some errors have detailed explanations: E0378, E0412, E0658. -For more information about an error, try `rustc --explain E0378`. +error[E0307]: invalid `self` parameter type: Smaht<Self, T> + --> $DIR/issue-78372.rs:9:18 + | +LL | fn foo(self: Smaht<Self, T>); + | ^^^^^^^^^^^^^^ + | + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0038, E0307, E0378, E0412, E0658. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/method-on-unbounded-type-param.rs b/tests/ui/traits/method-on-unbounded-type-param.rs new file mode 100644 index 00000000000..8505eb41e98 --- /dev/null +++ b/tests/ui/traits/method-on-unbounded-type-param.rs @@ -0,0 +1,15 @@ +fn f<T>(a: T, b: T) -> std::cmp::Ordering { + a.cmp(&b) //~ ERROR E0599 +} +fn g<T>(a: T, b: T) -> std::cmp::Ordering { + (&a).cmp(&b) //~ ERROR E0599 +} +fn h<T>(a: &T, b: T) -> std::cmp::Ordering { + a.cmp(&b) //~ ERROR E0599 +} +trait T {} +impl<X: std::cmp::Ord> T for X {} +fn main() { + let x: Box<dyn T> = Box::new(0); + x.cmp(&x); //~ ERROR E0599 +} diff --git a/tests/ui/traits/method-on-unbounded-type-param.stderr b/tests/ui/traits/method-on-unbounded-type-param.stderr new file mode 100644 index 00000000000..0d8bd8ee964 --- /dev/null +++ b/tests/ui/traits/method-on-unbounded-type-param.stderr @@ -0,0 +1,84 @@ +error[E0599]: no method named `cmp` found for type parameter `T` in the current scope + --> $DIR/method-on-unbounded-type-param.rs:2:7 + | +LL | fn f<T>(a: T, b: T) -> std::cmp::Ordering { + | - method `cmp` not found for this type parameter +LL | a.cmp(&b) + | ^^^ method cannot be called on `T` due to unsatisfied trait bounds + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them: + | +LL | fn f<T: Ord>(a: T, b: T) -> std::cmp::Ordering { + | +++++ +LL | fn f<T: Iterator>(a: T, b: T) -> std::cmp::Ordering { + | ++++++++++ + +error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied + --> $DIR/method-on-unbounded-type-param.rs:5:10 + | +LL | (&a).cmp(&b) + | ^^^ method cannot be called on `&T` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `T: Ord` + which is required by `&T: Ord` + `&T: Iterator` + which is required by `&mut &T: Iterator` + `T: Iterator` + which is required by `&mut T: Iterator` + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them: + | +LL | fn g<T: Ord>(a: T, b: T) -> std::cmp::Ordering { + | +++++ +LL | fn g<T: Iterator>(a: T, b: T) -> std::cmp::Ordering { + | ++++++++++ + +error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied + --> $DIR/method-on-unbounded-type-param.rs:8:7 + | +LL | a.cmp(&b) + | ^^^ method cannot be called on `&T` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `T: Ord` + which is required by `&T: Ord` + `&T: Iterator` + which is required by `&mut &T: Iterator` + `T: Iterator` + which is required by `&mut T: Iterator` + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them: + | +LL | fn h<T: Ord>(a: &T, b: T) -> std::cmp::Ordering { + | +++++ +LL | fn h<T: Iterator>(a: &T, b: T) -> std::cmp::Ordering { + | ++++++++++ + +error[E0599]: the method `cmp` exists for struct `Box<dyn T>`, but its trait bounds were not satisfied + --> $DIR/method-on-unbounded-type-param.rs:14:7 + | +LL | trait T {} + | ------- doesn't satisfy `dyn T: Iterator` or `dyn T: Ord` +... +LL | x.cmp(&x); + | ^^^ method cannot be called on `Box<dyn T>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `dyn T: Iterator` + which is required by `Box<dyn T>: Iterator` + `dyn T: Ord` + which is required by `Box<dyn T>: Ord` + `Box<dyn T>: Iterator` + which is required by `&mut Box<dyn T>: Iterator` + `dyn T: Iterator` + which is required by `&mut dyn T: Iterator` + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following traits define an item `cmp`, perhaps you need to implement one of them: + candidate #1: `Ord` + candidate #2: `Iterator` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs b/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs index f845e198aa5..e9ae8ab012a 100644 --- a/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs +++ b/tests/ui/traits/multidispatch-conditional-impl-not-considered.rs @@ -6,7 +6,7 @@ use std::cell::RefCell; -trait Foo { +trait Foo { //~ WARN trait `Foo` is never used fn foo(&self) {} } diff --git a/tests/ui/traits/multidispatch-conditional-impl-not-considered.stderr b/tests/ui/traits/multidispatch-conditional-impl-not-considered.stderr new file mode 100644 index 00000000000..25313a477f7 --- /dev/null +++ b/tests/ui/traits/multidispatch-conditional-impl-not-considered.stderr @@ -0,0 +1,10 @@ +warning: trait `Foo` is never used + --> $DIR/multidispatch-conditional-impl-not-considered.rs:9:7 + | +LL | trait Foo { + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/multidispatch-infer-convert-target.rs b/tests/ui/traits/multidispatch-infer-convert-target.rs index 626e1ae71bc..a3653dea2cb 100644 --- a/tests/ui/traits/multidispatch-infer-convert-target.rs +++ b/tests/ui/traits/multidispatch-infer-convert-target.rs @@ -5,7 +5,7 @@ use std::mem; trait Convert<Target> { - fn convert(&self) -> Target; + fn convert(&self) -> Target; //~ WARN method `convert` is never used } impl Convert<u32> for i16 { diff --git a/tests/ui/traits/multidispatch-infer-convert-target.stderr b/tests/ui/traits/multidispatch-infer-convert-target.stderr new file mode 100644 index 00000000000..c8c1b642719 --- /dev/null +++ b/tests/ui/traits/multidispatch-infer-convert-target.stderr @@ -0,0 +1,12 @@ +warning: method `convert` is never used + --> $DIR/multidispatch-infer-convert-target.rs:8:8 + | +LL | trait Convert<Target> { + | ------- method in this trait +LL | fn convert(&self) -> Target; + | ^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/negative-impls/negative-specializes-negative.rs b/tests/ui/traits/negative-impls/negative-specializes-negative.rs index 35297ab124e..01829e41301 100644 --- a/tests/ui/traits/negative-impls/negative-specializes-negative.rs +++ b/tests/ui/traits/negative-impls/negative-specializes-negative.rs @@ -3,7 +3,7 @@ // Test a negative impl that "specializes" another negative impl. // -// run-pass +// check-pass trait MyTrait {} diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs index af471b5e193..d7a2c8e7a92 100644 --- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs +++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs @@ -8,6 +8,7 @@ trait Overflow { } impl<T> Overflow for T { type Assoc = <T as Overflow>::Assoc; + //~^ ERROR: overflow } diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr index e3c0dabf549..583945723d5 100644 --- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `<LocalTy as Overflow>::Assoc` - --> $DIR/trait_ref_is_knowable-norm-overflow.rs:17:1 + --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1 | LL | impl<T: Copy> Trait for T {} | ------------------------- first implementation here @@ -7,6 +7,24 @@ LL | struct LocalTy; LL | impl Trait for <LocalTy as Overflow>::Assoc {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<LocalTy as Overflow>::Assoc` -error: aborting due to 1 previous error +error[E0275]: overflow evaluating the requirement `<T as Overflow>::Assoc: Sized` + --> $DIR/trait_ref_is_knowable-norm-overflow.rs:10:18 + | +LL | type Assoc = <T as Overflow>::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`) +note: required by a bound in `Overflow::Assoc` + --> $DIR/trait_ref_is_knowable-norm-overflow.rs:7:5 + | +LL | type Assoc; + | ^^^^^^^^^^^ required by this bound in `Overflow::Assoc` +help: consider relaxing the implicit `Sized` restriction + | +LL | type Assoc: ?Sized; + | ++++++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0119, E0275. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs index c7e2e2d5e04..f6c75317a34 100644 --- a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs +++ b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs @@ -24,6 +24,18 @@ where { } +// HACK: This impls is necessary so that the impl above is well-formed. +// +// When checking that the impl above is well-formed we check `B<T>: Trait<'a, 'b>` +// with the where clauses `A<T>: Trait<'a, 'b>` and `A<T> NotImplemented`. Trying to +// use the impl itself to prove that adds region constraints as we uniquified the +// regions in the `A<T>: Trait<'a, 'b>` where-bound. As both the impl above +// and the impl below now apply with some constraints, we failed with ambiguity. +impl<'a, 'b, T: ?Sized> Trait<'a, 'b> for B<T> +where + A<T>: NotImplemented, +{} + // This impl directly requires 'b to be equal to 'static. // // Because of the coinductive cycle through `C<T>` it also requires diff --git a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr index 7b3075f4ff3..0cbd9654044 100644 --- a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr +++ b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/fixpoint-rerun-all-cycle-heads.rs:47:5 + --> $DIR/fixpoint-rerun-all-cycle-heads.rs:59:5 | LL | fn check<'a, T: ?Sized>() { | -- lifetime `'a` defined here diff --git a/tests/ui/traits/next-solver/env-shadows-impls/ambig-env-no-shadow.rs b/tests/ui/traits/next-solver/env-shadows-impls/ambig-env-no-shadow.rs new file mode 100644 index 00000000000..37730d38c7a --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/ambig-env-no-shadow.rs @@ -0,0 +1,40 @@ +// compile-flags: -Znext-solver +// check-pass + +// If a trait goal is proven using the environment, we discard +// impl candidates when normalizing. However, in this example +// the env candidates start as ambiguous and end up not applying, +// so normalization should succeed later on. + +trait Trait<T>: Sized { + type Assoc: From<Self>; +} + +impl<T, U> Trait<U> for T { + type Assoc = T; +} + +fn mk_assoc<T: Trait<U>, U>(t: T, _: U) -> <T as Trait<U>>::Assoc { + t.into() +} + +fn generic<T>(t: T) -> T +where + T: Trait<u32>, + T: Trait<i16>, +{ + let u = Default::default(); + + // at this point we have 2 ambig env candidates + let ret: T = mk_assoc(t, u); + + // now both env candidates don't apply, so we're now able to + // normalize using this impl candidates. For this to work + // the normalizes-to must have remained ambiguous above. + let _: u8 = u; + ret +} + +fn main() { + assert_eq!(generic(1), 1); +} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-1.rs b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-1.rs new file mode 100644 index 00000000000..63742d0d1a1 --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-1.rs @@ -0,0 +1,30 @@ +// compile-flags: -Znext-solver +// check-pass + +// Normalizing `<T as Trait>::TraitAssoc` in the elaborated environment +// `[T: Trait, T: Super, <T as Super>::SuperAssoc = <T as Trait>::TraitAssoc]` +// has a single impl candidate, which uses the environment to +// normalize `<T as Trait>::TraitAssoc` to itself. We avoid this overflow +// by discarding impl candidates the trait bound is proven by a where-clause. + +// https://github.com/rust-lang/trait-system-refactor-initiative/issues/76 +trait Super { + type SuperAssoc; +} + +trait Trait: Super<SuperAssoc = Self::TraitAssoc> { + type TraitAssoc; +} + +impl<T, U> Trait for T +where + T: Super<SuperAssoc = U>, +{ + type TraitAssoc = U; +} + +fn overflow<T: Trait>() { + let x: <T as Trait>::TraitAssoc; +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-2.rs b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-2.rs new file mode 100644 index 00000000000..b0ef0d44baf --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-2.rs @@ -0,0 +1,29 @@ +// revisions: next current +//[next] compile-flags: -Znext-solver +// check-pass + +#![allow(warnings)] +trait Trait<U> { + type Assoc; +} + +impl<T> Trait<u64> for T { + type Assoc = T; +} + +fn lazy_init<T: Trait<U>, U>() -> (T, <T as Trait<U>>::Assoc) { + todo!() +} + +fn foo<T: Trait<u32, Assoc = T>>(x: T) { + // When considering impl candidates to be equally valid as env candidates + // this ends up being ambiguous as `U` can be both `u32´ and `u64` here. + // + // This is acceptable breakage but we should still note that it's + // theoretically breaking. + let (delayed, mut proj) = lazy_init::<_, _>(); + proj = x; + let _: T = delayed; +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-3.rs b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-3.rs new file mode 100644 index 00000000000..807e19a4a58 --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-3.rs @@ -0,0 +1,18 @@ +// compile-flags: -Znext-solver +// check-pass + +// If we normalize using the impl here the constraints from normalization and +// trait goals can differ. This is especially bad if normalization results +// in stronger constraints. +trait Trait<'a> { + type Assoc; +} + +impl<T> Trait<'static> for T { + type Assoc = (); +} + +// normalizing requires `'a == 'static`, the trait bound does not. +fn foo<'a, T: Trait<'a>>(_: T::Assoc) {} + +fn main() {} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/normalizes_to_ignores_unnormalizable_candidate.rs b/tests/ui/traits/next-solver/env-shadows-impls/normalizes_to_ignores_unnormalizable_candidate.rs new file mode 100644 index 00000000000..af2c44ea233 --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/normalizes_to_ignores_unnormalizable_candidate.rs @@ -0,0 +1,29 @@ +// compile-flags: -Znext-solver + +// Checks whether the new solver is smart enough to infer `?0 = U` when solving: +// `normalizes-to(<Vec<?0> as Trait>::Assoc, u8)` +// with `normalizes-to(<Vec<U> as Trait>::Assoc, u8)` in the paramenv even when +// there is a separate `Vec<T>: Trait` bound in the paramenv. +// +// We currently intentionally do not guide inference this way. + +trait Trait { + type Assoc; +} + +fn foo<T: Trait<Assoc = u8>>(x: T) {} + +fn unconstrained<T>() -> Vec<T> { + todo!() +} + +fn bar<T, U>() +where + Vec<T>: Trait, + Vec<U>: Trait<Assoc = u8>, +{ + foo(unconstrained()) + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr b/tests/ui/traits/next-solver/env-shadows-impls/normalizes_to_ignores_unnormalizable_candidate.stderr index c1a8b74df08..36d281e11dd 100644 --- a/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.self_infer.stderr +++ b/tests/ui/traits/next-solver/env-shadows-impls/normalizes_to_ignores_unnormalizable_candidate.stderr @@ -1,21 +1,21 @@ error[E0283]: type annotations needed - --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:36:5 + --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:25:5 | LL | foo(unconstrained()) | ^^^ --------------- type must be known at this point | | | cannot infer type of the type parameter `T` declared on the function `foo` | - = note: cannot satisfy `_: Trait` + = note: cannot satisfy `Vec<_>: Trait` note: required by a bound in `foo` - --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:19:11 + --> $DIR/normalizes_to_ignores_unnormalizable_candidate.rs:14:11 | LL | fn foo<T: Trait<Assoc = u8>>(x: T) {} | ^^^^^^^^^^^^^^^^^ required by this bound in `foo` help: consider specifying the generic argument | -LL | foo::<T>(unconstrained()) - | +++++ +LL | foo::<Vec<T>>(unconstrained()) + | ++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs new file mode 100644 index 00000000000..5989e605bd9 --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.rs @@ -0,0 +1,31 @@ +// compile-flags: -Znext-solver + +trait Foo { + type Assoc; +} + +trait Bar {} + +impl<T> Foo for T { + type Assoc = i32; +} + +impl<T> Bar for T where T: Foo<Assoc = i32> {} + +fn require_bar<T: Bar>() {} + +fn foo<T: Foo>() { + // Unlike the classic solver, the new solver previously projected + // `<T as Foo>::Assoc = _` down to `i32` even though there's a param-env + // candidate here, since we don't assemble any param-env projection + // candidates for `T: Foo` alone. + // + // However, allowing impl candidates shadowed by env candidates results + // in multiple issues, so we explicitly hide them, e.g. + // + // https://github.com/rust-lang/trait-system-refactor-initiative/issues/76 + require_bar::<T>(); + //~^ ERROR the trait bound `T: Bar` is not satisfied +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr new file mode 100644 index 00000000000..2785357e792 --- /dev/null +++ b/tests/ui/traits/next-solver/env-shadows-impls/param-candidate-shadows-project.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `T: Bar` is not satisfied + --> $DIR/param-candidate-shadows-project.rs:27:19 + | +LL | require_bar::<T>(); + | ^ the trait `Bar` is not implemented for `T` + | +note: required by a bound in `require_bar` + --> $DIR/param-candidate-shadows-project.rs:15:19 + | +LL | fn require_bar<T: Bar>() {} + | ^^^ required by this bound in `require_bar` +help: consider further restricting this bound + | +LL | fn foo<T: Foo + Bar>() { + | +++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr index ad8b24a39c7..aaadf604a80 100644 --- a/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr +++ b/tests/ui/traits/next-solver/generalize/occurs-check-nested-alias.next.stderr @@ -1,11 +1,9 @@ -error[E0275]: overflow evaluating the requirement `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _` +error[E0284]: type annotations needed: cannot satisfy `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _` --> $DIR/occurs-check-nested-alias.rs:36:9 | LL | x = y; - | ^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`occurs_check_nested_alias`) + | ^ cannot satisfy `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0275`. +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.rs b/tests/ui/traits/next-solver/issue-118950-root-region.rs index 10fb7d525b7..c50276c78b4 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.rs +++ b/tests/ui/traits/next-solver/issue-118950-root-region.rs @@ -12,6 +12,7 @@ trait ToUnit<'a> { trait Overlap<T> {} type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; +//~^ ERROR: not well-formed impl<T> Overlap<T> for T {} diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index c16a48d5f15..f4638348358 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -1,5 +1,5 @@ error[E0412]: cannot find type `Missing` in this scope - --> $DIR/issue-118950-root-region.rs:18:55 + --> $DIR/issue-118950-root-region.rs:19:55 | LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {} | ^^^^^^^ not found in this scope @@ -22,7 +22,7 @@ WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [ReBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) WARN rustc_infer::infer::relate::generalize may incompletely handle alias type: Alias(Weak, AliasTy { args: [RePlaceholder(!1_BoundRegion { var: 0, kind: BrNamed(DefId(0:15 ~ issue_118950_root_region[d54f]::{impl#1}::'a), 'a) }), ?1t], def_id: DefId(0:8 ~ issue_118950_root_region[d54f]::Assoc) }) error[E0119]: conflicting implementations of trait `Overlap<fn(_)>` for type `fn(_)` - --> $DIR/issue-118950-root-region.rs:18:1 + --> $DIR/issue-118950-root-region.rs:19:1 | LL | impl<T> Overlap<T> for T {} | ------------------------ first implementation here @@ -30,7 +30,13 @@ LL | LL | impl<T> Overlap<for<'a> fn(Assoc<'a, T>)> for T where Missing: Overlap<T> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(_)` -error: aborting due to 2 previous errors; 1 warning emitted +error: the type `<*const T as ToUnit<'a>>::Unit` is not well-formed + --> $DIR/issue-118950-root-region.rs:14:21 + | +LL | type Assoc<'a, T> = <*const T as ToUnit<'a>>::Unit; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted Some errors have detailed explanations: E0119, E0412. For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/next-solver/normalize-param-env-2.rs b/tests/ui/traits/next-solver/normalize-param-env-2.rs index ce084651bfb..9da1f8dbec1 100644 --- a/tests/ui/traits/next-solver/normalize-param-env-2.rs +++ b/tests/ui/traits/next-solver/normalize-param-env-2.rs @@ -1,24 +1,29 @@ -// check-pass // compile-flags: -Znext-solver -// Issue 92505 +// known-bug: #92505 +// When checking that the impl method where-bounds are implied by the trait, +// we prove `<() as A<T>>::Assoc: A<T>` in the environment `<() as A<T>>::Assoc: A<T>`. +// +// Normalizing `<() as A<T>>::Assoc` is ambiguous in that environment. The +// where-bound `<() as A<T>>::Assoc: A<T>` may apply, resulting in overflow. trait A<T> { - type I; + type Assoc; fn f() where - Self::I: A<T>, + Self::Assoc: A<T>, { } } impl<T> A<T> for () { - type I = (); + type Assoc = (); fn f() where - Self::I: A<T>, + Self::Assoc: A<T>, { + <() as A<T>>::f(); } } diff --git a/tests/ui/traits/next-solver/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize-param-env-2.stderr new file mode 100644 index 00000000000..a52022e539e --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-param-env-2.stderr @@ -0,0 +1,35 @@ +error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>` + --> $DIR/normalize-param-env-2.rs:24:22 + | +LL | Self::Assoc: A<T>, + | ^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`normalize_param_env_2`) +note: the requirement `<() as A<T>>::Assoc: A<T>` appears on the `impl`'s method `f` but not on the corresponding trait's method + --> $DIR/normalize-param-env-2.rs:12:8 + | +LL | trait A<T> { + | - in this trait +... +LL | fn f() + | ^ this trait's method doesn't have the requirement `<() as A<T>>::Assoc: A<T>` + +error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>` + --> $DIR/normalize-param-env-2.rs:24:22 + | +LL | Self::Assoc: A<T>, + | ^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`normalize_param_env_2`) + +error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc well-formed` + --> $DIR/normalize-param-env-2.rs:24:22 + | +LL | Self::Assoc: A<T>, + | ^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`normalize_param_env_2`) + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize-param-env-4.next.stderr new file mode 100644 index 00000000000..dec820c61b0 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-param-env-4.next.stderr @@ -0,0 +1,19 @@ +error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: Trait` + --> $DIR/normalize-param-env-4.rs:18:26 + | +LL | <T as Trait>::Assoc: Trait, + | ^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`normalize_param_env_4`) + +error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc well-formed` + --> $DIR/normalize-param-env-4.rs:18:26 + | +LL | <T as Trait>::Assoc: Trait, + | ^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`normalize_param_env_4`) + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/normalize-param-env-4.rs b/tests/ui/traits/next-solver/normalize-param-env-4.rs new file mode 100644 index 00000000000..d49f7492297 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-param-env-4.rs @@ -0,0 +1,34 @@ +// revisions: current next +//[next] compile-flags: -Znext-solver +//[next] known-bug: #92505 +//[current] check-pass + +trait Trait { + type Assoc; +} + +impl<T> Trait for T { + type Assoc = T; +} + +fn impls_trait<T: Trait>() {} + +fn foo<T>() +where + <T as Trait>::Assoc: Trait, +{ + // Trying to use `<T as Trait>::Assoc: Trait` to prove `T: Trait` + // requires normalizing `<T as Trait>::Assoc`. We do not normalize + // using impl candidates if there's a where-bound for that trait. + // + // We therefore check whether `T: Trait` is proven by the environment. + // For that we try to apply the `<T as Trait>::Assoc: Trait` candidate, + // trying to normalize its self type results in overflow. + // + // In the old solver we eagerly normalize the environment, ignoring the + // unnormalized `<T as Trait>::Assoc: Trait` where-bound when normalizing + // `<T as Trait>::Asosc` + impls_trait::<T>(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize-region-obligations.rs b/tests/ui/traits/next-solver/normalize-region-obligations.rs index 13c86b630f6..d189e4893a3 100644 --- a/tests/ui/traits/next-solver/normalize-region-obligations.rs +++ b/tests/ui/traits/next-solver/normalize-region-obligations.rs @@ -1,4 +1,4 @@ -// revisions: normalize_param_env normalize_obligation +// revisions: normalize_param_env normalize_obligation hrtb // check-pass // compile-flags: -Znext-solver @@ -7,16 +7,23 @@ trait Foo { type Gat<'a> where <Self as Mirror>::Assoc: 'a; #[cfg(normalize_obligation)] type Gat<'a> where Self: 'a; + #[cfg(hrtb)] + type Gat<'b> where for<'a> <Self as MirrorRegion<'a>>::Assoc: 'b; } trait Mirror { type Assoc: ?Sized; } impl<T: ?Sized> Mirror for T { type Assoc = T; } +trait MirrorRegion<'a> { type Assoc: ?Sized; } +impl<'a, T> MirrorRegion<'a> for T { type Assoc = T; } + impl<T> Foo for T { #[cfg(normalize_param_env)] type Gat<'a> = i32 where T: 'a; #[cfg(normalize_obligation)] type Gat<'a> = i32 where <T as Mirror>::Assoc: 'a; + #[cfg(hrtb)] + type Gat<'b> = i32 where Self: 'b; } fn main() {} diff --git a/tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs b/tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs new file mode 100644 index 00000000000..7477c56cd54 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-type-outlives-in-param-env.rs @@ -0,0 +1,18 @@ +// check-pass +// compile-flags: -Znext-solver + +trait Mirror { + type Assoc; +} + +impl<T> Mirror for T { + type Assoc = T; +} + +fn is_static<T: 'static>() {} + +fn test<T>() where <T as Mirror>::Assoc: 'static { + is_static::<T>(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize-type-outlives.rs b/tests/ui/traits/next-solver/normalize-type-outlives.rs new file mode 100644 index 00000000000..f50eb6326e2 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-type-outlives.rs @@ -0,0 +1,13 @@ +// check-pass + +trait Tr<'a> { + type Assoc; +} + +fn outlives<'o, T: 'o>() {} + +fn foo<'a, 'b, T: Tr<'a, Assoc = ()>>() { + outlives::<'b, T::Assoc>(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.rs b/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.rs deleted file mode 100644 index 7dc87daccd9..00000000000 --- a/tests/ui/traits/next-solver/normalizes_to_ignores_unnormalizable_candidate.rs +++ /dev/null @@ -1,40 +0,0 @@ -// [no_self_infer] check-pass -// compile-flags: -Znext-solver -// revisions: self_infer no_self_infer - -// checks that the new solver is smart enough to infer `?0 = U` when solving: -// `normalizes-to(<Vec<?0> as Trait>::Assoc, u8)` -// with `normalizes-to(<Vec<U> as Trait>::Assoc, u8)` in the paramenv even when -// there is a separate `Vec<T>: Trait` bound in the paramenv. -// -// FIXME(-Znext-solver) -// This could also compile for `normalizes-to(<?0 as Trait>::Assoc, u8)` but -// we currently immediately consider a goal ambiguous if the self type is an -// inference variable. - -trait Trait { - type Assoc; -} - -fn foo<T: Trait<Assoc = u8>>(x: T) {} - -#[cfg(self_infer)] -fn unconstrained<T>() -> T { - todo!() -} - -#[cfg(no_self_infer)] -fn unconstrained<T>() -> Vec<T> { - todo!() -} - -fn bar<T, U>() -where - Vec<T>: Trait, - Vec<U>: Trait<Assoc = u8>, -{ - foo(unconstrained()) - //[self_infer]~^ ERROR type annotations needed -} - -fn main() {} diff --git a/tests/ui/traits/next-solver/param-candidate-doesnt-shadow-project.rs b/tests/ui/traits/next-solver/param-candidate-doesnt-shadow-project.rs deleted file mode 100644 index f67b073c53c..00000000000 --- a/tests/ui/traits/next-solver/param-candidate-doesnt-shadow-project.rs +++ /dev/null @@ -1,25 +0,0 @@ -// compile-flags: -Znext-solver -// check-pass - -trait Foo { - type Assoc; -} - -trait Bar {} - -impl<T> Foo for T { - type Assoc = i32; -} - -impl<T> Bar for T where T: Foo<Assoc = i32> {} - -fn require_bar<T: Bar>() {} - -fn foo<T: Foo>() { - // Unlike the classic solver, `<T as Foo>::Assoc = _` will still project - // down to `i32` even though there's a param-env candidate here, since we - // don't assemble any param-env projection candidates for `T: Foo` alone. - require_bar::<T>(); -} - -fn main() {} diff --git a/tests/ui/traits/next-solver/specialization-transmute.rs b/tests/ui/traits/next-solver/specialization-transmute.rs index 6f93a1d3f40..d96936f60f7 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.rs +++ b/tests/ui/traits/next-solver/specialization-transmute.rs @@ -1,5 +1,5 @@ // compile-flags: -Znext-solver -//~^ ERROR cannot normalize `<T as Default>::Id` +//~^ ERROR cannot normalize `<T as Default>::Id: '_` #![feature(specialization)] //~^ WARN the feature `specialization` is incomplete diff --git a/tests/ui/traits/next-solver/specialization-transmute.stderr b/tests/ui/traits/next-solver/specialization-transmute.stderr index 946a7cbaa80..ea1ae387f56 100644 --- a/tests/ui/traits/next-solver/specialization-transmute.stderr +++ b/tests/ui/traits/next-solver/specialization-transmute.stderr @@ -8,7 +8,7 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default -error: cannot normalize `<T as Default>::Id` +error: cannot normalize `<T as Default>::Id: '_` error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id == _` --> $DIR/specialization-transmute.rs:16:23 diff --git a/tests/ui/traits/object/pretty.rs b/tests/ui/traits/object/pretty.rs new file mode 100644 index 00000000000..8958871ed5d --- /dev/null +++ b/tests/ui/traits/object/pretty.rs @@ -0,0 +1,37 @@ +// Test for pretty-printing trait object types. + +trait Super { + type Assoc; +} +trait Any: Super {} +trait Fixed: Super<Assoc = u8> {} +trait FixedSub: Fixed {} +trait FixedStatic: Super<Assoc = &'static u8> {} + +trait SuperGeneric<'a> { + type Assoc2; +} +trait AnyGeneric<'a>: SuperGeneric<'a> {} +trait FixedGeneric1<'a>: SuperGeneric<'a, Assoc2 = &'a u8> {} +trait FixedGeneric2<'a>: Super<Assoc = &'a u8> {} +trait FixedHrtb: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> {} +trait AnyDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super {} +trait FixedDifferentBinders: for<'a> SuperGeneric<'a, Assoc2 = &'a u8> + Super<Assoc = u8> {} + +fn dyn_super(x: &dyn Super<Assoc = u8>) { x } //~ERROR mismatched types +fn dyn_any(x: &dyn Any<Assoc = u8>) { x } //~ERROR mismatched types +fn dyn_fixed(x: &dyn Fixed) { x } //~ERROR mismatched types +fn dyn_fixed_multi(x: &dyn Fixed<Assoc = u16>) { x } //~ERROR mismatched types +fn dyn_fixed_sub(x: &dyn FixedSub) { x } //~ERROR mismatched types +fn dyn_fixed_static(x: &dyn FixedStatic) { x } //~ERROR mismatched types + +fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x } //~ERROR mismatched types +fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } //~ERROR mismatched types +fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } //~ERROR mismatched types +fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } //~ERROR mismatched types +fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } //~ERROR mismatched types +fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } //~ERROR mismatched types +fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x } //~ERROR mismatched types +fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } //~ERROR mismatched types + +fn main() {} diff --git a/tests/ui/traits/object/pretty.stderr b/tests/ui/traits/object/pretty.stderr new file mode 100644 index 00000000000..bc645e5f967 --- /dev/null +++ b/tests/ui/traits/object/pretty.stderr @@ -0,0 +1,157 @@ +error[E0308]: mismatched types + --> $DIR/pretty.rs:21:43 + | +LL | fn dyn_super(x: &dyn Super<Assoc = u8>) { x } + | - ^ expected `()`, found `&dyn Super<Assoc = u8>` + | | + | help: try adding a return type: `-> &dyn Super<Assoc = u8>` + | + = note: expected unit type `()` + found reference `&dyn Super<Assoc = u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:22:39 + | +LL | fn dyn_any(x: &dyn Any<Assoc = u8>) { x } + | - ^ expected `()`, found `&dyn Any<Assoc = u8>` + | | + | help: try adding a return type: `-> &dyn Any<Assoc = u8>` + | + = note: expected unit type `()` + found reference `&dyn Any<Assoc = u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:23:31 + | +LL | fn dyn_fixed(x: &dyn Fixed) { x } + | - ^ expected `()`, found `&dyn Fixed` + | | + | help: try adding a return type: `-> &dyn Fixed` + | + = note: expected unit type `()` + found reference `&dyn Fixed` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:24:50 + | +LL | fn dyn_fixed_multi(x: &dyn Fixed<Assoc = u16>) { x } + | - ^ expected `()`, found `&dyn Fixed<Assoc = u16>` + | | + | help: try adding a return type: `-> &dyn Fixed<Assoc = u16>` + | + = note: expected unit type `()` + found reference `&dyn Fixed<Assoc = u16>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:25:38 + | +LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x } + | - ^ expected `()`, found `&dyn FixedSub` + | | + | help: try adding a return type: `-> &dyn FixedSub` + | + = note: expected unit type `()` + found reference `&dyn FixedSub` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:26:44 + | +LL | fn dyn_fixed_static(x: &dyn FixedStatic) { x } + | - ^ expected `()`, found `&dyn FixedStatic` + | | + | help: try adding a return type: `-> &dyn FixedStatic` + | + = note: expected unit type `()` + found reference `&dyn FixedStatic` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:28:75 + | +LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>) { x } + | - ^ expected `()`, found `&dyn SuperGeneric<'a, Assoc2 = &u8>` + | | + | help: try adding a return type: `-> &dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> SuperGeneric<'a, Assoc2 = &'a u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:29:71 + | +LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>) { x } + | - ^ expected `()`, found `&dyn AnyGeneric<'a, Assoc2 = &u8>` + | | + | help: try adding a return type: `-> &dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> AnyGeneric<'a, Assoc2 = &'a u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:30:60 + | +LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x } + | - ^ expected `()`, found `&dyn FixedGeneric1<'a>` + | | + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> FixedGeneric1<'a>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:31:60 + | +LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x } + | - ^ expected `()`, found `&dyn FixedGeneric2<'a>` + | | + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric2<'a>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> FixedGeneric2<'a>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:32:79 + | +LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>) { x } + | - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc2 = ...>` + | | + | help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>` + | + = note: expected unit type `()` + found reference `&dyn for<'a> FixedGeneric1<'a, Assoc2 = &u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:33:40 + | +LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x } + | - ^ expected `()`, found `&dyn FixedHrtb` + | | + | help: try adding a return type: `-> &dyn FixedHrtb` + | + = note: expected unit type `()` + found reference `&dyn FixedHrtb` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:34:73 + | +LL | fn dyn_any_different_binders(x: &dyn AnyDifferentBinders<Assoc = u8>) { x } + | - ^ expected `()`, found `&dyn AnyDifferentBinders<Assoc = ...>` + | | + | help: try adding a return type: `-> &dyn AnyDifferentBinders<Assoc = u8>` + | + = note: expected unit type `()` + found reference `&dyn AnyDifferentBinders<Assoc = u8>` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:35:65 + | +LL | fn dyn_fixed_different_binders(x: &dyn FixedDifferentBinders) { x } + | - ^ expected `()`, found `&dyn FixedDifferentBinders` + | | + | help: try adding a return type: `-> &dyn FixedDifferentBinders` + | + = note: expected unit type `()` + found reference `&dyn FixedDifferentBinders` + +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/pointee-normalize-equate.rs b/tests/ui/traits/pointee-normalize-equate.rs new file mode 100644 index 00000000000..2e75933aca0 --- /dev/null +++ b/tests/ui/traits/pointee-normalize-equate.rs @@ -0,0 +1,56 @@ +// check-pass +// revisions: old next +//[next] compile-flags: -Znext-solver + +#![feature(ptr_metadata)] + +use std::ptr::{self, Pointee}; + +fn cast_same_meta<T: ?Sized, U: ?Sized>(ptr: *const T) -> *const U +where + T: Pointee<Metadata = <U as Pointee>::Metadata>, +{ + let (thin, meta) = ptr.to_raw_parts(); + ptr::from_raw_parts(thin, meta) +} + +struct Wrapper<T: ?Sized>(T); + +// normalize `Wrapper<T>::Metadata` -> `T::Metadata` +fn wrapper_to_tail<T: ?Sized>(ptr: *const T) -> *const Wrapper<T> { + cast_same_meta(ptr) +} + +// normalize `Wrapper<T>::Metadata` -> `T::Metadata` -> `()` +fn wrapper_to_unit<T>(ptr: *const ()) -> *const Wrapper<T> { + cast_same_meta(ptr) +} + +trait Project { + type Assoc: ?Sized; +} + +struct WrapperProject<T: ?Sized + Project>(T::Assoc); + +// normalize `WrapperProject<T>::Metadata` -> `T::Assoc::Metadata` +fn wrapper_project_tail<T: ?Sized + Project>(ptr: *const T::Assoc) -> *const WrapperProject<T> { + cast_same_meta(ptr) +} + +// normalize `WrapperProject<T>::Metadata` -> `T::Assoc::Metadata` -> `()` +fn wrapper_project_unit<T: ?Sized + Project>(ptr: *const ()) -> *const WrapperProject<T> +where + T::Assoc: Sized, +{ + cast_same_meta(ptr) +} + +// normalize `<[T] as Pointee>::Metadata` -> `usize`, even if `[T]: Sized` +fn sized_slice<T>(ptr: *const [T]) -> *const str +where + [T]: Sized, +{ + cast_same_meta(ptr) +} + +fn main() {} diff --git a/tests/ui/traits/self-without-lifetime-constraint.rs b/tests/ui/traits/self-without-lifetime-constraint.rs index 99013d32ab8..50901173b76 100644 --- a/tests/ui/traits/self-without-lifetime-constraint.rs +++ b/tests/ui/traits/self-without-lifetime-constraint.rs @@ -15,6 +15,7 @@ impl<'a> ValueRef<'a> { match *self { ValueRef::Text(t) => { std::str::from_utf8(t).map_err(|_| FromSqlError::InvalidType).map(|x| (x, &x)) + //~^ ERROR: cannot return value referencing function parameter `x` } _ => Err(FromSqlError::InvalidType), } diff --git a/tests/ui/traits/self-without-lifetime-constraint.stderr b/tests/ui/traits/self-without-lifetime-constraint.stderr index 0a5ae8a027e..8997d2a98b3 100644 --- a/tests/ui/traits/self-without-lifetime-constraint.stderr +++ b/tests/ui/traits/self-without-lifetime-constraint.stderr @@ -1,5 +1,5 @@ error: `impl` item signature doesn't match `trait` item signature - --> $DIR/self-without-lifetime-constraint.rs:45:5 + --> $DIR/self-without-lifetime-constraint.rs:46:5 | LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>; | -------------------------------------------------------------------- expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` @@ -10,10 +10,20 @@ LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { = note: expected signature `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` found signature `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` - --> $DIR/self-without-lifetime-constraint.rs:41:60 + --> $DIR/self-without-lifetime-constraint.rs:42:60 | LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>; | ^^^^ consider borrowing this type parameter in the trait -error: aborting due to 1 previous error +error[E0515]: cannot return value referencing function parameter `x` + --> $DIR/self-without-lifetime-constraint.rs:17:87 + | +LL | std::str::from_utf8(t).map_err(|_| FromSqlError::InvalidType).map(|x| (x, &x)) + | ^^^^--^ + | | | + | | `x` is borrowed here + | returns a value referencing data owned by the current function + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/traits/trait-upcasting/lifetime.rs b/tests/ui/traits/trait-upcasting/lifetime.rs index 9825158c2dd..6486ec3891c 100644 --- a/tests/ui/traits/trait-upcasting/lifetime.rs +++ b/tests/ui/traits/trait-upcasting/lifetime.rs @@ -7,7 +7,7 @@ trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync { 10 } - fn z(&self) -> i32 { + fn z(&self) -> i32 { //~ WARN methods `z` and `y` are never used 11 } @@ -21,7 +21,7 @@ trait Bar: Foo { 20 } - fn w(&self) -> i32 { + fn w(&self) -> i32 { //~ WARN method `w` is never used 21 } } diff --git a/tests/ui/traits/trait-upcasting/lifetime.stderr b/tests/ui/traits/trait-upcasting/lifetime.stderr new file mode 100644 index 00000000000..ca8f9cf63f3 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/lifetime.stderr @@ -0,0 +1,25 @@ +warning: methods `z` and `y` are never used + --> $DIR/lifetime.rs:10:8 + | +LL | trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync { + | --- methods in this trait +... +LL | fn z(&self) -> i32 { + | ^ +... +LL | fn y(&self) -> i32 { + | ^ + | + = note: `#[warn(dead_code)]` on by default + +warning: method `w` is never used + --> $DIR/lifetime.rs:24:8 + | +LL | trait Bar: Foo { + | --- method in this trait +... +LL | fn w(&self) -> i32 { + | ^ + +warning: 2 warnings emitted + diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.rs b/tests/ui/traits/trait-upcasting/replace-vptr.rs index 9ccfc9306ac..5ef65786bb7 100644 --- a/tests/ui/traits/trait-upcasting/replace-vptr.rs +++ b/tests/ui/traits/trait-upcasting/replace-vptr.rs @@ -3,7 +3,7 @@ #![feature(trait_upcasting)] trait A { - fn foo_a(&self); + fn foo_a(&self); //~ WARN method `foo_a` is never used } trait B { @@ -11,7 +11,7 @@ trait B { } trait C: A + B { - fn foo_c(&self); + fn foo_c(&self); //~ WARN method `foo_c` is never used } struct S(i32); diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.stderr b/tests/ui/traits/trait-upcasting/replace-vptr.stderr new file mode 100644 index 00000000000..823094761b3 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/replace-vptr.stderr @@ -0,0 +1,20 @@ +warning: method `foo_a` is never used + --> $DIR/replace-vptr.rs:6:8 + | +LL | trait A { + | - method in this trait +LL | fn foo_a(&self); + | ^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: method `foo_c` is never used + --> $DIR/replace-vptr.rs:14:8 + | +LL | trait C: A + B { + | - method in this trait +LL | fn foo_c(&self); + | ^^^^^ + +warning: 2 warnings emitted + diff --git a/tests/ui/traits/use-before-def.rs b/tests/ui/traits/use-before-def.rs index 1ee2b941909..e52dc53fbab 100644 --- a/tests/ui/traits/use-before-def.rs +++ b/tests/ui/traits/use-before-def.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![allow(non_camel_case_types)] // Issue #1761 diff --git a/tests/ui/traits/wf-object/reverse-order.rs b/tests/ui/traits/wf-object/reverse-order.rs index 74b2ef48533..e90c8763d65 100644 --- a/tests/ui/traits/wf-object/reverse-order.rs +++ b/tests/ui/traits/wf-object/reverse-order.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // Ensure that `dyn $($AutoTrait)+ ObjSafe` is well-formed. diff --git a/tests/ui/trivial_casts-rpass.rs b/tests/ui/trivial_casts-rpass.rs index 8e49468bf0c..4653a8df802 100644 --- a/tests/ui/trivial_casts-rpass.rs +++ b/tests/ui/trivial_casts-rpass.rs @@ -4,7 +4,7 @@ #![allow(trivial_casts, trivial_numeric_casts)] trait Foo { - fn foo(&self) {} + fn foo(&self) {} //~ WARN method `foo` is never used } pub struct Bar; diff --git a/tests/ui/trivial_casts-rpass.stderr b/tests/ui/trivial_casts-rpass.stderr new file mode 100644 index 00000000000..74698b61ab4 --- /dev/null +++ b/tests/ui/trivial_casts-rpass.stderr @@ -0,0 +1,12 @@ +warning: method `foo` is never used + --> $DIR/trivial_casts-rpass.rs:7:8 + | +LL | trait Foo { + | --- method in this trait +LL | fn foo(&self) {} + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs index acbf15dcb6c..5f3b711b31a 100644 --- a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs +++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.rs @@ -31,10 +31,7 @@ impl Tr for E { type V = u8; fn f() -> Self::V { 0 } //~^ ERROR ambiguous associated item - //~| ERROR ambiguous associated item //~| WARN this was previously accepted - //~| WARN this was previously accepted - //~| HELP use fully-qualified syntax //~| HELP use fully-qualified syntax } diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr index 359bd09ecd0..0f42fcbe04d 100644 --- a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr +++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr @@ -18,25 +18,5 @@ LL | type V; | ^^^^^^ = note: `#[deny(ambiguous_associated_items)]` on by default -error: ambiguous associated item - --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15 - | -LL | fn f() -> Self::V { 0 } - | ^^^^^^^ help: use fully-qualified syntax: `<E as Tr>::V` - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #57644 <https://github.com/rust-lang/rust/issues/57644> -note: `V` could refer to the variant defined here - --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5 - | -LL | V - | ^ -note: `V` could also refer to the associated type defined here - --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:26:5 - | -LL | type V; - | ^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs index ac32dbde04b..1a5daa13458 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs @@ -6,6 +6,7 @@ mod test_type_param_static { fn defining<A: 'static>(s: A) -> Ty<A> { s } fn assert_static<A: 'static>() {} fn test<A>() where Ty<A>: 'static { assert_static::<A>() } + //~^ ERROR: the parameter type `A` may not live long enough } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr index ff11aee4026..d1c06330c15 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -12,6 +12,20 @@ help: consider adding an explicit lifetime bound LL | type Ty<A: 'static> = impl Sized + 'static; | +++++++++ -error: aborting due to 1 previous error +error[E0310]: the parameter type `A` may not live long enough + --> $DIR/implied_lifetime_wf_check4_static.rs:8:41 + | +LL | fn test<A>() where Ty<A>: 'static { assert_static::<A>() } + | ^^^^^^^^^^^^^^^^^^ + | | + | the parameter type `A` must be valid for the static lifetime... + | ...so that the type `A` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn test<A: 'static>() where Ty<A>: 'static { assert_static::<A>() } + | +++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/issue-58887.rs b/tests/ui/type-alias-impl-trait/issue-58887.rs index 9675867656a..68d85ed6b0f 100644 --- a/tests/ui/type-alias-impl-trait/issue-58887.rs +++ b/tests/ui/type-alias-impl-trait/issue-58887.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass #![feature(impl_trait_in_assoc_type)] diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs index 3d6c826d6ac..2d9345a3e5e 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.rs +++ b/tests/ui/type-alias-impl-trait/issue-77179.rs @@ -7,6 +7,7 @@ type Pointer<T> = impl std::ops::Deref<Target = T>; fn test() -> Pointer<_> { //~^ ERROR: the placeholder `_` is not allowed within types Box::new(1) + //~^ ERROR: expected generic type parameter, found `i32` } fn main() { diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr index c5cacfd3cd3..ebd78e5b7a5 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.stderr +++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr @@ -8,7 +8,7 @@ LL | fn test() -> Pointer<_> { | help: replace with the correct return type: `Pointer<i32>` error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/issue-77179.rs:17:25 + --> $DIR/issue-77179.rs:18:25 | LL | fn bar() -> Pointer<_>; | ^ @@ -16,6 +16,16 @@ LL | fn bar() -> Pointer<_>; | not allowed in type signatures | help: use type parameters instead: `T` -error: aborting due to 2 previous errors +error[E0792]: expected generic type parameter, found `i32` + --> $DIR/issue-77179.rs:9:5 + | +LL | type Pointer<T> = impl std::ops::Deref<Target = T>; + | - this generic parameter must be used with a generic type parameter +... +LL | Box::new(1) + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0121`. +Some errors have detailed explanations: E0121, E0792. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs index 0f0a02e97d8..6431cf37df7 100644 --- a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs +++ b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs @@ -14,5 +14,7 @@ mod foo { } fn main() { - let _: foo::Foo = std::mem::transmute(0u8); + unsafe { + let _: foo::Foo = std::mem::transmute(0u8); + } } diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr index d92bafce142..fd76526644b 100644 --- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr +++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr @@ -1,4 +1,4 @@ -note: no errors encountered even though `span_delayed_bug` issued +note: no errors encountered even though delayed bugs were created note: those delayed bugs will now be shown as internal compiler errors diff --git a/tests/ui/issues/issue-16338.rs b/tests/ui/typeck/issue-16338.rs index 321b3576cd6..321b3576cd6 100644 --- a/tests/ui/issues/issue-16338.rs +++ b/tests/ui/typeck/issue-16338.rs diff --git a/tests/ui/issues/issue-16338.stderr b/tests/ui/typeck/issue-16338.stderr index e24b9bfa3c0..e24b9bfa3c0 100644 --- a/tests/ui/issues/issue-16338.stderr +++ b/tests/ui/typeck/issue-16338.stderr diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs index 4eba14f5a93..591a7278ddc 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.rs +++ b/tests/ui/typeck/typeck_type_placeholder_item.rs @@ -198,6 +198,7 @@ trait Qux { //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types } impl Qux for Struct { + //~^ ERROR not all trait items implemented, missing: `F` type A = _; //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated types type B = _; diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index a4325b01f02..bfcc76c1dae 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -29,7 +29,7 @@ LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error: associated constant in `impl` without body - --> $DIR/typeck_type_placeholder_item.rs:205:5 + --> $DIR/typeck_type_placeholder_item.rs:206:5 | LL | const C: _; | ^^^^^^^^^^- @@ -411,7 +411,7 @@ LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/typeck_type_placeholder_item.rs:216:31 + --> $DIR/typeck_type_placeholder_item.rs:217:31 | LL | fn value() -> Option<&'static _> { | ----------------^- @@ -420,7 +420,7 @@ LL | fn value() -> Option<&'static _> { | help: replace with the correct return type: `Option<&'static u8>` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/typeck_type_placeholder_item.rs:221:10 + --> $DIR/typeck_type_placeholder_item.rs:222:10 | LL | const _: Option<_> = map(value); | ^^^^^^^^^ @@ -429,7 +429,7 @@ LL | const _: Option<_> = map(value); | help: replace with the correct type: `Option<u8>` error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/typeck_type_placeholder_item.rs:224:31 + --> $DIR/typeck_type_placeholder_item.rs:225:31 | LL | fn evens_squared(n: usize) -> _ { | ^ @@ -438,13 +438,13 @@ LL | fn evens_squared(n: usize) -> _ { | help: replace with an appropriate return type: `impl Iterator<Item = usize>` error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/typeck_type_placeholder_item.rs:229:10 + --> $DIR/typeck_type_placeholder_item.rs:230:10 | LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^ not allowed in type signatures | -note: however, the inferred type `Map<Filter<Range<i32>, {closure@typeck_type_placeholder_item.rs:229:29}>, {closure@typeck_type_placeholder_item.rs:229:49}>` cannot be named - --> $DIR/typeck_type_placeholder_item.rs:229:14 +note: however, the inferred type `Map<Filter<Range<i32>, {closure@typeck_type_placeholder_item.rs:230:29}>, {closure@typeck_type_placeholder_item.rs:230:49}>` cannot be named + --> $DIR/typeck_type_placeholder_item.rs:230:14 | LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -631,25 +631,25 @@ LL | fn clone_from(&mut self, other: &FnTest9) { *self = FnTest9; } | ~~~~~~~~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types - --> $DIR/typeck_type_placeholder_item.rs:201:14 + --> $DIR/typeck_type_placeholder_item.rs:202:14 | LL | type A = _; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types - --> $DIR/typeck_type_placeholder_item.rs:203:14 + --> $DIR/typeck_type_placeholder_item.rs:204:14 | LL | type B = _; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:205:14 + --> $DIR/typeck_type_placeholder_item.rs:206:14 | LL | const C: _; | ^ not allowed in type signatures error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants - --> $DIR/typeck_type_placeholder_item.rs:208:14 + --> $DIR/typeck_type_placeholder_item.rs:209:14 | LL | const D: _ = 42; | ^ @@ -657,7 +657,16 @@ LL | const D: _ = 42; | not allowed in type signatures | help: replace with the correct type: `i32` -error: aborting due to 71 previous errors +error[E0046]: not all trait items implemented, missing: `F` + --> $DIR/typeck_type_placeholder_item.rs:200:1 + | +LL | type F: std::ops::Fn(_); + | ----------------------- `F` from trait +... +LL | impl Qux for Struct { + | ^^^^^^^^^^^^^^^^^^^ missing `F` in implementation + +error: aborting due to 72 previous errors -Some errors have detailed explanations: E0121, E0282, E0403. -For more information about an error, try `rustc --explain E0121`. +Some errors have detailed explanations: E0046, E0121, E0282, E0403. +For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/typeof/issue-100183.stderr b/tests/ui/typeof/issue-100183.stderr index 7be923d9383..57317d449cf 100644 --- a/tests/ui/typeof/issue-100183.stderr +++ b/tests/ui/typeof/issue-100183.stderr @@ -6,8 +6,8 @@ LL | y: (typeof("hey"),), | help: consider replacing `typeof(...)` with an actual type | -LL | y: (&'static str,), - | ~~~~~~~~~~~~ +LL | y: (&str,), + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr index e90784a54ae..c1281ce6a42 100644 --- a/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr +++ b/tests/ui/ufcs/ufcs-qpath-self-mismatch.stderr @@ -11,6 +11,19 @@ LL | <i32 as Add<u32>>::add(1, 2); <&'a i32 as Add<i32>> <&i32 as Add<&i32>> +error[E0277]: cannot add `u32` to `i32` + --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 + | +LL | <i32 as Add<u32>>::add(1, 2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` + | + = help: the trait `Add<u32>` is not implemented for `i32` + = help: the following other types implement trait `Add<Rhs>`: + <i32 as Add> + <i32 as Add<&i32>> + <&'a i32 as Add<i32>> + <&i32 as Add<&i32>> + error[E0308]: mismatched types --> $DIR/ufcs-qpath-self-mismatch.rs:7:28 | @@ -55,19 +68,6 @@ help: change the type of the numeric literal from `u32` to `i32` LL | <i32 as Add<i32>>::add(1, 2i32); | ~~~ -error[E0277]: cannot add `u32` to `i32` - --> $DIR/ufcs-qpath-self-mismatch.rs:4:5 - | -LL | <i32 as Add<u32>>::add(1, 2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32` - | - = help: the trait `Add<u32>` is not implemented for `i32` - = help: the following other types implement trait `Add<Rhs>`: - <i32 as Add> - <i32 as Add<&i32>> - <&'a i32 as Add<i32>> - <&i32 as Add<&i32>> - error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0308. diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs index ea73b8b3c4a..8537eb71774 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.rs @@ -33,6 +33,7 @@ fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) { //~^ ERROR trait takes 1 lifetime argument but 0 lifetime arguments were supplied // Here, the omitted lifetimes are expanded to distinct things. same_type(x, y) + //~^ ERROR borrowed data escapes outside of function } fn main() { } diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr index d73aef851fd..6e6c649ca3d 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-region.stderr @@ -34,6 +34,22 @@ note: trait defined here, with 1 lifetime parameter: `'a` LL | trait Foo<'a,T> { | ^^^ -- -error: aborting due to 3 previous errors +error[E0521]: borrowed data escapes outside of function + --> $DIR/unboxed-closure-sugar-region.rs:35:5 + | +LL | fn test2(x: &dyn Foo<(isize,),Output=()>, y: &dyn Foo(isize)) { + | - - `y` declared here, outside of the function body + | | + | `x` is a reference that is only valid in the function body + | has type `&dyn Foo<'1, (isize,), Output = ()>` +... +LL | same_type(x, y) + | ^^^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'1` must outlive `'static` + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0521. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs b/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs index 3d049cc5639..ebc38798544 100644 --- a/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs +++ b/tests/ui/underscore-lifetime/underscore-lifetime-binders.rs @@ -14,6 +14,7 @@ fn meh() -> Box<dyn for<'_> Meh<'_>> //~ ERROR cannot be used here } fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } //~ ERROR missing lifetime specifier +//~^ ERROR lifetime may not live long enough fn main() { let x = 5; diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr index cd74d27dcb5..5d2954d1d71 100644 --- a/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/tests/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -45,7 +45,15 @@ help: consider introducing a named lifetime parameter LL | fn foo2<'a>(_: &'a u8, y: &'a u8) -> &'a u8 { y } | ++++ ~~ ~~ ~~ -error: aborting due to 5 previous errors +error: lifetime may not live long enough + --> $DIR/underscore-lifetime-binders.rs:16:43 + | +LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } + | - ^ returning this value requires that `'1` must outlive `'static` + | | + | let's call the lifetime of this reference `'1` + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0106, E0637. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed index 5be6ff8e7e1..700e4f25423 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait WithType<T> {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs index d7072aa1181..66ba9b24dac 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait WithType<T> {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr index 54e62f34fba..f012120e550 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2015.stderr @@ -1,5 +1,5 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/where-clause-inherent-impl-ampersand-rust2015.rs:13:17 + --> $DIR/where-clause-inherent-impl-ampersand-rust2015.rs:14:17 | LL | T: WithType<&u32> | ^ explicit lifetime name needed here diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed index 0f1be586589..56682db3b0b 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.fixed @@ -1,5 +1,6 @@ // edition:2018 // run-rustfix +#![allow(dead_code)] trait WithType<T> {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs index 59f7e472e2d..5302b2f1576 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.rs @@ -1,5 +1,6 @@ // edition:2018 // run-rustfix +#![allow(dead_code)] trait WithType<T> {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr index 36f3e9ef145..7d675dd41e9 100644 --- a/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr +++ b/tests/ui/underscore-lifetime/where-clause-inherent-impl-ampersand-rust2018.stderr @@ -1,5 +1,5 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/where-clause-inherent-impl-ampersand-rust2018.rs:14:17 + --> $DIR/where-clause-inherent-impl-ampersand-rust2018.rs:15:17 | LL | T: WithType<&u32> | ^ explicit lifetime name needed here diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed index 55c7470960e..f3adc7e7fad 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.fixed @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait WithType<T> {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs index 42a35b02161..1e084e9ad41 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(dead_code)] trait WithType<T> {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr index 92b7a9c2af8..8aa0e52c688 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2015.stderr @@ -1,5 +1,5 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/where-clause-trait-impl-region-2015.rs:10:17 + --> $DIR/where-clause-trait-impl-region-2015.rs:11:17 | LL | T: WithType<&u32> | ^ explicit lifetime name needed here diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed index 09b96fe5ea4..dd8074abed7 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.fixed @@ -1,6 +1,8 @@ // run-rustfix // edition:2018 +#![allow(dead_code)] + trait WithType<T> {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs index 445f38cbee1..4fc9c71b179 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.rs @@ -1,6 +1,8 @@ // run-rustfix // edition:2018 +#![allow(dead_code)] + trait WithType<T> {} trait WithRegion<'a> { } diff --git a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr index 63d8b99ed18..22940d0b0b1 100644 --- a/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr +++ b/tests/ui/underscore-lifetime/where-clause-trait-impl-region-2018.stderr @@ -1,5 +1,5 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here - --> $DIR/where-clause-trait-impl-region-2018.rs:11:17 + --> $DIR/where-clause-trait-impl-region-2018.rs:13:17 | LL | T: WithType<&u32> | ^ explicit lifetime name needed here diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr index 304e738ed25..c9131a8372a 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.stderr +++ b/tests/ui/uninhabited/uninhabited-irrefutable.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error[E0005]: refutable pattern in local binding - --> $DIR/uninhabited-irrefutable.rs:29:9 + --> $DIR/uninhabited-irrefutable.rs:32:9 | LL | let Foo::D(_y, _z) = x; | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered @@ -7,7 +7,7 @@ LL | let Foo::D(_y, _z) = x; = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html note: `Foo` defined here - --> $DIR/uninhabited-irrefutable.rs:18:6 + --> $DIR/uninhabited-irrefutable.rs:21:6 | LL | enum Foo { | ^^^ diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr new file mode 100644 index 00000000000..c9131a8372a --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr @@ -0,0 +1,26 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/uninhabited-irrefutable.rs:32:9 + | +LL | let Foo::D(_y, _z) = x; + | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `Foo` defined here + --> $DIR/uninhabited-irrefutable.rs:21:6 + | +LL | enum Foo { + | ^^^ +LL | +LL | A(foo::SecretlyEmpty), + | - not covered + = note: pattern `Foo::A(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future + = note: the matched value is of type `Foo` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Foo::D(_y, _z) = x else { todo!() }; + | ++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.rs b/tests/ui/uninhabited/uninhabited-irrefutable.rs index cfd60a8d903..2ef3b668cb0 100644 --- a/tests/ui/uninhabited/uninhabited-irrefutable.rs +++ b/tests/ui/uninhabited/uninhabited-irrefutable.rs @@ -1,5 +1,8 @@ +// revisions: min_exhaustive_patterns exhaustive_patterns +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, feature(min_exhaustive_patterns))] +#![cfg_attr(min_exhaustive_patterns, allow(incomplete_features))] #![feature(never_type)] -#![feature(exhaustive_patterns)] mod foo { pub struct SecretlyEmpty { diff --git a/tests/ui/wf/hir-wf-canonicalized.rs b/tests/ui/wf/hir-wf-canonicalized.rs index bdb84409d00..eac238f0fca 100644 --- a/tests/ui/wf/hir-wf-canonicalized.rs +++ b/tests/ui/wf/hir-wf-canonicalized.rs @@ -9,8 +9,8 @@ trait Callback<T: Foo>: Fn(&Bar<'_, T>, &T::V) {} struct Bar<'a, T> { callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>, //~^ ERROR the trait bound `Bar<'a, T>: Foo` is not satisfied - //~| ERROR the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied - //~| ERROR the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time + //~| ERROR the trait bound `(dyn Callback<Bar<'a, T>, Output = ()> + 'static): Foo` is not satisfied + //~| ERROR the size for values of type `(dyn Callback<Bar<'a, T>, Output = ()> + 'static)` cannot be known at compilation time } impl<T: Foo> Bar<'_, Bar<'_, T>> {} diff --git a/tests/ui/wf/hir-wf-canonicalized.stderr b/tests/ui/wf/hir-wf-canonicalized.stderr index 4dca1f65232..8938801ce3d 100644 --- a/tests/ui/wf/hir-wf-canonicalized.stderr +++ b/tests/ui/wf/hir-wf-canonicalized.stderr @@ -10,11 +10,11 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^ -error[E0277]: the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied +error[E0277]: the trait bound `(dyn Callback<Bar<'a, T>, Output = ()> + 'static): Foo` is not satisfied --> $DIR/hir-wf-canonicalized.rs:10:15 | LL | callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback<Bar<'a, T>, Output = ()> + 'static)` | help: this trait has no implementations, consider adding one --> $DIR/hir-wf-canonicalized.rs:3:1 @@ -22,13 +22,13 @@ help: this trait has no implementations, consider adding one LL | trait Foo { | ^^^^^^^^^ -error[E0277]: the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time +error[E0277]: the size for values of type `(dyn Callback<Bar<'a, T>, Output = ()> + 'static)` cannot be known at compilation time --> $DIR/hir-wf-canonicalized.rs:10:15 | LL | callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` + = help: the trait `Sized` is not implemented for `(dyn Callback<Bar<'a, T>, Output = ()> + 'static)` note: required by an implicit `Sized` bound in `Bar` --> $DIR/hir-wf-canonicalized.rs:9:16 | diff --git a/tests/ui/where-clauses/issue-50825-1.rs b/tests/ui/where-clauses/issue-50825-1.rs index ee4316029a8..2ee34ad714e 100644 --- a/tests/ui/where-clauses/issue-50825-1.rs +++ b/tests/ui/where-clauses/issue-50825-1.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // regression test for issue #50825 // Make sure that the `impl` bound (): X<T = ()> is preferred over // the (): X bound in the where clause. diff --git a/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs b/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs index ea60fa70876..65fd2f3096c 100644 --- a/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs +++ b/tests/ui/where-clauses/where-clause-bounds-inconsistency.rs @@ -1,4 +1,4 @@ -// run-pass +// check-pass // pretty-expanded FIXME #23616 trait Bound { diff --git a/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs index 6fc570b9b5b..a7ce0590fcd 100644 --- a/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs +++ b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.rs @@ -3,7 +3,7 @@ // pretty-expanded FIXME #23616 -trait TheTrait { fn dummy(&self) { } } +trait TheTrait { fn dummy(&self) { } } //~ WARN method `dummy` is never used impl TheTrait for &'static isize { } diff --git a/tests/ui/where-clauses/where-clause-early-bound-lifetimes.stderr b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.stderr new file mode 100644 index 00000000000..a9fe11ea6b3 --- /dev/null +++ b/tests/ui/where-clauses/where-clause-early-bound-lifetimes.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/where-clause-early-bound-lifetimes.rs:6:21 + | +LL | trait TheTrait { fn dummy(&self) { } } + | -------- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs b/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs index daa3c8dd8e3..8f9c6fbff3d 100644 --- a/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs +++ b/tests/ui/where-clauses/where-clause-method-substituion-rpass.rs @@ -2,7 +2,7 @@ #![allow(unused_variables)] // pretty-expanded FIXME #23616 -trait Foo<T> { fn dummy(&self, arg: T) { } } +trait Foo<T> { fn dummy(&self, arg: T) { } } //~ WARN method `dummy` is never used trait Bar<A> { fn method<B>(&self) where A: Foo<B>; diff --git a/tests/ui/where-clauses/where-clause-method-substituion-rpass.stderr b/tests/ui/where-clauses/where-clause-method-substituion-rpass.stderr new file mode 100644 index 00000000000..0d09cb9de3f --- /dev/null +++ b/tests/ui/where-clauses/where-clause-method-substituion-rpass.stderr @@ -0,0 +1,12 @@ +warning: method `dummy` is never used + --> $DIR/where-clause-method-substituion-rpass.rs:5:19 + | +LL | trait Foo<T> { fn dummy(&self, arg: T) { } } + | --- ^^^^^ + | | + | method in this trait + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed index 2f47c0d91fa..4e1aa59aac0 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed @@ -1,6 +1,8 @@ // check-pass // run-rustfix +#![allow(dead_code)] + trait Trait { // Fine. type Assoc where u32: Copy; diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs index b20aa9398b5..05b2f8c82a4 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs @@ -1,6 +1,8 @@ // check-pass // run-rustfix +#![allow(dead_code)] + trait Trait { // Fine. type Assoc where u32: Copy; diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr index b4de051845f..6ff9d2dd73b 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr @@ -1,5 +1,5 @@ warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-impl.rs:13:16 + --> $DIR/where-clause-placement-assoc-type-in-impl.rs:15:16 | LL | type Assoc where u32: Copy = (); | ^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + type Assoc = () where u32: Copy; | warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-impl.rs:16:17 + --> $DIR/where-clause-placement-assoc-type-in-impl.rs:18:17 | LL | type Assoc2 where u32: Copy = () where i32: Copy; | ^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL + type Assoc2 = () where i32: Copy, u32: Copy; | warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-impl.rs:24:17 + --> $DIR/where-clause-placement-assoc-type-in-impl.rs:26:17 | LL | type Assoc2 where u32: Copy, i32: Copy = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed index d171eba50b7..940e2cc8e97 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed @@ -1,6 +1,7 @@ // check-pass // run-rustfix +#![allow(dead_code)] #![feature(associated_type_defaults)] trait Trait { diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs index 59afee65794..7001a9245a5 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs @@ -1,6 +1,7 @@ // check-pass // run-rustfix +#![allow(dead_code)] #![feature(associated_type_defaults)] trait Trait { diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr index a81cb8c8cd6..9e9967ef739 100644 --- a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr +++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr @@ -1,5 +1,5 @@ warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-trait.rs:8:16 + --> $DIR/where-clause-placement-assoc-type-in-trait.rs:9:16 | LL | type Assoc where u32: Copy = (); | ^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + type Assoc = () where u32: Copy; | warning: where clause not allowed here - --> $DIR/where-clause-placement-assoc-type-in-trait.rs:11:17 + --> $DIR/where-clause-placement-assoc-type-in-trait.rs:12:17 | LL | type Assoc2 where u32: Copy = () where i32: Copy; | ^^^^^^^^^^^^^^^ diff --git a/triagebot.toml b/triagebot.toml index 68c863bb919..ef3f3693e61 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -658,7 +658,6 @@ compiler-team = [ ] compiler-team-contributors = [ "@TaKO8Ki", - "@b-naber", "@nnethercote", "@fmease", ] @@ -670,7 +669,6 @@ libs = [ "@cuviper", "@joshtriplett", "@Mark-Simulacrum", - "@m-ou-se", ] bootstrap = [ "@Mark-Simulacrum",  | 
