Skip to content

Commit 79993ba

Browse files
committed
Guard us against degenerate default traits
1 parent 3a9b2c3 commit 79993ba

File tree

1 file changed

+62
-47
lines changed
  • compiler/rustc_hir_analysis/src/hir_ty_lowering

1 file changed

+62
-47
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 62 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -717,16 +717,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
717717
trait_ref: &hir::TraitRef<'tcx>,
718718
self_ty: Ty<'tcx>,
719719
) -> ty::TraitRef<'tcx> {
720-
let _ = self.prohibit_generic_args(
721-
trait_ref.path.segments.split_last().unwrap().1.iter(),
722-
GenericsArgsErrExtend::None,
723-
);
720+
let [leading_segments @ .., segment] = trait_ref.path.segments else { bug!() };
721+
722+
let _ = self.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
724723

725724
self.lower_mono_trait_ref(
726725
trait_ref.path.span,
727726
trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()),
728727
self_ty,
729-
trait_ref.path.segments.last().unwrap(),
728+
segment,
730729
true,
731730
)
732731
}
@@ -757,7 +756,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
757756
#[instrument(level = "debug", skip(self, bounds))]
758757
pub(crate) fn lower_poly_trait_ref(
759758
&self,
760-
poly_trait_ref: &hir::PolyTraitRef<'tcx>,
759+
&hir::PolyTraitRef {
760+
bound_generic_params,
761+
modifiers: hir::TraitBoundModifiers { constness, polarity },
762+
trait_ref,
763+
span,
764+
}: &hir::PolyTraitRef<'tcx>,
761765
self_ty: Ty<'tcx>,
762766
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
763767
predicate_filter: PredicateFilter,
@@ -767,52 +771,67 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
767771

768772
// We use the *resolved* bound vars later instead of the HIR ones since the former
769773
// also include the bound vars of the overarching predicate if applicable.
770-
let hir::PolyTraitRef { bound_generic_params: _, modifiers, trait_ref, span } =
771-
*poly_trait_ref;
772-
let hir::TraitBoundModifiers { constness, polarity } = modifiers;
774+
let _ = bound_generic_params;
773775

774776
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
775777

776-
// Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the `middle::ty` IR
778+
// Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the middle::ty IR
777779
// as they denote the *absence* of a default bound. However, we can't bail out early here since
778780
// we still need to perform several validation steps (see below). Instead, simply "pour" all
779781
// resulting bounds "down the drain", i.e., into a new `Vec` that just gets dropped at the end.
780-
let (polarity, bounds) = match polarity {
781-
rustc_ast::BoundPolarity::Positive
782-
if tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized) =>
783-
{
782+
let transient = match polarity {
783+
hir::BoundPolarity::Positive => {
784784
// To elaborate on the comment directly above, regarding `PointeeSized` specifically,
785785
// we don't "reify" such bounds to avoid trait system limitations -- namely,
786786
// non-global where-clauses being preferred over item bounds (where `PointeeSized`
787787
// bounds would be proven) -- which can result in errors when a `PointeeSized`
788788
// supertrait / bound / predicate is added to some items.
789-
(ty::PredicatePolarity::Positive, &mut Vec::new())
789+
tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized)
790790
}
791-
rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds),
792-
rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds),
793-
rustc_ast::BoundPolarity::Maybe(_) => {
791+
hir::BoundPolarity::Negative(_) => false,
792+
hir::BoundPolarity::Maybe(_) => {
794793
self.require_bound_to_relax_default_trait(trait_ref, span);
794+
true
795+
}
796+
};
797+
let bounds = if transient { &mut Vec::new() } else { bounds };
795798

796-
(ty::PredicatePolarity::Positive, &mut Vec::new())
799+
let polarity = match polarity {
800+
hir::BoundPolarity::Positive | hir::BoundPolarity::Maybe(_) => {
801+
ty::PredicatePolarity::Positive
797802
}
803+
hir::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
798804
};
799805

800-
let trait_segment = trait_ref.path.segments.last().unwrap();
806+
let [leading_segments @ .., segment] = trait_ref.path.segments else { bug!() };
801807

802-
let _ = self.prohibit_generic_args(
803-
trait_ref.path.segments.split_last().unwrap().1.iter(),
804-
GenericsArgsErrExtend::None,
805-
);
806-
self.report_internal_fn_trait(span, trait_def_id, trait_segment, false);
808+
let _ = self.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
809+
self.report_internal_fn_trait(span, trait_def_id, segment, false);
807810

808811
let (generic_args, arg_count) = self.lower_generic_args_of_path(
809812
trait_ref.path.span,
810813
trait_def_id,
811814
&[],
812-
trait_segment,
815+
segment,
813816
Some(self_ty),
814817
);
815818

819+
let constraints = segment.args().constraints;
820+
821+
if transient && (!generic_args[1..].is_empty() || !constraints.is_empty()) {
822+
// Since the bound won't be present in the middle::ty IR as established above, any
823+
// arguments or constraints won't be checked for well-formedness in later passes.
824+
//
825+
// This is only an issue if the trait ref is otherwise valid which can only happen if
826+
// the corresponding default trait has generic parameters or associated items. Such a
827+
// trait would be degenerate. We delay a bug to detect and guard us against these.
828+
//
829+
// E.g: Given `/*default*/ trait Bound<'a: 'static, T, const N: usize> {}`,
830+
// `?Bound<Vec<str>, { panic!() }>` won't be wfchecked.
831+
self.dcx()
832+
.span_delayed_bug(span, "transient bound should not have args or constraints");
833+
}
834+
816835
let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
817836
debug!(?bound_vars);
818837

@@ -924,7 +943,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
924943
== OverlappingAsssocItemConstraints::Forbidden)
925944
.then_some(FxIndexMap::default());
926945

927-
for constraint in trait_segment.args().constraints {
946+
for constraint in constraints {
928947
// Don't register any associated item constraints for negative bounds,
929948
// since we should have emitted an error for them earlier, and they
930949
// would not be well-formed!
@@ -1916,10 +1935,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
19161935
Res::Def(DefKind::OpaqueTy, did) => {
19171936
// Check for desugared `impl Trait`.
19181937
assert_matches!(tcx.opaque_ty_origin(did), hir::OpaqueTyOrigin::TyAlias { .. });
1919-
let item_segment = path.segments.split_last().unwrap();
1920-
let _ = self
1921-
.prohibit_generic_args(item_segment.1.iter(), GenericsArgsErrExtend::OpaqueTy);
1922-
let args = self.lower_generic_args_of_path_segment(span, did, item_segment.0);
1938+
let [leading_segments @ .., segment] = path.segments else { bug!() };
1939+
let _ = self.prohibit_generic_args(
1940+
leading_segments.iter(),
1941+
GenericsArgsErrExtend::OpaqueTy,
1942+
);
1943+
let args = self.lower_generic_args_of_path_segment(span, did, segment);
19231944
Ty::new_opaque(tcx, did, args)
19241945
}
19251946
Res::Def(
@@ -1931,11 +1952,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
19311952
did,
19321953
) => {
19331954
assert_eq!(opt_self_ty, None);
1934-
let _ = self.prohibit_generic_args(
1935-
path.segments.split_last().unwrap().1.iter(),
1936-
GenericsArgsErrExtend::None,
1937-
);
1938-
self.lower_path_segment(span, did, path.segments.last().unwrap())
1955+
let [leading_segments @ .., segment] = path.segments else { bug!() };
1956+
let _ = self
1957+
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
1958+
self.lower_path_segment(span, did, segment)
19391959
}
19401960
Res::Def(kind @ DefKind::Variant, def_id)
19411961
if let PermitVariants::Yes = permit_variants =>
@@ -1955,8 +1975,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
19551975
GenericsArgsErrExtend::DefVariant(&path.segments),
19561976
);
19571977

1958-
let GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
1959-
self.lower_path_segment(span, *def_id, &path.segments[*index])
1978+
let &GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
1979+
self.lower_path_segment(span, def_id, &path.segments[index])
19601980
}
19611981
Res::Def(DefKind::TyParam, def_id) => {
19621982
assert_eq!(opt_self_ty, None);
@@ -2242,15 +2262,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22422262
}
22432263
Res::Def(DefKind::Const | DefKind::Ctor(_, CtorKind::Const), did) => {
22442264
assert_eq!(opt_self_ty, None);
2245-
let _ = self.prohibit_generic_args(
2246-
path.segments.split_last().unwrap().1.iter(),
2247-
GenericsArgsErrExtend::None,
2248-
);
2249-
let args = self.lower_generic_args_of_path_segment(
2250-
span,
2251-
did,
2252-
path.segments.last().unwrap(),
2253-
);
2265+
let [leading_segments @ .., segment] = path.segments else { bug!() };
2266+
let _ = self
2267+
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
2268+
let args = self.lower_generic_args_of_path_segment(span, did, segment);
22542269
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
22552270
}
22562271
Res::Def(DefKind::AssocConst, did) => {

0 commit comments

Comments
 (0)