From: bors Date: Tue, 13 Dec 2022 13:09:40 +0000 (+0000) Subject: Auto merge of #105612 - oli-obk:bind_rustdoc, r=GuillaumeGomez X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=ed620cf9690fdafed65845bf35c455db992fbba1;hp=109cccbe4f345c0f0785ce860788580c3e2a29f5;p=rust.git Auto merge of #105612 - oli-obk:bind_rustdoc, r=GuillaumeGomez use ty::Binder in rustdoc instead of `skip_binder` r? `@GuillaumeGomez` this is a preliminary cleanup required to be able to normalize correctly/conveniently in rustdoc --- diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 64033c351b1..9b9c26d6a8b 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -980,8 +980,12 @@ impl<'tcx, T> Binder<'tcx, T> /// contain any bound vars that would be bound by the /// binder. This is commonly used to 'inject' a value T into a /// different binding level. + #[track_caller] pub fn dummy(value: T) -> Binder<'tcx, T> { - assert!(!value.has_escaping_bound_vars()); + assert!( + !value.has_escaping_bound_vars(), + "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder." + ); Binder(value, ty::List::empty()) } @@ -1128,6 +1132,13 @@ pub fn transpose(self) -> Option> { } } +impl<'tcx, T: IntoIterator> Binder<'tcx, T> { + pub fn iter(self) -> impl Iterator> { + let bound_vars = self.1; + self.0.into_iter().map(|v| Binder(v, bound_vars)) + } +} + /// Represents the projection of an associated type. In explicit UFCS /// form this would be written `>::N`. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 953f4aa8a1b..4d6f1524732 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -44,7 +44,7 @@ fn generate_for_trait( discard_positive_impl: bool, ) -> Option { let tcx = self.cx.tcx; - let trait_ref = tcx.mk_trait_ref(trait_def_id, [ty]); + let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(trait_def_id, [ty])); if !self.cx.generated_synthetics.insert((ty, trait_def_id)) { debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref); return None; @@ -124,7 +124,7 @@ fn generate_for_trait( unsafety: hir::Unsafety::Normal, generics: new_generics, trait_: Some(clean_trait_ref_with_bindings(self.cx, trait_ref, ThinVec::new())), - for_: clean_middle_ty(ty, self.cx, None), + for_: clean_middle_ty(ty::Binder::dummy(ty), self.cx, None), items: Vec::new(), polarity, kind: ImplKind::Auto, diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index a1145b90d65..4ef5747596b 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -105,10 +105,10 @@ pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec { // the post-inference `trait_ref`, as it's more accurate. trait_: Some(clean_trait_ref_with_bindings( cx, - trait_ref.0, + ty::Binder::dummy(trait_ref.0), ThinVec::new(), )), - for_: clean_middle_ty(ty.0, cx, None), + for_: clean_middle_ty(ty::Binder::dummy(ty.0), cx, None), items: cx .tcx .associated_items(impl_def_id) @@ -117,7 +117,7 @@ pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec { .collect::>(), polarity: ty::ImplPolarity::Positive, kind: ImplKind::Blanket(Box::new(clean_middle_ty( - trait_ref.0.self_ty(), + ty::Binder::dummy(trait_ref.0.self_ty()), cx, None, ))), diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index e7c3e5a45e8..50caef3553f 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -293,7 +293,7 @@ fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union { fn build_type_alias(cx: &mut DocContext<'_>, did: DefId) -> Box { let predicates = cx.tcx.explicit_predicates_of(did); - let type_ = clean_middle_ty(cx.tcx.type_of(did), cx, Some(did)); + let type_ = clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did)); Box::new(clean::Typedef { type_, @@ -405,7 +405,7 @@ pub(crate) fn build_impl( let for_ = match &impl_item { Some(impl_) => clean_ty(impl_.self_ty, cx), - None => clean_middle_ty(tcx.type_of(did), cx, Some(did)), + None => clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did)), }; // Only inline impl if the implementing type is @@ -496,7 +496,8 @@ pub(crate) fn build_impl( ), }; let polarity = tcx.impl_polarity(did); - let trait_ = associated_trait.map(|t| clean_trait_ref_with_bindings(cx, t, ThinVec::new())); + let trait_ = associated_trait + .map(|t| clean_trait_ref_with_bindings(cx, ty::Binder::dummy(t), ThinVec::new())); if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() { super::build_deref_target_impls(cx, &trait_items, ret); } @@ -640,14 +641,14 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String { fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant { clean::Constant { - type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)), + type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)), kind: clean::ConstantKind::Extern { def_id }, } } fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static { clean::Static { - type_: clean_middle_ty(cx.tcx.type_of(did), cx, Some(did)), + type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(did)), cx, Some(did)), mutability: if mutable { Mutability::Mut } else { Mutability::Not }, expr: None, } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2a2a9470d25..c6ab8e1a83b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -22,6 +22,7 @@ use rustc_middle::middle::resolve_lifetime as rl; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::InternalSubsts; +use rustc_middle::ty::TypeVisitable; use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_span::hygiene::{AstPass, MacroKind}; @@ -127,7 +128,7 @@ fn clean_generic_bound<'tcx>( hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => { let def_id = cx.tcx.require_lang_item(lang_item, Some(span)); - let trait_ref = ty::TraitRef::identity(cx.tcx, def_id).skip_binder(); + let trait_ref = ty::TraitRef::identity(cx.tcx, def_id); let generic_args = clean_generic_args(generic_args, cx); let GenericArgs::AngleBracketed { bindings, .. } = generic_args @@ -156,17 +157,18 @@ fn clean_generic_bound<'tcx>( pub(crate) fn clean_trait_ref_with_bindings<'tcx>( cx: &mut DocContext<'tcx>, - trait_ref: ty::TraitRef<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, bindings: ThinVec, ) -> Path { - let kind = cx.tcx.def_kind(trait_ref.def_id).into(); + let kind = cx.tcx.def_kind(trait_ref.def_id()).into(); if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) { - span_bug!(cx.tcx.def_span(trait_ref.def_id), "`TraitRef` had unexpected kind {:?}", kind); + span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {:?}", kind); } - inline::record_extern_fqn(cx, trait_ref.def_id, kind); - let path = external_path(cx, trait_ref.def_id, true, bindings, trait_ref.substs); + inline::record_extern_fqn(cx, trait_ref.def_id(), kind); + let path = + external_path(cx, trait_ref.def_id(), true, bindings, trait_ref.map_bound(|tr| tr.substs)); - debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs); + debug!(?trait_ref); path } @@ -187,7 +189,7 @@ fn clean_poly_trait_ref_with_bindings<'tcx>( }) .collect(); - let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref.skip_binder(), bindings); + let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings); GenericBound::TraitBound( PolyTrait { trait_, generic_params: late_bound_regions }, hir::TraitBoundModifier::None, @@ -212,19 +214,19 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant { let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id(); Constant { - type_: clean_middle_ty(cx.tcx.type_of(def_id), cx, Some(def_id)), + type_: clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(def_id)), cx, Some(def_id)), kind: ConstantKind::Anonymous { body: constant.value.body }, } } pub(crate) fn clean_middle_const<'tcx>( - constant: ty::Const<'tcx>, + constant: ty::Binder<'tcx, ty::Const<'tcx>>, cx: &mut DocContext<'tcx>, ) -> Constant { // FIXME: instead of storing the stringified expression, store `self` directly instead. Constant { - type_: clean_middle_ty(constant.ty(), cx, None), - kind: ConstantKind::TyConst { expr: constant.to_string().into() }, + type_: clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None), + kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() }, } } @@ -333,7 +335,7 @@ fn clean_poly_trait_predicate<'tcx>( let poly_trait_ref = pred.map_bound(|pred| pred.trait_ref); Some(WherePredicate::BoundPredicate { - ty: clean_middle_ty(poly_trait_ref.skip_binder().self_ty(), cx, None), + ty: clean_middle_ty(poly_trait_ref.self_ty(), cx, None), bounds: vec![clean_poly_trait_ref_with_bindings(cx, poly_trait_ref, ThinVec::new())], bound_params: Vec::new(), }) @@ -359,7 +361,7 @@ fn clean_type_outlives_predicate<'tcx>( let ty::OutlivesPredicate(ty, lt) = pred; Some(WherePredicate::BoundPredicate { - ty: clean_middle_ty(ty, cx, None), + ty: clean_middle_ty(ty::Binder::dummy(ty), cx, None), bounds: vec![GenericBound::Outlives( clean_middle_region(lt).expect("failed to clean lifetimes"), )], @@ -367,10 +369,13 @@ fn clean_type_outlives_predicate<'tcx>( }) } -fn clean_middle_term<'tcx>(term: ty::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Term { - match term.unpack() { - ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(ty, cx, None)), - ty::TermKind::Const(c) => Term::Constant(clean_middle_const(c, cx)), +fn clean_middle_term<'tcx>( + term: ty::Binder<'tcx, ty::Term<'tcx>>, + cx: &mut DocContext<'tcx>, +) -> Term { + match term.skip_binder().unpack() { + ty::TermKind::Ty(ty) => Term::Type(clean_middle_ty(term.rebind(ty), cx, None)), + ty::TermKind::Const(c) => Term::Constant(clean_middle_const(term.rebind(c), cx)), } } @@ -379,7 +384,10 @@ fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Te hir::Term::Ty(ty) => Term::Type(clean_ty(ty, cx)), hir::Term::Const(c) => { let def_id = cx.tcx.hir().local_def_id(c.hir_id); - Term::Constant(clean_middle_const(ty::Const::from_anon_const(cx.tcx, def_id), cx)) + Term::Constant(clean_middle_const( + ty::Binder::dummy(ty::Const::from_anon_const(cx.tcx, def_id)), + cx, + )) } } } @@ -398,32 +406,31 @@ fn clean_projection_predicate<'tcx>( }) .collect(); - let ty::ProjectionPredicate { projection_ty, term } = pred.skip_binder(); - WherePredicate::EqPredicate { - lhs: Box::new(clean_projection(projection_ty, cx, None)), - rhs: Box::new(clean_middle_term(term, cx)), + lhs: Box::new(clean_projection(pred.map_bound(|p| p.projection_ty), cx, None)), + rhs: Box::new(clean_middle_term(pred.map_bound(|p| p.term), cx)), bound_params: late_bound_regions, } } fn clean_projection<'tcx>( - ty: ty::ProjectionTy<'tcx>, + ty: ty::Binder<'tcx, ty::ProjectionTy<'tcx>>, cx: &mut DocContext<'tcx>, def_id: Option, ) -> Type { - if cx.tcx.def_kind(ty.item_def_id) == DefKind::ImplTraitPlaceholder { + if cx.tcx.def_kind(ty.skip_binder().item_def_id) == DefKind::ImplTraitPlaceholder { let bounds = cx .tcx - .explicit_item_bounds(ty.item_def_id) + .explicit_item_bounds(ty.skip_binder().item_def_id) .iter() - .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.substs)) + .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.skip_binder().substs)) .collect::>(); return clean_middle_opaque_bounds(cx, bounds); } - let trait_ = clean_trait_ref_with_bindings(cx, ty.trait_ref(cx.tcx), ThinVec::new()); - let self_type = clean_middle_ty(ty.self_ty(), cx, None); + let trait_ = + clean_trait_ref_with_bindings(cx, ty.map_bound(|ty| ty.trait_ref(cx.tcx)), ThinVec::new()); + let self_type = clean_middle_ty(ty.map_bound(|ty| ty.self_ty()), cx, None); let self_def_id = if let Some(def_id) = def_id { cx.tcx.opt_parent(def_id).or(Some(def_id)) } else { @@ -446,15 +453,16 @@ fn compute_should_show_cast(self_def_id: Option, trait_: &Path, self_type } fn projection_to_path_segment<'tcx>( - ty: ty::ProjectionTy<'tcx>, + ty: ty::Binder<'tcx, ty::ProjectionTy<'tcx>>, cx: &mut DocContext<'tcx>, ) -> PathSegment { - let item = cx.tcx.associated_item(ty.item_def_id); - let generics = cx.tcx.generics_of(ty.item_def_id); + let item = cx.tcx.associated_item(ty.skip_binder().item_def_id); + let generics = cx.tcx.generics_of(ty.skip_binder().item_def_id); PathSegment { name: item.name, args: GenericArgs::AngleBracketed { - args: substs_to_args(cx, &ty.substs[generics.parent_count..], false).into(), + args: substs_to_args(cx, ty.map_bound(|ty| &ty.substs[generics.parent_count..]), false) + .into(), bindings: Default::default(), }, } @@ -470,7 +478,11 @@ fn clean_generic_param_def<'tcx>( } ty::GenericParamDefKind::Type { has_default, synthetic, .. } => { let default = if has_default { - Some(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id))) + Some(clean_middle_ty( + ty::Binder::dummy(cx.tcx.type_of(def.def_id)), + cx, + Some(def.def_id), + )) } else { None }; @@ -488,7 +500,11 @@ fn clean_generic_param_def<'tcx>( def.name, GenericParamDefKind::Const { did: def.def_id, - ty: Box::new(clean_middle_ty(cx.tcx.type_of(def.def_id), cx, Some(def.def_id))), + ty: Box::new(clean_middle_ty( + ty::Binder::dummy(cx.tcx.type_of(def.def_id)), + cx, + Some(def.def_id), + )), default: match has_default { true => Some(Box::new(cx.tcx.const_param_default(def.def_id).to_string())), false => None, @@ -733,8 +749,10 @@ fn clean_ty_generics<'tcx>( .collect::>(); // param index -> [(trait DefId, associated type name & generics, type, higher-ranked params)] - let mut impl_trait_proj = - FxHashMap::, Vec)>>::default(); + let mut impl_trait_proj = FxHashMap::< + u32, + Vec<(DefId, PathSegment, ty::Binder<'_, Ty<'_>>, Vec)>, + >::default(); let where_predicates = preds .predicates @@ -783,8 +801,8 @@ fn clean_ty_generics<'tcx>( let proj = projection.map(|p| { ( - clean_projection(p.skip_binder().projection_ty, cx, None), - p.skip_binder().term, + clean_projection(p.map_bound(|p| p.projection_ty), cx, None), + p.map_bound(|p| p.term), ) }); if let Some(((_, trait_did, name), rhs)) = proj @@ -795,7 +813,7 @@ fn clean_ty_generics<'tcx>( impl_trait_proj.entry(param_idx).or_default().push(( trait_did, name, - rhs.ty().unwrap(), + rhs.map_bound(|rhs| rhs.ty().unwrap()), p.get_bound_params() .into_iter() .flatten() @@ -1066,7 +1084,7 @@ fn clean_fn_decl_from_did_and_sig<'tcx>( // We assume all empty tuples are default return type. This theoretically can discard `-> ()`, // but shouldn't change any code meaning. - let output = match clean_middle_ty(sig.skip_binder().output(), cx, None) { + let output = match clean_middle_ty(sig.output(), cx, None) { Type::Tuple(inner) if inner.is_empty() => DefaultReturn, ty => Return(ty), }; @@ -1076,11 +1094,10 @@ fn clean_fn_decl_from_did_and_sig<'tcx>( c_variadic: sig.skip_binder().c_variadic, inputs: Arguments { values: sig - .skip_binder() .inputs() .iter() .map(|t| Argument { - type_: clean_middle_ty(*t, cx, None), + type_: clean_middle_ty(t.map_bound(|t| *t), cx, None), name: names .next() .map(|i| i.name) @@ -1134,7 +1151,8 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext hir::TraitItemKind::Type(bounds, Some(default)) => { let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(); - let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, default), cx, None); + let item_type = + clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, default)), cx, None); AssocTypeItem( Box::new(Typedef { type_: clean_ty(default, cx), @@ -1173,7 +1191,8 @@ pub(crate) fn clean_impl_item<'tcx>( hir::ImplItemKind::Type(hir_ty) => { let type_ = clean_ty(hir_ty, cx); let generics = clean_generics(impl_.generics, cx); - let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None); + let item_type = + clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None); AssocTypeItem( Box::new(Typedef { type_, generics, item_type: Some(item_type) }), Vec::new(), @@ -1192,7 +1211,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( let tcx = cx.tcx; let kind = match assoc_item.kind { ty::AssocKind::Const => { - let ty = clean_middle_ty(tcx.type_of(assoc_item.def_id), cx, Some(assoc_item.def_id)); + let ty = clean_middle_ty( + ty::Binder::dummy(tcx.type_of(assoc_item.def_id)), + cx, + Some(assoc_item.def_id), + ); let provided = match assoc_item.container { ty::ImplContainer => true, @@ -1375,7 +1398,7 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool { AssocTypeItem( Box::new(Typedef { type_: clean_middle_ty( - tcx.type_of(assoc_item.def_id), + ty::Binder::dummy(tcx.type_of(assoc_item.def_id)), cx, Some(assoc_item.def_id), ), @@ -1393,7 +1416,7 @@ fn param_eq_arg(param: &GenericParamDef, arg: &GenericArg) -> bool { AssocTypeItem( Box::new(Typedef { type_: clean_middle_ty( - tcx.type_of(assoc_item.def_id), + ty::Binder::dummy(tcx.type_of(assoc_item.def_id)), cx, Some(assoc_item.def_id), ), @@ -1437,8 +1460,11 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type hir::QPath::Resolved(Some(qself), p) => { // Try to normalize `::T` to a type let ty = hir_ty_to_ty(cx.tcx, hir_ty); - if let Some(normalized_value) = normalize(cx, ty) { - return clean_middle_ty(normalized_value, cx, None); + // `hir_to_ty` can return projection types with escaping vars for GATs, e.g. `<() as Trait>::Gat<'_>` + if !ty.has_escaping_bound_vars() { + if let Some(normalized_value) = normalize(cx, ty::Binder::dummy(ty)) { + return clean_middle_ty(normalized_value, cx, None); + } } let trait_segments = &p.segments[..p.segments.len() - 1]; @@ -1465,7 +1491,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type // Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s. ty::Error(_) => return Type::Infer, // Otherwise, this is an inherent associated type. - _ => return clean_middle_ty(ty, cx, None), + _ => return clean_middle_ty(ty::Binder::dummy(ty), cx, None), }; let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx); register_res(cx, trait_.res); @@ -1632,7 +1658,10 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T } /// Returns `None` if the type could not be normalized -fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option> { +fn normalize<'tcx>( + cx: &mut DocContext<'tcx>, + ty: ty::Binder<'tcx, Ty<'tcx>>, +) -> Option>> { // HACK: low-churn fix for #79459 while we wait for a trait normalization fix if !cx.tcx.sess.opts.unstable_opts.normalize_docs { return None; @@ -1660,14 +1689,14 @@ fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option> } } +#[instrument(level = "trace", skip(cx), ret)] pub(crate) fn clean_middle_ty<'tcx>( - ty: Ty<'tcx>, + bound_ty: ty::Binder<'tcx, Ty<'tcx>>, cx: &mut DocContext<'tcx>, def_id: Option, ) -> Type { - trace!("cleaning type: {:?}", ty); - let ty = normalize(cx, ty).unwrap_or(ty); - match *ty.kind() { + let bound_ty = normalize(cx, bound_ty).unwrap_or(bound_ty); + match *bound_ty.skip_binder().kind() { ty::Never => Primitive(PrimitiveType::Never), ty::Bool => Primitive(PrimitiveType::Bool), ty::Char => Primitive(PrimitiveType::Char), @@ -1675,20 +1704,23 @@ pub(crate) fn clean_middle_ty<'tcx>( ty::Uint(uint_ty) => Primitive(uint_ty.into()), ty::Float(float_ty) => Primitive(float_ty.into()), ty::Str => Primitive(PrimitiveType::Str), - ty::Slice(ty) => Slice(Box::new(clean_middle_ty(ty, cx, None))), + ty::Slice(ty) => Slice(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None))), ty::Array(ty, mut n) => { n = n.eval(cx.tcx, ty::ParamEnv::reveal_all()); let n = print_const(cx, n); - Array(Box::new(clean_middle_ty(ty, cx, None)), n.into()) + Array(Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)), n.into()) + } + ty::RawPtr(mt) => { + RawPointer(mt.mutbl, Box::new(clean_middle_ty(bound_ty.rebind(mt.ty), cx, None))) } - ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(clean_middle_ty(mt.ty, cx, None))), ty::Ref(r, ty, mutbl) => BorrowedRef { lifetime: clean_middle_region(r), mutability: mutbl, - type_: Box::new(clean_middle_ty(ty, cx, None)), + type_: Box::new(clean_middle_ty(bound_ty.rebind(ty), cx, None)), }, ty::FnDef(..) | ty::FnPtr(_) => { - let sig = ty.fn_sig(cx.tcx); + // FIXME: should we merge the outer and inner binders somehow? + let sig = bound_ty.skip_binder().fn_sig(cx.tcx); let decl = clean_fn_decl_from_did_and_sig(cx, None, sig); BareFunction(Box::new(BareFunctionDecl { unsafety: sig.unsafety(), @@ -1705,12 +1737,18 @@ pub(crate) fn clean_middle_ty<'tcx>( AdtKind::Enum => ItemType::Enum, }; inline::record_extern_fqn(cx, did, kind); - let path = external_path(cx, did, false, ThinVec::new(), substs); + let path = external_path(cx, did, false, ThinVec::new(), bound_ty.rebind(substs)); Type::Path { path } } ty::Foreign(did) => { inline::record_extern_fqn(cx, did, ItemType::ForeignType); - let path = external_path(cx, did, false, ThinVec::new(), InternalSubsts::empty()); + let path = external_path( + cx, + did, + false, + ThinVec::new(), + ty::Binder::dummy(InternalSubsts::empty()), + ); Type::Path { path } } ty::Dynamic(obj, ref reg, _) => { @@ -1721,11 +1759,11 @@ pub(crate) fn clean_middle_ty<'tcx>( let did = obj .principal_def_id() .or_else(|| dids.next()) - .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", ty)); + .unwrap_or_else(|| panic!("found trait object `{bound_ty:?}` with no traits?")); let substs = match obj.principal() { - Some(principal) => principal.skip_binder().substs, + Some(principal) => principal.map_bound(|p| p.substs), // marker traits have no substs. - _ => cx.tcx.intern_substs(&[]), + _ => ty::Binder::dummy(InternalSubsts::empty()), }; inline::record_extern_fqn(cx, did, ItemType::Trait); @@ -1736,7 +1774,7 @@ pub(crate) fn clean_middle_ty<'tcx>( let lifetime = clean_middle_region(*reg); let mut bounds = dids .map(|did| { - let empty = cx.tcx.intern_substs(&[]); + let empty = ty::Binder::dummy(InternalSubsts::empty()); let path = external_path(cx, did, false, ThinVec::new(), empty); inline::record_extern_fqn(cx, did, ItemType::Trait); PolyTrait { trait_: path, generic_params: Vec::new() } @@ -1747,15 +1785,17 @@ pub(crate) fn clean_middle_ty<'tcx>( .projection_bounds() .map(|pb| TypeBinding { assoc: projection_to_path_segment( - pb.skip_binder() - // HACK(compiler-errors): Doesn't actually matter what self - // type we put here, because we're only using the GAT's substs. - .with_self_ty(cx.tcx, cx.tcx.types.self_param) - .projection_ty, + pb.map_bound(|pb| { + pb + // HACK(compiler-errors): Doesn't actually matter what self + // type we put here, because we're only using the GAT's substs. + .with_self_ty(cx.tcx, cx.tcx.types.self_param) + .projection_ty + }), cx, ), kind: TypeBindingKind::Equality { - term: clean_middle_term(pb.skip_binder().term, cx), + term: clean_middle_term(pb.map_bound(|pb| pb.term), cx), }, }) .collect(); @@ -1779,9 +1819,11 @@ pub(crate) fn clean_middle_ty<'tcx>( DynTrait(bounds, lifetime) } - ty::Tuple(t) => Tuple(t.iter().map(|t| clean_middle_ty(t, cx, None)).collect()), + ty::Tuple(t) => { + Tuple(t.iter().map(|t| clean_middle_ty(bound_ty.rebind(t), cx, None)).collect()) + } - ty::Projection(ref data) => clean_projection(*data, cx, def_id), + ty::Projection(ref data) => clean_projection(bound_ty.rebind(*data), cx, def_id), ty::Param(ref p) => { if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) { @@ -1854,9 +1896,12 @@ fn clean_middle_opaque_bounds<'tcx>( { if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() { Some(TypeBinding { - assoc: projection_to_path_segment(proj.projection_ty, cx), + assoc: projection_to_path_segment( + bound.kind().rebind(proj.projection_ty), + cx, + ), kind: TypeBindingKind::Equality { - term: clean_middle_term(proj.term, cx), + term: clean_middle_term(bound.kind().rebind(proj.term), cx), }, }) } else { @@ -1887,7 +1932,7 @@ pub(crate) fn clean_middle_field<'tcx>(field: &ty::FieldDef, cx: &mut DocContext clean_field_with_def_id( field.did, field.name, - clean_middle_ty(cx.tcx.type_of(field.did), cx, Some(field.did)), + clean_middle_ty(ty::Binder::dummy(cx.tcx.type_of(field.did)), cx, Some(field.did)), cx, ) } @@ -2100,7 +2145,7 @@ fn clean_maybe_renamed_item<'tcx>( }), ItemKind::TyAlias(hir_ty, generics) => { let rustdoc_ty = clean_ty(hir_ty, cx); - let ty = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None); + let ty = clean_middle_ty(ty::Binder::dummy(hir_ty_to_ty(cx.tcx, hir_ty)), cx, None); TypedefItem(Box::new(Typedef { type_: rustdoc_ty, generics: clean_generics(generics, cx), @@ -2211,7 +2256,9 @@ fn clean_impl<'tcx>( let for_ = clean_ty(impl_.self_ty, cx); let type_alias = for_.def_id(&cx.cache).and_then(|did| match tcx.def_kind(did) { - DefKind::TyAlias => Some(clean_middle_ty(tcx.type_of(did), cx, Some(did))), + DefKind::TyAlias => { + Some(clean_middle_ty(ty::Binder::dummy(tcx.type_of(did)), cx, Some(did))) + } _ => None, }); let mut make_item = |trait_: Option, for_: Type, items: Vec| { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 98329e7fc91..7a7313c4bc9 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1343,7 +1343,7 @@ pub(crate) enum GenericBound { impl GenericBound { pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound { let did = cx.tcx.require_lang_item(LangItem::Sized, None); - let empty = cx.tcx.intern_substs(&[]); + let empty = ty::Binder::dummy(ty::InternalSubsts::empty()); let path = external_path(cx, did, false, ThinVec::new(), empty); inline::record_extern_fqn(cx, did, ItemType::Trait); GenericBound::TraitBound( diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 246560bad29..a12f764fa8e 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -78,12 +78,16 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate { pub(crate) fn substs_to_args<'tcx>( cx: &mut DocContext<'tcx>, - substs: &[ty::subst::GenericArg<'tcx>], + substs: ty::Binder<'tcx, &[ty::subst::GenericArg<'tcx>]>, mut skip_first: bool, ) -> Vec { let mut ret_val = - Vec::with_capacity(substs.len().saturating_sub(if skip_first { 1 } else { 0 })); - ret_val.extend(substs.iter().filter_map(|kind| match kind.unpack() { + Vec::with_capacity(substs.skip_binder().len().saturating_sub(if skip_first { + 1 + } else { + 0 + })); + ret_val.extend(substs.iter().filter_map(|kind| match kind.skip_binder().unpack() { GenericArgKind::Lifetime(lt) => { Some(GenericArg::Lifetime(clean_middle_region(lt).unwrap_or(Lifetime::elided()))) } @@ -91,8 +95,12 @@ pub(crate) fn substs_to_args<'tcx>( skip_first = false; None } - GenericArgKind::Type(ty) => Some(GenericArg::Type(clean_middle_ty(ty, cx, None))), - GenericArgKind::Const(ct) => Some(GenericArg::Const(Box::new(clean_middle_const(ct, cx)))), + GenericArgKind::Type(ty) => { + Some(GenericArg::Type(clean_middle_ty(kind.rebind(ty), cx, None))) + } + GenericArgKind::Const(ct) => { + Some(GenericArg::Const(Box::new(clean_middle_const(kind.rebind(ct), cx)))) + } })); ret_val } @@ -102,15 +110,20 @@ fn external_generic_args<'tcx>( did: DefId, has_self: bool, bindings: ThinVec, - substs: SubstsRef<'tcx>, + substs: ty::Binder<'tcx, SubstsRef<'tcx>>, ) -> GenericArgs { - let args = substs_to_args(cx, substs, has_self); + let args = substs_to_args(cx, substs.map_bound(|substs| &substs[..]), has_self); if cx.tcx.fn_trait_kind_from_def_id(did).is_some() { + let ty = substs + .iter() + .nth(if has_self { 1 } else { 0 }) + .unwrap() + .map_bound(|arg| arg.expect_ty()); let inputs = // The trait's first substitution is the one after self, if there is one. - match substs.iter().nth(if has_self { 1 } else { 0 }).unwrap().expect_ty().kind() { - ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(t, cx, None)).collect::>().into(), + match ty.skip_binder().kind() { + ty::Tuple(tys) => tys.iter().map(|t| clean_middle_ty(ty.rebind(t), cx, None)).collect::>().into(), _ => return GenericArgs::AngleBracketed { args: args.into(), bindings }, }; let output = bindings.into_iter().next().and_then(|binding| match binding.kind { @@ -130,7 +143,7 @@ pub(super) fn external_path<'tcx>( did: DefId, has_self: bool, bindings: ThinVec, - substs: SubstsRef<'tcx>, + substs: ty::Binder<'tcx, SubstsRef<'tcx>>, ) -> Path { let def_kind = cx.tcx.def_kind(did); let name = cx.tcx.item_name(did);