diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 860e569ba7e5e..93fd36d37af3c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1744,6 +1744,7 @@ impl<'a> Resolver<'a> { let def_id = self.definitions.local_def_id(type_parameter.id); let def = Def::TyParam(space, index as u32, def_id, name); function_type_rib.bindings.insert(ast::Ident::with_empty_ctxt(name), def); + self.record_def(type_parameter.id, PathResolution::new(def)); } self.type_ribs.push(function_type_rib); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d609ad84a8383..26ea4890b30bf 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -36,8 +36,10 @@ use syntax_pos::{self, DUMMY_SP, Pos}; use rustc_trans::back::link; use rustc::middle::cstore; use rustc::middle::privacy::AccessLevels; +use rustc::middle::resolve_lifetime::DefRegion::*; use rustc::hir::def::Def; use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; +use rustc::hir::fold::Folder; use rustc::hir::print as pprust; use rustc::ty::subst::{self, ParamSpace, VecPerParamSpace}; use rustc::ty; @@ -1636,6 +1638,43 @@ impl PrimitiveType { } } + +// Poor man's type parameter substitution at HIR level. +// Used to replace private type aliases in public signatures with their aliased types. +struct SubstAlias<'a, 'tcx: 'a> { + tcx: &'a ty::TyCtxt<'a, 'tcx, 'tcx>, + // Table type parameter definition -> substituted type + ty_substs: HashMap, + // Table node id of lifetime parameter definition -> substituted lifetime + lt_substs: HashMap, +} + +impl<'a, 'tcx: 'a, 'b: 'tcx> Folder for SubstAlias<'a, 'tcx> { + fn fold_ty(&mut self, ty: P) -> P { + if let hir::TyPath(..) = ty.node { + let def = self.tcx.expect_def(ty.id); + if let Some(new_ty) = self.ty_substs.get(&def).cloned() { + return P(new_ty); + } + } + hir::fold::noop_fold_ty(ty, self) + } + fn fold_lifetime(&mut self, lt: hir::Lifetime) -> hir::Lifetime { + let def = self.tcx.named_region_map.defs.get(<.id).cloned(); + match def { + Some(DefEarlyBoundRegion(_, _, node_id)) | + Some(DefLateBoundRegion(_, node_id)) | + Some(DefFreeRegion(_, node_id)) => { + if let Some(lt) = self.lt_substs.get(&node_id).cloned() { + return lt; + } + } + _ => {} + } + hir::fold::noop_fold_lifetime(lt, self) + } +} + impl Clean for hir::Ty { fn clean(&self, cx: &DocContext) -> Type { use rustc::hir::*; @@ -1665,8 +1704,46 @@ impl Clean for hir::Ty { FixedVector(box ty.clean(cx), n) }, TyTup(ref tys) => Tuple(tys.clean(cx)), - TyPath(None, ref p) => { - resolve_type(cx, p.clean(cx), self.id) + TyPath(None, ref path) => { + if let Some(tcx) = cx.tcx_opt() { + // Substitute private type aliases + let def = tcx.expect_def(self.id); + if let Def::TyAlias(def_id) = def { + if let Some(node_id) = tcx.map.as_local_node_id(def_id) { + if !cx.access_levels.borrow().is_exported(def_id) { + let item = tcx.map.expect_item(node_id); + if let hir::ItemTy(ref ty, ref generics) = item.node { + let provided_params = &path.segments.last().unwrap().parameters; + let mut ty_substs = HashMap::new(); + let mut lt_substs = HashMap::new(); + for (i, ty_param) in generics.ty_params.iter().enumerate() { + let ty_param_def = tcx.expect_def(ty_param.id); + if let Some(ty) = provided_params.types().get(i).cloned() + .cloned() { + ty_substs.insert(ty_param_def, ty.unwrap()); + } else if let Some(default) = ty_param.default.clone() { + ty_substs.insert(ty_param_def, default.unwrap()); + } + } + for (i, lt_param) in generics.lifetimes.iter().enumerate() { + if let Some(lt) = provided_params.lifetimes().get(i) + .cloned() + .cloned() { + lt_substs.insert(lt_param.lifetime.id, lt); + } + } + let mut subst_alias = SubstAlias { + tcx: &tcx, + ty_substs: ty_substs, + lt_substs: lt_substs + }; + return subst_alias.fold_ty(ty.clone()).clean(cx); + } + } + } + } + } + resolve_type(cx, path.clean(cx), self.id) } TyPath(Some(ref qself), ref p) => { let mut segments: Vec<_> = p.segments.clone().into(); diff --git a/src/test/rustdoc/private-type-alias.rs b/src/test/rustdoc/private-type-alias.rs new file mode 100644 index 0000000000000..65e3e02383094 --- /dev/null +++ b/src/test/rustdoc/private-type-alias.rs @@ -0,0 +1,30 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +type MyResultPriv = Result; +pub type MyResultPub = Result; + +// @has private_type_alias/fn.get_result_priv.html '//pre' 'Result' +pub fn get_result_priv() -> MyResultPriv { + panic!(); +} + +// @has private_type_alias/fn.get_result_pub.html '//pre' 'MyResultPub' +pub fn get_result_pub() -> MyResultPub { + panic!(); +} + + +type MyLifetimePriv<'a> = &'a isize; + +// @has private_type_alias/fn.get_lifetime_priv.html '//pre' "&'static isize" +pub fn get_lifetime_priv() -> MyLifetimePriv<'static> { + panic!(); +}