From d60e772e14a862a1ed3f6a7ee23faadbdd9cf443 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 9 Jan 2023 15:21:08 +0000 Subject: [PATCH] `rustc_hir_analysis`: some general code improvements --- .../src/check/compare_impl_item.rs | 162 ++++++++---------- .../src/coherence/builtin.rs | 7 +- compiler/rustc_hir_analysis/src/collect.rs | 28 ++- compiler/rustc_hir_analysis/src/lib.rs | 9 +- 4 files changed, 92 insertions(+), 114 deletions(-) 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 2133b5ac50b..6b47f4f019d 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -916,16 +916,14 @@ fn report_trait_method_mismatch<'tcx>( // When the `impl` receiver is an arbitrary self type, like `self: Box`, the // span points only at the type `Box, but we want to cover the whole // argument pattern and type. - let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { - ImplItemKind::Fn(ref sig, body) => tcx - .hir() - .body_param_names(body) - .zip(sig.decl.inputs.iter()) - .map(|(param, ty)| param.span.to(ty.span)) - .next() - .unwrap_or(impl_err_span), - _ => bug!("{:?} is not a method", impl_m), - }; + let ImplItemKind::Fn(ref sig, body) = tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind else { bug!("{impl_m:?} is not a method") }; + let span = tcx + .hir() + .body_param_names(body) + .zip(sig.decl.inputs.iter()) + .map(|(param, ty)| param.span.to(ty.span)) + .next() + .unwrap_or(impl_err_span); diag.span_suggestion( span, @@ -938,22 +936,21 @@ fn report_trait_method_mismatch<'tcx>( if trait_sig.inputs().len() == *i { // Suggestion to change output type. We do not suggest in `async` functions // to avoid complex logic or incorrect output. - match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { - ImplItemKind::Fn(ref sig, _) if !sig.header.asyncness.is_async() => { - let msg = "change the output type to match the trait"; - let ap = Applicability::MachineApplicable; - match sig.decl.output { - hir::FnRetTy::DefaultReturn(sp) => { - let sugg = format!("-> {} ", trait_sig.output()); - diag.span_suggestion_verbose(sp, msg, sugg, ap); - } - hir::FnRetTy::Return(hir_ty) => { - let sugg = trait_sig.output(); - diag.span_suggestion(hir_ty.span, msg, sugg, ap); - } - }; - } - _ => {} + if let ImplItemKind::Fn(sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind + && !sig.header.asyncness.is_async() + { + let msg = "change the output type to match the trait"; + let ap = Applicability::MachineApplicable; + match sig.decl.output { + hir::FnRetTy::DefaultReturn(sp) => { + let sugg = format!("-> {} ", trait_sig.output()); + diag.span_suggestion_verbose(sp, msg, sugg, ap); + } + hir::FnRetTy::Return(hir_ty) => { + let sugg = trait_sig.output(); + diag.span_suggestion(hir_ty.span, msg, sugg, ap); + } + }; }; } else if let Some(trait_ty) = trait_sig.inputs().get(*i) { diag.span_suggestion( @@ -1080,25 +1077,18 @@ fn extract_spans_for_error_reporting<'tcx>( trait_m: &ty::AssocItem, ) -> (Span, Option) { let tcx = infcx.tcx; - let mut impl_args = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { - ImplItemKind::Fn(ref sig, _) => { - sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) - } - _ => bug!("{:?} is not a method", impl_m), + let mut impl_args = { + let ImplItemKind::Fn(sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind else { bug!("{:?} is not a method", impl_m) }; + sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) }; - let trait_args = - trait_m.def_id.as_local().map(|def_id| match tcx.hir().expect_trait_item(def_id).kind { - TraitItemKind::Fn(ref sig, _) => { - sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) - } - _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m), - }); + + let trait_args = trait_m.def_id.as_local().map(|def_id| { + let TraitItemKind::Fn(sig, _) = &tcx.hir().expect_trait_item(def_id).kind else { bug!("{:?} is not a TraitItemKind::Fn", trait_m) }; + sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span())) + }); match terr { - TypeError::ArgumentMutability(i) => { - (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i))) - } - TypeError::ArgumentSorts(ExpectedFound { .. }, i) => { + TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => { (impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i))) } _ => (cause.span(), tcx.hir().span_if_local(trait_m.def_id)), @@ -1158,8 +1148,7 @@ fn compare_self_type<'tcx>( } else { err.note_trait_signature(trait_m.name, trait_m.signature(tcx)); } - let reported = err.emit(); - return Err(reported); + return Err(err.emit()); } (true, false) => { @@ -1178,8 +1167,8 @@ fn compare_self_type<'tcx>( } else { err.note_trait_signature(trait_m.name, trait_m.signature(tcx)); } - let reported = err.emit(); - return Err(reported); + + return Err(err.emit()); } } @@ -1361,41 +1350,41 @@ fn compare_number_of_method_arguments<'tcx>( let trait_m_fty = tcx.fn_sig(trait_m.def_id); let trait_number_args = trait_m_fty.inputs().skip_binder().len(); let impl_number_args = impl_m_fty.inputs().skip_binder().len(); + if trait_number_args != impl_number_args { - let trait_span = if let Some(def_id) = trait_m.def_id.as_local() { - match tcx.hir().expect_trait_item(def_id).kind { - TraitItemKind::Fn(ref trait_m_sig, _) => { - let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 }; - if let Some(arg) = trait_m_sig.decl.inputs.get(pos) { - Some(if pos == 0 { - arg.span - } else { - arg.span.with_lo(trait_m_sig.decl.inputs[0].span.lo()) - }) + let trait_span = trait_m + .def_id + .as_local() + .and_then(|def_id| { + let TraitItemKind::Fn(trait_m_sig, _) = &tcx.hir().expect_trait_item(def_id).kind else { bug!("{:?} is not a method", impl_m) }; + let pos = trait_number_args.saturating_sub(1); + trait_m_sig.decl.inputs.get(pos).map(|arg| { + if pos == 0 { + arg.span } else { - trait_item_span + arg.span.with_lo(trait_m_sig.decl.inputs[0].span.lo()) } - } - _ => bug!("{:?} is not a method", impl_m), - } - } else { - trait_item_span - }; - let impl_span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { - ImplItemKind::Fn(ref impl_m_sig, _) => { - let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 }; - if let Some(arg) = impl_m_sig.decl.inputs.get(pos) { + }) + }) + .or(trait_item_span); + + let impl_span = { + let ImplItemKind::Fn(impl_m_sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind else { bug!("{:?} is not a method", impl_m) }; + let pos = impl_number_args.saturating_sub(1); + impl_m_sig + .decl + .inputs + .get(pos) + .map(|arg| { if pos == 0 { arg.span } else { arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo()) } - } else { - impl_m_span - } - } - _ => bug!("{:?} is not a method", impl_m), + }) + .unwrap_or(impl_m_span) }; + let mut err = struct_span_err!( tcx.sess, impl_span, @@ -1406,6 +1395,7 @@ fn compare_number_of_method_arguments<'tcx>( tcx.def_path_str(trait_m.def_id), trait_number_args ); + if let Some(trait_span) = trait_span { err.span_label( trait_span, @@ -1417,6 +1407,7 @@ fn compare_number_of_method_arguments<'tcx>( } else { err.note_trait_signature(trait_m.name, trait_m.signature(tcx)); } + err.span_label( impl_span, format!( @@ -1425,8 +1416,8 @@ fn compare_number_of_method_arguments<'tcx>( impl_number_args ), ); - let reported = err.emit(); - return Err(reported); + + return Err(err.emit()); } Ok(()) @@ -1515,10 +1506,9 @@ fn compare_synthetic_generics<'tcx>( let _: Option<_> = try { let impl_m = impl_m.def_id.as_local()?; let impl_m = tcx.hir().expect_impl_item(impl_m); - let input_tys = match impl_m.kind { - hir::ImplItemKind::Fn(ref sig, _) => sig.decl.inputs, - _ => unreachable!(), - }; + let hir::ImplItemKind::Fn(sig, _) = &impl_m.kind else { unreachable!() }; + let input_tys = sig.decl.inputs; + struct Visitor(Option, hir::def_id::LocalDefId); impl<'v> intravisit::Visitor<'v> for Visitor { fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { @@ -1532,6 +1522,7 @@ fn compare_synthetic_generics<'tcx>( } } } + let mut visitor = Visitor(None, impl_def_id); for ty in input_tys { intravisit::Visitor::visit_ty(&mut visitor, ty); @@ -1556,8 +1547,7 @@ fn compare_synthetic_generics<'tcx>( } _ => unreachable!(), } - let reported = err.emit(); - error_found = Some(reported); + error_found = Some(err.emit()); } } if let Some(reported) = error_found { Err(reported) } else { Ok(()) } @@ -1717,10 +1707,8 @@ pub(super) fn compare_impl_const_raw( ); // Locate the Span containing just the type of the offending impl - match tcx.hir().expect_impl_item(impl_const_item_def).kind { - ImplItemKind::Const(ref ty, _) => cause.span = ty.span, - _ => bug!("{:?} is not a impl const", impl_const_item), - } + let ImplItemKind::Const(ty, _) = tcx.hir().expect_impl_item(impl_const_item_def).kind else { bug!("{impl_const_item:?} is not a impl const") }; + cause.span = ty.span; let mut diag = struct_span_err!( tcx.sess, @@ -1732,10 +1720,8 @@ pub(super) fn compare_impl_const_raw( let trait_c_span = trait_const_item_def.as_local().map(|trait_c_def_id| { // Add a label to the Span containing just the type of the const - match tcx.hir().expect_trait_item(trait_c_def_id).kind { - TraitItemKind::Const(ref ty, _) => ty.span, - _ => bug!("{:?} is not a trait const", trait_const_item), - } + let TraitItemKind::Const(ty, _) = tcx.hir().expect_trait_item(trait_c_def_id).kind else { bug!("{trait_const_item:?} is not a trait const") }; + ty.span }); infcx.err_ctxt().note_type_err( diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 5bdd18fcd63..3e6dafd2c6f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -54,12 +54,9 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) { _ => {} } - let sp = match tcx.hir().expect_item(impl_did).kind { - ItemKind::Impl(ref impl_) => impl_.self_ty.span, - _ => bug!("expected Drop impl item"), - }; + let ItemKind::Impl(impl_) = tcx.hir().expect_item(impl_did).kind else { bug!("expected Drop impl item") }; - tcx.sess.emit_err(DropImplOnWrongItem { span: sp }); + tcx.sess.emit_err(DropImplOnWrongItem { span: impl_.self_ty.span }); } fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 35f47dfc1a5..093a84160fe 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1342,21 +1342,19 @@ fn suggest_impl_trait<'tcx>( fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option>> { let icx = ItemCtxt::new(tcx, def_id); let item = tcx.hir().expect_item(def_id.expect_local()); - match item.kind { - hir::ItemKind::Impl(ref impl_) => impl_ - .of_trait - .as_ref() - .map(|ast_trait_ref| { - let selfty = tcx.type_of(def_id); - icx.astconv().instantiate_mono_trait_ref( - ast_trait_ref, - selfty, - check_impl_constness(tcx, impl_.constness, ast_trait_ref), - ) - }) - .map(ty::EarlyBinder), - _ => bug!(), - } + let hir::ItemKind::Impl(impl_) = item.kind else { bug!() }; + impl_ + .of_trait + .as_ref() + .map(|ast_trait_ref| { + let selfty = tcx.type_of(def_id); + icx.astconv().instantiate_mono_trait_ref( + ast_trait_ref, + selfty, + check_impl_constness(tcx, impl_.constness, ast_trait_ref), + ) + }) + .map(ty::EarlyBinder) } fn check_impl_constness( diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index ddc5b766881..97fff85f424 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -114,6 +114,7 @@ use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; use std::iter; +use std::ops::Not; use astconv::AstConv; use bounds::Bounds; @@ -203,12 +204,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { } let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); match tcx.hir().find(hir_id) { - Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => { - if !generics.params.is_empty() { - Some(generics.span) - } else { - None - } + Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => { + generics.params.is_empty().not().then(|| generics.span) } _ => { span_bug!(tcx.def_span(def_id), "main has a non-function type");