mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Auto merge of #115909 - Dylan-DPC:rollup-uf96r2d, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #114965 (Remove Drop impl of mpsc Receiver and (Sync)Sender) - #115434 (make `Debug` impl for `ascii::Char` match that of `char`) - #115477 (Stabilize the `Saturating` type) - #115611 (add diagnostic for raw identifiers in format string) - #115654 (improve PassMode docs) - #115862 (Migrate `compiler/rustc_hir_typeck/src/callee.rs` to translatable diagnostics) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
db9c21fd94
@ -137,6 +137,8 @@ builtin_macros_format_positional_after_named = positional arguments cannot follo
|
||||
.label = positional arguments must be before named arguments
|
||||
.named_args = named argument
|
||||
|
||||
builtin_macros_format_remove_raw_ident = remove the `r#`
|
||||
|
||||
builtin_macros_format_requires_string = requires at least a format string argument
|
||||
|
||||
builtin_macros_format_string_invalid = invalid format string: {$desc}
|
||||
@ -165,6 +167,8 @@ builtin_macros_format_unused_arg = {$named ->
|
||||
builtin_macros_format_unused_args = multiple unused formatting arguments
|
||||
.label = multiple missing formatting specifiers
|
||||
|
||||
builtin_macros_format_use_positional = consider using a positional formatting argument instead
|
||||
|
||||
builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
|
||||
|
||||
builtin_macros_invalid_crate_attribute = invalid crate attribute
|
||||
@ -205,8 +209,6 @@ builtin_macros_requires_cfg_pattern =
|
||||
|
||||
builtin_macros_should_panic = functions using `#[should_panic]` must return `()`
|
||||
|
||||
builtin_macros_sugg = consider using a positional formatting argument instead
|
||||
|
||||
builtin_macros_test_arg_non_lifetime = functions used as tests can not have any non-lifetime generic parameters
|
||||
|
||||
builtin_macros_test_args = functions used as tests can not have any arguments
|
||||
|
@ -539,18 +539,29 @@ pub(crate) struct InvalidFormatStringLabel {
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
builtin_macros_sugg,
|
||||
style = "verbose",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
pub(crate) struct InvalidFormatStringSuggestion {
|
||||
#[suggestion_part(code = "{len}")]
|
||||
pub(crate) captured: Span,
|
||||
pub(crate) len: String,
|
||||
#[suggestion_part(code = ", {arg}")]
|
||||
pub(crate) span: Span,
|
||||
pub(crate) arg: String,
|
||||
pub(crate) enum InvalidFormatStringSuggestion {
|
||||
#[multipart_suggestion(
|
||||
builtin_macros_format_use_positional,
|
||||
style = "verbose",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
UsePositional {
|
||||
#[suggestion_part(code = "{len}")]
|
||||
captured: Span,
|
||||
len: String,
|
||||
#[suggestion_part(code = ", {arg}")]
|
||||
span: Span,
|
||||
arg: String,
|
||||
},
|
||||
#[suggestion(
|
||||
builtin_macros_format_remove_raw_ident,
|
||||
code = "",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
RemoveRawIdent {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
@ -260,20 +260,29 @@ fn make_format_args(
|
||||
if let Some((label, span)) = err.secondary_label && is_source_literal {
|
||||
e.label_ = Some(errors::InvalidFormatStringLabel { span: fmt_span.from_inner(InnerSpan::new(span.start, span.end)), label } );
|
||||
}
|
||||
if err.should_be_replaced_with_positional_argument {
|
||||
let captured_arg_span =
|
||||
fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end));
|
||||
if let Ok(arg) = ecx.source_map().span_to_snippet(captured_arg_span) {
|
||||
let span = match args.unnamed_args().last() {
|
||||
Some(arg) => arg.expr.span,
|
||||
None => fmt_span,
|
||||
};
|
||||
e.sugg_ = Some(errors::InvalidFormatStringSuggestion {
|
||||
captured: captured_arg_span,
|
||||
len: args.unnamed_args().len().to_string(),
|
||||
span: span.shrink_to_hi(),
|
||||
arg,
|
||||
});
|
||||
match err.suggestion {
|
||||
parse::Suggestion::None => {}
|
||||
parse::Suggestion::UsePositional => {
|
||||
let captured_arg_span =
|
||||
fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end));
|
||||
if let Ok(arg) = ecx.source_map().span_to_snippet(captured_arg_span) {
|
||||
let span = match args.unnamed_args().last() {
|
||||
Some(arg) => arg.expr.span,
|
||||
None => fmt_span,
|
||||
};
|
||||
e.sugg_ = Some(errors::InvalidFormatStringSuggestion::UsePositional {
|
||||
captured: captured_arg_span,
|
||||
len: args.unnamed_args().len().to_string(),
|
||||
span: span.shrink_to_hi(),
|
||||
arg,
|
||||
});
|
||||
}
|
||||
}
|
||||
parse::Suggestion::RemoveRawIdent(span) => {
|
||||
if is_source_literal {
|
||||
let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end));
|
||||
e.sugg_ = Some(errors::InvalidFormatStringSuggestion::RemoveRawIdent { span })
|
||||
}
|
||||
}
|
||||
}
|
||||
ecx.emit_err(e);
|
||||
|
@ -100,11 +100,11 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
||||
}
|
||||
_ => unreachable!("{:?}", self.layout.abi),
|
||||
},
|
||||
PassMode::Cast(ref cast, pad_i32) => {
|
||||
PassMode::Cast { ref cast, pad_i32 } => {
|
||||
assert!(!pad_i32, "padding support not yet implemented");
|
||||
cast_target_to_abi_params(cast)
|
||||
}
|
||||
PassMode::Indirect { attrs, extra_attrs: None, on_stack } => {
|
||||
PassMode::Indirect { attrs, meta_attrs: None, on_stack } => {
|
||||
if on_stack {
|
||||
// Abi requires aligning struct size to pointer size
|
||||
let size = self.layout.size.align_to(tcx.data_layout.pointer_align.abi);
|
||||
@ -117,11 +117,11 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
||||
smallvec![apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs)]
|
||||
}
|
||||
}
|
||||
PassMode::Indirect { attrs, extra_attrs: Some(extra_attrs), on_stack } => {
|
||||
PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
|
||||
assert!(!on_stack);
|
||||
smallvec![
|
||||
apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs),
|
||||
apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), extra_attrs),
|
||||
apply_arg_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), meta_attrs),
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -148,14 +148,14 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
||||
}
|
||||
_ => unreachable!("{:?}", self.layout.abi),
|
||||
},
|
||||
PassMode::Cast(ref cast, _) => {
|
||||
PassMode::Cast { ref cast, .. } => {
|
||||
(None, cast_target_to_abi_params(cast).into_iter().collect())
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack } => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack } => {
|
||||
assert!(!on_stack);
|
||||
(Some(AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructReturn)), vec![])
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||
unreachable!("unsized return value")
|
||||
}
|
||||
}
|
||||
@ -229,7 +229,7 @@ pub(super) fn adjust_arg_for_abi<'tcx>(
|
||||
let (a, b) = arg.load_scalar_pair(fx);
|
||||
smallvec![a, b]
|
||||
}
|
||||
PassMode::Cast(ref cast, _) => to_casted_value(fx, arg, cast),
|
||||
PassMode::Cast { ref cast, .. } => to_casted_value(fx, arg, cast),
|
||||
PassMode::Indirect { .. } => {
|
||||
if is_owned {
|
||||
match arg.force_stack(fx) {
|
||||
@ -287,14 +287,14 @@ pub(super) fn cvalue_for_param<'tcx>(
|
||||
assert_eq!(block_params.len(), 2, "{:?}", block_params);
|
||||
Some(CValue::by_val_pair(block_params[0], block_params[1], arg_abi.layout))
|
||||
}
|
||||
PassMode::Cast(ref cast, _) => {
|
||||
PassMode::Cast { ref cast, .. } => {
|
||||
Some(from_casted_value(fx, &block_params, arg_abi.layout, cast))
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
|
||||
assert_eq!(block_params.len(), 1, "{:?}", block_params);
|
||||
Some(CValue::by_ref(Pointer::new(block_params[0]), arg_abi.layout))
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||
assert_eq!(block_params.len(), 2, "{:?}", block_params);
|
||||
Some(CValue::by_ref_unsized(
|
||||
Pointer::new(block_params[0]),
|
||||
|
@ -13,7 +13,7 @@ pub(super) fn codegen_return_param<'tcx>(
|
||||
block_params_iter: &mut impl Iterator<Item = Value>,
|
||||
) -> CPlace<'tcx> {
|
||||
let (ret_place, ret_param): (_, SmallVec<[_; 2]>) = match fx.fn_abi.as_ref().unwrap().ret.mode {
|
||||
PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(..) => {
|
||||
PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast { .. } => {
|
||||
let is_ssa =
|
||||
ssa_analyzed[RETURN_PLACE].is_ssa(fx, fx.fn_abi.as_ref().unwrap().ret.layout.ty);
|
||||
(
|
||||
@ -26,7 +26,7 @@ pub(super) fn codegen_return_param<'tcx>(
|
||||
smallvec![],
|
||||
)
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
|
||||
let ret_param = block_params_iter.next().unwrap();
|
||||
assert_eq!(fx.bcx.func.dfg.value_type(ret_param), fx.pointer_type);
|
||||
(
|
||||
@ -34,7 +34,7 @@ pub(super) fn codegen_return_param<'tcx>(
|
||||
smallvec![ret_param],
|
||||
)
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||
unreachable!("unsized return value")
|
||||
}
|
||||
};
|
||||
@ -62,7 +62,7 @@ pub(super) fn codegen_with_call_return_arg<'tcx>(
|
||||
) {
|
||||
let (ret_temp_place, return_ptr) = match ret_arg_abi.mode {
|
||||
PassMode::Ignore => (None, None),
|
||||
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
|
||||
if let Some(ret_ptr) = ret_place.try_to_ptr() {
|
||||
// This is an optimization to prevent unnecessary copies of the return value when
|
||||
// the return place is already a memory place as opposed to a register.
|
||||
@ -73,10 +73,10 @@ pub(super) fn codegen_with_call_return_arg<'tcx>(
|
||||
(Some(place), Some(place.to_ptr().get_addr(fx)))
|
||||
}
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||
unreachable!("unsized return value")
|
||||
}
|
||||
PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast(..) => (None, None),
|
||||
PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast { .. } => (None, None),
|
||||
};
|
||||
|
||||
let call_inst = f(fx, return_ptr);
|
||||
@ -93,21 +93,21 @@ pub(super) fn codegen_with_call_return_arg<'tcx>(
|
||||
ret_place
|
||||
.write_cvalue(fx, CValue::by_val_pair(ret_val_a, ret_val_b, ret_arg_abi.layout));
|
||||
}
|
||||
PassMode::Cast(ref cast, _) => {
|
||||
PassMode::Cast { ref cast, .. } => {
|
||||
let results =
|
||||
fx.bcx.inst_results(call_inst).iter().copied().collect::<SmallVec<[Value; 2]>>();
|
||||
let result =
|
||||
super::pass_mode::from_casted_value(fx, &results, ret_place.layout(), cast);
|
||||
ret_place.write_cvalue(fx, result);
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
|
||||
if let Some(ret_temp_place) = ret_temp_place {
|
||||
// If ret_temp_place is None, it is not necessary to copy the return value.
|
||||
let ret_temp_value = ret_temp_place.to_cvalue(fx);
|
||||
ret_place.write_cvalue(fx, ret_temp_value);
|
||||
}
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||
unreachable!("unsized return value")
|
||||
}
|
||||
}
|
||||
@ -116,10 +116,10 @@ pub(super) fn codegen_with_call_return_arg<'tcx>(
|
||||
/// Codegen a return instruction with the right return value(s) if any.
|
||||
pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, '_>) {
|
||||
match fx.fn_abi.as_ref().unwrap().ret.mode {
|
||||
PassMode::Ignore | PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
|
||||
PassMode::Ignore | PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
|
||||
fx.bcx.ins().return_(&[]);
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||
unreachable!("unsized return value")
|
||||
}
|
||||
PassMode::Direct(_) => {
|
||||
@ -132,7 +132,7 @@ pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, '_>) {
|
||||
let (ret_val_a, ret_val_b) = place.to_cvalue(fx).load_scalar_pair(fx);
|
||||
fx.bcx.ins().return_(&[ret_val_a, ret_val_b]);
|
||||
}
|
||||
PassMode::Cast(ref cast, _) => {
|
||||
PassMode::Cast { ref cast, .. } => {
|
||||
let place = fx.get_local_place(RETURN_PLACE);
|
||||
let ret_val = place.to_cvalue(fx);
|
||||
let ret_vals = super::pass_mode::to_casted_value(fx, ret_val, cast);
|
||||
|
@ -113,7 +113,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
match self.ret.mode {
|
||||
PassMode::Ignore => cx.type_void(),
|
||||
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_gcc_type(cx),
|
||||
PassMode::Cast(ref cast, _) => cast.gcc_type(cx),
|
||||
PassMode::Cast { ref cast, .. } => cast.gcc_type(cx),
|
||||
PassMode::Indirect { .. } => {
|
||||
argument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx)));
|
||||
cx.type_void()
|
||||
@ -129,21 +129,21 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 1));
|
||||
continue;
|
||||
}
|
||||
PassMode::Indirect { extra_attrs: Some(_), .. } => {
|
||||
PassMode::Indirect { meta_attrs: Some(_), .. } => {
|
||||
unimplemented!();
|
||||
}
|
||||
PassMode::Cast(ref cast, pad_i32) => {
|
||||
PassMode::Cast { ref cast, pad_i32 } => {
|
||||
// add padding
|
||||
if pad_i32 {
|
||||
argument_tys.push(Reg::i32().gcc_type(cx));
|
||||
}
|
||||
cast.gcc_type(cx)
|
||||
}
|
||||
PassMode::Indirect { extra_attrs: None, on_stack: true, .. } => {
|
||||
PassMode::Indirect { meta_attrs: None, on_stack: true, .. } => {
|
||||
on_stack_param_indices.insert(argument_tys.len());
|
||||
arg.memory_ty(cx)
|
||||
},
|
||||
PassMode::Indirect { extra_attrs: None, on_stack: false, .. } => cx.type_ptr_to(arg.memory_ty(cx)),
|
||||
PassMode::Indirect { meta_attrs: None, on_stack: false, .. } => cx.type_ptr_to(arg.memory_ty(cx)),
|
||||
};
|
||||
argument_tys.push(arg_ty);
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
sym::volatile_load | sym::unaligned_volatile_load => {
|
||||
let tp_ty = fn_args.type_at(0);
|
||||
let mut ptr = args[0].immediate();
|
||||
if let PassMode::Cast(ty, _) = &fn_abi.ret.mode {
|
||||
if let PassMode::Cast { cast: ty, .. } = &fn_abi.ret.mode {
|
||||
ptr = self.pointercast(ptr, self.type_ptr_to(ty.gcc_type(self)));
|
||||
}
|
||||
let load = self.volatile_load(ptr.get_type(), ptr);
|
||||
@ -353,7 +353,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
};
|
||||
|
||||
if !fn_abi.ret.is_ignore() {
|
||||
if let PassMode::Cast(ty, _) = &fn_abi.ret.mode {
|
||||
if let PassMode::Cast { cast: ty, .. } = &fn_abi.ret.mode {
|
||||
let ptr_llty = self.type_ptr_to(ty.gcc_type(self));
|
||||
let ptr = self.pointercast(result.llval, ptr_llty);
|
||||
self.store(llval, ptr, result.align);
|
||||
@ -449,7 +449,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
||||
else if self.is_unsized_indirect() {
|
||||
bug!("unsized `ArgAbi` must be handled through `store_fn_arg`");
|
||||
}
|
||||
else if let PassMode::Cast(ref cast, _) = self.mode {
|
||||
else if let PassMode::Cast { ref cast, .. } = self.mode {
|
||||
// FIXME(eddyb): Figure out when the simpler Store is safe, clang
|
||||
// uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
|
||||
let can_store_through_cast_ptr = false;
|
||||
@ -511,10 +511,10 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
||||
PassMode::Pair(..) => {
|
||||
OperandValue::Pair(next(), next()).store(bx, dst);
|
||||
},
|
||||
PassMode::Indirect { extra_attrs: Some(_), .. } => {
|
||||
PassMode::Indirect { meta_attrs: Some(_), .. } => {
|
||||
OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst);
|
||||
},
|
||||
PassMode::Direct(_) | PassMode::Indirect { extra_attrs: None, .. } | PassMode::Cast(..) => {
|
||||
PassMode::Direct(_) | PassMode::Indirect { meta_attrs: None, .. } | PassMode::Cast { .. } => {
|
||||
let next_arg = next();
|
||||
self.store(bx, next_arg, dst);
|
||||
},
|
||||
|
@ -211,7 +211,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
||||
OperandValue::Ref(val, None, self.layout.align.abi).store(bx, dst)
|
||||
} else if self.is_unsized_indirect() {
|
||||
bug!("unsized `ArgAbi` must be handled through `store_fn_arg`");
|
||||
} else if let PassMode::Cast(cast, _) = &self.mode {
|
||||
} else if let PassMode::Cast { cast, pad_i32: _ } = &self.mode {
|
||||
// FIXME(eddyb): Figure out when the simpler Store is safe, clang
|
||||
// uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
|
||||
let can_store_through_cast_ptr = false;
|
||||
@ -274,12 +274,12 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
||||
PassMode::Pair(..) => {
|
||||
OperandValue::Pair(next(), next()).store(bx, dst);
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||
OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst);
|
||||
}
|
||||
PassMode::Direct(_)
|
||||
| PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ }
|
||||
| PassMode::Cast(..) => {
|
||||
| PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ }
|
||||
| PassMode::Cast { .. } => {
|
||||
let next_arg = next();
|
||||
self.store(bx, next_arg, dst);
|
||||
}
|
||||
@ -332,7 +332,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
let llreturn_ty = match &self.ret.mode {
|
||||
PassMode::Ignore => cx.type_void(),
|
||||
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx),
|
||||
PassMode::Cast(cast, _) => cast.llvm_type(cx),
|
||||
PassMode::Cast { cast, pad_i32: _ } => cast.llvm_type(cx),
|
||||
PassMode::Indirect { .. } => {
|
||||
llargument_tys.push(cx.type_ptr());
|
||||
cx.type_void()
|
||||
@ -351,6 +351,11 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
// guarnateeing that we generate ABI-compatible LLVM IR. Things get tricky for
|
||||
// aggregates...
|
||||
if matches!(arg.layout.abi, abi::Abi::Aggregate { .. }) {
|
||||
assert!(
|
||||
arg.layout.is_sized(),
|
||||
"`PassMode::Direct` for unsized type: {}",
|
||||
arg.layout.ty
|
||||
);
|
||||
// This really shouldn't happen, since `immediate_llvm_type` will use
|
||||
// `layout.fields` to turn this Rust type into an LLVM type. This means all
|
||||
// sorts of Rust type details leak into the ABI. However wasm sadly *does*
|
||||
@ -378,8 +383,10 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true));
|
||||
continue;
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
|
||||
assert!(arg.layout.is_unsized());
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack } => {
|
||||
// `Indirect` with metadata is only for unsized types, and doesn't work with
|
||||
// on-stack passing.
|
||||
assert!(arg.layout.is_unsized() && !on_stack);
|
||||
// Construct the type of a (wide) pointer to `ty`, and pass its two fields.
|
||||
// Any two ABI-compatible unsized types have the same metadata type and
|
||||
// moreover the same metadata value leads to the same dynamic size and
|
||||
@ -390,7 +397,13 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 1, true));
|
||||
continue;
|
||||
}
|
||||
PassMode::Cast(cast, pad_i32) => {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
|
||||
assert!(arg.layout.is_sized());
|
||||
cx.type_ptr()
|
||||
}
|
||||
PassMode::Cast { cast, pad_i32 } => {
|
||||
// `Cast` means "transmute to `CastType`"; that only makes sense for sized types.
|
||||
assert!(arg.layout.is_sized());
|
||||
// add padding
|
||||
if *pad_i32 {
|
||||
llargument_tys.push(Reg::i32().llvm_type(cx));
|
||||
@ -399,7 +412,6 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
// We assume here that ABI-compatible Rust types have the same cast type.
|
||||
cast.llvm_type(cx)
|
||||
}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => cx.type_ptr(),
|
||||
};
|
||||
llargument_tys.push(llarg_ty);
|
||||
}
|
||||
@ -442,13 +454,13 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
PassMode::Direct(attrs) => {
|
||||
attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);
|
||||
}
|
||||
PassMode::Indirect { attrs, extra_attrs: _, on_stack } => {
|
||||
PassMode::Indirect { attrs, meta_attrs: _, on_stack } => {
|
||||
assert!(!on_stack);
|
||||
let i = apply(attrs);
|
||||
let sret = llvm::CreateStructRetAttr(cx.llcx, self.ret.layout.llvm_type(cx));
|
||||
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[sret]);
|
||||
}
|
||||
PassMode::Cast(cast, _) => {
|
||||
PassMode::Cast { cast, pad_i32: _ } => {
|
||||
cast.attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, cx, llfn);
|
||||
}
|
||||
_ => {}
|
||||
@ -456,25 +468,25 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
for arg in self.args.iter() {
|
||||
match &arg.mode {
|
||||
PassMode::Ignore => {}
|
||||
PassMode::Indirect { attrs, extra_attrs: None, on_stack: true } => {
|
||||
PassMode::Indirect { attrs, meta_attrs: None, on_stack: true } => {
|
||||
let i = apply(attrs);
|
||||
let byval = llvm::CreateByValAttr(cx.llcx, arg.layout.llvm_type(cx));
|
||||
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[byval]);
|
||||
}
|
||||
PassMode::Direct(attrs)
|
||||
| PassMode::Indirect { attrs, extra_attrs: None, on_stack: false } => {
|
||||
| PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
|
||||
apply(attrs);
|
||||
}
|
||||
PassMode::Indirect { attrs, extra_attrs: Some(extra_attrs), on_stack } => {
|
||||
PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
|
||||
assert!(!on_stack);
|
||||
apply(attrs);
|
||||
apply(extra_attrs);
|
||||
apply(meta_attrs);
|
||||
}
|
||||
PassMode::Pair(a, b) => {
|
||||
apply(a);
|
||||
apply(b);
|
||||
}
|
||||
PassMode::Cast(cast, pad_i32) => {
|
||||
PassMode::Cast { cast, pad_i32 } => {
|
||||
if *pad_i32 {
|
||||
apply(&ArgAttributes::new());
|
||||
}
|
||||
@ -504,13 +516,13 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
PassMode::Direct(attrs) => {
|
||||
attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, bx.cx, callsite);
|
||||
}
|
||||
PassMode::Indirect { attrs, extra_attrs: _, on_stack } => {
|
||||
PassMode::Indirect { attrs, meta_attrs: _, on_stack } => {
|
||||
assert!(!on_stack);
|
||||
let i = apply(bx.cx, attrs);
|
||||
let sret = llvm::CreateStructRetAttr(bx.cx.llcx, self.ret.layout.llvm_type(bx));
|
||||
attributes::apply_to_callsite(callsite, llvm::AttributePlace::Argument(i), &[sret]);
|
||||
}
|
||||
PassMode::Cast(cast, _) => {
|
||||
PassMode::Cast { cast, pad_i32: _ } => {
|
||||
cast.attrs.apply_attrs_to_callsite(
|
||||
llvm::AttributePlace::ReturnValue,
|
||||
&bx.cx,
|
||||
@ -532,7 +544,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
for arg in self.args.iter() {
|
||||
match &arg.mode {
|
||||
PassMode::Ignore => {}
|
||||
PassMode::Indirect { attrs, extra_attrs: None, on_stack: true } => {
|
||||
PassMode::Indirect { attrs, meta_attrs: None, on_stack: true } => {
|
||||
let i = apply(bx.cx, attrs);
|
||||
let byval = llvm::CreateByValAttr(bx.cx.llcx, arg.layout.llvm_type(bx));
|
||||
attributes::apply_to_callsite(
|
||||
@ -542,18 +554,18 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
);
|
||||
}
|
||||
PassMode::Direct(attrs)
|
||||
| PassMode::Indirect { attrs, extra_attrs: None, on_stack: false } => {
|
||||
| PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
|
||||
apply(bx.cx, attrs);
|
||||
}
|
||||
PassMode::Indirect { attrs, extra_attrs: Some(extra_attrs), on_stack: _ } => {
|
||||
PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack: _ } => {
|
||||
apply(bx.cx, attrs);
|
||||
apply(bx.cx, extra_attrs);
|
||||
apply(bx.cx, meta_attrs);
|
||||
}
|
||||
PassMode::Pair(a, b) => {
|
||||
apply(bx.cx, a);
|
||||
apply(bx.cx, b);
|
||||
}
|
||||
PassMode::Cast(cast, pad_i32) => {
|
||||
PassMode::Cast { cast, pad_i32 } => {
|
||||
if *pad_i32 {
|
||||
apply(bx.cx, &ArgAttributes::new());
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
||||
sym::volatile_load | sym::unaligned_volatile_load => {
|
||||
let tp_ty = fn_args.type_at(0);
|
||||
let ptr = args[0].immediate();
|
||||
let load = if let PassMode::Cast(ty, _) = &fn_abi.ret.mode {
|
||||
let load = if let PassMode::Cast { cast: ty, pad_i32: _ } = &fn_abi.ret.mode {
|
||||
let llty = ty.llvm_type(self);
|
||||
self.volatile_load(llty, ptr)
|
||||
} else {
|
||||
@ -386,7 +386,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
||||
};
|
||||
|
||||
if !fn_abi.ret.is_ignore() {
|
||||
if let PassMode::Cast(_, _) = &fn_abi.ret.mode {
|
||||
if let PassMode::Cast { .. } = &fn_abi.ret.mode {
|
||||
self.store(llval, result.llval, result.align);
|
||||
} else {
|
||||
OperandRef::from_immediate_or_packed_pair(self, llval, result.layout)
|
||||
|
@ -416,7 +416,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
}
|
||||
}
|
||||
|
||||
PassMode::Cast(cast_ty, _) => {
|
||||
PassMode::Cast { cast: cast_ty, pad_i32: _ } => {
|
||||
let op = match self.locals[mir::RETURN_PLACE] {
|
||||
LocalRef::Operand(op) => op,
|
||||
LocalRef::PendingOperand => bug!("use of return before def"),
|
||||
@ -1310,7 +1310,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
) {
|
||||
match arg.mode {
|
||||
PassMode::Ignore => return,
|
||||
PassMode::Cast(_, true) => {
|
||||
PassMode::Cast { pad_i32: true, .. } => {
|
||||
// Fill padding with undef value, where applicable.
|
||||
llargs.push(bx.const_undef(bx.reg_backend_type(&Reg::i32())));
|
||||
}
|
||||
@ -1322,7 +1322,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
}
|
||||
_ => bug!("codegen_argument: {:?} invalid for pair argument", op),
|
||||
},
|
||||
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => match op.val {
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => match op.val {
|
||||
Ref(a, Some(b), _) => {
|
||||
llargs.push(a);
|
||||
llargs.push(b);
|
||||
@ -1347,7 +1347,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
op.val.store(bx, scratch);
|
||||
(scratch.llval, scratch.align, true)
|
||||
}
|
||||
PassMode::Cast(..) => {
|
||||
PassMode::Cast { .. } => {
|
||||
let scratch = PlaceRef::alloca(bx, arg.layout);
|
||||
op.val.store(bx, scratch);
|
||||
(scratch.llval, scratch.align, true)
|
||||
@ -1400,7 +1400,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
|
||||
if by_ref && !arg.is_indirect() {
|
||||
// Have to load the argument, maybe while casting it.
|
||||
if let PassMode::Cast(ty, _) = &arg.mode {
|
||||
if let PassMode::Cast { cast: ty, .. } = &arg.mode {
|
||||
let llty = bx.cast_backend_type(ty);
|
||||
llval = bx.load(llty, llval, align.min(arg.layout.align.abi));
|
||||
} else {
|
||||
@ -1744,7 +1744,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
}
|
||||
DirectOperand(index) => {
|
||||
// If there is a cast, we have to store and reload.
|
||||
let op = if let PassMode::Cast(..) = ret_abi.mode {
|
||||
let op = if let PassMode::Cast { .. } = ret_abi.mode {
|
||||
let tmp = PlaceRef::alloca(bx, ret_abi.layout);
|
||||
tmp.storage_live(bx);
|
||||
bx.store_arg(&ret_abi, llval, tmp);
|
||||
|
@ -462,7 +462,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
};
|
||||
|
||||
if !fn_abi.ret.is_ignore() {
|
||||
if let PassMode::Cast(..) = &fn_abi.ret.mode {
|
||||
if let PassMode::Cast { .. } = &fn_abi.ret.mode {
|
||||
bx.store(llval, result.llval, result.align);
|
||||
} else {
|
||||
OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
|
||||
|
@ -327,7 +327,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
for i in 0..tupled_arg_tys.len() {
|
||||
let arg = &fx.fn_abi.args[idx];
|
||||
idx += 1;
|
||||
if let PassMode::Cast(_, true) = arg.mode {
|
||||
if let PassMode::Cast { pad_i32: true, .. } = arg.mode {
|
||||
llarg_idx += 1;
|
||||
}
|
||||
let pr_field = place.project_field(bx, i);
|
||||
@ -351,7 +351,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
|
||||
let arg = &fx.fn_abi.args[idx];
|
||||
idx += 1;
|
||||
if let PassMode::Cast(_, true) = arg.mode {
|
||||
if let PassMode::Cast { pad_i32: true, .. } = arg.mode {
|
||||
llarg_idx += 1;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,10 @@ hir_typeck_expected_default_return_type = expected `()` because of default retur
|
||||
|
||||
hir_typeck_expected_return_type = expected `{$expected}` because of return type
|
||||
|
||||
hir_typeck_explicit_destructor = explicit use of destructor method
|
||||
.label = explicit destructor calls not allowed
|
||||
.suggestion = consider using `drop` function
|
||||
|
||||
hir_typeck_field_multiply_specified_in_initializer =
|
||||
field `{$ident}` specified more than once
|
||||
.label = used more than once
|
||||
@ -52,8 +56,10 @@ hir_typeck_functional_record_update_on_non_struct =
|
||||
|
||||
hir_typeck_help_set_edition_cargo = set `edition = "{$edition}"` in `Cargo.toml`
|
||||
hir_typeck_help_set_edition_standalone = pass `--edition {$edition}` to `rustc`
|
||||
hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
|
||||
|
||||
hir_typeck_invalid_callee = expected function, found {$ty}
|
||||
|
||||
hir_typeck_lang_start_expected_sig_note = the `start` lang item should have the signature `fn(fn() -> T, isize, *const *const u8, u8) -> isize`
|
||||
hir_typeck_lang_start_incorrect_number_params = incorrect number of parameters for the `start` lang item
|
||||
hir_typeck_lang_start_incorrect_number_params_note_expected_count = the `start` lang item should have four parameters, but found {$found_param_count}
|
||||
|
||||
@ -66,6 +72,9 @@ hir_typeck_lang_start_incorrect_ret_ty = the return type of the `start` lang ite
|
||||
hir_typeck_method_call_on_unknown_raw_pointee =
|
||||
cannot call a method on a raw pointer with an unknown pointee type
|
||||
|
||||
hir_typeck_missing_fn_lang_items = failed to find an overloaded call trait for closure call
|
||||
.help = make sure the `fn`/`fn_mut`/`fn_once` lang items are defined and have correctly defined `call`/`call_mut`/`call_once` methods
|
||||
|
||||
hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
|
||||
|
||||
hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method ->
|
||||
@ -92,6 +101,9 @@ hir_typeck_return_stmt_outside_of_fn_body =
|
||||
.encl_body_label = the {$statement_kind} is part of this body...
|
||||
.encl_fn_label = ...not the enclosing function body
|
||||
|
||||
hir_typeck_rustcall_incorrect_args =
|
||||
functions with the "rust-call" ABI must take a single non-self tuple argument
|
||||
|
||||
hir_typeck_struct_expr_non_exhaustive =
|
||||
cannot create non-exhaustive {$what} using struct expression
|
||||
|
||||
|
@ -2,9 +2,9 @@ use super::method::probe::ProbeScope;
|
||||
use super::method::MethodCallee;
|
||||
use super::{Expectation, FnCtxt, TupleArgumentsFlag};
|
||||
|
||||
use crate::type_error_struct;
|
||||
use crate::errors;
|
||||
use rustc_ast::util::parser::PREC_POSTFIX;
|
||||
use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, StashKey};
|
||||
use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, StashKey};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{self, CtorKind, DefKind, Namespace, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
@ -44,23 +44,15 @@ pub fn check_legal_trait_for_method_call(
|
||||
trait_id: DefId,
|
||||
) {
|
||||
if tcx.lang_items().drop_trait() == Some(trait_id) {
|
||||
let mut err = struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method");
|
||||
err.span_label(span, "explicit destructor calls not allowed");
|
||||
|
||||
let (sp, suggestion) = receiver
|
||||
.and_then(|s| tcx.sess.source_map().span_to_snippet(s).ok())
|
||||
.filter(|snippet| !snippet.is_empty())
|
||||
.map(|snippet| (expr_span, format!("drop({snippet})")))
|
||||
.unwrap_or_else(|| (span, "drop".to_string()));
|
||||
|
||||
err.span_suggestion(
|
||||
sp,
|
||||
"consider using `drop` function",
|
||||
suggestion,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
||||
err.emit();
|
||||
let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
|
||||
errors::ExplicitDestructorCallSugg::Snippet {
|
||||
lo: expr_span.shrink_to_lo(),
|
||||
hi: receiver.shrink_to_hi().to(expr_span.shrink_to_hi()),
|
||||
}
|
||||
} else {
|
||||
errors::ExplicitDestructorCallSugg::Empty(span)
|
||||
};
|
||||
tcx.sess.emit_err(errors::ExplicitDestructorCall { span, sugg });
|
||||
}
|
||||
}
|
||||
|
||||
@ -387,6 +379,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// Unit testing: function items annotated with
|
||||
// `#[rustc_evaluate_where_clauses]` trigger special output
|
||||
// to let us test the trait evaluation system.
|
||||
// Untranslatable diagnostics are okay for rustc internals
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) {
|
||||
let predicates = self.tcx.predicates_of(def_id);
|
||||
let predicates = predicates.instantiate(self.tcx, args);
|
||||
@ -478,10 +473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
);
|
||||
self.require_type_is_sized(ty, sp, traits::RustCall);
|
||||
} else {
|
||||
self.tcx.sess.span_err(
|
||||
sp,
|
||||
"functions with the \"rust-call\" ABI must take a single non-self tuple argument",
|
||||
);
|
||||
self.tcx.sess.emit_err(errors::RustCallIncorrectArgs { span: sp });
|
||||
}
|
||||
}
|
||||
|
||||
@ -610,17 +602,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
let callee_ty = self.resolve_vars_if_possible(callee_ty);
|
||||
let mut err = type_error_struct!(
|
||||
self.tcx.sess,
|
||||
callee_expr.span,
|
||||
callee_ty,
|
||||
E0618,
|
||||
"expected function, found {}",
|
||||
match &unit_variant {
|
||||
let mut err = self.tcx.sess.create_err(errors::InvalidCallee {
|
||||
span: callee_expr.span,
|
||||
ty: match &unit_variant {
|
||||
Some((_, kind, path)) => format!("{kind} `{path}`"),
|
||||
None => format!("`{callee_ty}`"),
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
if callee_ty.references_error() {
|
||||
err.downgrade_to_delayed_bug();
|
||||
}
|
||||
|
||||
self.identify_bad_closure_def_and_call(
|
||||
&mut err,
|
||||
@ -891,15 +882,7 @@ impl<'a, 'tcx> DeferredCallResolution<'tcx> {
|
||||
None => {
|
||||
// This can happen if `#![no_core]` is used and the `fn/fn_mut/fn_once`
|
||||
// lang items are not defined (issue #86238).
|
||||
let mut err = fcx.inh.tcx.sess.struct_span_err(
|
||||
self.call_expr.span,
|
||||
"failed to find an overloaded call trait for closure call",
|
||||
);
|
||||
err.help(
|
||||
"make sure the `fn`/`fn_mut`/`fn_once` lang items are defined \
|
||||
and have correctly defined `call`/`call_mut`/`call_once` methods",
|
||||
);
|
||||
err.emit();
|
||||
fcx.inh.tcx.sess.emit_err(errors::MissingFnLangItems { span: self.call_expr.span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,13 @@ impl IntoDiagnosticArg for ReturnLikeStatementKind {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_rustcall_incorrect_args)]
|
||||
pub struct RustCallIncorrectArgs {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_yield_expr_outside_of_generator, code = "E0627")]
|
||||
pub struct YieldExprOutsideOfGenerator {
|
||||
@ -76,6 +83,14 @@ pub struct MethodCallOnUnknownRawPointee {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_missing_fn_lang_items)]
|
||||
#[help]
|
||||
pub struct MissingFnLangItems {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_functional_record_update_on_non_struct, code = "E0436")]
|
||||
pub struct FunctionalRecordUpdateOnNonStruct {
|
||||
@ -129,6 +144,29 @@ pub enum ExpectedReturnTypeLabel<'tcx> {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_explicit_destructor, code = "E0040")]
|
||||
pub struct ExplicitDestructorCall {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub sugg: ExplicitDestructorCallSugg,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum ExplicitDestructorCallSugg {
|
||||
#[suggestion(hir_typeck_suggestion, code = "drop", applicability = "maybe-incorrect")]
|
||||
Empty(#[primary_span] Span),
|
||||
#[multipart_suggestion(hir_typeck_suggestion, style = "short")]
|
||||
Snippet {
|
||||
#[suggestion_part(code = "drop(")]
|
||||
lo: Span,
|
||||
#[suggestion_part(code = ")")]
|
||||
hi: Span,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_missing_parentheses_in_range, code = "E0689")]
|
||||
pub struct MissingParenthesesInRange {
|
||||
@ -252,6 +290,14 @@ impl HelpUseLatestEdition {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_invalid_callee, code = "E0618")]
|
||||
pub struct InvalidCallee {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub ty: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum OptionResultRefMismatch {
|
||||
#[suggestion(
|
||||
|
@ -210,7 +210,17 @@ pub struct ParseError {
|
||||
pub label: string::String,
|
||||
pub span: InnerSpan,
|
||||
pub secondary_label: Option<(string::String, InnerSpan)>,
|
||||
pub should_be_replaced_with_positional_argument: bool,
|
||||
pub suggestion: Suggestion,
|
||||
}
|
||||
|
||||
pub enum Suggestion {
|
||||
None,
|
||||
/// Replace inline argument with positional argument:
|
||||
/// `format!("{foo.bar}")` -> `format!("{}", foo.bar)`
|
||||
UsePositional,
|
||||
/// Remove `r#` from identifier:
|
||||
/// `format!("{r#foo}")` -> `format!("{foo}")`
|
||||
RemoveRawIdent(InnerSpan),
|
||||
}
|
||||
|
||||
/// The parser structure for interpreting the input format string. This is
|
||||
@ -365,7 +375,7 @@ impl<'a> Parser<'a> {
|
||||
label: label.into(),
|
||||
span,
|
||||
secondary_label: None,
|
||||
should_be_replaced_with_positional_argument: false,
|
||||
suggestion: Suggestion::None,
|
||||
});
|
||||
}
|
||||
|
||||
@ -389,7 +399,7 @@ impl<'a> Parser<'a> {
|
||||
label: label.into(),
|
||||
span,
|
||||
secondary_label: None,
|
||||
should_be_replaced_with_positional_argument: false,
|
||||
suggestion: Suggestion::None,
|
||||
});
|
||||
}
|
||||
|
||||
@ -493,7 +503,7 @@ impl<'a> Parser<'a> {
|
||||
label,
|
||||
span: pos.to(pos),
|
||||
secondary_label,
|
||||
should_be_replaced_with_positional_argument: false,
|
||||
suggestion: Suggestion::None,
|
||||
});
|
||||
|
||||
None
|
||||
@ -573,7 +583,37 @@ impl<'a> Parser<'a> {
|
||||
Some(ArgumentIs(i))
|
||||
} else {
|
||||
match self.cur.peek() {
|
||||
Some(&(_, c)) if rustc_lexer::is_id_start(c) => Some(ArgumentNamed(self.word())),
|
||||
Some(&(lo, c)) if rustc_lexer::is_id_start(c) => {
|
||||
let word = self.word();
|
||||
|
||||
// Recover from `r#ident` in format strings.
|
||||
// FIXME: use a let chain
|
||||
if word == "r" {
|
||||
if let Some((pos, '#')) = self.cur.peek() {
|
||||
if self.input[pos + 1..]
|
||||
.chars()
|
||||
.next()
|
||||
.is_some_and(rustc_lexer::is_id_start)
|
||||
{
|
||||
self.cur.next();
|
||||
let word = self.word();
|
||||
let prefix_span = self.span(lo, lo + 2);
|
||||
let full_span = self.span(lo, lo + 2 + word.len());
|
||||
self.errors.insert(0, ParseError {
|
||||
description: "raw identifiers are not supported".to_owned(),
|
||||
note: Some("identifiers in format strings can be keywords and don't need to be prefixed with `r#`".to_string()),
|
||||
label: "raw identifier used here".to_owned(),
|
||||
span: full_span,
|
||||
secondary_label: None,
|
||||
suggestion: Suggestion::RemoveRawIdent(prefix_span),
|
||||
});
|
||||
return Some(ArgumentNamed(word));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(ArgumentNamed(word))
|
||||
}
|
||||
|
||||
// This is an `ArgumentNext`.
|
||||
// Record the fact and do the resolution after parsing the
|
||||
@ -841,7 +881,7 @@ impl<'a> Parser<'a> {
|
||||
label: "expected `?` to occur after `:`".to_owned(),
|
||||
span: pos.to(pos),
|
||||
secondary_label: None,
|
||||
should_be_replaced_with_positional_argument: false,
|
||||
suggestion: Suggestion::None,
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -867,7 +907,7 @@ impl<'a> Parser<'a> {
|
||||
label: "not supported".to_string(),
|
||||
span: InnerSpan::new(arg.position_span.start, field.position_span.end),
|
||||
secondary_label: None,
|
||||
should_be_replaced_with_positional_argument: true,
|
||||
suggestion: Suggestion::UsePositional,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -46,17 +46,17 @@ pub enum PassMode {
|
||||
///
|
||||
/// The argument has a layout abi of `ScalarPair`.
|
||||
Pair(ArgAttributes, ArgAttributes),
|
||||
/// Pass the argument after casting it, to either a single uniform or a
|
||||
/// pair of registers. The bool indicates if a `Reg::i32()` dummy argument
|
||||
/// is emitted before the real argument.
|
||||
Cast(Box<CastTarget>, bool),
|
||||
/// Pass the argument after casting it. See the `CastTarget` docs for details. The bool
|
||||
/// indicates if a `Reg::i32()` dummy argument is emitted before the real argument.
|
||||
Cast { pad_i32: bool, cast: Box<CastTarget> },
|
||||
/// Pass the argument indirectly via a hidden pointer.
|
||||
/// The `extra_attrs` value, if any, is for the extra data (vtable or length)
|
||||
/// which indicates that it refers to an unsized rvalue.
|
||||
/// `on_stack` defines that the value should be passed at a fixed
|
||||
/// stack offset in accordance to the ABI rather than passed using a
|
||||
/// pointer. This corresponds to the `byval` LLVM argument attribute.
|
||||
Indirect { attrs: ArgAttributes, extra_attrs: Option<ArgAttributes>, on_stack: bool },
|
||||
/// The `meta_attrs` value, if any, is for the metadata (vtable or length) of an unsized
|
||||
/// argument. (This is the only mode that supports unsized arguments.)
|
||||
/// `on_stack` defines that the value should be passed at a fixed stack offset in accordance to
|
||||
/// the ABI rather than passed using a pointer. This corresponds to the `byval` LLVM argument
|
||||
/// attribute (using the Rust type of this argument). `on_stack` cannot be true for unsized
|
||||
/// arguments, i.e., when `meta_attrs` is `Some`.
|
||||
Indirect { attrs: ArgAttributes, meta_attrs: Option<ArgAttributes>, on_stack: bool },
|
||||
}
|
||||
|
||||
impl PassMode {
|
||||
@ -65,17 +65,20 @@ impl PassMode {
|
||||
/// so that needs to be compared as well!
|
||||
pub fn eq_abi(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(PassMode::Ignore, PassMode::Ignore) => true, // can still be reached for the return type
|
||||
(PassMode::Ignore, PassMode::Ignore) => true,
|
||||
(PassMode::Direct(a1), PassMode::Direct(a2)) => a1.eq_abi(a2),
|
||||
(PassMode::Pair(a1, b1), PassMode::Pair(a2, b2)) => a1.eq_abi(a2) && b1.eq_abi(b2),
|
||||
(PassMode::Cast(c1, pad1), PassMode::Cast(c2, pad2)) => c1.eq_abi(c2) && pad1 == pad2,
|
||||
(
|
||||
PassMode::Indirect { attrs: a1, extra_attrs: None, on_stack: s1 },
|
||||
PassMode::Indirect { attrs: a2, extra_attrs: None, on_stack: s2 },
|
||||
PassMode::Cast { cast: c1, pad_i32: pad1 },
|
||||
PassMode::Cast { cast: c2, pad_i32: pad2 },
|
||||
) => c1.eq_abi(c2) && pad1 == pad2,
|
||||
(
|
||||
PassMode::Indirect { attrs: a1, meta_attrs: None, on_stack: s1 },
|
||||
PassMode::Indirect { attrs: a2, meta_attrs: None, on_stack: s2 },
|
||||
) => a1.eq_abi(a2) && s1 == s2,
|
||||
(
|
||||
PassMode::Indirect { attrs: a1, extra_attrs: Some(e1), on_stack: s1 },
|
||||
PassMode::Indirect { attrs: a2, extra_attrs: Some(e2), on_stack: s2 },
|
||||
PassMode::Indirect { attrs: a1, meta_attrs: Some(e1), on_stack: s1 },
|
||||
PassMode::Indirect { attrs: a2, meta_attrs: Some(e2), on_stack: s2 },
|
||||
) => a1.eq_abi(a2) && e1.eq_abi(e2) && s1 == s2,
|
||||
_ => false,
|
||||
}
|
||||
@ -256,6 +259,13 @@ impl Uniform {
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes the type used for `PassMode::Cast`.
|
||||
///
|
||||
/// Passing arguments in this mode works as follows: the registers in the `prefix` (the ones that
|
||||
/// are `Some`) get laid out one after the other (using `repr(C)` layout rules). Then the
|
||||
/// `rest.unit` register type gets repeated often enough to cover `rest.size`. This describes the
|
||||
/// actual type used for the call; the Rust type of the argument is then transmuted to this ABI type
|
||||
/// (and all data in the padding between the registers is dropped).
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||
pub struct CastTarget {
|
||||
pub prefix: [Option<Reg>; 8],
|
||||
@ -565,15 +575,15 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
|
||||
attrs.pointee_size = layout.size;
|
||||
attrs.pointee_align = Some(layout.align.abi);
|
||||
|
||||
let extra_attrs = layout.is_unsized().then_some(ArgAttributes::new());
|
||||
let meta_attrs = layout.is_unsized().then_some(ArgAttributes::new());
|
||||
|
||||
PassMode::Indirect { attrs, extra_attrs, on_stack: false }
|
||||
PassMode::Indirect { attrs, meta_attrs, on_stack: false }
|
||||
}
|
||||
|
||||
pub fn make_indirect(&mut self) {
|
||||
match self.mode {
|
||||
PassMode::Direct(_) | PassMode::Pair(_, _) => {}
|
||||
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: false } => return,
|
||||
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: false } => return,
|
||||
_ => panic!("Tried to make {:?} indirect", self.mode),
|
||||
}
|
||||
|
||||
@ -583,7 +593,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
|
||||
pub fn make_indirect_byval(&mut self, byval_align: Option<Align>) {
|
||||
self.make_indirect();
|
||||
match self.mode {
|
||||
PassMode::Indirect { ref mut attrs, extra_attrs: _, ref mut on_stack } => {
|
||||
PassMode::Indirect { ref mut attrs, meta_attrs: _, ref mut on_stack } => {
|
||||
*on_stack = true;
|
||||
|
||||
// Some platforms, like 32-bit x86, change the alignment of the type when passing
|
||||
@ -616,11 +626,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
|
||||
}
|
||||
|
||||
pub fn cast_to<T: Into<CastTarget>>(&mut self, target: T) {
|
||||
self.mode = PassMode::Cast(Box::new(target.into()), false);
|
||||
self.mode = PassMode::Cast { cast: Box::new(target.into()), pad_i32: false };
|
||||
}
|
||||
|
||||
pub fn cast_to_and_pad_i32<T: Into<CastTarget>>(&mut self, target: T, pad_i32: bool) {
|
||||
self.mode = PassMode::Cast(Box::new(target.into()), pad_i32);
|
||||
self.mode = PassMode::Cast { cast: Box::new(target.into()), pad_i32 };
|
||||
}
|
||||
|
||||
pub fn is_indirect(&self) -> bool {
|
||||
@ -628,11 +638,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
|
||||
}
|
||||
|
||||
pub fn is_sized_indirect(&self) -> bool {
|
||||
matches!(self.mode, PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ })
|
||||
matches!(self.mode, PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ })
|
||||
}
|
||||
|
||||
pub fn is_unsized_indirect(&self) -> bool {
|
||||
matches!(self.mode, PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ })
|
||||
matches!(self.mode, PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ })
|
||||
}
|
||||
|
||||
pub fn is_ignore(&self) -> bool {
|
||||
|
@ -142,13 +142,13 @@ where
|
||||
for arg in fn_abi.args.iter_mut() {
|
||||
let attrs = match arg.mode {
|
||||
PassMode::Ignore
|
||||
| PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
|
||||
| PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
|
||||
continue;
|
||||
}
|
||||
PassMode::Direct(ref mut attrs) => attrs,
|
||||
PassMode::Pair(..)
|
||||
| PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ }
|
||||
| PassMode::Cast(..) => {
|
||||
| PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ }
|
||||
| PassMode::Cast { .. } => {
|
||||
unreachable!("x86 shouldn't be passing arguments by {:?}", arg.mode)
|
||||
}
|
||||
};
|
||||
|
@ -144,7 +144,6 @@
|
||||
#![feature(ptr_metadata)]
|
||||
#![feature(ptr_sub_ptr)]
|
||||
#![feature(receiver_trait)]
|
||||
#![feature(saturating_int_impl)]
|
||||
#![feature(set_ptr_value)]
|
||||
#![feature(sized_type_properties)]
|
||||
#![feature(slice_from_ptr_range)]
|
||||
|
@ -3,7 +3,7 @@
|
||||
//! suggestions from rustc if you get anything slightly wrong in here, and overall
|
||||
//! helps with clarity as we're also referring to `char` intentionally in here.
|
||||
|
||||
use crate::fmt;
|
||||
use crate::fmt::{self, Write};
|
||||
use crate::mem::transmute;
|
||||
|
||||
/// One of the 128 Unicode characters from U+0000 through U+007F,
|
||||
@ -54,7 +54,7 @@ use crate::mem::transmute;
|
||||
/// [chart]: https://www.unicode.org/charts/PDF/U0000.pdf
|
||||
/// [NIST FIPS 1-2]: https://nvlpubs.nist.gov/nistpubs/Legacy/FIPS/fipspub1-2-1977.pdf
|
||||
/// [NamesList]: https://www.unicode.org/Public/15.0.0/ucd/NamesList.txt
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||
#[repr(u8)]
|
||||
pub enum AsciiChar {
|
||||
@ -563,3 +563,40 @@ impl fmt::Display for AsciiChar {
|
||||
<str as fmt::Display>::fmt(self.as_str(), f)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "ascii_char", issue = "110998")]
|
||||
impl fmt::Debug for AsciiChar {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
#[inline]
|
||||
fn backslash(a: AsciiChar) -> ([AsciiChar; 4], u8) {
|
||||
([AsciiChar::ReverseSolidus, a, AsciiChar::Null, AsciiChar::Null], 2)
|
||||
}
|
||||
|
||||
let (buf, len) = match self {
|
||||
AsciiChar::Null => backslash(AsciiChar::Digit0),
|
||||
AsciiChar::CharacterTabulation => backslash(AsciiChar::SmallT),
|
||||
AsciiChar::CarriageReturn => backslash(AsciiChar::SmallR),
|
||||
AsciiChar::LineFeed => backslash(AsciiChar::SmallN),
|
||||
AsciiChar::ReverseSolidus => backslash(AsciiChar::ReverseSolidus),
|
||||
AsciiChar::Apostrophe => backslash(AsciiChar::Apostrophe),
|
||||
_ => {
|
||||
let byte = self.to_u8();
|
||||
if !byte.is_ascii_control() {
|
||||
([*self, AsciiChar::Null, AsciiChar::Null, AsciiChar::Null], 1)
|
||||
} else {
|
||||
const HEX_DIGITS: [AsciiChar; 16] = *b"0123456789abcdef".as_ascii().unwrap();
|
||||
|
||||
let hi = HEX_DIGITS[usize::from(byte >> 4)];
|
||||
let lo = HEX_DIGITS[usize::from(byte & 0xf)];
|
||||
([AsciiChar::ReverseSolidus, AsciiChar::SmallX, hi, lo], 4)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
f.write_char('\'')?;
|
||||
for byte in &buf[..len as usize] {
|
||||
f.write_str(byte.as_str())?;
|
||||
}
|
||||
f.write_char('\'')
|
||||
}
|
||||
}
|
||||
|
@ -44,11 +44,10 @@ mod uint_macros; // import uint_impl!
|
||||
mod error;
|
||||
mod int_log10;
|
||||
mod nonzero;
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
mod saturating;
|
||||
mod wrapping;
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub use saturating::Saturating;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use wrapping::Wrapping;
|
||||
|
@ -4,7 +4,7 @@ use crate::fmt;
|
||||
use crate::ops::{Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign};
|
||||
use crate::ops::{BitXor, BitXorAssign, Div, DivAssign};
|
||||
use crate::ops::{Mul, MulAssign, Neg, Not, Rem, RemAssign};
|
||||
use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
|
||||
use crate::ops::{Sub, SubAssign};
|
||||
|
||||
/// Provides intentionally-saturating arithmetic on `T`.
|
||||
///
|
||||
@ -24,7 +24,6 @@ use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
/// let max = Saturating(u32::MAX);
|
||||
@ -32,181 +31,186 @@ use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
|
||||
///
|
||||
/// assert_eq!(u32::MAX, (max + one).0);
|
||||
/// ```
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_diagnostic_item = "Saturating"]
|
||||
pub struct Saturating<T>(#[unstable(feature = "saturating_int_impl", issue = "87920")] pub T);
|
||||
pub struct Saturating<T>(
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")] pub T,
|
||||
);
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: fmt::Debug> fmt::Debug for Saturating<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: fmt::Display> fmt::Display for Saturating<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: fmt::Binary> fmt::Binary for Saturating<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: fmt::Octal> fmt::Octal for Saturating<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: fmt::LowerHex> fmt::LowerHex for Saturating<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: fmt::UpperHex> fmt::UpperHex for Saturating<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! sh_impl_signed {
|
||||
($t:ident, $f:ident) => {
|
||||
// FIXME what is the correct implementation here? see discussion https://github.com/rust-lang/rust/pull/87921#discussion_r695870065
|
||||
//
|
||||
// #[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
// impl Shl<$f> for Saturating<$t> {
|
||||
// type Output = Saturating<$t>;
|
||||
//
|
||||
// #[inline]
|
||||
// fn shl(self, other: $f) -> Saturating<$t> {
|
||||
// if other < 0 {
|
||||
// Saturating(self.0.shr((-other & self::shift_max::$t as $f) as u32))
|
||||
// } else {
|
||||
// Saturating(self.0.shl((other & self::shift_max::$t as $f) as u32))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f,
|
||||
// #[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
//
|
||||
// #[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
// impl ShlAssign<$f> for Saturating<$t> {
|
||||
// #[inline]
|
||||
// fn shl_assign(&mut self, other: $f) {
|
||||
// *self = *self << other;
|
||||
// }
|
||||
// }
|
||||
// forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
impl Shr<$f> for Saturating<$t> {
|
||||
type Output = Saturating<$t>;
|
||||
|
||||
#[inline]
|
||||
fn shr(self, other: $f) -> Saturating<$t> {
|
||||
if other < 0 {
|
||||
Saturating(self.0.shl((-other & self::shift_max::$t as $f) as u32))
|
||||
} else {
|
||||
Saturating(self.0.shr((other & self::shift_max::$t as $f) as u32))
|
||||
}
|
||||
}
|
||||
}
|
||||
forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
impl ShrAssign<$f> for Saturating<$t> {
|
||||
#[inline]
|
||||
fn shr_assign(&mut self, other: $f) {
|
||||
*self = *self >> other;
|
||||
}
|
||||
}
|
||||
forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f }
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! sh_impl_unsigned {
|
||||
($t:ident, $f:ident) => {
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
impl Shl<$f> for Saturating<$t> {
|
||||
type Output = Saturating<$t>;
|
||||
|
||||
#[inline]
|
||||
fn shl(self, other: $f) -> Saturating<$t> {
|
||||
Saturating(self.0.wrapping_shl(other as u32))
|
||||
}
|
||||
}
|
||||
forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
impl ShlAssign<$f> for Saturating<$t> {
|
||||
#[inline]
|
||||
fn shl_assign(&mut self, other: $f) {
|
||||
*self = *self << other;
|
||||
}
|
||||
}
|
||||
forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
impl Shr<$f> for Saturating<$t> {
|
||||
type Output = Saturating<$t>;
|
||||
|
||||
#[inline]
|
||||
fn shr(self, other: $f) -> Saturating<$t> {
|
||||
Saturating(self.0.wrapping_shr(other as u32))
|
||||
}
|
||||
}
|
||||
forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
impl ShrAssign<$f> for Saturating<$t> {
|
||||
#[inline]
|
||||
fn shr_assign(&mut self, other: $f) {
|
||||
*self = *self >> other;
|
||||
}
|
||||
}
|
||||
forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f }
|
||||
};
|
||||
}
|
||||
|
||||
// FIXME (#23545): uncomment the remaining impls
|
||||
macro_rules! sh_impl_all {
|
||||
($($t:ident)*) => ($(
|
||||
//sh_impl_unsigned! { $t, u8 }
|
||||
//sh_impl_unsigned! { $t, u16 }
|
||||
//sh_impl_unsigned! { $t, u32 }
|
||||
//sh_impl_unsigned! { $t, u64 }
|
||||
//sh_impl_unsigned! { $t, u128 }
|
||||
sh_impl_unsigned! { $t, usize }
|
||||
|
||||
//sh_impl_signed! { $t, i8 }
|
||||
//sh_impl_signed! { $t, i16 }
|
||||
//sh_impl_signed! { $t, i32 }
|
||||
//sh_impl_signed! { $t, i64 }
|
||||
//sh_impl_signed! { $t, i128 }
|
||||
//sh_impl_signed! { $t, isize }
|
||||
)*)
|
||||
}
|
||||
|
||||
sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
|
||||
// FIXME the correct implementation is not clear. Waiting for a real world use case at https://github.com/rust-lang/libs-team/issues/230
|
||||
//
|
||||
// #[allow(unused_macros)]
|
||||
// macro_rules! sh_impl_signed {
|
||||
// ($t:ident, $f:ident) => {
|
||||
// // FIXME what is the correct implementation here? see discussion https://github.com/rust-lang/rust/pull/87921#discussion_r695870065
|
||||
// //
|
||||
// // #[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
// // impl Shl<$f> for Saturating<$t> {
|
||||
// // type Output = Saturating<$t>;
|
||||
// //
|
||||
// // #[inline]
|
||||
// // fn shl(self, other: $f) -> Saturating<$t> {
|
||||
// // if other < 0 {
|
||||
// // Saturating(self.0.shr((-other & self::shift_max::$t as $f) as u32))
|
||||
// // } else {
|
||||
// // Saturating(self.0.shl((other & self::shift_max::$t as $f) as u32))
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
// // forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f,
|
||||
// // #[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
// //
|
||||
// // #[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
// // impl ShlAssign<$f> for Saturating<$t> {
|
||||
// // #[inline]
|
||||
// // fn shl_assign(&mut self, other: $f) {
|
||||
// // *self = *self << other;
|
||||
// // }
|
||||
// // }
|
||||
// // forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f }
|
||||
//
|
||||
// #[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
// impl Shr<$f> for Saturating<$t> {
|
||||
// type Output = Saturating<$t>;
|
||||
//
|
||||
// #[inline]
|
||||
// fn shr(self, other: $f) -> Saturating<$t> {
|
||||
// if other < 0 {
|
||||
// Saturating(self.0.shl((-other & self::shift_max::$t as $f) as u32))
|
||||
// } else {
|
||||
// Saturating(self.0.shr((other & self::shift_max::$t as $f) as u32))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f,
|
||||
// #[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
//
|
||||
// #[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
// impl ShrAssign<$f> for Saturating<$t> {
|
||||
// #[inline]
|
||||
// fn shr_assign(&mut self, other: $f) {
|
||||
// *self = *self >> other;
|
||||
// }
|
||||
// }
|
||||
// forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f }
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// macro_rules! sh_impl_unsigned {
|
||||
// ($t:ident, $f:ident) => {
|
||||
// #[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
// impl Shl<$f> for Saturating<$t> {
|
||||
// type Output = Saturating<$t>;
|
||||
//
|
||||
// #[inline]
|
||||
// fn shl(self, other: $f) -> Saturating<$t> {
|
||||
// Saturating(self.0.wrapping_shl(other as u32))
|
||||
// }
|
||||
// }
|
||||
// forward_ref_binop! { impl Shl, shl for Saturating<$t>, $f,
|
||||
// #[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
//
|
||||
// #[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
// impl ShlAssign<$f> for Saturating<$t> {
|
||||
// #[inline]
|
||||
// fn shl_assign(&mut self, other: $f) {
|
||||
// *self = *self << other;
|
||||
// }
|
||||
// }
|
||||
// forward_ref_op_assign! { impl ShlAssign, shl_assign for Saturating<$t>, $f }
|
||||
//
|
||||
// #[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
// impl Shr<$f> for Saturating<$t> {
|
||||
// type Output = Saturating<$t>;
|
||||
//
|
||||
// #[inline]
|
||||
// fn shr(self, other: $f) -> Saturating<$t> {
|
||||
// Saturating(self.0.wrapping_shr(other as u32))
|
||||
// }
|
||||
// }
|
||||
// forward_ref_binop! { impl Shr, shr for Saturating<$t>, $f,
|
||||
// #[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
//
|
||||
// #[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
// impl ShrAssign<$f> for Saturating<$t> {
|
||||
// #[inline]
|
||||
// fn shr_assign(&mut self, other: $f) {
|
||||
// *self = *self >> other;
|
||||
// }
|
||||
// }
|
||||
// forward_ref_op_assign! { impl ShrAssign, shr_assign for Saturating<$t>, $f }
|
||||
// };
|
||||
// }
|
||||
//
|
||||
// // FIXME (#23545): uncomment the remaining impls
|
||||
// macro_rules! sh_impl_all {
|
||||
// ($($t:ident)*) => ($(
|
||||
// //sh_impl_unsigned! { $t, u8 }
|
||||
// //sh_impl_unsigned! { $t, u16 }
|
||||
// //sh_impl_unsigned! { $t, u32 }
|
||||
// //sh_impl_unsigned! { $t, u64 }
|
||||
// //sh_impl_unsigned! { $t, u128 }
|
||||
// sh_impl_unsigned! { $t, usize }
|
||||
//
|
||||
// //sh_impl_signed! { $t, i8 }
|
||||
// //sh_impl_signed! { $t, i16 }
|
||||
// //sh_impl_signed! { $t, i32 }
|
||||
// //sh_impl_signed! { $t, i64 }
|
||||
// //sh_impl_signed! { $t, i128 }
|
||||
// //sh_impl_signed! { $t, isize }
|
||||
// )*)
|
||||
// }
|
||||
//
|
||||
// sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
|
||||
|
||||
// FIXME(30524): impl Op<T> for Saturating<T>, impl OpAssign<T> for Saturating<T>
|
||||
macro_rules! saturating_impl {
|
||||
($($t:ty)*) => ($(
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Add for Saturating<$t> {
|
||||
type Output = Saturating<$t>;
|
||||
|
||||
@ -216,9 +220,9 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
}
|
||||
forward_ref_binop! { impl Add, add for Saturating<$t>, Saturating<$t>,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")] }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl AddAssign for Saturating<$t> {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: Saturating<$t>) {
|
||||
@ -227,7 +231,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, Saturating<$t> }
|
||||
|
||||
#[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
|
||||
#[stable(feature = "saturating_int_assign_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl AddAssign<$t> for Saturating<$t> {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: $t) {
|
||||
@ -236,7 +240,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl AddAssign, add_assign for Saturating<$t>, $t }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Sub for Saturating<$t> {
|
||||
type Output = Saturating<$t>;
|
||||
|
||||
@ -246,9 +250,9 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
}
|
||||
forward_ref_binop! { impl Sub, sub for Saturating<$t>, Saturating<$t>,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")] }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl SubAssign for Saturating<$t> {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, other: Saturating<$t>) {
|
||||
@ -257,7 +261,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, Saturating<$t> }
|
||||
|
||||
#[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
|
||||
#[stable(feature = "saturating_int_assign_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl SubAssign<$t> for Saturating<$t> {
|
||||
#[inline]
|
||||
fn sub_assign(&mut self, other: $t) {
|
||||
@ -266,7 +270,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl SubAssign, sub_assign for Saturating<$t>, $t }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Mul for Saturating<$t> {
|
||||
type Output = Saturating<$t>;
|
||||
|
||||
@ -276,9 +280,9 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
}
|
||||
forward_ref_binop! { impl Mul, mul for Saturating<$t>, Saturating<$t>,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")] }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl MulAssign for Saturating<$t> {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, other: Saturating<$t>) {
|
||||
@ -287,7 +291,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl MulAssign, mul_assign for Saturating<$t>, Saturating<$t> }
|
||||
|
||||
#[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
|
||||
#[stable(feature = "saturating_int_assign_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl MulAssign<$t> for Saturating<$t> {
|
||||
#[inline]
|
||||
fn mul_assign(&mut self, other: $t) {
|
||||
@ -301,7 +305,6 @@ macro_rules! saturating_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("assert_eq!(Saturating(2", stringify!($t), "), Saturating(5", stringify!($t), ") / Saturating(2));")]
|
||||
@ -310,12 +313,11 @@ macro_rules! saturating_impl {
|
||||
/// ```
|
||||
///
|
||||
/// ```should_panic
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("let _ = Saturating(0", stringify!($t), ") / Saturating(0);")]
|
||||
/// ```
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Div for Saturating<$t> {
|
||||
type Output = Saturating<$t>;
|
||||
|
||||
@ -325,10 +327,10 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
}
|
||||
forward_ref_binop! { impl Div, div for Saturating<$t>, Saturating<$t>,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")] }
|
||||
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl DivAssign for Saturating<$t> {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, other: Saturating<$t>) {
|
||||
@ -337,7 +339,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, Saturating<$t> }
|
||||
|
||||
#[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
|
||||
#[stable(feature = "saturating_int_assign_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl DivAssign<$t> for Saturating<$t> {
|
||||
#[inline]
|
||||
fn div_assign(&mut self, other: $t) {
|
||||
@ -346,7 +348,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl DivAssign, div_assign for Saturating<$t>, $t }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Rem for Saturating<$t> {
|
||||
type Output = Saturating<$t>;
|
||||
|
||||
@ -356,9 +358,9 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
}
|
||||
forward_ref_binop! { impl Rem, rem for Saturating<$t>, Saturating<$t>,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")] }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl RemAssign for Saturating<$t> {
|
||||
#[inline]
|
||||
fn rem_assign(&mut self, other: Saturating<$t>) {
|
||||
@ -367,7 +369,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, Saturating<$t> }
|
||||
|
||||
#[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
|
||||
#[stable(feature = "saturating_int_assign_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl RemAssign<$t> for Saturating<$t> {
|
||||
#[inline]
|
||||
fn rem_assign(&mut self, other: $t) {
|
||||
@ -376,7 +378,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl RemAssign, rem_assign for Saturating<$t>, $t }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Not for Saturating<$t> {
|
||||
type Output = Saturating<$t>;
|
||||
|
||||
@ -386,9 +388,9 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
}
|
||||
forward_ref_unop! { impl Not, not for Saturating<$t>,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")] }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl BitXor for Saturating<$t> {
|
||||
type Output = Saturating<$t>;
|
||||
|
||||
@ -398,9 +400,9 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
}
|
||||
forward_ref_binop! { impl BitXor, bitxor for Saturating<$t>, Saturating<$t>,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")] }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl BitXorAssign for Saturating<$t> {
|
||||
#[inline]
|
||||
fn bitxor_assign(&mut self, other: Saturating<$t>) {
|
||||
@ -409,7 +411,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, Saturating<$t> }
|
||||
|
||||
#[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
|
||||
#[stable(feature = "saturating_int_assign_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl BitXorAssign<$t> for Saturating<$t> {
|
||||
#[inline]
|
||||
fn bitxor_assign(&mut self, other: $t) {
|
||||
@ -418,7 +420,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for Saturating<$t>, $t }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl BitOr for Saturating<$t> {
|
||||
type Output = Saturating<$t>;
|
||||
|
||||
@ -428,9 +430,9 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
}
|
||||
forward_ref_binop! { impl BitOr, bitor for Saturating<$t>, Saturating<$t>,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")] }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl BitOrAssign for Saturating<$t> {
|
||||
#[inline]
|
||||
fn bitor_assign(&mut self, other: Saturating<$t>) {
|
||||
@ -439,7 +441,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, Saturating<$t> }
|
||||
|
||||
#[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
|
||||
#[stable(feature = "saturating_int_assign_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl BitOrAssign<$t> for Saturating<$t> {
|
||||
#[inline]
|
||||
fn bitor_assign(&mut self, other: $t) {
|
||||
@ -448,7 +450,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl BitOrAssign, bitor_assign for Saturating<$t>, $t }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl BitAnd for Saturating<$t> {
|
||||
type Output = Saturating<$t>;
|
||||
|
||||
@ -458,9 +460,9 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
}
|
||||
forward_ref_binop! { impl BitAnd, bitand for Saturating<$t>, Saturating<$t>,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")] }
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl BitAndAssign for Saturating<$t> {
|
||||
#[inline]
|
||||
fn bitand_assign(&mut self, other: Saturating<$t>) {
|
||||
@ -469,7 +471,7 @@ macro_rules! saturating_impl {
|
||||
}
|
||||
forward_ref_op_assign! { impl BitAndAssign, bitand_assign for Saturating<$t>, Saturating<$t> }
|
||||
|
||||
#[unstable(feature = "saturating_int_assign_impl", issue = "92354")]
|
||||
#[stable(feature = "saturating_int_assign_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl BitAndAssign<$t> for Saturating<$t> {
|
||||
#[inline]
|
||||
fn bitand_assign(&mut self, other: $t) {
|
||||
@ -493,12 +495,11 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::MIN, Saturating(", stringify!($t), "::MIN));")]
|
||||
/// ```
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const MIN: Self = Self(<$t>::MIN);
|
||||
|
||||
/// Returns the largest value that can be represented by this integer type.
|
||||
@ -508,12 +509,11 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::MAX, Saturating(", stringify!($t), "::MAX));")]
|
||||
/// ```
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const MAX: Self = Self(<$t>::MAX);
|
||||
|
||||
/// Returns the size of this integer type in bits.
|
||||
@ -523,12 +523,11 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("assert_eq!(<Saturating<", stringify!($t), ">>::BITS, ", stringify!($t), "::BITS);")]
|
||||
/// ```
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const BITS: u32 = <$t>::BITS;
|
||||
|
||||
/// Returns the number of ones in the binary representation of `self`.
|
||||
@ -538,7 +537,6 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("let n = Saturating(0b01001100", stringify!($t), ");")]
|
||||
@ -550,7 +548,8 @@ macro_rules! saturating_int_impl {
|
||||
#[doc(alias = "popcnt")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn count_ones(self) -> u32 {
|
||||
self.0.count_ones()
|
||||
}
|
||||
@ -562,7 +561,6 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("assert_eq!(Saturating(!0", stringify!($t), ").count_zeros(), 0);")]
|
||||
@ -570,7 +568,8 @@ macro_rules! saturating_int_impl {
|
||||
#[inline]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn count_zeros(self) -> u32 {
|
||||
self.0.count_zeros()
|
||||
}
|
||||
@ -582,7 +581,6 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("let n = Saturating(0b0101000", stringify!($t), ");")]
|
||||
@ -592,7 +590,8 @@ macro_rules! saturating_int_impl {
|
||||
#[inline]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn trailing_zeros(self) -> u32 {
|
||||
self.0.trailing_zeros()
|
||||
}
|
||||
@ -609,7 +608,6 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
/// let n: Saturating<i64> = Saturating(0x0123456789ABCDEF);
|
||||
@ -620,7 +618,8 @@ macro_rules! saturating_int_impl {
|
||||
#[inline]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn rotate_left(self, n: u32) -> Self {
|
||||
Saturating(self.0.rotate_left(n))
|
||||
}
|
||||
@ -637,7 +636,6 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
/// let n: Saturating<i64> = Saturating(0x0123456789ABCDEF);
|
||||
@ -648,7 +646,8 @@ macro_rules! saturating_int_impl {
|
||||
#[inline]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn rotate_right(self, n: u32) -> Self {
|
||||
Saturating(self.0.rotate_right(n))
|
||||
}
|
||||
@ -660,7 +659,6 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
/// let n: Saturating<i16> = Saturating(0b0000000_01010101);
|
||||
@ -674,7 +672,8 @@ macro_rules! saturating_int_impl {
|
||||
#[inline]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn swap_bytes(self) -> Self {
|
||||
Saturating(self.0.swap_bytes())
|
||||
}
|
||||
@ -689,7 +688,6 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
/// let n = Saturating(0b0000000_01010101i16);
|
||||
@ -701,8 +699,8 @@ macro_rules! saturating_int_impl {
|
||||
/// assert_eq!(m, Saturating(-22016));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub const fn reverse_bits(self) -> Self {
|
||||
@ -719,7 +717,6 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
|
||||
@ -732,7 +729,8 @@ macro_rules! saturating_int_impl {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn from_be(x: Self) -> Self {
|
||||
Saturating(<$t>::from_be(x.0))
|
||||
}
|
||||
@ -747,7 +745,6 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
|
||||
@ -760,7 +757,8 @@ macro_rules! saturating_int_impl {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn from_le(x: Self) -> Self {
|
||||
Saturating(<$t>::from_le(x.0))
|
||||
}
|
||||
@ -775,7 +773,6 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
|
||||
@ -787,7 +784,8 @@ macro_rules! saturating_int_impl {
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub const fn to_be(self) -> Self {
|
||||
@ -804,7 +802,6 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("let n = Saturating(0x1A", stringify!($t), ");")]
|
||||
@ -816,7 +813,8 @@ macro_rules! saturating_int_impl {
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub const fn to_le(self) -> Self {
|
||||
@ -830,7 +828,6 @@ macro_rules! saturating_int_impl {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("assert_eq!(Saturating(3", stringify!($t), ").pow(4), Saturating(81));")]
|
||||
@ -839,17 +836,17 @@ macro_rules! saturating_int_impl {
|
||||
/// Results that are too large are saturated:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
/// assert_eq!(Saturating(3i8).pow(5), Saturating(127));
|
||||
/// assert_eq!(Saturating(3i8).pow(6), Saturating(127));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub fn pow(self, exp: u32) -> Self {
|
||||
pub const fn pow(self, exp: u32) -> Self {
|
||||
Saturating(self.0.saturating_pow(exp))
|
||||
}
|
||||
}
|
||||
@ -868,7 +865,6 @@ macro_rules! saturating_int_impl_signed {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("let n = Saturating(", stringify!($t), "::MAX >> 2);")]
|
||||
@ -876,7 +872,8 @@ macro_rules! saturating_int_impl_signed {
|
||||
/// assert_eq!(n.leading_zeros(), 3);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub const fn leading_zeros(self) -> u32 {
|
||||
@ -891,7 +888,6 @@ macro_rules! saturating_int_impl_signed {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("assert_eq!(Saturating(100", stringify!($t), ").abs(), Saturating(100));")]
|
||||
@ -901,10 +897,11 @@ macro_rules! saturating_int_impl_signed {
|
||||
#[doc = concat!("assert_eq!(Saturating(", stringify!($t), "::MIN).abs(), Saturating(", stringify!($t), "::MAX));")]
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub fn abs(self) -> Saturating<$t> {
|
||||
pub const fn abs(self) -> Saturating<$t> {
|
||||
Saturating(self.0.saturating_abs())
|
||||
}
|
||||
|
||||
@ -919,7 +916,6 @@ macro_rules! saturating_int_impl_signed {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("assert_eq!(Saturating(10", stringify!($t), ").signum(), Saturating(1));")]
|
||||
@ -927,10 +923,11 @@ macro_rules! saturating_int_impl_signed {
|
||||
#[doc = concat!("assert_eq!(Saturating(-10", stringify!($t), ").signum(), Saturating(-1));")]
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub fn signum(self) -> Saturating<$t> {
|
||||
pub const fn signum(self) -> Saturating<$t> {
|
||||
Saturating(self.0.signum())
|
||||
}
|
||||
|
||||
@ -942,7 +939,6 @@ macro_rules! saturating_int_impl_signed {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("assert!(Saturating(10", stringify!($t), ").is_positive());")]
|
||||
@ -950,7 +946,8 @@ macro_rules! saturating_int_impl_signed {
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn is_positive(self) -> bool {
|
||||
self.0.is_positive()
|
||||
}
|
||||
@ -963,7 +960,6 @@ macro_rules! saturating_int_impl_signed {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("assert!(Saturating(-10", stringify!($t), ").is_negative());")]
|
||||
@ -971,13 +967,14 @@ macro_rules! saturating_int_impl_signed {
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn is_negative(self) -> bool {
|
||||
self.0.is_negative()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Neg for Saturating<$t> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
@ -986,7 +983,7 @@ macro_rules! saturating_int_impl_signed {
|
||||
}
|
||||
}
|
||||
forward_ref_unop! { impl Neg, neg for Saturating<$t>,
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")] }
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")] }
|
||||
)*)
|
||||
}
|
||||
|
||||
@ -1002,7 +999,6 @@ macro_rules! saturating_int_impl_unsigned {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("let n = Saturating(", stringify!($t), "::MAX >> 2);")]
|
||||
@ -1010,7 +1006,8 @@ macro_rules! saturating_int_impl_unsigned {
|
||||
/// assert_eq!(n.leading_zeros(), 2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
pub const fn leading_zeros(self) -> u32 {
|
||||
@ -1024,7 +1021,6 @@ macro_rules! saturating_int_impl_unsigned {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(saturating_int_impl)]
|
||||
/// use std::num::Saturating;
|
||||
///
|
||||
#[doc = concat!("assert!(Saturating(16", stringify!($t), ").is_power_of_two());")]
|
||||
@ -1032,8 +1028,9 @@ macro_rules! saturating_int_impl_unsigned {
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
pub fn is_power_of_two(self) -> bool {
|
||||
#[rustc_const_stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn is_power_of_two(self) -> bool {
|
||||
self.0.is_power_of_two()
|
||||
}
|
||||
|
||||
|
@ -375,7 +375,6 @@
|
||||
#![feature(get_many_mut)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(log_syntax)]
|
||||
#![feature(saturating_int_impl)]
|
||||
#![feature(stdsimd)]
|
||||
#![feature(test)]
|
||||
#![feature(trace_macros)]
|
||||
|
@ -12,7 +12,7 @@ mod tests;
|
||||
#[cfg(test)]
|
||||
mod benches;
|
||||
|
||||
#[unstable(feature = "saturating_int_impl", issue = "87920")]
|
||||
#[stable(feature = "saturating_int_impl", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub use core::num::Saturating;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::num::Wrapping;
|
||||
|
@ -626,11 +626,6 @@ impl<T> Clone for Sender<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Drop for Sender<T> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
#[stable(feature = "mpsc_debug", since = "1.8.0")]
|
||||
impl<T> fmt::Debug for Sender<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@ -755,11 +750,6 @@ impl<T> Clone for SyncSender<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Drop for SyncSender<T> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
#[stable(feature = "mpsc_debug", since = "1.8.0")]
|
||||
impl<T> fmt::Debug for SyncSender<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@ -1096,11 +1086,6 @@ impl<T> IntoIterator for Receiver<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Drop for Receiver<T> {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
#[stable(feature = "mpsc_debug", since = "1.8.0")]
|
||||
impl<T> fmt::Debug for Receiver<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
@ -10,7 +10,7 @@
|
||||
arithmetic_overflow,
|
||||
unconditional_panic
|
||||
)]
|
||||
#![feature(const_mut_refs, inline_const, saturating_int_impl)]
|
||||
#![feature(const_mut_refs, inline_const)]
|
||||
#![warn(clippy::arithmetic_side_effects)]
|
||||
|
||||
extern crate proc_macro_derive;
|
||||
|
@ -450,7 +450,7 @@ error: ABIs are not compatible
|
||||
Align(1 bytes),
|
||||
),
|
||||
},
|
||||
extra_attrs: None,
|
||||
meta_attrs: None,
|
||||
on_stack: false,
|
||||
},
|
||||
},
|
||||
@ -521,7 +521,7 @@ error: ABIs are not compatible
|
||||
Align(4 bytes),
|
||||
),
|
||||
},
|
||||
extra_attrs: None,
|
||||
meta_attrs: None,
|
||||
on_stack: false,
|
||||
},
|
||||
},
|
||||
|
@ -2,10 +2,12 @@ error[E0040]: explicit use of destructor method
|
||||
--> $DIR/E0040.rs:16:7
|
||||
|
|
||||
LL | x.drop();
|
||||
| --^^^^--
|
||||
| | |
|
||||
| | explicit destructor calls not allowed
|
||||
| help: consider using `drop` function: `drop(x)`
|
||||
| ^^^^ explicit destructor calls not allowed
|
||||
|
|
||||
help: consider using `drop` function
|
||||
|
|
||||
LL | drop(x);
|
||||
| +++++ ~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,10 +2,12 @@ error[E0040]: explicit use of destructor method
|
||||
--> $DIR/explicit-call-to-dtor.rs:15:7
|
||||
|
|
||||
LL | x.drop();
|
||||
| --^^^^--
|
||||
| | |
|
||||
| | explicit destructor calls not allowed
|
||||
| help: consider using `drop` function: `drop(x)`
|
||||
| ^^^^ explicit destructor calls not allowed
|
||||
|
|
||||
help: consider using `drop` function
|
||||
|
|
||||
LL | drop(x);
|
||||
| +++++ ~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -2,10 +2,12 @@ error[E0040]: explicit use of destructor method
|
||||
--> $DIR/explicit-call-to-supertrait-dtor.rs:22:14
|
||||
|
|
||||
LL | self.drop();
|
||||
| -----^^^^--
|
||||
| | |
|
||||
| | explicit destructor calls not allowed
|
||||
| help: consider using `drop` function: `drop(self)`
|
||||
| ^^^^ explicit destructor calls not allowed
|
||||
|
|
||||
help: consider using `drop` function
|
||||
|
|
||||
LL | drop(self);
|
||||
| +++++ ~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
17
tests/ui/fmt/raw-idents.rs
Normal file
17
tests/ui/fmt/raw-idents.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Regression test for https://github.com/rust-lang/rust/issues/115466
|
||||
|
||||
// The "identifier" in format strings is parsed as an IDENTIFIER_OR_KEYWORD, not an IDENTIFIER.
|
||||
// Test that there is an actionable diagnostic if a RAW_IDENTIFIER is used instead.
|
||||
|
||||
fn main() {
|
||||
let r#type = "foobar";
|
||||
println!("It is {r#type}"); //~ ERROR: invalid format string: raw identifiers are not supported
|
||||
println!(r##"It still is {r#type}"##); //~ ERROR: invalid format string: raw identifiers are not supported
|
||||
println!(concat!("{r#", "type}")); //~ ERROR: invalid format string: raw identifiers are not supported
|
||||
println!("{\x72\x23type:?}"); //~ ERROR: invalid format string: raw identifiers are not supported
|
||||
|
||||
// OK
|
||||
println!("{type}");
|
||||
println!("{let}", let = r#type);
|
||||
println!("{let}", r#let = r#type);
|
||||
}
|
44
tests/ui/fmt/raw-idents.stderr
Normal file
44
tests/ui/fmt/raw-idents.stderr
Normal file
@ -0,0 +1,44 @@
|
||||
error: invalid format string: raw identifiers are not supported
|
||||
--> $DIR/raw-idents.rs:8:22
|
||||
|
|
||||
LL | println!("It is {r#type}");
|
||||
| --^^^^
|
||||
| |
|
||||
| raw identifier used here in format string
|
||||
| help: remove the `r#`
|
||||
|
|
||||
= note: identifiers in format strings can be keywords and don't need to be prefixed with `r#`
|
||||
|
||||
error: invalid format string: raw identifiers are not supported
|
||||
--> $DIR/raw-idents.rs:9:31
|
||||
|
|
||||
LL | println!(r##"It still is {r#type}"##);
|
||||
| --^^^^
|
||||
| |
|
||||
| raw identifier used here in format string
|
||||
| help: remove the `r#`
|
||||
|
|
||||
= note: identifiers in format strings can be keywords and don't need to be prefixed with `r#`
|
||||
|
||||
error: invalid format string: raw identifiers are not supported
|
||||
--> $DIR/raw-idents.rs:10:14
|
||||
|
|
||||
LL | println!(concat!("{r#", "type}"));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ raw identifier used here in format string
|
||||
|
|
||||
= note: identifiers in format strings can be keywords and don't need to be prefixed with `r#`
|
||||
= note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: invalid format string: raw identifiers are not supported
|
||||
--> $DIR/raw-idents.rs:11:16
|
||||
|
|
||||
LL | println!("{\x72\x23type:?}");
|
||||
| --------^^^^
|
||||
| |
|
||||
| raw identifier used here in format string
|
||||
| help: remove the `r#`
|
||||
|
|
||||
= note: identifiers in format strings can be keywords and don't need to be prefixed with `r#`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -46,7 +46,7 @@ fn channel() {
|
||||
tx.send(&z).unwrap();
|
||||
}
|
||||
//~^^ ERROR `z` does not live long enough
|
||||
// (channels lack #[may_dangle], thus their dtors are implicit uses of `z`)
|
||||
tx.use_ref(); // (channel drop glue does not use `z` => needs explicit use)
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -75,11 +75,9 @@ LL | tx.send(&z).unwrap();
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL | }
|
||||
| - `z` dropped here while still borrowed
|
||||
...
|
||||
LL | }
|
||||
| - borrow might be used here, when `tx` is dropped and runs the `Drop` code for type `Sender`
|
||||
|
|
||||
= note: values in a scope are dropped in the opposite order they are defined
|
||||
LL |
|
||||
LL | tx.use_ref(); // (channel drop glue does not use `z` => needs explicit use)
|
||||
| -- borrow later used here
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user