Fix `unused_parens` triggers on macro by example code
Fix#66295
Unfortunately this does also break [an existing test](4787e97475/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs (L22)). I'm not sure how to handle that, because that seems to be quite similar to the allowed cases
If this gets accepted it would be great to backport this fix to beta.
Add by-value arrays to `improper_ctypes` lint
Hi,
C doesn't have a notion of passing arrays by value, only by reference/pointer.
Rust currently will pass it correctly by reference by it looks very misleading, and can confuse the borrow checker to think a move had occurred.
Fixes#58905 and fixes#24578.
We could also improve the borrow checker here but I think it's kinda a waste of work if we instead just tell the user it's an invalid FFI call.
(My first PR to `rustc` so if I missed some test or formatting guideline please tell me :) )
Move error codes
Works towards #66210.
r? @Centril
Oh btw, for the ones interested, I used this python script to get all error codes content sorted into one final file:
<details>
```python
from os import listdir
from os.path import isdir, isfile, join
def get_error_codes(error_codes, f_path):
with open(f_path) as f:
short_mode = False
lines = f.read().split("\n")
i = 0
while i < len(lines):
line = lines[i]
if not short_mode and line.startswith("E0") and line.endswith(": r##\""):
error = line
error += "\n"
i += 1
while i < len(lines):
line = lines[i]
error += line
if line.endswith("\"##,"):
break
error += "\n"
i += 1
error_codes["long"].append(error)
elif line == ';':
short_mode = True
elif short_mode is True and len(line) > 0 and line != "}":
error_codes["short"].append(line)
while i + 1 < len(lines):
line = lines[i + 1].strip()
if not line.startswith("//"):
break
parts = line.split("//")
if len(parts) < 2:
break
if parts[1].strip().startswith("E0"):
break
error_codes["short"][-1] += "\n"
error_codes["short"][-1] += lines[i + 1]
i += 1
i += 1
def loop_dirs(error_codes, cur_dir):
for entry in listdir(cur_dir):
f = join(cur_dir, entry)
if isfile(f) and entry == "error_codes.rs":
get_error_codes(error_codes, f)
elif isdir(f) and not entry.startswith("librustc_error_codes"):
loop_dirs(error_codes, f)
def get_error_code(err):
x = err.split(",")
if len(x) < 2:
return err
x = x[0]
if x.strip().startswith("//"):
x = x.split("//")[1].strip()
return x.strip()
def write_into_file(error_codes, f_path):
with open(f_path, "w") as f:
f.write("// Error messages for EXXXX errors. Each message should start and end with a\n")
f.write("// new line, and be wrapped to 80 characters. In vim you can `:set tw=80` and\n")
f.write("// use `gq` to wrap paragraphs. Use `:set tw=0` to disable.\n\n")
f.write("syntax::register_diagnostics! {\n\n")
error_codes["long"].sort()
for i in error_codes["long"]:
f.write(i)
f.write("\n\n")
f.write(";\n")
error_codes["short"] = sorted(error_codes["short"], key=lambda err: get_error_code(err))
for i in error_codes["short"]:
f.write(i)
f.write("\n")
f.write("}\n")
error_codes = {
"long": [],
"short": []
}
loop_dirs(error_codes, "src")
write_into_file(error_codes, "src/librustc_error_codes/src/error_codes.rs")
```
</details>
And to move the error codes into their own files:
<details>
```python
import os
try:
os.mkdir("src/librustc_error_codes/error_codes")
except OSError:
print("Seems like folder already exist, moving on!")
data = ''
with open("src/librustc_error_codes/error_codes.rs") as f:
x = f.read().split('\n')
i = 0
short_part = False
while i < len(x):
line = x[i]
if short_part is False and line.startswith('E0') and line.endswith(': r##"'):
err_code = line.split(':')[0]
i += 1
content = ''
while i < len(x):
if x[i] == '"##,':
break
content += x[i]
content += '\n'
i += 1
f_path = "src/librustc_error_codes/error_codes/{}.md".format(err_code)
with open(f_path, "w") as ff:
ff.write(content)
data += '{}: include_str!("./error_codes/{}.md"),'.format(err_code, err_code)
elif short_part is False and line == ';':
short_part is True
data += ';\n'
else:
data += line
data += '\n'
i += 1
with open("src/librustc_error_codes/error_codes.rs", "w") as f:
f.write(data)
```
</details>
invalid_value lint: use diagnostic items
This adjusts the invalid_value lint to use diagnostic items.
@Centril @oli-obk For some reason, this fails to recognize `transmute` -- somehow the diagnostic item is not found. Any idea why?
r? @Centril
Cc https://github.com/rust-lang/rust/issues/66075
invalid_value lint: fix help text
Now that we also warn about `MaybUninit::uninit().assume_init()`, just telling people "use `MaybeUninit`" isn't always sufficient. And anyway this seems like an important enough point to mention it here.
Add future incompatibility lint for `array.into_iter()`
This is for #65819. This lint warns when calling `into_iter` on an array directly. That's because today the method call resolves to `<&[T] as IntoIterator>::into_iter` but that would change when adding `IntoIterator` impls for arrays. This problem is discussed in detail in #65819.
We still haven't decided how to proceed exactly, but it seems like adding a lint is a good idea regardless?
Also: this is the first time I implement a lint, so there are probably a lot of things I can improve. I used a different strategy than @scottmcm describes [here](https://github.com/rust-lang/rust/pull/65819#issuecomment-548667847) since I already started implementing this before they commented.
### TODO
- [x] Decide if we want this lint -> apparently [we want](https://github.com/rust-lang/rust/pull/65819#issuecomment-548964818)
- [x] Open a lint-tracking-issue and add the correct issue number in the code -> https://github.com/rust-lang/rust/issues/66145
syntax: ABI-oblivious grammar
This PR has the following effects:
1. `extern $lit` is now legal where `$lit:literal` and `$lit` is substituted for a string literal.
2. `extern "abi_that_does_not_exist"` is now *syntactically* legal whereas before, the set of ABI strings was hard-coded into the grammar of the language. With this PR, the set of ABIs are instead validated and translated during lowering. That seems more appropriate.
3. `ast::FloatTy` is now distinct from `rustc_target::abi::FloatTy`. The former is used substantially more and the translation between them is only necessary in a single place.
4. As a result of 2-3, libsyntax no longer depends on librustc_target, which should improve pipe-lining somewhat.
cc @rust-lang/lang -- the points 1-2 slightly change the definition of the language but in a way which seems consistent with our general principles (in particular wrt. the discussions of turning things into semantic errors). I expect this to be uncontroversial but it's worth letting y'all know. :)
r? @varkor
We also sever syntax's dependency on rustc_target as a result.
This should slightly improve pipe-lining.
Moreover, some cleanup is done in related code.
Improve uninit/zeroed lint
* Also warn when creating a raw pointer with a NULL vtable.
* Also identify `MaybeUninit::uninit().assume_init()` and `MaybeUninit::zeroed().assume_init()` as dangerous.
Cheaper doc comments
This PR implements the idea from #60935: represent doc comments more cheaply, rather than converting them into `#[doc="..."]` attribute form. Unlike #60936 (which is about coalescing doc comments to reduce their number), this approach does not have any backwards compatibility concerns, and it eliminates about 80-90% of the current cost of doc comments (as estimated using the numbers in #60930, which eliminated the cost of doc comments entirely by treating them as normal comments).
r? @petrochenkov
As we might want to add `IntoIterator` impls for arrays in the future,
and since that introduces a breaking change, this lint warns and
suggests using `iter()` instead (which is shorter and more explicit).