diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 03dbcc45024..94e2a40e1fe 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -145,8 +145,6 @@ pub struct ConstStability { pub feature: Symbol, /// whether the function has a `#[rustc_promotable]` attribute pub promotable: bool, - /// whether the function has a `#[rustc_allow_const_fn_ptr]` attribute - pub allow_const_fn_ptr: bool, } /// The available stability levels. @@ -190,7 +188,6 @@ where let mut stab: Option = None; let mut const_stab: Option = None; let mut promotable = false; - let mut allow_const_fn_ptr = false; let diagnostic = &sess.parse_sess.span_diagnostic; 'outer: for attr in attrs_iter { @@ -200,7 +197,6 @@ where sym::unstable, sym::stable, sym::rustc_promotable, - sym::rustc_allow_const_fn_ptr, ] .iter() .any(|&s| attr.has_name(s)) @@ -215,9 +211,6 @@ where if attr.has_name(sym::rustc_promotable) { promotable = true; } - if attr.has_name(sym::rustc_allow_const_fn_ptr) { - allow_const_fn_ptr = true; - } // attributes with data else if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta { let meta = meta.as_ref().unwrap(); @@ -360,12 +353,8 @@ where if sym::unstable == meta_name { stab = Some(Stability { level, feature }); } else { - const_stab = Some(ConstStability { - level, - feature, - promotable: false, - allow_const_fn_ptr: false, - }); + const_stab = + Some(ConstStability { level, feature, promotable: false }); } } (None, _, _) => { @@ -440,12 +429,8 @@ where if sym::stable == meta_name { stab = Some(Stability { level, feature }); } else { - const_stab = Some(ConstStability { - level, - feature, - promotable: false, - allow_const_fn_ptr: false, - }); + const_stab = + Some(ConstStability { level, feature, promotable: false }); } } (None, _) => { @@ -464,18 +449,16 @@ where } // Merge the const-unstable info into the stability info - if promotable || allow_const_fn_ptr { + if promotable { if let Some(ref mut stab) = const_stab { stab.promotable = promotable; - stab.allow_const_fn_ptr = allow_const_fn_ptr; } else { struct_span_err!( diagnostic, item_sp, E0717, - "rustc_promotable and rustc_allow_const_fn_ptr attributes \ - must be paired with either a rustc_const_unstable or a rustc_const_stable \ - attribute" + "`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` \ + or a `rustc_const_stable` attribute" ) .emit(); } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 7118437c0c8..544efc124e1 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -141,6 +141,9 @@ pub fn run_compiler( callbacks: &mut (dyn Callbacks + Send), file_loader: Option>, emitter: Option>, + make_codegen_backend: Option< + Box Box + Send>, + >, ) -> interface::Result<()> { let mut args = Vec::new(); for arg in at_args { @@ -162,6 +165,11 @@ pub fn run_compiler( let sopts = config::build_session_options(&matches); let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg")); + // We wrap `make_codegen_backend` in another `Option` such that `dummy_config` can take + // ownership of it when necessary, while also allowing the non-dummy config to take ownership + // when `dummy_config` is not used. + let mut make_codegen_backend = Some(make_codegen_backend); + let mut dummy_config = |sopts, cfg, diagnostic_output| { let mut config = interface::Config { opts: sopts, @@ -177,6 +185,7 @@ pub fn run_compiler( lint_caps: Default::default(), register_lints: None, override_queries: None, + make_codegen_backend: make_codegen_backend.take().unwrap(), registry: diagnostics_registry(), }; callbacks.config(&mut config); @@ -253,6 +262,7 @@ pub fn run_compiler( lint_caps: Default::default(), register_lints: None, override_queries: None, + make_codegen_backend: make_codegen_backend.unwrap(), registry: diagnostics_registry(), }; @@ -1265,7 +1275,7 @@ pub fn main() -> ! { }) }) .collect::>(); - run_compiler(&args, &mut callbacks, None, None) + run_compiler(&args, &mut callbacks, None, None, None) }); // The extra `\t` is necessary to align this label with the others. print_time_passes_entry(callbacks.time_passes, "\ttotal", start.elapsed()); diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 17b9e1ee7e8..7f5b1913480 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -587,6 +587,9 @@ declare_features! ( /// Allows basic arithmetic on floating point types in a `const fn`. (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None), + /// Allows using and casting function pointers in a `const fn`. + (active, const_fn_fn_ptr_basics, "1.48.0", Some(57563), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 8b7fd59cd87..22c1ca2f289 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -464,7 +464,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== rustc_attr!(rustc_promotable, AssumedUsed, template!(Word), IMPL_DETAIL), - rustc_attr!(rustc_allow_const_fn_ptr, AssumedUsed, template!(Word), IMPL_DETAIL), rustc_attr!(rustc_args_required_const, AssumedUsed, template!(List: "N"), INTERNAL_UNSTABLE), // ========================================================================== diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 4d84462c42b..73a51ad477b 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -154,6 +154,10 @@ pub struct Config { pub override_queries: Option, + /// This is a callback from the driver that is called to create a codegen backend. + pub make_codegen_backend: + Option Box + Send>>, + /// Registry of diagnostics codes. pub registry: Registry, } @@ -167,6 +171,7 @@ pub fn create_compiler_and_run(config: Config, f: impl FnOnce(&Compiler) -> R config.file_loader, config.input_path.clone(), config.lint_caps, + config.make_codegen_backend, registry.clone(), ); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 0eed6938c31..7ace707cc88 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -63,9 +63,17 @@ pub fn create_session( file_loader: Option>, input_path: Option, lint_caps: FxHashMap, + make_codegen_backend: Option< + Box Box + Send>, + >, descriptions: Registry, ) -> (Lrc, Lrc>) { - let codegen_backend = get_codegen_backend(&sopts); + let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend { + make_codegen_backend(&sopts) + } else { + get_codegen_backend(&sopts) + }; + // target_override is documented to be called before init(), so this is okay let target_override = codegen_backend.target_override(&sopts); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 784d6c3b2ce..d5b99ea4d28 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -457,10 +457,6 @@ rustc_queries! { desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) } } - query const_fn_is_allowed_fn_ptr(key: DefId) -> bool { - desc { |tcx| "checking if const fn allows `fn()` types: `{}`", tcx.def_path_str(key) } - } - /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`). query is_foreign_item(key: DefId) -> bool { desc { |tcx| "checking if `{}` is a foreign item", tcx.def_path_str(key) } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 342a37cadba..67c69d69bda 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -475,6 +475,18 @@ impl Trait for X { #traits-as-parameters", ); } + (ty::Param(p), ty::Closure(..) | ty::Generator(..)) => { + let generics = self.generics_of(body_owner_def_id); + let p_span = self.def_span(generics.type_param(p, self).def_id); + if !sp.contains(p_span) { + db.span_label(p_span, "this type parameter"); + } + db.help(&format!( + "every closure has a distinct type and so could not always match the \ + caller-chosen type of parameter `{}`", + p + )); + } (ty::Param(p), _) | (_, ty::Param(p)) => { let generics = self.generics_of(body_owner_def_id); let p_span = self.def_span(generics.type_param(p, self).def_id); diff --git a/compiler/rustc_mir/src/const_eval/fn_queries.rs b/compiler/rustc_mir/src/const_eval/fn_queries.rs index 1db1f6ceeda..aca822a05bd 100644 --- a/compiler/rustc_mir/src/const_eval/fn_queries.rs +++ b/compiler/rustc_mir/src/const_eval/fn_queries.rs @@ -151,17 +151,11 @@ fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } } -fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - is_const_fn(tcx, def_id) - && tcx.lookup_const_stability(def_id).map(|stab| stab.allow_const_fn_ptr).unwrap_or(false) -} - pub fn provide(providers: &mut Providers) { *providers = Providers { is_const_fn_raw, is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, def_id.expect_local()), is_promotable_const_fn, - const_fn_is_allowed_fn_ptr, ..*providers }; } diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs index 1d741085853..3b8d8a5aa99 100644 --- a/compiler/rustc_mir/src/transform/check_consts/ops.rs +++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs @@ -213,11 +213,21 @@ impl NonConstOp for FnPtrCast { const STOPS_CONST_CHECKING: bool = true; fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { - mcf_status_in_item(ccx) + if ccx.const_kind() != hir::ConstContext::ConstFn { + Status::Allowed + } else { + Status::Unstable(sym::const_fn_fn_ptr_basics) + } } fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) { - mcf_emit_error(ccx, span, "function pointer casts are not allowed in const fn"); + feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_fn_fn_ptr_basics, + span, + &format!("function pointer casts are not allowed in {}s", ccx.const_kind()), + ) + .emit() } } @@ -596,17 +606,21 @@ pub mod ty { const STOPS_CONST_CHECKING: bool = true; fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status { - // FIXME: This attribute a hack to allow the specialization of the `futures` API. See - // #59739. We should have a proper feature gate for this. - if ccx.tcx.has_attr(ccx.def_id.to_def_id(), sym::rustc_allow_const_fn_ptr) { + if ccx.const_kind() != hir::ConstContext::ConstFn { Status::Allowed } else { - mcf_status_in_item(ccx) + Status::Unstable(sym::const_fn_fn_ptr_basics) } } fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) { - mcf_emit_error(ccx, span, "function pointers in const fn are unstable"); + feature_err( + &ccx.tcx.sess.parse_sess, + sym::const_fn_fn_ptr_basics, + span, + &format!("function pointers cannot appear in {}s", ccx.const_kind()), + ) + .emit() } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 12134a85f45..4234aef3359 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -353,6 +353,7 @@ symbols! { const_extern_fn, const_fn, const_fn_floating_point_arithmetic, + const_fn_fn_ptr_basics, const_fn_transmute, const_fn_union, const_generics, @@ -884,7 +885,6 @@ symbols! { rustc, rustc_allocator, rustc_allocator_nounwind, - rustc_allow_const_fn_ptr, rustc_args_required_const, rustc_attrs, rustc_builtin_macro, diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 247bbf637ce..3e66885448b 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -117,11 +117,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } - // Checks that the type of `expr` can be coerced to `expected`. - // - // N.B., this code relies on `self.diverges` to be accurate. In - // particular, assignments to `!` will be permitted if the - // diverges flag is currently "always". + /// Checks that the type of `expr` can be coerced to `expected`. + /// + /// N.B., this code relies on `self.diverges` to be accurate. In particular, assignments to `!` + /// will be permitted if the diverges flag is currently "always". pub fn demand_coerce_diag( &self, expr: &hir::Expr<'_>, diff --git a/library/alloc/tests/boxed.rs b/library/alloc/tests/boxed.rs index 851ca17a365..6a83f5da87c 100644 --- a/library/alloc/tests/boxed.rs +++ b/library/alloc/tests/boxed.rs @@ -1,3 +1,4 @@ +use std::cell::Cell; use std::mem::MaybeUninit; use std::ptr::NonNull; @@ -49,3 +50,10 @@ fn box_clone_from_ptr_stability() { assert_eq!(copy.as_ptr() as usize, copy_raw); } } + +#[test] +fn box_deref_lval() { + let x = Box::new(Cell::new(5)); + x.set(1000); + assert_eq!(x.get(), 1000); +} diff --git a/library/alloc/tests/fmt.rs b/library/alloc/tests/fmt.rs index 0ad092b4997..757fddd2418 100644 --- a/library/alloc/tests/fmt.rs +++ b/library/alloc/tests/fmt.rs @@ -1,7 +1,327 @@ -use std::fmt; +#![deny(warnings)] + +use std::cell::RefCell; +use std::fmt::{self, Write}; #[test] fn test_format() { let s = fmt::format(format_args!("Hello, {}!", "world")); assert_eq!(s, "Hello, world!"); } + +struct A; +struct B; +struct C; +struct D; + +impl fmt::LowerHex for A { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("aloha") + } +} +impl fmt::UpperHex for B { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("adios") + } +} +impl fmt::Display for C { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad_integral(true, "☃", "123") + } +} +impl fmt::Binary for D { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("aa")?; + f.write_char('☃')?; + f.write_str("bb") + } +} + +macro_rules! t { + ($a:expr, $b:expr) => { + assert_eq!($a, $b) + }; +} + +#[test] +fn test_format_macro_interface() { + // Various edge cases without formats + t!(format!(""), ""); + t!(format!("hello"), "hello"); + t!(format!("hello {{"), "hello {"); + + // default formatters should work + t!(format!("{}", 1.0f32), "1"); + t!(format!("{}", 1.0f64), "1"); + t!(format!("{}", "a"), "a"); + t!(format!("{}", "a".to_string()), "a"); + t!(format!("{}", false), "false"); + t!(format!("{}", 'a'), "a"); + + // At least exercise all the formats + t!(format!("{}", true), "true"); + t!(format!("{}", '☃'), "☃"); + t!(format!("{}", 10), "10"); + t!(format!("{}", 10_usize), "10"); + t!(format!("{:?}", '☃'), "'☃'"); + t!(format!("{:?}", 10), "10"); + t!(format!("{:?}", 10_usize), "10"); + t!(format!("{:?}", "true"), "\"true\""); + t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\""); + t!( + format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"), + r#""foo\n\"bar\"\r\n\'baz\'\t\\qux\\""# + ); + t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"), r#""foo\u{0}bar\u{1}baz\u{7f}qux""#); + t!(format!("{:o}", 10_usize), "12"); + t!(format!("{:x}", 10_usize), "a"); + t!(format!("{:X}", 10_usize), "A"); + t!(format!("{}", "foo"), "foo"); + t!(format!("{}", "foo".to_string()), "foo"); + if cfg!(target_pointer_width = "32") { + t!(format!("{:#p}", 0x1234 as *const isize), "0x00001234"); + t!(format!("{:#p}", 0x1234 as *mut isize), "0x00001234"); + } else { + t!(format!("{:#p}", 0x1234 as *const isize), "0x0000000000001234"); + t!(format!("{:#p}", 0x1234 as *mut isize), "0x0000000000001234"); + } + t!(format!("{:p}", 0x1234 as *const isize), "0x1234"); + t!(format!("{:p}", 0x1234 as *mut isize), "0x1234"); + t!(format!("{:x}", A), "aloha"); + t!(format!("{:X}", B), "adios"); + t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃"); + t!(format!("{1} {0}", 0, 1), "1 0"); + t!(format!("{foo} {bar}", foo = 0, bar = 1), "0 1"); + t!(format!("{foo} {1} {bar} {0}", 0, 1, foo = 2, bar = 3), "2 1 3 0"); + t!(format!("{} {0}", "a"), "a a"); + t!(format!("{_foo}", _foo = 6usize), "6"); + t!(format!("{foo_bar}", foo_bar = 1), "1"); + t!(format!("{}", 5 + 5), "10"); + t!(format!("{:#4}", C), "☃123"); + t!(format!("{:b}", D), "aa☃bb"); + + let a: &dyn fmt::Debug = &1; + t!(format!("{:?}", a), "1"); + + // Formatting strings and their arguments + t!(format!("{}", "a"), "a"); + t!(format!("{:4}", "a"), "a "); + t!(format!("{:4}", "☃"), "☃ "); + t!(format!("{:>4}", "a"), " a"); + t!(format!("{:<4}", "a"), "a "); + t!(format!("{:^5}", "a"), " a "); + t!(format!("{:^5}", "aa"), " aa "); + t!(format!("{:^4}", "a"), " a "); + t!(format!("{:^4}", "aa"), " aa "); + t!(format!("{:.4}", "a"), "a"); + t!(format!("{:4.4}", "a"), "a "); + t!(format!("{:4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); + t!(format!("{:<4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); + t!(format!("{:>4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); + t!(format!("{:^4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); + t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), " aaaa"); + t!(format!("{:2.4}", "aaaaa"), "aaaa"); + t!(format!("{:2.4}", "aaaa"), "aaaa"); + t!(format!("{:2.4}", "aaa"), "aaa"); + t!(format!("{:2.4}", "aa"), "aa"); + t!(format!("{:2.4}", "a"), "a "); + t!(format!("{:0>2}", "a"), "0a"); + t!(format!("{:.*}", 4, "aaaaaaaaaaaaaaaaaa"), "aaaa"); + t!(format!("{:.1$}", "aaaaaaaaaaaaaaaaaa", 4), "aaaa"); + t!(format!("{:.a$}", "aaaaaaaaaaaaaaaaaa", a = 4), "aaaa"); + t!(format!("{:._a$}", "aaaaaaaaaaaaaaaaaa", _a = 4), "aaaa"); + t!(format!("{:1$}", "a", 4), "a "); + t!(format!("{1:0$}", 4, "a"), "a "); + t!(format!("{:a$}", "a", a = 4), "a "); + t!(format!("{:-#}", "a"), "a"); + t!(format!("{:+#}", "a"), "a"); + t!(format!("{:/^10.8}", "1234567890"), "/12345678/"); + + // Some float stuff + t!(format!("{:}", 1.0f32), "1"); + t!(format!("{:}", 1.0f64), "1"); + t!(format!("{:.3}", 1.0f64), "1.000"); + t!(format!("{:10.3}", 1.0f64), " 1.000"); + t!(format!("{:+10.3}", 1.0f64), " +1.000"); + t!(format!("{:+10.3}", -1.0f64), " -1.000"); + + t!(format!("{:e}", 1.2345e6f32), "1.2345e6"); + t!(format!("{:e}", 1.2345e6f64), "1.2345e6"); + t!(format!("{:E}", 1.2345e6f64), "1.2345E6"); + t!(format!("{:.3e}", 1.2345e6f64), "1.234e6"); + t!(format!("{:10.3e}", 1.2345e6f64), " 1.234e6"); + t!(format!("{:+10.3e}", 1.2345e6f64), " +1.234e6"); + t!(format!("{:+10.3e}", -1.2345e6f64), " -1.234e6"); + + // Float edge cases + t!(format!("{}", -0.0), "0"); + t!(format!("{:?}", -0.0), "-0.0"); + t!(format!("{:?}", 0.0), "0.0"); + + // sign aware zero padding + t!(format!("{:<3}", 1), "1 "); + t!(format!("{:>3}", 1), " 1"); + t!(format!("{:^3}", 1), " 1 "); + t!(format!("{:03}", 1), "001"); + t!(format!("{:<03}", 1), "001"); + t!(format!("{:>03}", 1), "001"); + t!(format!("{:^03}", 1), "001"); + t!(format!("{:+03}", 1), "+01"); + t!(format!("{:<+03}", 1), "+01"); + t!(format!("{:>+03}", 1), "+01"); + t!(format!("{:^+03}", 1), "+01"); + t!(format!("{:#05x}", 1), "0x001"); + t!(format!("{:<#05x}", 1), "0x001"); + t!(format!("{:>#05x}", 1), "0x001"); + t!(format!("{:^#05x}", 1), "0x001"); + t!(format!("{:05}", 1.2), "001.2"); + t!(format!("{:<05}", 1.2), "001.2"); + t!(format!("{:>05}", 1.2), "001.2"); + t!(format!("{:^05}", 1.2), "001.2"); + t!(format!("{:05}", -1.2), "-01.2"); + t!(format!("{:<05}", -1.2), "-01.2"); + t!(format!("{:>05}", -1.2), "-01.2"); + t!(format!("{:^05}", -1.2), "-01.2"); + t!(format!("{:+05}", 1.2), "+01.2"); + t!(format!("{:<+05}", 1.2), "+01.2"); + t!(format!("{:>+05}", 1.2), "+01.2"); + t!(format!("{:^+05}", 1.2), "+01.2"); + + // Ergonomic format_args! + t!(format!("{0:x} {0:X}", 15), "f F"); + t!(format!("{0:x} {0:X} {}", 15), "f F 15"); + t!(format!("{:x}{0:X}{a:x}{:X}{1:x}{a:X}", 13, 14, a = 15), "dDfEeF"); + t!(format!("{a:x} {a:X}", a = 15), "f F"); + + // And its edge cases + t!( + format!( + "{a:.0$} {b:.0$} {0:.0$}\n{a:.c$} {b:.c$} {c:.c$}", + 4, + a = "abcdefg", + b = "hijklmn", + c = 3 + ), + "abcd hijk 4\nabc hij 3" + ); + t!(format!("{a:.*} {0} {:.*}", 4, 3, "efgh", a = "abcdef"), "abcd 4 efg"); + t!(format!("{:.a$} {a} {a:#x}", "aaaaaa", a = 2), "aa 2 0x2"); + + // Test that pointers don't get truncated. + { + let val = usize::MAX; + let exp = format!("{:#x}", val); + t!(format!("{:p}", val as *const isize), exp); + } + + // Escaping + t!(format!("{{"), "{"); + t!(format!("}}"), "}"); + + // make sure that format! doesn't move out of local variables + let a = Box::new(3); + format!("{}", a); + format!("{}", a); + + // make sure that format! doesn't cause spurious unused-unsafe warnings when + // it's inside of an outer unsafe block + unsafe { + let a: isize = ::std::mem::transmute(3_usize); + format!("{}", a); + } + + // test that trailing commas are acceptable + format!("{}", "test",); + format!("{foo}", foo = "test",); +} + +// Basic test to make sure that we can invoke the `write!` macro with an +// fmt::Write instance. +#[test] +fn test_write() { + let mut buf = String::new(); + let _ = write!(&mut buf, "{}", 3); + { + let w = &mut buf; + let _ = write!(w, "{foo}", foo = 4); + let _ = write!(w, "{}", "hello"); + let _ = writeln!(w, "{}", "line"); + let _ = writeln!(w, "{foo}", foo = "bar"); + let _ = w.write_char('☃'); + let _ = w.write_str("str"); + } + + t!(buf, "34helloline\nbar\n☃str"); +} + +// Just make sure that the macros are defined, there's not really a lot that we +// can do with them just yet (to test the output) +#[test] +fn test_print() { + print!("hi"); + print!("{:?}", vec![0u8]); + println!("hello"); + println!("this is a {}", "test"); + println!("{foo}", foo = "bar"); +} + +// Just make sure that the macros are defined, there's not really a lot that we +// can do with them just yet (to test the output) +#[test] +fn test_format_args() { + let mut buf = String::new(); + { + let w = &mut buf; + let _ = write!(w, "{}", format_args!("{}", 1)); + let _ = write!(w, "{}", format_args!("test")); + let _ = write!(w, "{}", format_args!("{test}", test = 3)); + } + let s = buf; + t!(s, "1test3"); + + let s = fmt::format(format_args!("hello {}", "world")); + t!(s, "hello world"); + let s = format!("{}: {}", "args were", format_args!("hello {}", "world")); + t!(s, "args were: hello world"); +} + +#[test] +fn test_order() { + // Make sure format!() arguments are always evaluated in a left-to-right + // ordering + fn foo() -> isize { + static mut FOO: isize = 0; + unsafe { + FOO += 1; + FOO + } + } + assert_eq!( + format!("{} {} {a} {b} {} {c}", foo(), foo(), foo(), a = foo(), b = foo(), c = foo()), + "1 2 4 5 3 6".to_string() + ); +} + +#[test] +fn test_once() { + // Make sure each argument are evaluated only once even though it may be + // formatted multiple times + fn foo() -> isize { + static mut FOO: isize = 0; + unsafe { + FOO += 1; + FOO + } + } + assert_eq!(format!("{0} {0} {0} {a} {a} {a}", foo(), a = foo()), "1 1 1 2 2 2".to_string()); +} + +#[test] +fn test_refcell() { + let refcell = RefCell::new(5); + assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }"); + let borrow = refcell.borrow_mut(); + assert_eq!(format!("{:?}", refcell), "RefCell { value: }"); + drop(borrow); + assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }"); +} diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index a49ca7c256a..b7c7138db4f 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::cell::Cell; use std::collections::TryReserveError::*; use std::fmt::Debug; use std::iter::InPlaceIterable; @@ -1831,3 +1832,82 @@ fn partialeq_vec_full() { assert_partial_eq_valid!(vec2,vec3; array2,array3); assert_partial_eq_valid!(vec2,vec3; arrayref2,arrayref3); } + +#[test] +fn test_vec_cycle() { + #[derive(Debug)] + struct C<'a> { + v: Vec>>>, + } + + impl<'a> C<'a> { + fn new() -> C<'a> { + C { v: Vec::new() } + } + } + + let mut c1 = C::new(); + let mut c2 = C::new(); + let mut c3 = C::new(); + + // Push + c1.v.push(Cell::new(None)); + c1.v.push(Cell::new(None)); + + c2.v.push(Cell::new(None)); + c2.v.push(Cell::new(None)); + + c3.v.push(Cell::new(None)); + c3.v.push(Cell::new(None)); + + // Set + c1.v[0].set(Some(&c2)); + c1.v[1].set(Some(&c3)); + + c2.v[0].set(Some(&c2)); + c2.v[1].set(Some(&c3)); + + c3.v[0].set(Some(&c1)); + c3.v[1].set(Some(&c2)); +} + +#[test] +fn test_vec_cycle_wrapped() { + struct Refs<'a> { + v: Vec>>>, + } + + struct C<'a> { + refs: Refs<'a>, + } + + impl<'a> Refs<'a> { + fn new() -> Refs<'a> { + Refs { v: Vec::new() } + } + } + + impl<'a> C<'a> { + fn new() -> C<'a> { + C { refs: Refs::new() } + } + } + + let mut c1 = C::new(); + let mut c2 = C::new(); + let mut c3 = C::new(); + + c1.refs.v.push(Cell::new(None)); + c1.refs.v.push(Cell::new(None)); + c2.refs.v.push(Cell::new(None)); + c2.refs.v.push(Cell::new(None)); + c3.refs.v.push(Cell::new(None)); + c3.refs.v.push(Cell::new(None)); + + c1.refs.v[0].set(Some(&c2)); + c1.refs.v[1].set(Some(&c3)); + c2.refs.v[0].set(Some(&c2)); + c2.refs.v[1].set(Some(&c3)); + c3.refs.v[0].set(Some(&c1)); + c3.refs.v[1].set(Some(&c2)); +} diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 8558cb5a5e8..c1038ce4260 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2238,5 +2238,6 @@ impl Debug for UnsafeCell { } } -// If you expected tests to be here, look instead at the ui/ifmt.rs test, +// If you expected tests to be here, look instead at the core/tests/fmt.rs file, // it's a lot easier than creating all of the rt::Piece structures here. +// There are also tests in the alloc crate, for those that need allocations. diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index a75f1d56fb7..845df3f5ca5 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -1976,6 +1976,8 @@ pub trait Iterator { /// // they're the same /// assert_eq!(result, result2); /// ``` + #[doc(alias = "reduce")] + #[doc(alias = "inject")] #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn fold(mut self, init: B, mut f: F) -> B diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 30fb87b0226..22bf2b15d66 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -83,6 +83,7 @@ #![feature(const_fn_union)] #![feature(const_fn)] #![cfg_attr(not(bootstrap), feature(const_fn_floating_point_arithmetic))] +#![cfg_attr(not(bootstrap), feature(const_fn_fn_ptr_basics))] #![feature(const_generics)] #![feature(const_option)] #![feature(const_precise_live_drops)] diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 668a028a3f1..ba3fb35caaf 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -129,13 +129,9 @@ impl RawWakerVTable { /// associated task. #[rustc_promotable] #[stable(feature = "futures_api", since = "1.36.0")] - // `rustc_allow_const_fn_ptr` is a hack that should not be used anywhere else - // without first consulting with T-Lang. - // - // FIXME: remove whenever we have a stable way to accept fn pointers from const fn - // (see https://github.com/rust-rfcs/const-eval/issues/19#issuecomment-472799062) - #[rustc_allow_const_fn_ptr] #[rustc_const_stable(feature = "futures_api", since = "1.36.0")] + #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_fn_ptr_basics))] + #[cfg_attr(bootstrap, rustc_allow_const_fn_ptr)] pub const fn new( clone: unsafe fn(*const ()) -> RawWaker, wake: unsafe fn(*const ()), diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs index dbcea2747a0..89c2a969c28 100644 --- a/library/core/tests/array.rs +++ b/library/core/tests/array.rs @@ -345,3 +345,32 @@ fn array_map_drop_safety() { assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create); panic!("test succeeded") } + +#[test] +fn cell_allows_array_cycle() { + use core::cell::Cell; + + #[derive(Debug)] + struct B<'a> { + a: [Cell>>; 2], + } + + impl<'a> B<'a> { + fn new() -> B<'a> { + B { a: [Cell::new(None), Cell::new(None)] } + } + } + + let b1 = B::new(); + let b2 = B::new(); + let b3 = B::new(); + + b1.a[0].set(Some(&b2)); + b1.a[1].set(Some(&b3)); + + b2.a[0].set(Some(&b2)); + b2.a[1].set(Some(&b3)); + + b3.a[0].set(Some(&b1)); + b3.a[1].set(Some(&b2)); +} diff --git a/library/core/tests/cell.rs b/library/core/tests/cell.rs index 801b60be0f0..40be01f4439 100644 --- a/library/core/tests/cell.rs +++ b/library/core/tests/cell.rs @@ -303,6 +303,53 @@ fn cell_into_inner() { assert_eq!("Hello world".to_owned(), cell.into_inner()); } +#[test] +fn cell_exterior() { + #[derive(Copy, Clone)] + #[allow(dead_code)] + struct Point { + x: isize, + y: isize, + z: isize, + } + + fn f(p: &Cell) { + assert_eq!(p.get().z, 12); + p.set(Point { x: 10, y: 11, z: 13 }); + assert_eq!(p.get().z, 13); + } + + let a = Point { x: 10, y: 11, z: 12 }; + let b = &Cell::new(a); + assert_eq!(b.get().z, 12); + f(b); + assert_eq!(a.z, 12); + assert_eq!(b.get().z, 13); +} + +#[test] +fn cell_does_not_clone() { + #[derive(Copy)] + #[allow(dead_code)] + struct Foo { + x: isize, + } + + impl Clone for Foo { + fn clone(&self) -> Foo { + // Using Cell in any way should never cause clone() to be + // invoked -- after all, that would permit evil user code to + // abuse `Cell` and trigger crashes. + + panic!(); + } + } + + let x = Cell::new(Foo { x: 22 }); + let _y = x.get(); + let _z = x.clone(); +} + #[test] fn refcell_default() { let cell: RefCell = Default::default(); @@ -367,3 +414,11 @@ fn refcell_replace_borrows() { let _b = x.borrow(); x.replace(1); } + +#[test] +fn refcell_format() { + let name = RefCell::new("rust"); + let what = RefCell::new("rocks"); + let msg = format!("{name} {}", &*what.borrow(), name = &*name.borrow()); + assert_eq!(msg, "rust rocks".to_string()); +} diff --git a/library/core/tests/iter.rs b/library/core/tests/iter.rs index 0eb9af3f454..ab97352a806 100644 --- a/library/core/tests/iter.rs +++ b/library/core/tests/iter.rs @@ -376,6 +376,103 @@ fn test_zip_next_back_side_effects_exhausted() { assert_eq!(b, vec![200, 300, 400]); } +#[derive(Debug)] +struct CountClone(Cell); + +fn count_clone() -> CountClone { + CountClone(Cell::new(0)) +} + +impl PartialEq for CountClone { + fn eq(&self, rhs: &i32) -> bool { + self.0.get() == *rhs + } +} + +impl Clone for CountClone { + fn clone(&self) -> Self { + let ret = CountClone(self.0.clone()); + let n = self.0.get(); + self.0.set(n + 1); + ret + } +} + +#[test] +fn test_zip_cloned_sideffectful() { + let xs = [count_clone(), count_clone(), count_clone(), count_clone()]; + let ys = [count_clone(), count_clone()]; + + for _ in xs.iter().cloned().zip(ys.iter().cloned()) {} + + assert_eq!(&xs, &[1, 1, 1, 0][..]); + assert_eq!(&ys, &[1, 1][..]); + + let xs = [count_clone(), count_clone()]; + let ys = [count_clone(), count_clone(), count_clone(), count_clone()]; + + for _ in xs.iter().cloned().zip(ys.iter().cloned()) {} + + assert_eq!(&xs, &[1, 1][..]); + assert_eq!(&ys, &[1, 1, 0, 0][..]); +} + +#[test] +fn test_zip_map_sideffectful() { + let mut xs = [0; 6]; + let mut ys = [0; 4]; + + for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) {} + + assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]); + assert_eq!(&ys, &[1, 1, 1, 1]); + + let mut xs = [0; 4]; + let mut ys = [0; 6]; + + for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) {} + + assert_eq!(&xs, &[1, 1, 1, 1]); + assert_eq!(&ys, &[1, 1, 1, 1, 0, 0]); +} + +#[test] +fn test_zip_map_rev_sideffectful() { + let mut xs = [0; 6]; + let mut ys = [0; 4]; + + { + let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)); + it.next_back(); + } + assert_eq!(&xs, &[0, 0, 0, 1, 1, 1]); + assert_eq!(&ys, &[0, 0, 0, 1]); + + let mut xs = [0; 6]; + let mut ys = [0; 4]; + + { + let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)); + (&mut it).take(5).count(); + it.next_back(); + } + assert_eq!(&xs, &[1, 1, 1, 1, 1, 1]); + assert_eq!(&ys, &[1, 1, 1, 1]); +} + +#[test] +fn test_zip_nested_sideffectful() { + let mut xs = [0; 6]; + let ys = [0; 4]; + + { + // test that it has the side effect nested inside enumerate + let it = xs.iter_mut().map(|x| *x = 1).enumerate().zip(&ys); + it.count(); + } + assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]); +} + #[test] fn test_zip_nth_back_side_effects_exhausted() { let mut a = Vec::new(); diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs index 9e86e07dd91..ae814efec20 100644 --- a/library/core/tests/option.rs +++ b/library/core/tests/option.rs @@ -1,3 +1,4 @@ +use core::cell::Cell; use core::clone::Clone; use core::mem; use core::ops::DerefMut; @@ -372,3 +373,32 @@ fn option_const() { const IS_NONE: bool = OPTION.is_none(); assert!(!IS_NONE); } + +#[test] +fn test_unwrap_drop() { + struct Dtor<'a> { + x: &'a Cell, + } + + impl<'a> std::ops::Drop for Dtor<'a> { + fn drop(&mut self) { + self.x.set(self.x.get() - 1); + } + } + + fn unwrap(o: Option) -> T { + match o { + Some(v) => v, + None => panic!(), + } + } + + let x = &Cell::new(1); + + { + let b = Some(Dtor { x }); + let _c = unwrap(b); + } + + assert_eq!(x.get(), 0); +} diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 9556d43f9d7..5ef30b1a889 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -1,3 +1,4 @@ +use core::cell::Cell; use core::result::Result::{Err, Ok}; #[test] @@ -1980,3 +1981,30 @@ fn test_is_sorted() { assert!(!["c", "bb", "aaa"].is_sorted()); assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len())); } + +#[test] +fn test_slice_run_destructors() { + // Make sure that destructors get run on slice literals + struct Foo<'a> { + x: &'a Cell, + } + + impl<'a> Drop for Foo<'a> { + fn drop(&mut self) { + self.x.set(self.x.get() + 1); + } + } + + fn foo(x: &Cell) -> Foo<'_> { + Foo { x } + } + + let x = &Cell::new(0); + + { + let l = &[foo(x)]; + assert_eq!(l[0].x.get(), 0); + } + + assert_eq!(x.get(), 1); +} diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index f81ffd2bb94..93fa1f4e585 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -21,6 +21,7 @@ #![feature(nll)] #![feature(staged_api)] #![feature(const_fn)] +#![cfg_attr(not(bootstrap), feature(const_fn_fn_ptr_basics))] #![feature(allow_internal_unstable)] #![feature(decl_macro)] #![feature(extern_types)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index d03428dd082..e343eef9112 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -239,6 +239,7 @@ #![cfg_attr(not(bootstrap), feature(const_fn_floating_point_arithmetic))] #![feature(const_fn_transmute)] #![feature(const_fn)] +#![cfg_attr(not(bootstrap), feature(const_fn_fn_ptr_basics))] #![feature(const_ip)] #![feature(const_ipv6)] #![feature(const_raw_ptr_deref)] diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 18d9c2f11b5..4281867314c 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -411,3 +411,6 @@ pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { pub fn resume_unwind(payload: Box) -> ! { panicking::rust_panic_without_hook(payload) } + +#[cfg(test)] +mod tests; diff --git a/src/test/ui/panics/panic-safe.rs b/library/std/src/panic/tests.rs similarity index 77% rename from src/test/ui/panics/panic-safe.rs rename to library/std/src/panic/tests.rs index 9867cc56406..b37d74011cc 100644 --- a/src/test/ui/panics/panic-safe.rs +++ b/library/std/src/panic/tests.rs @@ -1,16 +1,18 @@ -// run-pass #![allow(dead_code)] -use std::panic::{UnwindSafe, AssertUnwindSafe}; -use std::cell::RefCell; -use std::sync::{Mutex, RwLock, Arc}; -use std::rc::Rc; +use crate::cell::RefCell; +use crate::panic::{AssertUnwindSafe, UnwindSafe}; +use crate::rc::Rc; +use crate::sync::{Arc, Mutex, RwLock}; -struct Foo { a: i32 } +struct Foo { + a: i32, +} fn assert() {} -fn main() { +#[test] +fn panic_safety_traits() { assert::(); assert::<&i32>(); assert::<*mut i32>(); @@ -32,13 +34,16 @@ fn main() { assert::>(); assert::>(); - trait Trait: UnwindSafe {} - assert::>(); + { + trait Trait: UnwindSafe {} + assert::>(); + } fn bar() { assert::>(); assert::>(); } + fn baz() { assert::>(); assert::>(); diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index b48d2162eca..00680fadc18 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -93,60 +93,61 @@ pub fn init() { reset_sigpipe(); } - // In the case when all file descriptors are open, the poll has been - // observed to perform better than fcntl (on GNU/Linux). - #[cfg(not(any( - miri, - target_os = "emscripten", - target_os = "fuchsia", - // The poll on Darwin doesn't set POLLNVAL for closed fds. - target_os = "macos", - target_os = "ios", - target_os = "redox", - )))] - unsafe fn sanitize_standard_fds() { - use crate::sys::os::errno; - let pfds: &mut [_] = &mut [ - libc::pollfd { fd: 0, events: 0, revents: 0 }, - libc::pollfd { fd: 1, events: 0, revents: 0 }, - libc::pollfd { fd: 2, events: 0, revents: 0 }, - ]; - while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 { - if errno() == libc::EINTR { - continue; - } - libc::abort(); - } - for pfd in pfds { - if pfd.revents & libc::POLLNVAL == 0 { - continue; - } - if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 { - // If the stream is closed but we failed to reopen it, abort the - // process. Otherwise we wouldn't preserve the safety of - // operations on the corresponding Rust object Stdin, Stdout, or - // Stderr. - libc::abort(); - } - } - } - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))] - unsafe fn sanitize_standard_fds() { - use crate::sys::os::errno; - for fd in 0..3 { - if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { - if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 { + cfg_if::cfg_if! { + if #[cfg(miri)] { + // The standard fds are always available in Miri. + unsafe fn sanitize_standard_fds() {} + } else if #[cfg(not(any( + target_os = "emscripten", + target_os = "fuchsia", + // The poll on Darwin doesn't set POLLNVAL for closed fds. + target_os = "macos", + target_os = "ios", + target_os = "redox", + )))] { + // In the case when all file descriptors are open, the poll has been + // observed to perform better than fcntl (on GNU/Linux). + unsafe fn sanitize_standard_fds() { + use crate::sys::os::errno; + let pfds: &mut [_] = &mut [ + libc::pollfd { fd: 0, events: 0, revents: 0 }, + libc::pollfd { fd: 1, events: 0, revents: 0 }, + libc::pollfd { fd: 2, events: 0, revents: 0 }, + ]; + while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 { + if errno() == libc::EINTR { + continue; + } libc::abort(); } + for pfd in pfds { + if pfd.revents & libc::POLLNVAL == 0 { + continue; + } + if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 { + // If the stream is closed but we failed to reopen it, abort the + // process. Otherwise we wouldn't preserve the safety of + // operations on the corresponding Rust object Stdin, Stdout, or + // Stderr. + libc::abort(); + } + } } + } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))] { + unsafe fn sanitize_standard_fds() { + use crate::sys::os::errno; + for fd in 0..3 { + if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { + if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 { + libc::abort(); + } + } + } + } + } else { + unsafe fn sanitize_standard_fds() {} } } - #[cfg(any( - // The standard fds are always available in Miri. - miri, - target_os = "emscripten", - target_os = "fuchsia"))] - unsafe fn sanitize_standard_fds() {} #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))] unsafe fn reset_sigpipe() { diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index 9bed06d323e..af39424ec6c 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -410,7 +410,7 @@ reg_spec := / "" operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_" reg_operand := dir_spec "(" reg_spec ")" operand_expr operand := reg_operand / "const" const_expr / "sym" path -option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "att_syntax" +option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" options := "options(" option *["," option] [","] ")" asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) ["," options] [","] ")" ``` diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 074a43f2a70..391859050e8 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -419,6 +419,7 @@ pub fn run_core( (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id) }; }), + make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), }; diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 7b7c152d8ab..7a6c9eabb5f 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -95,6 +95,7 @@ pub fn run(options: Options) -> Result<(), ErrorReported> { lint_caps, register_lints: None, override_queries: None, + make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), }; diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs index af84faa7511..2636423c1a4 100644 --- a/src/test/run-make-fulldeps/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -60,6 +60,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { lint_caps: Default::default(), register_lints: None, override_queries: None, + make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), }; diff --git a/src/test/ui-fulldeps/compiler-calls.rs b/src/test/ui-fulldeps/compiler-calls.rs index e97dcab6ae5..0025b47403d 100644 --- a/src/test/ui-fulldeps/compiler-calls.rs +++ b/src/test/ui-fulldeps/compiler-calls.rs @@ -26,7 +26,13 @@ fn main() { let mut count = 1; let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; rustc_driver::catch_fatal_errors(|| { - rustc_driver::run_compiler(&args, &mut TestCalls { count: &mut count }, None, None).ok(); + rustc_driver::run_compiler( + &args, + &mut TestCalls { count: &mut count }, + None, + None, + None, + ).ok(); }).ok(); assert_eq!(count, 2); } diff --git a/src/test/ui/array-slice-vec/arr_cycle.rs b/src/test/ui/array-slice-vec/arr_cycle.rs deleted file mode 100644 index c262b5a1ff0..00000000000 --- a/src/test/ui/array-slice-vec/arr_cycle.rs +++ /dev/null @@ -1,31 +0,0 @@ -// run-pass - -use std::cell::Cell; - -#[derive(Debug)] -struct B<'a> { - a: [Cell>>; 2] -} - -impl<'a> B<'a> { - fn new() -> B<'a> { - B { a: [Cell::new(None), Cell::new(None)] } - } -} - -fn f() { - let (b1, b2, b3); - b1 = B::new(); - b2 = B::new(); - b3 = B::new(); - b1.a[0].set(Some(&b2)); - b1.a[1].set(Some(&b3)); - b2.a[0].set(Some(&b2)); - b2.a[1].set(Some(&b3)); - b3.a[0].set(Some(&b1)); - b3.a[1].set(Some(&b2)); -} - -fn main() { - f(); -} diff --git a/src/test/ui/array-slice-vec/vec-slice-drop.rs b/src/test/ui/array-slice-vec/vec-slice-drop.rs deleted file mode 100644 index 3a9ea86af34..00000000000 --- a/src/test/ui/array-slice-vec/vec-slice-drop.rs +++ /dev/null @@ -1,31 +0,0 @@ -// run-pass - -#![allow(non_camel_case_types)] - -use std::cell::Cell; - -// Make sure that destructors get run on slice literals -struct foo<'a> { - x: &'a Cell, -} - -impl<'a> Drop for foo<'a> { - fn drop(&mut self) { - self.x.set(self.x.get() + 1); - } -} - -fn foo(x: &Cell) -> foo { - foo { - x: x - } -} - -pub fn main() { - let x = &Cell::new(0); - { - let l = &[foo(x)]; - assert_eq!(l[0].x.get(), 0); - } - assert_eq!(x.get(), 1); -} diff --git a/src/test/ui/array-slice-vec/vec_cycle.rs b/src/test/ui/array-slice-vec/vec_cycle.rs deleted file mode 100644 index 82bce437282..00000000000 --- a/src/test/ui/array-slice-vec/vec_cycle.rs +++ /dev/null @@ -1,39 +0,0 @@ -// run-pass - -use std::cell::Cell; - -#[derive(Debug)] -struct C<'a> { - v: Vec>>>, -} - -impl<'a> C<'a> { - fn new() -> C<'a> { - C { v: Vec::new() } - } -} - -fn f() { - let (mut c1, mut c2, mut c3); - c1 = C::new(); - c2 = C::new(); - c3 = C::new(); - - c1.v.push(Cell::new(None)); - c1.v.push(Cell::new(None)); - c2.v.push(Cell::new(None)); - c2.v.push(Cell::new(None)); - c3.v.push(Cell::new(None)); - c3.v.push(Cell::new(None)); - - c1.v[0].set(Some(&c2)); - c1.v[1].set(Some(&c3)); - c2.v[0].set(Some(&c2)); - c2.v[1].set(Some(&c3)); - c3.v[0].set(Some(&c1)); - c3.v[1].set(Some(&c2)); -} - -fn main() { - f(); -} diff --git a/src/test/ui/array-slice-vec/vec_cycle_wrapped.rs b/src/test/ui/array-slice-vec/vec_cycle_wrapped.rs deleted file mode 100644 index 1a3606d5e8d..00000000000 --- a/src/test/ui/array-slice-vec/vec_cycle_wrapped.rs +++ /dev/null @@ -1,50 +0,0 @@ -// run-pass - -use std::cell::Cell; - -#[derive(Debug)] -struct Refs<'a> { - v: Vec>>>, -} - -#[derive(Debug)] -struct C<'a> { - refs: Refs<'a>, -} - -impl<'a> Refs<'a> { - fn new() -> Refs<'a> { - Refs { v: Vec::new() } - } -} - -impl<'a> C<'a> { - fn new() -> C<'a> { - C { refs: Refs::new() } - } -} - -fn f() { - let (mut c1, mut c2, mut c3); - c1 = C::new(); - c2 = C::new(); - c3 = C::new(); - - c1.refs.v.push(Cell::new(None)); - c1.refs.v.push(Cell::new(None)); - c2.refs.v.push(Cell::new(None)); - c2.refs.v.push(Cell::new(None)); - c3.refs.v.push(Cell::new(None)); - c3.refs.v.push(Cell::new(None)); - - c1.refs.v[0].set(Some(&c2)); - c1.refs.v[1].set(Some(&c3)); - c2.refs.v[0].set(Some(&c2)); - c2.refs.v[1].set(Some(&c3)); - c3.refs.v[0].set(Some(&c1)); - c3.refs.v[1].set(Some(&c2)); -} - -fn main() { - f(); -} diff --git a/src/test/ui/cell-does-not-clone.rs b/src/test/ui/cell-does-not-clone.rs deleted file mode 100644 index 587447b54b7..00000000000 --- a/src/test/ui/cell-does-not-clone.rs +++ /dev/null @@ -1,26 +0,0 @@ -// run-pass - -#![allow(dead_code)] - -use std::cell::Cell; - -#[derive(Copy)] -struct Foo { - x: isize -} - -impl Clone for Foo { - fn clone(&self) -> Foo { - // Using Cell in any way should never cause clone() to be - // invoked -- after all, that would permit evil user code to - // abuse `Cell` and trigger crashes. - - panic!(); - } -} - -pub fn main() { - let x = Cell::new(Foo { x: 22 }); - let _y = x.get(); - let _z = x.clone(); -} diff --git a/src/test/ui/consts/auxiliary/const_fn_lib.rs b/src/test/ui/consts/auxiliary/const_fn_lib.rs index 85714efdbe9..bf0b01a2ecf 100644 --- a/src/test/ui/consts/auxiliary/const_fn_lib.rs +++ b/src/test/ui/consts/auxiliary/const_fn_lib.rs @@ -1,6 +1,6 @@ // Crate that exports a const fn. Used for testing cross-crate. -#![feature(const_fn)] +#![feature(const_fn_fn_ptr_basics)] #![crate_type="rlib"] pub const fn foo() -> usize { 22 } diff --git a/src/test/ui/consts/const-eval/const_fn_ptr.stderr b/src/test/ui/consts/const-eval/const_fn_ptr.stderr index d0ae94079da..ab18020056b 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr.stderr +++ b/src/test/ui/consts/const-eval/const_fn_ptr.stderr @@ -10,11 +10,23 @@ help: skipping check that does not even have a feature gate | LL | X_CONST(x) | ^^^^^^^^^^ +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/const_fn_ptr.rs:19:14 + | +LL | const fn foo(x: fn(usize) -> usize, y: usize) -> usize { + | ^ +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/const_fn_ptr.rs:20:5 + | +LL | x(y) + | ^ help: skipping check that does not even have a feature gate --> $DIR/const_fn_ptr.rs:20:5 | LL | x(y) | ^^^^ -warning: 1 warning emitted +error: `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine + +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr index 90ee2afa315..822d4af8306 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr +++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr @@ -20,6 +20,16 @@ LL | assert_eq!(Z, 4); warning: skipping const checks | +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/const_fn_ptr_fail2.rs:12:14 + | +LL | const fn bar(x: fn(usize) -> usize, y: usize) -> usize { + | ^ +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/const_fn_ptr_fail2.rs:13:5 + | +LL | x(y) + | ^ help: skipping check that does not even have a feature gate --> $DIR/const_fn_ptr_fail2.rs:13:5 | diff --git a/src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs b/src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs index 59d46ea66c9..bf8bae5ea2c 100644 --- a/src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs +++ b/src/test/ui/consts/const-eval/issue-70804-fn-subtyping.rs @@ -1,5 +1,5 @@ // check-pass -#![feature(const_fn)] +#![feature(const_fn_fn_ptr_basics)] const fn nested(x: (for<'a> fn(&'a ()), String)) -> (fn(&'static ()), String) { x diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs index 094ae7378bc..8642954a75b 100644 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs @@ -2,7 +2,7 @@ const extern fn unsize(x: &[u8; 3]) -> &[u8] { x } const unsafe extern "C" fn closure() -> fn() { || {} } -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer const unsafe extern fn use_float() { 1.0 + 1.0; } //~^ ERROR floating point arithmetic const extern "C" fn ptr_cast(val: *const u8) { val as usize; } diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr index fcc34f358f9..455a822e2d0 100644 --- a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr @@ -1,11 +1,11 @@ -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/const-extern-fn-min-const-fn.rs:4:41 | LL | const unsafe extern "C" fn closure() -> fn() { || {} } | ^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error[E0658]: floating point arithmetic is not allowed in constant functions --> $DIR/const-extern-fn-min-const-fn.rs:6:38 @@ -27,5 +27,4 @@ LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; } error: aborting due to 3 previous errors -Some errors have detailed explanations: E0658, E0723. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/issue-37550.rs b/src/test/ui/consts/issue-37550.rs index 04865830df2..15877c53747 100644 --- a/src/test/ui/consts/issue-37550.rs +++ b/src/test/ui/consts/issue-37550.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] #![allow(unused_variables)] -#![feature(const_fn)] +#![feature(const_fn_fn_ptr_basics)] const fn x() { let t = true; diff --git a/src/test/ui/consts/issue-56164.rs b/src/test/ui/consts/issue-56164.rs index 9d1a8b59463..90ea217698d 100644 --- a/src/test/ui/consts/issue-56164.rs +++ b/src/test/ui/consts/issue-56164.rs @@ -1,12 +1,11 @@ -#![feature(const_fn)] +#![feature(const_fn_fn_ptr_basics)] const fn foo() { (||{})() } -//~^ ERROR calls in constant functions are limited to constant functions, tuple structs and tuple -// variants +//~^ ERROR calls in constant functions const fn bad(input: fn()) { input() - //~^ ERROR function pointers are not allowed in const fn + //~^ ERROR function pointer } fn main() { diff --git a/src/test/ui/consts/issue-56164.stderr b/src/test/ui/consts/issue-56164.stderr index d3e9ce379ae..500af0a4006 100644 --- a/src/test/ui/consts/issue-56164.stderr +++ b/src/test/ui/consts/issue-56164.stderr @@ -5,7 +5,7 @@ LL | const fn foo() { (||{})() } | ^^^^^^^^ error: function pointers are not allowed in const fn - --> $DIR/issue-56164.rs:8:5 + --> $DIR/issue-56164.rs:7:5 | LL | input() | ^^^^^^^ diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs index 937aae1a8e3..dc10db177ed 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs @@ -1,12 +1,14 @@ -#![feature(rustc_attrs, staged_api)] +#![feature(rustc_attrs, staged_api, allow_internal_unstable)] +#![feature(const_fn_fn_ptr_basics)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(since="1.0.0", feature = "mep")] -const fn error(_: fn()) {} //~ ERROR function pointers in const fn are unstable +const fn error(_: fn()) {} +//~^ ERROR const-stable function cannot use `#[feature(const_fn_fn_ptr_basics)]` #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allow_const_fn_ptr] #[rustc_const_stable(since="1.0.0", feature = "mep")] +#[allow_internal_unstable(const_fn_fn_ptr_basics)] const fn compiles(_: fn()) {} fn main() {} diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr index 9a14bcc2f73..94f6cda2097 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr @@ -1,12 +1,14 @@ -error[E0723]: function pointers in const fn are unstable - --> $DIR/allow_const_fn_ptr.rs:5:16 +error: const-stable function cannot use `#[feature(const_fn_fn_ptr_basics)]` + --> $DIR/allow_const_fn_ptr.rs:6:16 | LL | const fn error(_: fn()) {} | ^ | - = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = note: otherwise `#[allow_internal_unstable]` can be used to bypass stability checks +help: if it is not part of the public API, make this function unstably const + | +LL | #[rustc_const_unstable(feature = "...", issue = "...")] + | error: aborting due to previous error -For more information about this error, try `rustc --explain E0723`. diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs deleted file mode 100644 index 0f9d3729295..00000000000 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.rs +++ /dev/null @@ -1,11 +0,0 @@ -#![feature(staged_api)] - -#[stable(feature = "rust1", since = "1.0.0")] -const fn error(_: fn()) {} - -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allow_const_fn_ptr] -//~^ ERROR internal implementation detail -const fn compiles(_: fn()) {} - -fn main() {} diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr deleted file mode 100644 index 7794cc7583d..00000000000 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_feature_gate.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: internal implementation detail - --> $DIR/allow_const_fn_ptr_feature_gate.rs:7:1 - | -LL | #[rustc_allow_const_fn_ptr] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs index 7aa9bd7e2dc..b4e836bbc95 100644 --- a/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs +++ b/src/test/ui/consts/min_const_fn/allow_const_fn_ptr_run_pass.rs @@ -1,11 +1,13 @@ // run-pass +#![feature(allow_internal_unstable)] +#![feature(const_fn_fn_ptr_basics)] #![feature(rustc_attrs, staged_api)] #![stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_allow_const_fn_ptr] #[rustc_const_stable(since="1.0.0", feature = "mep")] +#[allow_internal_unstable(const_fn_fn_ptr_basics)] const fn takes_fn_ptr(_: fn()) {} const FN: fn() = || (); diff --git a/src/test/ui/consts/min_const_fn/cast_errors.rs b/src/test/ui/consts/min_const_fn/cast_errors.rs index 8d730df16b0..43ef8ea12eb 100644 --- a/src/test/ui/consts/min_const_fn/cast_errors.rs +++ b/src/test/ui/consts/min_const_fn/cast_errors.rs @@ -2,12 +2,12 @@ fn main() {} const fn unsize(x: &[u8; 3]) -> &[u8] { x } const fn closure() -> fn() { || {} } -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer const fn closure2() { (|| {}) as fn(); -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer } const fn reify(f: fn()) -> unsafe fn() { f } -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer const fn reify2() { main as unsafe fn(); } -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer diff --git a/src/test/ui/consts/min_const_fn/cast_errors.stderr b/src/test/ui/consts/min_const_fn/cast_errors.stderr index 583cb4e9720..ac77c181afd 100644 --- a/src/test/ui/consts/min_const_fn/cast_errors.stderr +++ b/src/test/ui/consts/min_const_fn/cast_errors.stderr @@ -1,39 +1,39 @@ -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/cast_errors.rs:4:23 | LL | const fn closure() -> fn() { || {} } | ^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/cast_errors.rs:7:5 | LL | (|| {}) as fn(); | ^^^^^^^^^^^^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/cast_errors.rs:10:28 | LL | const fn reify(f: fn()) -> unsafe fn() { f } | ^^^^^^^^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/cast_errors.rs:12:21 | LL | const fn reify2() { main as unsafe fn(); } | ^^^^^^^^^^^^^^^^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0723`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs index c2600f894dc..4aaf7b86e45 100644 --- a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs +++ b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs @@ -1,4 +1,4 @@ -const fn cmp(x: fn(), y: fn()) -> bool { //~ ERROR function pointers in const fn are unstable +const fn cmp(x: fn(), y: fn()) -> bool { //~ ERROR function pointer unsafe { x == y } } diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr index 74e5228d0dc..e913b187fee 100644 --- a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr +++ b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr @@ -1,12 +1,12 @@ -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/cmp_fn_pointers.rs:1:14 | LL | const fn cmp(x: fn(), y: fn()) -> bool { | ^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error: aborting due to previous error -For more information about this error, try `rustc --explain E0723`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs index 55a999d5cdc..06a44b27106 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs @@ -128,6 +128,6 @@ const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } //~^ ERROR trait bounds other than `Sized` const fn no_fn_ptrs(_x: fn()) {} -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } -//~^ ERROR function pointers in const fn are unstable +//~^ ERROR function pointer diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index a37e5203eee..5e6bf7ef890 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -209,23 +209,23 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 = note: see issue #57563 for more information = help: add `#![feature(const_fn)]` to the crate attributes to enable -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/min_const_fn.rs:130:21 | LL | const fn no_fn_ptrs(_x: fn()) {} | ^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/min_const_fn.rs:132:27 | LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } | ^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error: aborting due to 26 previous errors diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs index 584ea46b1a6..bc6fe89222b 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.rs @@ -1,3 +1,5 @@ +// gate-test-const_fn_fn_ptr_basics + struct HasPtr { field: fn(), } @@ -9,9 +11,9 @@ fn field() {} const fn no_inner_dyn_trait(_x: Hide) {} const fn no_inner_dyn_trait2(x: Hide) { x.0.field; -//~^ ERROR function pointers in const fn +//~^ ERROR function pointer } const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) } -//~^ ERROR function pointers in const fn +//~^ ERROR function pointer fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr index 58acbb5339a..8d60436ea39 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_fn_ptr.stderr @@ -1,21 +1,21 @@ -error[E0723]: function pointers in const fn are unstable - --> $DIR/min_const_fn_fn_ptr.rs:11:5 +error[E0658]: function pointers cannot appear in constant functions + --> $DIR/min_const_fn_fn_ptr.rs:13:5 | LL | x.0.field; | ^^^^^^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable -error[E0723]: function pointers in const fn are unstable - --> $DIR/min_const_fn_fn_ptr.rs:14:59 +error[E0658]: function pointers cannot appear in constant functions + --> $DIR/min_const_fn_fn_ptr.rs:16:59 | LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasPtr { field }) } | ^^^^^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0723`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr index 93b67fd7b14..8fd562c5dae 100644 --- a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr +++ b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr @@ -12,12 +12,12 @@ LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern " warning: skipping const checks | -help: skipping check for `const_fn` feature +help: skipping check for `const_fn_fn_ptr_basics` feature --> $DIR/abi-mismatch.rs:9:23 | LL | const fn call_rust_fn(my_fn: extern "Rust" fn()) { | ^^^^^ -help: skipping check for `const_fn` feature +help: skipping check for `const_fn_fn_ptr_basics` feature --> $DIR/abi-mismatch.rs:10:5 | LL | my_fn(); diff --git a/src/test/ui/deref-lval.rs b/src/test/ui/deref-lval.rs deleted file mode 100644 index f57872f80e0..00000000000 --- a/src/test/ui/deref-lval.rs +++ /dev/null @@ -1,11 +0,0 @@ -// run-pass - -#![feature(box_syntax)] - -use std::cell::Cell; - -pub fn main() { - let x: Box<_> = box Cell::new(5); - x.set(1000); - println!("{}", x.get()); -} diff --git a/src/test/ui/exterior.rs b/src/test/ui/exterior.rs deleted file mode 100644 index 6f2c37926be..00000000000 --- a/src/test/ui/exterior.rs +++ /dev/null @@ -1,24 +0,0 @@ -// run-pass - -#![allow(dead_code)] - - -use std::cell::Cell; - -#[derive(Copy, Clone)] -struct Point {x: isize, y: isize, z: isize} - -fn f(p: &Cell) { - assert_eq!(p.get().z, 12); - p.set(Point {x: 10, y: 11, z: 13}); - assert_eq!(p.get().z, 13); -} - -pub fn main() { - let a: Point = Point {x: 10, y: 11, z: 12}; - let b: &Cell = &Cell::new(a); - assert_eq!(b.get().z, 12); - f(b); - assert_eq!(a.z, 12); - assert_eq!(b.get().z, 13); -} diff --git a/src/test/ui/format-ref-cell.rs b/src/test/ui/format-ref-cell.rs deleted file mode 100644 index afb2f8488b8..00000000000 --- a/src/test/ui/format-ref-cell.rs +++ /dev/null @@ -1,10 +0,0 @@ -// run-pass - -use std::cell::RefCell; - -pub fn main() { - let name = RefCell::new("rust"); - let what = RefCell::new("rocks"); - let msg = format!("{name} {}", &*what.borrow(), name=&*name.borrow()); - assert_eq!(msg, "rust rocks".to_string()); -} diff --git a/src/test/ui/ifmt.rs b/src/test/ui/ifmt.rs deleted file mode 100644 index 27ab3d6b7ab..00000000000 --- a/src/test/ui/ifmt.rs +++ /dev/null @@ -1,319 +0,0 @@ -// run-pass - -#![deny(warnings)] -#![allow(unused_must_use)] -#![allow(unused_features)] -#![feature(box_syntax)] - -use std::cell::RefCell; -use std::fmt::{self, Write}; -use std::usize; - -struct A; -struct B; -struct C; -struct D; - -impl fmt::LowerHex for A { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("aloha") - } -} -impl fmt::UpperHex for B { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("adios") - } -} -impl fmt::Display for C { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad_integral(true, "☃", "123") - } -} -impl fmt::Binary for D { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str("aa")?; - f.write_char('☃')?; - f.write_str("bb") - } -} - -macro_rules! t { - ($a:expr, $b:expr) => { assert_eq!($a, $b) } -} - -pub fn main() { - // Various edge cases without formats - t!(format!(""), ""); - t!(format!("hello"), "hello"); - t!(format!("hello {{"), "hello {"); - - // default formatters should work - t!(format!("{}", 1.0f32), "1"); - t!(format!("{}", 1.0f64), "1"); - t!(format!("{}", "a"), "a"); - t!(format!("{}", "a".to_string()), "a"); - t!(format!("{}", false), "false"); - t!(format!("{}", 'a'), "a"); - - // At least exercise all the formats - t!(format!("{}", true), "true"); - t!(format!("{}", '☃'), "☃"); - t!(format!("{}", 10), "10"); - t!(format!("{}", 10_usize), "10"); - t!(format!("{:?}", '☃'), "'☃'"); - t!(format!("{:?}", 10), "10"); - t!(format!("{:?}", 10_usize), "10"); - t!(format!("{:?}", "true"), "\"true\""); - t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\""); - t!(format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"), - r#""foo\n\"bar\"\r\n\'baz\'\t\\qux\\""#); - t!(format!("{:?}", "foo\0bar\x01baz\u{7f}q\u{75}x"), - r#""foo\u{0}bar\u{1}baz\u{7f}qux""#); - t!(format!("{:o}", 10_usize), "12"); - t!(format!("{:x}", 10_usize), "a"); - t!(format!("{:X}", 10_usize), "A"); - t!(format!("{}", "foo"), "foo"); - t!(format!("{}", "foo".to_string()), "foo"); - if cfg!(target_pointer_width = "32") { - t!(format!("{:#p}", 0x1234 as *const isize), "0x00001234"); - t!(format!("{:#p}", 0x1234 as *mut isize), "0x00001234"); - } else { - t!(format!("{:#p}", 0x1234 as *const isize), "0x0000000000001234"); - t!(format!("{:#p}", 0x1234 as *mut isize), "0x0000000000001234"); - } - t!(format!("{:p}", 0x1234 as *const isize), "0x1234"); - t!(format!("{:p}", 0x1234 as *mut isize), "0x1234"); - t!(format!("{:x}", A), "aloha"); - t!(format!("{:X}", B), "adios"); - t!(format!("foo {} ☃☃☃☃☃☃", "bar"), "foo bar ☃☃☃☃☃☃"); - t!(format!("{1} {0}", 0, 1), "1 0"); - t!(format!("{foo} {bar}", foo=0, bar=1), "0 1"); - t!(format!("{foo} {1} {bar} {0}", 0, 1, foo=2, bar=3), "2 1 3 0"); - t!(format!("{} {0}", "a"), "a a"); - t!(format!("{_foo}", _foo = 6usize), "6"); - t!(format!("{foo_bar}", foo_bar=1), "1"); - t!(format!("{}", 5 + 5), "10"); - t!(format!("{:#4}", C), "☃123"); - t!(format!("{:b}", D), "aa☃bb"); - - let a: &dyn fmt::Debug = &1; - t!(format!("{:?}", a), "1"); - - // Formatting strings and their arguments - t!(format!("{}", "a"), "a"); - t!(format!("{:4}", "a"), "a "); - t!(format!("{:4}", "☃"), "☃ "); - t!(format!("{:>4}", "a"), " a"); - t!(format!("{:<4}", "a"), "a "); - t!(format!("{:^5}", "a"), " a "); - t!(format!("{:^5}", "aa"), " aa "); - t!(format!("{:^4}", "a"), " a "); - t!(format!("{:^4}", "aa"), " aa "); - t!(format!("{:.4}", "a"), "a"); - t!(format!("{:4.4}", "a"), "a "); - t!(format!("{:4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:<4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:>4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:^4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), " aaaa"); - t!(format!("{:2.4}", "aaaaa"), "aaaa"); - t!(format!("{:2.4}", "aaaa"), "aaaa"); - t!(format!("{:2.4}", "aaa"), "aaa"); - t!(format!("{:2.4}", "aa"), "aa"); - t!(format!("{:2.4}", "a"), "a "); - t!(format!("{:0>2}", "a"), "0a"); - t!(format!("{:.*}", 4, "aaaaaaaaaaaaaaaaaa"), "aaaa"); - t!(format!("{:.1$}", "aaaaaaaaaaaaaaaaaa", 4), "aaaa"); - t!(format!("{:.a$}", "aaaaaaaaaaaaaaaaaa", a=4), "aaaa"); - t!(format!("{:._a$}", "aaaaaaaaaaaaaaaaaa", _a=4), "aaaa"); - t!(format!("{:1$}", "a", 4), "a "); - t!(format!("{1:0$}", 4, "a"), "a "); - t!(format!("{:a$}", "a", a=4), "a "); - t!(format!("{:-#}", "a"), "a"); - t!(format!("{:+#}", "a"), "a"); - t!(format!("{:/^10.8}", "1234567890"), "/12345678/"); - - // Some float stuff - t!(format!("{:}", 1.0f32), "1"); - t!(format!("{:}", 1.0f64), "1"); - t!(format!("{:.3}", 1.0f64), "1.000"); - t!(format!("{:10.3}", 1.0f64), " 1.000"); - t!(format!("{:+10.3}", 1.0f64), " +1.000"); - t!(format!("{:+10.3}", -1.0f64), " -1.000"); - - t!(format!("{:e}", 1.2345e6f32), "1.2345e6"); - t!(format!("{:e}", 1.2345e6f64), "1.2345e6"); - t!(format!("{:E}", 1.2345e6f64), "1.2345E6"); - t!(format!("{:.3e}", 1.2345e6f64), "1.234e6"); - t!(format!("{:10.3e}", 1.2345e6f64), " 1.234e6"); - t!(format!("{:+10.3e}", 1.2345e6f64), " +1.234e6"); - t!(format!("{:+10.3e}", -1.2345e6f64), " -1.234e6"); - - // Float edge cases - t!(format!("{}", -0.0), "0"); - t!(format!("{:?}", -0.0), "-0.0"); - t!(format!("{:?}", 0.0), "0.0"); - - // sign aware zero padding - t!(format!("{:<3}", 1), "1 "); - t!(format!("{:>3}", 1), " 1"); - t!(format!("{:^3}", 1), " 1 "); - t!(format!("{:03}", 1), "001"); - t!(format!("{:<03}", 1), "001"); - t!(format!("{:>03}", 1), "001"); - t!(format!("{:^03}", 1), "001"); - t!(format!("{:+03}", 1), "+01"); - t!(format!("{:<+03}", 1), "+01"); - t!(format!("{:>+03}", 1), "+01"); - t!(format!("{:^+03}", 1), "+01"); - t!(format!("{:#05x}", 1), "0x001"); - t!(format!("{:<#05x}", 1), "0x001"); - t!(format!("{:>#05x}", 1), "0x001"); - t!(format!("{:^#05x}", 1), "0x001"); - t!(format!("{:05}", 1.2), "001.2"); - t!(format!("{:<05}", 1.2), "001.2"); - t!(format!("{:>05}", 1.2), "001.2"); - t!(format!("{:^05}", 1.2), "001.2"); - t!(format!("{:05}", -1.2), "-01.2"); - t!(format!("{:<05}", -1.2), "-01.2"); - t!(format!("{:>05}", -1.2), "-01.2"); - t!(format!("{:^05}", -1.2), "-01.2"); - t!(format!("{:+05}", 1.2), "+01.2"); - t!(format!("{:<+05}", 1.2), "+01.2"); - t!(format!("{:>+05}", 1.2), "+01.2"); - t!(format!("{:^+05}", 1.2), "+01.2"); - - // Ergonomic format_args! - t!(format!("{0:x} {0:X}", 15), "f F"); - t!(format!("{0:x} {0:X} {}", 15), "f F 15"); - t!(format!("{:x}{0:X}{a:x}{:X}{1:x}{a:X}", 13, 14, a=15), "dDfEeF"); - t!(format!("{a:x} {a:X}", a=15), "f F"); - - // And its edge cases - t!(format!("{a:.0$} {b:.0$} {0:.0$}\n{a:.c$} {b:.c$} {c:.c$}", - 4, a="abcdefg", b="hijklmn", c=3), - "abcd hijk 4\nabc hij 3"); - t!(format!("{a:.*} {0} {:.*}", 4, 3, "efgh", a="abcdef"), "abcd 4 efg"); - t!(format!("{:.a$} {a} {a:#x}", "aaaaaa", a=2), "aa 2 0x2"); - - // Test that pointers don't get truncated. - { - let val = usize::MAX; - let exp = format!("{:#x}", val); - t!(format!("{:p}", val as *const isize), exp); - } - - // Escaping - t!(format!("{{"), "{"); - t!(format!("}}"), "}"); - - test_write(); - test_print(); - test_order(); - test_once(); - - // make sure that format! doesn't move out of local variables - let a: Box<_> = box 3; - format!("{}", a); - format!("{}", a); - - // make sure that format! doesn't cause spurious unused-unsafe warnings when - // it's inside of an outer unsafe block - unsafe { - let a: isize = ::std::mem::transmute(3_usize); - format!("{}", a); - } - - test_format_args(); - - // test that trailing commas are acceptable - format!("{}", "test",); - format!("{foo}", foo="test",); - - test_refcell(); -} - -// Basic test to make sure that we can invoke the `write!` macro with an -// fmt::Write instance. -fn test_write() { - let mut buf = String::new(); - write!(&mut buf, "{}", 3); - { - let w = &mut buf; - write!(w, "{foo}", foo=4); - write!(w, "{}", "hello"); - writeln!(w, "{}", "line"); - writeln!(w, "{foo}", foo="bar"); - w.write_char('☃'); - w.write_str("str"); - } - - t!(buf, "34helloline\nbar\n☃str"); -} - -// Just make sure that the macros are defined, there's not really a lot that we -// can do with them just yet (to test the output) -fn test_print() { - print!("hi"); - print!("{:?}", vec![0u8]); - println!("hello"); - println!("this is a {}", "test"); - println!("{foo}", foo="bar"); -} - -// Just make sure that the macros are defined, there's not really a lot that we -// can do with them just yet (to test the output) -fn test_format_args() { - let mut buf = String::new(); - { - let w = &mut buf; - write!(w, "{}", format_args!("{}", 1)); - write!(w, "{}", format_args!("test")); - write!(w, "{}", format_args!("{test}", test=3)); - } - let s = buf; - t!(s, "1test3"); - - let s = fmt::format(format_args!("hello {}", "world")); - t!(s, "hello world"); - let s = format!("{}: {}", "args were", format_args!("hello {}", "world")); - t!(s, "args were: hello world"); -} - -fn test_order() { - // Make sure format!() arguments are always evaluated in a left-to-right - // ordering - fn foo() -> isize { - static mut FOO: isize = 0; - unsafe { - FOO += 1; - FOO - } - } - assert_eq!(format!("{} {} {a} {b} {} {c}", - foo(), foo(), foo(), a=foo(), b=foo(), c=foo()), - "1 2 4 5 3 6".to_string()); -} - -fn test_once() { - // Make sure each argument are evaluated only once even though it may be - // formatted multiple times - fn foo() -> isize { - static mut FOO: isize = 0; - unsafe { - FOO += 1; - FOO - } - } - assert_eq!(format!("{0} {0} {0} {a} {a} {a}", foo(), a=foo()), - "1 1 1 2 2 2".to_string()); -} - -fn test_refcell() { - let refcell = RefCell::new(5); - assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }"); - let borrow = refcell.borrow_mut(); - assert_eq!(format!("{:?}", refcell), "RefCell { value: }"); - drop(borrow); - assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }"); -} diff --git a/src/test/ui/issues/issue-37550.rs b/src/test/ui/issues/issue-37550.rs index 505c030b967..35b63bddca2 100644 --- a/src/test/ui/issues/issue-37550.rs +++ b/src/test/ui/issues/issue-37550.rs @@ -1,6 +1,6 @@ const fn x() { let t = true; - let x = || t; //~ ERROR function pointers in const fn are unstable + let x = || t; //~ ERROR function pointer } fn main() {} diff --git a/src/test/ui/issues/issue-37550.stderr b/src/test/ui/issues/issue-37550.stderr index 35da6258016..54b60df70fd 100644 --- a/src/test/ui/issues/issue-37550.stderr +++ b/src/test/ui/issues/issue-37550.stderr @@ -1,12 +1,12 @@ -error[E0723]: function pointers in const fn are unstable +error[E0658]: function pointers cannot appear in constant functions --> $DIR/issue-37550.rs:3:9 | LL | let x = || t; | ^ | = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable + = help: add `#![feature(const_fn_fn_ptr_basics)]` to the crate attributes to enable error: aborting due to previous error -For more information about this error, try `rustc --explain E0723`. +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-46553.rs b/src/test/ui/issues/issue-46553.rs index e21a532effd..0a1e835672d 100644 --- a/src/test/ui/issues/issue-46553.rs +++ b/src/test/ui/issues/issue-46553.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(const_fn)] +#![feature(const_fn_fn_ptr_basics)] #![deny(const_err)] pub struct Data { diff --git a/src/test/ui/issues/issue-51154.rs b/src/test/ui/issues/issue-51154.rs new file mode 100644 index 00000000000..12903f79010 --- /dev/null +++ b/src/test/ui/issues/issue-51154.rs @@ -0,0 +1,6 @@ +fn foo() { + let _: Box = Box::new(|| ()); + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/issues/issue-51154.stderr b/src/test/ui/issues/issue-51154.stderr new file mode 100644 index 00000000000..3c3428f3096 --- /dev/null +++ b/src/test/ui/issues/issue-51154.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/issue-51154.rs:2:30 + | +LL | fn foo() { + | - this type parameter +LL | let _: Box = Box::new(|| ()); + | ^^^^^ expected type parameter `F`, found closure + | + = note: expected type parameter `F` + found closure `[closure@$DIR/issue-51154.rs:2:30: 2:35]` + = help: every closure has a distinct type and so could not always match the caller-chosen type of parameter `F` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/iterators/iter-zip.rs b/src/test/ui/iterators/iter-zip.rs deleted file mode 100644 index a76fa2408bb..00000000000 --- a/src/test/ui/iterators/iter-zip.rs +++ /dev/null @@ -1,103 +0,0 @@ -// run-pass -// Test that .zip() specialization preserves side effects -// in sideeffectful iterator adaptors. - -use std::cell::Cell; - -#[derive(Debug)] -struct CountClone(Cell); - -fn count_clone() -> CountClone { CountClone(Cell::new(0)) } - -impl PartialEq for CountClone { - fn eq(&self, rhs: &i32) -> bool { - self.0.get() == *rhs - } -} - -impl Clone for CountClone { - fn clone(&self) -> Self { - let ret = CountClone(self.0.clone()); - let n = self.0.get(); - self.0.set(n + 1); - ret - } -} - -fn test_zip_cloned_sideffectful() { - let xs = [count_clone(), count_clone(), count_clone(), count_clone()]; - let ys = [count_clone(), count_clone()]; - - for _ in xs.iter().cloned().zip(ys.iter().cloned()) { } - - assert_eq!(&xs, &[1, 1, 1, 0][..]); - assert_eq!(&ys, &[1, 1][..]); - - let xs = [count_clone(), count_clone()]; - let ys = [count_clone(), count_clone(), count_clone(), count_clone()]; - - for _ in xs.iter().cloned().zip(ys.iter().cloned()) { } - - assert_eq!(&xs, &[1, 1][..]); - assert_eq!(&ys, &[1, 1, 0, 0][..]); -} - -fn test_zip_map_sideffectful() { - let mut xs = [0; 6]; - let mut ys = [0; 4]; - - for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) { } - - assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]); - assert_eq!(&ys, &[1, 1, 1, 1]); - - let mut xs = [0; 4]; - let mut ys = [0; 6]; - - for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) { } - - assert_eq!(&xs, &[1, 1, 1, 1]); - assert_eq!(&ys, &[1, 1, 1, 1, 0, 0]); -} - -fn test_zip_map_rev_sideffectful() { - let mut xs = [0; 6]; - let mut ys = [0; 4]; - - { - let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)); - it.next_back(); - } - assert_eq!(&xs, &[0, 0, 0, 1, 1, 1]); - assert_eq!(&ys, &[0, 0, 0, 1]); - - let mut xs = [0; 6]; - let mut ys = [0; 4]; - - { - let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)); - (&mut it).take(5).count(); - it.next_back(); - } - assert_eq!(&xs, &[1, 1, 1, 1, 1, 1]); - assert_eq!(&ys, &[1, 1, 1, 1]); -} - -fn test_zip_nested_sideffectful() { - let mut xs = [0; 6]; - let ys = [0; 4]; - - { - // test that it has the side effect nested inside enumerate - let it = xs.iter_mut().map(|x| *x = 1).enumerate().zip(&ys); - it.count(); - } - assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]); -} - -fn main() { - test_zip_cloned_sideffectful(); - test_zip_map_sideffectful(); - test_zip_map_rev_sideffectful(); - test_zip_nested_sideffectful(); -} diff --git a/src/test/ui/option-unwrap.rs b/src/test/ui/option-unwrap.rs deleted file mode 100644 index 173f803ee24..00000000000 --- a/src/test/ui/option-unwrap.rs +++ /dev/null @@ -1,32 +0,0 @@ -// run-pass - -#![allow(non_camel_case_types)] -use std::cell::Cell; - -struct dtor<'a> { - x: &'a Cell, -} - -impl<'a> Drop for dtor<'a> { - fn drop(&mut self) { - self.x.set(self.x.get() - 1); - } -} - -fn unwrap(o: Option) -> T { - match o { - Some(v) => v, - None => panic!() - } -} - -pub fn main() { - let x = &Cell::new(1); - - { - let b = Some(dtor { x:x }); - let _c = unwrap(b); - } - - assert_eq!(x.get(), 0); -} diff --git a/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr b/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr index cf8ca57714c..0291a526333 100644 --- a/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr +++ b/src/test/ui/rfc-2091-track-caller/caller-location-fnptr-rt-ctfe-equiv.stderr @@ -1,10 +1,27 @@ warning: skipping const checks | +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:20:9 + | +LL | let ptr: fn() -> L = attributed; + | ^^^ +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:21:5 + | +LL | ptr() + | ^^^ +help: skipping check for `const_fn_fn_ptr_basics` feature + --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:20:26 + | +LL | let ptr: fn() -> L = attributed; + | ^^^^^^^^^^ help: skipping check that does not even have a feature gate --> $DIR/caller-location-fnptr-rt-ctfe-equiv.rs:21:5 | LL | ptr() | ^^^^^ -warning: 1 warning emitted +error: `-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature gates, except when testing error paths in the CTFE engine + +error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/issue-53096.rs b/src/test/ui/type-alias-impl-trait/issue-53096.rs index 564c5c3d33f..bdf426bbd37 100644 --- a/src/test/ui/type-alias-impl-trait/issue-53096.rs +++ b/src/test/ui/type-alias-impl-trait/issue-53096.rs @@ -1,5 +1,5 @@ // check-pass -#![feature(const_fn)] +#![feature(const_fn, const_fn_fn_ptr_basics)] #![feature(type_alias_impl_trait)] type Foo = impl Fn() -> usize; diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 47315fa64cd..f4f2259cefd 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -357,7 +357,7 @@ pub fn main() { args.extend(vec!["--sysroot".into(), sys_root]); }; - return rustc_driver::run_compiler(&args, &mut DefaultCallbacks, None, None); + return rustc_driver::run_compiler(&args, &mut DefaultCallbacks, None, None, None); } if orig_args.iter().any(|a| a == "--version" || a == "-V") { @@ -420,6 +420,6 @@ pub fn main() { let mut default = DefaultCallbacks; let callbacks: &mut (dyn rustc_driver::Callbacks + Send) = if clippy_enabled { &mut clippy } else { &mut default }; - rustc_driver::run_compiler(&args, callbacks, None, None) + rustc_driver::run_compiler(&args, callbacks, None, None, None) })) }