diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index ec92afee47a6b..6225358569573 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(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(self, diag: &mut Diagnostic, _: F) { #[allow(rustc::untranslatable_diagnostic)] diag.note(self.0); } diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 993ddf00eb5b9..11aa6b250b129 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>, /// Outputs - nodes: IndexVec>>, + nodes: IndexVec>, parenting: LocalDefIdMap, /// The parent of this node @@ -29,16 +29,19 @@ pub(super) fn index_hir<'hir>( tcx: TyCtxt<'hir>, item: hir::OwnerNode<'hir>, bodies: &SortedMap>, -) -> (IndexVec>>, LocalDefIdMap) { - let mut nodes = IndexVec::new(); + num_nodes: usize, +) -> (IndexVec>, LocalDefIdMap) { + 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(&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/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 063b6627050bc..3f3826270765a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -675,7 +675,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 }; diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 5f54a0ddf8c38..9662c73ca8532 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); // The derive for `Vec` does multiple calls to `span_label`, adding commas between each impl AddToDiagnostic for EmptyLabelManySpans { - fn add_to_diagnostic_with(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(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(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(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_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 6debb3362b04c..64efc8b7ee356 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -401,66 +401,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 +1756,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 +1822,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 +2394,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 4f66468a865f8..716d30c5a485d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -87,7 +87,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/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 55649ec2f1645..ded282e4b4a28 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -396,7 +396,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 +688,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 +759,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 +1206,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/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 8c8ca1ead400b..0733fc48ed56c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -216,7 +216,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_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index eadb48ddd36d8..8d2e06bf30dac 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(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(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_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 1763c355069a9..03717a4d654c7 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -77,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(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage; + fn add_to_diagnostic_with(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"] diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 15effd3cbec9b..e936ebc7185fa 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(self, diag: &mut crate::Diagnostic, _: F) { + fn add_to_diagnostic_with(self, diag: &mut crate::Diagnostic, _: F) { diag.span_labels(self.spans, self.label); } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index ec5029e505f96..9c5a91adfa091 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -19,6 +19,7 @@ #![feature(never_type)] #![feature(rustc_attrs)] #![feature(rustdoc_internals)] +#![feature(trait_alias)] #![feature(try_blocks)] #![feature(yeet_expr)] // tidy-alphabetical-end @@ -35,6 +36,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, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c89ad0794481f..abf7a695fd2d1 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -831,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>>, + pub nodes: IndexVec>, /// Content of local bodies. pub bodies: SortedMap>, } @@ -839,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() } } @@ -856,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::>(), ) @@ -3347,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, } } @@ -3482,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> { @@ -3537,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 27c834d848fc4..52e1109ff9215 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>; + /// 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> { + 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_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 54d0fb6ffab72..d6f604c180bf6 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/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index d0683686d3812..6edd68f1baebe 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> 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 @@ -2252,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 649ac6c5aebbf..3d803258c8e5e 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/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index f4e6adb6b8395..20a7663f86441 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -521,6 +521,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder 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 4eba31e327f68..bec53693d6c94 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -166,17 +166,6 @@ pub struct LifetimesOrBoundsMismatchOnTrait { pub ident: Ident, } -#[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, - pub method_name: Symbol, -} - #[derive(Diagnostic)] #[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)] pub struct DropImplOnWrongItem { @@ -1512,6 +1501,16 @@ pub struct NotSupportedDelegation<'a> { pub callee_span: Span, } +#[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, +} + #[derive(Diagnostic)] #[diag(hir_analysis_unused_generic_parameter)] pub(crate) struct UnusedGenericParameter { 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 501915d2e7e53..3b1ee2975fd97 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 9d0c5cb0f32b0..32d91b596b0bd 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -23,7 +23,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 +117,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/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index ca636ebcade04..2beabc0835db1 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 b6dfc34d3ac19..d8974251de040 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>, ) { 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 70afb042441f9..10e12d01b1fe6 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(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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(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(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 54664f38b19b6..292b85eb97f7f 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: @@ -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/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index d30c7a4fb3899..35b3f27d79127 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 5395ffda1d134..ed0bdb9bdaa0d 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>, 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/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 007df203f7117..81b8239351547 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() @@ -2017,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) { @@ -3251,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 b9b3ed53dae8f..34ce0ab1f8b98 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 c4773a885218a..211109b59417a 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_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 0a128218c9229..8bfc05d6a96db 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(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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(mut self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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 is required @@ -799,10 +784,7 @@ pub struct DynTraitConstraintSuggestion { } impl AddToDiagnostic for DynTraitConstraintSuggestion { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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(mut self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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(self, diag: &mut Diagnostic, _f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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(self, diag: &mut rustc_errors::Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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 331e3633e908d..a59a4df77296d 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(self, diag: &mut Diagnostic, f: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 59bed38ec2af1..dd9ed80ca7242 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2182,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/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 5ee0a606a5f57..9a9d13ed60825 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -687,7 +687,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/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index eabc1b953af1c..ed551658d91a9 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_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index 3bd0c1b803199..21d4b6fa65b5b 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(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { OverruledAttributeSub::DefaultSource { id } => { diag.note(fluent::lint_default_source); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index f916deb4a46d1..40b68941b17fe 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -6,7 +6,7 @@ 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 +268,7 @@ pub struct SuggestChangingAssocTypes<'a, 'b> { } impl AddToDiagnostic for SuggestChangingAssocTypes<'_, '_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { // Access to associates types should use `::Assoc`, which does not need a // bound. Let's see if this type does that. @@ -323,10 +320,7 @@ pub struct BuiltinTypeAliasGenericBoundsSuggestion { } impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { diag.multipart_suggestion( fluent::lint_suggestion, self.suggestions, @@ -443,10 +437,7 @@ pub struct BuiltinUnpermittedTypeInitSub { } impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let mut err = self.err; loop { if let Some(span) = err.span { @@ -497,10 +488,7 @@ pub struct BuiltinClashingExternSub<'a> { } impl AddToDiagnostic for BuiltinClashingExternSub<'_> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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 +754,7 @@ pub struct HiddenUnicodeCodepointsDiagLabels { } impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { for (c, span) in self.spans { diag.span_label(span, format!("{c:?}")); } @@ -783,10 +768,7 @@ pub enum HiddenUnicodeCodepointsDiagSub { // Used because of multiple multipart_suggestion and note impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { diag.multipart_suggestion_with_style( @@ -934,10 +916,7 @@ pub struct NonBindingLetSub { } impl AddToDiagnostic for NonBindingLetSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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 +1196,7 @@ pub enum NonSnakeCaseDiagSub { } impl AddToDiagnostic for NonSnakeCaseDiagSub { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { NonSnakeCaseDiagSub::Label { span } => { diag.span_label(span, fluent::lint_label); @@ -1413,10 +1389,7 @@ pub enum OverflowingBinHexSign { } impl AddToDiagnostic for OverflowingBinHexSign { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { match self { OverflowingBinHexSign::Positive => { diag.note(fluent::lint_positive_note); diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index c029b931e7dde..3a5f289559e6a 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_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index bb02a8a1e4743..c18f0e7b7b938 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 { 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 { 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 { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 20e3ae3ba9492..11cb1bb6d9e6e 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, + /// 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 { 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 0b352a02b64c7..7cd2f58779f84 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 85631bd8edbfa..79aa9a547f7c6 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -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 ba1ae46626b22..bf72aac10332e 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -157,23 +157,15 @@ impl<'tcx> TyCtxt<'tcx> { self.hir_owner_nodes(owner_id).node() } - /// Retrieves the `hir::Node` corresponding to `id`, returning `None` if cannot be found. - pub fn opt_hir_node(self, id: HirId) -> Option> { - 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> { - 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 { 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> { - 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> { - 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)> { - 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 { 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 { - 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 { 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> { - 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("".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 94191df30a5e6..f66cd2370e3ee 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/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index b4054f8ff5edd..fd5302dc75b13 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> { + 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> { - 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>, - stack: Vec>, + visited: FxHashSet>, + stack: Vec>, } 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> { - if let Some(trait_ref) = self.stack.pop() { - self.elaborate(trait_ref); - Some(trait_ref) + fn next(&mut self) -> Option> { + 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/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index c0bfd2380ade0..f90703e61844e 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_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index 065c93e86a866..541a3129950ef 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, diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 232b6033946a0..0bc5fe6ef89ac 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(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index f9798bc4e70e6..6e4f8f710b683 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1231,8 +1231,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_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 86a64d90deb20..3c3a8d6fbb9c7 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(self, diag: &mut rustc_errors::Diagnostic, _: F) - where - F: Fn(&mut rustc_errors::Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index e652c79d85157..ec704dec352da 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -827,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() }); @@ -853,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 { @@ -2221,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/errors.rs b/compiler/rustc_passes/src/errors.rs index 61c953bcb59b8..a732bdbca5115 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}; @@ -1753,7 +1754,7 @@ pub struct UnusedVariableStringInterp { } impl AddToDiagnostic for UnusedVariableStringInterp { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { + fn add_to_diagnostic_with(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, diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 0f8cc583b03cf..e10a22cdf31b9 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 bdb6cf19eac4e..2dffdc9846c22 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; @@ -62,10 +62,7 @@ pub struct Overlap<'tcx> { } impl<'tcx> AddToDiagnostic for Overlap<'tcx> { - fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) { let Overlap { span, range } = self; // FIXME(mejrs) unfortunately `#[derive(LintDiagnostic)]` diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 576005b2c7f8f..80a807b4f2759 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1520,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 = place.is_scrutinee && !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()`. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index f0b5311f1e1bb..7c2d5f121009b 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}; @@ -4547,14 +4548,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/lib.rs b/compiler/rustc_resolve/src/lib.rs index 16dce7e431dbf..b3786f8588bf7 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1629,6 +1629,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_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 7894f8dd98fff..20cd573f46e9b 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(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 243f583aed825..a4d8cbb125c72 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), .. })) = @@ -1786,7 +1786,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 +2198,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 +3186,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 +3196,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 +3211,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 +3233,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 +3247,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 +3958,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 { @@ -4074,9 +4074,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 +4087,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 +4333,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... 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 4ef490758a332..e9f932a8300e7 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... diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3bac71dbc24e2..b8e0d75e7dc37 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/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index b055e355b788a..8ee35db56f8dd 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/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 9069098bf1a37..f7bc546470796 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/tools/clippy/clippy_lints/src/absolute_paths.rs b/src/tools/clippy/clippy_lints/src/absolute_paths.rs index 3822b83b4bc64..8ba661afeeb6f 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/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs index 91bad8256ecb1..0f29743856ac9 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/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index bb86b6f30759c..81d0def4322d3 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/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs index 6b0423200d765..b0f46f5c646cf 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/empty_drop.rs b/src/tools/clippy/clippy_lints/src/empty_drop.rs index 1d2b907b94821..74db250b3ae92 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 b7776263060be..218d7c6c01ae1 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/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs index e8c1e5db35e00..de048fef5f224 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/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs index 5417c13d07967..252be30c4e27d 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/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index c1ab020117ca6..27d85cde5320a 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/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs index 920a887a6fd1b..5f015db2b33bf 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 71a83a68db933..e1768c6d97641 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/methods/filter_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs index 9251130a30549..7339362193e54 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/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs index 624597ffca949..ab36f854fcb1d 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/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs index 41168230752a8..70cc43e266c6d 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 195ce17629a71..b593e48ae2e16 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/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index f8365deebd46e..10ab380ba1bc5 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/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs index 7a351dab2d458..07806b182f22b 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 = - 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 98f3235af10a0..fc5a45dd56d6b 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_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 4e499ff4cc612..3f936009e44ec 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -177,10 +177,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 +1327,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 { @@ -2696,10 +2696,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, diff --git a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff index 7a374c5675ab9..8b427cff67780 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) as Some).0: u32); StorageLive(_9); _9 = (((_3.1: std::option::Option) as Some).0: u32); + StorageLive(_8); + _8 = (((_3.0: std::option::Option) 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 21f58a14a2b3f..b91a469225cd2 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) as Some).0: u32); StorageLive(_10); _10 = (((_3.1: std::option::Option) as Some).0: u32); + StorageLive(_9); + _9 = (((_3.0: std::option::Option) 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 e058c409cb596..cc16af721ca69 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) as Some).0: u32); StorageLive(_9); _9 = (((_3.1: std::option::Option) as Some).0: bool); + StorageLive(_8); + _8 = (((_3.0: std::option::Option) 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 f98d68e6ffce3..eb8926d27ee87 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) as Some).0: u32); - StorageLive(_12); - _12 = (((_4.1: std::option::Option) as Some).0: u32); StorageLive(_13); _13 = (((_4.2: std::option::Option) as Some).0: u32); + StorageLive(_12); + _12 = (((_4.1: std::option::Option) as Some).0: u32); + StorageLive(_11); + _11 = (((_4.0: std::option::Option) 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 0c94794fa3ffe..79cf1c0e34ad5 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 09cdce718572e..af0337d0a7e71 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) as Some).0: u32); StorageLive(_10); _10 = (((_3.1: std::option::Option) as Some).0: u32); + StorageLive(_9); + _9 = (((_3.0: std::option::Option) as Some).0: u32); _0 = const 0_u32; - StorageDead(_10); StorageDead(_9); + StorageDead(_10); goto -> bb8; } 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 0000000000000..b12de636f58b1 --- /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 0000000000000..d216825e5e689 --- /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/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff index e7280f148377c..d273161528464 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); StorageLive(_6); _6 = _5; - _12 = move ((_5 as Err).0: i32); + _12 = ((_5 as Err).0: i32); _0 = Result::::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::::Err(_10); _2 = ControlFlow::, i32>::Break(move _11); @@ -92,7 +92,7 @@ } bb5: { - _9 = move ((_1 as Ok).0: i32); + _9 = ((_1 as Ok).0: i32); _2 = ControlFlow::, i32>::Continue(_9); goto -> bb3; } 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 0000000000000..25d0111a7b763 --- /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 0000000000000..7bc56b4263f26 --- /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 0000000000000..d13bf88462435 --- /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 0000000000000..310bf08e2b525 --- /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/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index ab42d3b8c1e4e..5a2099865d6a7 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(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + fn add_to_diagnostic_with(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(self, diag: &mut Diagnostic, _: F) - where - F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, - { + fn add_to_diagnostic_with(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 f70240ecf172a..108b7c8ea9cbb 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/async-await/in-trait/async-example-desugared-boxed.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs index c5a9841029e38..69871d0dca01d 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 + '_>> { - //~^ 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 1462c694e161e..54aba77cc05d0 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 + '_>> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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 { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ -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 c287b9a5b847f..c6e8f1ae90607 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 { @@ -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 a2f1060e36fc4..d94afd92c5691 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 { + | ~~~~~~~~~~~~~~~~~~~~~~~~~ -error: aborting due to 1 previous error +warning: 1 warning emitted 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 60077a7e00cc8..ecd5737cf3c23 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 f75ccb65d1509..8260cd5271ee9 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/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr index 79efcc5d8b041..6ad3effe0e26e 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/pattern/bindings-after-at/bind-by-copy.rs b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs index 2b349f0ed5f99..253b2d8890100 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 a61d682152407..bfb3c3b20d63c 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 324897151124c..ba0622090bb7d 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`, 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`, 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 06dc6e1c4da1f..ac57838f0298f 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 1ed019f0a6927..fd7a51388bc10 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`, 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 0b0a7801049fe..095c871e8d205 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 c8c4d9b8fdb13..45ada8fd51606 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 6bc0d346c111a..98f316dd74bdd 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 0b432487615b2..9359244c6ebc1 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`, 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`, 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 99739c7bce041..5f86a6a0ca919 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 c634ea470c5d5..3446148d2b15b 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/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr index 304435cb21e8a..4c43419243190 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 40494b726f00c..45f715dc7b2dc 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 ee9ff3dcf9012..c30cdfc2e4fee 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 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 9c3bebd7797b8..5f895fab0fba4 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 9c3bebd7797b8..5f895fab0fba4 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 321f24adc46b4..20ab702c9c899 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/traits/object/pretty.rs b/tests/ui/traits/object/pretty.rs new file mode 100644 index 0000000000000..8958871ed5d72 --- /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 {} +trait FixedSub: Fixed {} +trait FixedStatic: Super {} + +trait SuperGeneric<'a> { + type Assoc2; +} +trait AnyGeneric<'a>: SuperGeneric<'a> {} +trait FixedGeneric1<'a>: SuperGeneric<'a, Assoc2 = &'a u8> {} +trait FixedGeneric2<'a>: Super {} +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 {} + +fn dyn_super(x: &dyn Super) { x } //~ERROR mismatched types +fn dyn_any(x: &dyn Any) { x } //~ERROR mismatched types +fn dyn_fixed(x: &dyn Fixed) { x } //~ERROR mismatched types +fn dyn_fixed_multi(x: &dyn Fixed) { 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) { 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 0000000000000..bc645e5f9677d --- /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) { x } + | - ^ expected `()`, found `&dyn Super` + | | + | help: try adding a return type: `-> &dyn Super` + | + = note: expected unit type `()` + found reference `&dyn Super` + +error[E0308]: mismatched types + --> $DIR/pretty.rs:22:39 + | +LL | fn dyn_any(x: &dyn Any) { x } + | - ^ expected `()`, found `&dyn Any` + | | + | help: try adding a return type: `-> &dyn Any` + | + = note: expected unit type `()` + found reference `&dyn Any` + +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) { 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: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) { x } + | - ^ expected `()`, found `&dyn AnyDifferentBinders` + | | + | help: try adding a return type: `-> &dyn AnyDifferentBinders` + | + = note: expected unit type `()` + found reference `&dyn AnyDifferentBinders` + +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/wf/hir-wf-canonicalized.rs b/tests/ui/wf/hir-wf-canonicalized.rs index bdb84409d009d..eac238f0fcab1 100644 --- a/tests/ui/wf/hir-wf-canonicalized.rs +++ b/tests/ui/wf/hir-wf-canonicalized.rs @@ -9,8 +9,8 @@ trait Callback: Fn(&Bar<'_, T>, &T::V) {} struct Bar<'a, T> { callback: Box>>>, //~^ ERROR the trait bound `Bar<'a, T>: Foo` is not satisfied - //~| ERROR the trait bound `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied - //~| ERROR the size for values of type `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time + //~| ERROR the trait bound `(dyn Callback, Output = ()> + 'static): Foo` is not satisfied + //~| ERROR the size for values of type `(dyn Callback, Output = ()> + 'static)` cannot be known at compilation time } impl Bar<'_, Bar<'_, T>> {} diff --git a/tests/ui/wf/hir-wf-canonicalized.stderr b/tests/ui/wf/hir-wf-canonicalized.stderr index 4dca1f65232e2..8938801ce3d97 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, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied +error[E0277]: the trait bound `(dyn Callback, Output = ()> + 'static): Foo` is not satisfied --> $DIR/hir-wf-canonicalized.rs:10:15 | LL | callback: Box>>>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback, 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, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time +error[E0277]: the size for values of type `(dyn Callback, Output = ()> + 'static)` cannot be known at compilation time --> $DIR/hir-wf-canonicalized.rs:10:15 | LL | callback: Box>>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `(dyn Callback, for<'b, 'c, 'd> Output = ()> + 'static)` + = help: the trait `Sized` is not implemented for `(dyn Callback, Output = ()> + 'static)` note: required by an implicit `Sized` bound in `Bar` --> $DIR/hir-wf-canonicalized.rs:9:16 |