Auto merge of #88535 - m-ou-se:rollup-jeusxbo, r=m-ou-se

Rollup of 10 pull requests

Successful merges:

 - #85017 (Add carrying_add, borrowing_sub, widening_mul, carrying_mul methods to integers)
 - #86362 (Avoid cloning LocalDecls)
 - #88391 (Fix json tuple struct enum variant )
 - #88399 (Disallow the aapcs CC on Aarch64)
 - #88418 (Allow `~const` bounds on trait assoc functions)
 - #88445 (Clean up the lowering of AST items)
 - #88495 (Add `TcpStream::set_linger` and `TcpStream::linger`)
 - #88501 (Use right span in prelude collision suggestions with macros. )
 - #88504 (Keep turbofish in prelude collision lint.)
 - #88524 (Remove unnecessary `mut` from udp doctests)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-08-31 16:47:06 +00:00
commit 0a84708edc
48 changed files with 1008 additions and 128 deletions

View file

@ -26,44 +26,43 @@ pub(super) struct ItemLowerer<'a, 'lowering, 'hir> {
}
impl ItemLowerer<'_, '_, '_> {
fn with_trait_impl_ref(&mut self, impl_ref: &Option<TraitRef>, f: impl FnOnce(&mut Self)) {
fn with_trait_impl_ref<T>(
&mut self,
impl_ref: &Option<TraitRef>,
f: impl FnOnce(&mut Self) -> T,
) -> T {
let old = self.lctx.is_in_trait_impl;
self.lctx.is_in_trait_impl = impl_ref.is_some();
f(self);
let ret = f(self);
self.lctx.is_in_trait_impl = old;
ret
}
}
impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
fn visit_item(&mut self, item: &'a Item) {
let mut item_hir_id = None;
self.lctx.with_hir_id_owner(item.id, |lctx| {
let hir_id = self.lctx.with_hir_id_owner(item.id, |lctx| {
lctx.without_in_scope_lifetime_defs(|lctx| {
if let Some(hir_item) = lctx.lower_item(item) {
let id = lctx.insert_item(hir_item);
item_hir_id = Some(id);
}
let hir_item = lctx.lower_item(item);
lctx.insert_item(hir_item)
})
});
if let Some(hir_id) = item_hir_id {
self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
let this = &mut ItemLowerer { lctx: this };
match item.kind {
ItemKind::Mod(..) => {
let def_id = this.lctx.lower_node_id(item.id).expect_owner();
let old_current_module =
mem::replace(&mut this.lctx.current_module, def_id);
visit::walk_item(this, item);
this.lctx.current_module = old_current_module;
}
ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
}
_ => visit::walk_item(this, item),
self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
let this = &mut ItemLowerer { lctx: this };
match item.kind {
ItemKind::Mod(..) => {
let def_id = this.lctx.lower_node_id(item.id).expect_owner();
let old_current_module = mem::replace(&mut this.lctx.current_module, def_id);
visit::walk_item(this, item);
this.lctx.current_module = old_current_module;
}
});
}
ItemKind::Impl(box ImplKind { ref of_trait, .. }) => {
this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
}
_ => visit::walk_item(this, item),
}
});
}
fn visit_fn(&mut self, fk: FnKind<'a>, sp: Span, _: NodeId) {
@ -113,7 +112,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn with_parent_item_lifetime_defs<T>(
&mut self,
parent_hir_id: hir::ItemId,
f: impl FnOnce(&mut LoweringContext<'_, '_>) -> T,
f: impl FnOnce(&mut Self) -> T,
) -> T {
let old_len = self.in_scope_lifetimes.len();
@ -137,10 +136,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Clears (and restores) the `in_scope_lifetimes` field. Used when
// visiting nested items, which never inherit in-scope lifetimes
// from their surrounding environment.
fn without_in_scope_lifetime_defs<T>(
&mut self,
f: impl FnOnce(&mut LoweringContext<'_, '_>) -> T,
) -> T {
fn without_in_scope_lifetime_defs<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
let old_in_scope_lifetimes = mem::replace(&mut self.in_scope_lifetimes, vec![]);
// this vector is only used when walking over impl headers,
@ -208,19 +204,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item<'hir>> {
pub fn lower_item(&mut self, i: &Item) -> hir::Item<'hir> {
let mut ident = i.ident;
let mut vis = self.lower_visibility(&i.vis, None);
let hir_id = self.lower_node_id(i.id);
let attrs = self.lower_attrs(hir_id, &i.attrs);
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, &mut vis, &i.kind);
Some(hir::Item {
hir::Item {
def_id: hir_id.expect_owner(),
ident: self.lower_ident(ident),
kind,
vis,
span: self.lower_span(i.span),
})
}
}
fn lower_item_kind(

View file

@ -1442,7 +1442,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
if !self.is_tilde_const_allowed {
self.err_handler()
.struct_span_err(bound.span(), "`~const` is not allowed here")
.note("only allowed on bounds on traits' associated types, const fns, const impls and its associated functions")
.note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions")
.emit();
}
}
@ -1616,7 +1616,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
walk_list!(self, visit_ty, ty);
}
AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body))
if self.in_const_trait_impl =>
if self.in_const_trait_impl || ctxt == AssocCtxt::Trait =>
{
self.visit_vis(&item.vis);
self.visit_ident(item.ident);

View file

@ -426,6 +426,11 @@ impl<'tcx> Body<'tcx> {
(arg_count + 1..local_count).map(Local::new)
}
#[inline]
pub fn drain_vars_and_temps<'a>(&'a mut self) -> impl Iterator<Item = LocalDecl<'tcx>> + 'a {
self.local_decls.drain(self.arg_count + 1..)
}
/// Changes a statement to a nop. This is both faster than deleting instructions and avoids
/// invalidating statement indices in `Location`s.
pub fn make_statement_nop(&mut self, location: Location) {

View file

@ -607,13 +607,7 @@ impl Inliner<'tcx> {
}
// Insert all of the (mapped) parts of the callee body into the caller.
caller_body.local_decls.extend(
// FIXME(eddyb) make `Range<Local>` iterable so that we can use
// `callee_body.local_decls.drain(callee_body.vars_and_temps())`
callee_body
.vars_and_temps_iter()
.map(|local| callee_body.local_decls[local].clone()),
);
caller_body.local_decls.extend(callee_body.drain_vars_and_temps());
caller_body.source_scopes.extend(&mut callee_body.source_scopes.drain(..));
caller_body.var_debug_info.append(&mut callee_body.var_debug_info);
caller_body.basic_blocks_mut().extend(callee_body.basic_blocks_mut().drain(..));

View file

@ -597,6 +597,14 @@ impl Span {
if !expn_data.is_root() { Some(expn_data.call_site) } else { None }
}
/// Walk down the expansion ancestors to find a span that's contained within `outer`.
pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
while !outer.contains(self) {
self = self.parent()?;
}
Some(self)
}
/// Edition of the crate from which this span came.
pub fn edition(self) -> edition::Edition {
self.ctxt().edition()

View file

@ -1501,7 +1501,8 @@ impl Target {
| Cdecl
| EfiApi => true,
X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
Aapcs | CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
Aapcs => "arm" == self.arch,
CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
Win64 | SysV64 => self.arch == "x86_64",
PtxKernel => self.arch == "nvptx64",
Msp430Interrupt => self.arch == "msp430",

View file

@ -156,15 +156,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
segment.ident.name
));
let (self_adjusted, precise) = self.adjust_expr(pick, self_expr);
let (self_adjusted, precise) = self.adjust_expr(pick, self_expr, sp);
if precise {
let args = args
.iter()
.skip(1)
.map(|arg| {
let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
format!(
", {}",
self.sess().source_map().span_to_snippet(arg.span).unwrap()
self.sess().source_map().span_to_snippet(span).unwrap()
)
})
.collect::<String>();
@ -173,8 +174,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sp,
"disambiguate the associated function",
format!(
"{}::{}({}{})",
trait_name, segment.ident.name, self_adjusted, args
"{}::{}{}({}{})",
trait_name,
segment.ident.name,
if let Some(args) = segment.args.as_ref().and_then(|args| self
.sess()
.source_map()
.span_to_snippet(args.span_ext)
.ok())
{
// Keep turbofish.
format!("::{}", args)
} else {
String::new()
},
self_adjusted,
args,
),
Applicability::MachineApplicable,
);
@ -272,11 +287,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
method_name.name
));
let mut self_ty_name = self
.sess()
.source_map()
.span_to_snippet(self_ty_span)
.unwrap_or_else(|_| self_ty.to_string());
let mut self_ty_name = self_ty_span
.find_ancestor_inside(span)
.and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
.unwrap_or_else(|| self_ty.to_string());
// Get the number of generics the self type has (if an Adt) unless we can determine that
// the user has written the self type with generics already which we (naively) do by looking
@ -370,7 +384,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Creates a string version of the `expr` that includes explicit adjustments.
/// Returns the string and also a bool indicating whther this is a *precise*
/// suggestion.
fn adjust_expr(&self, pick: &Pick<'tcx>, expr: &hir::Expr<'tcx>) -> (String, bool) {
fn adjust_expr(
&self,
pick: &Pick<'tcx>,
expr: &hir::Expr<'tcx>,
outer: Span,
) -> (String, bool) {
let derefs = "*".repeat(pick.autoderefs);
let autoref = match pick.autoref_or_ptr_adjustment {
@ -379,12 +398,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(probe::AutorefOrPtrAdjustment::ToConstPtr) | None => "",
};
let (expr_text, precise) =
if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
(expr_text, true)
} else {
("(..)".to_string(), false)
};
let (expr_text, precise) = if let Some(expr_text) = expr
.span
.find_ancestor_inside(outer)
.and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
{
(expr_text, true)
} else {
("(..)".to_string(), false)
};
let adjusted_text = if let Some(probe::AutorefOrPtrAdjustment::ToConstPtr) =
pick.autoref_or_ptr_adjustment

View file

@ -680,15 +680,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
migrated_variables_concat
);
let mut closure_body_span = self.tcx.hir().span(body_id.hir_id);
// If the body was entirely expanded from a macro
// invocation, i.e. the body is not contained inside the
// closure span, then we walk up the expansion until we
// find the span before the expansion.
while !closure_body_span.is_dummy() && !closure_span.contains(closure_body_span) {
closure_body_span = closure_body_span.parent().unwrap_or(DUMMY_SP);
}
let closure_body_span = self.tcx.hir().span(body_id.hir_id)
.find_ancestor_inside(closure_span)
.unwrap_or(DUMMY_SP);
if let Ok(s) = self.tcx.sess.source_map().span_to_snippet(closure_body_span) {
let mut lines = s.lines();

View file

@ -76,6 +76,7 @@
#![feature(const_alloc_layout)]
#![feature(const_arguments_as_str)]
#![feature(const_assert_type)]
#![feature(const_bigint_helper_methods)]
#![feature(const_caller_location)]
#![feature(const_cell_into_inner)]
#![feature(const_discriminant)]

View file

@ -1341,6 +1341,33 @@ macro_rules! int_impl {
(a as Self, b)
}
/// Calculates `self + rhs + carry` without the ability to overflow.
///
/// Performs "ternary addition" which takes in an extra bit to add, and may return an
/// additional bit of overflow. This allows for chaining together multiple additions
/// to create "big integers" which represent larger values.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(bigint_helper_methods)]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (", stringify!($SelfT), "::MIN, false));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (", stringify!($SelfT), "::MIN + 1, false));")]
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) {
let (sum, carry) = (self as $UnsignedT).carrying_add(rhs as $UnsignedT, carry);
(sum as $SelfT, carry)
}
/// Calculates `self` - `rhs`
///
/// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow
@ -1365,6 +1392,33 @@ macro_rules! int_impl {
(a as Self, b)
}
/// Calculates `self - rhs - borrow` without the ability to overflow.
///
/// Performs "ternary subtraction" which takes in an extra bit to subtract, and may return
/// an additional bit of overflow. This allows for chaining together multiple subtractions
/// to create "big integers" which represent larger values.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(bigint_helper_methods)]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, false), (3, false));")]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, true), (2, false));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.borrowing_sub(1, false), (", stringify!($SelfT), "::MAX, false));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.borrowing_sub(1, true), (", stringify!($SelfT), "::MAX - 1, false));")]
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) {
let (sum, borrow) = (self as $UnsignedT).borrowing_sub(rhs as $UnsignedT, borrow);
(sum as $SelfT, borrow)
}
/// Calculates the multiplication of `self` and `rhs`.
///
/// Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic overflow

View file

@ -93,20 +93,96 @@ depending on the target pointer size.
};
}
macro_rules! widening_impl {
($SelfT:ty, $WideT:ty, $BITS:literal) => {
/// Calculates the complete product `self * rhs` without the possibility to overflow.
///
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
/// of the result as two separate values, in that order.
///
/// # Examples
///
/// Basic usage:
///
/// Please note that this example is shared between integer types.
/// Which explains why `u32` is used here.
///
/// ```
/// #![feature(bigint_helper_methods)]
/// assert_eq!(5u32.widening_mul(2), (10, 0));
/// assert_eq!(1_000_000_000u32.widening_mul(10), (1410065408, 2));
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn widening_mul(self, rhs: Self) -> (Self, Self) {
// note: longer-term this should be done via an intrinsic,
// but for now we can deal without an impl for u128/i128
// SAFETY: overflow will be contained within the wider types
let wide = unsafe { (self as $WideT).unchecked_mul(rhs as $WideT) };
(wide as $SelfT, (wide >> $BITS) as $SelfT)
}
/// Calculates the "full multiplication" `self * rhs + carry`
/// without the possibility to overflow.
///
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
/// of the result as two separate values, in that order.
///
/// Performs "long multiplication" which takes in an extra amount to add, and may return an
/// additional amount of overflow. This allows for chaining together multiple
/// multiplications to create "big integers" which represent larger values.
///
/// # Examples
///
/// Basic usage:
///
/// Please note that this example is shared between integer types.
/// Which explains why `u32` is used here.
///
/// ```
/// #![feature(bigint_helper_methods)]
/// assert_eq!(5u32.carrying_mul(2, 0), (10, 0));
/// assert_eq!(5u32.carrying_mul(2, 10), (20, 0));
/// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2));
/// assert_eq!(1_000_000_000u32.carrying_mul(10, 10), (1410065418, 2));
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn carrying_mul(self, rhs: Self, carry: Self) -> (Self, Self) {
// note: longer-term this should be done via an intrinsic,
// but for now we can deal without an impl for u128/i128
// SAFETY: overflow will be contained within the wider types
let wide = unsafe {
(self as $WideT).unchecked_mul(rhs as $WideT).unchecked_add(carry as $WideT)
};
(wide as $SelfT, (wide >> $BITS) as $SelfT)
}
};
}
#[lang = "i8"]
impl i8 {
widening_impl! { i8, i16, 8 }
int_impl! { i8, i8, u8, 8, 7, -128, 127, 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
"[0x12]", "[0x12]", "", "" }
}
#[lang = "i16"]
impl i16 {
widening_impl! { i16, i32, 16 }
int_impl! { i16, i16, u16, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
"0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
}
#[lang = "i32"]
impl i32 {
widening_impl! { i32, i64, 32 }
int_impl! { i32, i32, u32, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
"[0x12, 0x34, 0x56, 0x78]", "", "" }
@ -114,6 +190,7 @@ impl i32 {
#[lang = "i64"]
impl i64 {
widening_impl! { i64, i128, 64 }
int_impl! { i64, i64, u64, 64, 63, -9223372036854775808, 9223372036854775807, 12,
"0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
"0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
@ -135,6 +212,7 @@ impl i128 {
#[cfg(target_pointer_width = "16")]
#[lang = "isize"]
impl isize {
widening_impl! { isize, i32, 16 }
int_impl! { isize, i16, usize, 16, 15, -32768, 32767, 4, "-0x5ffd", "0x3a", "0x1234",
"0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
@ -143,6 +221,7 @@ impl isize {
#[cfg(target_pointer_width = "32")]
#[lang = "isize"]
impl isize {
widening_impl! { isize, i64, 32 }
int_impl! { isize, i32, usize, 32, 31, -2147483648, 2147483647, 8, "0x10000b3", "0xb301",
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
"[0x12, 0x34, 0x56, 0x78]",
@ -152,6 +231,7 @@ impl isize {
#[cfg(target_pointer_width = "64")]
#[lang = "isize"]
impl isize {
widening_impl! { isize, i128, 64 }
int_impl! { isize, i64, usize, 64, 63, -9223372036854775808, 9223372036854775807,
12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
"0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
@ -164,6 +244,7 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000;
#[lang = "u8"]
impl u8 {
widening_impl! { u8, u16, 8 }
uint_impl! { u8, u8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
"[0x12]", "", "" }
@ -697,18 +778,21 @@ impl u8 {
#[lang = "u16"]
impl u16 {
widening_impl! { u16, u32, 16 }
uint_impl! { u16, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
"[0x34, 0x12]", "[0x12, 0x34]", "", "" }
}
#[lang = "u32"]
impl u32 {
widening_impl! { u32, u64, 32 }
uint_impl! { u32, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
}
#[lang = "u64"]
impl u64 {
widening_impl! { u64, u128, 64 }
uint_impl! { u64, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
@ -731,6 +815,7 @@ impl u128 {
#[cfg(target_pointer_width = "16")]
#[lang = "usize"]
impl usize {
widening_impl! { usize, u32, 16 }
uint_impl! { usize, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
"[0x34, 0x12]", "[0x12, 0x34]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
@ -738,6 +823,7 @@ impl usize {
#[cfg(target_pointer_width = "32")]
#[lang = "usize"]
impl usize {
widening_impl! { usize, u64, 32 }
uint_impl! { usize, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678",
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
@ -746,6 +832,7 @@ impl usize {
#[cfg(target_pointer_width = "64")]
#[lang = "usize"]
impl usize {
widening_impl! { usize, u128, 64 }
uint_impl! { usize, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa",
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",

View file

@ -1408,6 +1408,36 @@ macro_rules! uint_impl {
(a as Self, b)
}
/// Calculates `self + rhs + carry` without the ability to overflow.
///
/// Performs "ternary addition" which takes in an extra bit to add, and may return an
/// additional bit of overflow. This allows for chaining together multiple additions
/// to create "big integers" which represent larger values.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(bigint_helper_methods)]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (0, true));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (1, true));")]
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn carrying_add(self, rhs: Self, carry: bool) -> (Self, bool) {
// note: longer-term this should be done via an intrinsic, but this has been shown
// to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic
let (a, b) = self.overflowing_add(rhs);
let (c, d) = a.overflowing_add(carry as $SelfT);
(c, b | d)
}
/// Calculates `self` - `rhs`
///
/// Returns a tuple of the subtraction along with a boolean indicating
@ -1433,6 +1463,36 @@ macro_rules! uint_impl {
(a as Self, b)
}
/// Calculates `self - rhs - borrow` without the ability to overflow.
///
/// Performs "ternary subtraction" which takes in an extra bit to subtract, and may return
/// an additional bit of overflow. This allows for chaining together multiple subtractions
/// to create "big integers" which represent larger values.
///
/// # Examples
///
/// Basic usage
///
/// ```
/// #![feature(bigint_helper_methods)]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, false), (3, false));")]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, true), (2, false));")]
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, false), (", stringify!($SelfT), "::MAX, true));")]
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, true), (", stringify!($SelfT), "::MAX - 1, true));")]
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn borrowing_sub(self, rhs: Self, borrow: bool) -> (Self, bool) {
// note: longer-term this should be done via an intrinsic, but this has been shown
// to generate optimal code for now, and LLVM doesn't have an equivalent intrinsic
let (a, b) = self.overflowing_sub(rhs);
let (c, d) = a.overflowing_sub(borrow as $SelfT);
(c, b | d)
}
/// Calculates the multiplication of `self` and `rhs`.
///
/// Returns a tuple of the multiplication along with a boolean

View file

@ -401,6 +401,53 @@ impl TcpStream {
self.0.peek(buf)
}
/// Sets the value of the `SO_LINGER` option on this socket.
///
/// This value controls how the socket is closed when data remains
/// to be sent. If `SO_LINGER` is set, the socket will remain open
/// for the specified duration as the system attempts to send pending data.
/// Otherwise, the system may close the socket immediately, or wait for a
/// default timeout.
///
/// # Examples
///
/// ```no_run
/// #![feature(tcp_linger)]
///
/// use std::net::TcpStream;
/// use std::time::Duration;
///
/// let stream = TcpStream::connect("127.0.0.1:8080")
/// .expect("Couldn't connect to the server...");
/// stream.set_linger(Some(Duration::from_secs(0))).expect("set_linger call failed");
/// ```
#[unstable(feature = "tcp_linger", issue = "88494")]
pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
self.0.set_linger(linger)
}
/// Gets the value of the `SO_LINGER` option on this socket.
///
/// For more information about this option, see [`TcpStream::set_linger`].
///
/// # Examples
///
/// ```no_run
/// #![feature(tcp_linger)]
///
/// use std::net::TcpStream;
/// use std::time::Duration;
///
/// let stream = TcpStream::connect("127.0.0.1:8080")
/// .expect("Couldn't connect to the server...");
/// stream.set_linger(Some(Duration::from_secs(0))).expect("set_linger call failed");
/// assert_eq!(stream.linger().unwrap(), Some(Duration::from_secs(0)));
/// ```
#[unstable(feature = "tcp_linger", issue = "88494")]
pub fn linger(&self) -> io::Result<Option<Duration>> {
self.0.linger()
}
/// Sets the value of the `TCP_NODELAY` option on this socket.
///
/// If set, this option disables the Nagle algorithm. This means that

View file

@ -767,6 +767,21 @@ fn test_timeout_zero_duration() {
drop(listener);
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)]
fn linger() {
let addr = next_test_ip4();
let _listener = t!(TcpListener::bind(&addr));
let stream = t!(TcpStream::connect(&("localhost", addr.port())));
assert_eq!(None, t!(stream.linger()));
t!(stream.set_linger(Some(Duration::from_secs(1))));
assert_eq!(Some(Duration::from_secs(1)), t!(stream.linger()));
t!(stream.set_linger(None));
assert_eq!(None, t!(stream.linger()));
}
#[test]
#[cfg_attr(target_env = "sgx", ignore)]
fn nodelay() {

View file

@ -39,7 +39,7 @@ use crate::time::Duration;
///
/// fn main() -> std::io::Result<()> {
/// {
/// let mut socket = UdpSocket::bind("127.0.0.1:34254")?;
/// let socket = UdpSocket::bind("127.0.0.1:34254")?;
///
/// // Receives a single datagram message on the socket. If `buf` is too small to hold
/// // the message, it will be cut off.

View file

@ -182,6 +182,14 @@ impl TcpStream {
Ok(self.clone())
}
pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
unsupported()
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
unsupported()
}
pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
.map_err(|_| io::Error::new_const(ErrorKind::Uncategorized, &"set_nodelay failed"))

View file

@ -183,6 +183,14 @@ impl TcpStream {
Ok(self.clone())
}
pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
sgx_ineffective(())
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
sgx_ineffective(None)
}
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
sgx_ineffective(())
}

View file

@ -98,6 +98,14 @@ pub mod net {
unimpl!();
}
pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
unimpl!();
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
unimpl!();
}
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
unimpl!();
}
@ -214,6 +222,14 @@ pub mod net {
unimpl!();
}
pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
unimpl!();
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
unimpl!();
}
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
unimpl!();
}

View file

@ -12,6 +12,14 @@ use crate::time::{Duration, Instant};
use libc::{c_int, c_void, size_t, sockaddr, socklen_t, MSG_PEEK};
cfg_if::cfg_if! {
if #[cfg(target_vendor = "apple")] {
use libc::SO_LINGER_SEC as SO_LINGER;
} else {
use libc::SO_LINGER;
}
}
pub use crate::sys::{cvt, cvt_r};
#[allow(unused_extern_crates)]
@ -376,6 +384,21 @@ impl Socket {
Ok(())
}
pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
let linger = libc::linger {
l_onoff: linger.is_some() as libc::c_int,
l_linger: linger.unwrap_or_default().as_secs() as libc::c_int,
};
setsockopt(self, libc::SOL_SOCKET, SO_LINGER, linger)
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
let val: libc::linger = getsockopt(self, libc::SOL_SOCKET, SO_LINGER)?;
Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
}
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
setsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as c_int)
}

View file

@ -76,6 +76,14 @@ impl TcpStream {
self.0
}
pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
self.0
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
self.0
}
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
self.0
}

View file

@ -127,6 +127,14 @@ impl TcpStream {
unsupported()
}
pub fn set_linger(&self, _: Option<Duration>) -> io::Result<()> {
unsupported()
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
unsupported()
}
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
unsupported()
}

View file

@ -197,6 +197,7 @@ pub const SOCK_DGRAM: c_int = 2;
pub const SOCK_STREAM: c_int = 1;
pub const SOCKET_ERROR: c_int = -1;
pub const SOL_SOCKET: c_int = 0xffff;
pub const SO_LINGER: c_int = 0x0080;
pub const SO_RCVTIMEO: c_int = 0x1006;
pub const SO_SNDTIMEO: c_int = 0x1005;
pub const IPPROTO_IP: c_int = 0;
@ -216,6 +217,13 @@ pub const IPV6_ADD_MEMBERSHIP: c_int = 12;
pub const IPV6_DROP_MEMBERSHIP: c_int = 13;
pub const MSG_PEEK: c_int = 0x2;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct linger {
pub l_onoff: c_ushort,
pub l_linger: c_ushort,
}
#[repr(C)]
pub struct ip_mreq {
pub imr_multiaddr: in_addr,

View file

@ -15,7 +15,7 @@ use crate::sys_common::net;
use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::time::Duration;
use libc::{c_int, c_long, c_ulong};
use libc::{c_int, c_long, c_ulong, c_ushort};
pub type wrlen_t = i32;
@ -446,6 +446,21 @@ impl Socket {
cvt(result).map(drop)
}
pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
let linger = c::linger {
l_onoff: linger.is_some() as c_ushort,
l_linger: linger.unwrap_or_default().as_secs() as c_ushort,
};
net::setsockopt(self, c::SOL_SOCKET, c::SO_LINGER, linger)
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
let val: c::linger = net::getsockopt(self, c::SOL_SOCKET, c::SO_LINGER)?;
Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64)))
}
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
net::setsockopt(self, c::IPPROTO_TCP, c::TCP_NODELAY, nodelay as c::BYTE)
}

View file

@ -297,6 +297,14 @@ impl TcpStream {
self.inner.duplicate().map(|s| TcpStream { inner: s })
}
pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
self.inner.set_linger(linger)
}
pub fn linger(&self) -> io::Result<Option<Duration>> {
self.inner.linger()
}
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
self.inner.set_nodelay(nodelay)
}

View file

@ -1702,12 +1702,28 @@ impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
}
}
impl Clean<Vec<Item>> for hir::VariantData<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
self.fields().iter().map(|x| x.clean(cx)).collect()
}
}
impl Clean<Item> for ty::VariantDef {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let kind = match self.ctor_kind {
CtorKind::Const => Variant::CLike,
CtorKind::Fn => Variant::Tuple(
self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect(),
self.fields
.iter()
.map(|field| {
let name = Some(field.ident.name);
let kind = StructFieldItem(cx.tcx.type_of(field.did).clean(cx));
let what_rustc_thinks =
Item::from_def_id_and_parts(field.did, name, kind, cx);
// don't show `pub` for fields, which are always public
Item { visibility: Visibility::Inherited, ..what_rustc_thinks }
})
.collect(),
),
CtorKind::Fictive => Variant::Struct(VariantStruct {
struct_type: CtorKind::Fictive,
@ -1737,13 +1753,7 @@ impl Clean<Variant> for hir::VariantData<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Variant {
match self {
hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)),
// Important note here: `Variant::Tuple` is used on tuple structs which are not in an
// enum (so where converting from `ty::VariantDef`). In case we are in an enum, the kind
// is provided by the `Variant` wrapper directly, and since we need the fields' name
// (even for a tuple struct variant!), it's simpler to just store it as a
// `Variant::Struct` instead of a `Variant::Tuple` (otherwise it would force us to make
// a lot of changes when rendering them to generate the name as well).
hir::VariantData::Tuple(..) => Variant::Struct(self.clean(cx)),
hir::VariantData::Tuple(..) => Variant::Tuple(self.clean(cx)),
hir::VariantData::Unit(..) => Variant::CLike,
}
}

View file

@ -715,6 +715,7 @@ impl ItemKind {
StructItem(s) => s.fields.iter(),
UnionItem(u) => u.fields.iter(),
VariantItem(Variant::Struct(v)) => v.fields.iter(),
VariantItem(Variant::Tuple(v)) => v.iter(),
EnumItem(e) => e.variants.iter(),
TraitItem(t) => t.items.iter(),
ImplItem(i) => i.items.iter(),
@ -1937,7 +1938,7 @@ crate struct Enum {
#[derive(Clone, Debug)]
crate enum Variant {
CLike,
Tuple(Vec<Type>),
Tuple(Vec<Item>),
Struct(VariantStruct),
}

View file

@ -56,6 +56,10 @@ crate trait DocFolder: Sized {
|| j.fields.iter().any(|f| f.is_stripped());
VariantItem(Variant::Struct(j))
}
Variant::Tuple(fields) => {
let fields = fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
VariantItem(Variant::Tuple(fields))
}
_ => VariantItem(i2),
}
}

View file

@ -937,6 +937,19 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
document_type_layout(w, cx, def_id);
}
fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]) {
for (i, ty) in s
.iter()
.map(|f| if let clean::StructFieldItem(ref ty) = *f.kind { ty } else { unreachable!() })
.enumerate()
{
if i > 0 {
w.write_str(",&nbsp;");
}
write!(w, "{}", ty.print(cx));
}
}
fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
wrap_into_docblock(w, |w| {
wrap_item(w, "enum", |w| {
@ -964,14 +977,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
match *v.kind {
clean::VariantItem(ref var) => match var {
clean::Variant::CLike => write!(w, "{}", name),
clean::Variant::Tuple(ref tys) => {
clean::Variant::Tuple(ref s) => {
write!(w, "{}(", name);
for (i, ty) in tys.iter().enumerate() {
if i > 0 {
w.write_str(",&nbsp;")
}
write!(w, "{}", ty.print(cx));
}
print_tuple_struct_fields(w, cx, s);
w.write_str(")");
}
clean::Variant::Struct(ref s) => {
@ -1024,14 +1032,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
id = id,
name = variant.name.as_ref().unwrap()
);
if let clean::VariantItem(clean::Variant::Tuple(ref tys)) = *variant.kind {
if let clean::VariantItem(clean::Variant::Tuple(ref s)) = *variant.kind {
w.write_str("(");
for (i, ty) in tys.iter().enumerate() {
if i > 0 {
w.write_str(",&nbsp;");
}
write!(w, "{}", ty.print(cx));
}
print_tuple_struct_fields(w, cx, s);
w.write_str(")");
}
w.write_str("</code>");
@ -1041,7 +1044,11 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
document_non_exhaustive(w, variant);
use crate::clean::Variant;
if let clean::VariantItem(Variant::Struct(ref s)) = *variant.kind {
if let Some((extra, fields)) = match *variant.kind {
clean::VariantItem(Variant::Struct(ref s)) => Some(("", &s.fields)),
clean::VariantItem(Variant::Tuple(ref fields)) => Some(("Tuple ", fields)),
_ => None,
} {
let variant_id = cx.derive_id(format!(
"{}.{}.fields",
ItemType::Variant,
@ -1051,10 +1058,10 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
write!(
w,
"<h3>{extra}Fields of <b>{name}</b></h3><div>",
extra = if s.struct_type == CtorKind::Fn { "Tuple " } else { "" },
extra = extra,
name = variant.name.as_ref().unwrap(),
);
for field in &s.fields {
for field in fields {
use crate::clean::StructFieldItem;
if let StructFieldItem(ref ty) = *field.kind {
let id = cx.derive_id(format!(

View file

@ -569,7 +569,18 @@ impl FromWithTcx<clean::Variant> for Variant {
use clean::Variant::*;
match variant {
CLike => Variant::Plain,
Tuple(t) => Variant::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
Tuple(fields) => Variant::Tuple(
fields
.into_iter()
.map(|f| {
if let clean::StructFieldItem(ty) = *f.kind {
ty.into_tcx(tcx)
} else {
unreachable!()
}
})
.collect(),
),
Struct(s) => Variant::Struct(ids(s.fields)),
}
}

View file

@ -94,8 +94,8 @@ impl<'a> DocFolder for Stripper<'a> {
// implementations of traits are always public.
clean::ImplItem(ref imp) if imp.trait_.is_some() => true,
// Struct variant fields have inherited visibility
clean::VariantItem(clean::Variant::Struct(..)) => true,
// Variant fields have inherited visibility
clean::VariantItem(clean::Variant::Struct(..) | clean::Variant::Tuple(..)) => true,
_ => false,
};

View file

@ -0,0 +1,11 @@
// @has variant_struct.json "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\"
// @has - "$.index[*][?(@.name=='EnumStruct')].kind" \"enum\"
pub enum EnumStruct {
// @has - "$.index[*][?(@.name=='VariantS')].inner.variant_kind" \"struct\"
// @has - "$.index[*][?(@.name=='x')]"
// @has - "$.index[*][?(@.name=='y')]"
VariantS {
x: u32,
y: String,
},
}

View file

@ -0,0 +1,6 @@
// @has variant_tuple_struct.json "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\"
// @has - "$.index[*][?(@.name=='EnumTupleStruct')].kind" \"enum\"
pub enum EnumTupleStruct {
// @has - "$.index[*][?(@.name=='VariantA')].inner.variant_kind" \"tuple\"
VariantA(u32, String),
}

View file

@ -1,41 +1,47 @@
error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:24:1
--> $DIR/unsupported.rs:26:1
|
LL | extern "ptx-kernel" fn ptx() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:26:1
--> $DIR/unsupported.rs:28:1
|
LL | extern "amdgpu-kernel" fn amdgpu() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"wasm"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:28:1
--> $DIR/unsupported.rs:30:1
|
LL | extern "wasm" fn wasm() {}
| ^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"aapcs"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:32:1
|
LL | extern "aapcs" fn aapcs() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:33:1
--> $DIR/unsupported.rs:36:1
|
LL | extern "msp430-interrupt" fn msp430() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:35:1
--> $DIR/unsupported.rs:38:1
|
LL | extern "avr-interrupt" fn avr() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:37:1
--> $DIR/unsupported.rs:40:1
|
LL | extern "x86-interrupt" fn x86() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of calling convention not supported on this target
--> $DIR/unsupported.rs:39:1
--> $DIR/unsupported.rs:43:1
|
LL | extern "stdcall" fn stdcall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -45,7 +51,7 @@ LL | extern "stdcall" fn stdcall() {}
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
warning: use of calling convention not supported on this target
--> $DIR/unsupported.rs:44:1
--> $DIR/unsupported.rs:50:1
|
LL | extern "thiscall" fn thiscall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -53,6 +59,6 @@ LL | extern "thiscall" fn thiscall() {}
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
error: aborting due to 6 previous errors; 2 warnings emitted
error: aborting due to 7 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0570`.

View file

@ -0,0 +1,58 @@
error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:26:1
|
LL | extern "ptx-kernel" fn ptx() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:28:1
|
LL | extern "amdgpu-kernel" fn amdgpu() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"wasm"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:30:1
|
LL | extern "wasm" fn wasm() {}
| ^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:36:1
|
LL | extern "msp430-interrupt" fn msp430() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:38:1
|
LL | extern "avr-interrupt" fn avr() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"x86-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:40:1
|
LL | extern "x86-interrupt" fn x86() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of calling convention not supported on this target
--> $DIR/unsupported.rs:43:1
|
LL | extern "stdcall" fn stdcall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unsupported_calling_conventions)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
warning: use of calling convention not supported on this target
--> $DIR/unsupported.rs:50:1
|
LL | extern "thiscall" fn thiscall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
error: aborting due to 6 previous errors; 2 warnings emitted
For more information about this error, try `rustc --explain E0570`.

View file

@ -1,35 +1,35 @@
error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:24:1
--> $DIR/unsupported.rs:26:1
|
LL | extern "ptx-kernel" fn ptx() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:26:1
--> $DIR/unsupported.rs:28:1
|
LL | extern "amdgpu-kernel" fn amdgpu() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"wasm"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:28:1
--> $DIR/unsupported.rs:30:1
|
LL | extern "wasm" fn wasm() {}
| ^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"aapcs"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:30:1
--> $DIR/unsupported.rs:32:1
|
LL | extern "aapcs" fn aapcs() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:33:1
--> $DIR/unsupported.rs:36:1
|
LL | extern "msp430-interrupt" fn msp430() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:35:1
--> $DIR/unsupported.rs:38:1
|
LL | extern "avr-interrupt" fn avr() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,11 +1,13 @@
// revisions: x64 i686 aarch64
// revisions: x64 i686 aarch64 arm
//
// [x64] needs-llvm-components: x86
// [x64]compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib
// [x64] compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib
// [i686] needs-llvm-components: x86
// [i686]compile-flags: --target=i686-unknown-linux-gnu --crate-type=rlib
// [i686] compile-flags: --target=i686-unknown-linux-gnu --crate-type=rlib
// [aarch64] needs-llvm-components: aarch64
// [aarch64]compile-flags: --target=aarch64-unknown-linux-gnu --crate-type=rlib
// [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu --crate-type=rlib
// [arm] needs-llvm-components: arm
// [arm] compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib
#![no_core]
#![feature(
no_core,
@ -30,19 +32,25 @@ extern "wasm" fn wasm() {}
extern "aapcs" fn aapcs() {}
//[x64]~^ ERROR is not a supported ABI
//[i686]~^^ ERROR is not a supported ABI
//[aarch64]~^^^ ERROR is not a supported ABI
extern "msp430-interrupt" fn msp430() {}
//~^ ERROR is not a supported ABI
extern "avr-interrupt" fn avr() {}
//~^ ERROR is not a supported ABI
extern "x86-interrupt" fn x86() {}
//[aarch64]~^ ERROR is not a supported ABI
//[arm]~^^ ERROR is not a supported ABI
extern "stdcall" fn stdcall() {}
//[x64]~^ WARN use of calling convention not supported
//[x64]~^^ WARN this was previously accepted
//[aarch64]~^^^ WARN use of calling convention not supported
//[aarch64]~^^^^ WARN this was previously accepted
//[arm]~^^^^^ WARN use of calling convention not supported
//[arm]~^^^^^^ WARN this was previously accepted
extern "thiscall" fn thiscall() {}
//[x64]~^ WARN use of calling convention not supported
//[x64]~^^ WARN this was previously accepted
//[aarch64]~^^^ WARN use of calling convention not supported
//[aarch64]~^^^^ WARN this was previously accepted
//[arm]~^^^^^ WARN use of calling convention not supported
//[arm]~^^^^^^ WARN this was previously accepted

View file

@ -1,41 +1,41 @@
error[E0570]: `"ptx-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:24:1
--> $DIR/unsupported.rs:26:1
|
LL | extern "ptx-kernel" fn ptx() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"amdgpu-kernel"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:26:1
--> $DIR/unsupported.rs:28:1
|
LL | extern "amdgpu-kernel" fn amdgpu() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"wasm"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:28:1
--> $DIR/unsupported.rs:30:1
|
LL | extern "wasm" fn wasm() {}
| ^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"aapcs"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:30:1
--> $DIR/unsupported.rs:32:1
|
LL | extern "aapcs" fn aapcs() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"msp430-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:33:1
--> $DIR/unsupported.rs:36:1
|
LL | extern "msp430-interrupt" fn msp430() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0570]: `"avr-interrupt"` is not a supported ABI for the current target
--> $DIR/unsupported.rs:35:1
--> $DIR/unsupported.rs:38:1
|
LL | extern "avr-interrupt" fn avr() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: use of calling convention not supported on this target
--> $DIR/unsupported.rs:39:1
--> $DIR/unsupported.rs:43:1
|
LL | extern "stdcall" fn stdcall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -45,7 +45,7 @@ LL | extern "stdcall" fn stdcall() {}
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
warning: use of calling convention not supported on this target
--> $DIR/unsupported.rs:44:1
--> $DIR/unsupported.rs:50:1
|
LL | extern "thiscall" fn thiscall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -4,7 +4,7 @@ error: `~const` is not allowed here
LL | fn rpit() -> impl ~const T { S }
| ^^^^^^^^
|
= note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions
= note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:11:17
@ -12,7 +12,7 @@ error: `~const` is not allowed here
LL | fn apit(_: impl ~const T) {}
| ^^^^^^^^
|
= note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions
= note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:14:50
@ -20,7 +20,7 @@ error: `~const` is not allowed here
LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
| ^^^^^^^^
|
= note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions
= note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:17:48
@ -28,7 +28,7 @@ error: `~const` is not allowed here
LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
| ^^^^^^^^
|
= note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions
= note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:20:15
@ -36,7 +36,7 @@ error: `~const` is not allowed here
LL | fn generic<P: ~const T>() {}
| ^^^^^^^^
|
= note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions
= note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
error: `~const` is not allowed here
--> $DIR/tilde-const-invalid-places.rs:23:31
@ -44,7 +44,7 @@ error: `~const` is not allowed here
LL | fn where_clause<P>() where P: ~const T {}
| ^^^^^^^^
|
= note: only allowed on bounds on traits' associated types, const fns, const impls and its associated functions
= note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
error: `~const` and `?` are mutually exclusive
--> $DIR/tilde-const-invalid-places.rs:26:25

View file

@ -0,0 +1,41 @@
// run-pass
#![feature(const_trait_impl)]
#![feature(const_fn_trait_bound)]
trait Bar {
fn bar() -> u8;
}
trait Foo {
#[default_method_body_is_const]
fn foo() -> u8 where Self: ~const Bar {
<Self as Bar>::bar() * 6
}
}
struct NonConst;
struct Const;
impl Bar for NonConst {
fn bar() -> u8 {
3
}
}
impl Foo for NonConst {}
impl const Bar for Const {
fn bar() -> u8 {
4
}
}
impl const Foo for Const {}
fn main() {
const ANS1: u8 = Const::foo();
let ans2 = NonConst::foo();
assert_eq!(ANS1 + ans2, 42);
}

View file

@ -0,0 +1,24 @@
// check-pass
#![feature(const_trait_impl)]
#![feature(const_fn_trait_bound)]
trait Foo {
fn bar() where Self: ~const Foo;
}
struct S;
impl Foo for S {
fn bar() {}
}
fn baz<T: Foo>() {
T::bar();
}
const fn qux<T: ~const Foo>() {
T::bar();
}
fn main() {}

View file

@ -0,0 +1,40 @@
#![feature(const_fn_trait_bound)]
#![feature(const_trait_impl)]
trait Bar {}
trait Foo {
fn a();
fn b() where Self: ~const Bar;
fn c<T: ~const Bar>();
}
const fn test1<T: ~const Foo + Bar>() {
T::a();
T::b();
//~^ ERROR the trait bound
T::c::<T>();
//~^ ERROR the trait bound
}
const fn test2<T: ~const Foo + ~const Bar>() {
T::a();
T::b();
T::c::<T>();
}
fn test3<T: Foo>() {
T::a();
T::b();
//~^ ERROR the trait bound
T::c::<T>();
//~^ ERROR the trait bound
}
fn test4<T: Foo + Bar>() {
T::a();
T::b();
T::c::<T>();
}
fn main() {}

View file

@ -0,0 +1,67 @@
error[E0277]: the trait bound `T: Bar` is not satisfied
--> $DIR/trait-where-clause.rs:14:5
|
LL | T::b();
| ^^^^ the trait `Bar` is not implemented for `T`
|
note: required by `Foo::b`
--> $DIR/trait-where-clause.rs:8:5
|
LL | fn b() where Self: ~const Bar;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider further restricting this bound
|
LL | const fn test1<T: ~const Foo + Bar + Bar>() {
| +++++
error[E0277]: the trait bound `T: Bar` is not satisfied
--> $DIR/trait-where-clause.rs:16:5
|
LL | T::c::<T>();
| ^^^^^^^^^ the trait `Bar` is not implemented for `T`
|
note: required by `Foo::c`
--> $DIR/trait-where-clause.rs:9:5
|
LL | fn c<T: ~const Bar>();
| ^^^^^^^^^^^^^^^^^^^^^^
help: consider further restricting this bound
|
LL | const fn test1<T: ~const Foo + Bar + Bar>() {
| +++++
error[E0277]: the trait bound `T: Bar` is not satisfied
--> $DIR/trait-where-clause.rs:28:5
|
LL | T::b();
| ^^^^ the trait `Bar` is not implemented for `T`
|
note: required by `Foo::b`
--> $DIR/trait-where-clause.rs:8:5
|
LL | fn b() where Self: ~const Bar;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider further restricting this bound
|
LL | fn test3<T: Foo + Bar>() {
| +++++
error[E0277]: the trait bound `T: Bar` is not satisfied
--> $DIR/trait-where-clause.rs:30:5
|
LL | T::c::<T>();
| ^^^^^^^^^ the trait `Bar` is not implemented for `T`
|
note: required by `Foo::c`
--> $DIR/trait-where-clause.rs:9:5
|
LL | fn c<T: ~const Bar>();
| ^^^^^^^^^^^^^^^^^^^^^^
help: consider further restricting this bound
|
LL | fn test3<T: Foo + Bar>() {
| +++++
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -0,0 +1,45 @@
// run-rustfix
// edition:2018
// check-pass
#![warn(rust_2021_prelude_collisions)]
#![allow(unreachable_code)]
macro_rules! foo {
() => {{
123;
S
}};
}
trait MyTry<T> {
fn try_into(self, _: u8);
}
struct S;
impl MyTry<i32> for S {
fn try_into(self, _: u8) {}
}
trait TryFromU8: Sized {
fn try_from(_: u8);
}
impl TryFromU8 for u32 {
fn try_from(_: u8) {}
}
macro_rules! bar {
() => {
u32
};
}
fn main() {
MyTry::try_into(foo!(), todo!());
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
//~| WARNING this is accepted in the current edition
<bar!() as TryFromU8>::try_from(0);
//~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
//~| WARNING this is accepted in the current edition
}

View file

@ -0,0 +1,45 @@
// run-rustfix
// edition:2018
// check-pass
#![warn(rust_2021_prelude_collisions)]
#![allow(unreachable_code)]
macro_rules! foo {
() => {{
123;
S
}};
}
trait MyTry<T> {
fn try_into(self, _: u8);
}
struct S;
impl MyTry<i32> for S {
fn try_into(self, _: u8) {}
}
trait TryFromU8: Sized {
fn try_from(_: u8);
}
impl TryFromU8 for u32 {
fn try_from(_: u8) {}
}
macro_rules! bar {
() => {
u32
};
}
fn main() {
foo!().try_into(todo!());
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
//~| WARNING this is accepted in the current edition
<bar!()>::try_from(0);
//~^ WARNING trait-associated function `try_from` will become ambiguous in Rust 2021
//~| WARNING this is accepted in the current edition
}

View file

@ -0,0 +1,25 @@
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-macros.rs:39:5
|
LL | foo!().try_into(todo!());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `MyTry::try_into(foo!(), todo!())`
|
note: the lint level is defined here
--> $DIR/future-prelude-collision-macros.rs:4:9
|
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait-associated function `try_from` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-macros.rs:42:5
|
LL | <bar!()>::try_from(0);
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<bar!() as TryFromU8>::try_from`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: 2 warnings emitted

View file

@ -0,0 +1,28 @@
// See https://github.com/rust-lang/rust/issues/88442
// run-rustfix
// edition:2018
// check-pass
#![allow(unused)]
#![warn(rust_2021_prelude_collisions)]
trait AnnotatableTryInto {
fn try_into<T>(self) -> Result<T, Self::Error>
where Self: std::convert::TryInto<T> {
std::convert::TryInto::try_into(self)
}
}
impl<T> AnnotatableTryInto for T where T: From<u8> {}
fn main() -> Result<(), &'static str> {
let x: u64 = 1;
AnnotatableTryInto::try_into::<usize>(x).or(Err("foo"))?.checked_sub(1);
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
//~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
AnnotatableTryInto::try_into::<usize>(x).or(Err("foo"))?;
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
//~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
Ok(())
}

View file

@ -0,0 +1,28 @@
// See https://github.com/rust-lang/rust/issues/88442
// run-rustfix
// edition:2018
// check-pass
#![allow(unused)]
#![warn(rust_2021_prelude_collisions)]
trait AnnotatableTryInto {
fn try_into<T>(self) -> Result<T, Self::Error>
where Self: std::convert::TryInto<T> {
std::convert::TryInto::try_into(self)
}
}
impl<T> AnnotatableTryInto for T where T: From<u8> {}
fn main() -> Result<(), &'static str> {
let x: u64 = 1;
x.try_into::<usize>().or(Err("foo"))?.checked_sub(1);
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
//~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
x.try_into::<usize>().or(Err("foo"))?;
//~^ WARNING trait method `try_into` will become ambiguous in Rust 2021
//~| WARNING this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
Ok(())
}

View file

@ -0,0 +1,25 @@
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-turbofish.rs:19:5
|
LL | x.try_into::<usize>().or(Err("foo"))?.checked_sub(1);
| ^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `AnnotatableTryInto::try_into::<usize>(x)`
|
note: the lint level is defined here
--> $DIR/future-prelude-collision-turbofish.rs:6:9
|
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-turbofish.rs:23:5
|
LL | x.try_into::<usize>().or(Err("foo"))?;
| ^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `AnnotatableTryInto::try_into::<usize>(x)`
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: 2 warnings emitted