Skip to content

Commit 2453034

Browse files
committed
Guard us against degenerate default traits
1 parent c4451a7 commit 2453034

File tree

1 file changed

+60
-46
lines changed
  • compiler/rustc_hir_analysis/src/hir_ty_lowering

1 file changed

+60
-46
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 60 additions & 46 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,66 @@ 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

776778
// 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+
};
795797

796-
(ty::PredicatePolarity::Positive, &mut Vec::new())
798+
let polarity = match polarity {
799+
hir::BoundPolarity::Positive | hir::BoundPolarity::Maybe(_) => {
800+
ty::PredicatePolarity::Positive
797801
}
802+
hir::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
798803
};
799804

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

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);
807+
let _ = self.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
808+
self.report_internal_fn_trait(span, trait_def_id, segment, false);
807809

808810
let (generic_args, arg_count) = self.lower_generic_args_of_path(
809811
trait_ref.path.span,
810812
trait_def_id,
811813
&[],
812-
trait_segment,
814+
segment,
813815
Some(self_ty),
814816
);
815817

818+
let constraints = segment.args().constraints;
819+
820+
if transient && (!generic_args.is_empty() || !constraints.is_empty()) {
821+
// Since the bound won't be present in the `middle::ty` IR for the reasons established
822+
// above, any arguments or constraints won't be checked for well-formedness later.
823+
//
824+
// To be clear, this is only an issue if the trait ref is valid according to this
825+
// function which can only happen if the corresponding default trait has generic
826+
// parameters or associated items which would be degenerate.
827+
//
828+
// This guards us against such situations. Example: `?Bound<'a, Vec<str>, { panic!() }>`
829+
// where `/* default */ trait Bound<'a: 'static, T, const N: usize> {}`.
830+
self.dcx()
831+
.span_delayed_bug(span, "transient bound should not have args or constraints");
832+
}
833+
816834
let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
817835
debug!(?bound_vars);
818836

@@ -924,7 +942,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
924942
== OverlappingAsssocItemConstraints::Forbidden)
925943
.then_some(FxIndexMap::default());
926944

927-
for constraint in trait_segment.args().constraints {
945+
for constraint in constraints {
928946
// Don't register any associated item constraints for negative bounds,
929947
// since we should have emitted an error for them earlier, and they
930948
// would not be well-formed!
@@ -1916,10 +1934,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
19161934
Res::Def(DefKind::OpaqueTy, did) => {
19171935
// Check for desugared `impl Trait`.
19181936
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);
1937+
let [leading_segments @ .., segment] = path.segments else { bug!() };
1938+
let _ = self.prohibit_generic_args(
1939+
leading_segments.iter(),
1940+
GenericsArgsErrExtend::OpaqueTy,
1941+
);
1942+
let args = self.lower_generic_args_of_path_segment(span, did, segment);
19231943
Ty::new_opaque(tcx, did, args)
19241944
}
19251945
Res::Def(
@@ -1931,11 +1951,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
19311951
did,
19321952
) => {
19331953
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())
1954+
let [leading_segments @ .., segment] = path.segments else { bug!() };
1955+
let _ = self
1956+
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
1957+
self.lower_path_segment(span, did, segment)
19391958
}
19401959
Res::Def(kind @ DefKind::Variant, def_id)
19411960
if let PermitVariants::Yes = permit_variants =>
@@ -1955,8 +1974,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
19551974
GenericsArgsErrExtend::DefVariant(&path.segments),
19561975
);
19571976

1958-
let GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
1959-
self.lower_path_segment(span, *def_id, &path.segments[*index])
1977+
let &GenericPathSegment(def_id, index) = generic_segments.last().unwrap();
1978+
self.lower_path_segment(span, def_id, &path.segments[index])
19601979
}
19611980
Res::Def(DefKind::TyParam, def_id) => {
19621981
assert_eq!(opt_self_ty, None);
@@ -2242,15 +2261,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22422261
}
22432262
Res::Def(DefKind::Const | DefKind::Ctor(_, CtorKind::Const), did) => {
22442263
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-
);
2264+
let [leading_segments @ .., segment] = path.segments else { bug!() };
2265+
let _ = self
2266+
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
2267+
let args = self.lower_generic_args_of_path_segment(span, did, segment);
22542268
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
22552269
}
22562270
Res::Def(DefKind::AssocConst, did) => {

0 commit comments

Comments
 (0)