Skip to content

Instantly share code, notes, and snippets.

@zackmdavis
Created August 12, 2018 04:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zackmdavis/839eb750fe3bd8152b0d5ec6faad87ea to your computer and use it in GitHub Desktop.
Save zackmdavis/839eb750fe3bd8152b0d5ec6faad87ea to your computer and use it in GitHub Desktop.
generate structs to exercise the explicit-outlives-requirements lint
import itertools
test = ""
signatures = set()
specs = []
def bound_type(bound):
if bound.startswith("'"):
return "lifetime"
else:
return "trait"
def bound_signature(location, bounds):
return (location, tuple(bound_type(bound) for bound in bounds))
def add_if_valid(spec):
has_lifetimes = False
for subspec in spec:
param_spec, bounds_spec = subspec
_param, position = param_spec
# empty where clause is illegal
if position == 'where' and not bounds_spec:
return
has_lifetimes |= any(bound.startswith("'") for bound in bounds_spec)
# We don't care about testing scenarios where none of the params have
# lifetimes
if has_lifetimes:
specs.append(spec)
for param_list in [[("T", 'inline')],
[("T", 'where')],
[("T", 'inline'), ("U", 'inline')],
[("T", 'inline'), ("U", 'where')],
[("T", 'where'), ("U", 'where')]]:
for lifetime_list in [[], ["'a"], ["'a", "'b"]]:
for trait_bound_list in [[], ["Debug"]]:
bounds = lifetime_list + trait_bound_list
if len(param_list) == 2:
for split in range(len(bounds)):
left = bounds[:split]
right = bounds[split:]
for left_order in itertools.permutations(left):
for right_order in itertools.permutations(right):
left_signature = bound_signature(param_list[0][1],
left_order)
right_signature = bound_signature(param_list[1][1],
right_order)
grand_signature = frozenset(
{left_signature, right_signature}
)
if grand_signature not in signatures:
signatures.add(grand_signature)
add_if_valid(
((param_list[0], left_order),
(param_list[1], right_order))
)
else:
for order in itertools.permutations(bounds):
signature = frozenset(
{bound_signature(param_list[0][1], order)}
)
if signature not in signatures:
signatures.add(signature)
add_if_valid(
((param_list[0], order),)
)
n = 0
def fab(spec):
lifetimes = []
params = []
for subspec in spec:
param_spec, bounds_spec = subspec
param, position = param_spec
params.append(param)
lifetimes.extend(
[bound for bound in bounds_spec if bound.startswith("'")]
)
inline_parts = lifetimes[:]
where_parts = []
body_parts = []
name = ""
for i, subspec in enumerate(spec):
param_spec, bounds_spec = subspec
param, position = param_spec
if position == 'inline':
if bounds_spec:
inline_parts.append(
"{}: {}".format(param, ' + '.join(bounds_spec))
)
else:
inline_parts.append(param)
elif position == 'where':
inline_parts.append(param)
where_parts.append("{}: {}".format(param, ' + '.join(bounds_spec)))
name += 'Tee' if param == 'T' else 'Yoo'
if position == 'where':
name += "Where"
for bound in bounds_spec:
if bound.startswith("'"):
name += "Outlives" + "Ay" if bound == "'a" else "Bee"
else:
name += "IsDebug"
param_lts = [bound for bound in bounds_spec if bound.startswith("'")]
if param_lts:
body_parts.append(
"{}: {} {}".format(
"tee" if param == 'T' else 'yoo',
' '.join("&{}".format(lt) for lt in param_lts),
param
)
)
else:
body_parts.append(
"{}: {}".format(
"tee" if param == 'T' else 'yoo',
param
)
)
global n
n += 1
print(inline_parts)
inline = ', '.join(inline_parts)
if where_parts:
where = "where " + ', '.join(where_parts)
else:
where = ""
err_tags = "//~^ ERROR outlives requirements can be inferred"
body = ',\n '.join(body_parts)
global test
test += """
struct {name}<{inline}> {where} {{
{err_tags}
{body}
}}""".format(**locals())
print(signatures)
print(specs)
print(len(signatures))
print(len(specs))
for spec in specs:
fab(spec)
print(test)
print(n)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment