diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 4f75dd7e99287..9b6dcfd17c62e 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -373,8 +373,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } fn unsized_feature_enabled(&self) -> bool { - let features = self.tcx().features(); - features.unsized_locals() || features.unsized_fn_params() + self.tcx().features().unsized_fn_params() } /// Equate the inferred type and the annotated type for user type annotations @@ -957,7 +956,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } - // When `unsized_fn_params` or `unsized_locals` is enabled, only function calls + // When `unsized_fn_params` is enabled, only function calls // and nullary ops are checked in `check_call_dest`. if !self.unsized_feature_enabled() { match self.body.local_kind(local) { @@ -1941,7 +1940,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); } - // When `unsized_fn_params` and `unsized_locals` are both not enabled, + // When `unsized_fn_params` is not enabled, // this check is done at `check_local`. if self.unsized_feature_enabled() { let span = term.source_info.span; diff --git a/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs b/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs index 5479b0c617bfb..f0d1f6e221572 100644 --- a/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs +++ b/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs @@ -32,10 +32,6 @@ impl, U> CoerceUnsized> for Wrapper {} impl, U> DispatchFromDyn> for Wrapper {} trait Trait { - // This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable - // without unsized_locals), but wrappers around `Self` currently are not. - // FIXME (mikeyhew) uncomment this when unsized rvalues object-safety is implemented - // fn wrapper(self: Wrapper) -> i32; fn ptr_wrapper(self: Ptr>) -> i32; fn wrapper_ptr(self: Wrapper>) -> i32; fn wrapper_ptr_wrapper(self: Wrapper>>) -> i32; diff --git a/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs b/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs index b299aa879740a..c26606f0bdd5c 100644 --- a/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs +++ b/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs @@ -37,10 +37,6 @@ impl, U> DispatchFromDyn> for Wrapper {} trait Trait { - // This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable - // without unsized_locals), but wrappers around `Self` currently are not. - // FIXME (mikeyhew) uncomment this when unsized rvalues object-safety is implemented - // fn wrapper(self: Wrapper) -> i32; fn ptr_wrapper(self: Ptr>) -> i32; fn wrapper_ptr(self: Wrapper>) -> i32; fn wrapper_ptr_wrapper(self: Wrapper>>) -> i32; diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 9738f169595e7..0cd090b25a4f8 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -263,6 +263,8 @@ declare_features! ( /// Allows unnamed fields of struct and union type (removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign"), 131045), (removed, unsafe_no_drop_flag, "1.0.0", None, None), + /// Allows unsized rvalues at arguments and parameters. + (removed, unsized_locals, "CURRENT_RUSTC_VERSION", Some(48055), Some("removed due to implementation concerns; see https://github.com/rust-lang/rust/issues/111942")), (removed, unsized_tuple_coercion, "1.87.0", Some(42877), Some("The feature restricts possible layouts for tuples, and this restriction is not worth it."), 137728), /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index cfdca8c48b0d1..bd6ea85014767 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -667,8 +667,6 @@ declare_features! ( (incomplete, unsized_const_params, "1.82.0", Some(95174)), /// Allows unsized fn parameters. (internal, unsized_fn_params, "1.49.0", Some(48055)), - /// Allows unsized rvalues at arguments and parameters. - (incomplete, unsized_locals, "1.30.0", Some(48055)), /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute. (unstable, used_with_arg, "1.60.0", Some(93798)), /// Allows use of attributes in `where` clauses. diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 3e98bd213d3bf..f768bd157abc8 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -599,7 +599,7 @@ hir_analysis_value_of_associated_struct_already_specified = .label = re-bound here .previous_bound_label = `{$item_name}` bound here first -hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions} +hir_analysis_variadic_function_compatible_convention = C-variadic functions with the {$convention} calling convention are not supported .label = C-variadic function must have a compatible calling convention hir_analysis_variances_of = {$variances} diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 7cb31a64e13e6..c458878da15b5 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -10,6 +10,7 @@ use std::mem; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; +use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Arm, Block, Expr, LetStmt, Pat, PatKind, Stmt}; @@ -752,13 +753,19 @@ fn resolve_local<'tcx>( record_rvalue_scope_if_borrow_expr(visitor, arm.body, blk_id); } } - hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) => { - // FIXME(@dingxiangfei2009): choose call arguments here - // for candidacy for extended parameter rule application - } - hir::ExprKind::Index(..) => { - // FIXME(@dingxiangfei2009): select the indices - // as candidate for rvalue scope rules + hir::ExprKind::Call(func, args) => { + // Recurse into tuple constructors, such as `Some(&temp())`. + // + // That way, there is no difference between `Some(..)` and `Some { 0: .. }`, + // even though the former is syntactically a function call. + if let hir::ExprKind::Path(path) = &func.kind + && let hir::QPath::Resolved(None, path) = path + && let Res::SelfCtor(_) | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) = path.res + { + for arg in args { + record_rvalue_scope_if_borrow_expr(visitor, arg, blk_id); + } + } } _ => {} } diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 809cb311c1f5b..8de2aec95a7b2 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -633,7 +633,7 @@ pub(crate) struct VariadicFunctionCompatibleConvention<'a> { #[primary_span] #[label] pub span: Span, - pub conventions: &'a str, + pub convention: &'a str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 007f3a6abf6c4..4f699462ac346 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -115,12 +115,6 @@ fn require_c_abi_if_c_variadic( abi: ExternAbi, span: Span, ) { - const CONVENTIONS_UNSTABLE: &str = - "`C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi`"; - const CONVENTIONS_STABLE: &str = "`C` or `cdecl`"; - const UNSTABLE_EXPLAIN: &str = - "using calling conventions other than `C` or `cdecl` for varargs functions is unstable"; - // ABIs which can stably use varargs if !decl.c_variadic || matches!(abi, ExternAbi::C { .. } | ExternAbi::Cdecl { .. }) { return; @@ -140,20 +134,18 @@ fn require_c_abi_if_c_variadic( // Looks like we need to pick an error to emit. // Is there any feature which we could have enabled to make this work? + let unstable_explain = + format!("C-variadic functions with the {abi} calling convention are unstable"); match abi { ExternAbi::System { .. } => { - feature_err(&tcx.sess, sym::extern_system_varargs, span, UNSTABLE_EXPLAIN) + feature_err(&tcx.sess, sym::extern_system_varargs, span, unstable_explain) } abi if abi.supports_varargs() => { - feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, UNSTABLE_EXPLAIN) + feature_err(&tcx.sess, sym::extended_varargs_abi_support, span, unstable_explain) } _ => tcx.dcx().create_err(errors::VariadicFunctionCompatibleConvention { span, - conventions: if tcx.sess.opts.unstable_features.is_nightly_build() { - CONVENTIONS_UNSTABLE - } else { - CONVENTIONS_STABLE - }, + convention: &format!("{abi}"), }), } .emit(); diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index d9fa56fefeb21..24092c01125fc 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1662,9 +1662,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { blk_id, expression, ); - if !fcx.tcx.features().unsized_locals() { - unsized_return = self.is_return_ty_definitely_unsized(fcx); - } + unsized_return = self.is_return_ty_definitely_unsized(fcx); } ObligationCauseCode::ReturnValue(return_expr_id) => { err = self.report_return_mismatched_types( @@ -1676,9 +1674,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { return_expr_id, expression, ); - if !fcx.tcx.features().unsized_locals() { - unsized_return = self.is_return_ty_definitely_unsized(fcx); - } + unsized_return = self.is_return_ty_definitely_unsized(fcx); } ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause { arm_span, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 87682d52dbfd3..30bf557dc93a8 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -809,9 +809,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } - // Here we want to prevent struct constructors from returning unsized types. - // There were two cases this happened: fn pointer coercion in stable - // and usual function call in presence of unsized_locals. + // Here we want to prevent struct constructors from returning unsized types, + // which can happen with fn pointer coercion on stable. // Also, as we just want to check sizedness, instead of introducing // placeholder lifetimes with probing, we just replace higher lifetimes // with fresh vars. diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs index 7d99b0e78694e..f1d6476a0f363 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -202,7 +202,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { ), ); } - } else if !self.fcx.tcx.features().unsized_locals() { + } else { self.fcx.require_type_is_sized( var_ty, p.span, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 6cb53bbd7452e..288d915e85c65 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -724,7 +724,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let def_path = tcx.def_path_str(adt_def.did()); err.span_suggestion( - ty.span.to(item_ident.span), + sugg_span, format!("to construct a value of type `{}`, use the explicit path", def_path), def_path, Applicability::MachineApplicable, diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 5b5253c7e7e21..982cfa2e42be4 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -492,7 +492,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let final_upvar_tys = self.final_upvar_tys(closure_def_id); debug!(?closure_hir_id, ?args, ?final_upvar_tys); - if self.tcx.features().unsized_locals() || self.tcx.features().unsized_fn_params() { + if self.tcx.features().unsized_fn_params() { for capture in self.typeck_results.borrow().closure_min_captures_flattened(closure_def_id) { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index f2f975a69683e..56f19d7929d43 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1133,13 +1133,6 @@ pub type AssertMessage<'tcx> = AssertKind>; /// Each local naturally corresponds to the place `Place { local, projection: [] }`. This place has /// the address of the local's allocation and the type of the local. /// -/// **Needs clarification:** Unsized locals seem to present a bit of an issue. Their allocation -/// can't actually be created on `StorageLive`, because it's unclear how big to make the allocation. -/// Furthermore, MIR produces assignments to unsized locals, although that is not permitted under -/// `#![feature(unsized_locals)]` in Rust. Besides just putting "unsized locals are special and -/// different" in a bunch of places, I (JakobDegen) don't know how to incorporate this behavior into -/// the current MIR semantics in a clean way - possibly this needs some design work first. -/// /// For places that are not locals, ie they have a non-empty list of projections, we define the /// values as a function of the parent place, that is the place with its last [`ProjectionElem`] /// stripped. The way this is computed of course depends on the kind of that last projection diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 5ba4e5446e9d4..68adfb3cdb388 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -79,7 +79,7 @@ pub enum InstanceKind<'tcx> { Intrinsic(DefId), /// `::method` where `method` receives unsizeable `self: Self` (part of the - /// `unsized_locals` feature). + /// `unsized_fn_params` feature). /// /// The generated shim will take `Self` via `*mut Self` - conceptually this is `&owned Self` - /// and dereference the argument to call the original function. diff --git a/compiler/rustc_mir_build/src/builder/expr/as_operand.rs b/compiler/rustc_mir_build/src/builder/expr/as_operand.rs index 2059610ee47d7..982e7aa8246b6 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_operand.rs @@ -55,9 +55,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// local variable of unsized type. For example, consider this program: /// /// ``` - /// #![feature(unsized_locals, unsized_fn_params)] + /// #![feature(unsized_fn_params)] /// # use core::fmt::Debug; - /// fn foo(p: dyn Debug) { dbg!(p); } + /// fn foo(_p: dyn Debug) { /* ... */ } /// /// fn bar(box_p: Box) { foo(*box_p); } /// ``` @@ -84,7 +84,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// will actually provide a pointer to the interior of the box, and not move the `dyn Debug` /// value to the stack. /// - /// See #68304 for more details. + /// See for more details. pub(crate) fn as_local_call_operand( &mut self, block: BasicBlock, diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index d5d0d56f52880..06c6b46a9c2aa 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1417,9 +1417,9 @@ fn check_field_tys_sized<'tcx>( coroutine_layout: &CoroutineLayout<'tcx>, def_id: LocalDefId, ) { - // No need to check if unsized_locals/unsized_fn_params is disabled, + // No need to check if unsized_fn_params is disabled, // since we will error during typeck. - if !tcx.features().unsized_locals() && !tcx.features().unsized_fn_params() { + if !tcx.features().unsized_fn_params() { return; } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 92c30d239b50a..bda71ceaa551a 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -240,8 +240,6 @@ struct VnState<'body, 'tcx> { next_opaque: usize, /// Cache the deref values. derefs: Vec, - /// Cache the value of the `unsized_locals` features, to avoid fetching it repeatedly in a loop. - feature_unsized_locals: bool, ssa: &'body SsaLocals, dominators: Dominators, reused_locals: DenseBitSet, @@ -273,7 +271,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { evaluated: IndexVec::with_capacity(num_values), next_opaque: 1, derefs: Vec::new(), - feature_unsized_locals: tcx.features().unsized_locals(), ssa, dominators, reused_locals: DenseBitSet::new_empty(local_decls.len()), @@ -329,13 +326,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { fn assign(&mut self, local: Local, value: VnIndex) { debug_assert!(self.ssa.is_ssa(local)); self.locals[local] = Some(value); - - // Only register the value if its type is `Sized`, as we will emit copies of it. - let is_sized = !self.feature_unsized_locals - || self.local_decls[local].ty.is_sized(self.tcx, self.typing_env()); - if is_sized { - self.rev_locals[value].push(local); - } + self.rev_locals[value].push(local); } fn insert_constant(&mut self, value: Const<'tcx>) -> VnIndex { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 68bd9440538fa..ee5a5b247ce8c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2995,9 +2995,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if local { err.note("all local variables must have a statically known size"); } - if !tcx.features().unsized_locals() { - err.help("unsized locals are gated as an unstable feature"); - } } ObligationCauseCode::SizedArgumentType(hir_id) => { let mut ty = None; diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 220a847cc230f..47d207e8d41b3 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -414,8 +414,8 @@ fn virtual_call_violations_for_method<'tcx>( let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0)); - // Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on. - // However, this is already considered dyn compatible. We allow it as a special case here. + // `self: Self` can't be dispatched on. + // However, this is considered dyn compatible. We allow it as a special case here. // FIXME(mikeyhew) get rid of this `if` statement once `receiver_is_dispatchable` allows // `Receiver: Unsize dyn Trait]>`. if receiver_ty != tcx.types.self_param { diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 51418036f428e..aa9e5fce1d4cc 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1220,11 +1220,11 @@ impl BTreeSet { /// assert_eq!(high.into_iter().collect::>(), [4, 5, 6, 7]); /// ``` #[unstable(feature = "btree_extract_if", issue = "70530")] - pub fn extract_if<'a, F, R>(&'a mut self, range: R, pred: F) -> ExtractIf<'a, T, R, F, A> + pub fn extract_if(&mut self, range: R, pred: F) -> ExtractIf<'_, T, R, F, A> where T: Ord, R: RangeBounds, - F: 'a + FnMut(&T) -> bool, + F: FnMut(&T) -> bool, { let (inner, alloc) = self.map.extract_if_inner(range); ExtractIf { pred, inner, alloc } @@ -1585,11 +1585,11 @@ where } #[unstable(feature = "btree_extract_if", issue = "70530")] -impl<'a, T, R, F, A: Allocator + Clone> Iterator for ExtractIf<'_, T, R, F, A> +impl Iterator for ExtractIf<'_, T, R, F, A> where T: PartialOrd, R: RangeBounds, - F: 'a + FnMut(&T) -> bool, + F: FnMut(&T) -> bool, { type Item = T; diff --git a/library/compiler-builtins/.release-plz.toml b/library/compiler-builtins/.release-plz.toml deleted file mode 100644 index 8023ade9bfd2f..0000000000000 --- a/library/compiler-builtins/.release-plz.toml +++ /dev/null @@ -1,13 +0,0 @@ -[workspace] -# As part of the release process, we delete `libm/Cargo.toml`. Since -# this is only run in CI, we shouldn't need to worry about it. -allow_dirty = true -publish_allow_dirty = true - -[[package]] -name = "compiler_builtins" -semver_check = false -changelog_include = ["libm"] # libm is included as part of builtins - -[[package]] -name = "libm" diff --git a/library/compiler-builtins/Cargo.toml b/library/compiler-builtins/Cargo.toml index fb638f2fb379f..41350c6cb9909 100644 --- a/library/compiler-builtins/Cargo.toml +++ b/library/compiler-builtins/Cargo.toml @@ -1,8 +1,8 @@ [workspace] resolver = "2" members = [ + "builtins-shim", "builtins-test", - "compiler-builtins", "crates/josh-sync", "crates/libm-macros", "crates/musl-math-sys", @@ -14,8 +14,8 @@ members = [ ] default-members = [ + "builtins-shim", "builtins-test", - "compiler-builtins", "crates/libm-macros", "libm", "libm-test", @@ -26,6 +26,10 @@ exclude = [ # and `mangled-names` disabled, which is the opposite of what is needed for # other tests, so it makes sense to keep it out of the workspace. "builtins-test-intrinsics", + # We test via the `builtins-shim` crate, so exclude the `compiler-builtins` + # that has a dependency on `core`. See `builtins-shim/Cargo.toml` for more + # details. + "compiler-builtins", ] [profile.release] diff --git a/library/compiler-builtins/builtins-shim/Cargo.toml b/library/compiler-builtins/builtins-shim/Cargo.toml new file mode 100644 index 0000000000000..8eb880c6fd1d0 --- /dev/null +++ b/library/compiler-builtins/builtins-shim/Cargo.toml @@ -0,0 +1,63 @@ +# NOTE: Must be kept in sync with `../compiler-builtins/Cargo.toml`. +# +# The manifest at `../compiler-builtins` is what actually gets used in the +# rust-lang/rust tree; however, we can't build it out of tree because it +# depends on `core` by path, and even optional Cargo dependencies need to be +# available at build time. So, we work around this by having this "shim" +# manifest that is identical except for the `core` dependency and forwards +# to the same sources, which acts as the `compiler-builtins` Cargo entrypoint +# for out of tree testing + +[package] +name = "compiler_builtins" +version = "0.1.160" +authors = ["Jorge Aparicio "] +description = "Compiler intrinsics used by the Rust compiler." +repository = "https://github.com/rust-lang/compiler-builtins" +license = "MIT AND Apache-2.0 WITH LLVM-exception AND (MIT OR Apache-2.0)" +edition = "2024" +publish = false +links = "compiler-rt" + +build = "../compiler-builtins/build.rs" + +[lib] +path = "../compiler-builtins/src/lib.rs" +bench = false +doctest = false +test = false + +[build-dependencies] +cc = { optional = true, version = "1.2" } + +[features] +default = ["compiler-builtins"] + +# Enable compilation of C code in compiler-rt, filling in some more optimized +# implementations and also filling in unimplemented intrinsics +c = ["dep:cc"] + +# Workaround for the Cranelift codegen backend. Disables any implementations +# which use inline assembly and fall back to pure Rust versions (if available). +no-asm = [] + +# Workaround for codegen backends which haven't yet implemented `f16` and +# `f128` support. Disabled any intrinsics which use those types. +no-f16-f128 = [] + +# Flag this library as the unstable compiler-builtins lib +compiler-builtins = [] + +# Generate memory-related intrinsics like memcpy +mem = [] + +# Mangle all names so this can be linked in with other versions or other +# compiler-rt implementations. Also used for testing +mangled-names = [] + +# Only used in the compiler's build system +rustc-dep-of-std = ["compiler-builtins"] + +# This makes certain traits and function specializations public that +# are not normally public but are required by the `builtins-test` +unstable-public-internals = [] diff --git a/library/compiler-builtins/builtins-test-intrinsics/Cargo.toml b/library/compiler-builtins/builtins-test-intrinsics/Cargo.toml index 064b7cad2f64b..e73a1f7b17e5b 100644 --- a/library/compiler-builtins/builtins-test-intrinsics/Cargo.toml +++ b/library/compiler-builtins/builtins-test-intrinsics/Cargo.toml @@ -6,7 +6,7 @@ publish = false license = "MIT OR Apache-2.0" [dependencies] -compiler_builtins = { path = "../compiler-builtins", features = ["compiler-builtins"] } +compiler_builtins = { path = "../builtins-shim", features = ["compiler-builtins"] } panic-handler = { path = "../crates/panic-handler" } [features] diff --git a/library/compiler-builtins/builtins-test/Cargo.toml b/library/compiler-builtins/builtins-test/Cargo.toml index c7742aa24275f..093d4633f8746 100644 --- a/library/compiler-builtins/builtins-test/Cargo.toml +++ b/library/compiler-builtins/builtins-test/Cargo.toml @@ -17,7 +17,7 @@ rustc_apfloat = "0.2.2" iai-callgrind = { version = "0.14.1", optional = true } [dependencies.compiler_builtins] -path = "../compiler-builtins" +path = "../builtins-shim" default-features = false features = ["unstable-public-internals"] diff --git a/library/compiler-builtins/builtins-test/tests/lse.rs b/library/compiler-builtins/builtins-test/tests/lse.rs index 53167d98fc0e3..0d85228d7a22d 100644 --- a/library/compiler-builtins/builtins-test/tests/lse.rs +++ b/library/compiler-builtins/builtins-test/tests/lse.rs @@ -1,4 +1,5 @@ #![feature(decl_macro)] // so we can use pub(super) +#![feature(macro_metavar_expr_concat)] #![cfg(all(target_arch = "aarch64", target_os = "linux", not(feature = "no-asm")))] /// Translate a byte size to a Rust type. @@ -87,7 +88,7 @@ test_op!(add, |left, right| left.wrapping_add(right)); test_op!(clr, |left, right| left & !right); test_op!(xor, std::ops::BitXor::bitxor); test_op!(or, std::ops::BitOr::bitor); - +use compiler_builtins::{foreach_bytes, foreach_ordering}; compiler_builtins::foreach_cas!(cas::test); compiler_builtins::foreach_cas16!(test_cas16); compiler_builtins::foreach_swp!(swap::test); diff --git a/library/compiler-builtins/ci/bench-icount.sh b/library/compiler-builtins/ci/bench-icount.sh index 5724955fe3672..d2baebb52d8fd 100755 --- a/library/compiler-builtins/ci/bench-icount.sh +++ b/library/compiler-builtins/ci/bench-icount.sh @@ -57,7 +57,7 @@ function run_icount_benchmarks() { # Disregard regressions after merge echo "Benchmarks completed with regressions; ignoring (not in a PR)" else - ./ci/ci-util.py handle-banch-regressions "$PR_NUMBER" + ./ci/ci-util.py handle-bench-regressions "$PR_NUMBER" fi } diff --git a/library/compiler-builtins/compiler-builtins/Cargo.toml b/library/compiler-builtins/compiler-builtins/Cargo.toml index df8e964825b32..c5446cd76e326 100644 --- a/library/compiler-builtins/compiler-builtins/Cargo.toml +++ b/library/compiler-builtins/compiler-builtins/Cargo.toml @@ -1,14 +1,18 @@ +# NOTE: Must be kept in sync with `../builtins-shim/Cargo.toml`. +# +# This manifest is actually used in-tree by rust-lang/rust, +# `../builtins-shim/Cargo.toml` is used by out-of-tree testing. See the other +# manifest for further details. + [package] -authors = ["Jorge Aparicio "] name = "compiler_builtins" version = "0.1.160" -license = "MIT AND Apache-2.0 WITH LLVM-exception AND (MIT OR Apache-2.0)" -readme = "README.md" +authors = ["Jorge Aparicio "] +description = "Compiler intrinsics used by the Rust compiler." repository = "https://github.com/rust-lang/compiler-builtins" -homepage = "https://github.com/rust-lang/compiler-builtins" -documentation = "https://docs.rs/compiler_builtins" +license = "MIT AND Apache-2.0 WITH LLVM-exception AND (MIT OR Apache-2.0)" edition = "2024" -description = "Compiler intrinsics used by the Rust compiler." +publish = false links = "compiler-rt" [lib] @@ -53,7 +57,3 @@ rustc-dep-of-std = ["compiler-builtins", "dep:core"] # This makes certain traits and function specializations public that # are not normally public but are required by the `builtins-test` unstable-public-internals = [] - -[lints.rust] -# The cygwin config can be dropped after our benchmark toolchain is bumped -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bootstrap)', 'cfg(target_os, values("cygwin"))'] } diff --git a/library/compiler-builtins/compiler-builtins/build.rs b/library/compiler-builtins/compiler-builtins/build.rs index 7c8da02fd287f..018899faf1d44 100644 --- a/library/compiler-builtins/compiler-builtins/build.rs +++ b/library/compiler-builtins/compiler-builtins/build.rs @@ -1,9 +1,6 @@ mod configure; -use std::collections::BTreeMap; use std::env; -use std::path::PathBuf; -use std::sync::atomic::Ordering; use configure::{Target, configure_aliases, configure_f16_f128}; @@ -86,10 +83,6 @@ fn main() { { println!("cargo:rustc-cfg=kernel_user_helpers") } - - if llvm_target[0].starts_with("aarch64") { - generate_aarch64_outlined_atomics(); - } } /// Run configuration for `libm` since it is included directly. @@ -132,61 +125,6 @@ fn configure_libm(target: &Target) { println!("cargo:rustc-cfg=feature=\"unstable-intrinsics\""); } -fn aarch64_symbol(ordering: Ordering) -> &'static str { - match ordering { - Ordering::Relaxed => "relax", - Ordering::Acquire => "acq", - Ordering::Release => "rel", - Ordering::AcqRel => "acq_rel", - _ => panic!("unknown symbol for {ordering:?}"), - } -} - -/// The `concat_idents` macro is extremely annoying and doesn't allow us to define new items. -/// Define them from the build script instead. -/// Note that the majority of the code is still defined in `aarch64.rs` through inline macros. -fn generate_aarch64_outlined_atomics() { - use std::fmt::Write; - // #[macro_export] so that we can use this in tests - let gen_macro = - |name| format!("#[macro_export] macro_rules! foreach_{name} {{ ($macro:path) => {{\n"); - - // Generate different macros for add/clr/eor/set so that we can test them separately. - let sym_names = ["cas", "ldadd", "ldclr", "ldeor", "ldset", "swp"]; - let mut macros = BTreeMap::new(); - for sym in sym_names { - macros.insert(sym, gen_macro(sym)); - } - - // Only CAS supports 16 bytes, and it has a different implementation that uses a different macro. - let mut cas16 = gen_macro("cas16"); - - for ordering in [ - Ordering::Relaxed, - Ordering::Acquire, - Ordering::Release, - Ordering::AcqRel, - ] { - let sym_ordering = aarch64_symbol(ordering); - for size in [1, 2, 4, 8] { - for (sym, macro_) in &mut macros { - let name = format!("__aarch64_{sym}{size}_{sym_ordering}"); - writeln!(macro_, "$macro!( {ordering:?}, {size}, {name} );").unwrap(); - } - } - let name = format!("__aarch64_cas16_{sym_ordering}"); - writeln!(cas16, "$macro!( {ordering:?}, {name} );").unwrap(); - } - - let mut buf = String::new(); - for macro_def in macros.values().chain(std::iter::once(&cas16)) { - buf += macro_def; - buf += "}; }\n"; - } - let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap()); - std::fs::write(out_dir.join("outlined_atomics.rs"), buf).unwrap(); -} - /// Emit directives for features we expect to support that aren't in `Cargo.toml`. /// /// These are mostly cfg elements emitted by this `build.rs`. diff --git a/library/compiler-builtins/compiler-builtins/src/aarch64_linux.rs b/library/compiler-builtins/compiler-builtins/src/aarch64_linux.rs index 226121237e878..38fcab152aed2 100644 --- a/library/compiler-builtins/compiler-builtins/src/aarch64_linux.rs +++ b/library/compiler-builtins/compiler-builtins/src/aarch64_linux.rs @@ -262,8 +262,78 @@ macro_rules! or { }; } -// See `generate_aarch64_outlined_atomics` in build.rs. -include!(concat!(env!("OUT_DIR"), "/outlined_atomics.rs")); +#[macro_export] +macro_rules! foreach_ordering { + ($macro:path, $bytes:tt, $name:ident) => { + $macro!( Relaxed, $bytes, ${concat($name, _relax)} ); + $macro!( Acquire, $bytes, ${concat($name, _acq)} ); + $macro!( Release, $bytes, ${concat($name, _rel)} ); + $macro!( AcqRel, $bytes, ${concat($name, _acq_rel)} ); + }; + ($macro:path, $name:ident) => { + $macro!( Relaxed, ${concat($name, _relax)} ); + $macro!( Acquire, ${concat($name, _acq)} ); + $macro!( Release, ${concat($name, _rel)} ); + $macro!( AcqRel, ${concat($name, _acq_rel)} ); + }; +} + +#[macro_export] +macro_rules! foreach_bytes { + ($macro:path, $name:ident) => { + foreach_ordering!( $macro, 1, ${concat(__aarch64_, $name, "1")} ); + foreach_ordering!( $macro, 2, ${concat(__aarch64_, $name, "2")} ); + foreach_ordering!( $macro, 4, ${concat(__aarch64_, $name, "4")} ); + foreach_ordering!( $macro, 8, ${concat(__aarch64_, $name, "8")} ); + }; +} + +/// Generate different macros for cas/swp/add/clr/eor/set so that we can test them separately. +#[macro_export] +macro_rules! foreach_cas { + ($macro:path) => { + foreach_bytes!($macro, cas); + }; +} + +/// Only CAS supports 16 bytes, and it has a different implementation that uses a different macro. +#[macro_export] +macro_rules! foreach_cas16 { + ($macro:path) => { + foreach_ordering!($macro, __aarch64_cas16); + }; +} +#[macro_export] +macro_rules! foreach_swp { + ($macro:path) => { + foreach_bytes!($macro, swp); + }; +} +#[macro_export] +macro_rules! foreach_ldadd { + ($macro:path) => { + foreach_bytes!($macro, ldadd); + }; +} +#[macro_export] +macro_rules! foreach_ldclr { + ($macro:path) => { + foreach_bytes!($macro, ldclr); + }; +} +#[macro_export] +macro_rules! foreach_ldeor { + ($macro:path) => { + foreach_bytes!($macro, ldeor); + }; +} +#[macro_export] +macro_rules! foreach_ldset { + ($macro:path) => { + foreach_bytes!($macro, ldset); + }; +} + foreach_cas!(compare_and_swap); foreach_cas16!(compare_and_swap_i128); foreach_swp!(swap); diff --git a/library/compiler-builtins/compiler-builtins/src/lib.rs b/library/compiler-builtins/compiler-builtins/src/lib.rs index 6549d4cef9eda..1cec39d8b41bb 100644 --- a/library/compiler-builtins/compiler-builtins/src/lib.rs +++ b/library/compiler-builtins/compiler-builtins/src/lib.rs @@ -8,6 +8,7 @@ #![feature(linkage)] #![feature(naked_functions)] #![feature(repr_simd)] +#![feature(macro_metavar_expr_concat)] #![feature(rustc_attrs)] #![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] diff --git a/library/compiler-builtins/libm/Cargo.toml b/library/compiler-builtins/libm/Cargo.toml index b6fb5efcf76e5..63b4d3c277989 100644 --- a/library/compiler-builtins/libm/Cargo.toml +++ b/library/compiler-builtins/libm/Cargo.toml @@ -1,14 +1,12 @@ [package] +name = "libm" +version = "0.2.15" authors = ["Jorge Aparicio "] -categories = ["no-std"] description = "libm in pure Rust" -documentation = "https://docs.rs/libm" +categories = ["no-std"] keywords = ["libm", "math"] -license = "MIT" -name = "libm" -readme = "README.md" repository = "https://github.com/rust-lang/compiler-builtins" -version = "0.2.15" +license = "MIT" edition = "2021" rust-version = "1.63" diff --git a/library/compiler-builtins/libm/src/math/fmin_fmax.rs b/library/compiler-builtins/libm/src/math/fmin_fmax.rs index 2947b783e2fc5..481301994e991 100644 --- a/library/compiler-builtins/libm/src/math/fmin_fmax.rs +++ b/library/compiler-builtins/libm/src/math/fmin_fmax.rs @@ -82,22 +82,77 @@ mod tests { fn fmin_spec_test(f: impl Fn(F, F) -> F) { let cases = [ (F::ZERO, F::ZERO, F::ZERO), - (F::ONE, F::ONE, F::ONE), (F::ZERO, F::ONE, F::ZERO), - (F::ONE, F::ZERO, F::ZERO), (F::ZERO, F::NEG_ONE, F::NEG_ONE), + (F::ZERO, F::INFINITY, F::ZERO), + (F::ZERO, F::NEG_INFINITY, F::NEG_INFINITY), + (F::ZERO, F::NAN, F::ZERO), + (F::ZERO, F::NEG_NAN, F::ZERO), + (F::NEG_ZERO, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_ZERO, F::ONE, F::NEG_ZERO), + (F::NEG_ZERO, F::NEG_ONE, F::NEG_ONE), + (F::NEG_ZERO, F::INFINITY, F::NEG_ZERO), + (F::NEG_ZERO, F::NEG_INFINITY, F::NEG_INFINITY), + (F::NEG_ZERO, F::NAN, F::NEG_ZERO), + (F::NEG_ZERO, F::NEG_NAN, F::NEG_ZERO), + (F::ONE, F::ZERO, F::ZERO), + (F::ONE, F::NEG_ZERO, F::NEG_ZERO), + (F::ONE, F::ONE, F::ONE), + (F::ONE, F::NEG_ONE, F::NEG_ONE), + (F::ONE, F::INFINITY, F::ONE), + (F::ONE, F::NEG_INFINITY, F::NEG_INFINITY), + (F::ONE, F::NAN, F::ONE), + (F::ONE, F::NEG_NAN, F::ONE), (F::NEG_ONE, F::ZERO, F::NEG_ONE), + (F::NEG_ONE, F::NEG_ZERO, F::NEG_ONE), + (F::NEG_ONE, F::ONE, F::NEG_ONE), + (F::NEG_ONE, F::NEG_ONE, F::NEG_ONE), + (F::NEG_ONE, F::INFINITY, F::NEG_ONE), + (F::NEG_ONE, F::NEG_INFINITY, F::NEG_INFINITY), + (F::NEG_ONE, F::NAN, F::NEG_ONE), + (F::NEG_ONE, F::NEG_NAN, F::NEG_ONE), (F::INFINITY, F::ZERO, F::ZERO), + (F::INFINITY, F::NEG_ZERO, F::NEG_ZERO), + (F::INFINITY, F::ONE, F::ONE), + (F::INFINITY, F::NEG_ONE, F::NEG_ONE), + (F::INFINITY, F::INFINITY, F::INFINITY), + (F::INFINITY, F::NEG_INFINITY, F::NEG_INFINITY), + (F::INFINITY, F::NAN, F::INFINITY), + (F::INFINITY, F::NEG_NAN, F::INFINITY), (F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_ZERO, F::NEG_INFINITY), + (F::NEG_INFINITY, F::ONE, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_ONE, F::NEG_INFINITY), + (F::NEG_INFINITY, F::INFINITY, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_INFINITY, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NAN, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_NAN, F::NEG_INFINITY), (F::NAN, F::ZERO, F::ZERO), - (F::ZERO, F::NAN, F::ZERO), + (F::NAN, F::NEG_ZERO, F::NEG_ZERO), + (F::NAN, F::ONE, F::ONE), + (F::NAN, F::NEG_ONE, F::NEG_ONE), + (F::NAN, F::INFINITY, F::INFINITY), + (F::NAN, F::NEG_INFINITY, F::NEG_INFINITY), (F::NAN, F::NAN, F::NAN), + (F::NEG_NAN, F::ZERO, F::ZERO), + (F::NEG_NAN, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_NAN, F::ONE, F::ONE), + (F::NEG_NAN, F::NEG_ONE, F::NEG_ONE), + (F::NEG_NAN, F::INFINITY, F::INFINITY), + (F::NEG_NAN, F::NEG_INFINITY, F::NEG_INFINITY), ]; for (x, y, res) in cases { let val = f(x, y); assert_biteq!(val, res, "fmin({}, {})", Hexf(x), Hexf(y)); } + + // Ordering between zeros and NaNs does not matter + assert_eq!(f(F::ZERO, F::NEG_ZERO), F::ZERO); + assert_eq!(f(F::NEG_ZERO, F::ZERO), F::ZERO); + assert!(f(F::NAN, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_NAN, F::NAN).is_nan()); + assert!(f(F::NEG_NAN, F::NEG_NAN).is_nan()); } #[test] @@ -125,22 +180,77 @@ mod tests { fn fmax_spec_test(f: impl Fn(F, F) -> F) { let cases = [ (F::ZERO, F::ZERO, F::ZERO), - (F::ONE, F::ONE, F::ONE), (F::ZERO, F::ONE, F::ONE), - (F::ONE, F::ZERO, F::ONE), (F::ZERO, F::NEG_ONE, F::ZERO), + (F::ZERO, F::INFINITY, F::INFINITY), + (F::ZERO, F::NEG_INFINITY, F::ZERO), + (F::ZERO, F::NAN, F::ZERO), + (F::ZERO, F::NEG_NAN, F::ZERO), + (F::NEG_ZERO, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_ZERO, F::ONE, F::ONE), + (F::NEG_ZERO, F::NEG_ONE, F::NEG_ZERO), + (F::NEG_ZERO, F::INFINITY, F::INFINITY), + (F::NEG_ZERO, F::NEG_INFINITY, F::NEG_ZERO), + (F::NEG_ZERO, F::NAN, F::NEG_ZERO), + (F::NEG_ZERO, F::NEG_NAN, F::NEG_ZERO), + (F::ONE, F::ZERO, F::ONE), + (F::ONE, F::NEG_ZERO, F::ONE), + (F::ONE, F::ONE, F::ONE), + (F::ONE, F::NEG_ONE, F::ONE), + (F::ONE, F::INFINITY, F::INFINITY), + (F::ONE, F::NEG_INFINITY, F::ONE), + (F::ONE, F::NAN, F::ONE), + (F::ONE, F::NEG_NAN, F::ONE), (F::NEG_ONE, F::ZERO, F::ZERO), + (F::NEG_ONE, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_ONE, F::ONE, F::ONE), + (F::NEG_ONE, F::NEG_ONE, F::NEG_ONE), + (F::NEG_ONE, F::INFINITY, F::INFINITY), + (F::NEG_ONE, F::NEG_INFINITY, F::NEG_ONE), + (F::NEG_ONE, F::NAN, F::NEG_ONE), + (F::NEG_ONE, F::NEG_NAN, F::NEG_ONE), (F::INFINITY, F::ZERO, F::INFINITY), + (F::INFINITY, F::NEG_ZERO, F::INFINITY), + (F::INFINITY, F::ONE, F::INFINITY), + (F::INFINITY, F::NEG_ONE, F::INFINITY), + (F::INFINITY, F::INFINITY, F::INFINITY), + (F::INFINITY, F::NEG_INFINITY, F::INFINITY), + (F::INFINITY, F::NAN, F::INFINITY), + (F::INFINITY, F::NEG_NAN, F::INFINITY), (F::NEG_INFINITY, F::ZERO, F::ZERO), + (F::NEG_INFINITY, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_INFINITY, F::ONE, F::ONE), + (F::NEG_INFINITY, F::NEG_ONE, F::NEG_ONE), + (F::NEG_INFINITY, F::INFINITY, F::INFINITY), + (F::NEG_INFINITY, F::NEG_INFINITY, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NAN, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_NAN, F::NEG_INFINITY), (F::NAN, F::ZERO, F::ZERO), - (F::ZERO, F::NAN, F::ZERO), + (F::NAN, F::NEG_ZERO, F::NEG_ZERO), + (F::NAN, F::ONE, F::ONE), + (F::NAN, F::NEG_ONE, F::NEG_ONE), + (F::NAN, F::INFINITY, F::INFINITY), + (F::NAN, F::NEG_INFINITY, F::NEG_INFINITY), (F::NAN, F::NAN, F::NAN), + (F::NEG_NAN, F::ZERO, F::ZERO), + (F::NEG_NAN, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_NAN, F::ONE, F::ONE), + (F::NEG_NAN, F::NEG_ONE, F::NEG_ONE), + (F::NEG_NAN, F::INFINITY, F::INFINITY), + (F::NEG_NAN, F::NEG_INFINITY, F::NEG_INFINITY), ]; for (x, y, res) in cases { let val = f(x, y); assert_biteq!(val, res, "fmax({}, {})", Hexf(x), Hexf(y)); } + + // Ordering between zeros and NaNs does not matter + assert_eq!(f(F::ZERO, F::NEG_ZERO), F::ZERO); + assert_eq!(f(F::NEG_ZERO, F::ZERO), F::ZERO); + assert!(f(F::NAN, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_NAN, F::NAN).is_nan()); + assert!(f(F::NEG_NAN, F::NEG_NAN).is_nan()); } #[test] diff --git a/library/compiler-builtins/libm/src/math/fminimum_fmaximum.rs b/library/compiler-builtins/libm/src/math/fminimum_fmaximum.rs index b7999e27392b1..8f1308670511a 100644 --- a/library/compiler-builtins/libm/src/math/fminimum_fmaximum.rs +++ b/library/compiler-builtins/libm/src/math/fminimum_fmaximum.rs @@ -74,24 +74,77 @@ mod tests { fn fminimum_spec_test(f: impl Fn(F, F) -> F) { let cases = [ (F::ZERO, F::ZERO, F::ZERO), - (F::ONE, F::ONE, F::ONE), + (F::ZERO, F::NEG_ZERO, F::NEG_ZERO), (F::ZERO, F::ONE, F::ZERO), - (F::ONE, F::ZERO, F::ZERO), (F::ZERO, F::NEG_ONE, F::NEG_ONE), + (F::ZERO, F::INFINITY, F::ZERO), + (F::ZERO, F::NEG_INFINITY, F::NEG_INFINITY), + (F::ZERO, F::NAN, F::NAN), + (F::NEG_ZERO, F::ZERO, F::NEG_ZERO), + (F::NEG_ZERO, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_ZERO, F::ONE, F::NEG_ZERO), + (F::NEG_ZERO, F::NEG_ONE, F::NEG_ONE), + (F::NEG_ZERO, F::INFINITY, F::NEG_ZERO), + (F::NEG_ZERO, F::NEG_INFINITY, F::NEG_INFINITY), + (F::NEG_ZERO, F::NAN, F::NAN), + (F::ONE, F::ZERO, F::ZERO), + (F::ONE, F::NEG_ZERO, F::NEG_ZERO), + (F::ONE, F::ONE, F::ONE), + (F::ONE, F::NEG_ONE, F::NEG_ONE), + (F::ONE, F::INFINITY, F::ONE), + (F::ONE, F::NEG_INFINITY, F::NEG_INFINITY), + (F::ONE, F::NAN, F::NAN), (F::NEG_ONE, F::ZERO, F::NEG_ONE), + (F::NEG_ONE, F::NEG_ZERO, F::NEG_ONE), + (F::NEG_ONE, F::ONE, F::NEG_ONE), + (F::NEG_ONE, F::NEG_ONE, F::NEG_ONE), + (F::NEG_ONE, F::INFINITY, F::NEG_ONE), + (F::NEG_ONE, F::NEG_INFINITY, F::NEG_INFINITY), + (F::NEG_ONE, F::NAN, F::NAN), (F::INFINITY, F::ZERO, F::ZERO), + (F::INFINITY, F::NEG_ZERO, F::NEG_ZERO), + (F::INFINITY, F::ONE, F::ONE), + (F::INFINITY, F::NEG_ONE, F::NEG_ONE), + (F::INFINITY, F::INFINITY, F::INFINITY), + (F::INFINITY, F::NEG_INFINITY, F::NEG_INFINITY), + (F::INFINITY, F::NAN, F::NAN), (F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_ZERO, F::NEG_INFINITY), + (F::NEG_INFINITY, F::ONE, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_ONE, F::NEG_INFINITY), + (F::NEG_INFINITY, F::INFINITY, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_INFINITY, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NAN, F::NAN), (F::NAN, F::ZERO, F::NAN), - (F::ZERO, F::NAN, F::NAN), + (F::NAN, F::NEG_ZERO, F::NAN), + (F::NAN, F::ONE, F::NAN), + (F::NAN, F::NEG_ONE, F::NAN), + (F::NAN, F::INFINITY, F::NAN), + (F::NAN, F::NEG_INFINITY, F::NAN), (F::NAN, F::NAN, F::NAN), - (F::ZERO, F::NEG_ZERO, F::NEG_ZERO), - (F::NEG_ZERO, F::ZERO, F::NEG_ZERO), ]; for (x, y, res) in cases { let val = f(x, y); assert_biteq!(val, res, "fminimum({}, {})", Hexf(x), Hexf(y)); } + + // Ordering between NaNs does not matter + assert!(f(F::NAN, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_NAN, F::NAN).is_nan()); + assert!(f(F::ZERO, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_ZERO, F::NEG_NAN).is_nan()); + assert!(f(F::ONE, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_ONE, F::NEG_NAN).is_nan()); + assert!(f(F::INFINITY, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_INFINITY, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_NAN, F::ZERO).is_nan()); + assert!(f(F::NEG_NAN, F::NEG_ZERO).is_nan()); + assert!(f(F::NEG_NAN, F::ONE).is_nan()); + assert!(f(F::NEG_NAN, F::NEG_ONE).is_nan()); + assert!(f(F::NEG_NAN, F::INFINITY).is_nan()); + assert!(f(F::NEG_NAN, F::NEG_INFINITY).is_nan()); + assert!(f(F::NEG_NAN, F::NEG_NAN).is_nan()); } #[test] @@ -119,24 +172,77 @@ mod tests { fn fmaximum_spec_test(f: impl Fn(F, F) -> F) { let cases = [ (F::ZERO, F::ZERO, F::ZERO), - (F::ONE, F::ONE, F::ONE), + (F::ZERO, F::NEG_ZERO, F::ZERO), (F::ZERO, F::ONE, F::ONE), - (F::ONE, F::ZERO, F::ONE), (F::ZERO, F::NEG_ONE, F::ZERO), + (F::ZERO, F::INFINITY, F::INFINITY), + (F::ZERO, F::NEG_INFINITY, F::ZERO), + (F::ZERO, F::NAN, F::NAN), + (F::NEG_ZERO, F::ZERO, F::ZERO), + (F::NEG_ZERO, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_ZERO, F::ONE, F::ONE), + (F::NEG_ZERO, F::NEG_ONE, F::NEG_ZERO), + (F::NEG_ZERO, F::INFINITY, F::INFINITY), + (F::NEG_ZERO, F::NEG_INFINITY, F::NEG_ZERO), + (F::NEG_ZERO, F::NAN, F::NAN), + (F::ONE, F::ZERO, F::ONE), + (F::ONE, F::NEG_ZERO, F::ONE), + (F::ONE, F::ONE, F::ONE), + (F::ONE, F::NEG_ONE, F::ONE), + (F::ONE, F::INFINITY, F::INFINITY), + (F::ONE, F::NEG_INFINITY, F::ONE), + (F::ONE, F::NAN, F::NAN), (F::NEG_ONE, F::ZERO, F::ZERO), + (F::NEG_ONE, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_ONE, F::ONE, F::ONE), + (F::NEG_ONE, F::NEG_ONE, F::NEG_ONE), + (F::NEG_ONE, F::INFINITY, F::INFINITY), + (F::NEG_ONE, F::NEG_INFINITY, F::NEG_ONE), + (F::NEG_ONE, F::NAN, F::NAN), (F::INFINITY, F::ZERO, F::INFINITY), + (F::INFINITY, F::NEG_ZERO, F::INFINITY), + (F::INFINITY, F::ONE, F::INFINITY), + (F::INFINITY, F::NEG_ONE, F::INFINITY), + (F::INFINITY, F::INFINITY, F::INFINITY), + (F::INFINITY, F::NEG_INFINITY, F::INFINITY), + (F::INFINITY, F::NAN, F::NAN), (F::NEG_INFINITY, F::ZERO, F::ZERO), + (F::NEG_INFINITY, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_INFINITY, F::ONE, F::ONE), + (F::NEG_INFINITY, F::NEG_ONE, F::NEG_ONE), + (F::NEG_INFINITY, F::INFINITY, F::INFINITY), + (F::NEG_INFINITY, F::NEG_INFINITY, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NAN, F::NAN), (F::NAN, F::ZERO, F::NAN), - (F::ZERO, F::NAN, F::NAN), + (F::NAN, F::NEG_ZERO, F::NAN), + (F::NAN, F::ONE, F::NAN), + (F::NAN, F::NEG_ONE, F::NAN), + (F::NAN, F::INFINITY, F::NAN), + (F::NAN, F::NEG_INFINITY, F::NAN), (F::NAN, F::NAN, F::NAN), - (F::ZERO, F::NEG_ZERO, F::ZERO), - (F::NEG_ZERO, F::ZERO, F::ZERO), ]; for (x, y, res) in cases { let val = f(x, y); assert_biteq!(val, res, "fmaximum({}, {})", Hexf(x), Hexf(y)); } + + // Ordering between NaNs does not matter + assert!(f(F::NAN, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_NAN, F::NAN).is_nan()); + assert!(f(F::ZERO, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_ZERO, F::NEG_NAN).is_nan()); + assert!(f(F::ONE, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_ONE, F::NEG_NAN).is_nan()); + assert!(f(F::INFINITY, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_INFINITY, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_NAN, F::ZERO).is_nan()); + assert!(f(F::NEG_NAN, F::NEG_ZERO).is_nan()); + assert!(f(F::NEG_NAN, F::ONE).is_nan()); + assert!(f(F::NEG_NAN, F::NEG_ONE).is_nan()); + assert!(f(F::NEG_NAN, F::INFINITY).is_nan()); + assert!(f(F::NEG_NAN, F::NEG_INFINITY).is_nan()); + assert!(f(F::NEG_NAN, F::NEG_NAN).is_nan()); } #[test] diff --git a/library/compiler-builtins/libm/src/math/fminimum_fmaximum_num.rs b/library/compiler-builtins/libm/src/math/fminimum_fmaximum_num.rs index 180d21f72b74c..fadf934180a05 100644 --- a/library/compiler-builtins/libm/src/math/fminimum_fmaximum_num.rs +++ b/library/compiler-builtins/libm/src/math/fminimum_fmaximum_num.rs @@ -74,24 +74,77 @@ mod tests { fn fminimum_num_spec_test(f: impl Fn(F, F) -> F) { let cases = [ (F::ZERO, F::ZERO, F::ZERO), - (F::ONE, F::ONE, F::ONE), + (F::ZERO, F::NEG_ZERO, F::NEG_ZERO), (F::ZERO, F::ONE, F::ZERO), - (F::ONE, F::ZERO, F::ZERO), (F::ZERO, F::NEG_ONE, F::NEG_ONE), + (F::ZERO, F::INFINITY, F::ZERO), + (F::ZERO, F::NEG_INFINITY, F::NEG_INFINITY), + (F::ZERO, F::NAN, F::ZERO), + (F::ZERO, F::NEG_NAN, F::ZERO), + (F::NEG_ZERO, F::ZERO, F::NEG_ZERO), + (F::NEG_ZERO, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_ZERO, F::ONE, F::NEG_ZERO), + (F::NEG_ZERO, F::NEG_ONE, F::NEG_ONE), + (F::NEG_ZERO, F::INFINITY, F::NEG_ZERO), + (F::NEG_ZERO, F::NEG_INFINITY, F::NEG_INFINITY), + (F::NEG_ZERO, F::NAN, F::NEG_ZERO), + (F::NEG_ZERO, F::NEG_NAN, F::NEG_ZERO), + (F::ONE, F::ZERO, F::ZERO), + (F::ONE, F::NEG_ZERO, F::NEG_ZERO), + (F::ONE, F::ONE, F::ONE), + (F::ONE, F::NEG_ONE, F::NEG_ONE), + (F::ONE, F::INFINITY, F::ONE), + (F::ONE, F::NEG_INFINITY, F::NEG_INFINITY), + (F::ONE, F::NAN, F::ONE), + (F::ONE, F::NEG_NAN, F::ONE), (F::NEG_ONE, F::ZERO, F::NEG_ONE), + (F::NEG_ONE, F::NEG_ZERO, F::NEG_ONE), + (F::NEG_ONE, F::ONE, F::NEG_ONE), + (F::NEG_ONE, F::NEG_ONE, F::NEG_ONE), + (F::NEG_ONE, F::INFINITY, F::NEG_ONE), + (F::NEG_ONE, F::NEG_INFINITY, F::NEG_INFINITY), + (F::NEG_ONE, F::NAN, F::NEG_ONE), + (F::NEG_ONE, F::NEG_NAN, F::NEG_ONE), (F::INFINITY, F::ZERO, F::ZERO), + (F::INFINITY, F::NEG_ZERO, F::NEG_ZERO), + (F::INFINITY, F::ONE, F::ONE), + (F::INFINITY, F::NEG_ONE, F::NEG_ONE), + (F::INFINITY, F::INFINITY, F::INFINITY), + (F::INFINITY, F::NEG_INFINITY, F::NEG_INFINITY), + (F::INFINITY, F::NAN, F::INFINITY), + (F::INFINITY, F::NEG_NAN, F::INFINITY), (F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_ZERO, F::NEG_INFINITY), + (F::NEG_INFINITY, F::ONE, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_ONE, F::NEG_INFINITY), + (F::NEG_INFINITY, F::INFINITY, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_INFINITY, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NAN, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_NAN, F::NEG_INFINITY), (F::NAN, F::ZERO, F::ZERO), - (F::ZERO, F::NAN, F::ZERO), + (F::NAN, F::NEG_ZERO, F::NEG_ZERO), + (F::NAN, F::ONE, F::ONE), + (F::NAN, F::NEG_ONE, F::NEG_ONE), + (F::NAN, F::INFINITY, F::INFINITY), + (F::NAN, F::NEG_INFINITY, F::NEG_INFINITY), (F::NAN, F::NAN, F::NAN), - (F::ZERO, F::NEG_ZERO, F::NEG_ZERO), - (F::NEG_ZERO, F::ZERO, F::NEG_ZERO), + (F::NEG_NAN, F::ZERO, F::ZERO), + (F::NEG_NAN, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_NAN, F::ONE, F::ONE), + (F::NEG_NAN, F::NEG_ONE, F::NEG_ONE), + (F::NEG_NAN, F::INFINITY, F::INFINITY), + (F::NEG_NAN, F::NEG_INFINITY, F::NEG_INFINITY), ]; - for (x, y, res) in cases { - let val = f(x, y); - assert_biteq!(val, res, "fminimum_num({}, {})", Hexf(x), Hexf(y)); + for (x, y, expected) in cases { + let actual = f(x, y); + assert_biteq!(actual, expected, "fminimum_num({}, {})", Hexf(x), Hexf(y)); } + + // Ordering between NaNs does not matter + assert!(f(F::NAN, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_NAN, F::NAN).is_nan()); + assert!(f(F::NEG_NAN, F::NEG_NAN).is_nan()); } #[test] @@ -119,24 +172,77 @@ mod tests { fn fmaximum_num_spec_test(f: impl Fn(F, F) -> F) { let cases = [ (F::ZERO, F::ZERO, F::ZERO), - (F::ONE, F::ONE, F::ONE), + (F::ZERO, F::NEG_ZERO, F::ZERO), (F::ZERO, F::ONE, F::ONE), - (F::ONE, F::ZERO, F::ONE), (F::ZERO, F::NEG_ONE, F::ZERO), + (F::ZERO, F::INFINITY, F::INFINITY), + (F::ZERO, F::NEG_INFINITY, F::ZERO), + (F::ZERO, F::NAN, F::ZERO), + (F::ZERO, F::NEG_NAN, F::ZERO), + (F::NEG_ZERO, F::ZERO, F::ZERO), + (F::NEG_ZERO, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_ZERO, F::ONE, F::ONE), + (F::NEG_ZERO, F::NEG_ONE, F::NEG_ZERO), + (F::NEG_ZERO, F::INFINITY, F::INFINITY), + (F::NEG_ZERO, F::NEG_INFINITY, F::NEG_ZERO), + (F::NEG_ZERO, F::NAN, F::NEG_ZERO), + (F::NEG_ZERO, F::NEG_NAN, F::NEG_ZERO), + (F::ONE, F::ZERO, F::ONE), + (F::ONE, F::NEG_ZERO, F::ONE), + (F::ONE, F::ONE, F::ONE), + (F::ONE, F::NEG_ONE, F::ONE), + (F::ONE, F::INFINITY, F::INFINITY), + (F::ONE, F::NEG_INFINITY, F::ONE), + (F::ONE, F::NAN, F::ONE), + (F::ONE, F::NEG_NAN, F::ONE), (F::NEG_ONE, F::ZERO, F::ZERO), + (F::NEG_ONE, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_ONE, F::ONE, F::ONE), + (F::NEG_ONE, F::NEG_ONE, F::NEG_ONE), + (F::NEG_ONE, F::INFINITY, F::INFINITY), + (F::NEG_ONE, F::NEG_INFINITY, F::NEG_ONE), + (F::NEG_ONE, F::NAN, F::NEG_ONE), + (F::NEG_ONE, F::NEG_NAN, F::NEG_ONE), (F::INFINITY, F::ZERO, F::INFINITY), + (F::INFINITY, F::NEG_ZERO, F::INFINITY), + (F::INFINITY, F::ONE, F::INFINITY), + (F::INFINITY, F::NEG_ONE, F::INFINITY), + (F::INFINITY, F::INFINITY, F::INFINITY), + (F::INFINITY, F::NEG_INFINITY, F::INFINITY), + (F::INFINITY, F::NAN, F::INFINITY), + (F::INFINITY, F::NEG_NAN, F::INFINITY), (F::NEG_INFINITY, F::ZERO, F::ZERO), + (F::NEG_INFINITY, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_INFINITY, F::ONE, F::ONE), + (F::NEG_INFINITY, F::NEG_ONE, F::NEG_ONE), + (F::NEG_INFINITY, F::INFINITY, F::INFINITY), + (F::NEG_INFINITY, F::NEG_INFINITY, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NAN, F::NEG_INFINITY), + (F::NEG_INFINITY, F::NEG_NAN, F::NEG_INFINITY), (F::NAN, F::ZERO, F::ZERO), - (F::ZERO, F::NAN, F::ZERO), + (F::NAN, F::NEG_ZERO, F::NEG_ZERO), + (F::NAN, F::ONE, F::ONE), + (F::NAN, F::NEG_ONE, F::NEG_ONE), + (F::NAN, F::INFINITY, F::INFINITY), + (F::NAN, F::NEG_INFINITY, F::NEG_INFINITY), (F::NAN, F::NAN, F::NAN), - (F::ZERO, F::NEG_ZERO, F::ZERO), - (F::NEG_ZERO, F::ZERO, F::ZERO), + (F::NEG_NAN, F::ZERO, F::ZERO), + (F::NEG_NAN, F::NEG_ZERO, F::NEG_ZERO), + (F::NEG_NAN, F::ONE, F::ONE), + (F::NEG_NAN, F::NEG_ONE, F::NEG_ONE), + (F::NEG_NAN, F::INFINITY, F::INFINITY), + (F::NEG_NAN, F::NEG_INFINITY, F::NEG_INFINITY), ]; - for (x, y, res) in cases { - let val = f(x, y); - assert_biteq!(val, res, "fmaximum_num({}, {})", Hexf(x), Hexf(y)); + for (x, y, expected) in cases { + let actual = f(x, y); + assert_biteq!(actual, expected, "fmaximum_num({}, {})", Hexf(x), Hexf(y)); } + + // Ordering between NaNs does not matter + assert!(f(F::NAN, F::NEG_NAN).is_nan()); + assert!(f(F::NEG_NAN, F::NAN).is_nan()); + assert!(f(F::NEG_NAN, F::NEG_NAN).is_nan()); } #[test] diff --git a/library/compiler-builtins/libm/src/math/generic/fmax.rs b/library/compiler-builtins/libm/src/math/generic/fmax.rs index 54207e4b3285f..b05804704d03e 100644 --- a/library/compiler-builtins/libm/src/math/generic/fmax.rs +++ b/library/compiler-builtins/libm/src/math/generic/fmax.rs @@ -19,6 +19,5 @@ use crate::support::Float; #[inline] pub fn fmax(x: F, y: F) -> F { let res = if x.is_nan() || x < y { y } else { x }; - // Canonicalize - res * F::ONE + res.canonicalize() } diff --git a/library/compiler-builtins/libm/src/math/generic/fmaximum.rs b/library/compiler-builtins/libm/src/math/generic/fmaximum.rs index 898828b80c7ff..55a031e18ee8d 100644 --- a/library/compiler-builtins/libm/src/math/generic/fmaximum.rs +++ b/library/compiler-builtins/libm/src/math/generic/fmaximum.rs @@ -4,8 +4,8 @@ //! Per the spec, returns the canonicalized result of: //! - `x` if `x > y` //! - `y` if `y > x` +//! - +0.0 if x and y are zero with opposite signs //! - qNaN if either operation is NaN -//! - Logic following +0.0 > -0.0 //! //! Excluded from our implementation is sNaN handling. @@ -23,6 +23,5 @@ pub fn fmaximum(x: F, y: F) -> F { y }; - // Canonicalize - res * F::ONE + res.canonicalize() } diff --git a/library/compiler-builtins/libm/src/math/generic/fmaximum_num.rs b/library/compiler-builtins/libm/src/math/generic/fmaximum_num.rs index 05df6cbd4643e..2dc60b2d237f5 100644 --- a/library/compiler-builtins/libm/src/math/generic/fmaximum_num.rs +++ b/library/compiler-builtins/libm/src/math/generic/fmaximum_num.rs @@ -4,10 +4,10 @@ //! Per the spec, returns: //! - `x` if `x > y` //! - `y` if `y > x` -//! - Non-NaN if one operand is NaN -//! - Logic following +0.0 > -0.0 +//! - +0.0 if x and y are zero with opposite signs //! - Either `x` or `y` if `x == y` and the signs are the same -//! - qNaN if either operand is a NaN +//! - Non-NaN if one operand is NaN +//! - qNaN if both operands are NaNx //! //! Excluded from our implementation is sNaN handling. @@ -15,12 +15,15 @@ use crate::support::Float; #[inline] pub fn fmaximum_num(x: F, y: F) -> F { - let res = if x.is_nan() || x < y || (x.biteq(F::NEG_ZERO) && y.is_sign_positive()) { + let res = if x > y || y.is_nan() { + x + } else if y > x || x.is_nan() { y - } else { + } else if x.is_sign_positive() { x + } else { + y }; - // Canonicalize - res * F::ONE + res.canonicalize() } diff --git a/library/compiler-builtins/libm/src/math/generic/fmin.rs b/library/compiler-builtins/libm/src/math/generic/fmin.rs index 0f86364d230b1..e2245bf9e137b 100644 --- a/library/compiler-builtins/libm/src/math/generic/fmin.rs +++ b/library/compiler-builtins/libm/src/math/generic/fmin.rs @@ -19,6 +19,5 @@ use crate::support::Float; #[inline] pub fn fmin(x: F, y: F) -> F { let res = if y.is_nan() || x < y { x } else { y }; - // Canonicalize - res * F::ONE + res.canonicalize() } diff --git a/library/compiler-builtins/libm/src/math/generic/fminimum.rs b/library/compiler-builtins/libm/src/math/generic/fminimum.rs index 8592ac5460ef0..aa68b1291d42b 100644 --- a/library/compiler-builtins/libm/src/math/generic/fminimum.rs +++ b/library/compiler-builtins/libm/src/math/generic/fminimum.rs @@ -4,8 +4,8 @@ //! Per the spec, returns the canonicalized result of: //! - `x` if `x < y` //! - `y` if `y < x` +//! - -0.0 if x and y are zero with opposite signs //! - qNaN if either operation is NaN -//! - Logic following +0.0 > -0.0 //! //! Excluded from our implementation is sNaN handling. @@ -23,6 +23,5 @@ pub fn fminimum(x: F, y: F) -> F { y }; - // Canonicalize - res * F::ONE + res.canonicalize() } diff --git a/library/compiler-builtins/libm/src/math/generic/fminimum_num.rs b/library/compiler-builtins/libm/src/math/generic/fminimum_num.rs index 6777bbf87721b..265bd4605ce39 100644 --- a/library/compiler-builtins/libm/src/math/generic/fminimum_num.rs +++ b/library/compiler-builtins/libm/src/math/generic/fminimum_num.rs @@ -4,10 +4,10 @@ //! Per the spec, returns: //! - `x` if `x < y` //! - `y` if `y < x` -//! - Non-NaN if one operand is NaN -//! - Logic following +0.0 > -0.0 +//! - -0.0 if x and y are zero with opposite signs //! - Either `x` or `y` if `x == y` and the signs are the same -//! - qNaN if either operand is a NaN +//! - Non-NaN if one operand is NaN +//! - qNaN if both operands are NaNx //! //! Excluded from our implementation is sNaN handling. @@ -15,12 +15,15 @@ use crate::support::Float; #[inline] pub fn fminimum_num(x: F, y: F) -> F { - let res = if y.is_nan() || x < y || (x.biteq(F::NEG_ZERO) && y.is_sign_positive()) { + let res = if x > y || x.is_nan() { + y + } else if y > x || y.is_nan() { x - } else { + } else if x.is_sign_positive() { y + } else { + x }; - // Canonicalize - res * F::ONE + res.canonicalize() } diff --git a/library/compiler-builtins/libm/src/math/support/float_traits.rs b/library/compiler-builtins/libm/src/math/support/float_traits.rs index dd9f46209c11d..c3e7eeec245c8 100644 --- a/library/compiler-builtins/libm/src/math/support/float_traits.rs +++ b/library/compiler-builtins/libm/src/math/support/float_traits.rs @@ -190,6 +190,15 @@ pub trait Float: Self::ONE.copysign(self) } } + + /// Make a best-effort attempt to canonicalize the number. Note that this is allowed + /// to be a nop and does not always quiet sNaNs. + fn canonicalize(self) -> Self { + // FIXME: LLVM often removes this. We should determine whether we can remove the operation, + // or switch to something based on `llvm.canonicalize` (which has crashes, + // ). + self * Self::ONE + } } /// Access the associated `Int` type from a float (helper to avoid ambiguous associated types). diff --git a/library/compiler-builtins/libm/src/math/support/macros.rs b/library/compiler-builtins/libm/src/math/support/macros.rs index 2b8fd580a50e5..550d2e92eb7c5 100644 --- a/library/compiler-builtins/libm/src/math/support/macros.rs +++ b/library/compiler-builtins/libm/src/math/support/macros.rs @@ -143,10 +143,12 @@ macro_rules! assert_biteq { let bits = $crate::support::Int::leading_zeros(l.to_bits() - l.to_bits()); assert!( $crate::support::Float::biteq(l, r), - "{}\nl: {l:?} ({lb:#0width$x})\nr: {r:?} ({rb:#0width$x})", + "{}\nl: {l:?} ({lb:#0width$x} {lh})\nr: {r:?} ({rb:#0width$x} {rh})", format_args!($($tt)*), lb = l.to_bits(), + lh = $crate::support::Hexf(l), rb = r.to_bits(), + rh = $crate::support::Hexf(r), width = ((bits / 4) + 2) as usize, ); diff --git a/library/compiler-builtins/rust-version b/library/compiler-builtins/rust-version index e05aaa0573cab..73183983599ff 100644 --- a/library/compiler-builtins/rust-version +++ b/library/compiler-builtins/rust-version @@ -1 +1 @@ -df8102fe5f24f28a918660b0cd918d7331c3896e +d087f112b7d1323446c7b39a8b616aee7fa56b3d diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 6819face4c219..73d9a8ee26d53 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -149,8 +149,32 @@ pub const fn forget(t: T) { /// Like [`forget`], but also accepts unsized values. /// -/// This function is just a shim intended to be removed when the `unsized_locals` feature gets -/// stabilized. +/// While Rust does not permit unsized locals since its removal in [#111942] it is +/// still possible to call functions with unsized values from a function argument +/// or in-place construction. +/// +/// ```rust +/// #![feature(unsized_fn_params, forget_unsized)] +/// #![allow(internal_features)] +/// +/// use std::mem::forget_unsized; +/// +/// pub fn in_place() { +/// forget_unsized(*Box::::from("str")); +/// } +/// +/// pub fn param(x: str) { +/// forget_unsized(x); +/// } +/// ``` +/// +/// This works because the compiler will alter these functions to pass the parameter +/// by reference instead. This trick is necessary to support `Box: FnOnce()`. +/// See [#68304] and [#71170] for more information. +/// +/// [#111942]: https://github.com/rust-lang/rust/issues/111942 +/// [#68304]: https://github.com/rust-lang/rust/issues/68304 +/// [#71170]: https://github.com/rust-lang/rust/pull/71170 #[inline] #[unstable(feature = "forget_unsized", issue = "none")] pub fn forget_unsized(t: T) { diff --git a/library/coretests/tests/floats/f128.rs b/library/coretests/tests/floats/f128.rs index 01770f119df10..cf78e8796a030 100644 --- a/library/coretests/tests/floats/f128.rs +++ b/library/coretests/tests/floats/f128.rs @@ -5,6 +5,8 @@ use core::ops::{Add, Div, Mul, Sub}; use std::f128::consts; use std::num::FpCategory as Fp; +use super::{assert_approx_eq, assert_biteq}; + // Note these tolerances make sense around zero, but not for more extreme exponents. /// Default tolerances. Works for values that should be near precise but not exact. Roughly @@ -53,34 +55,6 @@ fn test_num_f128() { // FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support // the intrinsics. -#[test] -#[cfg(any(miri, target_has_reliable_f128_math))] -fn test_min_nan() { - assert_biteq!(f128::NAN.min(2.0), 2.0); - assert_biteq!(2.0f128.min(f128::NAN), 2.0); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f128_math))] -fn test_max_nan() { - assert_biteq!(f128::NAN.max(2.0), 2.0); - assert_biteq!(2.0f128.max(f128::NAN), 2.0); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f128_math))] -fn test_minimum() { - assert!(f128::NAN.minimum(2.0).is_nan()); - assert!(2.0f128.minimum(f128::NAN).is_nan()); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f128_math))] -fn test_maximum() { - assert!(f128::NAN.maximum(2.0).is_nan()); - assert!(2.0f128.maximum(f128::NAN).is_nan()); -} - #[test] fn test_nan() { let nan: f128 = f128::NAN; @@ -232,98 +206,6 @@ fn test_classify() { assert_eq!(1e-4932f128.classify(), Fp::Subnormal); } -#[test] -#[cfg(target_has_reliable_f128_math)] -fn test_floor() { - assert_biteq!(1.0f128.floor(), 1.0f128); - assert_biteq!(1.3f128.floor(), 1.0f128); - assert_biteq!(1.5f128.floor(), 1.0f128); - assert_biteq!(1.7f128.floor(), 1.0f128); - assert_biteq!(0.0f128.floor(), 0.0f128); - assert_biteq!((-0.0f128).floor(), -0.0f128); - assert_biteq!((-1.0f128).floor(), -1.0f128); - assert_biteq!((-1.3f128).floor(), -2.0f128); - assert_biteq!((-1.5f128).floor(), -2.0f128); - assert_biteq!((-1.7f128).floor(), -2.0f128); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f128_math))] -fn test_ceil() { - assert_biteq!(1.0f128.ceil(), 1.0f128); - assert_biteq!(1.3f128.ceil(), 2.0f128); - assert_biteq!(1.5f128.ceil(), 2.0f128); - assert_biteq!(1.7f128.ceil(), 2.0f128); - assert_biteq!(0.0f128.ceil(), 0.0f128); - assert_biteq!((-0.0f128).ceil(), -0.0f128); - assert_biteq!((-1.0f128).ceil(), -1.0f128); - assert_biteq!((-1.3f128).ceil(), -1.0f128); - assert_biteq!((-1.5f128).ceil(), -1.0f128); - assert_biteq!((-1.7f128).ceil(), -1.0f128); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f128_math))] -fn test_round() { - assert_biteq!(2.5f128.round(), 3.0f128); - assert_biteq!(1.0f128.round(), 1.0f128); - assert_biteq!(1.3f128.round(), 1.0f128); - assert_biteq!(1.5f128.round(), 2.0f128); - assert_biteq!(1.7f128.round(), 2.0f128); - assert_biteq!(0.0f128.round(), 0.0f128); - assert_biteq!((-0.0f128).round(), -0.0f128); - assert_biteq!((-1.0f128).round(), -1.0f128); - assert_biteq!((-1.3f128).round(), -1.0f128); - assert_biteq!((-1.5f128).round(), -2.0f128); - assert_biteq!((-1.7f128).round(), -2.0f128); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f128_math))] -fn test_round_ties_even() { - assert_biteq!(2.5f128.round_ties_even(), 2.0f128); - assert_biteq!(1.0f128.round_ties_even(), 1.0f128); - assert_biteq!(1.3f128.round_ties_even(), 1.0f128); - assert_biteq!(1.5f128.round_ties_even(), 2.0f128); - assert_biteq!(1.7f128.round_ties_even(), 2.0f128); - assert_biteq!(0.0f128.round_ties_even(), 0.0f128); - assert_biteq!((-0.0f128).round_ties_even(), -0.0f128); - assert_biteq!((-1.0f128).round_ties_even(), -1.0f128); - assert_biteq!((-1.3f128).round_ties_even(), -1.0f128); - assert_biteq!((-1.5f128).round_ties_even(), -2.0f128); - assert_biteq!((-1.7f128).round_ties_even(), -2.0f128); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f128_math))] -fn test_trunc() { - assert_biteq!(1.0f128.trunc(), 1.0f128); - assert_biteq!(1.3f128.trunc(), 1.0f128); - assert_biteq!(1.5f128.trunc(), 1.0f128); - assert_biteq!(1.7f128.trunc(), 1.0f128); - assert_biteq!(0.0f128.trunc(), 0.0f128); - assert_biteq!((-0.0f128).trunc(), -0.0f128); - assert_biteq!((-1.0f128).trunc(), -1.0f128); - assert_biteq!((-1.3f128).trunc(), -1.0f128); - assert_biteq!((-1.5f128).trunc(), -1.0f128); - assert_biteq!((-1.7f128).trunc(), -1.0f128); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f128_math))] -fn test_fract() { - assert_biteq!(1.0f128.fract(), 0.0f128); - assert_biteq!(1.3f128.fract(), 0.300000000000000000000000000000000039f128); - assert_biteq!(1.5f128.fract(), 0.5f128); - assert_biteq!(1.7f128.fract(), 0.7f128); - assert_biteq!(0.0f128.fract(), 0.0f128); - assert_biteq!((-0.0f128).fract(), 0.0f128); - assert_biteq!((-1.0f128).fract(), 0.0f128); - assert_biteq!((-1.3f128).fract(), -0.300000000000000000000000000000000039f128); - assert_biteq!((-1.5f128).fract(), -0.5f128); - assert_biteq!((-1.7f128).fract(), -0.699999999999999999999999999999999961f128); -} - #[test] #[cfg(any(miri, target_has_reliable_f128_math))] fn test_abs() { diff --git a/library/coretests/tests/floats/f16.rs b/library/coretests/tests/floats/f16.rs index 4797573f7d0dd..9e91b654304b6 100644 --- a/library/coretests/tests/floats/f16.rs +++ b/library/coretests/tests/floats/f16.rs @@ -4,6 +4,8 @@ use std::f16::consts; use std::num::FpCategory as Fp; +use super::{assert_approx_eq, assert_biteq}; + /// Tolerance for results on the order of 10.0e-2 #[allow(unused)] const TOL_N2: f16 = 0.0001; @@ -49,34 +51,6 @@ fn test_num_f16() { // FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support // the intrinsics. -#[test] -#[cfg(any(miri, target_has_reliable_f16_math))] -fn test_min_nan() { - assert_biteq!(f16::NAN.min(2.0), 2.0); - assert_biteq!(2.0f16.min(f16::NAN), 2.0); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f16_math))] -fn test_max_nan() { - assert_biteq!(f16::NAN.max(2.0), 2.0); - assert_biteq!(2.0f16.max(f16::NAN), 2.0); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f16_math))] -fn test_minimum() { - assert!(f16::NAN.minimum(2.0).is_nan()); - assert!(2.0f16.minimum(f16::NAN).is_nan()); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f16_math))] -fn test_maximum() { - assert!(f16::NAN.maximum(2.0).is_nan()); - assert!(2.0f16.maximum(f16::NAN).is_nan()); -} - #[test] fn test_nan() { let nan: f16 = f16::NAN; @@ -228,98 +202,6 @@ fn test_classify() { assert_eq!(1e-5f16.classify(), Fp::Subnormal); } -#[test] -#[cfg(any(miri, target_has_reliable_f16_math))] -fn test_floor() { - assert_biteq!(1.0f16.floor(), 1.0f16); - assert_biteq!(1.3f16.floor(), 1.0f16); - assert_biteq!(1.5f16.floor(), 1.0f16); - assert_biteq!(1.7f16.floor(), 1.0f16); - assert_biteq!(0.0f16.floor(), 0.0f16); - assert_biteq!((-0.0f16).floor(), -0.0f16); - assert_biteq!((-1.0f16).floor(), -1.0f16); - assert_biteq!((-1.3f16).floor(), -2.0f16); - assert_biteq!((-1.5f16).floor(), -2.0f16); - assert_biteq!((-1.7f16).floor(), -2.0f16); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f16_math))] -fn test_ceil() { - assert_biteq!(1.0f16.ceil(), 1.0f16); - assert_biteq!(1.3f16.ceil(), 2.0f16); - assert_biteq!(1.5f16.ceil(), 2.0f16); - assert_biteq!(1.7f16.ceil(), 2.0f16); - assert_biteq!(0.0f16.ceil(), 0.0f16); - assert_biteq!((-0.0f16).ceil(), -0.0f16); - assert_biteq!((-1.0f16).ceil(), -1.0f16); - assert_biteq!((-1.3f16).ceil(), -1.0f16); - assert_biteq!((-1.5f16).ceil(), -1.0f16); - assert_biteq!((-1.7f16).ceil(), -1.0f16); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f16_math))] -fn test_round() { - assert_biteq!(2.5f16.round(), 3.0f16); - assert_biteq!(1.0f16.round(), 1.0f16); - assert_biteq!(1.3f16.round(), 1.0f16); - assert_biteq!(1.5f16.round(), 2.0f16); - assert_biteq!(1.7f16.round(), 2.0f16); - assert_biteq!(0.0f16.round(), 0.0f16); - assert_biteq!((-0.0f16).round(), -0.0f16); - assert_biteq!((-1.0f16).round(), -1.0f16); - assert_biteq!((-1.3f16).round(), -1.0f16); - assert_biteq!((-1.5f16).round(), -2.0f16); - assert_biteq!((-1.7f16).round(), -2.0f16); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f16_math))] -fn test_round_ties_even() { - assert_biteq!(2.5f16.round_ties_even(), 2.0f16); - assert_biteq!(1.0f16.round_ties_even(), 1.0f16); - assert_biteq!(1.3f16.round_ties_even(), 1.0f16); - assert_biteq!(1.5f16.round_ties_even(), 2.0f16); - assert_biteq!(1.7f16.round_ties_even(), 2.0f16); - assert_biteq!(0.0f16.round_ties_even(), 0.0f16); - assert_biteq!((-0.0f16).round_ties_even(), -0.0f16); - assert_biteq!((-1.0f16).round_ties_even(), -1.0f16); - assert_biteq!((-1.3f16).round_ties_even(), -1.0f16); - assert_biteq!((-1.5f16).round_ties_even(), -2.0f16); - assert_biteq!((-1.7f16).round_ties_even(), -2.0f16); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f16_math))] -fn test_trunc() { - assert_biteq!(1.0f16.trunc(), 1.0f16); - assert_biteq!(1.3f16.trunc(), 1.0f16); - assert_biteq!(1.5f16.trunc(), 1.0f16); - assert_biteq!(1.7f16.trunc(), 1.0f16); - assert_biteq!(0.0f16.trunc(), 0.0f16); - assert_biteq!((-0.0f16).trunc(), -0.0f16); - assert_biteq!((-1.0f16).trunc(), -1.0f16); - assert_biteq!((-1.3f16).trunc(), -1.0f16); - assert_biteq!((-1.5f16).trunc(), -1.0f16); - assert_biteq!((-1.7f16).trunc(), -1.0f16); -} - -#[test] -#[cfg(any(miri, target_has_reliable_f16_math))] -fn test_fract() { - assert_biteq!(1.0f16.fract(), 0.0f16); - assert_biteq!(1.3f16.fract(), 0.2998f16); - assert_biteq!(1.5f16.fract(), 0.5f16); - assert_biteq!(1.7f16.fract(), 0.7f16); - assert_biteq!(0.0f16.fract(), 0.0f16); - assert_biteq!((-0.0f16).fract(), 0.0f16); - assert_biteq!((-1.0f16).fract(), 0.0f16); - assert_biteq!((-1.3f16).fract(), -0.2998f16); - assert_biteq!((-1.5f16).fract(), -0.5f16); - assert_biteq!((-1.7f16).fract(), -0.7f16); -} - #[test] #[cfg(any(miri, target_has_reliable_f16_math))] fn test_abs() { diff --git a/library/coretests/tests/floats/f32.rs b/library/coretests/tests/floats/f32.rs index 98e9695d09036..d2724d12e3927 100644 --- a/library/coretests/tests/floats/f32.rs +++ b/library/coretests/tests/floats/f32.rs @@ -2,6 +2,8 @@ use core::f32; use core::f32::consts; use core::num::FpCategory as Fp; +use super::{assert_approx_eq, assert_biteq}; + /// Smallest number const TINY_BITS: u32 = 0x1; @@ -33,30 +35,6 @@ fn test_num_f32() { super::test_num(10f32, 2f32); } -#[test] -fn test_min_nan() { - assert_biteq!(f32::NAN.min(2.0), 2.0); - assert_biteq!(2.0f32.min(f32::NAN), 2.0); -} - -#[test] -fn test_max_nan() { - assert_biteq!(f32::NAN.max(2.0), 2.0); - assert_biteq!(2.0f32.max(f32::NAN), 2.0); -} - -#[test] -fn test_minimum() { - assert!(f32::NAN.minimum(2.0).is_nan()); - assert!(2.0f32.minimum(f32::NAN).is_nan()); -} - -#[test] -fn test_maximum() { - assert!(f32::NAN.maximum(2.0).is_nan()); - assert!(2.0f32.maximum(f32::NAN).is_nan()); -} - #[test] fn test_nan() { let nan: f32 = f32::NAN; @@ -208,92 +186,6 @@ fn test_classify() { assert_eq!(1e-38f32.classify(), Fp::Subnormal); } -#[test] -fn test_floor() { - assert_biteq!(f32::math::floor(1.0f32), 1.0f32); - assert_biteq!(f32::math::floor(1.3f32), 1.0f32); - assert_biteq!(f32::math::floor(1.5f32), 1.0f32); - assert_biteq!(f32::math::floor(1.7f32), 1.0f32); - assert_biteq!(f32::math::floor(0.0f32), 0.0f32); - assert_biteq!(f32::math::floor(-0.0f32), -0.0f32); - assert_biteq!(f32::math::floor(-1.0f32), -1.0f32); - assert_biteq!(f32::math::floor(-1.3f32), -2.0f32); - assert_biteq!(f32::math::floor(-1.5f32), -2.0f32); - assert_biteq!(f32::math::floor(-1.7f32), -2.0f32); -} - -#[test] -fn test_ceil() { - assert_biteq!(f32::math::ceil(1.0f32), 1.0f32); - assert_biteq!(f32::math::ceil(1.3f32), 2.0f32); - assert_biteq!(f32::math::ceil(1.5f32), 2.0f32); - assert_biteq!(f32::math::ceil(1.7f32), 2.0f32); - assert_biteq!(f32::math::ceil(0.0f32), 0.0f32); - assert_biteq!(f32::math::ceil(-0.0f32), -0.0f32); - assert_biteq!(f32::math::ceil(-1.0f32), -1.0f32); - assert_biteq!(f32::math::ceil(-1.3f32), -1.0f32); - assert_biteq!(f32::math::ceil(-1.5f32), -1.0f32); - assert_biteq!(f32::math::ceil(-1.7f32), -1.0f32); -} - -#[test] -fn test_round() { - assert_biteq!(f32::math::round(2.5f32), 3.0f32); - assert_biteq!(f32::math::round(1.0f32), 1.0f32); - assert_biteq!(f32::math::round(1.3f32), 1.0f32); - assert_biteq!(f32::math::round(1.5f32), 2.0f32); - assert_biteq!(f32::math::round(1.7f32), 2.0f32); - assert_biteq!(f32::math::round(0.0f32), 0.0f32); - assert_biteq!(f32::math::round(-0.0f32), -0.0f32); - assert_biteq!(f32::math::round(-1.0f32), -1.0f32); - assert_biteq!(f32::math::round(-1.3f32), -1.0f32); - assert_biteq!(f32::math::round(-1.5f32), -2.0f32); - assert_biteq!(f32::math::round(-1.7f32), -2.0f32); -} - -#[test] -fn test_round_ties_even() { - assert_biteq!(f32::math::round_ties_even(2.5f32), 2.0f32); - assert_biteq!(f32::math::round_ties_even(1.0f32), 1.0f32); - assert_biteq!(f32::math::round_ties_even(1.3f32), 1.0f32); - assert_biteq!(f32::math::round_ties_even(1.5f32), 2.0f32); - assert_biteq!(f32::math::round_ties_even(1.7f32), 2.0f32); - assert_biteq!(f32::math::round_ties_even(0.0f32), 0.0f32); - assert_biteq!(f32::math::round_ties_even(-0.0f32), -0.0f32); - assert_biteq!(f32::math::round_ties_even(-1.0f32), -1.0f32); - assert_biteq!(f32::math::round_ties_even(-1.3f32), -1.0f32); - assert_biteq!(f32::math::round_ties_even(-1.5f32), -2.0f32); - assert_biteq!(f32::math::round_ties_even(-1.7f32), -2.0f32); -} - -#[test] -fn test_trunc() { - assert_biteq!(f32::math::trunc(1.0f32), 1.0f32); - assert_biteq!(f32::math::trunc(1.3f32), 1.0f32); - assert_biteq!(f32::math::trunc(1.5f32), 1.0f32); - assert_biteq!(f32::math::trunc(1.7f32), 1.0f32); - assert_biteq!(f32::math::trunc(0.0f32), 0.0f32); - assert_biteq!(f32::math::trunc(-0.0f32), -0.0f32); - assert_biteq!(f32::math::trunc(-1.0f32), -1.0f32); - assert_biteq!(f32::math::trunc(-1.3f32), -1.0f32); - assert_biteq!(f32::math::trunc(-1.5f32), -1.0f32); - assert_biteq!(f32::math::trunc(-1.7f32), -1.0f32); -} - -#[test] -fn test_fract() { - assert_biteq!(f32::math::fract(1.0f32), 0.0f32); - assert_biteq!(f32::math::fract(1.3f32), 0.29999995f32); - assert_biteq!(f32::math::fract(1.5f32), 0.5f32); - assert_biteq!(f32::math::fract(1.7f32), 0.70000005f32); - assert_biteq!(f32::math::fract(0.0f32), 0.0f32); - assert_biteq!(f32::math::fract(-0.0f32), 0.0f32); - assert_biteq!(f32::math::fract(-1.0f32), 0.0f32); - assert_biteq!(f32::math::fract(-1.3f32), -0.29999995f32); - assert_biteq!(f32::math::fract(-1.5f32), -0.5f32); - assert_biteq!(f32::math::fract(-1.7f32), -0.70000005f32); -} - #[test] fn test_abs() { assert_biteq!(f32::INFINITY.abs(), f32::INFINITY); diff --git a/library/coretests/tests/floats/f64.rs b/library/coretests/tests/floats/f64.rs index dd5b67c251dc0..b2b2393a5279c 100644 --- a/library/coretests/tests/floats/f64.rs +++ b/library/coretests/tests/floats/f64.rs @@ -2,6 +2,8 @@ use core::f64; use core::f64::consts; use core::num::FpCategory as Fp; +use super::{assert_approx_eq, assert_biteq}; + /// Smallest number const TINY_BITS: u64 = 0x1; @@ -28,18 +30,6 @@ fn test_num_f64() { super::test_num(10f64, 2f64); } -#[test] -fn test_min_nan() { - assert_biteq!(f64::NAN.min(2.0), 2.0); - assert_biteq!(2.0f64.min(f64::NAN), 2.0); -} - -#[test] -fn test_max_nan() { - assert_biteq!(f64::NAN.max(2.0), 2.0); - assert_biteq!(2.0f64.max(f64::NAN), 2.0); -} - #[test] fn test_nan() { let nan: f64 = f64::NAN; @@ -190,92 +180,6 @@ fn test_classify() { assert_eq!(1e-308f64.classify(), Fp::Subnormal); } -#[test] -fn test_floor() { - assert_biteq!(f64::math::floor(1.0f64), 1.0f64); - assert_biteq!(f64::math::floor(1.3f64), 1.0f64); - assert_biteq!(f64::math::floor(1.5f64), 1.0f64); - assert_biteq!(f64::math::floor(1.7f64), 1.0f64); - assert_biteq!(f64::math::floor(0.0f64), 0.0f64); - assert_biteq!(f64::math::floor(-0.0f64), -0.0f64); - assert_biteq!(f64::math::floor(-1.0f64), -1.0f64); - assert_biteq!(f64::math::floor(-1.3f64), -2.0f64); - assert_biteq!(f64::math::floor(-1.5f64), -2.0f64); - assert_biteq!(f64::math::floor(-1.7f64), -2.0f64); -} - -#[test] -fn test_ceil() { - assert_biteq!(f64::math::ceil(1.0f64), 1.0f64); - assert_biteq!(f64::math::ceil(1.3f64), 2.0f64); - assert_biteq!(f64::math::ceil(1.5f64), 2.0f64); - assert_biteq!(f64::math::ceil(1.7f64), 2.0f64); - assert_biteq!(f64::math::ceil(0.0f64), 0.0f64); - assert_biteq!(f64::math::ceil(-0.0f64), -0.0f64); - assert_biteq!(f64::math::ceil(-1.0f64), -1.0f64); - assert_biteq!(f64::math::ceil(-1.3f64), -1.0f64); - assert_biteq!(f64::math::ceil(-1.5f64), -1.0f64); - assert_biteq!(f64::math::ceil(-1.7f64), -1.0f64); -} - -#[test] -fn test_round() { - assert_biteq!(f64::math::round(2.5f64), 3.0f64); - assert_biteq!(f64::math::round(1.0f64), 1.0f64); - assert_biteq!(f64::math::round(1.3f64), 1.0f64); - assert_biteq!(f64::math::round(1.5f64), 2.0f64); - assert_biteq!(f64::math::round(1.7f64), 2.0f64); - assert_biteq!(f64::math::round(0.0f64), 0.0f64); - assert_biteq!(f64::math::round(-0.0f64), -0.0f64); - assert_biteq!(f64::math::round(-1.0f64), -1.0f64); - assert_biteq!(f64::math::round(-1.3f64), -1.0f64); - assert_biteq!(f64::math::round(-1.5f64), -2.0f64); - assert_biteq!(f64::math::round(-1.7f64), -2.0f64); -} - -#[test] -fn test_round_ties_even() { - assert_biteq!(f64::math::round_ties_even(2.5f64), 2.0f64); - assert_biteq!(f64::math::round_ties_even(1.0f64), 1.0f64); - assert_biteq!(f64::math::round_ties_even(1.3f64), 1.0f64); - assert_biteq!(f64::math::round_ties_even(1.5f64), 2.0f64); - assert_biteq!(f64::math::round_ties_even(1.7f64), 2.0f64); - assert_biteq!(f64::math::round_ties_even(0.0f64), 0.0f64); - assert_biteq!(f64::math::round_ties_even(-0.0f64), -0.0f64); - assert_biteq!(f64::math::round_ties_even(-1.0f64), -1.0f64); - assert_biteq!(f64::math::round_ties_even(-1.3f64), -1.0f64); - assert_biteq!(f64::math::round_ties_even(-1.5f64), -2.0f64); - assert_biteq!(f64::math::round_ties_even(-1.7f64), -2.0f64); -} - -#[test] -fn test_trunc() { - assert_biteq!(f64::math::trunc(1.0f64), 1.0f64); - assert_biteq!(f64::math::trunc(1.3f64), 1.0f64); - assert_biteq!(f64::math::trunc(1.5f64), 1.0f64); - assert_biteq!(f64::math::trunc(1.7f64), 1.0f64); - assert_biteq!(f64::math::trunc(0.0f64), 0.0f64); - assert_biteq!(f64::math::trunc(-0.0f64), -0.0f64); - assert_biteq!(f64::math::trunc(-1.0f64), -1.0f64); - assert_biteq!(f64::math::trunc(-1.3f64), -1.0f64); - assert_biteq!(f64::math::trunc(-1.5f64), -1.0f64); - assert_biteq!(f64::math::trunc(-1.7f64), -1.0f64); -} - -#[test] -fn test_fract() { - assert_biteq!(f64::math::fract(1.0f64), 0.0f64); - assert_biteq!(f64::math::fract(1.3f64), 0.30000000000000004f64); - assert_biteq!(f64::math::fract(1.5f64), 0.5f64); - assert_biteq!(f64::math::fract(1.7f64), 0.7f64); - assert_biteq!(f64::math::fract(0.0f64), 0.0f64); - assert_biteq!(f64::math::fract(-0.0f64), 0.0f64); - assert_biteq!(f64::math::fract(-1.0f64), 0.0f64); - assert_biteq!(f64::math::fract(-1.3f64), -0.30000000000000004f64); - assert_biteq!(f64::math::fract(-1.5f64), -0.5f64); - assert_biteq!(f64::math::fract(-1.7f64), -0.69999999999999996f64); -} - #[test] fn test_abs() { assert_biteq!(f64::INFINITY.abs(), f64::INFINITY); diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs index f9b6c85f87105..6b4f586fa9b6b 100644 --- a/library/coretests/tests/floats/mod.rs +++ b/library/coretests/tests/floats/mod.rs @@ -1,9 +1,34 @@ use std::fmt; use std::ops::{Add, Div, Mul, Rem, Sub}; -/// Verify that floats are within a tolerance of each other, 1.0e-6 by default. -macro_rules! assert_approx_eq { - ($a:expr, $b:expr) => {{ assert_approx_eq!($a, $b, 1.0e-6) }}; +/// Set the default tolerance for float comparison based on the type. +trait Approx { + const LIM: Self; +} + +impl Approx for f16 { + const LIM: Self = 1e-3; +} +impl Approx for f32 { + const LIM: Self = 1e-6; +} +impl Approx for f64 { + const LIM: Self = 1e-6; +} +impl Approx for f128 { + const LIM: Self = 1e-9; +} + +/// Determine the tolerance for values of the argument type. +const fn lim_for_ty(_x: T) -> T { + T::LIM +} + +// We have runtime ("rt") and const versions of these macros. + +/// Verify that floats are within a tolerance of each other. +macro_rules! assert_approx_eq_rt { + ($a:expr, $b:expr) => {{ assert_approx_eq_rt!($a, $b, $crate::floats::lim_for_ty($a)) }}; ($a:expr, $b:expr, $lim:expr) => {{ let (a, b) = (&$a, &$b); let diff = (*a - *b).abs(); @@ -14,10 +39,18 @@ macro_rules! assert_approx_eq { ); }}; } +macro_rules! assert_approx_eq_const { + ($a:expr, $b:expr) => {{ assert_approx_eq_const!($a, $b, $crate::floats::lim_for_ty($a)) }}; + ($a:expr, $b:expr, $lim:expr) => {{ + let (a, b) = (&$a, &$b); + let diff = (*a - *b).abs(); + assert!(diff <= $lim); + }}; +} /// Verify that floats have the same bitwise representation. Used to avoid the default `0.0 == -0.0` /// behavior, as well as to ensure exact NaN bitpatterns. -macro_rules! assert_biteq { +macro_rules! assert_biteq_rt { (@inner $left:expr, $right:expr, $msg_sep:literal, $($tt:tt)*) => {{ let l = $left; let r = $right; @@ -41,32 +74,50 @@ macro_rules! assert_biteq { if !l.is_nan() && !r.is_nan() { // Also check that standard equality holds, since most tests use `assert_biteq` rather // than `assert_eq`. - assert_eq!(l, r) + assert_eq!(l, r); } }}; ($left:expr, $right:expr , $($tt:tt)*) => { - assert_biteq!(@inner $left, $right, "\n", $($tt)*) + assert_biteq_rt!(@inner $left, $right, "\n", $($tt)*) }; ($left:expr, $right:expr $(,)?) => { - assert_biteq!(@inner $left, $right, "", "") + assert_biteq_rt!(@inner $left, $right, "", "") }; } +macro_rules! assert_biteq_const { + (@inner $left:expr, $right:expr, $msg_sep:literal, $($tt:tt)*) => {{ + let l = $left; + let r = $right; -mod const_asserts { - // Shadow some assert implementations that would otherwise not compile in a const-context. - // Every macro added here also needs to be added in the `float_test!` macro below. - macro_rules! assert_eq { - ($left:expr, $right:expr $(,)?) => { - std::assert!($left == $right) - }; - ($left:expr, $right:expr, $($arg:tt)+) => { - std::assert!($left == $right, $($arg)+) - }; - } + // Hack to coerce left and right to the same type + let mut _eq_ty = l; + _eq_ty = r; + + assert!(l.to_bits() == r.to_bits()); - pub(crate) use assert_eq; + if !l.is_nan() && !r.is_nan() { + // Also check that standard equality holds, since most tests use `assert_biteq` rather + // than `assert_eq`. + assert!(l == r); + } + }}; + ($left:expr, $right:expr , $($tt:tt)*) => { + assert_biteq_const!(@inner $left, $right, "\n", $($tt)*) + }; + ($left:expr, $right:expr $(,)?) => { + assert_biteq_const!(@inner $left, $right, "", "") + }; } +// Use the runtime version by default. +// This way, they can be shadowed by the const versions. +pub(crate) use {assert_approx_eq_rt as assert_approx_eq, assert_biteq_rt as assert_biteq}; + +// Also make the const version available for re-exports. +#[rustfmt::skip] +pub(crate) use assert_biteq_const; +pub(crate) use assert_approx_eq_const; + /// Generate float tests for all our float types, for compile-time and run-time behavior. /// /// By default all tests run for all float types. Configuration can be applied via `attrs`. @@ -84,6 +135,7 @@ mod const_asserts { /// /* write tests here, using `Float` as the type */ /// } /// } +/// ``` macro_rules! float_test { ( name: $name:ident, @@ -101,6 +153,8 @@ macro_rules! float_test { test<$fty:ident> $test:block ) => { mod $name { + use super::*; + #[test] $( $( #[$f16_meta] )+ )? fn test_f16() { @@ -131,7 +185,14 @@ macro_rules! float_test { $( $( #[$const_meta] )+ )? mod const_ { - use $crate::floats::const_asserts::assert_eq; + #[allow(unused)] + use super::Approx; + // Shadow the runtime versions of the macro with const-compatible versions. + #[allow(unused)] + use $crate::floats::{ + assert_approx_eq_const as assert_approx_eq, + assert_biteq_const as assert_biteq, + }; #[test] $( $( #[$f16_const_meta] )+ )? @@ -196,29 +257,25 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((0.0 as Float).min(0.0), 0.0); - assert!((0.0 as Float).min(0.0).is_sign_positive()); - assert_eq!((-0.0 as Float).min(-0.0), -0.0); - assert!((-0.0 as Float).min(-0.0).is_sign_negative()); - assert_eq!((9.0 as Float).min(9.0), 9.0); - assert_eq!((-9.0 as Float).min(0.0), -9.0); - assert_eq!((0.0 as Float).min(9.0), 0.0); - assert!((0.0 as Float).min(9.0).is_sign_positive()); - assert_eq!((-0.0 as Float).min(9.0), -0.0); - assert!((-0.0 as Float).min(9.0).is_sign_negative()); - assert_eq!((-0.0 as Float).min(-9.0), -9.0); - assert_eq!(Float::INFINITY.min(9.0), 9.0); - assert_eq!((9.0 as Float).min(Float::INFINITY), 9.0); - assert_eq!(Float::INFINITY.min(-9.0), -9.0); - assert_eq!((-9.0 as Float).min(Float::INFINITY), -9.0); - assert_eq!(Float::NEG_INFINITY.min(9.0), Float::NEG_INFINITY); - assert_eq!((9.0 as Float).min(Float::NEG_INFINITY), Float::NEG_INFINITY); - assert_eq!(Float::NEG_INFINITY.min(-9.0), Float::NEG_INFINITY); - assert_eq!((-9.0 as Float).min(Float::NEG_INFINITY), Float::NEG_INFINITY); - assert_eq!(Float::NAN.min(9.0), 9.0); - assert_eq!(Float::NAN.min(-9.0), -9.0); - assert_eq!((9.0 as Float).min(Float::NAN), 9.0); - assert_eq!((-9.0 as Float).min(Float::NAN), -9.0); + assert_biteq!((0.0 as Float).min(0.0), 0.0); + assert_biteq!((-0.0 as Float).min(-0.0), -0.0); + assert_biteq!((9.0 as Float).min(9.0), 9.0); + assert_biteq!((-9.0 as Float).min(0.0), -9.0); + assert_biteq!((0.0 as Float).min(9.0), 0.0); + assert_biteq!((-0.0 as Float).min(9.0), -0.0); + assert_biteq!((-0.0 as Float).min(-9.0), -9.0); + assert_biteq!(Float::INFINITY.min(9.0), 9.0); + assert_biteq!((9.0 as Float).min(Float::INFINITY), 9.0); + assert_biteq!(Float::INFINITY.min(-9.0), -9.0); + assert_biteq!((-9.0 as Float).min(Float::INFINITY), -9.0); + assert_biteq!(Float::NEG_INFINITY.min(9.0), Float::NEG_INFINITY); + assert_biteq!((9.0 as Float).min(Float::NEG_INFINITY), Float::NEG_INFINITY); + assert_biteq!(Float::NEG_INFINITY.min(-9.0), Float::NEG_INFINITY); + assert_biteq!((-9.0 as Float).min(Float::NEG_INFINITY), Float::NEG_INFINITY); + assert_biteq!(Float::NAN.min(9.0), 9.0); + assert_biteq!(Float::NAN.min(-9.0), -9.0); + assert_biteq!((9.0 as Float).min(Float::NAN), 9.0); + assert_biteq!((-9.0 as Float).min(Float::NAN), -9.0); assert!(Float::NAN.min(Float::NAN).is_nan()); } } @@ -230,32 +287,26 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((0.0 as Float).max(0.0), 0.0); - assert!((0.0 as Float).max(0.0).is_sign_positive()); - assert_eq!((-0.0 as Float).max(-0.0), -0.0); - assert!((-0.0 as Float).max(-0.0).is_sign_negative()); - assert_eq!((9.0 as Float).max(9.0), 9.0); - assert_eq!((-9.0 as Float).max(0.0), 0.0); - assert!((-9.0 as Float).max(0.0).is_sign_positive()); - assert_eq!((-9.0 as Float).max(-0.0), -0.0); - assert!((-9.0 as Float).max(-0.0).is_sign_negative()); - assert_eq!((0.0 as Float).max(9.0), 9.0); - assert_eq!((0.0 as Float).max(-9.0), 0.0); - assert!((0.0 as Float).max(-9.0).is_sign_positive()); - assert_eq!((-0.0 as Float).max(-9.0), -0.0); - assert!((-0.0 as Float).max(-9.0).is_sign_negative()); - assert_eq!(Float::INFINITY.max(9.0), Float::INFINITY); - assert_eq!((9.0 as Float).max(Float::INFINITY), Float::INFINITY); - assert_eq!(Float::INFINITY.max(-9.0), Float::INFINITY); - assert_eq!((-9.0 as Float).max(Float::INFINITY), Float::INFINITY); - assert_eq!(Float::NEG_INFINITY.max(9.0), 9.0); - assert_eq!((9.0 as Float).max(Float::NEG_INFINITY), 9.0); - assert_eq!(Float::NEG_INFINITY.max(-9.0), -9.0); - assert_eq!((-9.0 as Float).max(Float::NEG_INFINITY), -9.0); - assert_eq!(Float::NAN.max(9.0), 9.0); - assert_eq!(Float::NAN.max(-9.0), -9.0); - assert_eq!((9.0 as Float).max(Float::NAN), 9.0); - assert_eq!((-9.0 as Float).max(Float::NAN), -9.0); + assert_biteq!((0.0 as Float).max(0.0), 0.0); + assert_biteq!((-0.0 as Float).max(-0.0), -0.0); + assert_biteq!((9.0 as Float).max(9.0), 9.0); + assert_biteq!((-9.0 as Float).max(0.0), 0.0); + assert_biteq!((-9.0 as Float).max(-0.0), -0.0); + assert_biteq!((0.0 as Float).max(9.0), 9.0); + assert_biteq!((0.0 as Float).max(-9.0), 0.0); + assert_biteq!((-0.0 as Float).max(-9.0), -0.0); + assert_biteq!(Float::INFINITY.max(9.0), Float::INFINITY); + assert_biteq!((9.0 as Float).max(Float::INFINITY), Float::INFINITY); + assert_biteq!(Float::INFINITY.max(-9.0), Float::INFINITY); + assert_biteq!((-9.0 as Float).max(Float::INFINITY), Float::INFINITY); + assert_biteq!(Float::NEG_INFINITY.max(9.0), 9.0); + assert_biteq!((9.0 as Float).max(Float::NEG_INFINITY), 9.0); + assert_biteq!(Float::NEG_INFINITY.max(-9.0), -9.0); + assert_biteq!((-9.0 as Float).max(Float::NEG_INFINITY), -9.0); + assert_biteq!(Float::NAN.max(9.0), 9.0); + assert_biteq!(Float::NAN.max(-9.0), -9.0); + assert_biteq!((9.0 as Float).max(Float::NAN), 9.0); + assert_biteq!((-9.0 as Float).max(Float::NAN), -9.0); assert!(Float::NAN.max(Float::NAN).is_nan()); } } @@ -267,27 +318,22 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((0.0 as Float).minimum(0.0), 0.0); - assert!((0.0 as Float).minimum(0.0).is_sign_positive()); - assert_eq!((-0.0 as Float).minimum(0.0), -0.0); - assert!((-0.0 as Float).minimum(0.0).is_sign_negative()); - assert_eq!((-0.0 as Float).minimum(-0.0), -0.0); - assert!((-0.0 as Float).minimum(-0.0).is_sign_negative()); - assert_eq!((9.0 as Float).minimum(9.0), 9.0); - assert_eq!((-9.0 as Float).minimum(0.0), -9.0); - assert_eq!((0.0 as Float).minimum(9.0), 0.0); - assert!((0.0 as Float).minimum(9.0).is_sign_positive()); - assert_eq!((-0.0 as Float).minimum(9.0), -0.0); - assert!((-0.0 as Float).minimum(9.0).is_sign_negative()); - assert_eq!((-0.0 as Float).minimum(-9.0), -9.0); - assert_eq!(Float::INFINITY.minimum(9.0), 9.0); - assert_eq!((9.0 as Float).minimum(Float::INFINITY), 9.0); - assert_eq!(Float::INFINITY.minimum(-9.0), -9.0); - assert_eq!((-9.0 as Float).minimum(Float::INFINITY), -9.0); - assert_eq!(Float::NEG_INFINITY.minimum(9.0), Float::NEG_INFINITY); - assert_eq!((9.0 as Float).minimum(Float::NEG_INFINITY), Float::NEG_INFINITY); - assert_eq!(Float::NEG_INFINITY.minimum(-9.0), Float::NEG_INFINITY); - assert_eq!((-9.0 as Float).minimum(Float::NEG_INFINITY), Float::NEG_INFINITY); + assert_biteq!((0.0 as Float).minimum(0.0), 0.0); + assert_biteq!((-0.0 as Float).minimum(0.0), -0.0); + assert_biteq!((-0.0 as Float).minimum(-0.0), -0.0); + assert_biteq!((9.0 as Float).minimum(9.0), 9.0); + assert_biteq!((-9.0 as Float).minimum(0.0), -9.0); + assert_biteq!((0.0 as Float).minimum(9.0), 0.0); + assert_biteq!((-0.0 as Float).minimum(9.0), -0.0); + assert_biteq!((-0.0 as Float).minimum(-9.0), -9.0); + assert_biteq!(Float::INFINITY.minimum(9.0), 9.0); + assert_biteq!((9.0 as Float).minimum(Float::INFINITY), 9.0); + assert_biteq!(Float::INFINITY.minimum(-9.0), -9.0); + assert_biteq!((-9.0 as Float).minimum(Float::INFINITY), -9.0); + assert_biteq!(Float::NEG_INFINITY.minimum(9.0), Float::NEG_INFINITY); + assert_biteq!((9.0 as Float).minimum(Float::NEG_INFINITY), Float::NEG_INFINITY); + assert_biteq!(Float::NEG_INFINITY.minimum(-9.0), Float::NEG_INFINITY); + assert_biteq!((-9.0 as Float).minimum(Float::NEG_INFINITY), Float::NEG_INFINITY); assert!(Float::NAN.minimum(9.0).is_nan()); assert!(Float::NAN.minimum(-9.0).is_nan()); assert!((9.0 as Float).minimum(Float::NAN).is_nan()); @@ -303,30 +349,23 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((0.0 as Float).maximum(0.0), 0.0); - assert!((0.0 as Float).maximum(0.0).is_sign_positive()); - assert_eq!((-0.0 as Float).maximum(0.0), 0.0); - assert!((-0.0 as Float).maximum(0.0).is_sign_positive()); - assert_eq!((-0.0 as Float).maximum(-0.0), -0.0); - assert!((-0.0 as Float).maximum(-0.0).is_sign_negative()); - assert_eq!((9.0 as Float).maximum(9.0), 9.0); - assert_eq!((-9.0 as Float).maximum(0.0), 0.0); - assert!((-9.0 as Float).maximum(0.0).is_sign_positive()); - assert_eq!((-9.0 as Float).maximum(-0.0), -0.0); - assert!((-9.0 as Float).maximum(-0.0).is_sign_negative()); - assert_eq!((0.0 as Float).maximum(9.0), 9.0); - assert_eq!((0.0 as Float).maximum(-9.0), 0.0); - assert!((0.0 as Float).maximum(-9.0).is_sign_positive()); - assert_eq!((-0.0 as Float).maximum(-9.0), -0.0); - assert!((-0.0 as Float).maximum(-9.0).is_sign_negative()); - assert_eq!(Float::INFINITY.maximum(9.0), Float::INFINITY); - assert_eq!((9.0 as Float).maximum(Float::INFINITY), Float::INFINITY); - assert_eq!(Float::INFINITY.maximum(-9.0), Float::INFINITY); - assert_eq!((-9.0 as Float).maximum(Float::INFINITY), Float::INFINITY); - assert_eq!(Float::NEG_INFINITY.maximum(9.0), 9.0); - assert_eq!((9.0 as Float).maximum(Float::NEG_INFINITY), 9.0); - assert_eq!(Float::NEG_INFINITY.maximum(-9.0), -9.0); - assert_eq!((-9.0 as Float).maximum(Float::NEG_INFINITY), -9.0); + assert_biteq!((0.0 as Float).maximum(0.0), 0.0); + assert_biteq!((-0.0 as Float).maximum(0.0), 0.0); + assert_biteq!((-0.0 as Float).maximum(-0.0), -0.0); + assert_biteq!((9.0 as Float).maximum(9.0), 9.0); + assert_biteq!((-9.0 as Float).maximum(0.0), 0.0); + assert_biteq!((-9.0 as Float).maximum(-0.0), -0.0); + assert_biteq!((0.0 as Float).maximum(9.0), 9.0); + assert_biteq!((0.0 as Float).maximum(-9.0), 0.0); + assert_biteq!((-0.0 as Float).maximum(-9.0), -0.0); + assert_biteq!(Float::INFINITY.maximum(9.0), Float::INFINITY); + assert_biteq!((9.0 as Float).maximum(Float::INFINITY), Float::INFINITY); + assert_biteq!(Float::INFINITY.maximum(-9.0), Float::INFINITY); + assert_biteq!((-9.0 as Float).maximum(Float::INFINITY), Float::INFINITY); + assert_biteq!(Float::NEG_INFINITY.maximum(9.0), 9.0); + assert_biteq!((9.0 as Float).maximum(Float::NEG_INFINITY), 9.0); + assert_biteq!(Float::NEG_INFINITY.maximum(-9.0), -9.0); + assert_biteq!((-9.0 as Float).maximum(Float::NEG_INFINITY), -9.0); assert!(Float::NAN.maximum(9.0).is_nan()); assert!(Float::NAN.maximum(-9.0).is_nan()); assert!((9.0 as Float).maximum(Float::NAN).is_nan()); @@ -342,41 +381,43 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((0.5 as Float).midpoint(0.5), 0.5); - assert_eq!((0.5 as Float).midpoint(2.5), 1.5); - assert_eq!((3.0 as Float).midpoint(4.0), 3.5); - assert_eq!((-3.0 as Float).midpoint(4.0), 0.5); - assert_eq!((3.0 as Float).midpoint(-4.0), -0.5); - assert_eq!((-3.0 as Float).midpoint(-4.0), -3.5); - assert_eq!((0.0 as Float).midpoint(0.0), 0.0); - assert_eq!((-0.0 as Float).midpoint(-0.0), -0.0); - assert_eq!((-5.0 as Float).midpoint(5.0), 0.0); - assert_eq!(Float::MAX.midpoint(Float::MIN), 0.0); - assert_eq!(Float::MIN.midpoint(Float::MAX), -0.0); - assert_eq!(Float::MAX.midpoint(Float::MIN_POSITIVE), Float::MAX / 2.); - assert_eq!((-Float::MAX).midpoint(Float::MIN_POSITIVE), -Float::MAX / 2.); - assert_eq!(Float::MAX.midpoint(-Float::MIN_POSITIVE), Float::MAX / 2.); - assert_eq!((-Float::MAX).midpoint(-Float::MIN_POSITIVE), -Float::MAX / 2.); - assert_eq!((Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.); - assert_eq!((Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.); - assert_eq!((-Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.); - assert_eq!((-Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.); - assert_eq!(Float::MAX.midpoint(Float::MAX), Float::MAX); - assert_eq!( + assert_biteq!((0.5 as Float).midpoint(0.5), 0.5); + assert_biteq!((0.5 as Float).midpoint(2.5), 1.5); + assert_biteq!((3.0 as Float).midpoint(4.0), 3.5); + assert_biteq!((-3.0 as Float).midpoint(4.0), 0.5); + assert_biteq!((3.0 as Float).midpoint(-4.0), -0.5); + assert_biteq!((-3.0 as Float).midpoint(-4.0), -3.5); + assert_biteq!((0.0 as Float).midpoint(0.0), 0.0); + assert_biteq!((-0.0 as Float).midpoint(-0.0), -0.0); + assert_biteq!((-5.0 as Float).midpoint(5.0), 0.0); + assert_biteq!(Float::MAX.midpoint(Float::MIN), 0.0); + assert_biteq!(Float::MIN.midpoint(Float::MAX), 0.0); + assert_biteq!(Float::MAX.midpoint(Float::MIN_POSITIVE), Float::MAX / 2.); + assert_biteq!((-Float::MAX).midpoint(Float::MIN_POSITIVE), -Float::MAX / 2.); + assert_biteq!(Float::MAX.midpoint(-Float::MIN_POSITIVE), Float::MAX / 2.); + assert_biteq!((-Float::MAX).midpoint(-Float::MIN_POSITIVE), -Float::MAX / 2.); + assert_biteq!((Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.); + assert_biteq!((Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.); + assert_biteq!((-Float::MIN_POSITIVE).midpoint(Float::MAX), Float::MAX / 2.); + assert_biteq!((-Float::MIN_POSITIVE).midpoint(-Float::MAX), -Float::MAX / 2.); + assert_biteq!(Float::MAX.midpoint(Float::MAX), Float::MAX); + assert_biteq!( (Float::MIN_POSITIVE).midpoint(Float::MIN_POSITIVE), Float::MIN_POSITIVE ); - assert_eq!( + assert_biteq!( (-Float::MIN_POSITIVE).midpoint(-Float::MIN_POSITIVE), -Float::MIN_POSITIVE ); - assert_eq!(Float::MAX.midpoint(5.0), Float::MAX / 2.0 + 2.5); - assert_eq!(Float::MAX.midpoint(-5.0), Float::MAX / 2.0 - 2.5); - assert_eq!(Float::INFINITY.midpoint(Float::INFINITY), Float::INFINITY); - assert_eq!( + assert_biteq!(Float::MAX.midpoint(5.0), Float::MAX / 2.0 + 2.5); + assert_biteq!(Float::MAX.midpoint(-5.0), Float::MAX / 2.0 - 2.5); + assert_biteq!(Float::INFINITY.midpoint(Float::INFINITY), Float::INFINITY); + assert_biteq!( Float::NEG_INFINITY.midpoint(Float::NEG_INFINITY), Float::NEG_INFINITY ); + assert!(Float::NEG_INFINITY.midpoint(Float::INFINITY).is_nan()); + assert!(Float::INFINITY.midpoint(Float::NEG_INFINITY).is_nan()); assert!(Float::NAN.midpoint(1.0).is_nan()); assert!((1.0 as Float).midpoint(Float::NAN).is_nan()); assert!(Float::NAN.midpoint(Float::NAN).is_nan()); @@ -410,7 +451,7 @@ float_test! { let naive = (large + small) / 2.0; let midpoint = large.midpoint(small); - assert_eq!(naive, midpoint); + assert_biteq!(naive, midpoint); } } } @@ -423,10 +464,10 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((-1.0 as Float).abs(), 1.0); - assert_eq!((1.0 as Float).abs(), 1.0); - assert_eq!(Float::NEG_INFINITY.abs(), Float::INFINITY); - assert_eq!(Float::INFINITY.abs(), Float::INFINITY); + assert_biteq!((-1.0 as Float).abs(), 1.0); + assert_biteq!((1.0 as Float).abs(), 1.0); + assert_biteq!(Float::NEG_INFINITY.abs(), Float::INFINITY); + assert_biteq!(Float::INFINITY.abs(), Float::INFINITY); } } @@ -437,10 +478,10 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((1.0 as Float).copysign(-2.0), -1.0); - assert_eq!((-1.0 as Float).copysign(2.0), 1.0); - assert_eq!(Float::INFINITY.copysign(-0.0), Float::NEG_INFINITY); - assert_eq!(Float::NEG_INFINITY.copysign(0.0), Float::INFINITY); + assert_biteq!((1.0 as Float).copysign(-2.0), -1.0); + assert_biteq!((-1.0 as Float).copysign(2.0), 1.0); + assert_biteq!(Float::INFINITY.copysign(-0.0), Float::NEG_INFINITY); + assert_biteq!(Float::NEG_INFINITY.copysign(0.0), Float::INFINITY); } } @@ -453,7 +494,7 @@ float_test! { }, test { assert!(Float::INFINITY.rem_euclid(42.0 as Float).is_nan()); - assert_eq!((42.0 as Float).rem_euclid(Float::INFINITY), (42.0 as Float)); + assert_biteq!((42.0 as Float).rem_euclid(Float::INFINITY), 42.0 as Float); assert!((42.0 as Float).rem_euclid(Float::NAN).is_nan()); assert!(Float::INFINITY.rem_euclid(Float::INFINITY).is_nan()); assert!(Float::INFINITY.rem_euclid(Float::NAN).is_nan()); @@ -469,7 +510,7 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((42.0 as Float).div_euclid(Float::INFINITY), 0.0); + assert_biteq!((42.0 as Float).div_euclid(Float::INFINITY), 0.0); assert!((42.0 as Float).div_euclid(Float::NAN).is_nan()); assert!(Float::INFINITY.div_euclid(Float::INFINITY).is_nan()); assert!(Float::INFINITY.div_euclid(Float::NAN).is_nan()); @@ -484,20 +525,25 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((0.0 as Float).floor(), 0.0); - assert!((0.0 as Float).floor().is_sign_positive()); - assert_eq!((-0.0 as Float).floor(), -0.0); - assert!((-0.0 as Float).floor().is_sign_negative()); - assert_eq!((0.5 as Float).floor(), 0.0); - assert_eq!((-0.5 as Float).floor(), -1.0); - assert_eq!((1.5 as Float).floor(), 1.0); - assert_eq!(Float::MAX.floor(), Float::MAX); - assert_eq!(Float::MIN.floor(), Float::MIN); - assert_eq!(Float::MIN_POSITIVE.floor(), 0.0); - assert_eq!((-Float::MIN_POSITIVE).floor(), -1.0); + assert_biteq!((1.0 as Float).floor(), 1.0); + assert_biteq!((1.3 as Float).floor(), 1.0); + assert_biteq!((1.5 as Float).floor(), 1.0); + assert_biteq!((1.7 as Float).floor(), 1.0); + assert_biteq!((0.5 as Float).floor(), 0.0); + assert_biteq!((0.0 as Float).floor(), 0.0); + assert_biteq!((-0.0 as Float).floor(), -0.0); + assert_biteq!((-0.5 as Float).floor(), -1.0); + assert_biteq!((-1.0 as Float).floor(), -1.0); + assert_biteq!((-1.3 as Float).floor(), -2.0); + assert_biteq!((-1.5 as Float).floor(), -2.0); + assert_biteq!((-1.7 as Float).floor(), -2.0); + assert_biteq!(Float::MAX.floor(), Float::MAX); + assert_biteq!(Float::MIN.floor(), Float::MIN); + assert_biteq!(Float::MIN_POSITIVE.floor(), 0.0); + assert_biteq!((-Float::MIN_POSITIVE).floor(), -1.0); assert!(Float::NAN.floor().is_nan()); - assert_eq!(Float::INFINITY.floor(), Float::INFINITY); - assert_eq!(Float::NEG_INFINITY.floor(), Float::NEG_INFINITY); + assert_biteq!(Float::INFINITY.floor(), Float::INFINITY); + assert_biteq!(Float::NEG_INFINITY.floor(), Float::NEG_INFINITY); } } @@ -508,19 +554,25 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((0.0 as Float).ceil(), 0.0); - assert!((0.0 as Float).ceil().is_sign_positive()); - assert_eq!((-0.0 as Float).ceil(), 0.0); - assert!((-0.0 as Float).ceil().is_sign_negative()); - assert_eq!((0.5 as Float).ceil(), 1.0); - assert_eq!((-0.5 as Float).ceil(), 0.0); - assert_eq!(Float::MAX.ceil(), Float::MAX); - assert_eq!(Float::MIN.ceil(), Float::MIN); - assert_eq!(Float::MIN_POSITIVE.ceil(), 1.0); - assert_eq!((-Float::MIN_POSITIVE).ceil(), 0.0); + assert_biteq!((1.0 as Float).ceil(), 1.0); + assert_biteq!((1.3 as Float).ceil(), 2.0); + assert_biteq!((1.5 as Float).ceil(), 2.0); + assert_biteq!((1.7 as Float).ceil(), 2.0); + assert_biteq!((0.5 as Float).ceil(), 1.0); + assert_biteq!((0.0 as Float).ceil(), 0.0); + assert_biteq!((-0.0 as Float).ceil(), -0.0); + assert_biteq!((-0.5 as Float).ceil(), -0.0); + assert_biteq!((-1.0 as Float).ceil(), -1.0); + assert_biteq!((-1.3 as Float).ceil(), -1.0); + assert_biteq!((-1.5 as Float).ceil(), -1.0); + assert_biteq!((-1.7 as Float).ceil(), -1.0); + assert_biteq!(Float::MAX.ceil(), Float::MAX); + assert_biteq!(Float::MIN.ceil(), Float::MIN); + assert_biteq!(Float::MIN_POSITIVE.ceil(), 1.0); + assert_biteq!((-Float::MIN_POSITIVE).ceil(), -0.0); assert!(Float::NAN.ceil().is_nan()); - assert_eq!(Float::INFINITY.ceil(), Float::INFINITY); - assert_eq!(Float::NEG_INFINITY.ceil(), Float::NEG_INFINITY); + assert_biteq!(Float::INFINITY.ceil(), Float::INFINITY); + assert_biteq!(Float::NEG_INFINITY.ceil(), Float::NEG_INFINITY); } } @@ -531,19 +583,26 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((0.0 as Float).round(), 0.0); - assert!((0.0 as Float).round().is_sign_positive()); - assert_eq!((-0.0 as Float).round(), -0.0); - assert!((-0.0 as Float).round().is_sign_negative()); - assert_eq!((0.5 as Float).round(), 1.0); - assert_eq!((-0.5 as Float).round(), -1.0); - assert_eq!(Float::MAX.round(), Float::MAX); - assert_eq!(Float::MIN.round(), Float::MIN); - assert_eq!(Float::MIN_POSITIVE.round(), 0.0); - assert_eq!((-Float::MIN_POSITIVE).round(), 0.0); + assert_biteq!((2.5 as Float).round(), 3.0); + assert_biteq!((1.0 as Float).round(), 1.0); + assert_biteq!((1.3 as Float).round(), 1.0); + assert_biteq!((1.5 as Float).round(), 2.0); + assert_biteq!((1.7 as Float).round(), 2.0); + assert_biteq!((0.5 as Float).round(), 1.0); + assert_biteq!((0.0 as Float).round(), 0.0); + assert_biteq!((-0.0 as Float).round(), -0.0); + assert_biteq!((-0.5 as Float).round(), -1.0); + assert_biteq!((-1.0 as Float).round(), -1.0); + assert_biteq!((-1.3 as Float).round(), -1.0); + assert_biteq!((-1.5 as Float).round(), -2.0); + assert_biteq!((-1.7 as Float).round(), -2.0); + assert_biteq!(Float::MAX.round(), Float::MAX); + assert_biteq!(Float::MIN.round(), Float::MIN); + assert_biteq!(Float::MIN_POSITIVE.round(), 0.0); + assert_biteq!((-Float::MIN_POSITIVE).round(), -0.0); assert!(Float::NAN.round().is_nan()); - assert_eq!(Float::INFINITY.round(), Float::INFINITY); - assert_eq!(Float::NEG_INFINITY.round(), Float::NEG_INFINITY); + assert_biteq!(Float::INFINITY.round(), Float::INFINITY); + assert_biteq!(Float::NEG_INFINITY.round(), Float::NEG_INFINITY); } } @@ -554,21 +613,26 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((0.0 as Float).round_ties_even(), 0.0); - assert!((0.0 as Float).round_ties_even().is_sign_positive()); - assert_eq!((-0.0 as Float).round_ties_even(), -0.0); - assert!((-0.0 as Float).round_ties_even().is_sign_negative()); - assert_eq!((0.5 as Float).round_ties_even(), 0.0); - assert!((0.5 as Float).round_ties_even().is_sign_positive()); - assert_eq!((-0.5 as Float).round_ties_even(), -0.0); - assert!((-0.5 as Float).round_ties_even().is_sign_negative()); - assert_eq!(Float::MAX.round_ties_even(), Float::MAX); - assert_eq!(Float::MIN.round_ties_even(), Float::MIN); - assert_eq!(Float::MIN_POSITIVE.round_ties_even(), 0.0); - assert_eq!((-Float::MIN_POSITIVE).round_ties_even(), 0.0); + assert_biteq!((2.5 as Float).round_ties_even(), 2.0); + assert_biteq!((1.0 as Float).round_ties_even(), 1.0); + assert_biteq!((1.3 as Float).round_ties_even(), 1.0); + assert_biteq!((1.5 as Float).round_ties_even(), 2.0); + assert_biteq!((1.7 as Float).round_ties_even(), 2.0); + assert_biteq!((0.5 as Float).round_ties_even(), 0.0); + assert_biteq!((0.0 as Float).round_ties_even(), 0.0); + assert_biteq!((-0.0 as Float).round_ties_even(), -0.0); + assert_biteq!((-0.5 as Float).round_ties_even(), -0.0); + assert_biteq!((-1.0 as Float).round_ties_even(), -1.0); + assert_biteq!((-1.3 as Float).round_ties_even(), -1.0); + assert_biteq!((-1.5 as Float).round_ties_even(), -2.0); + assert_biteq!((-1.7 as Float).round_ties_even(), -2.0); + assert_biteq!(Float::MAX.round_ties_even(), Float::MAX); + assert_biteq!(Float::MIN.round_ties_even(), Float::MIN); + assert_biteq!(Float::MIN_POSITIVE.round_ties_even(), 0.0); + assert_biteq!((-Float::MIN_POSITIVE).round_ties_even(), -0.0); assert!(Float::NAN.round_ties_even().is_nan()); - assert_eq!(Float::INFINITY.round_ties_even(), Float::INFINITY); - assert_eq!(Float::NEG_INFINITY.round_ties_even(), Float::NEG_INFINITY); + assert_biteq!(Float::INFINITY.round_ties_even(), Float::INFINITY); + assert_biteq!(Float::NEG_INFINITY.round_ties_even(), Float::NEG_INFINITY); } } @@ -579,21 +643,25 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((0.0 as Float).trunc(), 0.0); - assert!((0.0 as Float).trunc().is_sign_positive()); - assert_eq!((-0.0 as Float).trunc(), -0.0); - assert!((-0.0 as Float).trunc().is_sign_negative()); - assert_eq!((0.5 as Float).trunc(), 0.0); - assert!((0.5 as Float).trunc().is_sign_positive()); - assert_eq!((-0.5 as Float).trunc(), -0.0); - assert!((-0.5 as Float).trunc().is_sign_negative()); - assert_eq!(Float::MAX.trunc(), Float::MAX); - assert_eq!(Float::MIN.trunc(), Float::MIN); - assert_eq!(Float::MIN_POSITIVE.trunc(), 0.0); - assert_eq!((-Float::MIN_POSITIVE).trunc(), 0.0); + assert_biteq!((1.0 as Float).trunc(), 1.0); + assert_biteq!((1.3 as Float).trunc(), 1.0); + assert_biteq!((1.5 as Float).trunc(), 1.0); + assert_biteq!((1.7 as Float).trunc(), 1.0); + assert_biteq!((0.5 as Float).trunc(), 0.0); + assert_biteq!((0.0 as Float).trunc(), 0.0); + assert_biteq!((-0.0 as Float).trunc(), -0.0); + assert_biteq!((-0.5 as Float).trunc(), -0.0); + assert_biteq!((-1.0 as Float).trunc(), -1.0); + assert_biteq!((-1.3 as Float).trunc(), -1.0); + assert_biteq!((-1.5 as Float).trunc(), -1.0); + assert_biteq!((-1.7 as Float).trunc(), -1.0); + assert_biteq!(Float::MAX.trunc(), Float::MAX); + assert_biteq!(Float::MIN.trunc(), Float::MIN); + assert_biteq!(Float::MIN_POSITIVE.trunc(), 0.0); + assert_biteq!((-Float::MIN_POSITIVE).trunc(), -0.0); assert!(Float::NAN.trunc().is_nan()); - assert_eq!(Float::INFINITY.trunc(), Float::INFINITY); - assert_eq!(Float::NEG_INFINITY.trunc(), Float::NEG_INFINITY); + assert_biteq!(Float::INFINITY.trunc(), Float::INFINITY); + assert_biteq!(Float::NEG_INFINITY.trunc(), Float::NEG_INFINITY); } } @@ -604,19 +672,23 @@ float_test! { f128: #[cfg(any(miri, target_has_reliable_f128_math))], }, test { - assert_eq!((0.0 as Float).fract(), 0.0); - assert!((0.0 as Float).fract().is_sign_positive()); - assert_eq!((-0.0 as Float).fract(), 0.0); - assert!((-0.0 as Float).fract().is_sign_positive()); - assert_eq!((0.5 as Float).fract(), 0.5); - assert!((0.5 as Float).fract().is_sign_positive()); - assert_eq!((-0.5 as Float).fract(), -0.5); - assert!((-0.5 as Float).fract().is_sign_negative()); - assert_eq!(Float::MAX.fract(), 0.0); - assert_eq!(Float::MIN.fract(), 0.0); - assert_eq!(Float::MIN_POSITIVE.fract(), Float::MIN_POSITIVE); + assert_biteq!((1.0 as Float).fract(), 0.0); + assert_approx_eq!((1.3 as Float).fract(), 0.3); // rounding differs between float types + assert_biteq!((1.5 as Float).fract(), 0.5); + assert_approx_eq!((1.7 as Float).fract(), 0.7); + assert_biteq!((0.5 as Float).fract(), 0.5); + assert_biteq!((0.0 as Float).fract(), 0.0); + assert_biteq!((-0.0 as Float).fract(), 0.0); + assert_biteq!((-0.5 as Float).fract(), -0.5); + assert_biteq!((-1.0 as Float).fract(), 0.0); + assert_approx_eq!((-1.3 as Float).fract(), -0.3); // rounding differs between float types + assert_biteq!((-1.5 as Float).fract(), -0.5); + assert_approx_eq!((-1.7 as Float).fract(), -0.7); + assert_biteq!(Float::MAX.fract(), 0.0); + assert_biteq!(Float::MIN.fract(), 0.0); + assert_biteq!(Float::MIN_POSITIVE.fract(), Float::MIN_POSITIVE); assert!(Float::MIN_POSITIVE.fract().is_sign_positive()); - assert_eq!((-Float::MIN_POSITIVE).fract(), -Float::MIN_POSITIVE); + assert_biteq!((-Float::MIN_POSITIVE).fract(), -Float::MIN_POSITIVE); assert!((-Float::MIN_POSITIVE).fract().is_sign_negative()); assert!(Float::NAN.fract().is_nan()); assert!(Float::INFINITY.fract().is_nan()); diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs index bb60fb07468f9..197a14423b59d 100644 --- a/library/coretests/tests/ptr.rs +++ b/library/coretests/tests/ptr.rs @@ -653,7 +653,6 @@ fn thin_box() { // if `{size,align}_of_for_meta(T::Metadata)` are added. // * Constructing a `ThinBox` without consuming and deallocating a `Box` // requires either the unstable `Unsize` marker trait, - // or the unstable `unsized_locals` language feature, // or taking `&dyn T` and restricting to `T: Copy`. use std::alloc::*; diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index cb1246db3109e..fd6fe72dd248b 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -1,3 +1,4 @@ +use crate::bstr::ByteStr; use crate::ffi::OsStr; #[cfg(any(doc, target_os = "android", target_os = "linux"))] use crate::os::net::linux_ext; @@ -61,7 +62,7 @@ pub(super) fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::s enum AddressKind<'a> { Unnamed, Pathname(&'a Path), - Abstract(&'a [u8]), + Abstract(&'a ByteStr), } /// An address associated with a Unix socket. @@ -245,7 +246,7 @@ impl SocketAddr { { AddressKind::Unnamed } else if self.addr.sun_path[0] == 0 { - AddressKind::Abstract(&path[1..len]) + AddressKind::Abstract(ByteStr::from_bytes(&path[1..len])) } else { AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref()) } @@ -260,7 +261,7 @@ impl Sealed for SocketAddr {} #[stable(feature = "unix_socket_abstract", since = "1.70.0")] impl linux_ext::addr::SocketAddrExt for SocketAddr { fn as_abstract_name(&self) -> Option<&[u8]> { - if let AddressKind::Abstract(name) = self.address() { Some(name) } else { None } + if let AddressKind::Abstract(name) = self.address() { Some(name.as_bytes()) } else { None } } fn from_abstract_name(name: N) -> crate::io::Result @@ -295,7 +296,7 @@ impl fmt::Debug for SocketAddr { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self.address() { AddressKind::Unnamed => write!(fmt, "(unnamed)"), - AddressKind::Abstract(name) => write!(fmt, "\"{}\" (abstract)", name.escape_ascii()), + AddressKind::Abstract(name) => write!(fmt, "{name:?} (abstract)"), AddressKind::Pathname(path) => write!(fmt, "{path:?} (pathname)"), } } diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index 0398a535eb54a..9a88687b1df0c 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -411,6 +411,15 @@ fn test_unix_datagram_timeout_zero_duration() { assert_eq!(err.kind(), ErrorKind::InvalidInput); } +#[cfg(any(target_os = "android", target_os = "linux"))] +#[test] +fn abstract_socket_addr_debug() { + assert_eq!( + r#""\0hello world\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x11\x12\r\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x7f\x80\x81\xfe\xff" (abstract)"#, + format!("{:?}", SocketAddr::from_abstract_name(b"\0hello world\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x11\x12\r\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x7f\x80\x81\xfe\xff").unwrap()), + ); +} + #[test] fn abstract_namespace_not_allowed_connect() { assert!(UnixStream::connect("\0asdf").is_err()); diff --git a/src/doc/rustc-dev-guide/src/implementing_new_features.md b/src/doc/rustc-dev-guide/src/implementing_new_features.md index d7561bbbad22a..5d0e875cbc18c 100644 --- a/src/doc/rustc-dev-guide/src/implementing_new_features.md +++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md @@ -156,8 +156,8 @@ a new unstable feature: [`incomplete_features` lint]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#incomplete-features ```rust ignore - /// Allows unsized rvalues at arguments and parameters. - (incomplete, unsized_locals, "CURRENT_RUSTC_VERSION", Some(48055), None), + /// Allows deref patterns. + (incomplete, deref_patterns, "CURRENT_RUSTC_VERSION", Some(87121), None), ``` To avoid [semantic merge conflicts], please use `CURRENT_RUSTC_VERSION` instead of `1.70` or diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 69e5a5adbec29..27910ad0ab796 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -581,7 +581,9 @@ For this rust code: ```rust /// ``` +/// #![allow(dead_code)] /// let x = 12; +/// Ok(()) /// ``` pub trait Trait {} ``` @@ -590,10 +592,10 @@ The generated output (formatted) will look like this: ```json { - "format_version": 1, + "format_version": 2, "doctests": [ { - "file": "foo.rs", + "file": "src/lib.rs", "line": 1, "doctest_attributes": { "original": "", @@ -609,9 +611,17 @@ The generated output (formatted) will look like this: "added_css_classes": [], "unknown": [] }, - "original_code": "let x = 12;", - "doctest_code": "#![allow(unused)]\nfn main() {\nlet x = 12;\n}", - "name": "foo.rs - Trait (line 1)" + "original_code": "#![allow(dead_code)]\nlet x = 12;\nOk(())", + "doctest_code": { + "crate_level": "#![allow(unused)]\n#![allow(dead_code)]\n\n", + "code": "let x = 12;\nOk(())", + "wrapper": { + "before": "fn main() { fn _inner() -> core::result::Result<(), impl core::fmt::Debug> {\n", + "after": "\n} _inner().unwrap() }", + "returns_result": true + } + }, + "name": "src/lib.rs - (line 1)" } ] } @@ -624,6 +634,10 @@ The generated output (formatted) will look like this: * `doctest_attributes` contains computed information about the attributes used on the doctests. For more information about doctest attributes, take a look [here](write-documentation/documentation-tests.html#attributes). * `original_code` is the code as written in the source code before rustdoc modifies it. * `doctest_code` is the code modified by rustdoc that will be run. If there is a fatal syntax error, this field will not be present. + * `crate_level` is the crate level code (like attributes or `extern crate`) that will be added at the top-level of the generated doctest. + * `code` is "naked" doctest without anything from `crate_level` and `wrapper` content. + * `wrapper` contains extra code that will be added before and after `code`. + * `returns_result` is a boolean. If `true`, it means that the doctest returns a `Result` type. * `name` is the name generated by rustdoc which represents this doctest. ### html diff --git a/src/doc/unstable-book/src/language-features/unsized-locals.md b/src/doc/unstable-book/src/language-features/unsized-locals.md deleted file mode 100644 index d5b01a3d6168e..0000000000000 --- a/src/doc/unstable-book/src/language-features/unsized-locals.md +++ /dev/null @@ -1,175 +0,0 @@ -# `unsized_locals` - -The tracking issue for this feature is: [#48055] - -[#48055]: https://github.com/rust-lang/rust/issues/48055 - ------------------------- - -This implements [RFC1909]. When turned on, you can have unsized arguments and locals: - -[RFC1909]: https://github.com/rust-lang/rfcs/blob/master/text/1909-unsized-rvalues.md - -```rust -#![allow(incomplete_features)] -#![feature(unsized_locals, unsized_fn_params)] - -use std::any::Any; - -fn main() { - let x: Box = Box::new(42); - let x: dyn Any = *x; - // ^ unsized local variable - // ^^ unsized temporary - foo(x); -} - -fn foo(_: dyn Any) {} -// ^^^^^^ unsized argument -``` - -The RFC still forbids the following unsized expressions: - -```rust,compile_fail -#![feature(unsized_locals)] - -use std::any::Any; - -struct MyStruct { - content: T, -} - -struct MyTupleStruct(T); - -fn answer() -> Box { - Box::new(42) -} - -fn main() { - // You CANNOT have unsized statics. - static X: dyn Any = *answer(); // ERROR - const Y: dyn Any = *answer(); // ERROR - - // You CANNOT have struct initialized unsized. - MyStruct { content: *answer() }; // ERROR - MyTupleStruct(*answer()); // ERROR - (42, *answer()); // ERROR - - // You CANNOT have unsized return types. - fn my_function() -> dyn Any { *answer() } // ERROR - - // You CAN have unsized local variables... - let mut x: dyn Any = *answer(); // OK - // ...but you CANNOT reassign to them. - x = *answer(); // ERROR - - // You CANNOT even initialize them separately. - let y: dyn Any; // OK - y = *answer(); // ERROR - - // Not mentioned in the RFC, but by-move captured variables are also Sized. - let x: dyn Any = *answer(); - (move || { // ERROR - let y = x; - })(); - - // You CAN create a closure with unsized arguments, - // but you CANNOT call it. - // This is an implementation detail and may be changed in the future. - let f = |x: dyn Any| {}; - f(*answer()); // ERROR -} -``` - -## By-value trait objects - -With this feature, you can have by-value `self` arguments without `Self: Sized` bounds. - -```rust -#![feature(unsized_fn_params)] - -trait Foo { - fn foo(self) {} -} - -impl Foo for T {} - -fn main() { - let slice: Box<[i32]> = Box::new([1, 2, 3]); - <[i32] as Foo>::foo(*slice); -} -``` - -And `Foo` will also be object-safe. - -```rust -#![feature(unsized_fn_params)] - -trait Foo { - fn foo(self) {} -} - -impl Foo for T {} - -fn main () { - let slice: Box = Box::new([1, 2, 3]); - // doesn't compile yet - ::foo(*slice); -} -``` - -One of the objectives of this feature is to allow `Box`. - -## Variable length arrays - -The RFC also describes an extension to the array literal syntax: `[e; dyn n]`. In the syntax, `n` isn't necessarily a constant expression. The array is dynamically allocated on the stack and has the type of `[T]`, instead of `[T; n]`. - -```rust,ignore (not-yet-implemented) -#![feature(unsized_locals)] - -fn mergesort(a: &mut [T]) { - let mut tmp = [T; dyn a.len()]; - // ... -} - -fn main() { - let mut a = [3, 1, 5, 6]; - mergesort(&mut a); - assert_eq!(a, [1, 3, 5, 6]); -} -``` - -VLAs are not implemented yet. The syntax isn't final, either. We may need an alternative syntax for Rust 2015 because, in Rust 2015, expressions like `[e; dyn(1)]` would be ambiguous. One possible alternative proposed in the RFC is `[e; n]`: if `n` captures one or more local variables, then it is considered as `[e; dyn n]`. - -## Advisory on stack usage - -It's advised not to casually use the `#![feature(unsized_locals)]` feature. Typical use-cases are: - -- When you need a by-value trait objects. -- When you really need a fast allocation of small temporary arrays. - -Another pitfall is repetitive allocation and temporaries. Currently the compiler simply extends the stack frame every time it encounters an unsized assignment. So for example, the code - -```rust -#![feature(unsized_locals)] - -fn main() { - let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]); - let _x = {{{{{{{{{{*x}}}}}}}}}}; -} -``` - -and the code - -```rust -#![feature(unsized_locals)] - -fn main() { - for _ in 0..10 { - let x: Box<[i32]> = Box::new([1, 2, 3, 4, 5]); - let _x = *x; - } -} -``` - -will unnecessarily extend the stack frame. diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index a81d6020f7143..130fdff1afe29 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -1053,14 +1053,14 @@ fn doctest_run_fn( let report_unused_externs = |uext| { unused_externs.lock().unwrap().push(uext); }; - let (full_test_code, full_test_line_offset) = doctest.generate_unique_doctest( + let (wrapped, full_test_line_offset) = doctest.generate_unique_doctest( &scraped_test.text, scraped_test.langstr.test_harness, &global_opts, Some(&global_opts.crate_name), ); let runnable_test = RunnableDocTest { - full_test_code, + full_test_code: wrapped.to_string(), full_test_line_offset, test_opts, global_opts, diff --git a/src/librustdoc/doctest/extracted.rs b/src/librustdoc/doctest/extracted.rs index ebe6bfd22ba10..925fb6fee2caa 100644 --- a/src/librustdoc/doctest/extracted.rs +++ b/src/librustdoc/doctest/extracted.rs @@ -3,8 +3,10 @@ //! This module contains the logic to extract doctests and output a JSON containing this //! information. +use rustc_span::edition::Edition; use serde::Serialize; +use super::make::DocTestWrapResult; use super::{BuildDocTestBuilder, ScrapedDocTest}; use crate::config::Options as RustdocOptions; use crate::html::markdown; @@ -14,7 +16,7 @@ use crate::html::markdown; /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob into the `format_version` root field. /// Consuming code should assert that this value matches the format version(s) that it supports. -const FORMAT_VERSION: u32 = 1; +const FORMAT_VERSION: u32 = 2; #[derive(Serialize)] pub(crate) struct ExtractedDocTests { @@ -34,7 +36,16 @@ impl ExtractedDocTests { options: &RustdocOptions, ) { let edition = scraped_test.edition(options); + self.add_test_with_edition(scraped_test, opts, edition) + } + /// This method is used by unit tests to not have to provide a `RustdocOptions`. + pub(crate) fn add_test_with_edition( + &mut self, + scraped_test: ScrapedDocTest, + opts: &super::GlobalTestOptions, + edition: Edition, + ) { let ScrapedDocTest { filename, line, langstr, text, name, global_crate_attrs, .. } = scraped_test; @@ -44,8 +55,7 @@ impl ExtractedDocTests { .edition(edition) .lang_str(&langstr) .build(None); - - let (full_test_code, size) = doctest.generate_unique_doctest( + let (wrapped, _size) = doctest.generate_unique_doctest( &text, langstr.test_harness, opts, @@ -55,11 +65,46 @@ impl ExtractedDocTests { file: filename.prefer_remapped_unconditionaly().to_string(), line, doctest_attributes: langstr.into(), - doctest_code: if size != 0 { Some(full_test_code) } else { None }, + doctest_code: match wrapped { + DocTestWrapResult::Valid { crate_level_code, wrapper, code } => Some(DocTest { + crate_level: crate_level_code, + code, + wrapper: wrapper.map( + |super::make::WrapperInfo { before, after, returns_result, .. }| { + WrapperInfo { before, after, returns_result } + }, + ), + }), + DocTestWrapResult::SyntaxError { .. } => None, + }, original_code: text, name, }); } + + #[cfg(test)] + pub(crate) fn doctests(&self) -> &[ExtractedDocTest] { + &self.doctests + } +} + +#[derive(Serialize)] +pub(crate) struct WrapperInfo { + before: String, + after: String, + returns_result: bool, +} + +#[derive(Serialize)] +pub(crate) struct DocTest { + crate_level: String, + code: String, + /// This field can be `None` if one of the following conditions is true: + /// + /// * The doctest's codeblock has the `test_harness` attribute. + /// * The doctest has a `main` function. + /// * The doctest has the `![no_std]` attribute. + pub(crate) wrapper: Option, } #[derive(Serialize)] @@ -69,7 +114,7 @@ pub(crate) struct ExtractedDocTest { doctest_attributes: LangString, original_code: String, /// `None` if the code syntax is invalid. - doctest_code: Option, + pub(crate) doctest_code: Option, name: String, } diff --git a/src/librustdoc/doctest/make.rs b/src/librustdoc/doctest/make.rs index 5e571613d6ff6..3ff6828e52f96 100644 --- a/src/librustdoc/doctest/make.rs +++ b/src/librustdoc/doctest/make.rs @@ -196,6 +196,80 @@ pub(crate) struct DocTestBuilder { pub(crate) can_be_merged: bool, } +/// Contains needed information for doctest to be correctly generated with expected "wrapping". +pub(crate) struct WrapperInfo { + pub(crate) before: String, + pub(crate) after: String, + pub(crate) returns_result: bool, + insert_indent_space: bool, +} + +impl WrapperInfo { + fn len(&self) -> usize { + self.before.len() + self.after.len() + } +} + +/// Contains a doctest information. Can be converted into code with the `to_string()` method. +pub(crate) enum DocTestWrapResult { + Valid { + crate_level_code: String, + /// This field can be `None` if one of the following conditions is true: + /// + /// * The doctest's codeblock has the `test_harness` attribute. + /// * The doctest has a `main` function. + /// * The doctest has the `![no_std]` attribute. + wrapper: Option, + /// Contains the doctest processed code without the wrappers (which are stored in the + /// `wrapper` field). + code: String, + }, + /// Contains the original source code. + SyntaxError(String), +} + +impl std::string::ToString for DocTestWrapResult { + fn to_string(&self) -> String { + match self { + Self::SyntaxError(s) => s.clone(), + Self::Valid { crate_level_code, wrapper, code } => { + let mut prog_len = code.len() + crate_level_code.len(); + if let Some(wrapper) = wrapper { + prog_len += wrapper.len(); + if wrapper.insert_indent_space { + prog_len += code.lines().count() * 4; + } + } + let mut prog = String::with_capacity(prog_len); + + prog.push_str(crate_level_code); + if let Some(wrapper) = wrapper { + prog.push_str(&wrapper.before); + + // add extra 4 spaces for each line to offset the code block + if wrapper.insert_indent_space { + write!( + prog, + "{}", + fmt::from_fn(|f| code + .lines() + .map(|line| fmt::from_fn(move |f| write!(f, " {line}"))) + .joined("\n", f)) + ) + .unwrap(); + } else { + prog.push_str(code); + } + prog.push_str(&wrapper.after); + } else { + prog.push_str(code); + } + prog + } + } + } +} + impl DocTestBuilder { fn invalid( global_crate_attrs: Vec, @@ -228,50 +302,49 @@ impl DocTestBuilder { dont_insert_main: bool, opts: &GlobalTestOptions, crate_name: Option<&str>, - ) -> (String, usize) { + ) -> (DocTestWrapResult, usize) { if self.invalid_ast { // If the AST failed to compile, no need to go generate a complete doctest, the error // will be better this way. debug!("invalid AST:\n{test_code}"); - return (test_code.to_string(), 0); + return (DocTestWrapResult::SyntaxError(test_code.to_string()), 0); } let mut line_offset = 0; - let mut prog = String::new(); - let everything_else = self.everything_else.trim(); - + let mut crate_level_code = String::new(); + let processed_code = self.everything_else.trim(); if self.global_crate_attrs.is_empty() { // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some // lints that are commonly triggered in doctests. The crate-level test attributes are // commonly used to make tests fail in case they trigger warnings, so having this there in // that case may cause some tests to pass when they shouldn't have. - prog.push_str("#![allow(unused)]\n"); + crate_level_code.push_str("#![allow(unused)]\n"); line_offset += 1; } // Next, any attributes that came from #![doc(test(attr(...)))]. for attr in &self.global_crate_attrs { - prog.push_str(&format!("#![{attr}]\n")); + crate_level_code.push_str(&format!("#![{attr}]\n")); line_offset += 1; } // Now push any outer attributes from the example, assuming they // are intended to be crate attributes. if !self.crate_attrs.is_empty() { - prog.push_str(&self.crate_attrs); + crate_level_code.push_str(&self.crate_attrs); if !self.crate_attrs.ends_with('\n') { - prog.push('\n'); + crate_level_code.push('\n'); } } if !self.maybe_crate_attrs.is_empty() { - prog.push_str(&self.maybe_crate_attrs); + crate_level_code.push_str(&self.maybe_crate_attrs); if !self.maybe_crate_attrs.ends_with('\n') { - prog.push('\n'); + crate_level_code.push('\n'); } } if !self.crates.is_empty() { - prog.push_str(&self.crates); + crate_level_code.push_str(&self.crates); if !self.crates.ends_with('\n') { - prog.push('\n'); + crate_level_code.push('\n'); } } @@ -289,17 +362,20 @@ impl DocTestBuilder { { // rustdoc implicitly inserts an `extern crate` item for the own crate // which may be unused, so we need to allow the lint. - prog.push_str("#[allow(unused_extern_crates)]\n"); + crate_level_code.push_str("#[allow(unused_extern_crates)]\n"); - prog.push_str(&format!("extern crate r#{crate_name};\n")); + crate_level_code.push_str(&format!("extern crate r#{crate_name};\n")); line_offset += 1; } // FIXME: This code cannot yet handle no_std test cases yet - if dont_insert_main || self.has_main_fn || prog.contains("![no_std]") { - prog.push_str(everything_else); + let wrapper = if dont_insert_main + || self.has_main_fn + || crate_level_code.contains("![no_std]") + { + None } else { - let returns_result = everything_else.ends_with("(())"); + let returns_result = processed_code.ends_with("(())"); // Give each doctest main function a unique name. // This is for example needed for the tooling around `-C instrument-coverage`. let inner_fn_name = if let Some(ref test_id) = self.test_id { @@ -333,28 +409,22 @@ impl DocTestBuilder { // /// ``` <- end of the inner main line_offset += 1; - prog.push_str(&main_pre); - - // add extra 4 spaces for each line to offset the code block - if opts.insert_indent_space { - write!( - prog, - "{}", - fmt::from_fn(|f| everything_else - .lines() - .map(|line| fmt::from_fn(move |f| write!(f, " {line}"))) - .joined("\n", f)) - ) - .unwrap(); - } else { - prog.push_str(everything_else); - }; - prog.push_str(&main_post); - } - - debug!("final doctest:\n{prog}"); + Some(WrapperInfo { + before: main_pre, + after: main_post, + returns_result, + insert_indent_space: opts.insert_indent_space, + }) + }; - (prog, line_offset) + ( + DocTestWrapResult::Valid { + code: processed_code.to_string(), + wrapper, + crate_level_code, + }, + line_offset, + ) } } diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index ce2984ced7904..ccc3e55a33122 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -1,6 +1,11 @@ use std::path::PathBuf; -use super::{BuildDocTestBuilder, GlobalTestOptions}; +use rustc_span::edition::Edition; +use rustc_span::{DUMMY_SP, FileName}; + +use super::extracted::ExtractedDocTests; +use super::{BuildDocTestBuilder, GlobalTestOptions, ScrapedDocTest}; +use crate::html::markdown::LangString; fn make_test( test_code: &str, @@ -19,9 +24,9 @@ fn make_test( builder = builder.test_id(test_id.to_string()); } let doctest = builder.build(None); - let (code, line_offset) = + let (wrapped, line_offset) = doctest.generate_unique_doctest(test_code, dont_insert_main, opts, crate_name); - (code, line_offset) + (wrapped.to_string(), line_offset) } /// Default [`GlobalTestOptions`] for these unit tests. @@ -461,3 +466,51 @@ pub mod outer_module { let (output, len) = make_test(input, None, false, &opts, Vec::new(), None); assert_eq!((output, len), (expected, 2)); } + +fn get_extracted_doctests(code: &str) -> ExtractedDocTests { + let opts = default_global_opts(""); + let mut extractor = ExtractedDocTests::new(); + extractor.add_test_with_edition( + ScrapedDocTest::new( + FileName::Custom(String::new()), + 0, + Vec::new(), + LangString::default(), + code.to_string(), + DUMMY_SP, + Vec::new(), + ), + &opts, + Edition::Edition2018, + ); + extractor +} + +// Test that `extracted::DocTest::wrapper` is `None` if the doctest has a `main` function. +#[test] +fn test_extracted_doctest_wrapper_field() { + let extractor = get_extracted_doctests("fn main() {}"); + + assert_eq!(extractor.doctests().len(), 1); + let doctest_code = extractor.doctests()[0].doctest_code.as_ref().unwrap(); + assert!(doctest_code.wrapper.is_none()); +} + +// Test that `ExtractedDocTest::doctest_code` is `None` if the doctest has syntax error. +#[test] +fn test_extracted_doctest_doctest_code_field() { + let extractor = get_extracted_doctests("let x +="); + + assert_eq!(extractor.doctests().len(), 1); + assert!(extractor.doctests()[0].doctest_code.is_none()); +} + +// Test that `extracted::DocTest::wrapper` is `Some` if the doctest needs wrapping. +#[test] +fn test_extracted_doctest_wrapper_field_with_info() { + let extractor = get_extracted_doctests("let x = 12;"); + + assert_eq!(extractor.doctests().len(), 1); + let doctest_code = extractor.doctests()[0].doctest_code.as_ref().unwrap(); + assert!(doctest_code.wrapper.is_some()); +} diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index d3701784f9dff..f626e07b000a6 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -307,7 +307,8 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { builder = builder.crate_name(krate); } let doctest = builder.build(None); - let (test, _) = doctest.generate_unique_doctest(&test, false, &opts, krate); + let (wrapped, _) = doctest.generate_unique_doctest(&test, false, &opts, krate); + let test = wrapped.to_string(); let channel = if test.contains("#![feature(") { "&version=nightly" } else { "" }; let test_escaped = small_url_encode(test); diff --git a/src/tools/clippy/tests/ui/large_stack_frames.rs b/src/tools/clippy/tests/ui/large_stack_frames.rs index 3ed124f69ef35..132f1450b6ded 100644 --- a/src/tools/clippy/tests/ui/large_stack_frames.rs +++ b/src/tools/clippy/tests/ui/large_stack_frames.rs @@ -1,8 +1,7 @@ //@ normalize-stderr-test: "\b10000(08|16|32)\b" -> "100$$PTR" //@ normalize-stderr-test: "\b2500(060|120)\b" -> "250$$PTR" -#![allow(unused, incomplete_features)] +#![allow(unused)] #![warn(clippy::large_stack_frames)] -#![feature(unsized_locals)] use std::hint::black_box; @@ -11,11 +10,6 @@ fn generic() { black_box(&x); } -fn unsized_local() { - let x: dyn std::fmt::Display = *(Box::new(1) as Box); - black_box(&x); -} - struct ArrayDefault([u8; N]); impl Default for ArrayDefault { diff --git a/src/tools/clippy/tests/ui/large_stack_frames.stderr b/src/tools/clippy/tests/ui/large_stack_frames.stderr index 0ff49e9f5b372..79482e65c3e62 100644 --- a/src/tools/clippy/tests/ui/large_stack_frames.stderr +++ b/src/tools/clippy/tests/ui/large_stack_frames.stderr @@ -1,5 +1,5 @@ error: this function may allocate 250$PTR bytes on the stack - --> tests/ui/large_stack_frames.rs:27:4 + --> tests/ui/large_stack_frames.rs:21:4 | LL | fn many_small_arrays() { | ^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | let x5 = [0u8; 500_000]; = help: to override `-D warnings` add `#[allow(clippy::large_stack_frames)]` error: this function may allocate 1000000 bytes on the stack - --> tests/ui/large_stack_frames.rs:38:4 + --> tests/ui/large_stack_frames.rs:32:4 | LL | fn large_return_value() -> ArrayDefault<1_000_000> { | ^^^^^^^^^^^^^^^^^^ ----------------------- this is the largest part, at 1000000 bytes for type `ArrayDefault<1000000>` @@ -21,7 +21,7 @@ LL | fn large_return_value() -> ArrayDefault<1_000_000> { = note: 1000000 bytes is larger than Clippy's configured `stack-size-threshold` of 512000 error: this function may allocate 100$PTR bytes on the stack - --> tests/ui/large_stack_frames.rs:44:4 + --> tests/ui/large_stack_frames.rs:38:4 | LL | fn large_fn_arg(x: ArrayDefault<1_000_000>) { | ^^^^^^^^^^^^ - `x` is the largest part, at 1000000 bytes for type `ArrayDefault<1000000>` @@ -29,7 +29,7 @@ LL | fn large_fn_arg(x: ArrayDefault<1_000_000>) { = note: 100$PTR bytes is larger than Clippy's configured `stack-size-threshold` of 512000 error: this function may allocate 100$PTR bytes on the stack - --> tests/ui/large_stack_frames.rs:51:13 + --> tests/ui/large_stack_frames.rs:45:13 | LL | let f = || black_box(&[0u8; 1_000_000]); | ^^^^^^^^^^^^^^----------------^ diff --git a/src/tools/miri/tests/fail/unsized-local.rs b/src/tools/miri/tests/fail/unsized-local.rs deleted file mode 100644 index ceccae4e3e76f..0000000000000 --- a/src/tools/miri/tests/fail/unsized-local.rs +++ /dev/null @@ -1,23 +0,0 @@ -#![feature(unsized_locals)] -#![allow(incomplete_features)] - -fn main() { - pub trait Foo { - fn foo(self) -> String; - } - - struct A; - - impl Foo for A { - fn foo(self) -> String { - format!("hello") - } - } - - let x = *(Box::new(A) as Box); //~ERROR: unsized locals are not supported - assert_eq!(x.foo(), format!("hello")); - - // I'm not sure whether we want this to work - let x = Box::new(A) as Box; - assert_eq!(x.foo(), format!("hello")); -} diff --git a/src/tools/miri/tests/fail/unsized-local.stderr b/src/tools/miri/tests/fail/unsized-local.stderr deleted file mode 100644 index 548f3d66c7338..0000000000000 --- a/src/tools/miri/tests/fail/unsized-local.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: unsupported operation: unsized locals are not supported - --> tests/fail/unsized-local.rs:LL:CC - | -LL | let x = *(Box::new(A) as Box); - | ^ unsized locals are not supported - | - = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support - = note: BACKTRACE: - = note: inside `main` at tests/fail/unsized-local.rs:LL:CC - -note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace - -error: aborting due to 1 previous error - diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 3e9d79224fdde..045f2f0692a10 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -754,7 +754,6 @@ ui/consts/issue-46553.rs ui/consts/issue-47789.rs ui/consts/issue-50439.rs ui/consts/issue-52023-array-size-pointer-cast.rs -ui/consts/issue-54224.rs ui/consts/issue-54348.rs ui/consts/issue-54387.rs ui/consts/issue-54582.rs diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs index 2a8251785e77d..3287e018b4044 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-32bit.rs @@ -10,8 +10,8 @@ //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled #![crate_type = "lib"] -#![allow(incomplete_features)] -#![feature(unsized_locals, unsized_fn_params)] +#![allow(internal_features)] +#![feature(unsized_fn_params)] // CHECK-LABEL: emptyfn: #[no_mangle] @@ -357,27 +357,3 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie } - -// CHECK-LABEL: unsized_local -#[no_mangle] -pub fn unsized_local(s: &[u8], l: bool, f: fn(&mut [u8])) { - let n = if l { 1 } else { 2 }; - let mut a: [u8] = *Box::<[u8]>::from(&s[0..n]); // slice-copy with Box::from - f(&mut a); - - // This function allocates a slice as a local variable in its stack - // frame. Since the size is not a compile-time constant, an array - // alloca is required, and the function is protected by both the - // `strong` and `basic` heuristic. - - // We should have a __security_check_cookie call in `all`, `strong` and `basic` modes but - // LLVM does not support generating stack protectors in functions with funclet - // based EH personalities. - // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 - // all-NOT: __security_check_cookie - // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie - - // none-NOT: __security_check_cookie - // missing-NOT: __security_check_cookie -} diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs index 9729da4e5d25a..9a3dabc74dded 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect-windows-64bit.rs @@ -10,8 +10,7 @@ //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled #![crate_type = "lib"] -#![allow(incomplete_features)] -#![feature(unsized_locals, unsized_fn_params)] +#![feature(unsized_fn_params)] // CHECK-LABEL: emptyfn: #[no_mangle] @@ -365,27 +364,3 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // none-NOT: __security_check_cookie // missing-NOT: __security_check_cookie } - -// CHECK-LABEL: unsized_local -#[no_mangle] -pub fn unsized_local(s: &[u8], l: bool, f: fn(&mut [u8])) { - let n = if l { 1 } else { 2 }; - let mut a: [u8] = *Box::<[u8]>::from(&s[0..n]); // slice-copy with Box::from - f(&mut a); - - // This function allocates a slice as a local variable in its stack - // frame. Since the size is not a compile-time constant, an array - // alloca is required, and the function is protected by both the - // `strong` and `basic` heuristic. - - // We should have a __security_check_cookie call in `all`, `strong` and `basic` modes but - // LLVM does not support generating stack protectors in functions with funclet - // based EH personalities. - // https://github.com/llvm/llvm-project/blob/37fd3c96b917096d8a550038f6e61cdf0fc4174f/llvm/lib/CodeGen/StackProtector.cpp#L103C1-L109C4 - // all-NOT: __security_check_cookie - // strong-NOT: __security_check_cookie - // basic-NOT: __security_check_cookie - - // none-NOT: __security_check_cookie - // missing-NOT: __security_check_cookie -} diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs index 91c83fa2f5ba9..ae281cb95da5f 100644 --- a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs @@ -16,8 +16,8 @@ // See comments on https://github.com/rust-lang/rust/issues/114903. #![crate_type = "lib"] -#![allow(incomplete_features)] -#![feature(unsized_locals, unsized_fn_params)] +#![allow(internal_features)] +#![feature(unsized_fn_params)] // CHECK-LABEL: emptyfn{{:|\[}} #[no_mangle] @@ -343,22 +343,3 @@ pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { // none-NOT: __stack_chk_fail // missing-NOT: __stack_chk_fail } - -// CHECK-LABEL: unsized_local{{:|\[}} -#[no_mangle] -pub fn unsized_local(s: &[u8], l: bool, f: fn(&mut [u8])) { - let n = if l { 1 } else { 2 }; - let mut a: [u8] = *Box::<[u8]>::from(&s[0..n]); // slice-copy with Box::from - f(&mut a); - - // This function allocates a slice as a local variable in its stack - // frame. Since the size is not a compile-time constant, an array - // alloca is required, and the function is protected by both the - // `strong` and `basic` heuristic. - - // all: __stack_chk_fail - // strong: __stack_chk_fail - // basic: __stack_chk_fail - // none-NOT: __stack_chk_fail - // missing-NOT: __stack_chk_fail -} diff --git a/tests/codegen/deduced-param-attrs.rs b/tests/codegen/deduced-param-attrs.rs index 22db090d4d889..34504c80fad1b 100644 --- a/tests/codegen/deduced-param-attrs.rs +++ b/tests/codegen/deduced-param-attrs.rs @@ -1,8 +1,8 @@ //@ compile-flags: -Copt-level=3 #![crate_type = "lib"] -#![allow(incomplete_features)] -#![feature(unsized_locals, unsized_fn_params)] +#![allow(internal_features)] +#![feature(unsized_fn_params)] use std::cell::Cell; use std::hint; diff --git a/tests/codegen/virtual-function-elimination.rs b/tests/codegen/virtual-function-elimination.rs index d2d0c4b78abd1..26604478c11a2 100644 --- a/tests/codegen/virtual-function-elimination.rs +++ b/tests/codegen/virtual-function-elimination.rs @@ -6,8 +6,6 @@ // CHECK: @vtable.2 = {{.*}}, !type ![[TYPE2:[0-9]+]], !vcall_visibility ![[VCALL_VIS2:[0-9]+]] #![crate_type = "lib"] -#![allow(incomplete_features)] -#![feature(unsized_locals)] use std::rc::Rc; diff --git a/tests/crashes/79409.rs b/tests/crashes/79409.rs deleted file mode 100644 index 98b5f60633627..0000000000000 --- a/tests/crashes/79409.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: #79409 - -#![feature(extern_types)] -#![feature(unsized_locals)] - -extern { - type Device; -} - -unsafe fn make_device() -> Box { - Box::from_raw(0 as *mut _) -} - -fn main() { - let d: Device = unsafe { *make_device() }; -} diff --git a/tests/rustdoc-ui/extract-doctests-result.rs b/tests/rustdoc-ui/extract-doctests-result.rs new file mode 100644 index 0000000000000..88affb6d33316 --- /dev/null +++ b/tests/rustdoc-ui/extract-doctests-result.rs @@ -0,0 +1,11 @@ +// Test to ensure that it generates expected output for `--output-format=doctest` command-line +// flag. + +//@ compile-flags:-Z unstable-options --output-format=doctest +//@ normalize-stdout: "tests/rustdoc-ui" -> "$$DIR" +//@ check-pass + +//! ``` +//! let x = 12; +//! Ok(()) +//! ``` diff --git a/tests/rustdoc-ui/extract-doctests-result.stdout b/tests/rustdoc-ui/extract-doctests-result.stdout new file mode 100644 index 0000000000000..44e6d33c66268 --- /dev/null +++ b/tests/rustdoc-ui/extract-doctests-result.stdout @@ -0,0 +1 @@ +{"format_version":2,"doctests":[{"file":"$DIR/extract-doctests-result.rs","line":8,"doctest_attributes":{"original":"","should_panic":false,"no_run":false,"ignore":"None","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nOk(())","doctest_code":{"crate_level":"#![allow(unused)]\n","code":"let x = 12;\nOk(())","wrapper":{"before":"fn main() { fn _inner() -> core::result::Result<(), impl core::fmt::Debug> {\n","after":"\n} _inner().unwrap() }","returns_result":true}},"name":"$DIR/extract-doctests-result.rs - (line 8)"}]} \ No newline at end of file diff --git a/tests/rustdoc-ui/extract-doctests.stdout b/tests/rustdoc-ui/extract-doctests.stdout index b11531b844ee4..796ecd82f1c93 100644 --- a/tests/rustdoc-ui/extract-doctests.stdout +++ b/tests/rustdoc-ui/extract-doctests.stdout @@ -1 +1 @@ -{"format_version":1,"doctests":[{"file":"$DIR/extract-doctests.rs","line":8,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":"#![allow(unused)]\nfn main() {\nlet x = 12;\nlet y = 14;\n}","name":"$DIR/extract-doctests.rs - (line 8)"},{"file":"$DIR/extract-doctests.rs","line":13,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":null,"name":"$DIR/extract-doctests.rs - (line 13)"}]} \ No newline at end of file +{"format_version":2,"doctests":[{"file":"$DIR/extract-doctests.rs","line":8,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":{"crate_level":"#![allow(unused)]\n","code":"let x = 12;\nlet y = 14;","wrapper":{"before":"fn main() {\n","after":"\n}","returns_result":false}},"name":"$DIR/extract-doctests.rs - (line 8)"},{"file":"$DIR/extract-doctests.rs","line":13,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":null,"name":"$DIR/extract-doctests.rs - (line 13)"}]} \ No newline at end of file diff --git a/tests/ui/associated-types/associated-type-call.fixed b/tests/ui/associated-types/associated-type-call.fixed new file mode 100644 index 0000000000000..d450b3b82c96f --- /dev/null +++ b/tests/ui/associated-types/associated-type-call.fixed @@ -0,0 +1,22 @@ +// issue: +// +//@ run-rustfix +#![allow(unused)] +struct T(); + +trait Trait { + type Assoc; + + fn f(); +} + +impl Trait for () { + type Assoc = T; + + fn f() { + T(); + //~^ ERROR no associated item named `Assoc` found for unit type `()` in the current scope + } +} + +fn main() {} diff --git a/tests/ui/associated-types/associated-type-call.rs b/tests/ui/associated-types/associated-type-call.rs new file mode 100644 index 0000000000000..ffe540c329eb9 --- /dev/null +++ b/tests/ui/associated-types/associated-type-call.rs @@ -0,0 +1,22 @@ +// issue: +// +//@ run-rustfix +#![allow(unused)] +struct T(); + +trait Trait { + type Assoc; + + fn f(); +} + +impl Trait for () { + type Assoc = T; + + fn f() { + ::Assoc(); + //~^ ERROR no associated item named `Assoc` found for unit type `()` in the current scope + } +} + +fn main() {} diff --git a/tests/ui/associated-types/associated-type-call.stderr b/tests/ui/associated-types/associated-type-call.stderr new file mode 100644 index 0000000000000..eaef775e30406 --- /dev/null +++ b/tests/ui/associated-types/associated-type-call.stderr @@ -0,0 +1,15 @@ +error[E0599]: no associated item named `Assoc` found for unit type `()` in the current scope + --> $DIR/associated-type-call.rs:17:17 + | +LL | ::Assoc(); + | ^^^^^ associated item not found in `()` + | +help: to construct a value of type `T`, use the explicit path + | +LL - ::Assoc(); +LL + T(); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/associated-types/associated-types-unsized.stderr b/tests/ui/associated-types/associated-types-unsized.stderr index e46b2a394640b..5a55e0341c1a2 100644 --- a/tests/ui/associated-types/associated-types-unsized.stderr +++ b/tests/ui/associated-types/associated-types-unsized.stderr @@ -6,7 +6,6 @@ LL | let x = t.get(); | = help: the trait `Sized` is not implemented for `::Value` = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider further restricting the associated type | LL | fn foo(t: T) where ::Value: Sized { diff --git a/tests/ui/async-await/awaiting-unsized-param.rs b/tests/ui/async-await/awaiting-unsized-param.rs index 45611eae41f5c..d957e5bd9b7c9 100644 --- a/tests/ui/async-await/awaiting-unsized-param.rs +++ b/tests/ui/async-await/awaiting-unsized-param.rs @@ -1,12 +1,11 @@ //@ edition: 2021 -#![feature(unsized_fn_params, unsized_locals)] -//~^ WARN the feature `unsized_locals` is incomplete +#![feature(unsized_fn_params)] use std::future::Future; async fn bug(mut f: dyn Future + Unpin) -> T { - //~^ ERROR the size for values of type `(dyn Future + Unpin + 'static)` cannot be known at compilation time + //~^ ERROR the size for values of type `dyn Future + Unpin` cannot be known at compilation time (&mut f).await } diff --git a/tests/ui/async-await/awaiting-unsized-param.stderr b/tests/ui/async-await/awaiting-unsized-param.stderr index 0104736976d5d..bcb0bcdf71ae4 100644 --- a/tests/ui/async-await/awaiting-unsized-param.stderr +++ b/tests/ui/async-await/awaiting-unsized-param.stderr @@ -1,21 +1,12 @@ -warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/awaiting-unsized-param.rs:3:31 - | -LL | #![feature(unsized_fn_params, unsized_locals)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #48055 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0277]: the size for values of type `(dyn Future + Unpin + 'static)` cannot be known at compilation time - --> $DIR/awaiting-unsized-param.rs:8:17 +error[E0277]: the size for values of type `dyn Future + Unpin` cannot be known at compilation time + --> $DIR/awaiting-unsized-param.rs:7:17 | LL | async fn bug(mut f: dyn Future + Unpin) -> T { | ^^^^^ doesn't have a size known at compile-time | - = help: the trait `Sized` is not implemented for `(dyn Future + Unpin + 'static)` - = note: all values captured by value by a closure must have a statically known size + = help: the trait `Sized` is not implemented for `dyn Future + Unpin` + = note: all local variables must have a statically known size -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/async-await/unsized-across-await.rs b/tests/ui/async-await/unsized-across-await.rs index b6bd5567fb221..3e8d58d42438b 100644 --- a/tests/ui/async-await/unsized-across-await.rs +++ b/tests/ui/async-await/unsized-across-await.rs @@ -1,8 +1,5 @@ //@ edition: 2021 -#![feature(unsized_locals)] -//~^ WARN the feature `unsized_locals` is incomplete - async fn f() {} async fn g(x: Box) { diff --git a/tests/ui/async-await/unsized-across-await.stderr b/tests/ui/async-await/unsized-across-await.stderr index 5bb2b7f479177..f06c390ae1684 100644 --- a/tests/ui/async-await/unsized-across-await.stderr +++ b/tests/ui/async-await/unsized-across-await.stderr @@ -1,21 +1,17 @@ -warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/unsized-across-await.rs:3:12 - | -LL | #![feature(unsized_locals)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #48055 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0277]: the size for values of type `dyn std::fmt::Display` cannot be known at compilation time - --> $DIR/unsized-across-await.rs:9:9 + --> $DIR/unsized-across-await.rs:6:9 | LL | let _x = *x; | ^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn std::fmt::Display` - = note: all values live across `await` must have a statically known size + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let _x = *x; +LL + let _x = x; + | -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs index 58370bff2200e..1e0576b21866b 100644 --- a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs +++ b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.rs @@ -1,15 +1,15 @@ //@ only-x86_64 fn efiapi(f: extern "efiapi" fn(usize, ...)) { - //~^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable + //~^ ERROR: unstable f(22, 44); } fn sysv(f: extern "sysv64" fn(usize, ...)) { - //~^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable + //~^ ERROR: unstable f(22, 44); } fn win(f: extern "win64" fn(usize, ...)) { - //~^ ERROR: using calling conventions other than `C` or `cdecl` for varargs functions is unstable + //~^ ERROR: unstable f(22, 44); } diff --git a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr index 9565575dc4279..7ef54b639ad2b 100644 --- a/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr +++ b/tests/ui/c-variadic/feature-gate-extended_varargs_abi_support.stderr @@ -1,4 +1,4 @@ -error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable +error[E0658]: C-variadic functions with the "efiapi" calling convention are unstable --> $DIR/feature-gate-extended_varargs_abi_support.rs:3:14 | LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { @@ -8,7 +8,7 @@ LL | fn efiapi(f: extern "efiapi" fn(usize, ...)) { = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable +error[E0658]: C-variadic functions with the "sysv64" calling convention are unstable --> $DIR/feature-gate-extended_varargs_abi_support.rs:7:12 | LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { @@ -18,7 +18,7 @@ LL | fn sysv(f: extern "sysv64" fn(usize, ...)) { = help: add `#![feature(extended_varargs_abi_support)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable +error[E0658]: C-variadic functions with the "win64" calling convention are unstable --> $DIR/feature-gate-extended_varargs_abi_support.rs:11:11 | LL | fn win(f: extern "win64" fn(usize, ...)) { diff --git a/tests/ui/c-variadic/variadic-ffi-1.rs b/tests/ui/c-variadic/variadic-ffi-1.rs index 9dcd55d13e3c7..cd8f2a951ef89 100644 --- a/tests/ui/c-variadic/variadic-ffi-1.rs +++ b/tests/ui/c-variadic/variadic-ffi-1.rs @@ -9,8 +9,7 @@ use minicore::*; extern "stdcall" { fn printf(_: *const u8, ...); - //~^ ERROR: C-variadic function must have a compatible calling convention, - // like C, cdecl, win64, sysv64 or efiapi + //~^ ERROR: C-variadic functions with the "stdcall" calling convention are not supported } extern "C" { diff --git a/tests/ui/c-variadic/variadic-ffi-1.stderr b/tests/ui/c-variadic/variadic-ffi-1.stderr index f99abed0a625f..a49fc0ce12603 100644 --- a/tests/ui/c-variadic/variadic-ffi-1.stderr +++ b/tests/ui/c-variadic/variadic-ffi-1.stderr @@ -1,17 +1,17 @@ -error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` +error[E0045]: C-variadic functions with the "stdcall" calling convention are not supported --> $DIR/variadic-ffi-1.rs:11:5 | LL | fn printf(_: *const u8, ...); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied - --> $DIR/variadic-ffi-1.rs:24:9 + --> $DIR/variadic-ffi-1.rs:23:9 | LL | foo(); | ^^^-- two arguments of type `isize` and `u8` are missing | note: function defined here - --> $DIR/variadic-ffi-1.rs:17:8 + --> $DIR/variadic-ffi-1.rs:16:8 | LL | fn foo(f: isize, x: u8, ...); | ^^^ - - @@ -21,13 +21,13 @@ LL | foo(/* isize */, /* u8 */); | +++++++++++++++++++++ error[E0060]: this function takes at least 2 arguments but 1 argument was supplied - --> $DIR/variadic-ffi-1.rs:25:9 + --> $DIR/variadic-ffi-1.rs:24:9 | LL | foo(1); | ^^^--- argument #2 of type `u8` is missing | note: function defined here - --> $DIR/variadic-ffi-1.rs:17:8 + --> $DIR/variadic-ffi-1.rs:16:8 | LL | fn foo(f: isize, x: u8, ...); | ^^^ - @@ -37,7 +37,7 @@ LL | foo(1, /* u8 */); | ++++++++++ error[E0308]: mismatched types - --> $DIR/variadic-ffi-1.rs:27:56 + --> $DIR/variadic-ffi-1.rs:26:56 | LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo; | ------------------------------------- ^^^ expected non-variadic fn, found variadic function @@ -48,7 +48,7 @@ LL | let x: unsafe extern "C" fn(f: isize, x: u8) = foo; found fn item `unsafe extern "C" fn(_, _, ...) {foo}` error[E0308]: mismatched types - --> $DIR/variadic-ffi-1.rs:28:54 + --> $DIR/variadic-ffi-1.rs:27:54 | LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar; | ----------------------------------- ^^^ expected variadic fn, found non-variadic function @@ -59,7 +59,7 @@ LL | let y: extern "C" fn(f: isize, x: u8, ...) = bar; found fn item `extern "C" fn(_, _) {bar}` error[E0617]: can't pass `f32` to variadic function - --> $DIR/variadic-ffi-1.rs:30:19 + --> $DIR/variadic-ffi-1.rs:29:19 | LL | foo(1, 2, 3f32); | ^^^^ @@ -70,7 +70,7 @@ LL | foo(1, 2, 3f32 as c_double); | +++++++++++ error[E0617]: can't pass `bool` to variadic function - --> $DIR/variadic-ffi-1.rs:31:19 + --> $DIR/variadic-ffi-1.rs:30:19 | LL | foo(1, 2, true); | ^^^^ @@ -81,7 +81,7 @@ LL | foo(1, 2, true as c_int); | ++++++++ error[E0617]: can't pass `i8` to variadic function - --> $DIR/variadic-ffi-1.rs:32:19 + --> $DIR/variadic-ffi-1.rs:31:19 | LL | foo(1, 2, 1i8); | ^^^ @@ -92,7 +92,7 @@ LL | foo(1, 2, 1i8 as c_int); | ++++++++ error[E0617]: can't pass `u8` to variadic function - --> $DIR/variadic-ffi-1.rs:33:19 + --> $DIR/variadic-ffi-1.rs:32:19 | LL | foo(1, 2, 1u8); | ^^^ @@ -103,7 +103,7 @@ LL | foo(1, 2, 1u8 as c_uint); | +++++++++ error[E0617]: can't pass `i16` to variadic function - --> $DIR/variadic-ffi-1.rs:34:19 + --> $DIR/variadic-ffi-1.rs:33:19 | LL | foo(1, 2, 1i16); | ^^^^ @@ -114,7 +114,7 @@ LL | foo(1, 2, 1i16 as c_int); | ++++++++ error[E0617]: can't pass `u16` to variadic function - --> $DIR/variadic-ffi-1.rs:35:19 + --> $DIR/variadic-ffi-1.rs:34:19 | LL | foo(1, 2, 1u16); | ^^^^ diff --git a/tests/ui/c-variadic/variadic-ffi-2.rs b/tests/ui/c-variadic/variadic-ffi-2.rs index da7bb76fc14bf..adfd9bfa27962 100644 --- a/tests/ui/c-variadic/variadic-ffi-2.rs +++ b/tests/ui/c-variadic/variadic-ffi-2.rs @@ -1,8 +1,7 @@ #![feature(extended_varargs_abi_support)] fn baz(f: extern "Rust" fn(usize, ...)) { - //~^ ERROR: C-variadic function must have a compatible calling convention, - // like C, cdecl, system, aapcs, win64, sysv64 or efiapi + //~^ ERROR: C-variadic functions with the "Rust" calling convention are not supported f(22, 44); } diff --git a/tests/ui/c-variadic/variadic-ffi-2.stderr b/tests/ui/c-variadic/variadic-ffi-2.stderr index 9f8dcefdb0338..2ac0a9f5ea2cf 100644 --- a/tests/ui/c-variadic/variadic-ffi-2.stderr +++ b/tests/ui/c-variadic/variadic-ffi-2.stderr @@ -1,4 +1,4 @@ -error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` +error[E0045]: C-variadic functions with the "Rust" calling convention are not supported --> $DIR/variadic-ffi-2.rs:3:11 | LL | fn baz(f: extern "Rust" fn(usize, ...)) { diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs index 18041b0806170..84080890e0802 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs @@ -38,4 +38,4 @@ type WithTransparentTraitObject = //~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798] type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...); -//~^ ERROR C-variadic function must have a compatible calling convention, like `C` +//~^ ERROR C-variadic functions with the "C-cmse-nonsecure-call" calling convention are not supported diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr index ab7c9cee4f03b..2b51f48915b30 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr @@ -69,7 +69,7 @@ LL | extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTranspa = note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size -error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` +error[E0045]: C-variadic functions with the "C-cmse-nonsecure-call" calling convention are not supported --> $DIR/generics.rs:40:20 | LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...); diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs index 29474c7632038..28facc1888600 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.rs @@ -18,7 +18,7 @@ const B: *mut i32 = &mut 4; //~ ERROR mutable references are not allowed const B2: Option<&mut i32> = None; // Not ok, can't prove that no mutable allocation ends up in final value -const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR temporary value dropped while borrowed +const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR mutable references are not allowed const fn helper(x: &mut i32) -> Option<&mut i32> { Some(x) } const B4: Option<&mut i32> = helper(&mut 42); //~ ERROR temporary value dropped while borrowed diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr index 834ea3410f6fb..122e5c1bdf0ae 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final.stderr @@ -4,15 +4,11 @@ error[E0764]: mutable references are not allowed in the final value of constants LL | const B: *mut i32 = &mut 4; | ^^^^^^ -error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final.rs:21:40 +error[E0764]: mutable references are not allowed in the final value of constants + --> $DIR/mut_ref_in_final.rs:21:35 | LL | const B3: Option<&mut i32> = Some(&mut 42); - | ----------^^- - | | | | - | | | temporary value is freed at the end of this statement - | | creates a temporary value which is freed while still in use - | using this value as a constant requires that borrow lasts for `'static` + | ^^^^^^^ error[E0716]: temporary value dropped while borrowed --> $DIR/mut_ref_in_final.rs:24:42 diff --git a/tests/ui/consts/issue-54224.rs b/tests/ui/consts/issue-54224.rs deleted file mode 100644 index f1947933d6707..0000000000000 --- a/tests/ui/consts/issue-54224.rs +++ /dev/null @@ -1,12 +0,0 @@ -const FOO: Option<&[[u8; 3]]> = Some(&[*b"foo"]); //~ ERROR temporary value dropped while borrowed - -use std::borrow::Cow; - -pub const X: [u8; 3] = *b"ABC"; -pub const Y: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[X]); - - -pub const Z: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[*b"ABC"]); -//~^ ERROR temporary value dropped while borrowed - -fn main() {} diff --git a/tests/ui/consts/issue-54224.stderr b/tests/ui/consts/issue-54224.stderr deleted file mode 100644 index 55fe55759df54..0000000000000 --- a/tests/ui/consts/issue-54224.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0716]: temporary value dropped while borrowed - --> $DIR/issue-54224.rs:1:39 - | -LL | const FOO: Option<&[[u8; 3]]> = Some(&[*b"foo"]); - | ------^^^^^^^^^- - | | | | - | | | temporary value is freed at the end of this statement - | | creates a temporary value which is freed while still in use - | using this value as a constant requires that borrow lasts for `'static` - -error[E0716]: temporary value dropped while borrowed - --> $DIR/issue-54224.rs:9:57 - | -LL | pub const Z: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[*b"ABC"]); - | ---------------^^^^^^^^^- - | | | | - | | | temporary value is freed at the end of this statement - | | creates a temporary value which is freed while still in use - | using this value as a constant requires that borrow lasts for `'static` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/consts/promote-not.rs b/tests/ui/consts/promote-not.rs index 207baccd6abb5..74e0efb858aa0 100644 --- a/tests/ui/consts/promote-not.rs +++ b/tests/ui/consts/promote-not.rs @@ -3,10 +3,11 @@ #![allow(unconditional_panic)] use std::cell::Cell; +use std::convert::identity; use std::mem::ManuallyDrop; // We do not promote mutable references. -static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); //~ ERROR temporary value dropped while borrowed +static mut TEST1: &mut [i32] = identity(&mut [1, 2, 3]); //~ ERROR temporary value dropped while borrowed static mut TEST2: &'static mut [i32] = { let x = &mut [1,2,3]; //~ ERROR temporary value dropped while borrowed diff --git a/tests/ui/consts/promote-not.stderr b/tests/ui/consts/promote-not.stderr index d8b6091dc9aab..ec552d9dd7d48 100644 --- a/tests/ui/consts/promote-not.stderr +++ b/tests/ui/consts/promote-not.stderr @@ -1,15 +1,15 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:9:50 + --> $DIR/promote-not.rs:10:46 | -LL | static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); - | ----------^^^^^^^^^- - | | | | - | | | temporary value is freed at the end of this statement - | | creates a temporary value which is freed while still in use - | using this value as a static requires that borrow lasts for `'static` +LL | static mut TEST1: &mut [i32] = identity(&mut [1, 2, 3]); + | --------------^^^^^^^^^- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary value which is freed while still in use + | using this value as a static requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:12:18 + --> $DIR/promote-not.rs:13:18 | LL | let x = &mut [1,2,3]; | ^^^^^^^ creates a temporary value which is freed while still in use @@ -19,7 +19,7 @@ LL | }; | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:34:29 + --> $DIR/promote-not.rs:35:29 | LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x }; | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -29,7 +29,7 @@ LL | }; | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:40:29 + --> $DIR/promote-not.rs:41:29 | LL | let _val: &'static _ = &(Cell::new(1), 2).1; | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -39,7 +39,7 @@ LL | }; | - temporary value is freed at the end of this statement error[E0493]: destructor of `String` cannot be evaluated at compile-time - --> $DIR/promote-not.rs:47:14 + --> $DIR/promote-not.rs:48:14 | LL | let x = &String::new(); | ^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants @@ -48,7 +48,7 @@ LL | }; | - value is dropped here error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:59:33 + --> $DIR/promote-not.rs:60:33 | LL | let _x: &'static u32 = &mk_panic(); | ------------ ^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -58,7 +58,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:21:32 + --> $DIR/promote-not.rs:22:32 | LL | let _x: &'static () = &foo(); | ----------- ^^^^^ creates a temporary value which is freed while still in use @@ -68,7 +68,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:29:29 + --> $DIR/promote-not.rs:30:29 | LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x }; | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -78,7 +78,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:65:29 + --> $DIR/promote-not.rs:66:29 | LL | let _val: &'static _ = &(Cell::new(1), 2).0; | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -89,7 +89,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:66:29 + --> $DIR/promote-not.rs:67:29 | LL | let _val: &'static _ = &(Cell::new(1), 2).1; | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -100,7 +100,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:69:29 + --> $DIR/promote-not.rs:70:29 | LL | let _val: &'static _ = &(1/0); | ---------- ^^^^^ creates a temporary value which is freed while still in use @@ -111,7 +111,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:70:29 + --> $DIR/promote-not.rs:71:29 | LL | let _val: &'static _ = &(1/(1-1)); | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use @@ -122,7 +122,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:71:29 + --> $DIR/promote-not.rs:72:29 | LL | let _val: &'static _ = &((1+1)/(1-1)); | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -133,7 +133,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:72:29 + --> $DIR/promote-not.rs:73:29 | LL | let _val: &'static _ = &(i32::MIN/-1); | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -144,7 +144,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:73:29 + --> $DIR/promote-not.rs:74:29 | LL | let _val: &'static _ = &(i32::MIN/(0-1)); | ---------- ^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -155,7 +155,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:74:29 + --> $DIR/promote-not.rs:75:29 | LL | let _val: &'static _ = &(-128i8/-1); | ---------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -166,7 +166,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:75:29 + --> $DIR/promote-not.rs:76:29 | LL | let _val: &'static _ = &(1%0); | ---------- ^^^^^ creates a temporary value which is freed while still in use @@ -177,7 +177,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:76:29 + --> $DIR/promote-not.rs:77:29 | LL | let _val: &'static _ = &(1%(1-1)); | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use @@ -188,7 +188,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:77:29 + --> $DIR/promote-not.rs:78:29 | LL | let _val: &'static _ = &([1,2,3][4]+1); | ---------- ^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -199,7 +199,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:81:29 + --> $DIR/promote-not.rs:82:29 | LL | let _val: &'static _ = &TEST_DROP; | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use @@ -210,7 +210,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:83:29 + --> $DIR/promote-not.rs:84:29 | LL | let _val: &'static _ = &&TEST_DROP; | ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -221,7 +221,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:83:30 + --> $DIR/promote-not.rs:84:30 | LL | let _val: &'static _ = &&TEST_DROP; | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use @@ -232,7 +232,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:86:29 + --> $DIR/promote-not.rs:87:29 | LL | let _val: &'static _ = &(&TEST_DROP,); | ---------- ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -243,7 +243,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:86:31 + --> $DIR/promote-not.rs:87:31 | LL | let _val: &'static _ = &(&TEST_DROP,); | ---------- ^^^^^^^^^ creates a temporary value which is freed while still in use @@ -254,7 +254,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:89:29 + --> $DIR/promote-not.rs:90:29 | LL | let _val: &'static _ = &[&TEST_DROP; 1]; | ---------- ^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use @@ -265,7 +265,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:89:31 + --> $DIR/promote-not.rs:90:31 | LL | let _val: &'static _ = &[&TEST_DROP; 1]; | ---------- ^^^^^^^^^ - temporary value is freed at the end of this statement @@ -274,7 +274,7 @@ LL | let _val: &'static _ = &[&TEST_DROP; 1]; | type annotation requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:98:26 + --> $DIR/promote-not.rs:99:26 | LL | let x: &'static _ = &UnionWithCell { f1: 0 }; | ---------- ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use diff --git a/tests/ui/coroutine/auto-trait-regions.rs b/tests/ui/coroutine/auto-trait-regions.rs index 1c7f0304ddbec..f115896a473cd 100644 --- a/tests/ui/coroutine/auto-trait-regions.rs +++ b/tests/ui/coroutine/auto-trait-regions.rs @@ -43,8 +43,8 @@ fn main() { // Disallow impls which relates lifetimes in the coroutine interior let gen = #[coroutine] move || { let a = A(&mut true, &mut true, No); - //~^ ERROR temporary value dropped while borrowed - //~| ERROR temporary value dropped while borrowed + //~^ ERROR borrow may still be in use when coroutine yields + //~| ERROR borrow may still be in use when coroutine yields yield; assert_foo(a); }; diff --git a/tests/ui/coroutine/auto-trait-regions.stderr b/tests/ui/coroutine/auto-trait-regions.stderr index a3b5a5f006e61..77b5f3ce57c4a 100644 --- a/tests/ui/coroutine/auto-trait-regions.stderr +++ b/tests/ui/coroutine/auto-trait-regions.stderr @@ -1,36 +1,34 @@ -error[E0716]: temporary value dropped while borrowed - --> $DIR/auto-trait-regions.rs:45:24 +error[E0626]: borrow may still be in use when coroutine yields + --> $DIR/auto-trait-regions.rs:45:19 | +LL | let gen = #[coroutine] move || { + | ------- within this coroutine LL | let a = A(&mut true, &mut true, No); - | ^^^^ - temporary value is freed at the end of this statement - | | - | creates a temporary value which is freed while still in use + | ^^^^^^^^^ ... -LL | assert_foo(a); - | - borrow later used here +LL | yield; + | ----- possible yield occurs here | -help: consider using a `let` binding to create a longer lived value - | -LL ~ let mut binding = true; -LL ~ let a = A(&mut binding, &mut true, No); +help: add `static` to mark this coroutine as unmovable | +LL | let gen = #[coroutine] static move || { + | ++++++ -error[E0716]: temporary value dropped while borrowed - --> $DIR/auto-trait-regions.rs:45:35 +error[E0626]: borrow may still be in use when coroutine yields + --> $DIR/auto-trait-regions.rs:45:30 | +LL | let gen = #[coroutine] move || { + | ------- within this coroutine LL | let a = A(&mut true, &mut true, No); - | ^^^^ - temporary value is freed at the end of this statement - | | - | creates a temporary value which is freed while still in use + | ^^^^^^^^^ ... -LL | assert_foo(a); - | - borrow later used here - | -help: consider using a `let` binding to create a longer lived value +LL | yield; + | ----- possible yield occurs here | -LL ~ let mut binding = true; -LL ~ let a = A(&mut true, &mut binding, No); +help: add `static` to mark this coroutine as unmovable | +LL | let gen = #[coroutine] static move || { + | ++++++ error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:31:5 @@ -52,4 +50,4 @@ LL | assert_foo(gen); error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0716`. +For more information about this error, try `rustc --explain E0626`. diff --git a/tests/ui/coroutine/unsized-capture-across-yield.rs b/tests/ui/coroutine/unsized-capture-across-yield.rs index c86b1823aafff..ee27ea064ec23 100644 --- a/tests/ui/coroutine/unsized-capture-across-yield.rs +++ b/tests/ui/coroutine/unsized-capture-across-yield.rs @@ -1,16 +1,13 @@ #![feature(coroutine_trait)] #![feature(coroutines)] -#![feature(unsized_locals)] -//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes use std::ops::Coroutine; fn capture() -> impl Coroutine { - let b: [u8] = *(Box::new([]) as Box<[u8]>); + let b: [u8] = *(Box::new([]) as Box<[u8]>); //~ERROR he size for values of type `[u8]` cannot be known at compilation time #[coroutine] move || { println!("{:?}", &b); - //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time yield; diff --git a/tests/ui/coroutine/unsized-capture-across-yield.stderr b/tests/ui/coroutine/unsized-capture-across-yield.stderr index 03551f1bbff51..c46c08ff53e8c 100644 --- a/tests/ui/coroutine/unsized-capture-across-yield.stderr +++ b/tests/ui/coroutine/unsized-capture-across-yield.stderr @@ -1,23 +1,16 @@ -warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/unsized-capture-across-yield.rs:3:12 - | -LL | #![feature(unsized_locals)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #48055 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/unsized-capture-across-yield.rs:12:27 + --> $DIR/unsized-capture-across-yield.rs:7:9 | -LL | move || { - | -- this closure captures all values by move -LL | println!("{:?}", &b); - | ^ doesn't have a size known at compile-time +LL | let b: [u8] = *(Box::new([]) as Box<[u8]>); + | ^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` - = note: all values captured by value by a closure must have a statically known size + = note: all local variables must have a statically known size +help: consider borrowing here + | +LL | let b: &[u8] = *(Box::new([]) as Box<[u8]>); + | + -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/coroutine/unsized-local-across-yield.rs b/tests/ui/coroutine/unsized-local-across-yield.rs index cb8ced13a111a..4c688e5b99790 100644 --- a/tests/ui/coroutine/unsized-local-across-yield.rs +++ b/tests/ui/coroutine/unsized-local-across-yield.rs @@ -1,7 +1,5 @@ #![feature(coroutine_trait)] #![feature(coroutines)] -#![feature(unsized_locals)] -//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes use std::ops::Coroutine; diff --git a/tests/ui/coroutine/unsized-local-across-yield.stderr b/tests/ui/coroutine/unsized-local-across-yield.stderr index 4fe0f135a9d62..fd6cd4676c2b2 100644 --- a/tests/ui/coroutine/unsized-local-across-yield.stderr +++ b/tests/ui/coroutine/unsized-local-across-yield.stderr @@ -1,21 +1,16 @@ -warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/unsized-local-across-yield.rs:3:12 - | -LL | #![feature(unsized_locals)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #48055 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/unsized-local-across-yield.rs:11:13 + --> $DIR/unsized-local-across-yield.rs:9:13 | LL | let b: [u8] = *(Box::new([]) as Box<[u8]>); | ^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` - = note: all values live across `yield` must have a statically known size + = note: all local variables must have a statically known size +help: consider borrowing here + | +LL | let b: &[u8] = *(Box::new([]) as Box<[u8]>); + | + -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/error-codes/E0045.stderr b/tests/ui/error-codes/E0045.stderr index b8ee31a40495a..ecf5f4e0182eb 100644 --- a/tests/ui/error-codes/E0045.stderr +++ b/tests/ui/error-codes/E0045.stderr @@ -1,4 +1,4 @@ -error[E0045]: C-variadic function must have a compatible calling convention, like `C`, `cdecl`, `system`, `aapcs`, `win64`, `sysv64` or `efiapi` +error[E0045]: C-variadic functions with the "Rust" calling convention are not supported --> $DIR/E0045.rs:1:17 | LL | extern "Rust" { fn foo(x: u8, ...); } diff --git a/tests/ui/error-codes/E0161.rs b/tests/ui/error-codes/E0161.rs index 3a9b93d24303f..1ae2a67d60e9a 100644 --- a/tests/ui/error-codes/E0161.rs +++ b/tests/ui/error-codes/E0161.rs @@ -1,12 +1,7 @@ // Check that E0161 is a hard error in all possible configurations that might // affect it. -//@ revisions: base ul -//@[base] check-fail -//@[ul] check-pass - -#![allow(incomplete_features)] -#![cfg_attr(ul, feature(unsized_locals))] +#![crate_type = "lib"] trait Bar { fn f(self); @@ -14,7 +9,5 @@ trait Bar { fn foo(x: Box) { x.f(); - //[base]~^ ERROR E0161 + //~^ ERROR E0161 } - -fn main() {} diff --git a/tests/ui/error-codes/E0161.base.stderr b/tests/ui/error-codes/E0161.stderr similarity index 90% rename from tests/ui/error-codes/E0161.base.stderr rename to tests/ui/error-codes/E0161.stderr index d80de66b24733..f84f348459bf1 100644 --- a/tests/ui/error-codes/E0161.base.stderr +++ b/tests/ui/error-codes/E0161.stderr @@ -1,5 +1,5 @@ error[E0161]: cannot move a value of type `dyn Bar` - --> $DIR/E0161.rs:16:5 + --> $DIR/E0161.rs:11:5 | LL | x.f(); | ^ the size of `dyn Bar` cannot be statically determined diff --git a/tests/ui/extern/unsized-extern-derefmove.rs b/tests/ui/extern/unsized-extern-derefmove.rs new file mode 100644 index 0000000000000..4ec9e53f49d87 --- /dev/null +++ b/tests/ui/extern/unsized-extern-derefmove.rs @@ -0,0 +1,15 @@ +//! Regression test for #79409 + +#![feature(extern_types)] + +unsafe extern "C" { + type Device; +} + +unsafe fn make_device() -> Box { + Box::from_raw(0 as *mut _) +} + +fn main() { + let d: Device = unsafe { *make_device() }; //~ERROR the size for values of type `Device` cannot be known at compilation time +} diff --git a/tests/ui/extern/unsized-extern-derefmove.stderr b/tests/ui/extern/unsized-extern-derefmove.stderr new file mode 100644 index 0000000000000..c43184d94e177 --- /dev/null +++ b/tests/ui/extern/unsized-extern-derefmove.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `Device` cannot be known at compilation time + --> $DIR/unsized-extern-derefmove.rs:14:9 + | +LL | let d: Device = unsafe { *make_device() }; + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `Device` + = note: all local variables must have a statically known size +help: consider borrowing here + | +LL | let d: &Device = unsafe { *make_device() }; + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/feature-gates/feature-gate-extern_system_varargs.rs b/tests/ui/feature-gates/feature-gate-extern_system_varargs.rs index f5cfbe72ca8db..2206776cccac1 100644 --- a/tests/ui/feature-gates/feature-gate-extern_system_varargs.rs +++ b/tests/ui/feature-gates/feature-gate-extern_system_varargs.rs @@ -1,5 +1,5 @@ fn system(f: extern "system" fn(usize, ...)) { - //~^ ERROR using calling conventions other than `C` or `cdecl` for varargs functions is unstable + //~^ ERROR unstable f(22, 44); } diff --git a/tests/ui/feature-gates/feature-gate-extern_system_varargs.stderr b/tests/ui/feature-gates/feature-gate-extern_system_varargs.stderr index f3206b25264e0..1209275f719c0 100644 --- a/tests/ui/feature-gates/feature-gate-extern_system_varargs.stderr +++ b/tests/ui/feature-gates/feature-gate-extern_system_varargs.stderr @@ -1,4 +1,4 @@ -error[E0658]: using calling conventions other than `C` or `cdecl` for varargs functions is unstable +error[E0658]: C-variadic functions with the "system" calling convention are unstable --> $DIR/feature-gate-extern_system_varargs.rs:1:14 | LL | fn system(f: extern "system" fn(usize, ...)) { diff --git a/tests/ui/issues/issue-15756.stderr b/tests/ui/issues/issue-15756.stderr index af50fe467d17c..a487d360bef98 100644 --- a/tests/ui/issues/issue-15756.stderr +++ b/tests/ui/issues/issue-15756.stderr @@ -6,7 +6,6 @@ LL | &mut something | = help: the trait `Sized` is not implemented for `[T]` = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature error: aborting due to 1 previous error diff --git a/tests/ui/iterators/collect-into-slice.stderr b/tests/ui/iterators/collect-into-slice.stderr index 56f1bf770607e..e5729a2badc71 100644 --- a/tests/ui/iterators/collect-into-slice.stderr +++ b/tests/ui/iterators/collect-into-slice.stderr @@ -16,7 +16,6 @@ LL | let some_generated_vec = (0..10).collect(); | = help: the trait `Sized` is not implemented for `[i32]` = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> $DIR/collect-into-slice.rs:6:38 diff --git a/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.rs b/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.rs new file mode 100644 index 0000000000000..bb537f855a4ab --- /dev/null +++ b/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.rs @@ -0,0 +1,36 @@ +//@ edition:2024 + +fn temp() -> String { + String::from("Hello") +} + +#[derive(Debug)] +struct X<'a>(&'a String); + +trait T<'a> { + const A: X<'a>; + const B: X<'a>; +} + +impl<'a> T<'a> for X<'a> { + // Check both Self() and X() syntax: + const A: X<'a> = Self(&String::new()); + const B: X<'a> = X(&String::new()); +} + +fn main() { + let a = &temp(); + let b = Some(&temp()); + let c = Option::Some::<&String>(&temp()); + use Option::Some as S; + let d = S(&temp()); + let e = X(&temp()); + let f = Some(Ok::<_, ()>(std::borrow::Cow::Borrowed(if true { + &temp() + } else { + panic!() + }))); + let some = Some; // Turn the ctor into a regular function. + let g = some(&temp()); //~ERROR temporary value dropped while borrowe + println!("{a:?} {b:?} {c:?} {d:?} {e:?} {f:?} {g:?}"); +} diff --git a/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.stderr b/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.stderr new file mode 100644 index 0000000000000..66f9140f63cff --- /dev/null +++ b/tests/ui/lifetimes/temporary-lifetime-extension-tuple-ctor.stderr @@ -0,0 +1,19 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/temporary-lifetime-extension-tuple-ctor.rs:34:19 + | +LL | let g = some(&temp()); + | ^^^^^^ - temporary value is freed at the end of this statement + | | + | creates a temporary value which is freed while still in use +LL | println!("{a:?} {b:?} {c:?} {d:?} {e:?} {f:?} {g:?}"); + | ----- borrow later used here + | +help: consider using a `let` binding to create a longer lived value + | +LL ~ let binding = temp(); +LL ~ let g = some(&binding); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0716`. diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs index 5ef1d0c6dc9b5..6ceec11930833 100644 --- a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs +++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs @@ -1,8 +1,7 @@ //@ dont-require-annotations: NOTE #![feature(arbitrary_self_types, coerce_unsized, dispatch_from_dyn, unsize)] -#![feature(unsized_locals, unsized_fn_params)] -//~^ WARN the feature `unsized_locals` is incomplete +#![feature(unsized_fn_params)] // This tests a few edge-cases around `arbitrary_self_types`. Most specifically, // it checks that the `ObjectCandidate` you get from method matching can't diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr index 213139a9b0b6d..32cff62284e09 100644 --- a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr +++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr @@ -1,14 +1,5 @@ -warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:4:12 - | -LL | #![feature(unsized_locals, unsized_fn_params)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #48055 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0308]: mismatched types - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:89:24 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:88:24 | LL | let _seetype: () = z; | -- ^ expected `()`, found `u32` @@ -16,7 +7,7 @@ LL | let _seetype: () = z; | expected due to this error[E0308]: mismatched types - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:106:24 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:105:24 | LL | let _seetype: () = z; | -- ^ expected `()`, found `u64` @@ -24,23 +15,23 @@ LL | let _seetype: () = z; | expected due to this error[E0034]: multiple applicable items in scope - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:124:15 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:123:15 | LL | let z = x.foo(); | ^^^ multiple `foo` found | note: candidate #1 is defined in the trait `FinalFoo` - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:61:5 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:60:5 | LL | fn foo(&self) -> u8; | ^^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `NuisanceFoo` for the type `T` - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:74:9 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:73:9 | LL | fn foo(self) {} | ^^^^^^^^^^^^ note: candidate #3 is defined in an impl of the trait `X` for the type `T` - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:47:9 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:46:9 | LL | fn foo(self: Smaht) -> u64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +52,7 @@ LL + let z = X::foo(x); | error[E0308]: mismatched types - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:141:24 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:140:24 | LL | let _seetype: () = z; | -- ^ expected `()`, found `u8` @@ -69,7 +60,7 @@ LL | let _seetype: () = z; | expected due to this error[E0308]: mismatched types - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:159:24 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:158:24 | LL | let _seetype: () = z; | -- ^ expected `()`, found `u32` @@ -77,14 +68,14 @@ LL | let _seetype: () = z; | expected due to this error[E0308]: mismatched types - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:176:24 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:175:24 | LL | let _seetype: () = z; | -- ^ expected `()`, found `u32` | | | expected due to this -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 6 previous errors Some errors have detailed explanations: E0034, E0308. For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/moves/move-out-of-slice-2.rs b/tests/ui/moves/move-out-of-slice-2.rs index 2f7394fbfd36c..6428dc4b711a6 100644 --- a/tests/ui/moves/move-out-of-slice-2.rs +++ b/tests/ui/moves/move-out-of-slice-2.rs @@ -1,5 +1,3 @@ -#![feature(unsized_locals)] -//~^ WARN the feature `unsized_locals` is incomplete #![allow(unused)] struct A; @@ -9,28 +7,24 @@ struct C; fn main() { let a: Box<[A]> = Box::new([A]); match *a { - //~^ ERROR cannot move out of type `[A]`, a non-copy slice - [a @ ..] => {} + [a @ ..] => {} //~ERROR the size for values of type `[A]` cannot be known at compilation time [E0277] _ => {} } let b: Box<[A]> = Box::new([A, A, A]); match *b { - //~^ ERROR cannot move out of type `[A]`, a non-copy slice - [_, _, b @ .., _] => {} + [_, _, b @ .., _] => {} //~ERROR the size for values of type `[A]` cannot be known at compilation time [E0277] _ => {} } // `[C]` isn't `Copy`, even if `C` is. let c: Box<[C]> = Box::new([C]); match *c { - //~^ ERROR cannot move out of type `[C]`, a non-copy slice - [c @ ..] => {} + [c @ ..] => {} //~ERROR the size for values of type `[C]` cannot be known at compilation time [E0277] _ => {} } let d: Box<[C]> = Box::new([C, C, C]); match *d { - //~^ ERROR cannot move out of type `[C]`, a non-copy slice - [_, _, d @ .., _] => {} + [_, _, d @ .., _] => {} //~ERROR the size for values of type `[C]` cannot be known at compilation time [E0277] _ => {} } } diff --git a/tests/ui/moves/move-out-of-slice-2.stderr b/tests/ui/moves/move-out-of-slice-2.stderr index b46854cd6b458..207194611c521 100644 --- a/tests/ui/moves/move-out-of-slice-2.stderr +++ b/tests/ui/moves/move-out-of-slice-2.stderr @@ -1,80 +1,39 @@ -warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/move-out-of-slice-2.rs:1:12 +error[E0277]: the size for values of type `[A]` cannot be known at compilation time + --> $DIR/move-out-of-slice-2.rs:10:10 | -LL | #![feature(unsized_locals)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #48055 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0508]: cannot move out of type `[A]`, a non-copy slice - --> $DIR/move-out-of-slice-2.rs:11:11 - | -LL | match *a { - | ^^ cannot move out of here -LL | LL | [a @ ..] => {} - | - - | | - | data moved here - | move occurs because `a` has type `[A]`, which does not implement the `Copy` trait - | -help: consider borrowing the pattern binding + | ^^^^^^ doesn't have a size known at compile-time | -LL | [ref a @ ..] => {} - | +++ + = help: the trait `Sized` is not implemented for `[A]` + = note: all local variables must have a statically known size -error[E0508]: cannot move out of type `[A]`, a non-copy slice - --> $DIR/move-out-of-slice-2.rs:17:11 +error[E0277]: the size for values of type `[A]` cannot be known at compilation time + --> $DIR/move-out-of-slice-2.rs:15:16 | -LL | match *b { - | ^^ cannot move out of here -LL | LL | [_, _, b @ .., _] => {} - | - - | | - | data moved here - | move occurs because `b` has type `[A]`, which does not implement the `Copy` trait + | ^^^^^^ doesn't have a size known at compile-time | -help: consider borrowing the pattern binding - | -LL | [_, _, ref b @ .., _] => {} - | +++ + = help: the trait `Sized` is not implemented for `[A]` + = note: all local variables must have a statically known size -error[E0508]: cannot move out of type `[C]`, a non-copy slice - --> $DIR/move-out-of-slice-2.rs:25:11 +error[E0277]: the size for values of type `[C]` cannot be known at compilation time + --> $DIR/move-out-of-slice-2.rs:22:10 | -LL | match *c { - | ^^ cannot move out of here -LL | LL | [c @ ..] => {} - | - - | | - | data moved here - | move occurs because `c` has type `[C]`, which does not implement the `Copy` trait - | -help: consider borrowing the pattern binding + | ^^^^^^ doesn't have a size known at compile-time | -LL | [ref c @ ..] => {} - | +++ + = help: the trait `Sized` is not implemented for `[C]` + = note: all local variables must have a statically known size -error[E0508]: cannot move out of type `[C]`, a non-copy slice - --> $DIR/move-out-of-slice-2.rs:31:11 +error[E0277]: the size for values of type `[C]` cannot be known at compilation time + --> $DIR/move-out-of-slice-2.rs:27:16 | -LL | match *d { - | ^^ cannot move out of here -LL | LL | [_, _, d @ .., _] => {} - | - - | | - | data moved here - | move occurs because `d` has type `[C]`, which does not implement the `Copy` trait - | -help: consider borrowing the pattern binding + | ^^^^^^ doesn't have a size known at compile-time | -LL | [_, _, ref d @ .., _] => {} - | +++ + = help: the trait `Sized` is not implemented for `[C]` + = note: all local variables must have a statically known size -error: aborting due to 4 previous errors; 1 warning emitted +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0508`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs index 76d7754384ebe..4dc170c3a65a1 100644 --- a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs +++ b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs @@ -50,10 +50,6 @@ impl, U> DispatchFromDyn> for Wrapper {} trait Trait { - // This method isn't dyn-compatible yet. Unsized by-value `self` is dyn-compatible (but not - // callable without unsized_locals), but wrappers arond `Self` currently are not. - // FIXME (mikeyhew) uncomment this when unsized rvalues dyn-compatibility is implemented - // fn wrapper(self: Wrapper) -> i32; fn ptr_wrapper(self: Ptr>) -> i32; fn wrapper_ptr(self: Wrapper>) -> i32; fn wrapper_ptr_wrapper(self: Wrapper>>) -> i32; diff --git a/tests/ui/sized/unsized-binding.stderr b/tests/ui/sized/unsized-binding.stderr index 8de236cd0b6e0..da3ba53b0bf5f 100644 --- a/tests/ui/sized/unsized-binding.stderr +++ b/tests/ui/sized/unsized-binding.stderr @@ -6,7 +6,6 @@ LL | let x = *""; | = help: the trait `Sized` is not implemented for `str` = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression | LL - let x = *""; diff --git a/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs index 35abbb80d99e5..fff6806e9a4be 100644 --- a/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs +++ b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.rs @@ -16,7 +16,6 @@ fn main() { //~^ ERROR the size for values of type `str` cannot be known at compilation time //~| HELP consider not dereferencing the expression //~| HELP the trait `Sized` is not implemented for `str` - //~| HELP unsized locals are gated as an unstable feature bar(x); S.baz(x); bar(*""); diff --git a/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr index 9b7258aff1261..29cedf3ecfdd0 100644 --- a/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr +++ b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr @@ -22,7 +22,6 @@ LL | let x = *""; | = help: the trait `Sized` is not implemented for `str` = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression | LL - let x = *""; @@ -30,7 +29,7 @@ LL + let x = ""; | error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:22:9 + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:21:9 | LL | bar(*""); | --- ^^^ doesn't have a size known at compile-time @@ -50,7 +49,7 @@ LL + bar(""); | error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:26:11 + --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:25:11 | LL | S.baz(*""); | --- ^^^ doesn't have a size known at compile-time diff --git a/tests/ui/static/static-drop-scope.rs b/tests/ui/static/static-drop-scope.rs index 74b224c9be085..ddcabeb12cc74 100644 --- a/tests/ui/static/static-drop-scope.rs +++ b/tests/ui/static/static-drop-scope.rs @@ -4,12 +4,6 @@ impl Drop for WithDtor { fn drop(&mut self) {} } -static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); -//~^ ERROR destructor of - -const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); -//~^ ERROR destructor of - static EARLY_DROP_S: i32 = (WithDtor, 0).1; //~^ ERROR destructor of diff --git a/tests/ui/static/static-drop-scope.stderr b/tests/ui/static/static-drop-scope.stderr index 24658bc601e7b..0fdf081e23432 100644 --- a/tests/ui/static/static-drop-scope.stderr +++ b/tests/ui/static/static-drop-scope.stderr @@ -1,21 +1,5 @@ -error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:7:60 - | -LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor); - | ^^^^^^^^- value is dropped here - | | - | the destructor for this type cannot be evaluated in statics - -error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:10:59 - | -LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor); - | ^^^^^^^^- value is dropped here - | | - | the destructor for this type cannot be evaluated in constants - error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:13:28 + --> $DIR/static-drop-scope.rs:7:28 | LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; | ^^^^^^^^^^^^^ - value is dropped here @@ -23,7 +7,7 @@ LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1; | the destructor for this type cannot be evaluated in statics error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:16:27 + --> $DIR/static-drop-scope.rs:10:27 | LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; | ^^^^^^^^^^^^^ - value is dropped here @@ -31,7 +15,7 @@ LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1; | the destructor for this type cannot be evaluated in constants error[E0493]: destructor of `(Option, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:27:34 + --> $DIR/static-drop-scope.rs:21:34 | LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; | ^^^^^^^^^^^^^^^^^^^ - value is dropped here @@ -39,7 +23,7 @@ LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1; | the destructor for this type cannot be evaluated in constants error[E0493]: destructor of `(Option, i32)` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:32:43 + --> $DIR/static-drop-scope.rs:26:43 | LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; | ^^^^^^^^^^^ - value is dropped here @@ -47,7 +31,7 @@ LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1; | the destructor for this type cannot be evaluated in constants error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:19:24 + --> $DIR/static-drop-scope.rs:13:24 | LL | const fn const_drop(_: T) {} | ^ - value is dropped here @@ -55,7 +39,7 @@ LL | const fn const_drop(_: T) {} | the destructor for this type cannot be evaluated in constant functions error[E0493]: destructor of `(T, ())` cannot be evaluated at compile-time - --> $DIR/static-drop-scope.rs:23:5 + --> $DIR/static-drop-scope.rs:17:5 | LL | (x, ()).1 | ^^^^^^^ the destructor for this type cannot be evaluated in constant functions @@ -63,6 +47,6 @@ LL | LL | } | - value is dropped here -error: aborting due to 8 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/str/str-array-assignment.stderr b/tests/ui/str/str-array-assignment.stderr index 515cb9e12f858..76eb7833225a8 100644 --- a/tests/ui/str/str-array-assignment.stderr +++ b/tests/ui/str/str-array-assignment.stderr @@ -25,7 +25,6 @@ LL | let v = s[..2]; | = help: the trait `Sized` is not implemented for `str` = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider borrowing here | LL | let v = &s[..2]; diff --git a/tests/ui/unsized-locals/align.rs b/tests/ui/unsized-locals/align.rs index a3820e3e6dcf3..fdb83a848bc42 100644 --- a/tests/ui/unsized-locals/align.rs +++ b/tests/ui/unsized-locals/align.rs @@ -1,8 +1,5 @@ // Test that unsized locals uphold alignment requirements. // Regression test for #71416. -//@ run-pass -#![feature(unsized_locals)] -#![allow(incomplete_features)] use std::any::Any; #[repr(align(256))] @@ -23,7 +20,7 @@ fn mk() -> Box { } fn main() { - let x = *mk(); + let x = *mk(); //~ERROR the size for values of type `dyn Any` cannot be known at compilation time let dwncst = x.downcast_ref::().unwrap(); let addr = dwncst.f(); assert_eq!(addr as usize % 256, 0); diff --git a/tests/ui/unsized-locals/align.stderr b/tests/ui/unsized-locals/align.stderr new file mode 100644 index 0000000000000..7a48ad1107eb4 --- /dev/null +++ b/tests/ui/unsized-locals/align.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `dyn Any` cannot be known at compilation time + --> $DIR/align.rs:23:9 + | +LL | let x = *mk(); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Any` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *mk(); +LL + let x = mk(); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/autoderef.rs b/tests/ui/unsized-locals/autoderef.rs index 31b58ba4002b4..24f8a4c5d0801 100644 --- a/tests/ui/unsized-locals/autoderef.rs +++ b/tests/ui/unsized-locals/autoderef.rs @@ -1,7 +1,4 @@ -//@ run-pass - -#![allow(incomplete_features)] -#![feature(unsized_locals, unsized_fn_params)] +#![feature(unsized_fn_params)] pub trait Foo { fn foo(self) -> String; @@ -26,7 +23,7 @@ impl Foo for dyn FnMut() -> String { } fn main() { - let x = *(Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>); + let x = *(Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>); //~ERROR the size for values of type `[char]` cannot be known at compilation time assert_eq!(&x.foo() as &str, "hello"); let x = Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>; @@ -35,13 +32,13 @@ fn main() { let x = "hello".to_owned().into_boxed_str(); assert_eq!(&x.foo() as &str, "hello"); - let x = *("hello".to_owned().into_boxed_str()); + let x = *("hello".to_owned().into_boxed_str()); //~ERROR the size for values of type `str` cannot be known at compilation time assert_eq!(&x.foo() as &str, "hello"); let x = "hello".to_owned().into_boxed_str(); assert_eq!(&x.foo() as &str, "hello"); - let x = *(Box::new(|| "hello".to_owned()) as Box String>); + let x = *(Box::new(|| "hello".to_owned()) as Box String>); //~ERROR the size for values of type `dyn FnMut() -> String` cannot be known at compilation time assert_eq!(&x.foo() as &str, "hello"); let x = Box::new(|| "hello".to_owned()) as Box String>; diff --git a/tests/ui/unsized-locals/autoderef.stderr b/tests/ui/unsized-locals/autoderef.stderr new file mode 100644 index 0000000000000..785badce19913 --- /dev/null +++ b/tests/ui/unsized-locals/autoderef.stderr @@ -0,0 +1,45 @@ +error[E0277]: the size for values of type `[char]` cannot be known at compilation time + --> $DIR/autoderef.rs:26:9 + | +LL | let x = *(Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[char]` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *(Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>); +LL + let x = (Box::new(['h', 'e', 'l', 'l', 'o']) as Box<[char]>); + | + +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/autoderef.rs:35:9 + | +LL | let x = *("hello".to_owned().into_boxed_str()); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *("hello".to_owned().into_boxed_str()); +LL + let x = ("hello".to_owned().into_boxed_str()); + | + +error[E0277]: the size for values of type `dyn FnMut() -> String` cannot be known at compilation time + --> $DIR/autoderef.rs:41:9 + | +LL | let x = *(Box::new(|| "hello".to_owned()) as Box String>); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn FnMut() -> String` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *(Box::new(|| "hello".to_owned()) as Box String>); +LL + let x = (Box::new(|| "hello".to_owned()) as Box String>); + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/auxiliary/ufuncs.rs b/tests/ui/unsized-locals/auxiliary/ufuncs.rs index 5954abf3a1fc5..78534182e8dc1 100644 --- a/tests/ui/unsized-locals/auxiliary/ufuncs.rs +++ b/tests/ui/unsized-locals/auxiliary/ufuncs.rs @@ -1,3 +1,3 @@ -#![feature(unsized_locals, unsized_fn_params)] +#![feature(unsized_fn_params)] pub fn udrop(_x: T) {} diff --git a/tests/ui/unsized-locals/borrow-after-move.rs b/tests/ui/unsized-locals/borrow-after-move.rs index ad73b720fa39d..6c510911f8957 100644 --- a/tests/ui/unsized-locals/borrow-after-move.rs +++ b/tests/ui/unsized-locals/borrow-after-move.rs @@ -1,5 +1,4 @@ -#![feature(unsized_locals, unsized_fn_params)] -//~^ WARN the feature `unsized_locals` is incomplete +#![feature(unsized_fn_params)] pub trait Foo { fn foo(self) -> String; @@ -16,28 +15,23 @@ fn drop_unsized(_: T) {} fn main() { { let x = "hello".to_owned().into_boxed_str(); - let y = *x; + let y = *x; //~ERROR the size for values of type `str` cannot be known at compilation time [E0277] drop_unsized(y); println!("{}", &x); - //~^ERROR borrow of moved value println!("{}", &y); - //~^ERROR borrow of moved value } { let x = "hello".to_owned().into_boxed_str(); - let y = *x; + let y = *x; //~ERROR the size for values of type `str` cannot be known at compilation time [E0277] y.foo(); println!("{}", &x); - //~^ERROR borrow of moved value println!("{}", &y); - //~^ERROR borrow of moved value } { let x = "hello".to_owned().into_boxed_str(); x.foo(); println!("{}", &x); - //~^ERROR borrow of moved value } } diff --git a/tests/ui/unsized-locals/borrow-after-move.stderr b/tests/ui/unsized-locals/borrow-after-move.stderr index 9e3c345dd8001..1a4ce39fa7b31 100644 --- a/tests/ui/unsized-locals/borrow-after-move.stderr +++ b/tests/ui/unsized-locals/borrow-after-move.stderr @@ -1,85 +1,31 @@ -warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/borrow-after-move.rs:1:12 - | -LL | #![feature(unsized_locals, unsized_fn_params)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #48055 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0382]: borrow of moved value: `x` - --> $DIR/borrow-after-move.rs:21:24 +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/borrow-after-move.rs:18:13 | LL | let y = *x; - | -- value moved here -LL | drop_unsized(y); -LL | println!("{}", &x); - | ^^ value borrowed here after move + | ^ doesn't have a size known at compile-time | - = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait - -error[E0382]: borrow of moved value: `y` - --> $DIR/borrow-after-move.rs:23:24 + = help: the trait `Sized` is not implemented for `str` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression | -LL | let y = *x; - | - move occurs because `y` has type `str`, which does not implement the `Copy` trait -LL | drop_unsized(y); - | - value moved here -... -LL | println!("{}", &y); - | ^^ value borrowed here after move - | -note: consider changing this parameter type in function `drop_unsized` to borrow instead if owning the value isn't necessary - --> $DIR/borrow-after-move.rs:14:31 +LL - let y = *x; +LL + let y = x; | -LL | fn drop_unsized(_: T) {} - | ------------ ^ this parameter takes ownership of the value - | | - | in this function -error[E0382]: borrow of moved value: `x` - --> $DIR/borrow-after-move.rs:31:24 +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/borrow-after-move.rs:26:13 | LL | let y = *x; - | -- value moved here -LL | y.foo(); -LL | println!("{}", &x); - | ^^ value borrowed here after move - | - = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait - -error[E0382]: borrow of moved value: `y` - --> $DIR/borrow-after-move.rs:33:24 - | -LL | let y = *x; - | - move occurs because `y` has type `str`, which does not implement the `Copy` trait -LL | y.foo(); - | ----- `y` moved due to this method call -... -LL | println!("{}", &y); - | ^^ value borrowed here after move - | -note: `Foo::foo` takes ownership of the receiver `self`, which moves `y` - --> $DIR/borrow-after-move.rs:5:12 - | -LL | fn foo(self) -> String; - | ^^^^ - -error[E0382]: borrow of moved value: `x` - --> $DIR/borrow-after-move.rs:40:24 + | ^ doesn't have a size known at compile-time | -LL | let x = "hello".to_owned().into_boxed_str(); - | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait -LL | x.foo(); - | - value moved here -LL | println!("{}", &x); - | ^^ value borrowed here after move + = help: the trait `Sized` is not implemented for `str` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression | -help: consider cloning the value if the performance cost is acceptable +LL - let y = *x; +LL + let y = x; | -LL | x.clone().foo(); - | ++++++++ -error: aborting due to 5 previous errors; 1 warning emitted +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0382`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-rpass.rs b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-rpass.rs index 7ccea43d182e9..26d2bc6c8e0c5 100644 --- a/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-rpass.rs +++ b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-rpass.rs @@ -1,8 +1,3 @@ -//@ run-pass - -#![allow(incomplete_features)] -#![feature(unsized_locals)] - pub trait Foo { fn foo(self) -> String; } @@ -16,7 +11,7 @@ impl Foo for A { } fn main() { - let x = *(Box::new(A) as Box); + let x = *(Box::new(A) as Box); //~ERROR the size for values of type `dyn Foo` cannot be known at compilation time assert_eq!(x.foo(), format!("hello")); // I'm not sure whether we want this to work diff --git a/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-rpass.stderr b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-rpass.stderr new file mode 100644 index 0000000000000..231cc051f7acd --- /dev/null +++ b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-rpass.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `dyn Foo` cannot be known at compilation time + --> $DIR/by-value-trait-dyn-compatibility-rpass.rs:14:9 + | +LL | let x = *(Box::new(A) as Box); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Foo` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *(Box::new(A) as Box); +LL + let x = (Box::new(A) as Box); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-with-default.rs b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-with-default.rs index 1f9b5f11fb507..554c2706e1eb4 100644 --- a/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-with-default.rs +++ b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-with-default.rs @@ -1,7 +1,5 @@ -//@ run-pass - -#![allow(incomplete_features)] -#![feature(unsized_locals, unsized_fn_params)] +#![allow(internal_features)] +#![feature(unsized_fn_params)] pub trait Foo { fn foo(self) -> String { @@ -14,7 +12,7 @@ struct A; impl Foo for A {} fn main() { - let x = *(Box::new(A) as Box); + let x = *(Box::new(A) as Box); //~ERROR the size for values of type `dyn Foo` cannot be known at compilation time assert_eq!(x.foo(), format!("hello")); // I'm not sure whether we want this to work diff --git a/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-with-default.stderr b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-with-default.stderr new file mode 100644 index 0000000000000..6d8370fac630a --- /dev/null +++ b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility-with-default.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `dyn Foo` cannot be known at compilation time + --> $DIR/by-value-trait-dyn-compatibility-with-default.rs:15:9 + | +LL | let x = *(Box::new(A) as Box); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Foo` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *(Box::new(A) as Box); +LL + let x = (Box::new(A) as Box); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.rs b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.rs index d0ba6944a1e81..d390f18c69f5b 100644 --- a/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.rs +++ b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.rs @@ -1,6 +1,3 @@ -#![feature(unsized_locals)] -//~^ WARN the feature `unsized_locals` is incomplete - pub trait Foo { fn foo(self) -> String where @@ -16,7 +13,7 @@ impl Foo for A { } fn main() { - let x = *(Box::new(A) as Box); + let x = *(Box::new(A) as Box); //~ERROR the size for values of type `dyn Foo` cannot be known at compilation time [E0277] x.foo(); //~^ERROR the `foo` method cannot be invoked on a trait object } diff --git a/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.stderr b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.stderr index 223624cfca4dd..1c681ba1215f9 100644 --- a/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.stderr +++ b/tests/ui/unsized-locals/by-value-trait-dyn-compatibility.stderr @@ -1,14 +1,5 @@ -warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/by-value-trait-dyn-compatibility.rs:1:12 - | -LL | #![feature(unsized_locals)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #48055 for more information - = note: `#[warn(incomplete_features)]` on by default - error: the `foo` method cannot be invoked on a trait object - --> $DIR/by-value-trait-dyn-compatibility.rs:20:7 + --> $DIR/by-value-trait-dyn-compatibility.rs:17:7 | LL | Self: Sized; | ----- this has a `Sized` requirement @@ -16,5 +7,20 @@ LL | Self: Sized; LL | x.foo(); | ^^^ -error: aborting due to 1 previous error; 1 warning emitted +error[E0277]: the size for values of type `dyn Foo` cannot be known at compilation time + --> $DIR/by-value-trait-dyn-compatibility.rs:16:9 + | +LL | let x = *(Box::new(A) as Box); + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `dyn Foo` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let x = *(Box::new(A) as Box); +LL + let x = (Box::new(A) as Box); + | + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/double-move.rs b/tests/ui/unsized-locals/double-move.rs index 9e46ef9be487c..254528abfb40c 100644 --- a/tests/ui/unsized-locals/double-move.rs +++ b/tests/ui/unsized-locals/double-move.rs @@ -1,5 +1,4 @@ -#![feature(unsized_locals, unsized_fn_params)] -//~^ WARN the feature `unsized_locals` is incomplete +#![feature(unsized_fn_params)] pub trait Foo { fn foo(self) -> String; @@ -16,39 +15,39 @@ fn drop_unsized(_: T) {} fn main() { { let x = "hello".to_owned().into_boxed_str(); - let y = *x; + let y = *x; //~ERROR the size for values of type `str` cannot be known at compilation time [E0277] + drop_unsized(y); drop_unsized(y); - drop_unsized(y); //~ERROR use of moved value } { let x = "hello".to_owned().into_boxed_str(); - let _y = *x; - drop_unsized(x); //~ERROR use of moved value + let _y = *x; //~ERROR the size for values of type `str` cannot be known at compilation time [E0277] + drop_unsized(x); } { let x = "hello".to_owned().into_boxed_str(); drop_unsized(x); - let _y = *x; //~ERROR use of moved value + let _y = *x; //~ERROR the size for values of type `str` cannot be known at compilation time [E0277] } { let x = "hello".to_owned().into_boxed_str(); - let y = *x; + let y = *x; //~ERROR the size for values of type `str` cannot be known at compilation time [E0277] + y.foo(); y.foo(); - y.foo(); //~ERROR use of moved value } { let x = "hello".to_owned().into_boxed_str(); - let _y = *x; - x.foo(); //~ERROR use of moved value + let _y = *x; //~ERROR the size for values of type `str` cannot be known at compilation time [E0277] + x.foo(); } { let x = "hello".to_owned().into_boxed_str(); x.foo(); - let _y = *x; //~ERROR use of moved value + let _y = *x; //~ERROR the size for values of type `str` cannot be known at compilation time [E0277] } } diff --git a/tests/ui/unsized-locals/double-move.stderr b/tests/ui/unsized-locals/double-move.stderr index 49b906bbe02b7..8d97b16d00c5d 100644 --- a/tests/ui/unsized-locals/double-move.stderr +++ b/tests/ui/unsized-locals/double-move.stderr @@ -1,86 +1,87 @@ -warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/double-move.rs:1:12 +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/double-move.rs:18:13 | -LL | #![feature(unsized_locals, unsized_fn_params)] - | ^^^^^^^^^^^^^^ +LL | let y = *x; + | ^ doesn't have a size known at compile-time | - = note: see issue #48055 for more information - = note: `#[warn(incomplete_features)]` on by default - -error[E0382]: use of moved value: `y` - --> $DIR/double-move.rs:21:22 + = help: the trait `Sized` is not implemented for `str` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let y = *x; +LL + let y = x; | -LL | let y = *x; - | - move occurs because `y` has type `str`, which does not implement the `Copy` trait -LL | drop_unsized(y); - | - value moved here -LL | drop_unsized(y); - | ^ value used here after move - | -note: consider changing this parameter type in function `drop_unsized` to borrow instead if owning the value isn't necessary - --> $DIR/double-move.rs:14:31 - | -LL | fn drop_unsized(_: T) {} - | ------------ ^ this parameter takes ownership of the value - | | - | in this function -error[E0382]: use of moved value: `x` - --> $DIR/double-move.rs:27:22 +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/double-move.rs:25:13 | LL | let _y = *x; - | -- value moved here -LL | drop_unsized(x); - | ^ value used here after move + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let _y = *x; +LL + let _y = x; | - = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `*x` - --> $DIR/double-move.rs:33:18 +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/double-move.rs:32:13 | -LL | let x = "hello".to_owned().into_boxed_str(); - | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait -LL | drop_unsized(x); - | - value moved here LL | let _y = *x; - | ^^ value used here after move + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let _y = *x; +LL + let _y = x; + | -error[E0382]: use of moved value: `y` - --> $DIR/double-move.rs:40:9 +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/double-move.rs:37:13 | LL | let y = *x; - | - move occurs because `y` has type `str`, which does not implement the `Copy` trait -LL | y.foo(); - | ----- `y` moved due to this method call -LL | y.foo(); - | ^ value used here after move + | ^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression | -note: `Foo::foo` takes ownership of the receiver `self`, which moves `y` - --> $DIR/double-move.rs:5:12 +LL - let y = *x; +LL + let y = x; | -LL | fn foo(self) -> String; - | ^^^^ -error[E0382]: use of moved value: `x` - --> $DIR/double-move.rs:46:9 +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/double-move.rs:44:13 | LL | let _y = *x; - | -- value moved here -LL | x.foo(); - | ^ value used here after move + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let _y = *x; +LL + let _y = x; | - = note: move occurs because `*x` has type `str`, which does not implement the `Copy` trait -error[E0382]: use of moved value: `*x` - --> $DIR/double-move.rs:52:18 +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/double-move.rs:51:13 | -LL | let x = "hello".to_owned().into_boxed_str(); - | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait -LL | x.foo(); - | - value moved here LL | let _y = *x; - | ^^ value used here after move + | ^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: all local variables must have a statically known size +help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression + | +LL - let _y = *x; +LL + let _y = x; + | -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0382`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.rs b/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.rs index ec475673d0d84..4b15e191a0ba6 100644 --- a/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.rs +++ b/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.rs @@ -1,7 +1,5 @@ // ICE size_and_align_of::<[closure@test.rs:15:5: 17:7]> not supported #88212 // issue: rust-lang/rust#88212 -#![feature(unsized_locals)] -//~^ WARN the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes trait Example {} struct Foo(); @@ -13,9 +11,8 @@ fn example() -> Box { } fn main() { - let x: dyn Example = *example(); + let x: dyn Example = *example(); //~ERROR the size for values of type `dyn Example` cannot be known at compilation time (move || { - let _y = x; - //~^ ERROR the size for values of type `dyn Example` cannot be known at compilation time + let _y = x; //~ERROR the size for values of type `dyn Example` cannot be known at compilation time })(); } diff --git a/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.stderr b/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.stderr index a0253ac1f35aa..ffee9852c2a37 100644 --- a/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.stderr +++ b/tests/ui/unsized-locals/ice-size_and_align_of-closure-not-supported-88212.stderr @@ -1,23 +1,25 @@ -warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/ice-size_and_align_of-closure-not-supported-88212.rs:3:12 +error[E0277]: the size for values of type `dyn Example` cannot be known at compilation time + --> $DIR/ice-size_and_align_of-closure-not-supported-88212.rs:14:9 + | +LL | let x: dyn Example = *example(); + | ^ doesn't have a size known at compile-time | -LL | #![feature(unsized_locals)] - | ^^^^^^^^^^^^^^ + = help: the trait `Sized` is not implemented for `dyn Example` + = note: all local variables must have a statically known size +help: consider borrowing here | - = note: see issue #48055 for more information - = note: `#[warn(incomplete_features)]` on by default +LL | let x: &dyn Example = *example(); + | + error[E0277]: the size for values of type `dyn Example` cannot be known at compilation time - --> $DIR/ice-size_and_align_of-closure-not-supported-88212.rs:18:18 + --> $DIR/ice-size_and_align_of-closure-not-supported-88212.rs:16:13 | -LL | (move || { - | -- this closure captures all values by move LL | let _y = x; - | ^ doesn't have a size known at compile-time + | ^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `dyn Example` - = note: all values captured by value by a closure must have a statically known size + = note: all local variables must have a statically known size -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/issue-30276-feature-flagged.rs b/tests/ui/unsized-locals/issue-30276-feature-flagged.rs index 8b5b321ec4989..6b67ebbec1c0c 100644 --- a/tests/ui/unsized-locals/issue-30276-feature-flagged.rs +++ b/tests/ui/unsized-locals/issue-30276-feature-flagged.rs @@ -1,6 +1,3 @@ -#![feature(unsized_locals)] -//~^ WARN the feature `unsized_locals` is incomplete - struct Test([i32]); fn main() { diff --git a/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr b/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr index ee8e4f3eee26b..a7bf27a0c4acc 100644 --- a/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr +++ b/tests/ui/unsized-locals/issue-30276-feature-flagged.stderr @@ -1,14 +1,5 @@ -warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-30276-feature-flagged.rs:1:12 - | -LL | #![feature(unsized_locals)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #48055 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0277]: the size for values of type `[i32]` cannot be known at compilation time - --> $DIR/issue-30276-feature-flagged.rs:7:29 + --> $DIR/issue-30276-feature-flagged.rs:4:29 | LL | let _x: fn(_) -> Test = Test; | ^^^^ doesn't have a size known at compile-time @@ -17,6 +8,6 @@ LL | let _x: fn(_) -> Test = Test; = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/issue-50940-with-feature.rs b/tests/ui/unsized-locals/issue-50940-with-feature.rs index 63b0e830be4ed..9a1ba7af19156 100644 --- a/tests/ui/unsized-locals/issue-50940-with-feature.rs +++ b/tests/ui/unsized-locals/issue-50940-with-feature.rs @@ -1,5 +1,4 @@ -#![feature(unsized_locals, unsized_fn_params)] -//~^ WARN the feature `unsized_locals` is incomplete +#![feature(unsized_fn_params)] fn main() { struct A(X); diff --git a/tests/ui/unsized-locals/issue-50940-with-feature.stderr b/tests/ui/unsized-locals/issue-50940-with-feature.stderr index b39eb2e70bbae..f3fb3ac1a09ff 100644 --- a/tests/ui/unsized-locals/issue-50940-with-feature.stderr +++ b/tests/ui/unsized-locals/issue-50940-with-feature.stderr @@ -1,26 +1,17 @@ -warning: the feature `unsized_locals` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-50940-with-feature.rs:1:12 - | -LL | #![feature(unsized_locals, unsized_fn_params)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #48055 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/issue-50940-with-feature.rs:6:5 + --> $DIR/issue-50940-with-feature.rs:5:5 | LL | A as fn(str) -> A; | ^ doesn't have a size known at compile-time | = help: within `A`, the trait `Sized` is not implemented for `str` note: required because it appears within the type `A` - --> $DIR/issue-50940-with-feature.rs:5:12 + --> $DIR/issue-50940-with-feature.rs:4:12 | LL | struct A(X); | ^ = note: the return type of a function must have a statically known size -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/reference-unsized-locals.rs b/tests/ui/unsized-locals/reference-unsized-locals.rs index 5b5fca22a0124..757bae4bb914d 100644 --- a/tests/ui/unsized-locals/reference-unsized-locals.rs +++ b/tests/ui/unsized-locals/reference-unsized-locals.rs @@ -1,10 +1,5 @@ -//@ run-pass - -#![allow(incomplete_features)] -#![feature(unsized_locals)] - fn main() { let foo: Box<[u8]> = Box::new(*b"foo"); - let foo: [u8] = *foo; + let foo: [u8] = *foo; //~ERROR the size for values of type `[u8]` cannot be known at compilation time [E0277] assert_eq!(&foo, b"foo" as &[u8]); } diff --git a/tests/ui/unsized-locals/reference-unsized-locals.stderr b/tests/ui/unsized-locals/reference-unsized-locals.stderr new file mode 100644 index 0000000000000..d1cba9ba79e4f --- /dev/null +++ b/tests/ui/unsized-locals/reference-unsized-locals.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/reference-unsized-locals.rs:3:9 + | +LL | let foo: [u8] = *foo; + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size +help: consider borrowing here + | +LL | let foo: &[u8] = *foo; + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/simple-unsized-locals.rs b/tests/ui/unsized-locals/simple-unsized-locals.rs index 374031b80bd28..e6c8bdc7a8851 100644 --- a/tests/ui/unsized-locals/simple-unsized-locals.rs +++ b/tests/ui/unsized-locals/simple-unsized-locals.rs @@ -1,9 +1,4 @@ -//@ run-pass - -#![allow(incomplete_features)] -#![feature(unsized_locals)] - fn main() { let foo: Box<[u8]> = Box::new(*b"foo"); - let _foo: [u8] = *foo; + let _foo: [u8] = *foo; //~ERROR the size for values of type `[u8]` cannot be known at compilation time [E0277] } diff --git a/tests/ui/unsized-locals/simple-unsized-locals.stderr b/tests/ui/unsized-locals/simple-unsized-locals.stderr new file mode 100644 index 0000000000000..83a64bd0711c9 --- /dev/null +++ b/tests/ui/unsized-locals/simple-unsized-locals.stderr @@ -0,0 +1,16 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/simple-unsized-locals.rs:3:9 + | +LL | let _foo: [u8] = *foo; + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[u8]` + = note: all local variables must have a statically known size +help: consider borrowing here + | +LL | let _foo: &[u8] = *foo; + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsized-locals/suggest-borrow.stderr b/tests/ui/unsized-locals/suggest-borrow.stderr index 8741b35cdcff8..a3b4403cf9bcb 100644 --- a/tests/ui/unsized-locals/suggest-borrow.stderr +++ b/tests/ui/unsized-locals/suggest-borrow.stderr @@ -6,7 +6,6 @@ LL | let x: [u8] = vec!(1, 2, 3)[..]; | = help: the trait `Sized` is not implemented for `[u8]` = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider borrowing here | LL | let x: &[u8] = vec!(1, 2, 3)[..]; @@ -51,7 +50,6 @@ LL | let x: [u8] = &vec!(1, 2, 3)[..]; | = help: the trait `Sized` is not implemented for `[u8]` = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider borrowing here | LL | let x: &[u8] = &vec!(1, 2, 3)[..]; diff --git a/tests/ui/unsized-locals/unsized-exprs-rpass.rs b/tests/ui/unsized-locals/unsized-exprs-rpass.rs index 861583efc401d..54ecd00034365 100644 --- a/tests/ui/unsized-locals/unsized-exprs-rpass.rs +++ b/tests/ui/unsized-locals/unsized-exprs-rpass.rs @@ -1,6 +1,6 @@ //@ run-pass -#![allow(incomplete_features, unused_braces, unused_parens)] -#![feature(unsized_locals, unsized_fn_params)] +#![allow(internal_features, unused_braces, unused_parens)] +#![feature(unsized_fn_params)] struct A(#[allow(dead_code)] X); diff --git a/tests/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr b/tests/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr index ace5a87187b8d..fe6780c438c96 100644 --- a/tests/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr +++ b/tests/ui/unsized-locals/unsized-locals-using-unsized-fn-params.stderr @@ -6,7 +6,6 @@ LL | fn f1(box box _b: Box>) {} | = help: the trait `Sized` is not implemented for `[u8]` = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> $DIR/unsized-locals-using-unsized-fn-params.rs:8:12 @@ -16,7 +15,6 @@ LL | fn f2((_x, _y): (i32, [i32])) {} | = help: the trait `Sized` is not implemented for `[i32]` = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/unsized-locals-using-unsized-fn-params.rs:13:9 @@ -26,7 +24,6 @@ LL | let _foo: [u8] = *foo; | = help: the trait `Sized` is not implemented for `[u8]` = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider borrowing here | LL | let _foo: &[u8] = *foo; diff --git a/tests/ui/unsized-locals/yote.rs b/tests/ui/unsized-locals/yote.rs new file mode 100644 index 0000000000000..aa5b68a307820 --- /dev/null +++ b/tests/ui/unsized-locals/yote.rs @@ -0,0 +1,4 @@ +//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION" + +#![feature(unsized_locals)] //~ERROR feature has been removed +#![crate_type = "lib"] diff --git a/tests/ui/unsized-locals/yote.stderr b/tests/ui/unsized-locals/yote.stderr new file mode 100644 index 0000000000000..655aad5360cc8 --- /dev/null +++ b/tests/ui/unsized-locals/yote.stderr @@ -0,0 +1,12 @@ +error[E0557]: feature has been removed + --> $DIR/yote.rs:3:12 + | +LL | #![feature(unsized_locals)] + | ^^^^^^^^^^^^^^ feature has been removed + | + = note: removed in CURRENT_RUSTC_VERSION (you are using $RUSTC_VERSION) + = note: removed due to implementation concerns; see https://github.com/rust-lang/rust/issues/111942 + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0557`. diff --git a/tests/ui/unsized/unsized6.stderr b/tests/ui/unsized/unsized6.stderr index de921709865bf..2dcdd3c3c0be9 100644 --- a/tests/ui/unsized/unsized6.stderr +++ b/tests/ui/unsized/unsized6.stderr @@ -8,7 +8,6 @@ LL | let y: Y; | ^ doesn't have a size known at compile-time | = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f1(x: &X) { @@ -60,7 +59,6 @@ LL | let y: X; | ^ doesn't have a size known at compile-time | = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f2(x: &X) { @@ -96,7 +94,6 @@ LL | let y: X = *x1; | ^ doesn't have a size known at compile-time | = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f3(x1: Box, x2: Box, x3: Box) { @@ -117,7 +114,6 @@ LL | let y = *x2; | ^ doesn't have a size known at compile-time | = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f3(x1: Box, x2: Box, x3: Box) { @@ -139,7 +135,6 @@ LL | let (y, z) = (*x3, 4); | ^ doesn't have a size known at compile-time | = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f3(x1: Box, x2: Box, x3: Box) { @@ -155,7 +150,6 @@ LL | let y: X = *x1; | ^ doesn't have a size known at compile-time | = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f4(x1: Box, x2: Box, x3: Box) { @@ -176,7 +170,6 @@ LL | let y = *x2; | ^ doesn't have a size known at compile-time | = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f4(x1: Box, x2: Box, x3: Box) { @@ -198,7 +191,6 @@ LL | let (y, z) = (*x3, 4); | ^ doesn't have a size known at compile-time | = note: all local variables must have a statically known size - = help: unsized locals are gated as an unstable feature help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn f4(x1: Box, x2: Box, x3: Box) {