Skip to content
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

Rollup of 6 pull requests #110990

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
42 changes: 31 additions & 11 deletions compiler/rustc_arena/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#![feature(rustc_attrs)]
#![cfg_attr(test, feature(test))]
#![feature(strict_provenance)]
#![deny(unsafe_op_in_unsafe_fn)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#![allow(clippy::mut_from_ref)] // Arena allocators are one of the places where this pattern is fine.
Expand Down Expand Up @@ -74,19 +75,27 @@ impl<T> ArenaChunk<T> {
#[inline]
unsafe fn new(capacity: usize) -> ArenaChunk<T> {
ArenaChunk {
storage: NonNull::new_unchecked(Box::into_raw(Box::new_uninit_slice(capacity))),
storage: NonNull::from(Box::leak(Box::new_uninit_slice(capacity))),
entries: 0,
}
}

/// Destroys this arena chunk.
///
/// # Safety
///
/// The caller must ensure that `len` elements of this chunk have been initialized.
#[inline]
unsafe fn destroy(&mut self, len: usize) {
// The branch on needs_drop() is an -O1 performance optimization.
// Without the branch, dropping TypedArena<u8> takes linear time.
// Without the branch, dropping TypedArena<T> takes linear time.
if mem::needs_drop::<T>() {
let slice = self.storage.as_mut();
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len]));
// SAFETY: The caller must ensure that `len` elements of this chunk have
// been initialized.
unsafe {
let slice = self.storage.as_mut();
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len]));
}
}
}

Expand Down Expand Up @@ -255,7 +264,9 @@ impl<T> TypedArena<T> {
self.ensure_capacity(len);

let start_ptr = self.ptr.get();
self.ptr.set(start_ptr.add(len));
// SAFETY: `self.ensure_capacity` makes sure that there is enough space
// for `len` elements.
unsafe { self.ptr.set(start_ptr.add(len)) };
start_ptr
}

Expand Down Expand Up @@ -483,6 +494,10 @@ impl DroplessArena {
}
}

/// # Safety
///
/// The caller must ensure that `mem` is valid for writes up to
/// `size_of::<T>() * len`.
#[inline]
unsafe fn write_from_iter<T, I: Iterator<Item = T>>(
&self,
Expand All @@ -494,13 +509,18 @@ impl DroplessArena {
// Use a manual loop since LLVM manages to optimize it better for
// slice iterators
loop {
let value = iter.next();
if i >= len || value.is_none() {
// We only return as many items as the iterator gave us, even
// though it was supposed to give us `len`
return slice::from_raw_parts_mut(mem, i);
// SAFETY: The caller must ensure that `mem` is valid for writes up to
// `size_of::<T>() * len`.
unsafe {
match iter.next() {
Some(value) if i < len => mem.add(i).write(value),
Some(_) | None => {
// We only return as many items as the iterator gave us, even
// though it was supposed to give us `len`
return slice::from_raw_parts_mut(mem, i);
}
}
}
ptr::write(mem.add(i), value.unwrap());
i += 1;
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ where
is_private_dep: false,
add_prelude: true,
nounused_dep: false,
force: false,
}
}

Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_metadata/src/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,17 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
}
}

fn inject_forced_externs(&mut self) {
for (name, entry) in self.sess.opts.externs.iter() {
if entry.force {
let name_interned = Symbol::intern(name);
if !self.used_extern_options.contains(&name_interned) {
self.resolve_crate(name_interned, DUMMY_SP, CrateDepKind::Explicit);
}
}
}
}

fn inject_dependency_if(
&self,
krate: CrateNum,
Expand Down Expand Up @@ -913,7 +924,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
// Don't worry about pathless `--extern foo` sysroot references
continue;
}
if entry.nounused_dep {
if entry.nounused_dep || entry.force {
// We're not worried about this one
continue;
}
Expand Down Expand Up @@ -942,6 +953,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
}

pub fn postprocess(&mut self, krate: &ast::Crate) {
self.inject_forced_externs();
self.inject_profiler_runtime(krate);
self.inject_allocator_crate(krate);
self.inject_panic_runtime(krate);
Expand Down
18 changes: 17 additions & 1 deletion compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,12 @@ pub struct ExternEntry {
/// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to
/// suppress `unused-crate-dependencies` warnings.
pub nounused_dep: bool,
/// If the extern entry is not referenced in the crate, force it to be resolved anyway.
///
/// Allows a dependency satisfying, for instance, a missing panic handler to be injected
/// without modifying source:
/// `--extern force:extras=/path/to/lib/libstd.rlib`
pub force: bool,
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -556,7 +562,13 @@ impl Externs {

impl ExternEntry {
fn new(location: ExternLocation) -> ExternEntry {
ExternEntry { location, is_private_dep: false, add_prelude: false, nounused_dep: false }
ExternEntry {
location,
is_private_dep: false,
add_prelude: false,
nounused_dep: false,
force: false,
}
}

pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
Expand Down Expand Up @@ -2236,6 +2248,7 @@ pub fn parse_externs(
let mut is_private_dep = false;
let mut add_prelude = true;
let mut nounused_dep = false;
let mut force = false;
if let Some(opts) = options {
if !is_unstable_enabled {
early_error(
Expand All @@ -2258,6 +2271,7 @@ pub fn parse_externs(
}
}
"nounused" => nounused_dep = true,
"force" => force = true,
_ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
}
}
Expand All @@ -2268,6 +2282,8 @@ pub fn parse_externs(
entry.is_private_dep |= is_private_dep;
// likewise `nounused`
entry.nounused_dep |= nounused_dep;
// and `force`
entry.force |= force;
// If any flag is missing `noprelude`, then add to the prelude.
entry.add_prelude |= add_prelude;
}
Expand Down
35 changes: 29 additions & 6 deletions src/bootstrap/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
except ImportError:
lzma = None

if sys.platform == 'win32':
def platform_is_win32():
return sys.platform == 'win32'

if platform_is_win32():
EXE_SUFFIX = ".exe"
else:
EXE_SUFFIX = ""
Expand Down Expand Up @@ -78,15 +81,14 @@ def _download(path, url, probably_big, verbose, exception):
if probably_big or verbose:
print("downloading {}".format(url))

platform_is_win32 = sys.platform == 'win32'
try:
if probably_big or verbose:
option = "-#"
else:
option = "-s"
# If curl is not present on Win32, we should not sys.exit
# but raise `CalledProcessError` or `OSError` instead
require(["curl", "--version"], exception=platform_is_win32)
require(["curl", "--version"], exception=platform_is_win32())
with open(path, "wb") as outfile:
run(["curl", option,
"-L", # Follow redirect.
Expand All @@ -99,8 +101,8 @@ def _download(path, url, probably_big, verbose, exception):
)
except (subprocess.CalledProcessError, OSError, RuntimeError):
# see http://serverfault.com/questions/301128/how-to-download
if platform_is_win32:
run(["PowerShell.exe", "/nologo", "-Command",
if platform_is_win32():
run_powershell([
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;",
"(New-Object System.Net.WebClient).DownloadFile('{}', '{}')".format(url, path)],
verbose=verbose,
Expand Down Expand Up @@ -174,6 +176,10 @@ def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs):
else:
sys.exit(err)

def run_powershell(script, *args, **kwargs):
"""Run a powershell script"""
run(["PowerShell.exe", "/nologo", "-Command"] + script, *args, **kwargs)


def require(cmd, exit=True, exception=False):
'''Run a command, returning its output.
Expand Down Expand Up @@ -229,7 +235,7 @@ def default_build_triple(verbose):
print("pre-installed rustc not detected: {}".format(e))
print("falling back to auto-detect")

required = sys.platform != 'win32'
required = not platform_is_win32()
ostype = require(["uname", "-s"], exit=required)
cputype = require(['uname', '-m'], exit=required)

Expand Down Expand Up @@ -434,6 +440,23 @@ def download_toolchain(self):
(not os.path.exists(self.rustc()) or
self.program_out_of_date(self.rustc_stamp(), key)):
if os.path.exists(bin_root):
# HACK: On Windows, we can't delete rust-analyzer-proc-macro-server while it's
# running. Kill it.
if platform_is_win32():
print("Killing rust-analyzer-proc-macro-srv before deleting stage0 toolchain")
regex = '{}\\\\(host|{})\\\\stage0\\\\libexec'.format(
os.path.basename(self.build_dir),
self.build
)
script = (
# NOTE: can't use `taskkill` or `Get-Process -Name` because they error if
# the server isn't running.
'Get-Process | ' +
'Where-Object {$_.Name -eq "rust-analyzer-proc-macro-srv"} |' +
'Where-Object {{$_.Path -match "{}"}} |'.format(regex) +
'Stop-Process'
)
run_powershell([script])
shutil.rmtree(bin_root)
tarball_suffix = '.tar.gz' if lzma is None else '.tar.xz'
filename = "rust-std-{}-{}{}".format(
Expand Down
38 changes: 38 additions & 0 deletions src/doc/rustdoc/src/lints.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,3 +374,41 @@ warning: this URL is not a hyperlink

warning: 2 warnings emitted
```

## `unescaped_backticks`

This lint is **allowed by default**. It detects backticks (\`) that are not escaped.
This usually means broken inline code. For example:

```rust
#![warn(rustdoc::unescaped_backticks)]

/// `add(a, b) is the same as `add(b, a)`.
pub fn add(a: i32, b: i32) -> i32 { a + b }
```

Which will give:

```text
warning: unescaped backtick
--> src/lib.rs:3:41
|
3 | /// `add(a, b) is the same as `add(b, a)`.
| ^
|
note: the lint level is defined here
--> src/lib.rs:1:9
|
1 | #![warn(rustdoc::unescaped_backticks)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: a previous inline code might be longer than expected
|
3 | /// `add(a, b)` is the same as `add(b, a)`.
| +
help: if you meant to use a literal backtick, escape it
|
3 | /// `add(a, b) is the same as `add(b, a)\`.
| +

warning: 1 warning emitted
```
18 changes: 12 additions & 6 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1155,10 +1155,10 @@ fn render_assoc_items_inner(
let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
if !non_trait.is_empty() {
let mut tmp_buf = Buffer::html();
let (render_mode, id) = match what {
let (render_mode, id, class_html) = match what {
AssocItemRender::All => {
write_impl_section_heading(&mut tmp_buf, "Implementations", "implementations");
(RenderMode::Normal, "implementations-list".to_owned())
(RenderMode::Normal, "implementations-list".to_owned(), "")
}
AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
let id =
Expand All @@ -1175,7 +1175,11 @@ fn render_assoc_items_inner(
),
&id,
);
(RenderMode::ForDeref { mut_: deref_mut_ }, cx.derive_id(id))
(
RenderMode::ForDeref { mut_: deref_mut_ },
cx.derive_id(id),
r#" class="impl-items""#,
)
}
};
let mut impls_buf = Buffer::html();
Expand All @@ -1199,7 +1203,7 @@ fn render_assoc_items_inner(
}
if !impls_buf.is_empty() {
write!(w, "{}", tmp_buf.into_inner()).unwrap();
write!(w, "<div id=\"{}\">", id).unwrap();
write!(w, "<div id=\"{id}\"{class_html}>").unwrap();
write!(w, "{}", impls_buf.into_inner()).unwrap();
w.write_str("</div>").unwrap();
}
Expand Down Expand Up @@ -1788,12 +1792,14 @@ fn render_impl(
.into_string()
);
}
if !default_impl_items.is_empty() || !impl_items.is_empty() {
w.write_str("<div class=\"impl-items\">");
close_tags.insert_str(0, "</div>");
}
}
if !default_impl_items.is_empty() || !impl_items.is_empty() {
w.write_str("<div class=\"impl-items\">");
w.push_buffer(default_impl_items);
w.push_buffer(impl_items);
close_tags.insert_str(0, "</div>");
}
w.write_str(&close_tags);
}
Expand Down
11 changes: 6 additions & 5 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(drain_filter)]
#![feature(impl_trait_in_assoc_type)]
#![feature(iter_intersperse)]
#![feature(lazy_cell)]
#![feature(let_chains)]
#![feature(test)]
#![feature(never_type)]
#![feature(lazy_cell)]
#![feature(type_ascription)]
#![feature(iter_intersperse)]
#![feature(round_char_boundary)]
#![feature(test)]
#![feature(type_alias_impl_trait)]
#![feature(impl_trait_in_assoc_type)]
#![feature(type_ascription)]
#![recursion_limit = "256"]
#![warn(rustc::internal)]
#![allow(clippy::collapsible_if, clippy::collapsible_else_if)]
Expand Down
Loading