mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Auto merge of #93457 - matthiaskrgr:rollup-e43ry1l, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #88205 (Add Explanation For Error E0772) - #92274 (Add `intrinsics::const_deallocate`) - #93236 (Make `NonNull::new` `const`) - #93299 (Fix dot separator when there is no source link) - #93410 (kmc-solid: Implement `net::FileDesc::duplicate`) - #93424 (fix nit) - #93431 (remove unused `jemallocator` crate) - #93453 (Add GUI theme change test) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
a00e130dae
11
Cargo.lock
11
Cargo.lock
@ -3319,7 +3319,6 @@ dependencies = [
|
|||||||
"rustc_codegen_ssa",
|
"rustc_codegen_ssa",
|
||||||
"rustc_driver",
|
"rustc_driver",
|
||||||
"tikv-jemalloc-sys",
|
"tikv-jemalloc-sys",
|
||||||
"tikv-jemallocator",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5164,16 +5163,6 @@ dependencies = [
|
|||||||
"libc",
|
"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]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.43"
|
version = "0.1.43"
|
||||||
|
@ -15,11 +15,7 @@ version = '0.4.0'
|
|||||||
optional = true
|
optional = true
|
||||||
features = ['unprefixed_malloc_on_supported_platforms']
|
features = ['unprefixed_malloc_on_supported_platforms']
|
||||||
|
|
||||||
[dependencies.tikv-jemallocator]
|
|
||||||
version = '0.4.0'
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
jemalloc = ['tikv-jemalloc-sys', 'tikv-jemallocator']
|
jemalloc = ['tikv-jemalloc-sys']
|
||||||
llvm = ['rustc_driver/llvm']
|
llvm = ['rustc_driver/llvm']
|
||||||
max_level_info = ['rustc_driver/max_level_info']
|
max_level_info = ['rustc_driver/max_level_info']
|
||||||
|
@ -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:
|
// This requires that atomic intrinsics follow a specific naming pattern:
|
||||||
// "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
|
// "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
|
||||||
name if name_str.starts_with("atomic_") => {
|
name if name_str.starts_with("atomic_") => {
|
||||||
|
@ -347,6 +347,33 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||||||
)?;
|
)?;
|
||||||
ecx.write_pointer(ptr, dest)?;
|
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!(
|
return Err(ConstEvalErrKind::NeedsRfc(format!(
|
||||||
"calling intrinsic `{}`",
|
"calling intrinsic `{}`",
|
||||||
|
@ -472,6 +472,7 @@ E0768: include_str!("./error_codes/E0768.md"),
|
|||||||
E0769: include_str!("./error_codes/E0769.md"),
|
E0769: include_str!("./error_codes/E0769.md"),
|
||||||
E0770: include_str!("./error_codes/E0770.md"),
|
E0770: include_str!("./error_codes/E0770.md"),
|
||||||
E0771: include_str!("./error_codes/E0771.md"),
|
E0771: include_str!("./error_codes/E0771.md"),
|
||||||
|
E0772: include_str!("./error_codes/E0772.md"),
|
||||||
E0773: include_str!("./error_codes/E0773.md"),
|
E0773: include_str!("./error_codes/E0773.md"),
|
||||||
E0774: include_str!("./error_codes/E0774.md"),
|
E0774: include_str!("./error_codes/E0774.md"),
|
||||||
E0775: include_str!("./error_codes/E0775.md"),
|
E0775: include_str!("./error_codes/E0775.md"),
|
||||||
@ -642,5 +643,4 @@ E0787: include_str!("./error_codes/E0787.md"),
|
|||||||
// E0723, // unstable feature in `const` context
|
// E0723, // unstable feature in `const` context
|
||||||
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
|
E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
|
||||||
// E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
|
// 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
compiler/rustc_error_codes/src/error_codes/E0772.md
Normal file
89
compiler/rustc_error_codes/src/error_codes/E0772.md
Normal file
@ -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
|
@ -1810,7 +1810,7 @@ impl<'tcx> TyS<'tcx> {
|
|||||||
pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||||
match self.kind() {
|
match self.kind() {
|
||||||
Array(ty, _) | Slice(ty) => ty,
|
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),
|
_ => bug!("`sequence_element_type` called on non-sequence value: {}", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -461,6 +461,7 @@ symbols! {
|
|||||||
const_async_blocks,
|
const_async_blocks,
|
||||||
const_compare_raw_pointers,
|
const_compare_raw_pointers,
|
||||||
const_constructor,
|
const_constructor,
|
||||||
|
const_deallocate,
|
||||||
const_eval_limit,
|
const_eval_limit,
|
||||||
const_eval_select,
|
const_eval_select,
|
||||||
const_eval_select_ct,
|
const_eval_select_ct,
|
||||||
|
@ -297,6 +297,11 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
|||||||
sym::const_allocate => {
|
sym::const_allocate => {
|
||||||
(0, vec![tcx.types.usize, tcx.types.usize], tcx.mk_mut_ptr(tcx.types.u8))
|
(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 => {
|
sym::ptr_offset_from => {
|
||||||
(1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize)
|
(1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize)
|
||||||
|
@ -1914,10 +1914,31 @@ extern "rust-intrinsic" {
|
|||||||
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||||
pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
|
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")]
|
#[rustc_const_unstable(feature = "const_heap", issue = "79597")]
|
||||||
pub fn const_allocate(size: usize, align: usize) -> *mut u8;
|
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.
|
/// Determines whether the raw bytes of the two values are equal.
|
||||||
///
|
///
|
||||||
/// This is particularly handy for arrays, since it allows things like just
|
/// This is particularly handy for arrays, since it allows things like just
|
||||||
|
@ -211,8 +211,9 @@ impl<T: ?Sized> NonNull<T> {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_nonnull_new", issue = "93235")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(ptr: *mut T) -> Option<Self> {
|
pub const fn new(ptr: *mut T) -> Option<Self> {
|
||||||
if !ptr.is_null() {
|
if !ptr.is_null() {
|
||||||
// SAFETY: The pointer is already checked and is not null
|
// SAFETY: The pointer is already checked and is not null
|
||||||
Some(unsafe { Self::new_unchecked(ptr) })
|
Some(unsafe { Self::new_unchecked(ptr) })
|
||||||
|
@ -80,3 +80,25 @@ fn test_hints_in_const_contexts() {
|
|||||||
assert!(42u32 == core::hint::black_box(42u32));
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,10 +13,13 @@
|
|||||||
#![feature(const_bool_to_option)]
|
#![feature(const_bool_to_option)]
|
||||||
#![feature(const_cell_into_inner)]
|
#![feature(const_cell_into_inner)]
|
||||||
#![feature(const_convert)]
|
#![feature(const_convert)]
|
||||||
|
#![feature(const_heap)]
|
||||||
#![feature(const_maybe_uninit_as_mut_ptr)]
|
#![feature(const_maybe_uninit_as_mut_ptr)]
|
||||||
#![feature(const_maybe_uninit_assume_init)]
|
#![feature(const_maybe_uninit_assume_init)]
|
||||||
#![feature(const_maybe_uninit_assume_init_read)]
|
#![feature(const_maybe_uninit_assume_init_read)]
|
||||||
|
#![feature(const_nonnull_new)]
|
||||||
#![feature(const_num_from_num)]
|
#![feature(const_num_from_num)]
|
||||||
|
#![feature(const_ptr_as_ref)]
|
||||||
#![feature(const_ptr_read)]
|
#![feature(const_ptr_read)]
|
||||||
#![feature(const_ptr_write)]
|
#![feature(const_ptr_write)]
|
||||||
#![feature(const_ptr_offset)]
|
#![feature(const_ptr_offset)]
|
||||||
|
@ -274,6 +274,21 @@ fn test_unsized_nonnull() {
|
|||||||
assert!(ys == zs);
|
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]
|
#[test]
|
||||||
#[allow(warnings)]
|
#[allow(warnings)]
|
||||||
// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
|
// Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
|
||||||
|
@ -175,6 +175,9 @@ extern "C" {
|
|||||||
#[link_name = "SOLID_NET_Close"]
|
#[link_name = "SOLID_NET_Close"]
|
||||||
pub fn close(s: c_int) -> c_int;
|
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"]
|
#[link_name = "SOLID_NET_GetPeerName"]
|
||||||
pub fn getpeername(s: c_int, name: *mut sockaddr, namelen: *mut socklen_t) -> c_int;
|
pub fn getpeername(s: c_int, name: *mut sockaddr, namelen: *mut socklen_t) -> c_int;
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ impl FileDesc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn duplicate(&self) -> io::Result<FileDesc> {
|
fn duplicate(&self) -> io::Result<FileDesc> {
|
||||||
super::unsupported()
|
cvt(unsafe { netc::dup(self.fd) }).map(Self::new)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}"
|
|||||||
# https://github.com/puppeteer/puppeteer/issues/375
|
# https://github.com/puppeteer/puppeteer/issues/375
|
||||||
#
|
#
|
||||||
# We also specify the version in case we need to update it to go around cache limitations.
|
# 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 \
|
ENV RUST_CONFIGURE_ARGS \
|
||||||
--build=x86_64-unknown-linux-gnu \
|
--build=x86_64-unknown-linux-gnu \
|
||||||
|
@ -1676,11 +1676,12 @@ fn render_rightside(
|
|||||||
containing_item.stable_since(tcx),
|
containing_item.stable_since(tcx),
|
||||||
const_stable_since,
|
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(" · ");
|
w.write_str(" · ");
|
||||||
}
|
}
|
||||||
|
w.push_buffer(tmp_buf);
|
||||||
write_srclink(cx, item, w);
|
|
||||||
w.write_str("</div>");
|
w.write_str("</div>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,3 +9,19 @@ click: "#theme-choices > button:last-child"
|
|||||||
wait-for: 500
|
wait-for: 500
|
||||||
// should be the light theme so let's check the color
|
// should be the light theme so let's check the color
|
||||||
assert-css: ("body", { "background-color": "rgb(255, 255, 255)" })
|
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" }
|
||||||
|
23
src/test/rustdoc/version-separator-without-source.rs
Normal file
23
src/test/rustdoc/version-separator-without-source.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#![doc(html_no_source)]
|
||||||
|
#![feature(staged_api)]
|
||||||
|
#![stable(feature = "bar", since = "1.0")]
|
||||||
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
|
// @has foo/fn.foo.html
|
||||||
|
// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · '
|
||||||
|
// @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · '
|
||||||
|
#[stable(feature = "bar", since = "1.0")]
|
||||||
|
pub fn foo() {}
|
||||||
|
|
||||||
|
// @has foo/struct.Bar.html
|
||||||
|
// @has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · '
|
||||||
|
// @!has - '//div[@class="main-heading"]/*[@class="out-of-band"]' '1.0 · source · '
|
||||||
|
#[stable(feature = "bar", since = "1.0")]
|
||||||
|
pub struct Bar;
|
||||||
|
|
||||||
|
impl Bar {
|
||||||
|
// @has - '//div[@id="method.bar"]/*[@class="rightside"]' '2.0'
|
||||||
|
// @!has - '//div[@id="method.bar"]/*[@class="rightside"]' '2.0 ·'
|
||||||
|
#[stable(feature = "foobar", since = "2.0")]
|
||||||
|
pub fn bar() {}
|
||||||
|
}
|
@ -6,11 +6,10 @@ use std::intrinsics;
|
|||||||
const FOO: i32 = foo();
|
const FOO: i32 = foo();
|
||||||
const fn foo() -> i32 {
|
const fn foo() -> i32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _ = intrinsics::const_allocate(4, 3) as * mut i32;
|
let _ = intrinsics::const_allocate(4, 3) as *mut i32;
|
||||||
//~^ error: evaluation of constant value failed
|
//~^ error: evaluation of constant value failed
|
||||||
}
|
}
|
||||||
1
|
1
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -4,7 +4,7 @@ error[E0080]: evaluation of constant value failed
|
|||||||
LL | const FOO: i32 = foo();
|
LL | const FOO: i32 = foo();
|
||||||
| ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:6:18
|
| ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:6:18
|
||||||
...
|
...
|
||||||
LL | let _ = intrinsics::const_allocate(4, 3) as * mut i32;
|
LL | let _ = intrinsics::const_allocate(4, 3) as *mut i32;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| align has to be a power of 2, `3` is not a power of 2
|
| align has to be a power of 2, `3` is not a power of 2
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
// run-pass
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
#![feature(const_heap)]
|
||||||
|
#![feature(inline_const)]
|
||||||
|
|
||||||
|
use std::intrinsics;
|
||||||
|
|
||||||
|
struct ZST;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
const {
|
||||||
|
unsafe {
|
||||||
|
let _ = intrinsics::const_allocate(0, 0) as *mut ZST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
src/test/ui/consts/const-eval/heap/dealloc_intrinsic.rs
Normal file
36
src/test/ui/consts/const-eval/heap/dealloc_intrinsic.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// run-pass
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
#![feature(const_heap)]
|
||||||
|
#![feature(const_mut_refs)]
|
||||||
|
|
||||||
|
use std::intrinsics;
|
||||||
|
|
||||||
|
const _X: () = unsafe {
|
||||||
|
let ptr = intrinsics::const_allocate(4, 4);
|
||||||
|
intrinsics::const_deallocate(ptr, 4, 4);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Y: &u32 = unsafe {
|
||||||
|
let ptr = intrinsics::const_allocate(4, 4) as *mut u32;
|
||||||
|
*ptr = 42;
|
||||||
|
&*ptr
|
||||||
|
};
|
||||||
|
|
||||||
|
const Z: &u32 = &42;
|
||||||
|
|
||||||
|
const _Z: () = unsafe {
|
||||||
|
let ptr1 = Y as *const _ as *mut u8;
|
||||||
|
intrinsics::const_deallocate(ptr1, 4, 4); // nop
|
||||||
|
intrinsics::const_deallocate(ptr1, 2, 4); // nop
|
||||||
|
intrinsics::const_deallocate(ptr1, 4, 2); // nop
|
||||||
|
|
||||||
|
let ptr2 = Z as *const _ as *mut u8;
|
||||||
|
intrinsics::const_deallocate(ptr2, 4, 4); // nop
|
||||||
|
intrinsics::const_deallocate(ptr2, 2, 4); // nop
|
||||||
|
intrinsics::const_deallocate(ptr2, 4, 2); // nop
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(*Y, 42);
|
||||||
|
assert_eq!(*Z, 42);
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
#![feature(core_intrinsics)]
|
||||||
|
#![feature(const_heap)]
|
||||||
|
#![feature(const_mut_refs)]
|
||||||
|
|
||||||
|
use std::intrinsics;
|
||||||
|
|
||||||
|
const _X: &'static u8 = unsafe {
|
||||||
|
let ptr = intrinsics::const_allocate(4, 4);
|
||||||
|
intrinsics::const_deallocate(ptr, 4, 4);
|
||||||
|
&*ptr
|
||||||
|
//~^ error: evaluation of constant value failed
|
||||||
|
};
|
||||||
|
|
||||||
|
const _Y: u8 = unsafe {
|
||||||
|
let ptr = intrinsics::const_allocate(4, 4);
|
||||||
|
let reference = &*ptr;
|
||||||
|
intrinsics::const_deallocate(ptr, 4, 4);
|
||||||
|
*reference
|
||||||
|
//~^ error: evaluation of constant value failed
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,15 @@
|
|||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/dealloc_intrinsic_dangling.rs:10:5
|
||||||
|
|
|
||||||
|
LL | &*ptr
|
||||||
|
| ^^^^^ pointer to alloc2 was dereferenced after this allocation got freed
|
||||||
|
|
||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/dealloc_intrinsic_dangling.rs:18:5
|
||||||
|
|
|
||||||
|
LL | *reference
|
||||||
|
| ^^^^^^^^^^ pointer to alloc4 was dereferenced after this allocation got freed
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0080`.
|
@ -0,0 +1,13 @@
|
|||||||
|
#![feature(core_intrinsics)]
|
||||||
|
#![feature(const_heap)]
|
||||||
|
|
||||||
|
use std::intrinsics;
|
||||||
|
|
||||||
|
const _X: () = unsafe {
|
||||||
|
let ptr = intrinsics::const_allocate(4, 4);
|
||||||
|
intrinsics::const_deallocate(ptr, 4, 4);
|
||||||
|
intrinsics::const_deallocate(ptr, 4, 4);
|
||||||
|
//~^ error: evaluation of constant value failed
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,9 @@
|
|||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/dealloc_intrinsic_duplicate.rs:9:5
|
||||||
|
|
|
||||||
|
LL | intrinsics::const_deallocate(ptr, 4, 4);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pointer to alloc2 was dereferenced after this allocation got freed
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0080`.
|
@ -0,0 +1,29 @@
|
|||||||
|
#![feature(core_intrinsics)]
|
||||||
|
#![feature(const_heap)]
|
||||||
|
|
||||||
|
use std::intrinsics;
|
||||||
|
|
||||||
|
const _X: () = unsafe {
|
||||||
|
let ptr = intrinsics::const_allocate(4, 4);
|
||||||
|
intrinsics::const_deallocate(ptr, 4, 2);
|
||||||
|
//~^ error: evaluation of constant value failed
|
||||||
|
};
|
||||||
|
const _Y: () = unsafe {
|
||||||
|
let ptr = intrinsics::const_allocate(4, 4);
|
||||||
|
intrinsics::const_deallocate(ptr, 2, 4);
|
||||||
|
//~^ error: evaluation of constant value failed
|
||||||
|
};
|
||||||
|
|
||||||
|
const _Z: () = unsafe {
|
||||||
|
let ptr = intrinsics::const_allocate(4, 4);
|
||||||
|
intrinsics::const_deallocate(ptr, 3, 4);
|
||||||
|
//~^ error: evaluation of constant value failed
|
||||||
|
};
|
||||||
|
|
||||||
|
const _W: () = unsafe {
|
||||||
|
let ptr = intrinsics::const_allocate(4, 4);
|
||||||
|
intrinsics::const_deallocate(ptr, 4, 3);
|
||||||
|
//~^ error: evaluation of constant value failed
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,27 @@
|
|||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/dealloc_intrinsic_incorrect_layout.rs:8:5
|
||||||
|
|
|
||||||
|
LL | intrinsics::const_deallocate(ptr, 4, 2);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc2 has size 4 and alignment 4, but gave size 4 and alignment 2
|
||||||
|
|
||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/dealloc_intrinsic_incorrect_layout.rs:13:5
|
||||||
|
|
|
||||||
|
LL | intrinsics::const_deallocate(ptr, 2, 4);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc4 has size 4 and alignment 4, but gave size 2 and alignment 4
|
||||||
|
|
||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/dealloc_intrinsic_incorrect_layout.rs:19:5
|
||||||
|
|
|
||||||
|
LL | intrinsics::const_deallocate(ptr, 3, 4);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect layout on deallocation: alloc6 has size 4 and alignment 4, but gave size 3 and alignment 4
|
||||||
|
|
||||||
|
error[E0080]: evaluation of constant value failed
|
||||||
|
--> $DIR/dealloc_intrinsic_incorrect_layout.rs:25:5
|
||||||
|
|
|
||||||
|
LL | intrinsics::const_deallocate(ptr, 4, 3);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ align has to be a power of 2, `3` is not a power of 2
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0080`.
|
@ -0,0 +1,17 @@
|
|||||||
|
// run-pass
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
#![feature(const_heap)]
|
||||||
|
#![feature(inline_const)]
|
||||||
|
|
||||||
|
use std::intrinsics;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
const {
|
||||||
|
unsafe {
|
||||||
|
let ptr1 = intrinsics::const_allocate(0, 0);
|
||||||
|
let ptr2 = intrinsics::const_allocate(0, 0);
|
||||||
|
intrinsics::const_deallocate(ptr1, 0, 0);
|
||||||
|
intrinsics::const_deallocate(ptr2, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -38,4 +38,5 @@ LL | impl MyTrait for Box<dyn ObjectTrait<Assoc = i32> + '_> {
|
|||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0515`.
|
Some errors have detailed explanations: E0515, E0772.
|
||||||
|
For more information about an error, try `rustc --explain E0515`.
|
||||||
|
@ -131,4 +131,5 @@ LL | impl MyTrait for Box<dyn ObjectTrait + '_> {
|
|||||||
|
|
||||||
error: aborting due to 6 previous errors
|
error: aborting due to 6 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0759`.
|
Some errors have detailed explanations: E0759, E0772.
|
||||||
|
For more information about an error, try `rustc --explain E0759`.
|
||||||
|
Loading…
Reference in New Issue
Block a user