Skip to content

Rustdoc-Json: Add Path type for traits. #100335

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 29 additions & 29 deletions src/etc/check_missing_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def check_generic_bound(bound):
if "trait_bound" in bound:
for param in bound["trait_bound"]["generic_params"]:
check_generic_param(param)
check_type(bound["trait_bound"]["trait"])
check_path(bound["trait_bound"]["trait"])


def check_decl(decl):
Expand All @@ -66,35 +66,35 @@ def check_decl(decl):
if decl["output"]:
check_type(decl["output"])

def check_path(path):
args = path["args"]
if args:
if "angle_bracketed" in args:
for arg in args["angle_bracketed"]["args"]:
if "type" in arg:
check_type(arg["type"])
elif "const" in arg:
check_type(arg["const"]["type"])
for binding in args["angle_bracketed"]["bindings"]:
if "equality" in binding["binding"]:
term = binding["binding"]["equality"]
if "type" in term: check_type(term["type"])
elif "const" in term: check_type(term["const"])
elif "constraint" in binding["binding"]:
for bound in binding["binding"]["constraint"]:
check_generic_bound(bound)
elif "parenthesized" in args:
for input_ty in args["parenthesized"]["inputs"]:
check_type(input_ty)
if args["parenthesized"]["output"]:
check_type(args["parenthesized"]["output"])
if not valid_id(path["id"]):
print("Type contained an invalid ID:", path["id"])
sys.exit(1)

def check_type(ty):
if ty["kind"] == "resolved_path":
for bound in ty["inner"]["param_names"]:
check_generic_bound(bound)
args = ty["inner"]["args"]
if args:
if "angle_bracketed" in args:
for arg in args["angle_bracketed"]["args"]:
if "type" in arg:
check_type(arg["type"])
elif "const" in arg:
check_type(arg["const"]["type"])
for binding in args["angle_bracketed"]["bindings"]:
if "equality" in binding["binding"]:
term = binding["binding"]["equality"]
if "type" in term: check_type(term["type"])
elif "const" in term: check_type(term["const"])
elif "constraint" in binding["binding"]:
for bound in binding["binding"]["constraint"]:
check_generic_bound(bound)
elif "parenthesized" in args:
for input_ty in args["parenthesized"]["inputs"]:
check_type(input_ty)
if args["parenthesized"]["output"]:
check_type(args["parenthesized"]["output"])
if not valid_id(ty["inner"]["id"]):
print("Type contained an invalid ID:", ty["inner"]["id"])
sys.exit(1)
check_path(ty["inner"])
elif ty["kind"] == "tuple":
for ty in ty["inner"]:
check_type(ty)
Expand All @@ -111,7 +111,7 @@ def check_type(ty):
check_decl(ty["inner"]["decl"])
elif ty["kind"] == "qualified_path":
check_type(ty["inner"]["self_type"])
check_type(ty["inner"]["trait"])
check_path(ty["inner"]["trait"])


work_list = set([crate["root"]])
Expand Down Expand Up @@ -174,7 +174,7 @@ def check_type(ty):
elif item["kind"] == "impl":
check_generics(item["inner"]["generics"])
if item["inner"]["trait"]:
check_type(item["inner"]["trait"])
check_path(item["inner"]["trait"])
if item["inner"]["blanket_impl"]:
check_type(item["inner"]["blanket_impl"])
check_type(item["inner"]["for"])
Expand Down
46 changes: 20 additions & 26 deletions src/librustdoc/json/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -428,10 +428,8 @@ impl FromWithTcx<clean::GenericBound> for GenericBound {
use clean::GenericBound::*;
match bound {
TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
// FIXME: should `trait_` be a clean::Path equivalent in JSON?
let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
GenericBound::TraitBound {
trait_,
trait_: trait_.into_tcx(tcx),
generic_params: generic_params.into_tcx(tcx),
modifier: from_trait_bound_modifier(modifier),
}
Expand Down Expand Up @@ -460,12 +458,7 @@ impl FromWithTcx<clean::Type> for Type {
};

match ty {
clean::Type::Path { path } => Type::ResolvedPath {
name: path.whole_name(),
id: from_item_id(path.def_id().into(), tcx),
args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
param_names: Vec::new(),
},
clean::Type::Path { path } => Type::ResolvedPath(path.into_tcx(tcx)),
clean::Type::DynTrait(bounds, lt) => Type::DynTrait(DynTrait {
lifetime: lt.map(convert_lifetime),
traits: bounds.into_tcx(tcx),
Expand All @@ -487,16 +480,22 @@ impl FromWithTcx<clean::Type> for Type {
mutable: mutability == ast::Mutability::Mut,
type_: Box::new((*type_).into_tcx(tcx)),
},
QPath { assoc, self_type, trait_, .. } => {
// FIXME: should `trait_` be a clean::Path equivalent in JSON?
let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
Type::QualifiedPath {
name: assoc.name.to_string(),
args: Box::new(assoc.args.clone().into_tcx(tcx)),
self_type: Box::new((*self_type).into_tcx(tcx)),
trait_: Box::new(trait_),
}
}
QPath { assoc, self_type, trait_, .. } => Type::QualifiedPath {
name: assoc.name.to_string(),
args: Box::new(assoc.args.clone().into_tcx(tcx)),
self_type: Box::new((*self_type).into_tcx(tcx)),
trait_: trait_.into_tcx(tcx),
},
}
}
}

impl FromWithTcx<clean::Path> for Path {
fn from_tcx(path: clean::Path, tcx: TyCtxt<'_>) -> Path {
Path {
name: path.whole_name(),
id: from_item_id(path.def_id().into(), tcx),
args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
}
}
}
Expand Down Expand Up @@ -565,19 +564,14 @@ impl FromWithTcx<clean::PolyTrait> for PolyTrait {
clean::PolyTrait { trait_, generic_params }: clean::PolyTrait,
tcx: TyCtxt<'_>,
) -> Self {
PolyTrait {
trait_: clean::Type::Path { path: trait_ }.into_tcx(tcx),
generic_params: generic_params.into_tcx(tcx),
}
PolyTrait { trait_: trait_.into_tcx(tcx), generic_params: generic_params.into_tcx(tcx) }
}
}

impl FromWithTcx<clean::Impl> for Impl {
fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
let provided_trait_methods = impl_.provided_trait_methods(tcx);
let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_;
// FIXME: should `trait_` be a clean::Path equivalent in JSON?
let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
// FIXME: use something like ImplKind in JSON?
let (synthetic, blanket_impl) = match kind {
clean::ImplKind::Normal | clean::ImplKind::FakeVaradic => (false, None),
Expand All @@ -595,7 +589,7 @@ impl FromWithTcx<clean::Impl> for Impl {
.into_iter()
.map(|x| x.to_string())
.collect(),
trait_,
trait_: trait_.map(|path| path.into_tcx(tcx)),
for_: for_.into_tcx(tcx),
items: ids(items, tcx),
negative: negative_polarity,
Expand Down
31 changes: 20 additions & 11 deletions src/rustdoc-json-types/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::path::PathBuf;
use serde::{Deserialize, Serialize};

/// rustdoc format-version.
pub const FORMAT_VERSION: u32 = 17;
pub const FORMAT_VERSION: u32 = 18;

/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
/// about the language items in the local crate, as well as info about external items to allow
Expand Down Expand Up @@ -133,7 +133,7 @@ pub struct DynTrait {
/// A trait and potential HRTBs
pub struct PolyTrait {
#[serde(rename = "trait")]
pub trait_: Type,
pub trait_: Path,
/// Used for Higher-Rank Trait Bounds (HRTBs)
/// ```text
/// dyn for<'a> Fn() -> &'a i32"
Expand Down Expand Up @@ -447,7 +447,7 @@ pub enum WherePredicate {
pub enum GenericBound {
TraitBound {
#[serde(rename = "trait")]
trait_: Type,
trait_: Path,
/// Used for Higher-Rank Trait Bounds (HRTBs)
/// ```text
/// where F: for<'a, 'b> Fn(&'a u8, &'b u8)
Expand Down Expand Up @@ -481,12 +481,7 @@ pub enum Term {
#[serde(tag = "kind", content = "inner")]
pub enum Type {
/// Structs, enums, and traits
ResolvedPath {
name: String,
id: Id,
args: Option<Box<GenericArgs>>,
param_names: Vec<GenericBound>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, you removed this field because it was always empty?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, is was origionaly ment to be part of handling dyn traits, but was never used, and we handle dyn differently now (#99787)

},
ResolvedPath(Path),
DynTrait(DynTrait),
/// Parameterized types
Generic(String),
Expand Down Expand Up @@ -527,10 +522,24 @@ pub enum Type {
args: Box<GenericArgs>,
self_type: Box<Type>,
#[serde(rename = "trait")]
trait_: Box<Type>,
trait_: Path,
},
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Path {
pub name: String,
pub id: Id,
/// Generic arguments to the type
/// ```test
/// std::borrow::Cow<'static, str>
/// ^^^^^^^^^^^^^^
/// |
/// this part
/// ```
pub args: Option<Box<GenericArgs>>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct FunctionPointer {
pub decl: FnDecl,
Expand Down Expand Up @@ -574,7 +583,7 @@ pub struct Impl {
pub generics: Generics,
pub provided_trait_methods: Vec<String>,
#[serde(rename = "trait")]
pub trait_: Option<Type>,
pub trait_: Option<Path>,
#[serde(rename = "for")]
pub for_: Type,
pub items: Vec<Id>,
Expand Down
12 changes: 6 additions & 6 deletions src/test/rustdoc-json/fns/generic_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub trait GenericFoo<'a> {}
// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].name" '"F"'
// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.default" 'null'
// @count - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[*]" 1
// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" '$foo'
// @is - "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo'
// @count - "$.index[*][?(@.name=='generics')].inner.decl.inputs[*]" 1
// @is - "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][0]" '"f"'
// @is - "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].kind" '"generic"'
Expand All @@ -24,12 +24,12 @@ pub fn generics<F: Foo>(f: F) {}
// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.where_predicates" "[]"
// @count - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[*]" 1
// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].name" '"impl Foo"'
// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $foo
// @is - "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo
// @count - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[*]" 1
// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][0]" '"f"'
// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].kind" '"impl_trait"'
// @count - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[*]" 1
// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.inner.id" $foo
// @is - "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $foo
pub fn impl_trait(f: impl Foo) {}

// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.params[*]" 3
Expand All @@ -43,11 +43,11 @@ pub fn impl_trait(f: impl Foo) {}

// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F", "kind": "generic"}'
// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[*]" 1
// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.inner.id" $foo
// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo

// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.type" '{"inner": "G", "kind": "generic"}'
// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[*]" 1
// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.inner.id" $generic_foo
// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo
// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1
// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\"
// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
Expand All @@ -57,7 +57,7 @@ pub fn impl_trait(f: impl Foo) {}
// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.lifetime" \"\'b\"
// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.type" '{"inner": "H", "kind": "generic"}'
// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[*]" 1
// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.inner.id" $foo
// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo
// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]"
// @count - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[*]" 1
// @is - "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\"
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc-json/fns/generic_returns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub trait Foo {}
// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.inputs" []
// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.kind" '"impl_trait"'
// @count - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[*]" 1
// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[0].trait_bound.trait.inner.id" $foo
// @is - "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[0].trait_bound.trait.id" $foo
pub fn get_foo() -> impl Foo {
Fooer {}
}
Expand Down
6 changes: 3 additions & 3 deletions src/test/rustdoc-json/fns/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ pub trait Wham {}
// @count - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[*]" 1
// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].name" '"T"'
// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" false
// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $wham_id
// @has - "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
// @is - "$.index[*][?(@.name=='one_generic_param_fn')].inner.decl.inputs" '[["w", {"inner": "T", "kind": "generic"}]]'
pub fn one_generic_param_fn<T: Wham>(w: T) {}

// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.where_predicates" []
// @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[*]" 1
// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].name" '"impl Wham"'
// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" true
// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.inner.id" $wham_id
// @has - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
// @count - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[*]" 1
// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][0]" '"w"'
// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].kind" '"impl_trait"'
// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.inner.id" $wham_id
// @is - "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $wham_id
pub fn one_synthetic_generic_param_fn(w: impl Wham) {}
10 changes: 5 additions & 5 deletions src/test/rustdoc-json/traits/supertrait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ pub trait Loud {}

// @set very_loud_id = - "$.index[*][?(@.name=='VeryLoud')].id"
// @count - "$.index[*][?(@.name=='VeryLoud')].inner.bounds[*]" 1
// @is - "$.index[*][?(@.name=='VeryLoud')].inner.bounds[0].trait_bound.trait.inner.id" $loud_id
// @is - "$.index[*][?(@.name=='VeryLoud')].inner.bounds[0].trait_bound.trait.id" $loud_id
pub trait VeryLoud: Loud {}

// @set sounds_good_id = - "$.index[*][?(@.name=='SoundsGood')].id"
pub trait SoundsGood {}

// @count - "$.index[*][?(@.name=='MetalBand')].inner.bounds[*]" 2
// @is - "$.index[*][?(@.name=='MetalBand')].inner.bounds[0].trait_bound.trait.inner.id" $very_loud_id
// @is - "$.index[*][?(@.name=='MetalBand')].inner.bounds[1].trait_bound.trait.inner.id" $sounds_good_id
// @is - "$.index[*][?(@.name=='MetalBand')].inner.bounds[0].trait_bound.trait.id" $very_loud_id
// @is - "$.index[*][?(@.name=='MetalBand')].inner.bounds[1].trait_bound.trait.id" $sounds_good_id
pub trait MetalBand: VeryLoud + SoundsGood {}

// @count - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[*]" 2
// @is - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[1].trait_bound.trait.inner.id" $very_loud_id
// @is - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[0].trait_bound.trait.inner.id" $sounds_good_id
// @is - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[1].trait_bound.trait.id" $very_loud_id
// @is - "$.index[*][?(@.name=='DnabLatem')].inner.bounds[0].trait_bound.trait.id" $sounds_good_id
pub trait DnabLatem: SoundsGood + VeryLoud {}
Loading