Rework prohibit_generics
This commit is contained in:
parent
395a09c3da
commit
f023b920b1
@ -16,7 +16,7 @@ use crate::require_c_abi_if_c_variadic;
|
|||||||
use rustc_ast::TraitObjectSyntax;
|
use rustc_ast::TraitObjectSyntax;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError,
|
struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, MultiSpan,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
|
use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
|
||||||
@ -653,7 +653,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
span, item_def_id, item_segment
|
span, item_def_id, item_segment
|
||||||
);
|
);
|
||||||
if tcx.generics_of(item_def_id).params.is_empty() {
|
if tcx.generics_of(item_def_id).params.is_empty() {
|
||||||
self.prohibit_generics(slice::from_ref(item_segment));
|
self.prohibit_generics(slice::from_ref(item_segment).iter());
|
||||||
|
|
||||||
parent_substs
|
parent_substs
|
||||||
} else {
|
} else {
|
||||||
@ -681,7 +681,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
trait_ref: &hir::TraitRef<'_>,
|
trait_ref: &hir::TraitRef<'_>,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
) -> ty::TraitRef<'tcx> {
|
) -> ty::TraitRef<'tcx> {
|
||||||
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
|
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter());
|
||||||
|
|
||||||
self.ast_path_to_mono_trait_ref(
|
self.ast_path_to_mono_trait_ref(
|
||||||
trait_ref.path.span,
|
trait_ref.path.span,
|
||||||
@ -784,7 +784,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
let args = trait_segment.args();
|
let args = trait_segment.args();
|
||||||
let infer_args = trait_segment.infer_args;
|
let infer_args = trait_segment.infer_args;
|
||||||
|
|
||||||
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
|
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter());
|
||||||
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false);
|
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false);
|
||||||
|
|
||||||
self.instantiate_poly_trait_ref_inner(
|
self.instantiate_poly_trait_ref_inner(
|
||||||
@ -1796,7 +1796,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
if let Some(variant_def) = variant_def {
|
if let Some(variant_def) = variant_def {
|
||||||
if permit_variants {
|
if permit_variants {
|
||||||
tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span, None);
|
tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span, None);
|
||||||
self.prohibit_generics(slice::from_ref(assoc_segment));
|
self.prohibit_generics(slice::from_ref(assoc_segment).iter());
|
||||||
return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
|
return Ok((qself_ty, DefKind::Variant, variant_def.def_id));
|
||||||
} else {
|
} else {
|
||||||
variant_resolution = Some(variant_def.def_id);
|
variant_resolution = Some(variant_def.def_id);
|
||||||
@ -2017,69 +2017,79 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs))
|
self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prohibit_generics<'a, T: IntoIterator<Item = &'a hir::PathSegment<'a>>>(
|
pub fn prohibit_generics<'a, T: Iterator<Item = &'a hir::PathSegment<'a>> + Clone>(
|
||||||
&self,
|
&self,
|
||||||
segments: T,
|
segments: T,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut has_err = false;
|
let args = segments.clone().flat_map(|segment| segment.args().args);
|
||||||
for segment in segments {
|
|
||||||
let (mut err_for_lt, mut err_for_ty, mut err_for_ct) = (false, false, false);
|
|
||||||
for arg in segment.args().args {
|
|
||||||
let (span, kind) = match arg {
|
|
||||||
hir::GenericArg::Lifetime(lt) => {
|
|
||||||
if err_for_lt {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
err_for_lt = true;
|
|
||||||
has_err = true;
|
|
||||||
(lt.span, "lifetime")
|
|
||||||
}
|
|
||||||
hir::GenericArg::Type(ty) => {
|
|
||||||
if err_for_ty {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
err_for_ty = true;
|
|
||||||
has_err = true;
|
|
||||||
(ty.span, "type")
|
|
||||||
}
|
|
||||||
hir::GenericArg::Const(ct) => {
|
|
||||||
if err_for_ct {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
err_for_ct = true;
|
|
||||||
has_err = true;
|
|
||||||
(ct.span, "const")
|
|
||||||
}
|
|
||||||
hir::GenericArg::Infer(inf) => {
|
|
||||||
if err_for_ty {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
has_err = true;
|
|
||||||
err_for_ty = true;
|
|
||||||
(inf.span, "generic")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let mut err = struct_span_err!(
|
|
||||||
self.tcx().sess,
|
|
||||||
span,
|
|
||||||
E0109,
|
|
||||||
"{} arguments are not allowed for this type",
|
|
||||||
kind,
|
|
||||||
);
|
|
||||||
err.span_label(span, format!("{} argument not allowed", kind));
|
|
||||||
err.emit();
|
|
||||||
if err_for_lt && err_for_ty && err_for_ct {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let (lt, ty, ct, inf) =
|
||||||
|
args.clone().fold((false, false, false, false), |(lt, ty, ct, inf), arg| match arg {
|
||||||
|
hir::GenericArg::Lifetime(_) => (true, ty, ct, inf),
|
||||||
|
hir::GenericArg::Type(_) => (lt, true, ct, inf),
|
||||||
|
hir::GenericArg::Const(_) => (lt, ty, true, inf),
|
||||||
|
hir::GenericArg::Infer(_) => (lt, ty, ct, true),
|
||||||
|
});
|
||||||
|
let mut emitted = false;
|
||||||
|
if lt || ty || ct || inf {
|
||||||
|
let arg_spans: Vec<Span> = args
|
||||||
|
.map(|arg| match arg {
|
||||||
|
hir::GenericArg::Lifetime(lt) => lt.span,
|
||||||
|
hir::GenericArg::Type(ty) => ty.span,
|
||||||
|
hir::GenericArg::Const(ct) => ct.span,
|
||||||
|
hir::GenericArg::Infer(inf) => inf.span,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut types = Vec::with_capacity(4);
|
||||||
|
if lt {
|
||||||
|
types.push("lifetime");
|
||||||
|
}
|
||||||
|
if ty {
|
||||||
|
types.push("type");
|
||||||
|
}
|
||||||
|
if ct {
|
||||||
|
types.push("const");
|
||||||
|
}
|
||||||
|
if inf {
|
||||||
|
types.push("generic");
|
||||||
|
}
|
||||||
|
let (kind, s) = match types[..] {
|
||||||
|
[.., _, last] => (
|
||||||
|
format!(
|
||||||
|
"{} and `{last}`",
|
||||||
|
types[..types.len() - 1]
|
||||||
|
.iter()
|
||||||
|
.map(|&x| x)
|
||||||
|
.intersperse(", ")
|
||||||
|
.collect::<String>()
|
||||||
|
),
|
||||||
|
"s",
|
||||||
|
),
|
||||||
|
[only] => (format!("{only}"), ""),
|
||||||
|
[] => unreachable!(),
|
||||||
|
};
|
||||||
|
let last_span = *arg_spans.last().unwrap();
|
||||||
|
let span: MultiSpan = arg_spans.into();
|
||||||
|
let mut err = struct_span_err!(
|
||||||
|
self.tcx().sess,
|
||||||
|
span,
|
||||||
|
E0109,
|
||||||
|
"{kind} arguments are not allowed for this type",
|
||||||
|
);
|
||||||
|
err.span_label(last_span, format!("{kind} argument{s} not allowed"));
|
||||||
|
err.emit();
|
||||||
|
emitted = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for segment in segments {
|
||||||
// Only emit the first error to avoid overloading the user with error messages.
|
// Only emit the first error to avoid overloading the user with error messages.
|
||||||
if let [binding, ..] = segment.args().bindings {
|
if let [binding, ..] = segment.args().bindings {
|
||||||
has_err = true;
|
|
||||||
Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
|
Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
has_err
|
emitted
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(eddyb, varkor) handle type paths here too, not just value ones.
|
// FIXME(eddyb, varkor) handle type paths here too, not just value ones.
|
||||||
@ -2229,7 +2239,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
// Check for desugared `impl Trait`.
|
// Check for desugared `impl Trait`.
|
||||||
assert!(ty::is_impl_trait_defn(tcx, did).is_none());
|
assert!(ty::is_impl_trait_defn(tcx, did).is_none());
|
||||||
let item_segment = path.segments.split_last().unwrap();
|
let item_segment = path.segments.split_last().unwrap();
|
||||||
self.prohibit_generics(item_segment.1);
|
self.prohibit_generics(item_segment.1.iter());
|
||||||
let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
|
let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
|
||||||
self.normalize_ty(span, tcx.mk_opaque(did, substs))
|
self.normalize_ty(span, tcx.mk_opaque(did, substs))
|
||||||
}
|
}
|
||||||
@ -2242,7 +2252,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
did,
|
did,
|
||||||
) => {
|
) => {
|
||||||
assert_eq!(opt_self_ty, None);
|
assert_eq!(opt_self_ty, None);
|
||||||
self.prohibit_generics(path.segments.split_last().unwrap().1);
|
self.prohibit_generics(path.segments.split_last().unwrap().1.iter());
|
||||||
self.ast_path_to_ty(span, did, path.segments.last().unwrap())
|
self.ast_path_to_ty(span, did, path.segments.last().unwrap())
|
||||||
}
|
}
|
||||||
Res::Def(kind @ DefKind::Variant, def_id) if permit_variants => {
|
Res::Def(kind @ DefKind::Variant, def_id) if permit_variants => {
|
||||||
@ -2265,7 +2275,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
}
|
}
|
||||||
Res::Def(DefKind::TyParam, def_id) => {
|
Res::Def(DefKind::TyParam, def_id) => {
|
||||||
assert_eq!(opt_self_ty, None);
|
assert_eq!(opt_self_ty, None);
|
||||||
self.prohibit_generics(path.segments);
|
self.prohibit_generics(path.segments.iter());
|
||||||
|
|
||||||
let def_id = def_id.expect_local();
|
let def_id = def_id.expect_local();
|
||||||
let item_def_id = tcx.hir().ty_param_owner(def_id);
|
let item_def_id = tcx.hir().ty_param_owner(def_id);
|
||||||
@ -2276,13 +2286,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
Res::SelfTy { trait_: Some(_), alias_to: None } => {
|
Res::SelfTy { trait_: Some(_), alias_to: None } => {
|
||||||
// `Self` in trait or type alias.
|
// `Self` in trait or type alias.
|
||||||
assert_eq!(opt_self_ty, None);
|
assert_eq!(opt_self_ty, None);
|
||||||
self.prohibit_generics(path.segments);
|
self.prohibit_generics(path.segments.iter());
|
||||||
tcx.types.self_param
|
tcx.types.self_param
|
||||||
}
|
}
|
||||||
Res::SelfTy { trait_: _, alias_to: Some((def_id, forbid_generic)) } => {
|
Res::SelfTy { trait_: _, alias_to: Some((def_id, forbid_generic)) } => {
|
||||||
// `Self` in impl (we know the concrete type).
|
// `Self` in impl (we know the concrete type).
|
||||||
assert_eq!(opt_self_ty, None);
|
assert_eq!(opt_self_ty, None);
|
||||||
self.prohibit_generics(path.segments);
|
self.prohibit_generics(path.segments.iter());
|
||||||
// Try to evaluate any array length constants.
|
// Try to evaluate any array length constants.
|
||||||
let ty = tcx.at(span).type_of(def_id);
|
let ty = tcx.at(span).type_of(def_id);
|
||||||
// HACK(min_const_generics): Forbid generic `Self` types
|
// HACK(min_const_generics): Forbid generic `Self` types
|
||||||
@ -2324,7 +2334,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
}
|
}
|
||||||
Res::Def(DefKind::AssocTy, def_id) => {
|
Res::Def(DefKind::AssocTy, def_id) => {
|
||||||
debug_assert!(path.segments.len() >= 2);
|
debug_assert!(path.segments.len() >= 2);
|
||||||
self.prohibit_generics(&path.segments[..path.segments.len() - 2]);
|
self.prohibit_generics(path.segments[..path.segments.len() - 2].iter());
|
||||||
self.qpath_to_ty(
|
self.qpath_to_ty(
|
||||||
span,
|
span,
|
||||||
opt_self_ty,
|
opt_self_ty,
|
||||||
@ -2335,7 +2345,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
|||||||
}
|
}
|
||||||
Res::PrimTy(prim_ty) => {
|
Res::PrimTy(prim_ty) => {
|
||||||
assert_eq!(opt_self_ty, None);
|
assert_eq!(opt_self_ty, None);
|
||||||
self.prohibit_generics(path.segments);
|
self.prohibit_generics(path.segments.iter());
|
||||||
match prim_ty {
|
match prim_ty {
|
||||||
hir::PrimTy::Bool => tcx.types.bool,
|
hir::PrimTy::Bool => tcx.types.bool,
|
||||||
hir::PrimTy::Char => tcx.types.char,
|
hir::PrimTy::Char => tcx.types.char,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user