Skip to content

Commit f9a328f

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 f9a328f

File tree

4 files changed

+180
-134
lines changed

4 files changed

+180
-134
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

+167-2
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,22 @@ 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+
};
28+
29+
#[derive(PartialEq, Eq, Hash)]
30+
pub enum ProhibitGenericsArg {
31+
Lifetime,
32+
Type,
33+
Const,
34+
Infer,
35+
}
2436

2537
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2638
/// On missing type parameters, emit an E0393 error and provide a structured suggestion using
@@ -1024,6 +1036,159 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10241036
Ok(())
10251037
}
10261038
}
1039+
1040+
pub fn report_prohibit_generics_error<'a>(
1041+
&self,
1042+
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
1043+
args_visitors: impl Iterator<Item = &'a hir::GenericArg<'a>> + Clone,
1044+
extend: impl Fn(&mut Diag<'_>),
1045+
) -> ErrorGuaranteed {
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+
span: Span,
1143+
trait_bounds: &Vec<(Binder<'tcx, TraitRef<'tcx>>, Span)>,
1144+
regular_traits: &Vec<TraitAliasExpansionInfo<'_>>,
1145+
) -> ErrorGuaranteed {
1146+
let tcx = self.tcx();
1147+
if regular_traits.len() > 1 {
1148+
let first_trait = &regular_traits[0];
1149+
let additional_trait = &regular_traits[1];
1150+
let mut err = struct_span_code_err!(
1151+
tcx.dcx(),
1152+
additional_trait.bottom().1,
1153+
E0225,
1154+
"only auto traits can be used as additional traits in a trait object"
1155+
);
1156+
additional_trait.label_with_exp_info(
1157+
&mut err,
1158+
"additional non-auto trait",
1159+
"additional use",
1160+
);
1161+
first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
1162+
err.help(format!(
1163+
"consider creating a new trait with all of these as supertraits and using that \
1164+
trait here instead: `trait NewTrait: {} {{}}`",
1165+
regular_traits
1166+
.iter()
1167+
// FIXME: This should `print_sugared`, but also needs to integrate projection bounds...
1168+
.map(|t| t.trait_ref().print_only_trait_path().to_string())
1169+
.collect::<Vec<_>>()
1170+
.join(" + "),
1171+
));
1172+
err.note(
1173+
"auto-traits like `Send` and `Sync` are traits that have special properties; \
1174+
for more information on them, visit \
1175+
<https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
1176+
);
1177+
let reported = err.emit();
1178+
self.set_tainted_by_errors(reported);
1179+
reported
1180+
} else {
1181+
let trait_alias_span = trait_bounds
1182+
.iter()
1183+
.map(|&(trait_ref, _)| trait_ref.def_id())
1184+
.find(|&trait_ref| tcx.is_trait_alias(trait_ref))
1185+
.map(|trait_ref| tcx.def_span(trait_ref));
1186+
let reported =
1187+
tcx.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
1188+
self.set_tainted_by_errors(reported);
1189+
reported
1190+
}
1191+
}
10271192
}
10281193

10291194
/// Emits an error regarding forbidden type binding associations

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+3-91
Original file line numberDiff line numberDiff line change
@@ -1626,98 +1626,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16261626
segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
16271627
extend: impl Fn(&mut Diag<'_>),
16281628
) -> bool {
1629-
let args = segments.clone().flat_map(|segment| segment.args().args);
1630-
1631-
let (lt, ty, ct, inf) =
1632-
args.clone().fold((false, false, false, false), |(lt, ty, ct, inf), arg| match arg {
1633-
hir::GenericArg::Lifetime(_) => (true, ty, ct, inf),
1634-
hir::GenericArg::Type(_) => (lt, true, ct, inf),
1635-
hir::GenericArg::Const(_) => (lt, ty, true, inf),
1636-
hir::GenericArg::Infer(_) => (lt, ty, ct, true),
1637-
});
1629+
let args_visitors = segments.clone().flat_map(|segment| segment.args().args);
16381630
let mut emitted = false;
1639-
if lt || ty || ct || inf {
1640-
let types_and_spans: Vec<_> = segments
1641-
.clone()
1642-
.flat_map(|segment| {
1643-
if segment.args().args.is_empty() {
1644-
None
1645-
} else {
1646-
Some((
1647-
match segment.res {
1648-
Res::PrimTy(ty) => {
1649-
format!("{} `{}`", segment.res.descr(), ty.name())
1650-
}
1651-
Res::Def(_, def_id)
1652-
if let Some(name) = self.tcx().opt_item_name(def_id) =>
1653-
{
1654-
format!("{} `{name}`", segment.res.descr())
1655-
}
1656-
Res::Err => "this type".to_string(),
1657-
_ => segment.res.descr().to_string(),
1658-
},
1659-
segment.ident.span,
1660-
))
1661-
}
1662-
})
1663-
.collect();
1664-
let this_type = match &types_and_spans[..] {
1665-
[.., _, (last, _)] => format!(
1666-
"{} and {last}",
1667-
types_and_spans[..types_and_spans.len() - 1]
1668-
.iter()
1669-
.map(|(x, _)| x.as_str())
1670-
.intersperse(", ")
1671-
.collect::<String>()
1672-
),
1673-
[(only, _)] => only.to_string(),
1674-
[] => "this type".to_string(),
1675-
};
1676-
1677-
let arg_spans: Vec<Span> = args.map(|arg| arg.span()).collect();
1678-
1679-
let mut kinds = Vec::with_capacity(4);
1680-
if lt {
1681-
kinds.push("lifetime");
1682-
}
1683-
if ty {
1684-
kinds.push("type");
1685-
}
1686-
if ct {
1687-
kinds.push("const");
1688-
}
1689-
if inf {
1690-
kinds.push("generic");
1691-
}
1692-
let (kind, s) = match kinds[..] {
1693-
[.., _, last] => (
1694-
format!(
1695-
"{} and {last}",
1696-
kinds[..kinds.len() - 1]
1697-
.iter()
1698-
.map(|&x| x)
1699-
.intersperse(", ")
1700-
.collect::<String>()
1701-
),
1702-
"s",
1703-
),
1704-
[only] => (only.to_string(), ""),
1705-
[] => unreachable!("expected at least one generic to prohibit"),
1706-
};
1707-
let last_span = *arg_spans.last().unwrap();
1708-
let span: MultiSpan = arg_spans.into();
1709-
let mut err = struct_span_code_err!(
1710-
self.tcx().dcx(),
1711-
span,
1712-
E0109,
1713-
"{kind} arguments are not allowed on {this_type}",
1714-
);
1715-
err.span_label(last_span, format!("{kind} argument{s} not allowed"));
1716-
for (what, span) in types_and_spans {
1717-
err.span_label(span, format!("not allowed on {what}"));
1718-
}
1719-
extend(&mut err);
1720-
self.set_tainted_by_errors(err.emit());
1631+
if let Some(_) = args_visitors.clone().next() {
1632+
let _ = self.report_prohibit_generics_error(segments.clone(), args_visitors, extend);
17211633
emitted = true;
17221634
}
17231635

compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs

+9-40
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::bounds::Bounds;
2-
use crate::errors::TraitObjectDeclaredWithNoTraits;
32
use crate::hir_ty_lowering::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds};
43
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
54
use rustc_errors::{codes::*, struct_span_code_err};
@@ -86,47 +85,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
8685
let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) =
8786
expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id()));
8887
if regular_traits.len() > 1 {
89-
let first_trait = &regular_traits[0];
90-
let additional_trait = &regular_traits[1];
91-
let mut err = struct_span_code_err!(
92-
tcx.dcx(),
93-
additional_trait.bottom().1,
94-
E0225,
95-
"only auto traits can be used as additional traits in a trait object"
88+
let _ = self.report_trait_object_addition_traits_error(
89+
span,
90+
&trait_bounds,
91+
&regular_traits,
9692
);
97-
additional_trait.label_with_exp_info(
98-
&mut err,
99-
"additional non-auto trait",
100-
"additional use",
93+
} else if regular_traits.is_empty() && auto_traits.is_empty() {
94+
let reported = self.report_trait_object_addition_traits_error(
95+
span,
96+
&trait_bounds,
97+
&regular_traits,
10198
);
102-
first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
103-
err.help(format!(
104-
"consider creating a new trait with all of these as supertraits and using that \
105-
trait here instead: `trait NewTrait: {} {{}}`",
106-
regular_traits
107-
.iter()
108-
// FIXME: This should `print_sugared`, but also needs to integrate projection bounds...
109-
.map(|t| t.trait_ref().print_only_trait_path().to_string())
110-
.collect::<Vec<_>>()
111-
.join(" + "),
112-
));
113-
err.note(
114-
"auto-traits like `Send` and `Sync` are traits that have special properties; \
115-
for more information on them, visit \
116-
<https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
117-
);
118-
self.set_tainted_by_errors(err.emit());
119-
}
120-
121-
if regular_traits.is_empty() && auto_traits.is_empty() {
122-
let trait_alias_span = trait_bounds
123-
.iter()
124-
.map(|&(trait_ref, _)| trait_ref.def_id())
125-
.find(|&trait_ref| tcx.is_trait_alias(trait_ref))
126-
.map(|trait_ref| tcx.def_span(trait_ref));
127-
let reported =
128-
tcx.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
129-
self.set_tainted_by_errors(reported);
13099
return Ty::new_error(tcx, reported);
131100
}
132101

compiler/rustc_trait_selection/src/traits/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ pub use self::util::{
6565
check_args_compatible, supertrait_def_ids, supertraits, transitive_bounds,
6666
transitive_bounds_that_define_assoc_item, SupertraitDefIds,
6767
};
68-
pub use self::util::{expand_trait_aliases, TraitAliasExpander};
68+
pub use self::util::{expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfo};
6969
pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
7070
pub use self::util::{with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
7171

0 commit comments

Comments
 (0)