Skip to content

Commit 90f3036

Browse files
committed
Simplify elision of default generic arguments
1 parent 6d10170 commit 90f3036

File tree

1 file changed

+45
-48
lines changed

1 file changed

+45
-48
lines changed

src/librustdoc/clean/utils.rs

Lines changed: 45 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ use rustc_hir::def::{DefKind, Res};
1616
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
1717
use rustc_metadata::rendered_const;
1818
use rustc_middle::mir;
19+
use rustc_middle::ty::TypeVisitableExt;
1920
use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt};
20-
use rustc_middle::ty::{TypeVisitable, TypeVisitableExt};
2121
use rustc_span::symbol::{kw, sym, Symbol};
22+
use std::assert_matches::debug_assert_matches;
2223
use std::fmt::Write as _;
2324
use std::mem;
2425
use std::sync::LazyLock as Lazy;
@@ -108,57 +109,49 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
108109
std::borrow::Cow::from(args)
109110
};
110111

111-
let clean_middle_arg = |(index, arg): (usize, &ty::GenericArg<'tcx>)| match arg.unpack() {
112-
GenericArgKind::Lifetime(lt) => {
113-
Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
112+
let clean_middle_arg = |(index, arg): (usize, &ty::GenericArg<'tcx>)| {
113+
// Elide the self type.
114+
if has_self && index == 0 {
115+
return None;
114116
}
115-
GenericArgKind::Type(_) if has_self && index == 0 => None,
116-
GenericArgKind::Type(ty) => {
117-
let ty = ty::Binder::bind_with_vars(ty, bound_vars);
118-
119-
if !elision_has_failed_once_before
120-
&& let Some(default) = generics.params[index].default_value(cx.tcx)
121-
{
122-
let default = default.instantiate(cx.tcx, args.as_ref()).expect_ty();
123-
if can_elide_generic_arg(ty, ty.rebind(default)) {
124-
return None;
125-
}
126117

127-
elision_has_failed_once_before = true;
118+
// Elide internal host effect args.
119+
if let ty::GenericParamDefKind::Const { is_host_effect: true, .. } =
120+
generics.params[index].kind
121+
{
122+
return None;
123+
}
124+
125+
let arg = ty::Binder::bind_with_vars(*arg, bound_vars);
126+
127+
// Elide arguments that coincide with their default.
128+
if !elision_has_failed_once_before
129+
&& let Some(default) = generics.params[index].default_value(cx.tcx)
130+
{
131+
let default = default.instantiate(cx.tcx, args.as_ref());
132+
if can_elide_generic_arg(arg, arg.rebind(default)) {
133+
return None;
128134
}
135+
elision_has_failed_once_before = true;
136+
}
129137

130-
Some(GenericArg::Type(clean_middle_ty(
131-
ty,
138+
match arg.skip_binder().unpack() {
139+
GenericArgKind::Lifetime(lt) => {
140+
Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided())))
141+
}
142+
GenericArgKind::Type(ty) => Some(GenericArg::Type(clean_middle_ty(
143+
arg.rebind(ty),
132144
cx,
133145
None,
134146
Some(crate::clean::ContainerTy::Regular {
135147
ty: owner,
136-
args: ty.rebind(args.as_ref()),
148+
args: arg.rebind(args.as_ref()),
137149
arg: index,
138150
}),
139-
)))
140-
}
141-
GenericArgKind::Const(ct) => {
142-
if let ty::GenericParamDefKind::Const { is_host_effect: true, .. } =
143-
generics.params[index].kind
144-
{
145-
return None;
151+
))),
152+
GenericArgKind::Const(ct) => {
153+
Some(GenericArg::Const(Box::new(clean_middle_const(arg.rebind(ct), cx))))
146154
}
147-
148-
let ct = ty::Binder::bind_with_vars(ct, bound_vars);
149-
150-
if !elision_has_failed_once_before
151-
&& let Some(default) = generics.params[index].default_value(cx.tcx)
152-
{
153-
let default = default.instantiate(cx.tcx, args.as_ref()).expect_const();
154-
if can_elide_generic_arg(ct, ct.rebind(default)) {
155-
return None;
156-
}
157-
158-
elision_has_failed_once_before = true;
159-
}
160-
161-
Some(GenericArg::Const(Box::new(clean_middle_const(ct, cx))))
162155
}
163156
};
164157

@@ -172,13 +165,17 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
172165
/// This uses a very conservative approach for performance and correctness reasons, meaning for
173166
/// several classes of terms it claims that they cannot be elided even if they theoretically could.
174167
/// This is absolutely fine since it mostly concerns edge cases.
175-
fn can_elide_generic_arg<'tcx, Term>(
176-
actual: ty::Binder<'tcx, Term>,
177-
default: ty::Binder<'tcx, Term>,
178-
) -> bool
179-
where
180-
Term: Eq + TypeVisitable<TyCtxt<'tcx>>,
181-
{
168+
fn can_elide_generic_arg<'tcx>(
169+
actual: ty::Binder<'tcx, ty::GenericArg<'tcx>>,
170+
default: ty::Binder<'tcx, ty::GenericArg<'tcx>>,
171+
) -> bool {
172+
debug_assert_matches!(
173+
(actual.skip_binder().unpack(), default.skip_binder().unpack()),
174+
(ty::GenericArgKind::Lifetime(_), ty::GenericArgKind::Lifetime(_))
175+
| (ty::GenericArgKind::Type(_), ty::GenericArgKind::Type(_))
176+
| (ty::GenericArgKind::Const(_), ty::GenericArgKind::Const(_))
177+
);
178+
182179
// In practice, we shouldn't have any inference variables at this point.
183180
// However to be safe, we bail out if we do happen to stumble upon them.
184181
if actual.has_infer() || default.has_infer() {

0 commit comments

Comments
 (0)