rustc_hir_analysis
: some general code improvements
This commit is contained in:
parent
360e978437
commit
d60e772e14
@ -916,16 +916,14 @@ fn report_trait_method_mismatch<'tcx>(
|
|||||||
// When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
|
// When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
|
||||||
// span points only at the type `Box<Self`>, but we want to cover the whole
|
// span points only at the type `Box<Self`>, but we want to cover the whole
|
||||||
// argument pattern and type.
|
// argument pattern and type.
|
||||||
let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
|
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") };
|
||||||
ImplItemKind::Fn(ref sig, body) => tcx
|
let span = tcx
|
||||||
.hir()
|
.hir()
|
||||||
.body_param_names(body)
|
.body_param_names(body)
|
||||||
.zip(sig.decl.inputs.iter())
|
.zip(sig.decl.inputs.iter())
|
||||||
.map(|(param, ty)| param.span.to(ty.span))
|
.map(|(param, ty)| param.span.to(ty.span))
|
||||||
.next()
|
.next()
|
||||||
.unwrap_or(impl_err_span),
|
.unwrap_or(impl_err_span);
|
||||||
_ => bug!("{:?} is not a method", impl_m),
|
|
||||||
};
|
|
||||||
|
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
span,
|
span,
|
||||||
@ -938,22 +936,21 @@ fn report_trait_method_mismatch<'tcx>(
|
|||||||
if trait_sig.inputs().len() == *i {
|
if trait_sig.inputs().len() == *i {
|
||||||
// Suggestion to change output type. We do not suggest in `async` functions
|
// Suggestion to change output type. We do not suggest in `async` functions
|
||||||
// to avoid complex logic or incorrect output.
|
// to avoid complex logic or incorrect output.
|
||||||
match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
|
if let ImplItemKind::Fn(sig, _) = &tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind
|
||||||
ImplItemKind::Fn(ref sig, _) if !sig.header.asyncness.is_async() => {
|
&& !sig.header.asyncness.is_async()
|
||||||
let msg = "change the output type to match the trait";
|
{
|
||||||
let ap = Applicability::MachineApplicable;
|
let msg = "change the output type to match the trait";
|
||||||
match sig.decl.output {
|
let ap = Applicability::MachineApplicable;
|
||||||
hir::FnRetTy::DefaultReturn(sp) => {
|
match sig.decl.output {
|
||||||
let sugg = format!("-> {} ", trait_sig.output());
|
hir::FnRetTy::DefaultReturn(sp) => {
|
||||||
diag.span_suggestion_verbose(sp, msg, sugg, ap);
|
let sugg = format!("-> {} ", trait_sig.output());
|
||||||
}
|
diag.span_suggestion_verbose(sp, msg, sugg, ap);
|
||||||
hir::FnRetTy::Return(hir_ty) => {
|
}
|
||||||
let sugg = trait_sig.output();
|
hir::FnRetTy::Return(hir_ty) => {
|
||||||
diag.span_suggestion(hir_ty.span, msg, sugg, ap);
|
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) {
|
} else if let Some(trait_ty) = trait_sig.inputs().get(*i) {
|
||||||
diag.span_suggestion(
|
diag.span_suggestion(
|
||||||
@ -1080,25 +1077,18 @@ fn extract_spans_for_error_reporting<'tcx>(
|
|||||||
trait_m: &ty::AssocItem,
|
trait_m: &ty::AssocItem,
|
||||||
) -> (Span, Option<Span>) {
|
) -> (Span, Option<Span>) {
|
||||||
let tcx = infcx.tcx;
|
let tcx = infcx.tcx;
|
||||||
let mut impl_args = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
|
let mut impl_args = {
|
||||||
ImplItemKind::Fn(ref sig, _) => {
|
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()))
|
sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
|
||||||
}
|
|
||||||
_ => bug!("{:?} is not a method", impl_m),
|
|
||||||
};
|
};
|
||||||
let trait_args =
|
|
||||||
trait_m.def_id.as_local().map(|def_id| match tcx.hir().expect_trait_item(def_id).kind {
|
let trait_args = trait_m.def_id.as_local().map(|def_id| {
|
||||||
TraitItemKind::Fn(ref sig, _) => {
|
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()))
|
sig.decl.inputs.iter().map(|t| t.span).chain(iter::once(sig.decl.output.span()))
|
||||||
}
|
});
|
||||||
_ => bug!("{:?} is not a TraitItemKind::Fn", trait_m),
|
|
||||||
});
|
|
||||||
|
|
||||||
match terr {
|
match terr {
|
||||||
TypeError::ArgumentMutability(i) => {
|
TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => {
|
||||||
(impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(i)))
|
|
||||||
}
|
|
||||||
TypeError::ArgumentSorts(ExpectedFound { .. }, i) => {
|
|
||||||
(impl_args.nth(i).unwrap(), trait_args.and_then(|mut args| args.nth(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)),
|
_ => (cause.span(), tcx.hir().span_if_local(trait_m.def_id)),
|
||||||
@ -1158,8 +1148,7 @@ fn compare_self_type<'tcx>(
|
|||||||
} else {
|
} else {
|
||||||
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
|
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
|
||||||
}
|
}
|
||||||
let reported = err.emit();
|
return Err(err.emit());
|
||||||
return Err(reported);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(true, false) => {
|
(true, false) => {
|
||||||
@ -1178,8 +1167,8 @@ fn compare_self_type<'tcx>(
|
|||||||
} else {
|
} else {
|
||||||
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
|
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_m_fty = tcx.fn_sig(trait_m.def_id);
|
||||||
let trait_number_args = trait_m_fty.inputs().skip_binder().len();
|
let trait_number_args = trait_m_fty.inputs().skip_binder().len();
|
||||||
let impl_number_args = impl_m_fty.inputs().skip_binder().len();
|
let impl_number_args = impl_m_fty.inputs().skip_binder().len();
|
||||||
|
|
||||||
if trait_number_args != impl_number_args {
|
if trait_number_args != impl_number_args {
|
||||||
let trait_span = if let Some(def_id) = trait_m.def_id.as_local() {
|
let trait_span = trait_m
|
||||||
match tcx.hir().expect_trait_item(def_id).kind {
|
.def_id
|
||||||
TraitItemKind::Fn(ref trait_m_sig, _) => {
|
.as_local()
|
||||||
let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 };
|
.and_then(|def_id| {
|
||||||
if let Some(arg) = trait_m_sig.decl.inputs.get(pos) {
|
let TraitItemKind::Fn(trait_m_sig, _) = &tcx.hir().expect_trait_item(def_id).kind else { bug!("{:?} is not a method", impl_m) };
|
||||||
Some(if pos == 0 {
|
let pos = trait_number_args.saturating_sub(1);
|
||||||
arg.span
|
trait_m_sig.decl.inputs.get(pos).map(|arg| {
|
||||||
} else {
|
if pos == 0 {
|
||||||
arg.span.with_lo(trait_m_sig.decl.inputs[0].span.lo())
|
arg.span
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
trait_item_span
|
arg.span.with_lo(trait_m_sig.decl.inputs[0].span.lo())
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
_ => bug!("{:?} is not a method", impl_m),
|
})
|
||||||
}
|
.or(trait_item_span);
|
||||||
} else {
|
|
||||||
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 impl_span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
|
let pos = impl_number_args.saturating_sub(1);
|
||||||
ImplItemKind::Fn(ref impl_m_sig, _) => {
|
impl_m_sig
|
||||||
let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 };
|
.decl
|
||||||
if let Some(arg) = impl_m_sig.decl.inputs.get(pos) {
|
.inputs
|
||||||
|
.get(pos)
|
||||||
|
.map(|arg| {
|
||||||
if pos == 0 {
|
if pos == 0 {
|
||||||
arg.span
|
arg.span
|
||||||
} else {
|
} else {
|
||||||
arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo())
|
arg.span.with_lo(impl_m_sig.decl.inputs[0].span.lo())
|
||||||
}
|
}
|
||||||
} else {
|
})
|
||||||
impl_m_span
|
.unwrap_or(impl_m_span)
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => bug!("{:?} is not a method", impl_m),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
tcx.sess,
|
tcx.sess,
|
||||||
impl_span,
|
impl_span,
|
||||||
@ -1406,6 +1395,7 @@ fn compare_number_of_method_arguments<'tcx>(
|
|||||||
tcx.def_path_str(trait_m.def_id),
|
tcx.def_path_str(trait_m.def_id),
|
||||||
trait_number_args
|
trait_number_args
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(trait_span) = trait_span {
|
if let Some(trait_span) = trait_span {
|
||||||
err.span_label(
|
err.span_label(
|
||||||
trait_span,
|
trait_span,
|
||||||
@ -1417,6 +1407,7 @@ fn compare_number_of_method_arguments<'tcx>(
|
|||||||
} else {
|
} else {
|
||||||
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
|
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
|
||||||
}
|
}
|
||||||
|
|
||||||
err.span_label(
|
err.span_label(
|
||||||
impl_span,
|
impl_span,
|
||||||
format!(
|
format!(
|
||||||
@ -1425,8 +1416,8 @@ fn compare_number_of_method_arguments<'tcx>(
|
|||||||
impl_number_args
|
impl_number_args
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
let reported = err.emit();
|
|
||||||
return Err(reported);
|
return Err(err.emit());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1515,10 +1506,9 @@ fn compare_synthetic_generics<'tcx>(
|
|||||||
let _: Option<_> = try {
|
let _: Option<_> = try {
|
||||||
let impl_m = impl_m.def_id.as_local()?;
|
let impl_m = impl_m.def_id.as_local()?;
|
||||||
let impl_m = tcx.hir().expect_impl_item(impl_m);
|
let impl_m = tcx.hir().expect_impl_item(impl_m);
|
||||||
let input_tys = match impl_m.kind {
|
let hir::ImplItemKind::Fn(sig, _) = &impl_m.kind else { unreachable!() };
|
||||||
hir::ImplItemKind::Fn(ref sig, _) => sig.decl.inputs,
|
let input_tys = sig.decl.inputs;
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
struct Visitor(Option<Span>, hir::def_id::LocalDefId);
|
struct Visitor(Option<Span>, hir::def_id::LocalDefId);
|
||||||
impl<'v> intravisit::Visitor<'v> for Visitor {
|
impl<'v> intravisit::Visitor<'v> for Visitor {
|
||||||
fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
|
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);
|
let mut visitor = Visitor(None, impl_def_id);
|
||||||
for ty in input_tys {
|
for ty in input_tys {
|
||||||
intravisit::Visitor::visit_ty(&mut visitor, ty);
|
intravisit::Visitor::visit_ty(&mut visitor, ty);
|
||||||
@ -1556,8 +1547,7 @@ fn compare_synthetic_generics<'tcx>(
|
|||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
let reported = err.emit();
|
error_found = Some(err.emit());
|
||||||
error_found = Some(reported);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(reported) = error_found { Err(reported) } else { Ok(()) }
|
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
|
// Locate the Span containing just the type of the offending impl
|
||||||
match tcx.hir().expect_impl_item(impl_const_item_def).kind {
|
let ImplItemKind::Const(ty, _) = tcx.hir().expect_impl_item(impl_const_item_def).kind else { bug!("{impl_const_item:?} is not a impl const") };
|
||||||
ImplItemKind::Const(ref ty, _) => cause.span = ty.span,
|
cause.span = ty.span;
|
||||||
_ => bug!("{:?} is not a impl const", impl_const_item),
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut diag = struct_span_err!(
|
let mut diag = struct_span_err!(
|
||||||
tcx.sess,
|
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| {
|
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
|
// Add a label to the Span containing just the type of the const
|
||||||
match tcx.hir().expect_trait_item(trait_c_def_id).kind {
|
let TraitItemKind::Const(ty, _) = tcx.hir().expect_trait_item(trait_c_def_id).kind else { bug!("{trait_const_item:?} is not a trait const") };
|
||||||
TraitItemKind::Const(ref ty, _) => ty.span,
|
ty.span
|
||||||
_ => bug!("{:?} is not a trait const", trait_const_item),
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
infcx.err_ctxt().note_type_err(
|
infcx.err_ctxt().note_type_err(
|
||||||
|
@ -54,12 +54,9 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sp = match tcx.hir().expect_item(impl_did).kind {
|
let ItemKind::Impl(impl_) = tcx.hir().expect_item(impl_did).kind else { bug!("expected Drop impl item") };
|
||||||
ItemKind::Impl(ref impl_) => impl_.self_ty.span,
|
|
||||||
_ => 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) {
|
fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
|
||||||
|
@ -1342,21 +1342,19 @@ fn suggest_impl_trait<'tcx>(
|
|||||||
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
|
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
|
||||||
let icx = ItemCtxt::new(tcx, def_id);
|
let icx = ItemCtxt::new(tcx, def_id);
|
||||||
let item = tcx.hir().expect_item(def_id.expect_local());
|
let item = tcx.hir().expect_item(def_id.expect_local());
|
||||||
match item.kind {
|
let hir::ItemKind::Impl(impl_) = item.kind else { bug!() };
|
||||||
hir::ItemKind::Impl(ref impl_) => impl_
|
impl_
|
||||||
.of_trait
|
.of_trait
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|ast_trait_ref| {
|
.map(|ast_trait_ref| {
|
||||||
let selfty = tcx.type_of(def_id);
|
let selfty = tcx.type_of(def_id);
|
||||||
icx.astconv().instantiate_mono_trait_ref(
|
icx.astconv().instantiate_mono_trait_ref(
|
||||||
ast_trait_ref,
|
ast_trait_ref,
|
||||||
selfty,
|
selfty,
|
||||||
check_impl_constness(tcx, impl_.constness, ast_trait_ref),
|
check_impl_constness(tcx, impl_.constness, ast_trait_ref),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.map(ty::EarlyBinder),
|
.map(ty::EarlyBinder)
|
||||||
_ => bug!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_constness(
|
fn check_impl_constness(
|
||||||
|
@ -114,6 +114,7 @@ use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
|||||||
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
|
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
|
||||||
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
use std::ops::Not;
|
||||||
|
|
||||||
use astconv::AstConv;
|
use astconv::AstConv;
|
||||||
use bounds::Bounds;
|
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());
|
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
|
||||||
match tcx.hir().find(hir_id) {
|
match tcx.hir().find(hir_id) {
|
||||||
Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, ref generics, _), .. })) => {
|
Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => {
|
||||||
if !generics.params.is_empty() {
|
generics.params.is_empty().not().then(|| generics.span)
|
||||||
Some(generics.span)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
span_bug!(tcx.def_span(def_id), "main has a non-function type");
|
span_bug!(tcx.def_span(def_id), "main has a non-function type");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user