Skip to content

Commit

Permalink
Auto merge of rust-lang#93457 - matthiaskrgr:rollup-e43ry1l, r=matthi…
Browse files Browse the repository at this point in the history
…askrgr

Rollup of 8 pull requests

Successful merges:

 - rust-lang#88205 (Add Explanation For Error E0772)
 - rust-lang#92274 (Add `intrinsics::const_deallocate`)
 - rust-lang#93236 (Make `NonNull::new` `const`)
 - rust-lang#93299 (Fix dot separator when there is no source link)
 - rust-lang#93410 (kmc-solid: Implement `net::FileDesc::duplicate`)
 - rust-lang#93424 (fix nit)
 - rust-lang#93431 (remove unused `jemallocator` crate)
 - rust-lang#93453 (Add GUI theme change test)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jan 29, 2022
2 parents d08e816 + d62b414 commit a00e130
Show file tree
Hide file tree
Showing 33 changed files with 437 additions and 30 deletions.
11 changes: 0 additions & 11 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3319,7 +3319,6 @@ dependencies = [
"rustc_codegen_ssa",
"rustc_driver",
"tikv-jemalloc-sys",
"tikv-jemallocator",
]

[[package]]
Expand Down Expand Up @@ -5164,16 +5163,6 @@ dependencies = [
"libc",
]

[[package]]
name = "tikv-jemallocator"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c14a5a604eb8715bc5785018a37d00739b180bcf609916ddf4393d33d49ccdf"
dependencies = [
"libc",
"tikv-jemalloc-sys",
]

[[package]]
name = "time"
version = "0.1.43"
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,7 @@ version = '0.4.0'
optional = true
features = ['unprefixed_malloc_on_supported_platforms']

[dependencies.tikv-jemallocator]
version = '0.4.0'
optional = true

[features]
jemalloc = ['tikv-jemalloc-sys', 'tikv-jemallocator']
jemalloc = ['tikv-jemalloc-sys']
llvm = ['rustc_driver/llvm']
max_level_info = ['rustc_driver/max_level_info']
10 changes: 10 additions & 0 deletions compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}

sym::const_allocate => {
// returns a null pointer at runtime.
bx.const_null(bx.type_i8p())
}

sym::const_deallocate => {
// nop at runtime.
return;
}

// This requires that atomic intrinsics follow a specific naming pattern:
// "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
name if name_str.starts_with("atomic_") => {
Expand Down
27 changes: 27 additions & 0 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,33 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
)?;
ecx.write_pointer(ptr, dest)?;
}
sym::const_deallocate => {
let ptr = ecx.read_pointer(&args[0])?;
let size = ecx.read_scalar(&args[1])?.to_machine_usize(ecx)?;
let align = ecx.read_scalar(&args[2])?.to_machine_usize(ecx)?;

let size = Size::from_bytes(size);
let align = match Align::from_bytes(align) {
Ok(a) => a,
Err(err) => throw_ub_format!("align has to be a power of 2, {}", err),
};

// If an allocation is created in an another const,
// we don't deallocate it.
let (alloc_id, _, _) = ecx.memory.ptr_get_alloc(ptr)?;
let is_allocated_in_another_const = matches!(
ecx.tcx.get_global_alloc(alloc_id),
Some(interpret::GlobalAlloc::Memory(_))
);

if !is_allocated_in_another_const {
ecx.memory.deallocate(
ptr,
Some((size, align)),
interpret::MemoryKind::Machine(MemoryKind::Heap),
)?;
}
}
_ => {
return Err(ConstEvalErrKind::NeedsRfc(format!(
"calling intrinsic `{}`",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ E0768: include_str!("./error_codes/E0768.md"),
E0769: include_str!("./error_codes/E0769.md"),
E0770: include_str!("./error_codes/E0770.md"),
E0771: include_str!("./error_codes/E0771.md"),
E0772: include_str!("./error_codes/E0772.md"),
E0773: include_str!("./error_codes/E0773.md"),
E0774: include_str!("./error_codes/E0774.md"),
E0775: include_str!("./error_codes/E0775.md"),
Expand Down Expand Up @@ -642,5 +643,4 @@ E0787: include_str!("./error_codes/E0787.md"),
// E0723, // unstable feature in `const` context
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
E0772, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
}
89 changes: 89 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0772.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
A trait object has some specific lifetime `'1`, but it was used in a way that
requires it to have a `'static` lifetime.

Example of erroneous code:

```compile_fail,E0772
trait BooleanLike {}
trait Person {}
impl BooleanLike for bool {}
impl dyn Person {
fn is_cool(&self) -> bool {
// hey you, you're pretty cool
true
}
}
fn get_is_cool<'p>(person: &'p dyn Person) -> impl BooleanLike {
// error: `person` has an anonymous lifetime `'p` but calling
// `print_cool_fn` introduces an implicit `'static` lifetime
// requirement
person.is_cool()
}
```

The trait object `person` in the function `get_is_cool`, while already being
behind a reference with lifetime `'p`, also has it's own implicit lifetime,
`'2`.

Lifetime `'2` represents the data the trait object might hold inside, for
example:

```
trait MyTrait {}
struct MyStruct<'a>(&'a i32);
impl<'a> MyTrait for MyStruct<'a> {}
```

With this scenario, if a trait object of `dyn MyTrait + '2` was made from
`MyStruct<'a>`, `'a` must live as long, if not longer than `'2`. This allows the
trait object's internal data to be accessed safely from any trait methods. This
rule also goes for any lifetime any struct made into a trait object may have.

In the implementation for `dyn Person`, the `'2` lifetime representing the
internal data was ommitted, meaning that the compiler inferred the lifetime
`'static`. As a result, the implementation's `is_cool` is inferred by the
compiler to look like this:

```
# trait Person {}
#
# impl dyn Person {
fn is_cool<'a>(self: &'a (dyn Person + 'static)) -> bool {unimplemented!()}
# }
```

While the `get_is_cool` function is inferred to look like this:

```
# trait Person {}
# trait BooleanLike {}
#
fn get_is_cool<'p, R: BooleanLike>(person: &'p (dyn Person + 'p)) -> R {
unimplemented!()
}
```

Which brings us to the core of the problem; the assignment of type
`&'_ (dyn Person + '_)` to type `&'_ (dyn Person + 'static)` is impossible.

Fixing it is as simple as being generic over lifetime `'2`, as to prevent the
compiler from inferring it as `'static`:

```
# trait Person {}
#
impl<'d> dyn Person + 'd {/* ... */}
// This works too, and is more elegant:
//impl dyn Person + '_ {/* ... */}
```

See the [Rust Reference on Trait Object Lifetime Bounds][trait-objects] for
more information on trait object lifetimes.

[trait-object-lifetime-bounds]: https://doc.rust-lang.org/reference/types/trait-object.html#trait-object-lifetime-bounds
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1810,7 +1810,7 @@ impl<'tcx> TyS<'tcx> {
pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
match self.kind() {
Array(ty, _) | Slice(ty) => ty,
Str => tcx.mk_mach_uint(ty::UintTy::U8),
Str => tcx.types.u8,
_ => bug!("`sequence_element_type` called on non-sequence value: {}", self),
}
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ symbols! {
const_async_blocks,
const_compare_raw_pointers,
const_constructor,
const_deallocate,
const_eval_limit,
const_eval_select,
const_eval_select_ct,
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_typeck/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,11 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::const_allocate => {
(0, vec![tcx.types.usize, tcx.types.usize], tcx.mk_mut_ptr(tcx.types.u8))
}
sym::const_deallocate => (
0,
vec![tcx.mk_mut_ptr(tcx.types.u8), tcx.types.usize, tcx.types.usize],
tcx.mk_unit(),
),

sym::ptr_offset_from => {
(1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize)
Expand Down
23 changes: 22 additions & 1 deletion library/core/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1914,10 +1914,31 @@ extern "rust-intrinsic" {
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;

/// Allocate at compile time. Should not be called at runtime.
/// Allocates a block of memory at compile time.
/// At runtime, just returns a null pointer.
///
/// # Safety
///
/// - The `align` argument must be a power of two.
/// - At compile time, a compile error occurs if this constraint is violated.
/// - At runtime, it is not checked.
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
pub fn const_allocate(size: usize, align: usize) -> *mut u8;

/// Deallocates a memory which allocated by `intrinsics::const_allocate` at compile time.
/// At runtime, does nothing.
///
/// # Safety
///
/// - The `align` argument must be a power of two.
/// - At compile time, a compile error occurs if this constraint is violated.
/// - At runtime, it is not checked.
/// - If the `ptr` is created in an another const, this intrinsic doesn't deallocate it.
/// - If the `ptr` is pointing to a local variable, this intrinsic doesn't deallocate it.
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
#[cfg(not(bootstrap))]
pub fn const_deallocate(ptr: *mut u8, size: usize, align: usize);

/// Determines whether the raw bytes of the two values are equal.
///
/// This is particularly handy for arrays, since it allows things like just
Expand Down
3 changes: 2 additions & 1 deletion library/core/src/ptr/non_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,9 @@ impl<T: ?Sized> NonNull<T> {
/// }
/// ```
#[stable(feature = "nonnull", since = "1.25.0")]
#[rustc_const_unstable(feature = "const_nonnull_new", issue = "93235")]
#[inline]
pub fn new(ptr: *mut T) -> Option<Self> {
pub const fn new(ptr: *mut T) -> Option<Self> {
if !ptr.is_null() {
// SAFETY: The pointer is already checked and is not null
Some(unsafe { Self::new_unchecked(ptr) })
Expand Down
22 changes: 22 additions & 0 deletions library/core/tests/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,25 @@ fn test_hints_in_const_contexts() {
assert!(42u32 == core::hint::black_box(42u32));
}
}

#[cfg(not(bootstrap))]
#[test]
fn test_const_allocate_at_runtime() {
use core::intrinsics::const_allocate;
unsafe {
assert!(const_allocate(4, 4).is_null());
}
}

#[cfg(not(bootstrap))]
#[test]
fn test_const_deallocate_at_runtime() {
use core::intrinsics::const_deallocate;
const X: &u32 = &42u32;
let x = &0u32;
unsafe {
const_deallocate(X as *const _ as *mut u8, 4, 4); // nop
const_deallocate(x as *const _ as *mut u8, 4, 4); // nop
const_deallocate(core::ptr::null_mut(), 1, 1); // nop
}
}
3 changes: 3 additions & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
#![feature(const_bool_to_option)]
#![feature(const_cell_into_inner)]
#![feature(const_convert)]
#![feature(const_heap)]
#![feature(const_maybe_uninit_as_mut_ptr)]
#![feature(const_maybe_uninit_assume_init)]
#![feature(const_maybe_uninit_assume_init_read)]
#![feature(const_nonnull_new)]
#![feature(const_num_from_num)]
#![feature(const_ptr_as_ref)]
#![feature(const_ptr_read)]
#![feature(const_ptr_write)]
#![feature(const_ptr_offset)]
Expand Down
15 changes: 15 additions & 0 deletions library/core/tests/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,21 @@ fn test_unsized_nonnull() {
assert!(ys == zs);
}

#[test]
fn test_const_nonnull_new() {
const {
assert!(NonNull::new(core::ptr::null_mut::<()>()).is_none());

let value = &mut 0u32;
let mut ptr = NonNull::new(value).unwrap();
unsafe { *ptr.as_mut() = 42 };

let reference = unsafe { &*ptr.as_ref() };
assert!(*reference == *value);
assert!(*reference == 42);
};
}

#[test]
#[allow(warnings)]
// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
Expand Down
3 changes: 3 additions & 0 deletions library/std/src/sys/solid/abi/sockets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ extern "C" {
#[link_name = "SOLID_NET_Close"]
pub fn close(s: c_int) -> c_int;

#[link_name = "SOLID_NET_Dup"]
pub fn dup(s: c_int) -> c_int;

#[link_name = "SOLID_NET_GetPeerName"]
pub fn getpeername(s: c_int, name: *mut sockaddr, namelen: *mut socklen_t) -> c_int;

Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/solid/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl FileDesc {
}

fn duplicate(&self) -> io::Result<FileDesc> {
super::unsupported()
cvt(unsafe { netc::dup(self.fd) }).map(Self::new)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}"
# https://github.com/puppeteer/puppeteer/issues/375
#
# We also specify the version in case we need to update it to go around cache limitations.
RUN npm install -g browser-ui-test@0.5.3 --unsafe-perm=true
RUN npm install -g browser-ui-test@0.5.8 --unsafe-perm=true

ENV RUST_CONFIGURE_ARGS \
--build=x86_64-unknown-linux-gnu \
Expand Down
7 changes: 4 additions & 3 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1676,11 +1676,12 @@ fn render_rightside(
containing_item.stable_since(tcx),
const_stable_since,
);
if has_stability {
let mut tmp_buf = Buffer::empty_from(w);
write_srclink(cx, item, &mut tmp_buf);
if has_stability && !tmp_buf.is_empty() {
w.write_str(" · ");
}

write_srclink(cx, item, w);
w.push_buffer(tmp_buf);
w.write_str("</div>");
}

Expand Down
16 changes: 16 additions & 0 deletions src/test/rustdoc-gui/theme-change.goml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,19 @@ click: "#theme-choices > button:last-child"
wait-for: 500
// should be the light theme so let's check the color
assert-css: ("body", { "background-color": "rgb(255, 255, 255)" })

goto: file://|DOC_PATH|/settings.html
click: "#theme-light"
wait-for: 500
assert-css: ("body", { "background-color": "rgb(255, 255, 255)" })
assert-local-storage: { "rustdoc-theme": "light" }

click: "#theme-dark"
wait-for: 500
assert-css: ("body", { "background-color": "rgb(53, 53, 53)" })
assert-local-storage: { "rustdoc-theme": "dark" }

click: "#theme-ayu"
wait-for: 500
assert-css: ("body", { "background-color": "rgb(15, 20, 25)" })
assert-local-storage: { "rustdoc-theme": "ayu" }
Loading

0 comments on commit a00e130

Please sign in to comment.