Skip to content

Commit 95c1e1e

Browse files
committed
Rustfmt stability
1 parent c80d43f commit 95c1e1e

File tree

1 file changed

+173
-10
lines changed

1 file changed

+173
-10
lines changed

stability/rustfmt.md

Lines changed: 173 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,200 @@
11
# Stability - rustfmt
22

3-
WIP
3+
This document enumerates areas where backwards compatibility could be a concern
4+
and some possible quality measures for Rustfmt. For background on what stability
5+
means for tools in general see [README.md](README.md).
46

5-
## Backwards compatability
7+
## Backwards compatibility
68

79
* Output of formatting
8-
- expected major changes soon due to style RFC process
10+
11+
I don't think we can promise 'no changes' without it preventing us fixing bugs.
12+
I think we can promise that there will be no changes which violate the RFC/spec.
13+
That would leave us some wriggle room in the ambiguities. It raises the question
14+
of what happens if we change the spec. I hope we finish the spec before Rustfmt
15+
1.0 and any changes after that (beyond 'bug fixes') are a breaking change for
16+
Rustfmt.
17+
18+
I think we should only make promises for the default options. No promises at all
19+
if you're using any non-default options.
20+
921
* Command line args (`rustfmt` and `cargo fmt`)
10-
* Accepted options in rustfmt.toml and their defaults
22+
23+
I think we need a notion of stable vs unstable arguments with the obvious back
24+
compat guarantees. Presumably, unstable arguments should only be usable on the
25+
nightly channel.
26+
27+
An important argument is the `write-mode` that Rustfmt operates in - this
28+
controls the output and what is done with it (overwrite files with or without
29+
backup, pipe to stdout, etc.). We should extend stability to these and promise
30+
that stable modes will not be removed, nor their operation changed.
31+
32+
The current default write mode is `replace` which leaves a backup, however,
33+
before stabilisation we should change to `overwrite`, which does not. We should
34+
then promise not to change the default again.
35+
36+
* exit codes
37+
38+
For stable modes, any change to the possible exit codes must be a breaking
39+
change. The same code should continue to give the same exit code.
40+
41+
* Configuration options in rustfmt.toml and their defaults
42+
43+
We promise not to remove options, but we can change their effect, including
44+
making them have no effect at all. We can deprecate options which means we stop
45+
documenting them and warn on use. Alternatively we could also allow removing
46+
options and not warn/error if using an unknown option.
47+
1148
* Library API
1249

50+
I would like to stabilise the public API of the Rustfmt crate with the usual
51+
meaning for a library. I'm not happy enough with the current API to do it right
52+
now though.
53+
54+
* skip attributes
55+
56+
Rustfmt can be made to skip sections using an attribute. I would prefer not to
57+
stabilise the attribute we use before we settle how custom attributes work
58+
(https://github.com/rust-lang/rfcs/pull/1755). However, I don't want to block
59+
stabilisation on this. If we get to 1.0 before the custom attributes RFC is
60+
decided, then we'll just support all supported attributes forever.
61+
62+
* warnings
63+
64+
Rustfmt gives warnings on overlong lines and trailing whitespace it can't fix,
65+
and could add other warnings. These trigger a failing exit code in some modes. I
66+
think we must promise not to add or remove warnings without opt-in of some kind.
67+
1368

1469
## Quality
1570

1671
### Bugs vs formatting errors
1772

18-
Classify a bug as crashing rustfmt or producing code which fails to compile, or compiles but has different semantics from the source.
73+
We classify a bug as crashing Rustfmt or producing code which fails to compile,
74+
or compiles but has different semantics from the source.
75+
76+
Formatting errors are where Rustfmt succeeds, but produces code which does not
77+
match the RFC style guide or exceeds the width guide (with the exception of
78+
comments or string literals, or exceptional situations such as very long
79+
identifier names).
80+
81+
82+
#### Comments and multi-line strings
83+
84+
Currently, comments and string literals are only formatted when some non-default
85+
options are set. Ideally we would format these things, but in practice there is
86+
often semantic info in their formatting and Rustfmt screws it up. It's not clear
87+
if there is a better compromise than the current 'do as little as possible'
88+
approach.
89+
90+
A second issue is that due to the nature of the AST (and architecture of
91+
Rustfmt) we sometimes miss and thus erase comments in certain positions. Fixing
92+
this will take either a rewrite of Rustfmt, a rewrite of libsyntax, or using a
93+
different parser and AST (which would effectively mean a rewrite of both). I
94+
don't think this is going to happen, and yet this is a major flaw in Rustfmt
95+
right now.
96+
97+
I think we can make no promises about which comments we preserve since that
98+
depends on libsyntax which is perma-unstable.
1999

20-
Formatting errors are where Rustfmt succeeds, but produces code which does not match the RFC style guide or exceeds the width guide (with the exception of comments or string literals, or exceptional situation such as very long identifier names).
21100

22101
### Performance
23102

24-
How long does Rustfmt take to run on large codebases
103+
How long does Rustfmt take to run on large code bases? It is currently a bit
104+
slow. I don't think this is a problem for users except on very large projects
105+
(Servo or rustc scale).
106+
107+
I don't think this should block any milestone, but we should keep an eye on it
108+
and collect some data.
109+
25110

26111
### Testing
27112

28-
run on large test projects, e.g., the Rust repo
113+
I've found running on large projects (e.g., Rust) to be a good stress test. I
114+
haven't done this for a while and doing this again should probably block a 1.0
115+
announcement.
116+
117+
Rustfmt's test suite is fairly comprehensive, but is not well-organised. I don't
118+
think there are any blocking issues there.
29119

30-
Rustfmt's test suite
31120

32121
### Customisability
33122

34-
For which options do we apply the quality measures
123+
For which options do we apply the quality measures? I'm inclined to only care
124+
about the defaults and to be explicit about this. I think we need to ensure that
125+
we are offering the right set of options and none of them are too buggy. I don't
126+
think there is any hope of ensuring quality for all combinations of options.
127+
128+
129+
### Unicode wide char support
130+
131+
Rustfmt is currently not great with unicode - we use `byte`s in a bunch of
132+
places we should use `char`s. I believe this won't cause us to crash anywhere,
133+
but it will mean sub-optimal formatting and perhaps incorrect line-length
134+
checks.
135+
136+
137+
### Other important issues
138+
139+
* range support (important for IDEs, not so much for command line editors)
140+
* warnings for skipped sections (i.e., if a section is skipped, should we warn
141+
on over-long lines, etc.?)
35142

36143

37144
## milestones
145+
146+
### Inclusion with 'Rust product'
147+
148+
* agree on stability criteria
149+
150+
151+
### stable channel
152+
153+
* tests running and passing on CI
154+
* overwrite mode by default
155+
* implement stable/unstable command line arguments
156+
* resolve 'warnings for skipped sections'
157+
158+
159+
### stable
160+
161+
* audit command line options
162+
* audit config options
163+
* RFC style fully implemented
164+
* audit exit codes
165+
* TBD - bugs, performance (at least collect data), skip attributes
166+
* Library API is stablised
167+
168+
169+
## Appendix - Rustfmt options and exit codes
170+
171+
```
172+
Options:
173+
-h, --help show this message
174+
-V, --version show version information
175+
-v, --verbose print verbose output
176+
--write-mode [replace|overwrite|display|diff|coverage|checkstyle]
177+
mode to write in (not usable when piping from stdin)
178+
--skip-children
179+
don't reformat child modules
180+
--config-help show details of rustfmt configuration options
181+
--dump-default-config PATH
182+
Dumps the default configuration to a file and exits.
183+
--dump-minimal-config PATH
184+
Dumps configuration options that were checked during
185+
formatting to a file.
186+
--config-path [Path for the configuration file]
187+
Recursively searches the given path for the
188+
rustfmt.toml config file. If not found reverts to the
189+
input file path
190+
--file-lines JSON
191+
Format specified line ranges. See README for more
192+
detail on the JSON format.
193+
194+
Exit Codes:
195+
0 = No errors
196+
1 = Encountered operational errors e.g. an IO error
197+
2 = Failed to reformat code because of parsing errors
198+
3 = Code is valid, but it is impossible to format it properly
199+
4 = Formatted code differs from existing code (write-mode diff only)
200+
```

0 commit comments

Comments
 (0)