]> git.proxmox.com Git - rustc.git/blame - src/etc/check_missing_items.py
New upstream version 1.61.0+dfsg1
[rustc.git] / src / etc / check_missing_items.py
CommitLineData
fc512014
XL
1#!/usr/bin/env python
2
3# This test ensures that every ID in the produced json actually resolves to an item either in
4# `index` or `paths`. It DOES NOT check that the structure of the produced json is actually in
5# any way correct, for example an empty map would pass.
6
5869c6ff
XL
7# FIXME: Better error output
8
fc512014
XL
9import sys
10import json
11
c295e0f8 12crate = json.load(open(sys.argv[1], encoding="utf-8"))
fc512014
XL
13
14
15def get_local_item(item_id):
16 if item_id in crate["index"]:
17 return crate["index"][item_id]
18 print("Missing local ID:", item_id)
19 sys.exit(1)
20
21
22# local IDs have to be in `index`, external ones can sometimes be in `index` but otherwise have
23# to be in `paths`
24def valid_id(item_id):
25 return item_id in crate["index"] or item_id[0] != "0" and item_id in crate["paths"]
26
27
28def check_generics(generics):
29 for param in generics["params"]:
30 check_generic_param(param)
31 for where_predicate in generics["where_predicates"]:
32 if "bound_predicate" in where_predicate:
33 pred = where_predicate["bound_predicate"]
ee023bcb 34 check_type(pred["type"])
fc512014
XL
35 for bound in pred["bounds"]:
36 check_generic_bound(bound)
37 elif "region_predicate" in where_predicate:
38 pred = where_predicate["region_predicate"]
39 for bound in pred["bounds"]:
40 check_generic_bound(bound)
41 elif "eq_predicate" in where_predicate:
42 pred = where_predicate["eq_predicate"]
43 check_type(pred["rhs"])
44 check_type(pred["lhs"])
45
46
47def check_generic_param(param):
48 if "type" in param["kind"]:
49 ty = param["kind"]["type"]
50 if ty["default"]:
51 check_type(ty["default"])
52 for bound in ty["bounds"]:
53 check_generic_bound(bound)
54 elif "const" in param["kind"]:
55 check_type(param["kind"]["const"])
56
57
58def check_generic_bound(bound):
59 if "trait_bound" in bound:
60 for param in bound["trait_bound"]["generic_params"]:
61 check_generic_param(param)
62 check_type(bound["trait_bound"]["trait"])
63
64
65def check_decl(decl):
66 for (_name, ty) in decl["inputs"]:
67 check_type(ty)
68 if decl["output"]:
69 check_type(decl["output"])
70
71
72def check_type(ty):
73 if ty["kind"] == "resolved_path":
74 for bound in ty["inner"]["param_names"]:
75 check_generic_bound(bound)
76 args = ty["inner"]["args"]
77 if args:
78 if "angle_bracketed" in args:
79 for arg in args["angle_bracketed"]["args"]:
80 if "type" in arg:
81 check_type(arg["type"])
82 elif "const" in arg:
83 check_type(arg["const"]["type"])
84 for binding in args["angle_bracketed"]["bindings"]:
85 if "equality" in binding["binding"]:
5099ac24
FG
86 term = binding["binding"]["equality"]
87 if "type" in term: check_type(term["type"])
88 elif "const" in term: check_type(term["const"])
fc512014
XL
89 elif "constraint" in binding["binding"]:
90 for bound in binding["binding"]["constraint"]:
91 check_generic_bound(bound)
92 elif "parenthesized" in args:
93 for ty in args["parenthesized"]["inputs"]:
94 check_type(ty)
95 if args["parenthesized"]["output"]:
96 check_type(args["parenthesized"]["output"])
97 if not valid_id(ty["inner"]["id"]):
98 print("Type contained an invalid ID:", ty["inner"]["id"])
99 sys.exit(1)
100 elif ty["kind"] == "tuple":
101 for ty in ty["inner"]:
102 check_type(ty)
103 elif ty["kind"] == "slice":
104 check_type(ty["inner"])
105 elif ty["kind"] == "impl_trait":
106 for bound in ty["inner"]:
107 check_generic_bound(bound)
108 elif ty["kind"] in ("raw_pointer", "borrowed_ref", "array"):
109 check_type(ty["inner"]["type"])
110 elif ty["kind"] == "function_pointer":
111 for param in ty["inner"]["generic_params"]:
112 check_generic_param(param)
6a06907d 113 check_decl(ty["inner"]["decl"])
fc512014
XL
114 elif ty["kind"] == "qualified_path":
115 check_type(ty["inner"]["self_type"])
116 check_type(ty["inner"]["trait"])
117
118
119work_list = set([crate["root"]])
120visited = work_list.copy()
121
122while work_list:
123 current = work_list.pop()
124 visited.add(current)
125 item = get_local_item(current)
126 # check intradoc links
127 for (_name, link) in item["links"].items():
128 if not valid_id(link):
129 print("Intra-doc link contains invalid ID:", link)
130
131 # check all fields that reference types such as generics as well as nested items
132 # (modules, structs, traits, and enums)
133 if item["kind"] == "module":
134 work_list |= set(item["inner"]["items"]) - visited
135 elif item["kind"] == "struct":
136 check_generics(item["inner"]["generics"])
137 work_list |= (
138 set(item["inner"]["fields"]) | set(item["inner"]["impls"])
139 ) - visited
140 elif item["kind"] == "struct_field":
141 check_type(item["inner"])
142 elif item["kind"] == "enum":
143 check_generics(item["inner"]["generics"])
144 work_list |= (
145 set(item["inner"]["variants"]) | set(item["inner"]["impls"])
146 ) - visited
147 elif item["kind"] == "variant":
148 if item["inner"]["variant_kind"] == "tuple":
149 for ty in item["inner"]["variant_inner"]:
150 check_type(ty)
151 elif item["inner"]["variant_kind"] == "struct":
152 work_list |= set(item["inner"]["variant_inner"]) - visited
153 elif item["kind"] in ("function", "method"):
154 check_generics(item["inner"]["generics"])
155 check_decl(item["inner"]["decl"])
156 elif item["kind"] in ("static", "constant", "assoc_const"):
157 check_type(item["inner"]["type"])
158 elif item["kind"] == "typedef":
159 check_type(item["inner"]["type"])
160 check_generics(item["inner"]["generics"])
161 elif item["kind"] == "opaque_ty":
162 check_generics(item["inner"]["generics"])
163 for bound in item["inner"]["bounds"]:
164 check_generic_bound(bound)
165 elif item["kind"] == "trait_alias":
166 check_generics(item["inner"]["params"])
167 for bound in item["inner"]["bounds"]:
168 check_generic_bound(bound)
169 elif item["kind"] == "trait":
170 check_generics(item["inner"]["generics"])
171 for bound in item["inner"]["bounds"]:
172 check_generic_bound(bound)
173 work_list |= (
ee023bcb 174 set(item["inner"]["items"]) | set(item["inner"]["implementations"])
fc512014
XL
175 ) - visited
176 elif item["kind"] == "impl":
177 check_generics(item["inner"]["generics"])
178 if item["inner"]["trait"]:
179 check_type(item["inner"]["trait"])
180 if item["inner"]["blanket_impl"]:
181 check_type(item["inner"]["blanket_impl"])
182 check_type(item["inner"]["for"])
183 for assoc_item in item["inner"]["items"]:
184 if not valid_id(assoc_item):
185 print("Impl block referenced a missing ID:", assoc_item)
186 sys.exit(1)
187 elif item["kind"] == "assoc_type":
188 for bound in item["inner"]["bounds"]:
189 check_generic_bound(bound)
190 if item["inner"]["default"]:
191 check_type(item["inner"]["default"])