Skip to content

Commit 7940303

Browse files
committed
Split astconv's error report code in check functions to mod errors.
Move some error report codes to mod `astconv/errors.rs`
1 parent c3b05c6 commit 7940303

File tree

5 files changed

+296
-244
lines changed

5 files changed

+296
-244
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

+172-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use crate::errors::{
22
self, AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams,
3-
ParenthesizedFnTraitExpansion,
3+
ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
44
};
55
use crate::fluent_generated as fluent;
66
use crate::hir_ty_lowering::HirTyLowerer;
77
use crate::traits::error_reporting::report_object_safety_error;
88
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
99
use rustc_data_structures::sorted_map::SortedMap;
1010
use rustc_data_structures::unord::UnordMap;
11+
use rustc_errors::MultiSpan;
1112
use rustc_errors::{
1213
codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed,
1314
};
@@ -16,11 +17,14 @@ use rustc_hir::def_id::{DefId, LocalDefId};
1617
use rustc_infer::traits::FulfillmentError;
1718
use rustc_middle::query::Key;
1819
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt, TypeVisitableExt};
20+
use rustc_middle::ty::{Binder, TraitRef};
1921
use rustc_session::parse::feature_err;
2022
use rustc_span::edit_distance::find_best_match_for_name;
2123
use rustc_span::symbol::{sym, Ident};
2224
use rustc_span::{Span, Symbol, DUMMY_SP};
23-
use rustc_trait_selection::traits::object_safety_violations_for_assoc_item;
25+
use rustc_trait_selection::traits::{
26+
object_safety_violations_for_assoc_item, TraitAliasExpansionInfo,
27+
};
2428

2529
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2630
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
@@ -1024,15 +1028,179 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10241028
Ok(())
10251029
}
10261030
}
1031+
1032+
pub fn report_prohibit_generics_error<'a>(
1033+
&self,
1034+
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1035+
args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone,
1036+
extend: impl Fn(&mut Diag<'_>),
1037+
) -> ErrorGuaranteed {
1038+
#[derive(PartialEq, Eq, Hash)]
1039+
enum ProhibitGenericsArg {
1040+
Lifetime,
1041+
Type,
1042+
Const,
1043+
Infer,
1044+
}
1045+
1046+
let mut prohibit_args = FxIndexSet::default();
1047+
args_visitors.for_each(|arg| {
1048+
match arg {
1049+
hir::GenericArg::Lifetime(_) => prohibit_args.insert(ProhibitGenericsArg::Lifetime),
1050+
hir::GenericArg::Type(_) => prohibit_args.insert(ProhibitGenericsArg::Type),
1051+
hir::GenericArg::Const(_) => prohibit_args.insert(ProhibitGenericsArg::Const),
1052+
hir::GenericArg::Infer(_) => prohibit_args.insert(ProhibitGenericsArg::Infer),
1053+
};
1054+
});
1055+
1056+
let types_and_spans: Vec<_> = segments
1057+
.clone()
1058+
.flat_map(|segment| {
1059+
if segment.args().args.is_empty() {
1060+
None
1061+
} else {
1062+
Some((
1063+
match segment.res {
1064+
hir::def::Res::PrimTy(ty) => {
1065+
format!("{} `{}`", segment.res.descr(), ty.name())
1066+
}
1067+
hir::def::Res::Def(_, def_id)
1068+
if let Some(name) = self.tcx().opt_item_name(def_id) =>
1069+
{
1070+
format!("{} `{name}`", segment.res.descr())
1071+
}
1072+
hir::def::Res::Err => "this type".to_string(),
1073+
_ => segment.res.descr().to_string(),
1074+
},
1075+
segment.ident.span,
1076+
))
1077+
}
1078+
})
1079+
.collect();
1080+
let this_type = match &types_and_spans[..] {
1081+
[.., _, (last, _)] => format!(
1082+
"{} and {last}",
1083+
types_and_spans[..types_and_spans.len() - 1]
1084+
.iter()
1085+
.map(|(x, _)| x.as_str())
1086+
.intersperse(", ")
1087+
.collect::<String>()
1088+
),
1089+
[(only, _)] => only.to_string(),
1090+
[] => "this type".to_string(),
1091+
};
1092+
1093+
let arg_spans: Vec<Span> = segments
1094+
.clone()
1095+
.flat_map(|segment| segment.args().args)
1096+
.map(|arg| arg.span())
1097+
.collect();
1098+
1099+
let mut kinds = Vec::with_capacity(4);
1100+
prohibit_args.iter().for_each(|arg| match arg {
1101+
ProhibitGenericsArg::Lifetime => kinds.push("lifetime"),
1102+
ProhibitGenericsArg::Type => kinds.push("type"),
1103+
ProhibitGenericsArg::Const => kinds.push("const"),
1104+
ProhibitGenericsArg::Infer => kinds.push("generic"),
1105+
});
1106+
1107+
let (kind, s) = match kinds[..] {
1108+
[.., _, last] => (
1109+
format!(
1110+
"{} and {last}",
1111+
kinds[..kinds.len() - 1]
1112+
.iter()
1113+
.map(|&x| x)
1114+
.intersperse(", ")
1115+
.collect::<String>()
1116+
),
1117+
"s",
1118+
),
1119+
[only] => (only.to_string(), ""),
1120+
[] => unreachable!("expected at least one generic to prohibit"),
1121+
};
1122+
let last_span = *arg_spans.last().unwrap();
1123+
let span: MultiSpan = arg_spans.into();
1124+
let mut err = struct_span_code_err!(
1125+
self.tcx().dcx(),
1126+
span,
1127+
E0109,
1128+
"{kind} arguments are not allowed on {this_type}",
1129+
);
1130+
err.span_label(last_span, format!("{kind} argument{s} not allowed"));
1131+
for (what, span) in types_and_spans {
1132+
err.span_label(span, format!("not allowed on {what}"));
1133+
}
1134+
extend(&mut err);
1135+
let reported = err.emit();
1136+
self.set_tainted_by_errors(reported);
1137+
reported
1138+
}
1139+
1140+
pub fn report_trait_object_addition_traits_error(
1141+
&self,
1142+
regular_traits: &Vec<TraitAliasExpansionInfo<'_>>,
1143+
) -> ErrorGuaranteed {
1144+
let tcx = self.tcx();
1145+
let first_trait = &regular_traits[0];
1146+
let additional_trait = &regular_traits[1];
1147+
let mut err = struct_span_code_err!(
1148+
tcx.dcx(),
1149+
additional_trait.bottom().1,
1150+
E0225,
1151+
"only auto traits can be used as additional traits in a trait object"
1152+
);
1153+
additional_trait.label_with_exp_info(
1154+
&mut err,
1155+
"additional non-auto trait",
1156+
"additional use",
1157+
);
1158+
first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
1159+
err.help(format!(
1160+
"consider creating a new trait with all of these as supertraits and using that \
1161+
trait here instead: `trait NewTrait: {} {{}}`",
1162+
regular_traits
1163+
.iter()
1164+
// FIXME: This should `print_sugared`, but also needs to integrate projection bounds...
1165+
.map(|t| t.trait_ref().print_only_trait_path().to_string())
1166+
.collect::<Vec<_>>()
1167+
.join(" + "),
1168+
));
1169+
err.note(
1170+
"auto-traits like `Send` and `Sync` are traits that have special properties; \
1171+
for more information on them, visit \
1172+
<https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
1173+
);
1174+
let reported = err.emit();
1175+
self.set_tainted_by_errors(reported);
1176+
reported
1177+
}
1178+
1179+
pub fn report_trait_object_with_no_traits_error(
1180+
&self,
1181+
span: Span,
1182+
trait_bounds: &Vec<(Binder<'tcx, TraitRef<'tcx>>, Span)>,
1183+
) -> ErrorGuaranteed {
1184+
let tcx = self.tcx();
1185+
let trait_alias_span = trait_bounds
1186+
.iter()
1187+
.map(|&(trait_ref, _)| trait_ref.def_id())
1188+
.find(|&trait_ref| tcx.is_trait_alias(trait_ref))
1189+
.map(|trait_ref| tcx.def_span(trait_ref));
1190+
let reported =
1191+
tcx.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
1192+
self.set_tainted_by_errors(reported);
1193+
reported
1194+
}
10271195
}
10281196

10291197
/// Emits an error regarding forbidden type binding associations
10301198
pub fn prohibit_assoc_item_binding(
10311199
tcx: TyCtxt<'_>,
10321200
span: Span,
10331201
segment: Option<(&hir::PathSegment<'_>, Span)>,
1034-
) {
1035-
tcx.dcx().emit_err(AssocTypeBindingNotAllowed {
1202+
) -> ErrorGuaranteed {
1203+
return tcx.dcx().emit_err(AssocTypeBindingNotAllowed {
10361204
span,
10371205
fn_trait_expansion: if let Some((segment, span)) = segment
10381206
&& segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar

0 commit comments

Comments
 (0)