Skip to content

Commit 7cd1da4

Browse files
committed
Rename and move several error reporting methods
Name them more consistently, descriptively and appropriately. Move large error reporting methods into the dedicated error module to make the happy paths in HIR ty lowering more legible.
1 parent bda903e commit 7cd1da4

File tree

4 files changed

+205
-192
lines changed

4 files changed

+205
-192
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
675675

676676
// Good error for `where Trait::method(..): Send`.
677677
let Some(self_ty) = opt_self_ty else {
678-
let guar = self.error_missing_qpath_self_ty(
678+
let guar = self.report_missing_self_ty_for_resolved_path(
679679
trait_def_id,
680680
hir_ty.span,
681681
item_segment,

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
7878

7979
// We don't support empty trait objects.
8080
if regular_traits.is_empty() && auto_traits.is_empty() {
81-
let guar = self.report_trait_object_with_no_traits_error(
82-
span,
83-
user_written_bounds.iter().copied(),
84-
);
81+
let guar =
82+
self.report_trait_object_with_no_traits(span, user_written_bounds.iter().copied());
8583
return Ty::new_error(tcx, guar);
8684
}
8785
// We don't support >1 principal
8886
if regular_traits.len() > 1 {
89-
let guar = self.report_trait_object_addition_traits_error(&regular_traits);
87+
let guar = self.report_trait_object_addition_traits(&regular_traits);
9088
return Ty::new_error(tcx, guar);
9189
}
9290
// Don't create a dyn trait if we have errors in the principal.
@@ -344,7 +342,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
344342
hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
345343
&& hir_bound.span.contains(span)
346344
});
347-
self.complain_about_missing_type_params(
345+
self.report_missing_type_params(
348346
missing_type_params,
349347
trait_ref.def_id,
350348
span,

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

+181-14
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ use rustc_errors::codes::*;
55
use rustc_errors::{
66
Applicability, Diag, ErrorGuaranteed, MultiSpan, listify, pluralize, struct_span_code_err,
77
};
8-
use rustc_hir as hir;
98
use rustc_hir::def::{CtorOf, DefKind, Res};
109
use rustc_hir::def_id::DefId;
10+
use rustc_hir::{self as hir, HirId};
1111
use rustc_middle::bug;
1212
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
1313
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
@@ -23,6 +23,7 @@ use rustc_trait_selection::traits::{
2323
FulfillmentError, dyn_compatibility_violations_for_assoc_item,
2424
};
2525
use smallvec::SmallVec;
26+
use tracing::debug;
2627

2728
use crate::errors::{
2829
self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
@@ -34,7 +35,7 @@ use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
3435
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
3536
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
3637
/// the type parameter's name as a placeholder.
37-
pub(crate) fn complain_about_missing_type_params(
38+
pub(crate) fn report_missing_type_params(
3839
&self,
3940
missing_type_params: Vec<Symbol>,
4041
def_id: DefId,
@@ -56,7 +57,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
5657

5758
/// When the code is using the `Fn` traits directly, instead of the `Fn(A) -> B` syntax, emit
5859
/// an error and attempt to build a reasonable structured suggestion.
59-
pub(crate) fn complain_about_internal_fn_trait(
60+
pub(crate) fn report_internal_fn_trait(
6061
&self,
6162
span: Span,
6263
trait_def_id: DefId,
@@ -112,7 +113,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
112113
}
113114
}
114115

115-
pub(super) fn complain_about_assoc_item_not_found<I>(
116+
pub(super) fn report_unresolved_assoc_item<I>(
116117
&self,
117118
all_candidates: impl Fn() -> I,
118119
qself: AssocItemQSelf,
@@ -132,7 +133,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
132133
.filter_by_name_unhygienic(assoc_ident.name)
133134
.find(|item| tcx.hygienic_eq(assoc_ident, item.ident(tcx), r.def_id()))
134135
}) {
135-
return self.complain_about_assoc_kind_mismatch(
136+
return self.report_assoc_kind_mismatch(
136137
assoc_item,
137138
assoc_tag,
138139
assoc_ident,
@@ -331,7 +332,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
331332
self.dcx().emit_err(err)
332333
}
333334

334-
fn complain_about_assoc_kind_mismatch(
335+
fn report_assoc_kind_mismatch(
335336
&self,
336337
assoc_item: &ty::AssocItem,
337338
assoc_tag: ty::AssocTag,
@@ -396,7 +397,173 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
396397
})
397398
}
398399

399-
pub(super) fn report_ambiguous_assoc(
400+
pub(crate) fn report_missing_self_ty_for_resolved_path(
401+
&self,
402+
trait_def_id: DefId,
403+
span: Span,
404+
item_segment: &hir::PathSegment<'tcx>,
405+
assoc_tag: ty::AssocTag,
406+
) -> ErrorGuaranteed {
407+
let tcx = self.tcx();
408+
let path_str = tcx.def_path_str(trait_def_id);
409+
410+
let def_id = self.item_def_id();
411+
debug!(item_def_id = ?def_id);
412+
413+
// FIXME: document why/how this is different from `tcx.local_parent(def_id)`
414+
let parent_def_id = tcx.hir_get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id();
415+
debug!(?parent_def_id);
416+
417+
// If the trait in segment is the same as the trait defining the item,
418+
// use the `<Self as ..>` syntax in the error.
419+
let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id;
420+
let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id;
421+
422+
let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
423+
vec!["Self".to_string()]
424+
} else {
425+
// Find all the types that have an `impl` for the trait.
426+
tcx.all_impls(trait_def_id)
427+
.filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
428+
.filter(|header| {
429+
// Consider only accessible traits
430+
tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
431+
&& header.polarity != ty::ImplPolarity::Negative
432+
})
433+
.map(|header| header.trait_ref.instantiate_identity().self_ty())
434+
// We don't care about blanket impls.
435+
.filter(|self_ty| !self_ty.has_non_region_param())
436+
.map(|self_ty| tcx.erase_regions(self_ty).to_string())
437+
.collect()
438+
};
439+
// FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
440+
// references the trait. Relevant for the first case in
441+
// `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
442+
self.report_ambiguous_assoc_item_path(
443+
span,
444+
&type_names,
445+
&[path_str],
446+
item_segment.ident.name,
447+
assoc_tag,
448+
)
449+
}
450+
451+
pub(super) fn report_unresolved_type_relative_path(
452+
&self,
453+
self_ty: Ty<'tcx>,
454+
hir_self_ty: &hir::Ty<'_>,
455+
assoc_tag: ty::AssocTag,
456+
ident: Ident,
457+
qpath_hir_id: HirId,
458+
span: Span,
459+
variant_def_id: Option<DefId>,
460+
) -> ErrorGuaranteed {
461+
let tcx = self.tcx();
462+
let kind_str = assoc_tag_str(assoc_tag);
463+
if variant_def_id.is_some() {
464+
// Variant in type position
465+
let msg = format!("expected {kind_str}, found variant `{ident}`");
466+
self.dcx().span_err(span, msg)
467+
} else if self_ty.is_enum() {
468+
let mut err = self.dcx().create_err(errors::NoVariantNamed {
469+
span: ident.span,
470+
ident,
471+
ty: self_ty,
472+
});
473+
474+
let adt_def = self_ty.ty_adt_def().expect("enum is not an ADT");
475+
if let Some(variant_name) = find_best_match_for_name(
476+
&adt_def.variants().iter().map(|variant| variant.name).collect::<Vec<Symbol>>(),
477+
ident.name,
478+
None,
479+
) && let Some(variant) = adt_def.variants().iter().find(|s| s.name == variant_name)
480+
{
481+
let mut suggestion = vec![(ident.span, variant_name.to_string())];
482+
if let hir::Node::Stmt(&hir::Stmt { kind: hir::StmtKind::Semi(expr), .. })
483+
| hir::Node::Expr(expr) = tcx.parent_hir_node(qpath_hir_id)
484+
&& let hir::ExprKind::Struct(..) = expr.kind
485+
{
486+
match variant.ctor {
487+
None => {
488+
// struct
489+
suggestion = vec![(
490+
ident.span.with_hi(expr.span.hi()),
491+
if variant.fields.is_empty() {
492+
format!("{variant_name} {{}}")
493+
} else {
494+
format!(
495+
"{variant_name} {{ {} }}",
496+
variant
497+
.fields
498+
.iter()
499+
.map(|f| format!("{}: /* value */", f.name))
500+
.collect::<Vec<_>>()
501+
.join(", ")
502+
)
503+
},
504+
)];
505+
}
506+
Some((hir::def::CtorKind::Fn, def_id)) => {
507+
// tuple
508+
let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
509+
let inputs = fn_sig.inputs().skip_binder();
510+
suggestion = vec![(
511+
ident.span.with_hi(expr.span.hi()),
512+
format!(
513+
"{variant_name}({})",
514+
inputs
515+
.iter()
516+
.map(|i| format!("/* {i} */"))
517+
.collect::<Vec<_>>()
518+
.join(", ")
519+
),
520+
)];
521+
}
522+
Some((hir::def::CtorKind::Const, _)) => {
523+
// unit
524+
suggestion = vec![(
525+
ident.span.with_hi(expr.span.hi()),
526+
variant_name.to_string(),
527+
)];
528+
}
529+
}
530+
}
531+
err.multipart_suggestion_verbose(
532+
"there is a variant with a similar name",
533+
suggestion,
534+
Applicability::HasPlaceholders,
535+
);
536+
} else {
537+
err.span_label(ident.span, format!("variant not found in `{self_ty}`"));
538+
}
539+
540+
if let Some(sp) = tcx.hir_span_if_local(adt_def.did()) {
541+
err.span_label(sp, format!("variant `{ident}` not found here"));
542+
}
543+
544+
err.emit()
545+
} else if let Err(reported) = self_ty.error_reported() {
546+
reported
547+
} else {
548+
match self.maybe_report_similar_assoc_fn(span, self_ty, hir_self_ty) {
549+
Ok(()) => {}
550+
Err(reported) => return reported,
551+
}
552+
553+
let traits: Vec<_> = self.probe_traits_that_match_assoc_ty(self_ty, ident);
554+
555+
// Don't print `ty::Error` to the user.
556+
self.report_ambiguous_assoc_item_path(
557+
span,
558+
&[self_ty.to_string()],
559+
&traits,
560+
ident.name,
561+
assoc_tag,
562+
)
563+
}
564+
}
565+
566+
pub(super) fn report_ambiguous_assoc_item_path(
400567
&self,
401568
span: Span,
402569
types: &[String],
@@ -505,7 +672,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
505672
err.emit()
506673
}
507674

508-
pub(crate) fn complain_about_ambiguous_inherent_assoc(
675+
pub(crate) fn report_ambiguous_inherent_assoc_item(
509676
&self,
510677
name: Ident,
511678
candidates: Vec<DefId>,
@@ -518,12 +685,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
518685
"multiple applicable items in scope"
519686
);
520687
err.span_label(name.span, format!("multiple `{name}` found"));
521-
self.note_ambiguous_inherent_assoc_ty(&mut err, candidates, span);
688+
self.note_ambiguous_inherent_assoc_item(&mut err, candidates, span);
522689
err.emit()
523690
}
524691

525692
// FIXME(fmease): Heavily adapted from `rustc_hir_typeck::method::suggest`. Deduplicate.
526-
fn note_ambiguous_inherent_assoc_ty(
693+
fn note_ambiguous_inherent_assoc_item(
527694
&self,
528695
err: &mut Diag<'_>,
529696
candidates: Vec<DefId>,
@@ -566,7 +733,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
566733
}
567734

568735
// FIXME(inherent_associated_types): Find similarly named associated types and suggest them.
569-
pub(crate) fn complain_about_inherent_assoc_not_found(
736+
pub(crate) fn report_unresolved_inherent_assoc_item(
570737
&self,
571738
name: Ident,
572739
self_ty: Ty<'tcx>,
@@ -1046,7 +1213,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10461213
}
10471214
}
10481215

1049-
pub fn report_prohibit_generics_error<'a>(
1216+
pub fn report_prohibited_generic_args<'a>(
10501217
&self,
10511218
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
10521219
args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone,
@@ -1128,7 +1295,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11281295
err.emit()
11291296
}
11301297

1131-
pub fn report_trait_object_addition_traits_error(
1298+
pub fn report_trait_object_addition_traits(
11321299
&self,
11331300
regular_traits: &Vec<(ty::PolyTraitPredicate<'tcx>, SmallVec<[Span; 1]>)>,
11341301
) -> ErrorGuaranteed {
@@ -1171,7 +1338,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
11711338
err.emit()
11721339
}
11731340

1174-
pub fn report_trait_object_with_no_traits_error(
1341+
pub fn report_trait_object_with_no_traits(
11751342
&self,
11761343
span: Span,
11771344
user_written_clauses: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,

0 commit comments

Comments
 (0)