diff options
| author | Ellen <supbscripter@gmail.com> | 2022-05-05 17:44:54 +0100 |
|---|---|---|
| committer | Ellen <supbscripter@gmail.com> | 2022-05-05 17:45:39 +0100 |
| commit | fea1d765033eada386ffc1684d47c00a48d104f1 (patch) | |
| tree | fef19174b45842ee05a51064217311a101fed588 /compiler | |
| parent | 4208c53ed695ddb822b6510e3faa0a46e591060e (diff) | |
| download | rust-fea1d765033eada386ffc1684d47c00a48d104f1.tar.gz rust-fea1d765033eada386ffc1684d47c00a48d104f1.zip | |
make `compare_generic_param_kinds` errors consistent
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_typeck/src/check/compare_method.rs | 166 |
1 files changed, 48 insertions, 118 deletions
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index c810be16bf8..590131e4f6a 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -7,10 +7,10 @@ use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; use rustc_infer::traits::util; -use rustc_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::util::ExplicitSelf; +use rustc_middle::ty::{self, DefIdTree}; use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; @@ -48,7 +48,7 @@ crate fn compare_impl_method<'tcx>( return; } - if let Err(_) = compare_generic_param_kinds(tcx, impl_m, trait_m, trait_item_span) { + if let Err(_) = compare_generic_param_kinds(tcx, impl_m, trait_m) { return; } @@ -973,7 +973,6 @@ fn compare_generic_param_kinds<'tcx>( tcx: TyCtxt<'tcx>, impl_item: &ty::AssocItem, trait_item: &ty::AssocItem, - trait_item_span: Option<Span>, ) -> Result<(), ErrorGuaranteed> { assert_eq!(impl_item.kind, trait_item.kind); @@ -986,123 +985,54 @@ fn compare_generic_param_kinds<'tcx>( }) }; - let get_param_span = |param: &ty::GenericParamDef| match tcx.hir().get_if_local(param.def_id) { - Some(hir::Node::GenericParam(hir::GenericParam { span, .. })) => Some(span), - _ => None, - }; + for (param_impl, param_trait) in + iter::zip(ty_const_params_of(impl_item.def_id), ty_const_params_of(trait_item.def_id)) + { + use GenericParamDefKind::*; + if match (¶m_impl.kind, ¶m_trait.kind) { + (Const { .. }, Const { .. }) + if tcx.type_of(param_impl.def_id) != tcx.type_of(param_trait.def_id) => + { + true + } + (Const { .. }, Type { .. }) | (Type { .. }, Const { .. }) => true, + // this is exhaustive so that anyone adding new generic param kinds knows + // to make sure this error is reported for them. + (Const { .. }, Const { .. }) | (Type { .. }, Type { .. }) => false, + (Lifetime { .. }, _) | (_, Lifetime { .. }) => unreachable!(), + } { + let make_param_message = |prefix: &str, param: &ty::GenericParamDef| match param.kind { + Const { .. } => { + format!("{} const parameter with type `{}`", prefix, tcx.type_of(param.def_id)) + } + Type { .. } => format!("{} type parameter", prefix), + Lifetime { .. } => unreachable!(), + }; - let get_param_ident = |param: &ty::GenericParamDef| match tcx.hir().get_if_local(param.def_id) { - Some(hir::Node::GenericParam(hir::GenericParam { name, .. })) => match name { - hir::ParamName::Plain(ident) => Some(ident), - _ => None, - }, - other => bug!( - "expected GenericParam, found {:?}", - other.map_or_else(|| "nothing".to_string(), |n| format!("{:?}", n)) - ), - }; + let param_impl_span = tcx.def_span(param_impl.def_id); + let param_trait_span = tcx.def_span(param_trait.def_id); - let ty_const_params_impl = ty_const_params_of(impl_item.def_id); - let ty_const_params_trait = ty_const_params_of(trait_item.def_id); - let assoc_item_str = assoc_item_kind_str(&impl_item); + let mut err = struct_span_err!( + tcx.sess, + param_impl_span, + E0053, + "{} `{}` has an incompatible generic parameter for trait: `{}`", + assoc_item_kind_str(&impl_item), + trait_item.name, + &tcx.def_path_str(tcx.parent(trait_item.def_id)) + ); - for (param_impl, param_trait) in iter::zip(ty_const_params_impl, ty_const_params_trait) { - use GenericParamDefKind::*; - match (¶m_impl.kind, ¶m_trait.kind) { - (Const { .. }, Const { .. }) => { - let impl_ty = tcx.type_of(param_impl.def_id); - let trait_ty = tcx.type_of(param_trait.def_id); - if impl_ty != trait_ty { - let param_impl_span = get_param_span(param_impl).unwrap(); - let param_impl_ident = get_param_ident(param_impl); - let param_trait_span = get_param_span(param_trait); - - let mut err = struct_span_err!( - tcx.sess, - *param_impl_span, - E0053, - "{} `{}` has an incompatible const parameter type for trait", - assoc_item_str, - trait_item.name, - ); - err.span_note( - param_trait_span.map_or_else( - || trait_item_span.unwrap_or(*param_impl_span), - |span| *span, - ), - &format!( - "the const parameter{} has type `{}`, but the declaration \ - in trait `{}` has type `{}`", - ¶m_impl_ident - .map_or_else(|| "".to_string(), |ident| format!(" `{ident}`")), - impl_ty, - tcx.def_path_str(trait_item.def_id), - trait_ty - ), - ); - let reported = err.emit(); - return Err(reported); - } - } - (Const { .. }, Type { .. }) => { - let impl_ty = tcx.type_of(param_impl.def_id); - let param_impl_span = get_param_span(param_impl).unwrap(); - let param_impl_ident = get_param_ident(param_impl); - let param_trait_span = get_param_span(param_trait); - - let mut err = struct_span_err!( - tcx.sess, - *param_impl_span, - E0053, - "{} `{}` has an incompatible generic parameter for trait", - assoc_item_str, - trait_item.name, - ); - err.span_note( - param_trait_span - .map_or_else(|| trait_item_span.unwrap_or(*param_impl_span), |span| *span), - &format!( - "the trait impl specifies{} a const parameter of type `{}`, but the declaration \ - in trait `{}` requires it is a type parameter", - ¶m_impl_ident - .map_or_else(|| "".to_string(), |ident| format!(" `{ident}` is")), - impl_ty, - tcx.def_path_str(trait_item.def_id), - ), - ); - let reported = err.emit(); - return Err(reported); - } - (Type { .. }, Const { .. }) => { - let trait_ty = tcx.type_of(param_trait.def_id); - let param_impl_span = get_param_span(param_impl).unwrap(); - let param_impl_ident = get_param_ident(param_impl); - let param_trait_span = get_param_span(param_trait); - - let mut err = struct_span_err!( - tcx.sess, - *param_impl_span, - E0053, - "{} `{}` has an incompatible generic parameter for trait", - assoc_item_str, - trait_item.name, - ); - err.span_note( - param_trait_span - .map_or_else(|| trait_item_span.unwrap_or(*param_impl_span), |span| *span), - &format!( - "the trait impl specifies{} a type parameter, but the declaration \ - in trait `{}` requires it is a const parameter of type `{}`", - ¶m_impl_ident - .map_or_else(|| "".to_string(), |ident| format!(" `{ident}` is")), - tcx.def_path_str(trait_item.def_id), - trait_ty, - ), - ); - let reported = err.emit(); - return Err(reported); - } - _ => (), + let trait_header_span = tcx.def_ident_span(tcx.parent(trait_item.def_id)).unwrap(); + err.span_label(trait_header_span, ""); + err.span_label(param_trait_span, make_param_message("expected", param_trait)); + + let impl_header_span = + tcx.sess.source_map().guess_head_span(tcx.def_span(tcx.parent(impl_item.def_id))); + err.span_label(impl_header_span, ""); + err.span_label(param_impl_span, make_param_message("found", param_impl)); + + let reported = err.emit(); + return Err(reported); } } @@ -1228,7 +1158,7 @@ crate fn compare_ty_impl<'tcx>( let _: Result<(), ErrorGuaranteed> = (|| { compare_number_of_generics(tcx, impl_ty, impl_ty_span, trait_ty, trait_item_span)?; - compare_generic_param_kinds(tcx, impl_ty, trait_ty, trait_item_span)?; + compare_generic_param_kinds(tcx, impl_ty, trait_ty)?; let sp = tcx.def_span(impl_ty.def_id); compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?; |
