diff --git a/config.toml.example b/config.toml.example index c37cd4a985727..9b7327ea69e0b 100644 --- a/config.toml.example +++ b/config.toml.example @@ -444,6 +444,10 @@ # Use LLVM libunwind as the implementation for Rust's unwinder. #llvm-libunwind = false +# Enable Windows Control Flow Guard checks in the standard library. +# This only applies from stage 1 onwards, and only for Windows targets. +#control-flow-guard = false + # ============================================================================= # Options for specific targets # diff --git a/rustfmt.toml b/rustfmt.toml index 2a034845c6e0b..8f4c901fb9740 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -7,6 +7,7 @@ merge_derives = false # tidy only checks files which are not ignored, each entry follows gitignore style ignore = [ "build", + "/vendor/", # tests for now are not formatted, as they are sometimes pretty-printing constrained # (and generally rustfmt can move around comments in UI-testing incompatible ways) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index d0eed3f12d117..e4b57cddfb891 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1135,6 +1135,20 @@ impl<'a> Builder<'a> { ); } + // If Control Flow Guard is enabled, pass the `control_flow_guard=checks` flag to rustc + // when compiling the standard library, since this might be linked into the final outputs + // produced by rustc. Since this mitigation is only available on Windows, only enable it + // for the standard library in case the compiler is run on a non-Windows platform. + // This is not needed for stage 0 artifacts because these will only be used for building + // the stage 1 compiler. + if cfg!(windows) + && mode == Mode::Std + && self.config.control_flow_guard + && compiler.stage >= 1 + { + rustflags.arg("-Zcontrol_flow_guard=checks"); + } + // For `cargo doc` invocations, make rustdoc print the Rust version into the docs cargo.env("RUSTDOC_CRATE_VERSION", self.rust_version()); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index ac530da3557da..214d572329ec6 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -116,6 +116,7 @@ pub struct Config { pub targets: Vec>, pub local_rebuild: bool, pub jemalloc: bool, + pub control_flow_guard: bool, // dist misc pub dist_sign_folder: Option, @@ -333,6 +334,7 @@ struct Rust { jemalloc: Option, test_compare_mode: Option, llvm_libunwind: Option, + control_flow_guard: Option, } /// TOML representation of how each build target is configured. @@ -580,6 +582,7 @@ impl Config { set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir); config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit; set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo); + set(&mut config.control_flow_guard, rust.control_flow_guard); if let Some(ref backends) = rust.codegen_backends { config.rust_codegen_backends = diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 7cfc5385e2104..1fdd5d13e7fe7 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -60,6 +60,7 @@ def v(*args): o("lldb", "rust.lldb", "build lldb") o("missing-tools", "dist.missing-tools", "allow failures when building tools") o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++") +o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard") o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags") o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags") diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 77b80e0f71deb..a476d25f10214 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -103,7 +103,6 @@ //! More documentation can be found in each respective module below, and you can //! also check out the `src/bootstrap/README.md` file for more information. -#![feature(core_intrinsics)] #![feature(drain_filter)] use std::cell::{Cell, RefCell}; diff --git a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md new file mode 100644 index 0000000000000..f871df46250ba --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md @@ -0,0 +1,34 @@ +# `control_flow_guard` + +The tracking issue for this feature is: [#68793](https://github.com/rust-lang/rust/issues/68793). + +------------------------ + +The `-Zcontrol_flow_guard=checks` compiler flag enables the Windows [Control Flow Guard][cfguard-docs] platform security feature. When enabled, the compiler outputs a list of valid indirect call targets, and inserts runtime checks on all indirect jump instructions to ensure that the destination is in the list of valid call targets. + +[cfguard-docs]: https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard + +For testing purposes, the `-Zcontrol_flow_guard=nochecks` compiler flag can be used to emit only the list of valid call targets, but not the runtime checks. + +It is strongly recommended to also enable Control Flow Guard checks in all linked libraries, including the standard library. + +To enable Control Flow Guard in the standard library, you can use the [cargo `-Zbuild-std` functionality][build-std] to recompile the standard library with the same configuration options as the main program. + +[build-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std + +For example: +```cmd +rustup toolchain install --force nightly +rustup component add rust-src +SET RUSTFLAGS=-Zcontrol_flow_guard=checks +cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc +``` + +```PowerShell +rustup toolchain install --force nightly +rustup component add rust-src +$Env:RUSTFLAGS = "-Zcontrol_flow_guard=checks" +cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc +``` + +Alternatively, if you are building the standard library from source, you can set `control-flow-guard = true` in the config.toml file. diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 2f77792f7a198..ceac68704d2b0 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -27,7 +27,6 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(arbitrary_self_types)] #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] @@ -39,21 +38,15 @@ #![feature(marker_trait_attr)] #![feature(extern_types)] #![feature(nll)] -#![feature(optin_builtin_traits)] #![feature(option_expect_none)] #![feature(range_is_empty)] #![feature(specialization)] -#![feature(unboxed_closures)] -#![feature(thread_local)] -#![feature(trace_macros)] #![feature(trusted_len)] #![feature(vec_remove_item)] #![feature(stmt_expr_attributes)] -#![feature(integer_atomics)] #![feature(test)] #![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] -#![feature(log_syntax)] #![feature(associated_type_bounds)] #![feature(rustc_attrs)] #![feature(hash_raw_entry)] diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index cfeb392f87f46..17337ff0c92a6 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -3472,7 +3472,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // that order. let predicates = tcx.predicates_of(def_id); assert_eq!(predicates.parent, None); - let mut obligations = Vec::new(); + let mut obligations = Vec::with_capacity(predicates.predicates.len()); for (predicate, _) in predicates.predicates { let predicate = normalize_with_depth_to( self, diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index ca7740199ec7d..e09bcdcbc628e 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -86,10 +86,10 @@ impl<'tcx> Children { impl_def_id, simplified_self, possible_sibling, ); - let overlap_error = |overlap: traits::coherence::OverlapResult<'_>| { - // Found overlap, but no specialization; error out. + let create_overlap_error = |overlap: traits::coherence::OverlapResult<'_>| { let trait_ref = overlap.impl_header.trait_ref.unwrap(); let self_ty = trait_ref.self_ty(); + OverlapError { with_impl: possible_sibling, trait_desc: trait_ref.print_only_trait_path().to_string(), @@ -106,21 +106,49 @@ impl<'tcx> Children { } }; - let allowed_to_overlap = - tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling); + let report_overlap_error = |overlap: traits::coherence::OverlapResult<'_>, + last_lint: &mut _| { + // Found overlap, but no specialization; error out or report future-compat warning. + + // Do we *still* get overlap if we disable the future-incompatible modes? + let should_err = traits::overlapping_impls( + tcx, + possible_sibling, + impl_def_id, + traits::SkipLeakCheck::default(), + |_| true, + || false, + ); + + let error = create_overlap_error(overlap); + + if should_err { + Err(error) + } else { + *last_lint = Some(FutureCompatOverlapError { + error, + kind: FutureCompatOverlapErrorKind::LeakCheck, + }); + + Ok((false, false)) + } + }; + let last_lint_mut = &mut last_lint; let (le, ge) = traits::overlapping_impls( tcx, possible_sibling, impl_def_id, - traits::SkipLeakCheck::default(), + traits::SkipLeakCheck::Yes, |overlap| { - if let Some(overlap_kind) = &allowed_to_overlap { + if let Some(overlap_kind) = + tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) + { match overlap_kind { ty::ImplOverlapKind::Permitted { marker: _ } => {} ty::ImplOverlapKind::Issue33140 => { - last_lint = Some(FutureCompatOverlapError { - error: overlap_error(overlap), + *last_lint_mut = Some(FutureCompatOverlapError { + error: create_overlap_error(overlap), kind: FutureCompatOverlapErrorKind::Issue33140, }); } @@ -132,7 +160,11 @@ impl<'tcx> Children { let le = tcx.specializes((impl_def_id, possible_sibling)); let ge = tcx.specializes((possible_sibling, impl_def_id)); - if le == ge { Err(overlap_error(overlap)) } else { Ok((le, ge)) } + if le == ge { + report_overlap_error(overlap, last_lint_mut) + } else { + Ok((le, ge)) + } }, || Ok((false, false)), )?; @@ -153,27 +185,8 @@ impl<'tcx> Children { replace_children.push(possible_sibling); } else { - if let None = allowed_to_overlap { - // Do future-compat checks for overlap. - - if last_lint.is_none() { - traits::overlapping_impls( - tcx, - possible_sibling, - impl_def_id, - traits::SkipLeakCheck::Yes, - |overlap| { - last_lint = Some(FutureCompatOverlapError { - error: overlap_error(overlap), - kind: FutureCompatOverlapErrorKind::LeakCheck, - }); - }, - || (), - ); - } - } - - // no overlap (error bailed already via ?) + // Either there's no overlap, or the overlap was already reported by + // `overlap_error`. } } diff --git a/src/librustc/traits/wf.rs b/src/librustc/traits/wf.rs index 1c47b5353160d..48721ec04e7fd 100644 --- a/src/librustc/traits/wf.rs +++ b/src/librustc/traits/wf.rs @@ -143,14 +143,15 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let cause = self.cause(traits::MiscObligation); let infcx = &mut self.infcx; let param_env = self.param_env; - let mut obligations = Vec::new(); - self.out.iter().inspect(|pred| assert!(!pred.has_escaping_bound_vars())).for_each(|pred| { + let mut obligations = Vec::with_capacity(self.out.len()); + for pred in &self.out { + assert!(!pred.has_escaping_bound_vars()); let mut selcx = traits::SelectionContext::new(infcx); let i = obligations.len(); let value = traits::normalize_to(&mut selcx, param_env, cause.clone(), pred, &mut obligations); obligations.insert(i, value); - }); + } obligations } diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 8091a74854070..98a3e695fa079 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -6,18 +6,11 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(bool_to_option)] -#![feature(box_patterns)] -#![feature(box_syntax)] #![feature(const_cstr_unchecked)] #![feature(crate_visibility_modifier)] #![feature(extern_types)] #![feature(in_band_lifetimes)] -#![feature(libc)] #![feature(nll)] -#![feature(optin_builtin_traits)] -#![feature(concat_idents)] -#![feature(link_args)] -#![feature(static_nobundle)] #![feature(trusted_len)] #![recursion_limit = "256"] @@ -196,7 +189,7 @@ unsafe impl Sync for LlvmCodegenBackend {} impl LlvmCodegenBackend { pub fn new() -> Box { - box LlvmCodegenBackend(()) + Box::new(LlvmCodegenBackend(())) } } @@ -245,7 +238,7 @@ impl CodegenBackend for LlvmCodegenBackend { } fn metadata_loader(&self) -> Box { - box metadata::LlvmMetadataLoader + Box::new(metadata::LlvmMetadataLoader) } fn provide(&self, providers: &mut ty::query::Providers<'_>) { @@ -262,12 +255,12 @@ impl CodegenBackend for LlvmCodegenBackend { metadata: EncodedMetadata, need_metadata_module: bool, ) -> Box { - box rustc_codegen_ssa::base::codegen_crate( + Box::new(rustc_codegen_ssa::base::codegen_crate( LlvmCodegenBackend(()), tcx, metadata, need_metadata_module, - ) + )) } fn join_codegen( diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs index abe34bb148ce5..0f30c2c020de7 100644 --- a/src/librustc_codegen_llvm/metadata.rs +++ b/src/librustc_codegen_llvm/metadata.rs @@ -22,10 +22,11 @@ impl MetadataLoader for LlvmMetadataLoader { // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap // internally to read the file. We also avoid even using a memcpy by // just keeping the archive along while the metadata is in use. - let archive = ArchiveRO::open(filename).map(|ar| OwningRef::new(box ar)).map_err(|e| { - debug!("llvm didn't like `{}`: {}", filename.display(), e); - format!("failed to read rlib metadata in '{}': {}", filename.display(), e) - })?; + let archive = + ArchiveRO::open(filename).map(|ar| OwningRef::new(Box::new(ar))).map_err(|e| { + debug!("llvm didn't like `{}`: {}", filename.display(), e); + format!("failed to read rlib metadata in '{}': {}", filename.display(), e) + })?; let buf: OwningRef<_, [u8]> = archive.try_map(|ar| { ar.iter() .filter_map(|s| s.ok()) @@ -44,9 +45,10 @@ impl MetadataLoader for LlvmMetadataLoader { let buf = path_to_c_string(filename); let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr()) .ok_or_else(|| format!("error reading library: '{}'", filename.display()))?; - let of = ObjectFile::new(mb).map(|of| OwningRef::new(box of)).ok_or_else(|| { - format!("provided path not an object file: '{}'", filename.display()) - })?; + let of = + ObjectFile::new(mb).map(|of| OwningRef::new(Box::new(of))).ok_or_else(|| { + format!("provided path not an object file: '{}'", filename.display()) + })?; let buf = of.try_map(|of| search_meta_section(of, target, filename))?; Ok(rustc_erase_owner!(buf)) } diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index f39587122c56d..a2bb39b9e4019 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -1,10 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(bool_to_option)] #![feature(box_patterns)] -#![feature(box_syntax)] -#![feature(core_intrinsics)] -#![feature(libc)] -#![feature(stmt_expr_attributes)] #![feature(try_blocks)] #![feature(in_band_lifetimes)] #![feature(nll)] diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 6b802bf530e86..38906bbaef810 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -3,10 +3,6 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(arbitrary_self_types)] -#![feature(box_patterns)] -#![feature(box_syntax)] -#![feature(core_intrinsics)] #![feature(never_type)] #![feature(nll)] #![feature(in_band_lifetimes)] diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index aaac7fb4460cd..13792a0c890c4 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -12,7 +12,6 @@ #![feature(generators)] #![feature(generator_trait)] #![feature(fn_traits)] -#![feature(unsize)] #![feature(specialization)] #![feature(optin_builtin_traits)] #![feature(nll)] @@ -20,11 +19,9 @@ #![feature(hash_raw_entry)] #![feature(stmt_expr_attributes)] #![feature(core_intrinsics)] -#![feature(integer_atomics)] #![feature(test)] #![feature(associated_type_bounds)] #![feature(thread_id_value)] -#![cfg_attr(unix, feature(libc))] #![allow(rustc::default_hash_types)] #[macro_use] diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 019ff431bcb97..52c6399498534 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -5,12 +5,7 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(box_syntax)] -#![cfg_attr(unix, feature(libc))] #![feature(nll)] -#![feature(set_stdio)] -#![feature(no_debug)] -#![feature(integer_atomics)] #![recursion_limit = "256"] pub extern crate getopts; diff --git a/src/librustc_error_codes/error_codes/E0307.md b/src/librustc_error_codes/error_codes/E0307.md index c628d176836f9..52707b93acc86 100644 --- a/src/librustc_error_codes/error_codes/E0307.md +++ b/src/librustc_error_codes/error_codes/E0307.md @@ -1,5 +1,19 @@ -This error indicates that the `self` parameter in a method has an invalid -"receiver type". +The `self` parameter in a method has an invalid "receiver type". + +Erroneous code example: + +```compile_fail,E0307 +struct Foo; +struct Bar; + +trait Trait { + fn foo(&self); +} + +impl Trait for Foo { + fn foo(self: &Bar) {} +} +``` Methods take a special first parameter, of which there are three variants: `self`, `&self`, and `&mut self`. These are syntactic sugar for @@ -36,7 +50,7 @@ impl Trait for Foo { } ``` -E0307 will be emitted by the compiler when using an invalid receiver type, +This error will be emitted by the compiler when using an invalid receiver type, like in the following example: ```compile_fail,E0307 diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 97667febc3ca2..594e813def8a9 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -4,9 +4,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(crate_visibility_modifier)] -#![cfg_attr(unix, feature(libc))] #![feature(nll)] -#![feature(optin_builtin_traits)] pub use emitter::ColorConfig; diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index 7ce4def2886b8..ca824fde7efc1 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -3,7 +3,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(specialization)] #![recursion_limit = "256"] #[macro_use] diff --git a/src/librustc_interface/lib.rs b/src/librustc_interface/lib.rs index e4e6849ab8e59..ba1e2216ca805 100644 --- a/src/librustc_interface/lib.rs +++ b/src/librustc_interface/lib.rs @@ -2,10 +2,8 @@ #![feature(box_syntax)] #![feature(set_stdio)] #![feature(nll)] -#![feature(arbitrary_self_types)] #![feature(generator_trait)] #![feature(generators)] -#![cfg_attr(unix, feature(libc))] #![recursion_limit = "256"] #[cfg(unix)] diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 07ee1cbb27d60..2204e104803b3 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -28,7 +28,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![cfg_attr(test, feature(test))] #![feature(bool_to_option)] -#![feature(box_patterns)] #![feature(box_syntax)] #![feature(crate_visibility_modifier)] #![feature(never_type)] diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index d94f23ff8bc6a..d4cc3c32616ac 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -1,15 +1,11 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(bool_to_option)] -#![feature(box_patterns)] #![feature(core_intrinsics)] #![feature(crate_visibility_modifier)] #![feature(drain_filter)] #![feature(in_band_lifetimes)] -#![feature(libc)] #![feature(nll)] #![feature(proc_macro_internals)] -#![feature(proc_macro_quote)] -#![feature(rustc_private)] #![feature(specialization)] #![feature(stmt_expr_attributes)] #![recursion_limit = "256"] diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index 563ff1112c3a6..d91f6edc9800c 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -10,7 +10,7 @@ use rustc_span::Span; use crate::borrow_check::diagnostics::BorrowedContentSource; use crate::borrow_check::MirBorrowckCtxt; use crate::util::collect_writes::FindAssignments; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, DiagnosticBuilder}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub(crate) enum AccessKind { @@ -412,11 +412,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { projection: [ProjectionElem::Deref], // FIXME document what is this 1 magic number about } if local == Local::new(1) && !self.upvars.is_empty() => { - err.span_label(span, format!("cannot {ACT}", ACT = act)); - err.span_help( - self.body.span, - "consider changing this to accept closures that implement `FnMut`", - ); + self.expected_fn_found_fn_mut_call(&mut err, span, act); } PlaceRef { local: _, projection: [.., ProjectionElem::Deref] } => { @@ -448,6 +444,101 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.buffer(&mut self.errors_buffer); } + + /// Targetted error when encountering an `FnMut` closure where an `Fn` closure was expected. + fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) { + err.span_label(sp, format!("cannot {}", act)); + + let hir = self.infcx.tcx.hir(); + let closure_id = hir.as_local_hir_id(self.mir_def_id).unwrap(); + let fn_call_id = hir.get_parent_node(closure_id); + let node = hir.get(fn_call_id); + let item_id = hir.get_parent_item(fn_call_id); + let mut look_at_return = true; + // If we can detect the expression to be an `fn` call where the closure was an argument, + // we point at the `fn` definition argument... + match node { + hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Call(func, args), .. }) => { + let arg_pos = args + .iter() + .enumerate() + .filter(|(_, arg)| arg.span == self.body.span) + .map(|(pos, _)| pos) + .next(); + let def_id = hir.local_def_id(item_id); + let tables = self.infcx.tcx.typeck_tables_of(def_id); + if let Some(ty::FnDef(def_id, _)) = + tables.node_type_opt(func.hir_id).as_ref().map(|ty| &ty.kind) + { + let arg = match hir.get_if_local(*def_id) { + Some(hir::Node::Item(hir::Item { + ident, + kind: hir::ItemKind::Fn(sig, ..), + .. + })) + | Some(hir::Node::TraitItem(hir::TraitItem { + ident, + kind: hir::TraitItemKind::Method(sig, _), + .. + })) + | Some(hir::Node::ImplItem(hir::ImplItem { + ident, + kind: hir::ImplItemKind::Method(sig, _), + .. + })) => Some( + arg_pos + .and_then(|pos| { + sig.decl.inputs.get( + pos + if sig.decl.implicit_self.has_implicit_self() { + 1 + } else { + 0 + }, + ) + }) + .map(|arg| arg.span) + .unwrap_or(ident.span), + ), + _ => None, + }; + if let Some(span) = arg { + err.span_label(span, "change this to accept `FnMut` instead of `Fn`"); + err.span_label(func.span, "expects `Fn` instead of `FnMut`"); + if self.infcx.tcx.sess.source_map().is_multiline(self.body.span) { + err.span_label(self.body.span, "in this closure"); + } + look_at_return = false; + } + } + } + _ => {} + } + if look_at_return && hir.get_return_block(closure_id).is_some() { + // ...otherwise we are probably in the tail expression of the function, point at the + // return type. + match hir.get(hir.get_parent_item(fn_call_id)) { + hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. }) + | hir::Node::TraitItem(hir::TraitItem { + ident, + kind: hir::TraitItemKind::Method(sig, _), + .. + }) + | hir::Node::ImplItem(hir::ImplItem { + ident, + kind: hir::ImplItemKind::Method(sig, _), + .. + }) => { + err.span_label(ident.span, ""); + err.span_label( + sig.decl.output.span(), + "change this to return `FnMut` instead of `Fn`", + ); + err.span_label(self.body.span, "in this closure"); + } + _ => {} + } + } + } } fn suggest_ampmut_self<'tcx>( diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index f064869d66471..4f1b90e34cf00 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -6,21 +6,15 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(nll)] #![feature(in_band_lifetimes)] -#![feature(inner_deref)] #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(crate_visibility_modifier)] -#![feature(core_intrinsics)] -#![feature(decl_macro)] #![feature(drain_filter)] #![feature(exhaustive_patterns)] #![feature(iter_order_by)] #![feature(never_type)] #![feature(specialization)] -#![feature(try_trait)] -#![feature(unicode_internals)] -#![feature(slice_concat_ext)] #![feature(trusted_len)] #![feature(try_blocks)] #![feature(associated_type_bounds)] diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index af4ba4c0eb20e..2e63c3e170605 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -9,7 +9,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] -#![feature(label_break_value)] #![feature(nll)] #![recursion_limit = "256"] diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 87342d6a30120..8f00b76001f04 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -8,9 +8,7 @@ #![feature(crate_visibility_modifier)] #![feature(nll)] #![feature(optin_builtin_traits)] -#![feature(rustc_attrs)] #![feature(specialization)] -#![feature(step_trait)] use rustc_data_structures::AtomicRef; use rustc_macros::HashStable_Generic; diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index a9db0254a7d11..71150e74f70d4 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -8,7 +8,6 @@ //! LLVM. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(box_syntax)] #![feature(bool_to_option)] #![feature(nll)] diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 05ea9b1ac56dc..474868f0dd6c4 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -58,10 +58,8 @@ This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![allow(non_camel_case_types)] #![feature(bool_to_option)] -#![feature(box_patterns)] #![feature(box_syntax)] #![feature(crate_visibility_modifier)] -#![feature(exhaustive_patterns)] #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(try_blocks)] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index ed3f0f94e0ed8..4e0a2d9427431 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -3,19 +3,15 @@ html_playground_url = "https://play.rust-lang.org/" )] #![feature(rustc_private)] -#![feature(arbitrary_self_types)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(set_stdio)] #![feature(test)] #![feature(vec_remove_item)] #![feature(ptr_offset_from)] #![feature(crate_visibility_modifier)] -#![feature(drain_filter)] #![feature(never_type)] -#![feature(unicode_internals)] #![recursion_limit = "256"] extern crate env_logger; diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 280fb078f7de4..b990e71bef0dd 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -10,7 +10,6 @@ Core encoding and decoding interfaces. test(attr(allow(unused_variables), deny(warnings))) )] #![feature(box_syntax)] -#![feature(core_intrinsics)] #![feature(specialization)] #![feature(never_type)] #![feature(nll)] diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs index fed8bc95b6b86..62e27bcf1643f 100644 --- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs +++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs @@ -18,7 +18,10 @@ fn main() { let _g = to_fn(|| set(&mut y)); //~ ERROR cannot borrow let mut z = 0; - let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); }); //~ ERROR cannot assign + let _h = to_fn_mut(|| { + set(&mut z); + to_fn(|| z = 42); //~ ERROR cannot assign + }); } // By-value captures @@ -33,3 +36,19 @@ fn main() { let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); }); //~ ERROR cannot assign } } + +fn foo() -> Box usize> { + let mut x = 0; + Box::new(move || { + x += 1; //~ ERROR cannot assign + x + }) +} + +fn bar() -> impl Fn() -> usize { + let mut x = 0; + move || { + x += 1; //~ ERROR cannot assign + x + } +} diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr index 097e4c75065c9..3046b047d00f6 100644 --- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr +++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr @@ -1,76 +1,97 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:15:27 | +LL | fn to_fn>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | let _f = to_fn(|| x = 42); - | ^^^^^^ cannot assign - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/borrow-immutable-upvar-mutation.rs:15:24 - | -LL | let _f = to_fn(|| x = 42); - | ^^^^^^^^^ + | ----- ^^^^^^ cannot assign + | | + | expects `Fn` instead of `FnMut` error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:18:31 | +LL | fn to_fn>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | let _g = to_fn(|| set(&mut y)); - | ^^^^^^ cannot borrow as mutable - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/borrow-immutable-upvar-mutation.rs:18:24 - | -LL | let _g = to_fn(|| set(&mut y)); - | ^^^^^^^^^^^^^^ + | ----- ^^^^^^ cannot borrow as mutable + | | + | expects `Fn` instead of `FnMut` error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-immutable-upvar-mutation.rs:21:55 - | -LL | let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); }); - | ^^^^^^ cannot assign - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/borrow-immutable-upvar-mutation.rs:21:52 - | -LL | let _h = to_fn_mut(|| { set(&mut z); to_fn(|| z = 42); }); - | ^^^^^^^^^ + --> $DIR/borrow-immutable-upvar-mutation.rs:23:22 + | +LL | fn to_fn>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... +LL | to_fn(|| z = 42); + | ----- ^^^^^^ cannot assign + | | + | expects `Fn` instead of `FnMut` error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-immutable-upvar-mutation.rs:27:32 - | -LL | let _f = to_fn(move || x = 42); - | ^^^^^^ cannot assign - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/borrow-immutable-upvar-mutation.rs:27:24 + --> $DIR/borrow-immutable-upvar-mutation.rs:30:32 | +LL | fn to_fn>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | let _f = to_fn(move || x = 42); - | ^^^^^^^^^^^^^^ + | ----- ^^^^^^ cannot assign + | | + | expects `Fn` instead of `FnMut` error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-immutable-upvar-mutation.rs:30:36 - | -LL | let _g = to_fn(move || set(&mut y)); - | ^^^^^^ cannot borrow as mutable - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/borrow-immutable-upvar-mutation.rs:30:24 + --> $DIR/borrow-immutable-upvar-mutation.rs:33:36 | +LL | fn to_fn>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | let _g = to_fn(move || set(&mut y)); - | ^^^^^^^^^^^^^^^^^^^ + | ----- ^^^^^^ cannot borrow as mutable + | | + | expects `Fn` instead of `FnMut` error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-immutable-upvar-mutation.rs:33:65 + --> $DIR/borrow-immutable-upvar-mutation.rs:36:65 | +LL | fn to_fn>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); }); - | ^^^^^^ cannot assign - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/borrow-immutable-upvar-mutation.rs:33:57 - | -LL | let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); }); - | ^^^^^^^^^^^^^^ + | ----- ^^^^^^ cannot assign + | | + | expects `Fn` instead of `FnMut` + +error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-immutable-upvar-mutation.rs:43:9 + | +LL | fn foo() -> Box usize> { + | --- ---------------------- change this to return `FnMut` instead of `Fn` +LL | let mut x = 0; +LL | Box::new(move || { + | ______________- +LL | | x += 1; + | | ^^^^^^ cannot assign +LL | | x +LL | | }) + | |_____- in this closure + +error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-immutable-upvar-mutation.rs:51:9 + | +LL | fn bar() -> impl Fn() -> usize { + | --- ------------------ change this to return `FnMut` instead of `Fn` +LL | let mut x = 0; +LL | / move || { +LL | | x += 1; + | | ^^^^^^ cannot assign +LL | | x +LL | | } + | |_____- in this closure -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors Some errors have detailed explanations: E0594, E0596. For more information about an error, try `rustc --explain E0594`. diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr index cf01c362d50bc..44dde0fd80b0d 100644 --- a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -27,32 +27,32 @@ LL | f(); error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-raw-address-of-mutability.rs:29:17 | -LL | let y = &raw mut x; - | ^^^^^^^^^^ cannot borrow as mutable - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/borrow-raw-address-of-mutability.rs:28:21 - | +LL | fn make_fn(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | let f = make_fn(|| { - | _____________________^ + | _____________-------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | let y = &raw mut x; + | | ^^^^^^^^^^ cannot borrow as mutable LL | | }); - | |_____^ + | |_____- in this closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-raw-address-of-mutability.rs:37:17 | -LL | let y = &raw mut x; - | ^^^^^^^^^^ cannot borrow as mutable - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/borrow-raw-address-of-mutability.rs:36:21 - | +LL | fn make_fn(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | let f = make_fn(move || { - | _____________________^ + | _____________-------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | let y = &raw mut x; + | | ^^^^^^^^^^ cannot borrow as mutable LL | | }); - | |_____^ + | |_____- in this closure error: aborting due to 5 previous errors diff --git a/src/test/ui/borrowck/mutability-errors.stderr b/src/test/ui/borrowck/mutability-errors.stderr index 72547a40352c9..5361ebe3916d7 100644 --- a/src/test/ui/borrowck/mutability-errors.stderr +++ b/src/test/ui/borrowck/mutability-errors.stderr @@ -119,146 +119,146 @@ LL | &mut (*f()).0; error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/mutability-errors.rs:40:9 | -LL | x = (1,); - | ^^^^^^^^ cannot assign - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/mutability-errors.rs:39:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(|| { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | x = (1,); + | | ^^^^^^^^ cannot assign LL | | x.0 = 1; LL | | &mut x; LL | | &mut x.0; LL | | }); - | |_____^ + | |_____- in this closure error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables --> $DIR/mutability-errors.rs:41:9 | -LL | x.0 = 1; - | ^^^^^^^ cannot assign - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/mutability-errors.rs:39:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(|| { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | x = (1,); LL | | x.0 = 1; + | | ^^^^^^^ cannot assign LL | | &mut x; LL | | &mut x.0; LL | | }); - | |_____^ + | |_____- in this closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/mutability-errors.rs:42:9 | -LL | &mut x; - | ^^^^^^ cannot borrow as mutable - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/mutability-errors.rs:39:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(|| { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | x = (1,); LL | | x.0 = 1; LL | | &mut x; + | | ^^^^^^ cannot borrow as mutable LL | | &mut x.0; LL | | }); - | |_____^ + | |_____- in this closure error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables --> $DIR/mutability-errors.rs:43:9 | -LL | &mut x.0; - | ^^^^^^^^ cannot borrow as mutable - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/mutability-errors.rs:39:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(|| { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | x = (1,); LL | | x.0 = 1; LL | | &mut x; LL | | &mut x.0; + | | ^^^^^^^^ cannot borrow as mutable LL | | }); - | |_____^ + | |_____- in this closure error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/mutability-errors.rs:46:9 | -LL | x = (1,); - | ^^^^^^^^ cannot assign - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/mutability-errors.rs:45:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(move || { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | x = (1,); + | | ^^^^^^^^ cannot assign LL | | x.0 = 1; LL | | &mut x; LL | | &mut x.0; LL | | }); - | |_____^ + | |_____- in this closure error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables --> $DIR/mutability-errors.rs:47:9 | -LL | x.0 = 1; - | ^^^^^^^ cannot assign - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/mutability-errors.rs:45:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(move || { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | x = (1,); LL | | x.0 = 1; + | | ^^^^^^^ cannot assign LL | | &mut x; LL | | &mut x.0; LL | | }); - | |_____^ + | |_____- in this closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/mutability-errors.rs:48:9 | -LL | &mut x; - | ^^^^^^ cannot borrow as mutable - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/mutability-errors.rs:45:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(move || { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | x = (1,); LL | | x.0 = 1; LL | | &mut x; + | | ^^^^^^ cannot borrow as mutable LL | | &mut x.0; LL | | }); - | |_____^ + | |_____- in this closure error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables --> $DIR/mutability-errors.rs:49:9 | -LL | &mut x.0; - | ^^^^^^^^ cannot borrow as mutable - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/mutability-errors.rs:45:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(move || { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | x = (1,); LL | | x.0 = 1; LL | | &mut x; LL | | &mut x.0; + | | ^^^^^^^^ cannot borrow as mutable LL | | }); - | |_____^ + | |_____- in this closure error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable --> $DIR/mutability-errors.rs:54:5 diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr index a316d8f1698ac..3eb8e0ec18288 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr @@ -10,7 +10,7 @@ error: internal compiler error: mutable allocation in constant LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:357:17 +thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:355:17 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace error: internal compiler error: unexpected panic diff --git a/src/test/ui/fn/fn-closure-mutable-capture.rs b/src/test/ui/fn/fn-closure-mutable-capture.rs index 81376af091b45..0e427b9cf318f 100644 --- a/src/test/ui/fn/fn-closure-mutable-capture.rs +++ b/src/test/ui/fn/fn-closure-mutable-capture.rs @@ -1,11 +1,11 @@ -pub fn bar(_f: F) {} +pub fn bar(_f: F) {} //~ NOTE change this to accept `FnMut` instead of `Fn` pub fn foo() { let mut x = 0; bar(move || x = 1); //~^ ERROR cannot assign to `x`, as it is a captured variable in a `Fn` closure //~| NOTE cannot assign - //~| HELP consider changing this to accept closures that implement `FnMut` + //~| NOTE expects `Fn` instead of `FnMut` } fn main() {} diff --git a/src/test/ui/fn/fn-closure-mutable-capture.stderr b/src/test/ui/fn/fn-closure-mutable-capture.stderr index f7ab56da8de97..d23c363ae1582 100644 --- a/src/test/ui/fn/fn-closure-mutable-capture.stderr +++ b/src/test/ui/fn/fn-closure-mutable-capture.stderr @@ -1,14 +1,13 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/fn-closure-mutable-capture.rs:5:17 | +LL | pub fn bar(_f: F) {} + | - change this to accept `FnMut` instead of `Fn` +... LL | bar(move || x = 1); - | ^^^^^ cannot assign - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/fn-closure-mutable-capture.rs:5:9 - | -LL | bar(move || x = 1); - | ^^^^^^^^^^^^^ + | --- ^^^^^ cannot assign + | | + | expects `Fn` instead of `FnMut` error: aborting due to previous error diff --git a/src/test/ui/hygiene/assoc_ty_bindings.rs b/src/test/ui/hygiene/assoc_ty_bindings.rs index 93cf7591a0db2..0567beab9b9c8 100644 --- a/src/test/ui/hygiene/assoc_ty_bindings.rs +++ b/src/test/ui/hygiene/assoc_ty_bindings.rs @@ -12,8 +12,8 @@ trait Derived: Base { } macro mac() { - type A = Base; - type B = Derived; + type A = dyn Base; + type B = dyn Derived; impl Base for u8 { type AssocTy = u8; diff --git a/src/test/ui/issues/issue-21600.stderr b/src/test/ui/issues/issue-21600.stderr index 9c534809dbee3..84c7106e89016 100644 --- a/src/test/ui/issues/issue-21600.stderr +++ b/src/test/ui/issues/issue-21600.stderr @@ -1,34 +1,33 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/issue-21600.rs:14:20 | +LL | fn call_it(f: F) where F: Fn() { f(); } + | - change this to accept `FnMut` instead of `Fn` +... LL | call_it(|| x.gen_mut()); - | ^ cannot borrow as mutable - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/issue-21600.rs:14:17 - | -LL | call_it(|| x.gen_mut()); - | ^^^^^^^^^^^^^^ + | ------- ^ cannot borrow as mutable + | | + | expects `Fn` instead of `FnMut` error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/issue-21600.rs:14:17 | -LL | call_it(|| x.gen_mut()); - | ^^ - mutable borrow occurs due to use of `x` in closure - | | - | cannot borrow as mutable - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/issue-21600.rs:12:13 - | +LL | fn call_it(f: F) where F: Fn() { f(); } + | - change this to accept `FnMut` instead of `Fn` +... LL | call_it(|| { - | _____________^ + | _____-------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | call_it(|| x.gen()); LL | | call_it(|| x.gen_mut()); + | | ^^ - mutable borrow occurs due to use of `x` in closure + | | | + | | cannot borrow as mutable LL | | LL | | LL | | }); - | |_____^ + | |_____- in this closure error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/closure-captures.stderr b/src/test/ui/nll/closure-captures.stderr index b8f5cc86500c5..dd5f32ef4f581 100644 --- a/src/test/ui/nll/closure-captures.stderr +++ b/src/test/ui/nll/closure-captures.stderr @@ -37,36 +37,36 @@ LL | x = 1; error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:27:9 | -LL | || - | ^^ cannot borrow as mutable -LL | x = 1;} - | - mutable borrow occurs due to use of `x` in closure - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/closure-captures.rs:26:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(|| { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | || + | | ^^ cannot borrow as mutable LL | | x = 1;} - | |________________^ + | |__________-_____- in this closure + | | + | mutable borrow occurs due to use of `x` in closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:31:9 | -LL | || - | ^^ cannot borrow as mutable -LL | x = 1;}); - | - mutable borrow occurs due to use of `x` in closure - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/closure-captures.rs:30:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(move || { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | || + | | ^^ cannot borrow as mutable LL | | x = 1;}); - | |___________^ + | |_____-_____- in this closure + | | + | mutable borrow occurs due to use of `x` in closure error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/closure-captures.rs:39:10 @@ -80,19 +80,19 @@ LL | x = 1;} error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:38:9 | -LL | || - | ^^ cannot borrow as mutable -LL | x = 1;} - | - mutable borrow occurs due to use of `x` in closure - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/closure-captures.rs:37:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(|| { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | || + | | ^^ cannot borrow as mutable LL | | x = 1;} - | |________________^ + | |__________-_____- in this closure + | | + | mutable borrow occurs due to use of `x` in closure error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/closure-captures.rs:43:5 @@ -106,53 +106,53 @@ LL | x = 1;}); error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:42:9 | -LL | || - | ^^ cannot borrow as mutable -LL | x = 1;}); - | - mutable borrow occurs due to use of `x` in closure - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/closure-captures.rs:41:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(move || { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | || + | | ^^ cannot borrow as mutable LL | | x = 1;}); - | |___________^ + | |_____-_____- in this closure + | | + | mutable borrow occurs due to use of `x` in closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:48:9 | -LL | || - | ^^ cannot borrow as mutable -LL | *x = 1;}); - | - mutable borrow occurs due to use of `x` in closure - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/closure-captures.rs:47:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(|| { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | || + | | ^^ cannot borrow as mutable LL | | *x = 1;}); - | |________________^ + | |__________-_____- in this closure + | | + | mutable borrow occurs due to use of `x` in closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:51:9 | -LL | || - | ^^ cannot borrow as mutable -LL | *x = 1;}); - | - mutable borrow occurs due to use of `x` in closure - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/closure-captures.rs:50:12 - | +LL | fn fn_ref(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | fn_ref(move || { - | ____________^ + | _____------_- + | | | + | | expects `Fn` instead of `FnMut` LL | | || + | | ^^ cannot borrow as mutable LL | | *x = 1;}); - | |________________^ + | |__________-_____- in this closure + | | + | mutable borrow occurs due to use of `x` in closure error: aborting due to 12 previous errors diff --git a/src/test/ui/privacy/associated-item-privacy-type-binding.rs b/src/test/ui/privacy/associated-item-privacy-type-binding.rs index 591e9df81eb0b..b9c526f5156ba 100644 --- a/src/test/ui/privacy/associated-item-privacy-type-binding.rs +++ b/src/test/ui/privacy/associated-item-privacy-type-binding.rs @@ -8,19 +8,19 @@ mod priv_trait { pub trait PubTr: PrivTr {} pub macro mac1() { - let _: Box>; + let _: Box>; //~^ ERROR trait `priv_trait::PrivTr` is private //~| ERROR trait `priv_trait::PrivTr` is private - type InSignatureTy2 = Box>; + type InSignatureTy2 = Box>; //~^ ERROR trait `priv_trait::PrivTr` is private trait InSignatureTr2: PubTr {} //~^ ERROR trait `priv_trait::PrivTr` is private } pub macro mac2() { - let _: Box>; + let _: Box>; //~^ ERROR trait `priv_trait::PrivTr` is private //~| ERROR trait `priv_trait::PrivTr` is private - type InSignatureTy1 = Box>; + type InSignatureTy1 = Box>; //~^ ERROR trait `priv_trait::PrivTr` is private trait InSignatureTr1: PrivTr {} //~^ ERROR trait `priv_trait::PrivTr` is private @@ -41,15 +41,15 @@ mod priv_parent_substs { pub trait PubTr: PubTrWithParam {} pub macro mac() { - let _: Box>; + let _: Box>; //~^ ERROR type `priv_parent_substs::Priv` is private //~| ERROR type `priv_parent_substs::Priv` is private - let _: Box>; + let _: Box>; //~^ ERROR type `priv_parent_substs::Priv` is private //~| ERROR type `priv_parent_substs::Priv` is private - pub type InSignatureTy1 = Box>; + pub type InSignatureTy1 = Box>; //~^ ERROR type `priv_parent_substs::Priv` is private - pub type InSignatureTy2 = Box>; + pub type InSignatureTy2 = Box>; //~^ ERROR type `priv_parent_substs::Priv` is private trait InSignatureTr1: PubTrWithParam {} //~^ ERROR type `priv_parent_substs::Priv` is private diff --git a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr index 5afa286b85f27..fd8b8cf0db652 100644 --- a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr +++ b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr @@ -1,7 +1,7 @@ error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:11:13 | -LL | let _: Box>; +LL | let _: Box>; | ^ ... LL | priv_trait::mac1!(); @@ -12,8 +12,8 @@ LL | priv_trait::mac1!(); error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:11:16 | -LL | let _: Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _: Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | priv_trait::mac1!(); | -------------------- in this macro invocation @@ -23,8 +23,8 @@ LL | priv_trait::mac1!(); error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:14:31 | -LL | type InSignatureTy2 = Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type InSignatureTy2 = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | priv_trait::mac1!(); | -------------------- in this macro invocation @@ -45,7 +45,7 @@ LL | priv_trait::mac1!(); error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:20:13 | -LL | let _: Box>; +LL | let _: Box>; | ^ ... LL | priv_trait::mac2!(); @@ -56,8 +56,8 @@ LL | priv_trait::mac2!(); error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:20:16 | -LL | let _: Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _: Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | priv_trait::mac2!(); | -------------------- in this macro invocation @@ -67,8 +67,8 @@ LL | priv_trait::mac2!(); error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:23:31 | -LL | type InSignatureTy1 = Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type InSignatureTy1 = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | priv_trait::mac2!(); | -------------------- in this macro invocation @@ -89,7 +89,7 @@ LL | priv_trait::mac2!(); error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:44:13 | -LL | let _: Box>; +LL | let _: Box>; | ^ ... LL | priv_parent_substs::mac!(); @@ -100,8 +100,8 @@ LL | priv_parent_substs::mac!(); error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:44:16 | -LL | let _: Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _: Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -111,7 +111,7 @@ LL | priv_parent_substs::mac!(); error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:47:13 | -LL | let _: Box>; +LL | let _: Box>; | ^ ... LL | priv_parent_substs::mac!(); @@ -122,8 +122,8 @@ LL | priv_parent_substs::mac!(); error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:47:16 | -LL | let _: Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _: Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -133,8 +133,8 @@ LL | priv_parent_substs::mac!(); error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:50:35 | -LL | pub type InSignatureTy1 = Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub type InSignatureTy1 = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -144,8 +144,8 @@ LL | priv_parent_substs::mac!(); error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:52:35 | -LL | pub type InSignatureTy2 = Box>; - | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | pub type InSignatureTy2 = Box>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr index 6bba38510b676..48ec620d92ea7 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-mutate-upvar.stderr @@ -28,17 +28,17 @@ LL | n += 1; error[E0594]: cannot assign to `n`, as it is a captured variable in a `Fn` closure --> $DIR/unboxed-closures-mutate-upvar.rs:53:9 | -LL | n += 1; - | ^^^^^^ cannot assign - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/unboxed-closures-mutate-upvar.rs:52:23 - | +LL | fn to_fn>(f: F) -> F { f } + | - change this to accept `FnMut` instead of `Fn` +... LL | let mut f = to_fn(move || { - | _______________________^ + | _________________-----_- + | | | + | | expects `Fn` instead of `FnMut` LL | | n += 1; + | | ^^^^^^ cannot assign LL | | }); - | |_____^ + | |_____- in this closure error: aborting due to 4 previous errors diff --git a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr index a38c612e1dea9..80e84fb7cad3f 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr @@ -1,18 +1,18 @@ error[E0594]: cannot assign to `counter`, as it is a captured variable in a `Fn` closure --> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:11:9 | -LL | counter += 1; - | ^^^^^^^^^^^^ cannot assign - | -help: consider changing this to accept closures that implement `FnMut` - --> $DIR/unboxed-closures-mutated-upvar-from-fn-closure.rs:10:10 - | +LL | fn call(f: F) where F : Fn() { + | - change this to accept `FnMut` instead of `Fn` +... LL | call(|| { - | __________^ + | _____----_- + | | | + | | expects `Fn` instead of `FnMut` LL | | counter += 1; + | | ^^^^^^^^^^^^ cannot assign LL | | LL | | }); - | |_____^ + | |_____- in this closure error: aborting due to previous error