Skip to content

Commit f023b92

Browse files
committed
Rework prohibit_generics
1 parent 395a09c commit f023b92

File tree

1 file changed

+75
-65
lines changed
  • compiler/rustc_typeck/src/astconv

1 file changed

+75
-65
lines changed

compiler/rustc_typeck/src/astconv/mod.rs

Lines changed: 75 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::require_c_abi_if_c_variadic;
1616
use rustc_ast::TraitObjectSyntax;
1717
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1818
use rustc_errors::{
19-
struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError,
19+
struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, MultiSpan,
2020
};
2121
use rustc_hir as hir;
2222
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
@@ -653,7 +653,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
653653
span, item_def_id, item_segment
654654
);
655655
if tcx.generics_of(item_def_id).params.is_empty() {
656-
self.prohibit_generics(slice::from_ref(item_segment));
656+
self.prohibit_generics(slice::from_ref(item_segment).iter());
657657

658658
parent_substs
659659
} else {
@@ -681,7 +681,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
681681
trait_ref: &hir::TraitRef<'_>,
682682
self_ty: Ty<'tcx>,
683683
) -> ty::TraitRef<'tcx> {
684-
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
684+
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter());
685685

686686
self.ast_path_to_mono_trait_ref(
687687
trait_ref.path.span,
@@ -784,7 +784,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
784784
let args = trait_segment.args();
785785
let infer_args = trait_segment.infer_args;
786786

787-
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
787+
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter());
788788
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false);
789789

790790
self.instantiate_poly_trait_ref_inner(
@@ -1796,7 +1796,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
17961796
if let Some(variant_def) = variant_def {
17971797
if permit_variants {
17981798
tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span, None);
1799-
self.prohibit_generics(slice::from_ref(assoc_segment));
1799+
self.prohibit_generics(slice::from_ref(assoc_segment).iter());
18001800
return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
18011801
} else {
18021802
variant_resolution = Some(variant_def.def_id);
@@ -2017,69 +2017,79 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
20172017
self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs))
20182018
}
20192019

2020-
pub fn prohibit_generics<'a, T: IntoIterator<Item = &'a hir::PathSegment<'a>>>(
2020+
pub fn prohibit_generics<'a, T: Iterator<Item = &'a hir::PathSegment<'a>> + Clone>(
20212021
&self,
20222022
segments: T,
20232023
) -> bool {
2024-
let mut has_err = false;
2025-
for segment in segments {
2026-
let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false);
2027-
for arg in segment.args().args {
2028-
let (span, kind) = match arg {
2029-
hir::GenericArg::Lifetime(lt) => {
2030-
if err_for_lt {
2031-
continue;
2032-
}
2033-
err_for_lt = true;
2034-
has_err = true;
2035-
(lt.span, "lifetime")
2036-
}
2037-
hir::GenericArg::Type(ty) => {
2038-
if err_for_ty {
2039-
continue;
2040-
}
2041-
err_for_ty = true;
2042-
has_err = true;
2043-
(ty.span, "type")
2044-
}
2045-
hir::GenericArg::Const(ct) => {
2046-
if err_for_ct {
2047-
continue;
2048-
}
2049-
err_for_ct = true;
2050-
has_err = true;
2051-
(ct.span, "const")
2052-
}
2053-
hir::GenericArg::Infer(inf) => {
2054-
if err_for_ty {
2055-
continue;
2056-
}
2057-
has_err = true;
2058-
err_for_ty = true;
2059-
(inf.span, "generic")
2060-
}
2061-
};
2062-
let mut err = struct_span_err!(
2063-
self.tcx().sess,
2064-
span,
2065-
E0109,
2066-
"{} arguments are not allowed for this type",
2067-
kind,
2068-
);
2069-
err.span_label(span, format!("{} argument not allowed", kind));
2070-
err.emit();
2071-
if err_for_lt && err_for_ty && err_for_ct {
2072-
break;
2073-
}
2024+
let args = segments.clone().flat_map(|segment| segment.args().args);
2025+
2026+
let (lt, ty, ct, inf) =
2027+
args.clone().fold((false, false, false, false), |(lt, ty, ct, inf), arg| match arg {
2028+
hir::GenericArg::Lifetime(_) => (true, ty, ct, inf),
2029+
hir::GenericArg::Type(_) => (lt, true, ct, inf),
2030+
hir::GenericArg::Const(_) => (lt, ty, true, inf),
2031+
hir::GenericArg::Infer(_) => (lt, ty, ct, true),
2032+
});
2033+
let mut emitted = false;
2034+
if lt || ty || ct || inf {
2035+
let arg_spans: Vec<Span> = args
2036+
.map(|arg| match arg {
2037+
hir::GenericArg::Lifetime(lt) => lt.span,
2038+
hir::GenericArg::Type(ty) => ty.span,
2039+
hir::GenericArg::Const(ct) => ct.span,
2040+
hir::GenericArg::Infer(inf) => inf.span,
2041+
})
2042+
.collect();
2043+
2044+
let mut types = Vec::with_capacity(4);
2045+
if lt {
2046+
types.push("lifetime");
2047+
}
2048+
if ty {
2049+
types.push("type");
2050+
}
2051+
if ct {
2052+
types.push("const");
20742053
}
2054+
if inf {
2055+
types.push("generic");
2056+
}
2057+
let (kind, s) = match types[..] {
2058+
[.., _, last] => (
2059+
format!(
2060+
"{} and `{last}`",
2061+
types[..types.len() - 1]
2062+
.iter()
2063+
.map(|&x| x)
2064+
.intersperse(", ")
2065+
.collect::<String>()
2066+
),
2067+
"s",
2068+
),
2069+
[only] => (format!("{only}"), ""),
2070+
[] => unreachable!(),
2071+
};
2072+
let last_span = *arg_spans.last().unwrap();
2073+
let span: MultiSpan = arg_spans.into();
2074+
let mut err = struct_span_err!(
2075+
self.tcx().sess,
2076+
span,
2077+
E0109,
2078+
"{kind} arguments are not allowed for this type",
2079+
);
2080+
err.span_label(last_span, format!("{kind} argument{s} not allowed"));
2081+
err.emit();
2082+
emitted = true;
2083+
}
20752084

2085+
for segment in segments {
20762086
// Only emit the first error to avoid overloading the user with error messages.
20772087
if let [binding, ..] = segment.args().bindings {
2078-
has_err = true;
20792088
Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
2089+
return true;
20802090
}
20812091
}
2082-
has_err
2092+
emitted
20832093
}
20842094

20852095
// FIXME(eddyb, varkor) handle type paths here too, not just value ones.
@@ -2229,7 +2239,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22292239
// Check for desugared `impl Trait`.
22302240
assert!(ty::is_impl_trait_defn(tcx, did).is_none());
22312241
let item_segment = path.segments.split_last().unwrap();
2232-
self.prohibit_generics(item_segment.1);
2242+
self.prohibit_generics(item_segment.1.iter());
22332243
let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
22342244
self.normalize_ty(span, tcx.mk_opaque(did, substs))
22352245
}
@@ -2242,7 +2252,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22422252
did,
22432253
) => {
22442254
assert_eq!(opt_self_ty, None);
2245-
self.prohibit_generics(path.segments.split_last().unwrap().1);
2255+
self.prohibit_generics(path.segments.split_last().unwrap().1.iter());
22462256
self.ast_path_to_ty(span, did, path.segments.last().unwrap())
22472257
}
22482258
Res::Def(kind @ DefKind::Variant, def_id) if permit_variants => {
@@ -2265,7 +2275,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22652275
}
22662276
Res::Def(DefKind::TyParam, def_id) => {
22672277
assert_eq!(opt_self_ty, None);
2268-
self.prohibit_generics(path.segments);
2278+
self.prohibit_generics(path.segments.iter());
22692279

22702280
let def_id = def_id.expect_local();
22712281
let item_def_id = tcx.hir().ty_param_owner(def_id);
@@ -2276,13 +2286,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
22762286
Res::SelfTy { trait_: Some(_), alias_to: None } => {
22772287
// `Self` in trait or type alias.
22782288
assert_eq!(opt_self_ty, None);
2279-
self.prohibit_generics(path.segments);
2289+
self.prohibit_generics(path.segments.iter());
22802290
tcx.types.self_param
22812291
}
22822292
Res::SelfTy { trait_: _, alias_to: Some((def_id, forbid_generic)) } => {
22832293
// `Self` in impl (we know the concrete type).
22842294
assert_eq!(opt_self_ty, None);
2285-
self.prohibit_generics(path.segments);
2295+
self.prohibit_generics(path.segments.iter());
22862296
// Try to evaluate any array length constants.
22872297
let ty = tcx.at(span).type_of(def_id);
22882298
// HACK(min_const_generics): Forbid generic `Self` types
@@ -2324,7 +2334,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23242334
}
23252335
Res::Def(DefKind::AssocTy, def_id) => {
23262336
debug_assert!(path.segments.len() >= 2);
2327-
self.prohibit_generics(&path.segments[..path.segments.len() - 2]);
2337+
self.prohibit_generics(path.segments[..path.segments.len() - 2].iter());
23282338
self.qpath_to_ty(
23292339
span,
23302340
opt_self_ty,
@@ -2335,7 +2345,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
23352345
}
23362346
Res::PrimTy(prim_ty) => {
23372347
assert_eq!(opt_self_ty, None);
2338-
self.prohibit_generics(path.segments);
2348+
self.prohibit_generics(path.segments.iter());
23392349
match prim_ty {
23402350
hir::PrimTy::Bool => tcx.types.bool,
23412351
hir::PrimTy::Char => tcx.types.char,

0 commit comments

Comments
 (0)