mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #126473 - matthiaskrgr:rollup-8w2xm09, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #123769 (Improve escaping of byte, byte str, and c str proc-macro literals) - #126054 (`E0229`: Suggest Moving Type Constraints to Type Parameter Declaration) - #126135 (add HermitOS support for vectored read/write operations) - #126266 (Unify guarantees about the default allocator) - #126285 (`UniqueRc`: support allocators and `T: ?Sized`.) - #126399 (extend the check for LLVM build) - #126426 (const validation: fix ICE on dangling ZST reference) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f9515fdd5a
10
Cargo.lock
10
Cargo.lock
@ -1694,6 +1694,12 @@ name = "hermit-abi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
@ -2636,7 +2642,7 @@ version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"hermit-abi 0.3.9",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@ -5345,7 +5351,7 @@ dependencies = [
|
||||
"dlmalloc",
|
||||
"fortanix-sgx-abi",
|
||||
"hashbrown",
|
||||
"hermit-abi",
|
||||
"hermit-abi 0.4.0",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object 0.36.0",
|
||||
|
@ -29,7 +29,7 @@ use rustc_target::abi::{
|
||||
use std::hash::Hash;
|
||||
|
||||
use super::{
|
||||
err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, CheckInAllocMsg,
|
||||
err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, AllocKind, CheckInAllocMsg,
|
||||
GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
|
||||
Pointer, Projectable, Scalar, ValueVisitor,
|
||||
};
|
||||
@ -413,8 +413,6 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
||||
Ub(PointerOutOfBounds { .. }) => DanglingPtrOutOfBounds {
|
||||
ptr_kind
|
||||
},
|
||||
// This cannot happen during const-eval (because interning already detects
|
||||
// dangling pointers), but it can happen in Miri.
|
||||
Ub(PointerUseAfterFree(..)) => DanglingPtrUseAfterFree {
|
||||
ptr_kind,
|
||||
},
|
||||
@ -493,9 +491,17 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
||||
}
|
||||
}
|
||||
|
||||
// Mutability check.
|
||||
// Dangling and Mutability check.
|
||||
let (size, _align, alloc_kind) = self.ecx.get_alloc_info(alloc_id);
|
||||
if alloc_kind == AllocKind::Dead {
|
||||
// This can happen for zero-sized references. We can't have *any* references to non-existing
|
||||
// allocations though, interning rejects them all as the rest of rustc isn't happy with them...
|
||||
// so we throw an error, even though this isn't really UB.
|
||||
// A potential future alternative would be to resurrect this as a zero-sized allocation
|
||||
// (which codegen will then compile to an aligned dummy pointer anyway).
|
||||
throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind });
|
||||
}
|
||||
// If this allocation has size zero, there is no actual mutability here.
|
||||
let (size, _align, _alloc_kind) = self.ecx.get_alloc_info(alloc_id);
|
||||
if size != Size::ZERO {
|
||||
let alloc_actual_mutbl = mutability(self.ecx, alloc_id);
|
||||
// Mutable pointer to immutable memory is no good.
|
||||
|
@ -2471,6 +2471,15 @@ pub enum AssocItemConstraintKind<'hir> {
|
||||
Bound { bounds: &'hir [GenericBound<'hir>] },
|
||||
}
|
||||
|
||||
impl<'hir> AssocItemConstraintKind<'hir> {
|
||||
pub fn descr(&self) -> &'static str {
|
||||
match self {
|
||||
AssocItemConstraintKind::Equality { .. } => "binding",
|
||||
AssocItemConstraintKind::Bound { .. } => "constraint",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||
pub struct Ty<'hir> {
|
||||
pub hir_id: HirId,
|
||||
@ -3763,6 +3772,21 @@ impl<'hir> Node<'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get a `hir::Impl` if the node is an impl block for the given `trait_def_id`.
|
||||
pub fn impl_block_of_trait(self, trait_def_id: DefId) -> Option<&'hir Impl<'hir>> {
|
||||
match self {
|
||||
Node::Item(Item { kind: ItemKind::Impl(impl_block), .. })
|
||||
if impl_block
|
||||
.of_trait
|
||||
.and_then(|trait_ref| trait_ref.trait_def_id())
|
||||
.is_some_and(|trait_id| trait_id == trait_def_id) =>
|
||||
{
|
||||
Some(impl_block)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> {
|
||||
match self {
|
||||
Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
|
||||
|
@ -1217,7 +1217,6 @@ pub fn prohibit_assoc_item_constraint(
|
||||
// otherwise suggest the removal of the binding.
|
||||
if let Some((def_id, segment, _)) = segment
|
||||
&& segment.args().parenthesized == hir::GenericArgsParentheses::No
|
||||
&& let hir::AssocItemConstraintKind::Equality { term } = constraint.kind
|
||||
{
|
||||
// Suggests removal of the offending binding
|
||||
let suggest_removal = |e: &mut Diag<'_>| {
|
||||
@ -1263,7 +1262,7 @@ pub fn prohibit_assoc_item_constraint(
|
||||
if let Ok(suggestion) = tcx.sess.source_map().span_to_snippet(removal_span) {
|
||||
e.span_suggestion_verbose(
|
||||
removal_span,
|
||||
"consider removing this associated item binding",
|
||||
format!("consider removing this associated item {}", constraint.kind.descr()),
|
||||
suggestion,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
@ -1286,19 +1285,73 @@ pub fn prohibit_assoc_item_constraint(
|
||||
// Check if the type has a generic param with the same name
|
||||
// as the assoc type name in the associated item binding.
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let matching_param =
|
||||
generics.own_params.iter().find(|p| p.name.as_str() == constraint.ident.as_str());
|
||||
let matching_param = generics.own_params.iter().find(|p| p.name == constraint.ident.name);
|
||||
|
||||
// Now emit the appropriate suggestion
|
||||
if let Some(matching_param) = matching_param {
|
||||
match (&matching_param.kind, term) {
|
||||
(GenericParamDefKind::Type { .. }, hir::Term::Ty(ty)) => {
|
||||
suggest_direct_use(&mut err, ty.span);
|
||||
}
|
||||
(GenericParamDefKind::Const { .. }, hir::Term::Const(c)) => {
|
||||
match (constraint.kind, &matching_param.kind) {
|
||||
(
|
||||
hir::AssocItemConstraintKind::Equality { term: hir::Term::Ty(ty) },
|
||||
GenericParamDefKind::Type { .. },
|
||||
) => suggest_direct_use(&mut err, ty.span),
|
||||
(
|
||||
hir::AssocItemConstraintKind::Equality { term: hir::Term::Const(c) },
|
||||
GenericParamDefKind::Const { .. },
|
||||
) => {
|
||||
let span = tcx.hir().span(c.hir_id);
|
||||
suggest_direct_use(&mut err, span);
|
||||
}
|
||||
(hir::AssocItemConstraintKind::Bound { bounds }, _) => {
|
||||
// Suggest `impl<T: Bound> Trait<T> for Foo` when finding
|
||||
// `impl Trait<T: Bound> for Foo`
|
||||
|
||||
// Get the parent impl block based on the binding we have
|
||||
// and the trait DefId
|
||||
let impl_block = tcx
|
||||
.hir()
|
||||
.parent_iter(constraint.hir_id)
|
||||
.find_map(|(_, node)| node.impl_block_of_trait(def_id));
|
||||
|
||||
let type_with_constraints =
|
||||
tcx.sess.source_map().span_to_snippet(constraint.span);
|
||||
|
||||
if let Some(impl_block) = impl_block
|
||||
&& let Ok(type_with_constraints) = type_with_constraints
|
||||
{
|
||||
// Filter out the lifetime parameters because
|
||||
// they should be declared before the type parameter
|
||||
let lifetimes: String = bounds
|
||||
.iter()
|
||||
.filter_map(|bound| {
|
||||
if let hir::GenericBound::Outlives(lifetime) = bound {
|
||||
Some(format!("{lifetime}, "))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
// Figure out a span and suggestion string based on
|
||||
// whether there are any existing parameters
|
||||
let param_decl = if let Some(param_span) =
|
||||
impl_block.generics.span_for_param_suggestion()
|
||||
{
|
||||
(param_span, format!(", {lifetimes}{type_with_constraints}"))
|
||||
} else {
|
||||
(
|
||||
impl_block.generics.span.shrink_to_lo(),
|
||||
format!("<{lifetimes}{type_with_constraints}>"),
|
||||
)
|
||||
};
|
||||
let suggestions =
|
||||
vec![param_decl, (constraint.span, format!("{}", matching_param.name))];
|
||||
|
||||
err.multipart_suggestion_verbose(
|
||||
format!("declare the type parameter right after the `impl` keyword"),
|
||||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => suggest_removal(&mut err),
|
||||
}
|
||||
} else {
|
||||
|
@ -531,6 +531,7 @@ pub(crate) fn check_generic_arg_count(
|
||||
|
||||
let num_default_params = expected_max - expected_min;
|
||||
|
||||
let mut all_params_are_binded = false;
|
||||
let gen_args_info = if provided > expected_max {
|
||||
invalid_args.extend((expected_max..provided).map(|i| i + args_offset));
|
||||
let num_redundant_args = provided - expected_max;
|
||||
@ -547,6 +548,20 @@ pub(crate) fn check_generic_arg_count(
|
||||
} else {
|
||||
let num_missing_args = expected_max - provided;
|
||||
|
||||
let constraint_names: Vec<_> =
|
||||
gen_args.constraints.iter().map(|b| b.ident.name).collect();
|
||||
let param_names: Vec<_> = gen_params
|
||||
.own_params
|
||||
.iter()
|
||||
.filter(|param| !has_self || param.index != 0) // Assumes `Self` will always be the first parameter
|
||||
.map(|param| param.name)
|
||||
.collect();
|
||||
if constraint_names == param_names {
|
||||
// We set this to true and delay emitting `WrongNumberOfGenericArgs`
|
||||
// to provide a succinct error for cases like issue #113073
|
||||
all_params_are_binded = true;
|
||||
};
|
||||
|
||||
GenericArgsInfo::MissingTypesOrConsts {
|
||||
num_missing_args,
|
||||
num_default_params,
|
||||
@ -567,7 +582,7 @@ pub(crate) fn check_generic_arg_count(
|
||||
def_id,
|
||||
)
|
||||
.diagnostic()
|
||||
.emit()
|
||||
.emit_unless(all_params_are_binded)
|
||||
});
|
||||
|
||||
Err(reported)
|
||||
|
@ -3516,7 +3516,7 @@ fn data_offset_align(align: usize) -> usize {
|
||||
layout.size() + layout.padding_needed_for(align)
|
||||
}
|
||||
|
||||
/// A uniquely owned `Rc`
|
||||
/// A uniquely owned [`Rc`].
|
||||
///
|
||||
/// This represents an `Rc` that is known to be uniquely owned -- that is, have exactly one strong
|
||||
/// reference. Multiple weak pointers can be created, but attempts to upgrade those to strong
|
||||
@ -3554,13 +3554,24 @@ fn data_offset_align(align: usize) -> usize {
|
||||
/// including fallible or async constructors.
|
||||
#[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
#[derive(Debug)]
|
||||
pub struct UniqueRc<T> {
|
||||
pub struct UniqueRc<
|
||||
T: ?Sized,
|
||||
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
|
||||
> {
|
||||
ptr: NonNull<RcBox<T>>,
|
||||
phantom: PhantomData<RcBox<T>>,
|
||||
alloc: A,
|
||||
}
|
||||
|
||||
#[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
impl<T: ?Sized + Unsize<U>, U: ?Sized, A: Allocator> CoerceUnsized<UniqueRc<U, A>>
|
||||
for UniqueRc<T, A>
|
||||
{
|
||||
}
|
||||
|
||||
// Depends on A = Global
|
||||
impl<T> UniqueRc<T> {
|
||||
/// Creates a new `UniqueRc`
|
||||
/// Creates a new `UniqueRc`.
|
||||
///
|
||||
/// Weak references to this `UniqueRc` can be created with [`UniqueRc::downgrade`]. Upgrading
|
||||
/// these weak references will fail before the `UniqueRc` has been converted into an [`Rc`].
|
||||
@ -3569,34 +3580,36 @@ impl<T> UniqueRc<T> {
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
pub fn new(value: T) -> Self {
|
||||
Self {
|
||||
ptr: Box::leak(Box::new(RcBox {
|
||||
Self::new_in(value, Global)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, A: Allocator> UniqueRc<T, A> {
|
||||
/// Creates a new `UniqueRc` in the provided allocator.
|
||||
///
|
||||
/// Weak references to this `UniqueRc` can be created with [`UniqueRc::downgrade`]. Upgrading
|
||||
/// these weak references will fail before the `UniqueRc` has been converted into an [`Rc`].
|
||||
/// After converting the `UniqueRc` into an [`Rc`], any weak references created beforehand will
|
||||
/// point to the new [`Rc`].
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
#[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
pub fn new_in(value: T, alloc: A) -> Self {
|
||||
let (ptr, alloc) = Box::into_unique(Box::new_in(
|
||||
RcBox {
|
||||
strong: Cell::new(0),
|
||||
// keep one weak reference so if all the weak pointers that are created are dropped
|
||||
// the UniqueRc still stays valid.
|
||||
weak: Cell::new(1),
|
||||
value,
|
||||
}))
|
||||
.into(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
},
|
||||
alloc,
|
||||
));
|
||||
Self { ptr: ptr.into(), phantom: PhantomData, alloc }
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new weak reference to the `UniqueRc`
|
||||
///
|
||||
/// Attempting to upgrade this weak reference will fail before the `UniqueRc` has been converted
|
||||
/// to a [`Rc`] using [`UniqueRc::into_rc`].
|
||||
#[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
pub fn downgrade(this: &Self) -> Weak<T> {
|
||||
// SAFETY: This pointer was allocated at creation time and we guarantee that we only have
|
||||
// one strong reference before converting to a regular Rc.
|
||||
unsafe {
|
||||
this.ptr.as_ref().inc_weak();
|
||||
}
|
||||
Weak { ptr: this.ptr, alloc: Global }
|
||||
}
|
||||
|
||||
/// Converts the `UniqueRc` into a regular [`Rc`]
|
||||
impl<T: ?Sized, A: Allocator> UniqueRc<T, A> {
|
||||
/// Converts the `UniqueRc` into a regular [`Rc`].
|
||||
///
|
||||
/// This consumes the `UniqueRc` and returns a regular [`Rc`] that contains the `value` that
|
||||
/// is passed to `into_rc`.
|
||||
@ -3604,19 +3617,41 @@ impl<T> UniqueRc<T> {
|
||||
/// Any weak references created before this method is called can now be upgraded to strong
|
||||
/// references.
|
||||
#[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
pub fn into_rc(this: Self) -> Rc<T> {
|
||||
pub fn into_rc(this: Self) -> Rc<T, A> {
|
||||
let mut this = ManuallyDrop::new(this);
|
||||
|
||||
// Move the allocator out.
|
||||
// SAFETY: `this.alloc` will not be accessed again, nor dropped because it is in
|
||||
// a `ManuallyDrop`.
|
||||
let alloc: A = unsafe { ptr::read(&this.alloc) };
|
||||
|
||||
// SAFETY: This pointer was allocated at creation time so we know it is valid.
|
||||
unsafe {
|
||||
// Convert our weak reference into a strong reference
|
||||
this.ptr.as_mut().strong.set(1);
|
||||
Rc::from_inner(this.ptr)
|
||||
Rc::from_inner_in(this.ptr, alloc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized, A: Allocator + Clone> UniqueRc<T, A> {
|
||||
/// Creates a new weak reference to the `UniqueRc`.
|
||||
///
|
||||
/// Attempting to upgrade this weak reference will fail before the `UniqueRc` has been converted
|
||||
/// to a [`Rc`] using [`UniqueRc::into_rc`].
|
||||
#[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
pub fn downgrade(this: &Self) -> Weak<T, A> {
|
||||
// SAFETY: This pointer was allocated at creation time and we guarantee that we only have
|
||||
// one strong reference before converting to a regular Rc.
|
||||
unsafe {
|
||||
this.ptr.as_ref().inc_weak();
|
||||
}
|
||||
Weak { ptr: this.ptr, alloc: this.alloc.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
impl<T> Deref for UniqueRc<T> {
|
||||
impl<T: ?Sized, A: Allocator> Deref for UniqueRc<T, A> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
@ -3626,7 +3661,7 @@ impl<T> Deref for UniqueRc<T> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
impl<T> DerefMut for UniqueRc<T> {
|
||||
impl<T: ?Sized, A: Allocator> DerefMut for UniqueRc<T, A> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
// SAFETY: This pointer was allocated at creation time so we know it is valid. We know we
|
||||
// have unique ownership and therefore it's safe to make a mutable reference because
|
||||
@ -3636,7 +3671,7 @@ impl<T> DerefMut for UniqueRc<T> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "unique_rc_arc", issue = "112566")]
|
||||
unsafe impl<#[may_dangle] T> Drop for UniqueRc<T> {
|
||||
unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc<T, A> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// destroy the contained object
|
||||
@ -3646,7 +3681,7 @@ unsafe impl<#[may_dangle] T> Drop for UniqueRc<T> {
|
||||
self.ptr.as_ref().dec_weak();
|
||||
|
||||
if self.ptr.as_ref().weak() == 0 {
|
||||
Global.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr()));
|
||||
self.alloc.deallocate(self.ptr.cast(), Layout::for_value_raw(self.ptr.as_ptr()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -606,6 +606,23 @@ fn test_unique_rc_drops_contents() {
|
||||
assert!(dropped);
|
||||
}
|
||||
|
||||
/// Exercise the non-default allocator usage.
|
||||
#[test]
|
||||
fn test_unique_rc_with_alloc_drops_contents() {
|
||||
let mut dropped = false;
|
||||
struct DropMe<'a>(&'a mut bool);
|
||||
impl Drop for DropMe<'_> {
|
||||
fn drop(&mut self) {
|
||||
*self.0 = true;
|
||||
}
|
||||
}
|
||||
{
|
||||
let rc = UniqueRc::new_in(DropMe(&mut dropped), std::alloc::System);
|
||||
drop(rc);
|
||||
}
|
||||
assert!(dropped);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unique_rc_weak_clone_holding_ref() {
|
||||
let mut v = UniqueRc::new(0u8);
|
||||
@ -614,3 +631,12 @@ fn test_unique_rc_weak_clone_holding_ref() {
|
||||
let _ = w.clone(); // touch weak count
|
||||
*r = 123;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unique_rc_unsizing_coercion() {
|
||||
let mut rc: UniqueRc<[u8]> = UniqueRc::new([0u8; 3]);
|
||||
assert_eq!(rc.len(), 3);
|
||||
rc[0] = 123;
|
||||
let rc: Rc<[u8]> = UniqueRc::into_rc(rc);
|
||||
assert_eq!(*rc, [123, 0, 0]);
|
||||
}
|
||||
|
57
library/proc_macro/src/escape.rs
Normal file
57
library/proc_macro/src/escape.rs
Normal file
@ -0,0 +1,57 @@
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) struct EscapeOptions {
|
||||
/// Produce \'.
|
||||
pub escape_single_quote: bool,
|
||||
/// Produce \".
|
||||
pub escape_double_quote: bool,
|
||||
/// Produce \x escapes for non-ASCII, and use \x rather than \u for ASCII
|
||||
/// control characters.
|
||||
pub escape_nonascii: bool,
|
||||
}
|
||||
|
||||
pub(crate) fn escape_bytes(bytes: &[u8], opt: EscapeOptions) -> String {
|
||||
let mut repr = String::new();
|
||||
|
||||
if opt.escape_nonascii {
|
||||
for &byte in bytes {
|
||||
escape_single_byte(byte, opt, &mut repr);
|
||||
}
|
||||
} else {
|
||||
let mut chunks = bytes.utf8_chunks();
|
||||
while let Some(chunk) = chunks.next() {
|
||||
for ch in chunk.valid().chars() {
|
||||
escape_single_char(ch, opt, &mut repr);
|
||||
}
|
||||
for &byte in chunk.invalid() {
|
||||
escape_single_byte(byte, opt, &mut repr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repr
|
||||
}
|
||||
|
||||
fn escape_single_byte(byte: u8, opt: EscapeOptions, repr: &mut String) {
|
||||
if byte == b'\0' {
|
||||
repr.push_str("\\0");
|
||||
} else if (byte == b'\'' && !opt.escape_single_quote)
|
||||
|| (byte == b'"' && !opt.escape_double_quote)
|
||||
{
|
||||
repr.push(byte as char);
|
||||
} else {
|
||||
// Escapes \t, \r, \n, \\, \', \", and uses \x## for non-ASCII and
|
||||
// for ASCII control characters.
|
||||
repr.extend(byte.escape_ascii().map(char::from));
|
||||
}
|
||||
}
|
||||
|
||||
fn escape_single_char(ch: char, opt: EscapeOptions, repr: &mut String) {
|
||||
if (ch == '\'' && !opt.escape_single_quote) || (ch == '"' && !opt.escape_double_quote) {
|
||||
repr.push(ch);
|
||||
} else {
|
||||
// Escapes \0, \t, \r, \n, \\, \', \", and uses \u{...} for
|
||||
// non-printable characters and for Grapheme_Extend characters, which
|
||||
// includes things like U+0300 "Combining Grave Accent".
|
||||
repr.extend(ch.escape_debug());
|
||||
}
|
||||
}
|
@ -43,10 +43,12 @@
|
||||
pub mod bridge;
|
||||
|
||||
mod diagnostic;
|
||||
mod escape;
|
||||
|
||||
#[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
|
||||
pub use diagnostic::{Diagnostic, Level, MultiSpan};
|
||||
|
||||
use crate::escape::{escape_bytes, EscapeOptions};
|
||||
use std::ffi::CStr;
|
||||
use std::ops::{Range, RangeBounds};
|
||||
use std::path::PathBuf;
|
||||
@ -1356,40 +1358,61 @@ impl Literal {
|
||||
/// String literal.
|
||||
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
|
||||
pub fn string(string: &str) -> Literal {
|
||||
let quoted = format!("{:?}", string);
|
||||
assert!(quoted.starts_with('"') && quoted.ends_with('"'));
|
||||
let symbol = "ed[1..quoted.len() - 1];
|
||||
Literal::new(bridge::LitKind::Str, symbol, None)
|
||||
let escape = EscapeOptions {
|
||||
escape_single_quote: false,
|
||||
escape_double_quote: true,
|
||||
escape_nonascii: false,
|
||||
};
|
||||
let repr = escape_bytes(string.as_bytes(), escape);
|
||||
Literal::new(bridge::LitKind::Str, &repr, None)
|
||||
}
|
||||
|
||||
/// Character literal.
|
||||
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
|
||||
pub fn character(ch: char) -> Literal {
|
||||
let quoted = format!("{:?}", ch);
|
||||
assert!(quoted.starts_with('\'') && quoted.ends_with('\''));
|
||||
let symbol = "ed[1..quoted.len() - 1];
|
||||
Literal::new(bridge::LitKind::Char, symbol, None)
|
||||
let escape = EscapeOptions {
|
||||
escape_single_quote: true,
|
||||
escape_double_quote: false,
|
||||
escape_nonascii: false,
|
||||
};
|
||||
let repr = escape_bytes(ch.encode_utf8(&mut [0u8; 4]).as_bytes(), escape);
|
||||
Literal::new(bridge::LitKind::Char, &repr, None)
|
||||
}
|
||||
|
||||
/// Byte character literal.
|
||||
#[stable(feature = "proc_macro_byte_character", since = "1.79.0")]
|
||||
pub fn byte_character(byte: u8) -> Literal {
|
||||
let string = [byte].escape_ascii().to_string();
|
||||
Literal::new(bridge::LitKind::Byte, &string, None)
|
||||
let escape = EscapeOptions {
|
||||
escape_single_quote: true,
|
||||
escape_double_quote: false,
|
||||
escape_nonascii: true,
|
||||
};
|
||||
let repr = escape_bytes(&[byte], escape);
|
||||
Literal::new(bridge::LitKind::Byte, &repr, None)
|
||||
}
|
||||
|
||||
/// Byte string literal.
|
||||
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
|
||||
pub fn byte_string(bytes: &[u8]) -> Literal {
|
||||
let string = bytes.escape_ascii().to_string();
|
||||
Literal::new(bridge::LitKind::ByteStr, &string, None)
|
||||
let escape = EscapeOptions {
|
||||
escape_single_quote: false,
|
||||
escape_double_quote: true,
|
||||
escape_nonascii: true,
|
||||
};
|
||||
let repr = escape_bytes(bytes, escape);
|
||||
Literal::new(bridge::LitKind::ByteStr, &repr, None)
|
||||
}
|
||||
|
||||
/// C string literal.
|
||||
#[stable(feature = "proc_macro_c_str_literals", since = "1.79.0")]
|
||||
pub fn c_string(string: &CStr) -> Literal {
|
||||
let string = string.to_bytes().escape_ascii().to_string();
|
||||
Literal::new(bridge::LitKind::CStr, &string, None)
|
||||
let escape = EscapeOptions {
|
||||
escape_single_quote: false,
|
||||
escape_double_quote: true,
|
||||
escape_nonascii: false,
|
||||
};
|
||||
let repr = escape_bytes(string.to_bytes(), escape);
|
||||
Literal::new(bridge::LitKind::CStr, &repr, None)
|
||||
}
|
||||
|
||||
/// Returns the span encompassing this literal.
|
||||
|
@ -50,7 +50,7 @@ dlmalloc = { version = "0.2.4", features = ['rustc-dep-of-std'] }
|
||||
fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'], public = true }
|
||||
|
||||
[target.'cfg(target_os = "hermit")'.dependencies]
|
||||
hermit-abi = { version = "0.3.9", features = ['rustc-dep-of-std'], public = true }
|
||||
hermit-abi = { version = "0.4.0", features = ['rustc-dep-of-std'], public = true }
|
||||
|
||||
[target.'cfg(target_os = "wasi")'.dependencies]
|
||||
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
|
||||
|
@ -73,7 +73,9 @@ pub use alloc_crate::alloc::*;
|
||||
/// work, such as to serve alignment requests greater than the alignment
|
||||
/// provided directly by the backing system allocator.
|
||||
///
|
||||
/// This type implements the `GlobalAlloc` trait and Rust programs by default
|
||||
/// This type implements the [`GlobalAlloc`] trait. Currently the default
|
||||
/// global allocator is unspecified. Libraries, however, like `cdylib`s and
|
||||
/// `staticlib`s are guaranteed to use the [`System`] by default and as such
|
||||
/// work as if they had this definition:
|
||||
///
|
||||
/// ```rust
|
||||
|
@ -1,7 +1,8 @@
|
||||
#![unstable(reason = "not public", issue = "none", feature = "fd")]
|
||||
|
||||
use super::hermit_abi;
|
||||
use crate::io::{self, Read};
|
||||
use crate::cmp;
|
||||
use crate::io::{self, IoSlice, IoSliceMut, Read};
|
||||
use crate::os::hermit::io::{FromRawFd, OwnedFd, RawFd};
|
||||
use crate::sys::cvt;
|
||||
use crate::sys::unsupported;
|
||||
@ -9,6 +10,10 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
use crate::os::hermit::io::*;
|
||||
|
||||
const fn max_iov() -> usize {
|
||||
hermit_abi::IOV_MAX
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FileDesc {
|
||||
fd: OwnedFd,
|
||||
@ -21,6 +26,22 @@ impl FileDesc {
|
||||
Ok(result as usize)
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
let ret = cvt(unsafe {
|
||||
hermit_abi::readv(
|
||||
self.as_raw_fd(),
|
||||
bufs.as_mut_ptr() as *mut hermit_abi::iovec as *const hermit_abi::iovec,
|
||||
cmp::min(bufs.len(), max_iov()),
|
||||
)
|
||||
})?;
|
||||
Ok(ret as usize)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
let mut me = self;
|
||||
(&mut me).read_to_end(buf)
|
||||
@ -32,6 +53,22 @@ impl FileDesc {
|
||||
Ok(result as usize)
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let ret = cvt(unsafe {
|
||||
hermit_abi::writev(
|
||||
self.as_raw_fd(),
|
||||
bufs.as_ptr() as *const hermit_abi::iovec,
|
||||
cmp::min(bufs.len(), max_iov()),
|
||||
)
|
||||
})?;
|
||||
Ok(ret as usize)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<FileDesc> {
|
||||
self.duplicate_path(&[])
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::fd::FileDesc;
|
||||
use super::hermit_abi::{
|
||||
self, dirent64, stat as stat_struct, DT_DIR, DT_LNK, DT_REG, DT_UNKNOWN, O_APPEND, O_CREAT,
|
||||
O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG,
|
||||
O_DIRECTORY, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG,
|
||||
};
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::fmt;
|
||||
@ -62,7 +62,7 @@ pub struct DirEntry {
|
||||
/// 64-bit inode number
|
||||
ino: u64,
|
||||
/// File type
|
||||
type_: u32,
|
||||
type_: u8,
|
||||
/// name of the entry
|
||||
name: OsString,
|
||||
}
|
||||
@ -90,7 +90,7 @@ pub struct FilePermissions {
|
||||
|
||||
#[derive(Copy, Clone, Eq, Debug)]
|
||||
pub struct FileType {
|
||||
mode: u32,
|
||||
mode: u8,
|
||||
}
|
||||
|
||||
impl PartialEq for FileType {
|
||||
@ -112,31 +112,23 @@ pub struct DirBuilder {
|
||||
|
||||
impl FileAttr {
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
Ok(SystemTime::new(
|
||||
self.stat_val.st_mtime.try_into().unwrap(),
|
||||
self.stat_val.st_mtime_nsec.try_into().unwrap(),
|
||||
))
|
||||
Ok(SystemTime::new(self.stat_val.st_mtim.tv_sec, self.stat_val.st_mtim.tv_nsec))
|
||||
}
|
||||
|
||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
Ok(SystemTime::new(
|
||||
self.stat_val.st_atime.try_into().unwrap(),
|
||||
self.stat_val.st_atime_nsec.try_into().unwrap(),
|
||||
))
|
||||
Ok(SystemTime::new(self.stat_val.st_atim.tv_sec, self.stat_val.st_atim.tv_nsec))
|
||||
}
|
||||
|
||||
pub fn created(&self) -> io::Result<SystemTime> {
|
||||
Ok(SystemTime::new(
|
||||
self.stat_val.st_ctime.try_into().unwrap(),
|
||||
self.stat_val.st_ctime_nsec.try_into().unwrap(),
|
||||
))
|
||||
Ok(SystemTime::new(self.stat_val.st_ctim.tv_sec, self.stat_val.st_ctim.tv_nsec))
|
||||
}
|
||||
|
||||
pub fn size(&self) -> u64 {
|
||||
self.stat_val.st_size as u64
|
||||
}
|
||||
|
||||
pub fn perm(&self) -> FilePermissions {
|
||||
FilePermissions { mode: (self.stat_val.st_mode) }
|
||||
FilePermissions { mode: self.stat_val.st_mode }
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> FileType {
|
||||
@ -220,7 +212,7 @@ impl Iterator for ReadDir {
|
||||
let entry = DirEntry {
|
||||
root: self.inner.root.clone(),
|
||||
ino: dir.d_ino,
|
||||
type_: dir.d_type as u32,
|
||||
type_: dir.d_type,
|
||||
name: OsString::from_vec(name_bytes.to_vec()),
|
||||
};
|
||||
|
||||
@ -251,7 +243,7 @@ impl DirEntry {
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
Ok(FileType { mode: self.type_ as u32 })
|
||||
Ok(FileType { mode: self.type_ })
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -385,12 +377,12 @@ impl File {
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
crate::io::default_read_vectored(|buf| self.read(buf), bufs)
|
||||
self.0.read_vectored(bufs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
false
|
||||
self.0.is_read_vectored()
|
||||
}
|
||||
|
||||
pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
@ -402,12 +394,12 @@ impl File {
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
crate::io::default_write_vectored(|buf| self.write(buf), bufs)
|
||||
self.0.write_vectored(bufs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
false
|
||||
self.0.is_write_vectored()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -439,13 +431,13 @@ impl DirBuilder {
|
||||
|
||||
pub fn mkdir(&self, path: &Path) -> io::Result<()> {
|
||||
run_path_with_cstr(path, &|path| {
|
||||
cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode) }).map(|_| ())
|
||||
cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode.into()) }).map(|_| ())
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn set_mode(&mut self, mode: u32) {
|
||||
self.mode = mode as u32;
|
||||
self.mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
@ -501,8 +493,9 @@ impl FromRawFd for File {
|
||||
}
|
||||
|
||||
pub fn readdir(path: &Path) -> io::Result<ReadDir> {
|
||||
let fd_raw =
|
||||
run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::opendir(path.as_ptr()) }))?;
|
||||
let fd_raw = run_path_with_cstr(path, &|path| {
|
||||
cvt(unsafe { hermit_abi::open(path.as_ptr(), O_RDONLY | O_DIRECTORY, 0) })
|
||||
})?;
|
||||
let fd = unsafe { FileDesc::from_raw_fd(fd_raw as i32) };
|
||||
let root = path.to_path_buf();
|
||||
|
||||
|
@ -10,7 +10,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
|
||||
let timespec = timeout.and_then(|dur| {
|
||||
Some(hermit_abi::timespec {
|
||||
tv_sec: dur.as_secs().try_into().ok()?,
|
||||
tv_nsec: dur.subsec_nanos().into(),
|
||||
tv_nsec: dur.subsec_nanos().try_into().ok()?,
|
||||
})
|
||||
});
|
||||
|
||||
|
82
library/std/src/sys/pal/hermit/io.rs
Normal file
82
library/std/src/sys/pal/hermit/io.rs
Normal file
@ -0,0 +1,82 @@
|
||||
use crate::marker::PhantomData;
|
||||
use crate::os::hermit::io::{AsFd, AsRawFd};
|
||||
use crate::slice;
|
||||
|
||||
use hermit_abi::{c_void, iovec};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct IoSlice<'a> {
|
||||
vec: iovec,
|
||||
_p: PhantomData<&'a [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> IoSlice<'a> {
|
||||
#[inline]
|
||||
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
|
||||
IoSlice {
|
||||
vec: iovec { iov_base: buf.as_ptr() as *mut u8 as *mut c_void, iov_len: buf.len() },
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
if self.vec.iov_len < n {
|
||||
panic!("advancing IoSlice beyond its length");
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.vec.iov_len -= n;
|
||||
self.vec.iov_base = self.vec.iov_base.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct IoSliceMut<'a> {
|
||||
vec: iovec,
|
||||
_p: PhantomData<&'a mut [u8]>,
|
||||
}
|
||||
|
||||
impl<'a> IoSliceMut<'a> {
|
||||
#[inline]
|
||||
pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
|
||||
IoSliceMut {
|
||||
vec: iovec { iov_base: buf.as_mut_ptr() as *mut c_void, iov_len: buf.len() },
|
||||
_p: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
if self.vec.iov_len < n {
|
||||
panic!("advancing IoSliceMut beyond its length");
|
||||
}
|
||||
|
||||
unsafe {
|
||||
self.vec.iov_len -= n;
|
||||
self.vec.iov_base = self.vec.iov_base.add(n);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_mut_slice(&mut self) -> &mut [u8] {
|
||||
unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_terminal(fd: &impl AsFd) -> bool {
|
||||
let fd = fd.as_fd();
|
||||
hermit_abi::isatty(fd.as_raw_fd())
|
||||
}
|
@ -23,7 +23,6 @@ pub mod env;
|
||||
pub mod fd;
|
||||
pub mod fs;
|
||||
pub mod futex;
|
||||
#[path = "../unsupported/io.rs"]
|
||||
pub mod io;
|
||||
pub mod net;
|
||||
pub mod os;
|
||||
|
@ -175,12 +175,12 @@ impl Socket {
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
crate::io::default_read_vectored(|b| self.read(b), bufs)
|
||||
self.0.read_vectored(bufs)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
false
|
||||
self.0.is_read_vectored()
|
||||
}
|
||||
|
||||
fn recv_from_with_flags(&self, buf: &mut [u8], flags: i32) -> io::Result<(usize, SocketAddr)> {
|
||||
@ -209,16 +209,15 @@ impl Socket {
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
let sz = cvt(unsafe { netc::write(self.0.as_raw_fd(), buf.as_ptr(), buf.len()) })?;
|
||||
Ok(sz.try_into().unwrap())
|
||||
self.0.write(buf)
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
crate::io::default_write_vectored(|b| self.write(b), bufs)
|
||||
self.0.write_vectored(bufs)
|
||||
}
|
||||
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
false
|
||||
self.0.is_write_vectored()
|
||||
}
|
||||
|
||||
pub fn set_timeout(&self, dur: Option<Duration>, kind: i32) -> io::Result<()> {
|
||||
@ -265,7 +264,7 @@ impl Socket {
|
||||
Shutdown::Read => netc::SHUT_RD,
|
||||
Shutdown::Both => netc::SHUT_RDWR,
|
||||
};
|
||||
cvt(unsafe { netc::shutdown_socket(self.as_raw_fd(), how) })?;
|
||||
cvt(unsafe { netc::shutdown(self.as_raw_fd(), how) })?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -198,5 +198,5 @@ pub fn exit(code: i32) -> ! {
|
||||
}
|
||||
|
||||
pub fn getpid() -> u32 {
|
||||
unsafe { hermit_abi::getpid() }
|
||||
unsafe { hermit_abi::getpid() as u32 }
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
use super::hermit_abi;
|
||||
use crate::io;
|
||||
use crate::io::{IoSlice, IoSliceMut};
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::os::hermit::io::FromRawFd;
|
||||
use crate::sys::fd::FileDesc;
|
||||
|
||||
pub struct Stdin;
|
||||
pub struct Stdout;
|
||||
@ -13,12 +16,14 @@ impl Stdin {
|
||||
}
|
||||
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, data: &mut [u8]) -> io::Result<usize> {
|
||||
self.read_vectored(&mut [IoSliceMut::new(data)])
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(hermit_abi::STDIN_FILENO)).read(buf) }
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, _data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
Ok(0)
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
unsafe {
|
||||
ManuallyDrop::new(FileDesc::from_raw_fd(hermit_abi::STDIN_FILENO)).read_vectored(bufs)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -34,27 +39,13 @@ impl Stdout {
|
||||
}
|
||||
|
||||
impl io::Write for Stdout {
|
||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
||||
let len;
|
||||
|
||||
unsafe { len = hermit_abi::write(1, data.as_ptr() as *const u8, data.len()) }
|
||||
|
||||
if len < 0 {
|
||||
Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stdout is not able to print"))
|
||||
} else {
|
||||
Ok(len as usize)
|
||||
}
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(hermit_abi::STDOUT_FILENO)).write(buf) }
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let len;
|
||||
|
||||
unsafe { len = hermit_abi::write(1, data.as_ptr() as *const u8, data.len()) }
|
||||
|
||||
if len < 0 {
|
||||
Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stdout is not able to print"))
|
||||
} else {
|
||||
Ok(len as usize)
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
unsafe {
|
||||
ManuallyDrop::new(FileDesc::from_raw_fd(hermit_abi::STDOUT_FILENO)).write_vectored(bufs)
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,27 +66,13 @@ impl Stderr {
|
||||
}
|
||||
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
||||
let len;
|
||||
|
||||
unsafe { len = hermit_abi::write(2, data.as_ptr() as *const u8, data.len()) }
|
||||
|
||||
if len < 0 {
|
||||
Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stderr is not able to print"))
|
||||
} else {
|
||||
Ok(len as usize)
|
||||
}
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(hermit_abi::STDERR_FILENO)).write(buf) }
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let len;
|
||||
|
||||
unsafe { len = hermit_abi::write(2, data.as_ptr() as *const u8, data.len()) }
|
||||
|
||||
if len < 0 {
|
||||
Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stderr is not able to print"))
|
||||
} else {
|
||||
Ok(len as usize)
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
unsafe {
|
||||
ManuallyDrop::new(FileDesc::from_raw_fd(hermit_abi::STDERR_FILENO)).write_vectored(bufs)
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,10 +86,10 @@ impl io::Write for Stderr {
|
||||
}
|
||||
}
|
||||
|
||||
pub const STDIN_BUF_SIZE: usize = 0;
|
||||
pub const STDIN_BUF_SIZE: usize = 128;
|
||||
|
||||
pub fn is_ebadf(_err: &io::Error) -> bool {
|
||||
true
|
||||
pub fn is_ebadf(err: &io::Error) -> bool {
|
||||
err.raw_os_error() == Some(hermit_abi::EBADF)
|
||||
}
|
||||
|
||||
pub fn panic_output() -> Option<impl io::Write> {
|
||||
|
@ -98,5 +98,5 @@ impl Thread {
|
||||
}
|
||||
|
||||
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
||||
unsafe { Ok(NonZero::new_unchecked(hermit_abi::get_processor_count())) }
|
||||
unsafe { Ok(NonZero::new_unchecked(hermit_abi::available_parallelism())) }
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use super::hermit_abi::{self, timespec, CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC};
|
||||
use super::hermit_abi::{self, timespec, CLOCK_MONOTONIC, CLOCK_REALTIME};
|
||||
use crate::cmp::Ordering;
|
||||
use crate::ops::{Add, AddAssign, Sub, SubAssign};
|
||||
use crate::time::Duration;
|
||||
use core::hash::{Hash, Hasher};
|
||||
|
||||
const NSEC_PER_SEC: i32 = 1_000_000_000;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct Timespec {
|
||||
t: timespec,
|
||||
@ -16,8 +18,8 @@ impl Timespec {
|
||||
Timespec { t: timespec { tv_sec: 0, tv_nsec: 0 } }
|
||||
}
|
||||
|
||||
const fn new(tv_sec: i64, tv_nsec: i64) -> Timespec {
|
||||
assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC as i64);
|
||||
const fn new(tv_sec: i64, tv_nsec: i32) -> Timespec {
|
||||
assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC);
|
||||
// SAFETY: The assert above checks tv_nsec is within the valid range
|
||||
Timespec { t: timespec { tv_sec: tv_sec, tv_nsec: tv_nsec } }
|
||||
}
|
||||
@ -32,7 +34,7 @@ impl Timespec {
|
||||
} else {
|
||||
Duration::new(
|
||||
(self.t.tv_sec - 1 - other.t.tv_sec) as u64,
|
||||
self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - other.t.tv_nsec as u32,
|
||||
(self.t.tv_nsec + NSEC_PER_SEC - other.t.tv_nsec) as u32,
|
||||
)
|
||||
})
|
||||
} else {
|
||||
@ -48,9 +50,9 @@ impl Timespec {
|
||||
|
||||
// Nano calculations can't overflow because nanos are <1B which fit
|
||||
// in a u32.
|
||||
let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
|
||||
if nsec >= NSEC_PER_SEC as u32 {
|
||||
nsec -= NSEC_PER_SEC as u32;
|
||||
let mut nsec = other.subsec_nanos() + u32::try_from(self.t.tv_nsec).unwrap();
|
||||
if nsec >= NSEC_PER_SEC.try_into().unwrap() {
|
||||
nsec -= u32::try_from(NSEC_PER_SEC).unwrap();
|
||||
secs = secs.checked_add(1)?;
|
||||
}
|
||||
Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ } })
|
||||
@ -200,7 +202,7 @@ pub struct SystemTime(Timespec);
|
||||
pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero());
|
||||
|
||||
impl SystemTime {
|
||||
pub fn new(tv_sec: i64, tv_nsec: i64) -> SystemTime {
|
||||
pub fn new(tv_sec: i64, tv_nsec: i32) -> SystemTime {
|
||||
SystemTime(Timespec::new(tv_sec, tv_nsec))
|
||||
}
|
||||
|
||||
|
@ -137,7 +137,8 @@ pub fn check(build: &mut Build) {
|
||||
}
|
||||
|
||||
// We need cmake, but only if we're actually building LLVM or sanitizers.
|
||||
let building_llvm = build
|
||||
let building_llvm = !build.config.llvm_from_ci
|
||||
&& build
|
||||
.hosts
|
||||
.iter()
|
||||
.map(|host| {
|
||||
|
@ -5,6 +5,7 @@ pub trait Iter {
|
||||
|
||||
fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>;
|
||||
//~^ ERROR associated item constraints are not allowed here
|
||||
//~| HELP consider removing this associated item constraint
|
||||
}
|
||||
|
||||
impl Iter for () {
|
||||
|
@ -3,6 +3,11 @@ error[E0229]: associated item constraints are not allowed here
|
||||
|
|
||||
LL | fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>;
|
||||
| ^^^^^^^^^ associated item constraint not allowed here
|
||||
|
|
||||
help: consider removing this associated item constraint
|
||||
|
|
||||
LL | fn next<'a>(&'a mut self) -> Option<Self::Item<'a, As1: Copy>>;
|
||||
| ~~~~~~~~~~~
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
@ -76,7 +76,6 @@ trait Tr3<const N: i32, T2, T3> {
|
||||
impl Tr3<N
|
||||
//~^ ERROR associated item constraints are not allowed here
|
||||
//~| ERROR associated const equality is incomplete
|
||||
//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
|
||||
= 42, T2 = Qux, T3 = usize> for Bar {
|
||||
}
|
||||
|
||||
@ -92,7 +91,6 @@ impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
|
||||
// matches the const param ident but the constraint is a type arg
|
||||
impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
|
||||
//~^ ERROR associated item constraints are not allowed here
|
||||
//~| ERROR trait takes 3 generic arguments but 0 generic arguments were supplied
|
||||
}
|
||||
|
||||
// Test for when equality constraint's ident
|
||||
|
@ -5,7 +5,6 @@ LL | impl Tr3<N
|
||||
| __________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | = 42, T2 = Qux, T3 = usize> for Bar {
|
||||
| |____^
|
||||
|
|
||||
@ -14,7 +13,7 @@ LL | | = 42, T2 = Qux, T3 = usize> for Bar {
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: associated const equality is incomplete
|
||||
--> $DIR/associated-types-eq-2.rs:85:10
|
||||
--> $DIR/associated-types-eq-2.rs:84:10
|
||||
|
|
||||
LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
|
||||
| ^^^^^^
|
||||
@ -24,7 +23,7 @@ LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: associated const equality is incomplete
|
||||
--> $DIR/associated-types-eq-2.rs:100:14
|
||||
--> $DIR/associated-types-eq-2.rs:98:14
|
||||
|
|
||||
LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
|
||||
| ^^^^^^^
|
||||
@ -34,7 +33,7 @@ LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: associated const equality is incomplete
|
||||
--> $DIR/associated-types-eq-2.rs:108:10
|
||||
--> $DIR/associated-types-eq-2.rs:106:10
|
||||
|
|
||||
LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
|
||||
| ^^^^^^
|
||||
@ -190,22 +189,6 @@ help: to use `GenericTerm<i32>` as a generic argument specify it directly
|
||||
LL | impl Tr2<i32, Qux, GenericTerm<i32>> for Bar {
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
|
||||
error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
|
||||
--> $DIR/associated-types-eq-2.rs:76:6
|
||||
|
|
||||
LL | impl Tr3<N
|
||||
| ^^^ expected 3 generic arguments
|
||||
|
|
||||
note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
|
||||
--> $DIR/associated-types-eq-2.rs:69:7
|
||||
|
|
||||
LL | trait Tr3<const N: i32, T2, T3> {
|
||||
| ^^^ ------------ -- --
|
||||
help: add missing generic arguments
|
||||
|
|
||||
LL | impl Tr3<N, T2, T3, N
|
||||
| ++++++++++
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/associated-types-eq-2.rs:76:10
|
||||
|
|
||||
@ -213,7 +196,6 @@ LL | impl Tr3<N
|
||||
| __________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | = 42, T2 = Qux, T3 = usize> for Bar {
|
||||
| |____^ associated item constraint not allowed here
|
||||
|
|
||||
@ -223,7 +205,7 @@ LL | impl Tr3<42, T2 = Qux, T3 = usize> for Bar {
|
||||
| ~~
|
||||
|
||||
error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
|
||||
--> $DIR/associated-types-eq-2.rs:85:6
|
||||
--> $DIR/associated-types-eq-2.rs:84:6
|
||||
|
|
||||
LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
|
||||
| ^^^ expected 3 generic arguments
|
||||
@ -239,7 +221,7 @@ LL | impl Tr3<N, T2, T3, n = 42, T2 = Qux, T3 = usize> for Qux {
|
||||
| ++++++++++
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/associated-types-eq-2.rs:85:10
|
||||
--> $DIR/associated-types-eq-2.rs:84:10
|
||||
|
|
||||
LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
|
||||
| ^^^^^^ associated item constraint not allowed here
|
||||
@ -249,24 +231,8 @@ help: consider removing this associated item binding
|
||||
LL | impl Tr3<n = 42, T2 = Qux, T3 = usize> for Qux {
|
||||
| ~~~~~~~
|
||||
|
||||
error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
|
||||
--> $DIR/associated-types-eq-2.rs:93:6
|
||||
|
|
||||
LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
|
||||
| ^^^ expected 3 generic arguments
|
||||
|
|
||||
note: trait defined here, with 3 generic parameters: `N`, `T2`, `T3`
|
||||
--> $DIR/associated-types-eq-2.rs:69:7
|
||||
|
|
||||
LL | trait Tr3<const N: i32, T2, T3> {
|
||||
| ^^^ ------------ -- --
|
||||
help: add missing generic arguments
|
||||
|
|
||||
LL | impl Tr3<N, T2, T3, N = u32, T2 = Qux, T3 = usize> for Bar {
|
||||
| ++++++++++
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/associated-types-eq-2.rs:93:10
|
||||
--> $DIR/associated-types-eq-2.rs:92:10
|
||||
|
|
||||
LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
|
||||
| ^^^^^^^ associated item constraint not allowed here
|
||||
@ -277,7 +243,7 @@ LL | impl Tr3<N = u32, T2 = Qux, T3 = usize> for Bar {
|
||||
| ~~~~~~~~
|
||||
|
||||
error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
|
||||
--> $DIR/associated-types-eq-2.rs:100:6
|
||||
--> $DIR/associated-types-eq-2.rs:98:6
|
||||
|
|
||||
LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
|
||||
| ^^^ -- supplied 1 generic argument
|
||||
@ -295,7 +261,7 @@ LL | impl Tr3<42, T2, T3, T2 = 42, T3 = usize> for Bar {
|
||||
| ++++++++
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/associated-types-eq-2.rs:100:14
|
||||
--> $DIR/associated-types-eq-2.rs:98:14
|
||||
|
|
||||
LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
|
||||
| ^^^^^^^ associated item constraint not allowed here
|
||||
@ -306,7 +272,7 @@ LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar {
|
||||
| ~~~~~~~~~
|
||||
|
||||
error[E0107]: trait takes 3 generic arguments but 0 generic arguments were supplied
|
||||
--> $DIR/associated-types-eq-2.rs:108:6
|
||||
--> $DIR/associated-types-eq-2.rs:106:6
|
||||
|
|
||||
LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
|
||||
| ^^^ expected 3 generic arguments
|
||||
@ -322,7 +288,7 @@ LL | impl Tr3<N, T2, T3, X = 42, Y = Qux, Z = usize> for Bar {
|
||||
| ++++++++++
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/associated-types-eq-2.rs:108:10
|
||||
--> $DIR/associated-types-eq-2.rs:106:10
|
||||
|
|
||||
LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
|
||||
| ^^^^^^ associated item constraint not allowed here
|
||||
@ -333,13 +299,13 @@ LL | impl Tr3<X = 42, Y = Qux, Z = usize> for Bar {
|
||||
| ~~~~~~~
|
||||
|
||||
error[E0107]: struct takes 1 generic argument but 0 generic arguments were supplied
|
||||
--> $DIR/associated-types-eq-2.rs:119:13
|
||||
--> $DIR/associated-types-eq-2.rs:117:13
|
||||
|
|
||||
LL | impl<'a, T> St<'a , T = Qux> {
|
||||
| ^^ expected 1 generic argument
|
||||
|
|
||||
note: struct defined here, with 1 generic parameter: `T`
|
||||
--> $DIR/associated-types-eq-2.rs:117:8
|
||||
--> $DIR/associated-types-eq-2.rs:115:8
|
||||
|
|
||||
LL | struct St<'a, T> { v: &'a T }
|
||||
| ^^ -
|
||||
@ -349,7 +315,7 @@ LL | impl<'a, T> St<'a, T , T = Qux> {
|
||||
| +++
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/associated-types-eq-2.rs:119:21
|
||||
--> $DIR/associated-types-eq-2.rs:117:21
|
||||
|
|
||||
LL | impl<'a, T> St<'a , T = Qux> {
|
||||
| ^^^^^^^ associated item constraint not allowed here
|
||||
@ -359,7 +325,7 @@ help: to use `Qux` as a generic argument specify it directly
|
||||
LL | impl<'a, T> St<'a , Qux> {
|
||||
| ~~~
|
||||
|
||||
error: aborting due to 27 previous errors
|
||||
error: aborting due to 25 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0046, E0107, E0229, E0658.
|
||||
For more information about an error, try `rustc --explain E0046`.
|
||||
|
@ -12,6 +12,11 @@ error[E0229]: associated item constraints are not allowed here
|
||||
|
|
||||
LL | impl Super1<'_, bar(): Send> for () {}
|
||||
| ^^^^^^^^^^^ associated item constraint not allowed here
|
||||
|
|
||||
help: consider removing this associated item constraint
|
||||
|
|
||||
LL | impl Super1<'_, bar(): Send> for () {}
|
||||
| ~~~~~~~~~~~~~
|
||||
|
||||
error[E0046]: not all trait items implemented, missing: `bar`
|
||||
--> $DIR/rtn-in-impl-signature.rs:10:1
|
||||
|
@ -7,8 +7,7 @@ struct Bar;
|
||||
const T: usize = 42;
|
||||
|
||||
impl Foo<N = 3> for Bar {
|
||||
//~^ ERROR trait takes 1 generic argument but 0 generic arguments were supplied
|
||||
//~| ERROR associated item constraints are not allowed here
|
||||
//~^ ERROR associated item constraints are not allowed here
|
||||
//~| ERROR associated const equality is incomplete
|
||||
fn do_x(&self) -> [u8; 3] {
|
||||
[0u8; 3]
|
||||
|
@ -8,22 +8,6 @@ LL | impl Foo<N = 3> for Bar {
|
||||
= help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
|
||||
--> $DIR/issue-89013-no-kw.rs:9:6
|
||||
|
|
||||
LL | impl Foo<N = 3> for Bar {
|
||||
| ^^^ expected 1 generic argument
|
||||
|
|
||||
note: trait defined here, with 1 generic parameter: `N`
|
||||
--> $DIR/issue-89013-no-kw.rs:1:7
|
||||
|
|
||||
LL | trait Foo<const N: usize> {
|
||||
| ^^^ --------------
|
||||
help: add missing generic argument
|
||||
|
|
||||
LL | impl Foo<N, N = 3> for Bar {
|
||||
| ++
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/issue-89013-no-kw.rs:9:10
|
||||
|
|
||||
@ -35,7 +19,7 @@ help: to use `3` as a generic argument specify it directly
|
||||
LL | impl Foo<3> for Bar {
|
||||
| ~
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0107, E0229, E0658.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
||||
Some errors have detailed explanations: E0229, E0658.
|
||||
For more information about an error, try `rustc --explain E0229`.
|
||||
|
@ -8,7 +8,6 @@ const T: usize = 42;
|
||||
|
||||
impl Foo<N = const 3> for Bar {
|
||||
//~^ ERROR expected lifetime, type, or constant, found keyword `const`
|
||||
//~| ERROR trait takes 1 generic
|
||||
//~| ERROR associated item constraints are not allowed here
|
||||
//~| ERROR associated const equality is incomplete
|
||||
fn do_x(&self) -> [u8; 3] {
|
||||
|
@ -20,22 +20,6 @@ LL | impl Foo<N = const 3> for Bar {
|
||||
= help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
|
||||
--> $DIR/issue-89013.rs:9:6
|
||||
|
|
||||
LL | impl Foo<N = const 3> for Bar {
|
||||
| ^^^ expected 1 generic argument
|
||||
|
|
||||
note: trait defined here, with 1 generic parameter: `N`
|
||||
--> $DIR/issue-89013.rs:1:7
|
||||
|
|
||||
LL | trait Foo<const N: usize> {
|
||||
| ^^^ --------------
|
||||
help: add missing generic argument
|
||||
|
|
||||
LL | impl Foo<N, N = const 3> for Bar {
|
||||
| ++
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/issue-89013.rs:9:10
|
||||
|
|
||||
@ -47,7 +31,7 @@ help: to use `3` as a generic argument specify it directly
|
||||
LL | impl Foo<3> for Bar {
|
||||
| ~
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0107, E0229, E0658.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
||||
Some errors have detailed explanations: E0229, E0658.
|
||||
For more information about an error, try `rustc --explain E0229`.
|
||||
|
@ -10,7 +10,7 @@ union Foo<'a> {
|
||||
}
|
||||
|
||||
const FOO: &() = {
|
||||
//~^ ERROR encountered dangling pointer
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
let y = ();
|
||||
unsafe { Foo { y: &y }.long_live_the_unit }
|
||||
};
|
||||
|
@ -1,8 +1,14 @@
|
||||
error: encountered dangling pointer in final value of constant
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/dangling-alloc-id-ice.rs:12:1
|
||||
|
|
||||
LL | const FOO: &() = {
|
||||
| ^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (use-after-free)
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
HEX_DUMP
|
||||
}
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
15
tests/ui/consts/dangling-zst-ice-issue-126393.rs
Normal file
15
tests/ui/consts/dangling-zst-ice-issue-126393.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Strip out raw byte dumps to make comparison platform-independent:
|
||||
//@ normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
|
||||
//@ normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*A(LLOC)?[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
|
||||
//@ normalize-stderr-test "HEX_DUMP\s*\n\s*HEX_DUMP" -> "HEX_DUMP"
|
||||
|
||||
pub struct Wrapper;
|
||||
pub static MAGIC_FFI_REF: &'static Wrapper = unsafe {
|
||||
//~^ERROR: it is undefined behavior to use this value
|
||||
std::mem::transmute(&{
|
||||
let y = 42;
|
||||
y
|
||||
})
|
||||
};
|
||||
|
||||
fn main() {}
|
14
tests/ui/consts/dangling-zst-ice-issue-126393.stderr
Normal file
14
tests/ui/consts/dangling-zst-ice-issue-126393.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/dangling-zst-ice-issue-126393.rs:7:1
|
||||
|
|
||||
LL | pub static MAGIC_FFI_REF: &'static Wrapper = unsafe {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (use-after-free)
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
HEX_DUMP
|
||||
}
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
@ -0,0 +1,33 @@
|
||||
trait Foo<T> {}
|
||||
|
||||
impl Foo<T: Default> for String {}
|
||||
//~^ ERROR associated item constraints are not allowed here
|
||||
//~| HELP declare the type parameter right after the `impl` keyword
|
||||
|
||||
impl Foo<T: 'a + Default> for u8 {}
|
||||
//~^ ERROR associated item constraints are not allowed here
|
||||
//~| HELP declare the type parameter right after the `impl` keyword
|
||||
//~| ERROR use of undeclared lifetime name `'a`
|
||||
//~| HELP consider introducing lifetime `'a` here
|
||||
|
||||
impl<T> Foo<T: Default> for u16 {}
|
||||
//~^ ERROR associated item constraints are not allowed here
|
||||
//~| HELP declare the type parameter right after the `impl` keyword
|
||||
|
||||
impl<'a> Foo<T: 'a + Default> for u32 {}
|
||||
//~^ ERROR associated item constraints are not allowed here
|
||||
//~| HELP declare the type parameter right after the `impl` keyword
|
||||
|
||||
trait Bar<T, K> {}
|
||||
|
||||
impl Bar<T: Default, K: Default> for String {}
|
||||
//~^ ERROR associated item constraints are not allowed here
|
||||
//~| HELP declare the type parameter right after the `impl` keyword
|
||||
|
||||
impl<T> Bar<T, K: Default> for u8 {}
|
||||
//~^ ERROR trait takes 2 generic arguments but 1 generic argument was supplied
|
||||
//~| HELP add missing generic argument
|
||||
//~| ERROR associated item constraints are not allowed here
|
||||
//~| HELP declare the type parameter right after the `impl` keyword
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,96 @@
|
||||
error[E0261]: use of undeclared lifetime name `'a`
|
||||
--> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:7:13
|
||||
|
|
||||
LL | impl Foo<T: 'a + Default> for u8 {}
|
||||
| - ^^ undeclared lifetime
|
||||
| |
|
||||
| help: consider introducing lifetime `'a` here: `<'a>`
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:3:10
|
||||
|
|
||||
LL | impl Foo<T: Default> for String {}
|
||||
| ^^^^^^^^^^ associated item constraint not allowed here
|
||||
|
|
||||
help: declare the type parameter right after the `impl` keyword
|
||||
|
|
||||
LL | impl<T: Default> Foo<T> for String {}
|
||||
| ++++++++++++ ~
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:7:10
|
||||
|
|
||||
LL | impl Foo<T: 'a + Default> for u8 {}
|
||||
| ^^^^^^^^^^^^^^^ associated item constraint not allowed here
|
||||
|
|
||||
help: declare the type parameter right after the `impl` keyword
|
||||
|
|
||||
LL | impl<'a, T: 'a + Default> Foo<T> for u8 {}
|
||||
| +++++++++++++++++++++ ~
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:13:13
|
||||
|
|
||||
LL | impl<T> Foo<T: Default> for u16 {}
|
||||
| ^^^^^^^^^^ associated item constraint not allowed here
|
||||
|
|
||||
help: declare the type parameter right after the `impl` keyword
|
||||
|
|
||||
LL | impl<T, T: Default> Foo<T> for u16 {}
|
||||
| ++++++++++++ ~
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:17:14
|
||||
|
|
||||
LL | impl<'a> Foo<T: 'a + Default> for u32 {}
|
||||
| ^^^^^^^^^^^^^^^ associated item constraint not allowed here
|
||||
|
|
||||
help: declare the type parameter right after the `impl` keyword
|
||||
|
|
||||
LL | impl<'a, 'a, T: 'a + Default> Foo<T> for u32 {}
|
||||
| +++++++++++++++++++++ ~
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:23:10
|
||||
|
|
||||
LL | impl Bar<T: Default, K: Default> for String {}
|
||||
| ^^^^^^^^^^ associated item constraint not allowed here
|
||||
|
|
||||
help: declare the type parameter right after the `impl` keyword
|
||||
|
|
||||
LL | impl<T: Default> Bar<T, K: Default> for String {}
|
||||
| ++++++++++++ ~
|
||||
|
||||
error[E0107]: trait takes 2 generic arguments but 1 generic argument was supplied
|
||||
--> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:27:9
|
||||
|
|
||||
LL | impl<T> Bar<T, K: Default> for u8 {}
|
||||
| ^^^ - supplied 1 generic argument
|
||||
| |
|
||||
| expected 2 generic arguments
|
||||
|
|
||||
note: trait defined here, with 2 generic parameters: `T`, `K`
|
||||
--> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:21:7
|
||||
|
|
||||
LL | trait Bar<T, K> {}
|
||||
| ^^^ - -
|
||||
help: add missing generic argument
|
||||
|
|
||||
LL | impl<T> Bar<T, K, K: Default> for u8 {}
|
||||
| +++
|
||||
|
||||
error[E0229]: associated item constraints are not allowed here
|
||||
--> $DIR/impl-block-params-declared-in-wrong-spot-issue-113073.rs:27:16
|
||||
|
|
||||
LL | impl<T> Bar<T, K: Default> for u8 {}
|
||||
| ^^^^^^^^^^ associated item constraint not allowed here
|
||||
|
|
||||
help: declare the type parameter right after the `impl` keyword
|
||||
|
|
||||
LL | impl<T, K: Default> Bar<T, K> for u8 {}
|
||||
| ++++++++++++ ~
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0107, E0229, E0261.
|
||||
For more information about an error, try `rustc --explain E0107`.
|
83
tests/ui/proc-macro/auxiliary/api/literal.rs
Normal file
83
tests/ui/proc-macro/auxiliary/api/literal.rs
Normal file
@ -0,0 +1,83 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
use proc_macro::Literal;
|
||||
|
||||
pub fn test() {
|
||||
test_display_literal();
|
||||
test_parse_literal();
|
||||
}
|
||||
|
||||
fn test_display_literal() {
|
||||
assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "-10");
|
||||
assert_eq!(Literal::isize_suffixed(-10).to_string(), "-10isize");
|
||||
assert_eq!(Literal::f32_unsuffixed(-10.0).to_string(), "-10.0");
|
||||
assert_eq!(Literal::f32_suffixed(-10.0).to_string(), "-10f32");
|
||||
assert_eq!(Literal::f64_unsuffixed(-10.0).to_string(), "-10.0");
|
||||
assert_eq!(Literal::f64_suffixed(-10.0).to_string(), "-10f64");
|
||||
assert_eq!(
|
||||
Literal::f64_unsuffixed(1e100).to_string(),
|
||||
"10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0",
|
||||
);
|
||||
|
||||
assert_eq!(Literal::string("aA").to_string(), r#" "aA" "#.trim());
|
||||
assert_eq!(Literal::string("\t").to_string(), r#" "\t" "#.trim());
|
||||
assert_eq!(Literal::string("❤").to_string(), r#" "❤" "#.trim());
|
||||
assert_eq!(Literal::string("'").to_string(), r#" "'" "#.trim());
|
||||
assert_eq!(Literal::string("\"").to_string(), r#" "\"" "#.trim());
|
||||
assert_eq!(Literal::string("\0").to_string(), r#" "\0" "#.trim());
|
||||
assert_eq!(Literal::string("\u{1}").to_string(), r#" "\u{1}" "#.trim());
|
||||
|
||||
assert_eq!(Literal::byte_string(b"aA").to_string(), r#" b"aA" "#.trim());
|
||||
assert_eq!(Literal::byte_string(b"\t").to_string(), r#" b"\t" "#.trim());
|
||||
assert_eq!(Literal::byte_string(b"'").to_string(), r#" b"'" "#.trim());
|
||||
assert_eq!(Literal::byte_string(b"\"").to_string(), r#" b"\"" "#.trim());
|
||||
assert_eq!(Literal::byte_string(b"\0").to_string(), r#" b"\0" "#.trim());
|
||||
assert_eq!(Literal::byte_string(b"\x01").to_string(), r#" b"\x01" "#.trim());
|
||||
|
||||
assert_eq!(Literal::c_string(c"aA").to_string(), r#" c"aA" "#.trim());
|
||||
assert_eq!(Literal::c_string(c"\t").to_string(), r#" c"\t" "#.trim());
|
||||
assert_eq!(Literal::c_string(c"❤").to_string(), r#" c"❤" "#.trim());
|
||||
assert_eq!(Literal::c_string(c"\'").to_string(), r#" c"'" "#.trim());
|
||||
assert_eq!(Literal::c_string(c"\"").to_string(), r#" c"\"" "#.trim());
|
||||
assert_eq!(Literal::c_string(c"\x7f\xff\xfe\u{333}").to_string(), r#" c"\u{7f}\xff\xfe\u{333}" "#.trim());
|
||||
|
||||
assert_eq!(Literal::character('a').to_string(), r#" 'a' "#.trim());
|
||||
assert_eq!(Literal::character('\t').to_string(), r#" '\t' "#.trim());
|
||||
assert_eq!(Literal::character('❤').to_string(), r#" '❤' "#.trim());
|
||||
assert_eq!(Literal::character('\'').to_string(), r#" '\'' "#.trim());
|
||||
assert_eq!(Literal::character('"').to_string(), r#" '"' "#.trim());
|
||||
assert_eq!(Literal::character('\0').to_string(), r#" '\0' "#.trim());
|
||||
assert_eq!(Literal::character('\u{1}').to_string(), r#" '\u{1}' "#.trim());
|
||||
|
||||
assert_eq!(Literal::byte_character(b'a').to_string(), r#" b'a' "#.trim());
|
||||
assert_eq!(Literal::byte_character(b'\t').to_string(), r#" b'\t' "#.trim());
|
||||
assert_eq!(Literal::byte_character(b'\'').to_string(), r#" b'\'' "#.trim());
|
||||
assert_eq!(Literal::byte_character(b'"').to_string(), r#" b'"' "#.trim());
|
||||
assert_eq!(Literal::byte_character(0).to_string(), r#" b'\0' "#.trim());
|
||||
assert_eq!(Literal::byte_character(1).to_string(), r#" b'\x01' "#.trim());
|
||||
}
|
||||
|
||||
fn test_parse_literal() {
|
||||
assert_eq!("1".parse::<Literal>().unwrap().to_string(), "1");
|
||||
assert_eq!("1.0".parse::<Literal>().unwrap().to_string(), "1.0");
|
||||
assert_eq!("'a'".parse::<Literal>().unwrap().to_string(), "'a'");
|
||||
assert_eq!("b'a'".parse::<Literal>().unwrap().to_string(), "b'a'");
|
||||
assert_eq!("\"\n\"".parse::<Literal>().unwrap().to_string(), "\"\n\"");
|
||||
assert_eq!("b\"\"".parse::<Literal>().unwrap().to_string(), "b\"\"");
|
||||
assert_eq!("c\"\"".parse::<Literal>().unwrap().to_string(), "c\"\"");
|
||||
assert_eq!("r##\"\"##".parse::<Literal>().unwrap().to_string(), "r##\"\"##");
|
||||
assert_eq!("10ulong".parse::<Literal>().unwrap().to_string(), "10ulong");
|
||||
assert_eq!("-10ulong".parse::<Literal>().unwrap().to_string(), "-10ulong");
|
||||
|
||||
assert!("true".parse::<Literal>().is_err());
|
||||
assert!(".8".parse::<Literal>().is_err());
|
||||
assert!("0 1".parse::<Literal>().is_err());
|
||||
assert!("'a".parse::<Literal>().is_err());
|
||||
assert!(" 0".parse::<Literal>().is_err());
|
||||
assert!("0 ".parse::<Literal>().is_err());
|
||||
assert!("/* comment */0".parse::<Literal>().is_err());
|
||||
assert!("0/* comment */".parse::<Literal>().is_err());
|
||||
assert!("0// comment".parse::<Literal>().is_err());
|
||||
assert!("- 10".parse::<Literal>().is_err());
|
||||
assert!("-'x'".parse::<Literal>().is_err());
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
extern crate proc_macro;
|
||||
|
||||
mod cmp;
|
||||
mod parse;
|
||||
mod literal;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
@ -19,7 +19,7 @@ pub fn run(input: TokenStream) -> TokenStream {
|
||||
assert!(input.is_empty());
|
||||
|
||||
cmp::test();
|
||||
parse::test();
|
||||
literal::test();
|
||||
|
||||
TokenStream::new()
|
||||
}
|
||||
|
@ -1,58 +0,0 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
use proc_macro::Literal;
|
||||
|
||||
pub fn test() {
|
||||
test_display_literal();
|
||||
test_parse_literal();
|
||||
}
|
||||
|
||||
fn test_display_literal() {
|
||||
assert_eq!(Literal::isize_unsuffixed(-10).to_string(), "-10");
|
||||
assert_eq!(Literal::isize_suffixed(-10).to_string(), "-10isize");
|
||||
assert_eq!(Literal::f32_unsuffixed(-10.0).to_string(), "-10.0");
|
||||
assert_eq!(Literal::f32_suffixed(-10.0).to_string(), "-10f32");
|
||||
assert_eq!(Literal::f64_unsuffixed(-10.0).to_string(), "-10.0");
|
||||
assert_eq!(Literal::f64_suffixed(-10.0).to_string(), "-10f64");
|
||||
assert_eq!(
|
||||
Literal::f64_unsuffixed(1e100).to_string(),
|
||||
"10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0",
|
||||
);
|
||||
|
||||
assert_eq!(Literal::string("a \t ❤ ' \" \u{1}").to_string(), "\"a \\t ❤ ' \\\" \\u{1}\"",);
|
||||
assert_eq!(Literal::c_string(c"\'\"\x7f\u{7fff}").to_string(), r#"c"\'\"\x7f\xe7\xbf\xbf""#);
|
||||
assert_eq!(Literal::character('a').to_string(), "'a'");
|
||||
assert_eq!(Literal::character('\t').to_string(), "'\\t'");
|
||||
assert_eq!(Literal::character('❤').to_string(), "'❤'");
|
||||
assert_eq!(Literal::character('\'').to_string(), "'\\''");
|
||||
assert_eq!(Literal::character('"').to_string(), "'\"'");
|
||||
assert_eq!(Literal::character('\u{1}').to_string(), "'\\u{1}'");
|
||||
|
||||
assert_eq!(Literal::byte_character(b'a').to_string(), "b'a'");
|
||||
assert_eq!(Literal::byte_character(0).to_string(), "b'\\x00'");
|
||||
}
|
||||
|
||||
fn test_parse_literal() {
|
||||
assert_eq!("1".parse::<Literal>().unwrap().to_string(), "1");
|
||||
assert_eq!("1.0".parse::<Literal>().unwrap().to_string(), "1.0");
|
||||
assert_eq!("'a'".parse::<Literal>().unwrap().to_string(), "'a'");
|
||||
assert_eq!("b'a'".parse::<Literal>().unwrap().to_string(), "b'a'");
|
||||
assert_eq!("\"\n\"".parse::<Literal>().unwrap().to_string(), "\"\n\"");
|
||||
assert_eq!("b\"\"".parse::<Literal>().unwrap().to_string(), "b\"\"");
|
||||
assert_eq!("c\"\"".parse::<Literal>().unwrap().to_string(), "c\"\"");
|
||||
assert_eq!("r##\"\"##".parse::<Literal>().unwrap().to_string(), "r##\"\"##");
|
||||
assert_eq!("10ulong".parse::<Literal>().unwrap().to_string(), "10ulong");
|
||||
assert_eq!("-10ulong".parse::<Literal>().unwrap().to_string(), "-10ulong");
|
||||
|
||||
assert!("true".parse::<Literal>().is_err());
|
||||
assert!(".8".parse::<Literal>().is_err());
|
||||
assert!("0 1".parse::<Literal>().is_err());
|
||||
assert!("'a".parse::<Literal>().is_err());
|
||||
assert!(" 0".parse::<Literal>().is_err());
|
||||
assert!("0 ".parse::<Literal>().is_err());
|
||||
assert!("/* comment */0".parse::<Literal>().is_err());
|
||||
assert!("0/* comment */".parse::<Literal>().is_err());
|
||||
assert!("0// comment".parse::<Literal>().is_err());
|
||||
assert!("- 10".parse::<Literal>().is_err());
|
||||
assert!("-'x'".parse::<Literal>().is_err());
|
||||
}
|
Loading…
Reference in New Issue
Block a user