Guard us against degenerate default traits
This commit is contained in:
@@ -717,16 +717,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
trait_ref: &hir::TraitRef<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
) -> ty::TraitRef<'tcx> {
|
||||
let _ = self.prohibit_generic_args(
|
||||
trait_ref.path.segments.split_last().unwrap().1.iter(),
|
||||
GenericsArgsErrExtend::None,
|
||||
);
|
||||
let [leading_segments @ .., segment] = trait_ref.path.segments else { bug!() };
|
||||
|
||||
let _ = self.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
|
||||
|
||||
self.lower_mono_trait_ref(
|
||||
trait_ref.path.span,
|
||||
trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
|
||||
self_ty,
|
||||
trait_ref.path.segments.last().unwrap(),
|
||||
segment,
|
||||
true,
|
||||
)
|
||||
}
|
||||
@@ -757,7 +756,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
#[instrument(level = "debug", skip(self, bounds))]
|
||||
pub(crate) fn lower_poly_trait_ref(
|
||||
&self,
|
||||
poly_trait_ref: &hir::PolyTraitRef<'tcx>,
|
||||
&hir::PolyTraitRef {
|
||||
bound_generic_params,
|
||||
modifiers: hir::TraitBoundModifiers { constness, polarity },
|
||||
trait_ref,
|
||||
span,
|
||||
}: &hir::PolyTraitRef<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||
predicate_filter: PredicateFilter,
|
||||
@@ -767,52 +771,67 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
|
||||
// We use the *resolved* bound vars later instead of the HIR ones since the former
|
||||
// also include the bound vars of the overarching predicate if applicable.
|
||||
let hir::PolyTraitRef { bound_generic_params: _, modifiers, trait_ref, span } =
|
||||
*poly_trait_ref;
|
||||
let hir::TraitBoundModifiers { constness, polarity } = modifiers;
|
||||
let _ = bound_generic_params;
|
||||
|
||||
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
|
||||
|
||||
// Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the `middle::ty` IR
|
||||
// Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the middle::ty IR
|
||||
// as they denote the *absence* of a default bound. However, we can't bail out early here since
|
||||
// we still need to perform several validation steps (see below). Instead, simply "pour" all
|
||||
// resulting bounds "down the drain", i.e., into a new `Vec` that just gets dropped at the end.
|
||||
let (polarity, bounds) = match polarity {
|
||||
rustc_ast::BoundPolarity::Positive
|
||||
if tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized) =>
|
||||
{
|
||||
let transient = match polarity {
|
||||
hir::BoundPolarity::Positive => {
|
||||
// To elaborate on the comment directly above, regarding `PointeeSized` specifically,
|
||||
// we don't "reify" such bounds to avoid trait system limitations -- namely,
|
||||
// non-global where-clauses being preferred over item bounds (where `PointeeSized`
|
||||
// bounds would be proven) -- which can result in errors when a `PointeeSized`
|
||||
// supertrait / bound / predicate is added to some items.
|
||||
(ty::PredicatePolarity::Positive, &mut Vec::new())
|
||||
tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized)
|
||||
}
|
||||
rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds),
|
||||
rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds),
|
||||
rustc_ast::BoundPolarity::Maybe(_) => {
|
||||
hir::BoundPolarity::Negative(_) => false,
|
||||
hir::BoundPolarity::Maybe(_) => {
|
||||
self.require_bound_to_relax_default_trait(trait_ref, span);
|
||||
|
||||
(ty::PredicatePolarity::Positive, &mut Vec::new())
|
||||
true
|
||||
}
|
||||
};
|
||||
let bounds = if transient { &mut Vec::new() } else { bounds };
|
||||
|
||||
let trait_segment = trait_ref.path.segments.last().unwrap();
|
||||
let polarity = match polarity {
|
||||
hir::BoundPolarity::Positive | hir::BoundPolarity::Maybe(_) => {
|
||||
ty::PredicatePolarity::Positive
|
||||
}
|
||||
hir::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
|
||||
};
|
||||
|
||||
let _ = self.prohibit_generic_args(
|
||||
trait_ref.path.segments.split_last().unwrap().1.iter(),
|
||||
GenericsArgsErrExtend::None,
|
||||
);
|
||||
self.report_internal_fn_trait(span, trait_def_id, trait_segment, false);
|
||||
let [leading_segments @ .., segment] = trait_ref.path.segments else { bug!() };
|
||||
|
||||
let _ = self.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
|
||||
self.report_internal_fn_trait(span, trait_def_id, segment, false);
|
||||
|
||||
let (generic_args, arg_count) = self.lower_generic_args_of_path(
|
||||
trait_ref.path.span,
|
||||
trait_def_id,
|
||||
&[],
|
||||
trait_segment,
|
||||
segment,
|
||||
Some(self_ty),
|
||||
);
|
||||
|
||||
let constraints = segment.args().constraints;
|
||||
|
||||
if transient && (!generic_args[1..].is_empty() || !constraints.is_empty()) {
|
||||
// Since the bound won't be present in the middle::ty IR as established above, any
|
||||
// arguments or constraints won't be checked for well-formedness in later passes.
|
||||
//
|
||||
// This is only an issue if the trait ref is otherwise valid which can only happen if
|
||||
// the corresponding default trait has generic parameters or associated items. Such a
|
||||
// trait would be degenerate. We delay a bug to detect and guard us against these.
|
||||
//
|
||||
// E.g: Given `/*default*/ trait Bound<'a: 'static, T, const N: usize> {}`,
|
||||
// `?Bound<Vec<str>, { panic!() }>` won't be wfchecked.
|
||||
self.dcx()
|
||||
.span_delayed_bug(span, "transient bound should not have args or constraints");
|
||||
}
|
||||
|
||||
let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
|
||||
debug!(?bound_vars);
|
||||
|
||||
@@ -924,7 +943,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
== OverlappingAsssocItemConstraints::Forbidden)
|
||||
.then_some(FxIndexMap::default());
|
||||
|
||||
for constraint in trait_segment.args().constraints {
|
||||
for constraint in constraints {
|
||||
// Don't register any associated item constraints for negative bounds,
|
||||
// since we should have emitted an error for them earlier, and they
|
||||
// would not be well-formed!
|
||||
@@ -1916,10 +1935,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
Res::Def(DefKind::OpaqueTy, did) => {
|
||||
// Check for desugared `impl Trait`.
|
||||
assert_matches!(tcx.opaque_ty_origin(did), hir::OpaqueTyOrigin::TyAlias { .. });
|
||||
let item_segment = path.segments.split_last().unwrap();
|
||||
let _ = self
|
||||
.prohibit_generic_args(item_segment.1.iter(), GenericsArgsErrExtend::OpaqueTy);
|
||||
let args = self.lower_generic_args_of_path_segment(span, did, item_segment.0);
|
||||
let [leading_segments @ .., segment] = path.segments else { bug!() };
|
||||
let _ = self.prohibit_generic_args(
|
||||
leading_segments.iter(),
|
||||
GenericsArgsErrExtend::OpaqueTy,
|
||||
);
|
||||
let args = self.lower_generic_args_of_path_segment(span, did, segment);
|
||||
Ty::new_opaque(tcx, did, args)
|
||||
}
|
||||
Res::Def(
|
||||
@@ -1931,11 +1952,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
did,
|
||||
) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
let _ = self.prohibit_generic_args(
|
||||
path.segments.split_last().unwrap().1.iter(),
|
||||
GenericsArgsErrExtend::None,
|
||||
);
|
||||
self.lower_path_segment(span, did, path.segments.last().unwrap())
|
||||
let [leading_segments @ .., segment] = path.segments else { bug!() };
|
||||
let _ = self
|
||||
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
|
||||
self.lower_path_segment(span, did, segment)
|
||||
}
|
||||
Res::Def(kind @ DefKind::Variant, def_id)
|
||||
if let PermitVariants::Yes = permit_variants =>
|
||||
@@ -1955,8 +1975,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
GenericsArgsErrExtend::DefVariant(&path.segments),
|
||||
);
|
||||
|
||||
let GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
|
||||
self.lower_path_segment(span, *def_id, &path.segments[*index])
|
||||
let &GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
|
||||
self.lower_path_segment(span, def_id, &path.segments[index])
|
||||
}
|
||||
Res::Def(DefKind::TyParam, def_id) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
@@ -2242,15 +2262,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
}
|
||||
Res::Def(DefKind::Const | DefKind::Ctor(_, CtorKind::Const), did) => {
|
||||
assert_eq!(opt_self_ty, None);
|
||||
let _ = self.prohibit_generic_args(
|
||||
path.segments.split_last().unwrap().1.iter(),
|
||||
GenericsArgsErrExtend::None,
|
||||
);
|
||||
let args = self.lower_generic_args_of_path_segment(
|
||||
span,
|
||||
did,
|
||||
path.segments.last().unwrap(),
|
||||
);
|
||||
let [leading_segments @ .., segment] = path.segments else { bug!() };
|
||||
let _ = self
|
||||
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
|
||||
let args = self.lower_generic_args_of_path_segment(span, did, segment);
|
||||
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
|
||||
}
|
||||
Res::Def(DefKind::AssocConst, did) => {
|
||||
|
||||
Reference in New Issue
Block a user