Skip to content

Commit 77b18b0

Browse files
committed
Auto merge of rust-lang#123219 - fmease:rustdoc-variances-json, r=<try>
[WIP] rustdoc (base+json): add support for variances I had this patch lying around for more than a month without much progress. Submitting this now to move things forward hopefully. Addresses part of rust-lang#22108. --- For transparency, I've stalled work on this because I haven't had the time to find ways to obtain or represent the “reason” / “provenance” of variances — a feature kindly requested by `@obi1kenobi,` maintainer of cargo-semver-checks. With “reason” we're referring to the set of constituent types that have had an influence on the variance of a given generic parameter. This information could then be used in the diagnostics of cargo-semver-checks à la “variance of param `T` of ty `S` changed from covariant to contravariant because you changed the type of field `f` from `T` to `fn(T)”. On second thought, this seems like a major add-on and I fear that it's infeasible to implement this (smh. exposing the necessary info from rustc). On the other hand, this feature probably has a large impact on the design of the final API (i.e., how we represent variances in rustdoc JSON). I definitely don't want to hand-roll variance computation inside rustdoc. --- TODOs: * clean up the implementation (see individual FIXMEs) * write docs for `rustdoc-json-types` * add rustdoc JSON tests r? ghost
2 parents a3cfa03 + 3781173 commit 77b18b0

File tree

9 files changed

+320
-198
lines changed

9 files changed

+320
-198
lines changed

src/librustdoc/clean/auto_trait.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ where
106106
self.cx,
107107
tcx.generics_of(item_def_id),
108108
ty::GenericPredicates::default(),
109+
// FIXME(fmease): This DefId isn't ideal since it stands for the implementing type, not
110+
// for the synthetic impl. The variance code has no way of knowing this and decides to
111+
// compute variances for the impl which we don't want.
112+
item_def_id,
109113
);
110114
let params = raw_generics.params;
111115

@@ -456,6 +460,10 @@ where
456460
self.cx,
457461
tcx.generics_of(item_def_id),
458462
tcx.explicit_predicates_of(item_def_id),
463+
// FIXME(fmease): This DefId isn't ideal since it stands for the implementing type, not
464+
// for the synthetic impl. The variance code has no way of knowing this and decides to
465+
// compute variances for the impl which we don't want.
466+
item_def_id,
459467
);
460468
let mut generic_params = raw_generics.params;
461469

@@ -630,19 +638,19 @@ where
630638
existing_predicates.extend(final_bounds);
631639

632640
for param in generic_params.iter_mut() {
633-
match param.kind {
634-
GenericParamDefKind::Type { ref mut default, ref mut bounds, .. } => {
641+
match &mut param.kind {
642+
GenericParamDefKind::Type(ty_param) => {
635643
// We never want something like `impl<T=Foo>`.
636-
default.take();
644+
ty_param.default.take();
637645
let generic_ty = Type::Generic(param.name);
638646
if !has_sized.contains(&generic_ty) {
639-
bounds.insert(0, GenericBound::maybe_sized(self.cx));
647+
ty_param.bounds.insert(0, GenericBound::maybe_sized(self.cx));
640648
}
641649
}
642650
GenericParamDefKind::Lifetime { .. } => {}
643-
GenericParamDefKind::Const { ref mut default, .. } => {
651+
GenericParamDefKind::Const(ct_param) => {
644652
// We never want something like `impl<const N: usize = 10>`
645-
default.take();
653+
ct_param.default.take();
646654
}
647655
}
648656
}

src/librustdoc/clean/blanket_impl.rs

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
101101
cx,
102102
cx.tcx.generics_of(impl_def_id),
103103
cx.tcx.explicit_predicates_of(impl_def_id),
104+
impl_def_id,
104105
),
105106
// FIXME(eddyb) compute both `trait_` and `for_` from
106107
// the post-inference `trait_ref`, as it's more accurate.

src/librustdoc/clean/inline.rs

+19-11
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
272272
.collect();
273273

274274
let predicates = cx.tcx.predicates_of(did);
275-
let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
275+
let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates, did);
276276
let generics = filter_non_trait_generics(did, generics);
277277
let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
278278
clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds }
@@ -284,8 +284,12 @@ pub(crate) fn build_function<'tcx>(
284284
) -> Box<clean::Function> {
285285
let sig = cx.tcx.fn_sig(def_id).instantiate_identity();
286286
// The generics need to be cleaned before the signature.
287-
let mut generics =
288-
clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id));
287+
let mut generics = clean_ty_generics(
288+
cx,
289+
cx.tcx.generics_of(def_id),
290+
cx.tcx.explicit_predicates_of(def_id),
291+
def_id,
292+
);
289293
let bound_vars = clean_bound_vars(sig.bound_vars());
290294

291295
// At the time of writing early & late-bound params are stored separately in rustc,
@@ -317,7 +321,7 @@ fn build_enum(cx: &mut DocContext<'_>, did: DefId) -> clean::Enum {
317321
let predicates = cx.tcx.explicit_predicates_of(did);
318322

319323
clean::Enum {
320-
generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
324+
generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates, did),
321325
variants: cx.tcx.adt_def(did).variants().iter().map(|v| clean_variant_def(v, cx)).collect(),
322326
}
323327
}
@@ -328,7 +332,7 @@ fn build_struct(cx: &mut DocContext<'_>, did: DefId) -> clean::Struct {
328332

329333
clean::Struct {
330334
ctor_kind: variant.ctor_kind(),
331-
generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
335+
generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates, did),
332336
fields: variant.fields.iter().map(|x| clean_middle_field(x, cx)).collect(),
333337
}
334338
}
@@ -337,7 +341,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
337341
let predicates = cx.tcx.explicit_predicates_of(did);
338342
let variant = cx.tcx.adt_def(did).non_enum_variant();
339343

340-
let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
344+
let generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates, did);
341345
let fields = variant.fields.iter().map(|x| clean_middle_field(x, cx)).collect();
342346
clean::Union { generics, fields }
343347
}
@@ -354,7 +358,7 @@ fn build_type_alias(
354358

355359
Box::new(clean::TypeAlias {
356360
type_,
357-
generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates),
361+
generics: clean_ty_generics(cx, cx.tcx.generics_of(did), predicates, did),
358362
inner_type,
359363
item_type: None,
360364
})
@@ -532,7 +536,7 @@ pub(crate) fn build_impl(
532536
})
533537
.map(|item| clean_impl_item(item, cx))
534538
.collect::<Vec<_>>(),
535-
clean_generics(impl_.generics, cx),
539+
clean_generics(impl_.generics, cx, did),
536540
),
537541
None => (
538542
tcx.associated_items(did)
@@ -560,7 +564,7 @@ pub(crate) fn build_impl(
560564
.map(|item| clean_middle_assoc_item(item, cx))
561565
.collect::<Vec<_>>(),
562566
clean::enter_impl_trait(cx, |cx| {
563-
clean_ty_generics(cx, tcx.generics_of(did), predicates)
567+
clean_ty_generics(cx, tcx.generics_of(did), predicates, did)
564568
}),
565569
),
566570
};
@@ -718,8 +722,12 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
718722
}
719723

720724
fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
721-
let mut generics =
722-
clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id));
725+
let mut generics = clean_ty_generics(
726+
cx,
727+
cx.tcx.generics_of(def_id),
728+
cx.tcx.explicit_predicates_of(def_id),
729+
def_id,
730+
);
723731
clean::simplify::move_bounds_to_generic_parameters(&mut generics);
724732

725733
clean::Constant {

0 commit comments

Comments
 (0)