diff options
95 files changed, 1245 insertions, 481 deletions
diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index ff7a1552047..9ff2e32f06b 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -51,6 +51,14 @@ impl Mutability { } } + /// Returns `"const"` or `"mut"` depending on the mutability. + pub fn ptr_str(self) -> &'static str { + match self { + Mutability::Not => "const", + Mutability::Mut => "mut", + } + } + /// Returns `""` (empty string) or `"mutably "` depending on the mutability. pub fn mutably_str(self) -> &'static str { match self { diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 47bd24f1e14..c593d5a30b6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -652,6 +652,68 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err } + fn ty_kind_suggestion(&self, ty: Ty<'tcx>) -> Option<String> { + // Keep in sync with `rustc_hir_analysis/src/check/mod.rs:ty_kind_suggestion`. + // FIXME: deduplicate the above. + let tcx = self.infcx.tcx; + let implements_default = |ty| { + let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else { + return false; + }; + self.infcx + .type_implements_trait(default_trait, [ty], self.param_env) + .must_apply_modulo_regions() + }; + + Some(match ty.kind() { + ty::Never | ty::Error(_) => return None, + ty::Bool => "false".to_string(), + ty::Char => "\'x\'".to_string(), + ty::Int(_) | ty::Uint(_) => "42".into(), + ty::Float(_) => "3.14159".into(), + ty::Slice(_) => "[]".to_string(), + ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => { + "vec![]".to_string() + } + ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => { + "String::new()".to_string() + } + ty::Adt(def, args) if def.is_box() => { + format!("Box::new({})", self.ty_kind_suggestion(args[0].expect_ty())?) + } + ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => { + "None".to_string() + } + ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => { + format!("Ok({})", self.ty_kind_suggestion(args[0].expect_ty())?) + } + ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(), + ty::Ref(_, ty, mutability) => { + if let (ty::Str, hir::Mutability::Not) = (ty.kind(), mutability) { + "\"\"".to_string() + } else { + let Some(ty) = self.ty_kind_suggestion(*ty) else { + return None; + }; + format!("&{}{ty}", mutability.prefix_str()) + } + } + ty::Array(ty, len) => format!( + "[{}; {}]", + self.ty_kind_suggestion(*ty)?, + len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()), + ), + ty::Tuple(tys) => format!( + "({})", + tys.iter() + .map(|ty| self.ty_kind_suggestion(ty)) + .collect::<Option<Vec<String>>>()? + .join(", ") + ), + _ => "value".to_string(), + }) + } + fn suggest_assign_value( &self, err: &mut Diag<'_>, @@ -661,34 +723,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let ty = moved_place.ty(self.body, self.infcx.tcx).ty; debug!("ty: {:?}, kind: {:?}", ty, ty.kind()); - let tcx = self.infcx.tcx; - let implements_default = |ty, param_env| { - let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else { - return false; - }; - self.infcx - .type_implements_trait(default_trait, [ty], param_env) - .must_apply_modulo_regions() - }; - - let assign_value = match ty.kind() { - ty::Bool => "false", - ty::Float(_) => "0.0", - ty::Int(_) | ty::Uint(_) => "0", - ty::Never | ty::Error(_) => "", - ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => "vec![]", - ty::Adt(_, _) if implements_default(ty, self.param_env) => "Default::default()", - _ => "todo!()", + let Some(assign_value) = self.ty_kind_suggestion(ty) else { + return; }; - if !assign_value.is_empty() { - err.span_suggestion_verbose( - sugg_span.shrink_to_hi(), - "consider assigning a value", - format!(" = {assign_value}"), - Applicability::MaybeIncorrect, - ); - } + err.span_suggestion_verbose( + sugg_span.shrink_to_hi(), + "consider assigning a value", + format!(" = {assign_value}"), + Applicability::MaybeIncorrect, + ); } fn suggest_borrow_fn_like( diff --git a/compiler/rustc_codegen_cranelift/.cirrus.yml b/compiler/rustc_codegen_cranelift/.cirrus.yml index 97c2f45d31e..5a464bfac36 100644 --- a/compiler/rustc_codegen_cranelift/.cirrus.yml +++ b/compiler/rustc_codegen_cranelift/.cirrus.yml @@ -7,7 +7,7 @@ task: - curl https://sh.rustup.rs -sSf --output rustup.sh - sh rustup.sh --default-toolchain none -y --profile=minimal target_cache: - folder: target + folder: build/cg_clif prepare_script: - . $HOME/.cargo/env - ./y.sh prepare @@ -16,4 +16,5 @@ task: # Disabling incr comp reduces cache size and incr comp doesn't save as much # on CI anyway. - export CARGO_BUILD_INCREMENTAL=false - - ./y.sh test + # Skip rand as it fails on FreeBSD due to rust-random/rand#1355 + - ./y.sh test --skip-test test.rust-random/rand diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js b/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js index 6fcfca34ea7..1eb2b7f23b2 100644 --- a/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js +++ b/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js @@ -56,7 +56,7 @@ async function runOnce() { force: true, }); } catch (e) { - console.log("ERROR: ", JSON.stringify(e.data, null, 2)); + console.log("ERROR: ", JSON.stringify(e.response, null, 2)); core.info(`creating dev tag`); try { await octokit.rest.git.createRef({ @@ -68,7 +68,7 @@ async function runOnce() { } catch (e) { // we might race with others, so assume someone else has created the // tag by this point. - console.log("failed to create tag: ", JSON.stringify(e.data, null, 2)); + console.log("failed to create tag: ", JSON.stringify(e.response, null, 2)); } } diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml index 913a5c5a850..14aa850ff5c 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml @@ -268,6 +268,9 @@ jobs: if: ${{ github.ref == 'refs/heads/master' }} needs: [rustfmt, test, bench, dist] + permissions: + contents: write # for creating the dev tag and release + concurrency: group: release-dev cancel-in-progress: true diff --git a/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch index 646928893e9..a3f370af916 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch @@ -82,6 +82,19 @@ index d9de37e..8293fce 100644 #[cfg(target_has_atomic_load_store = "ptr")] macro_rules! atomic_int_ptr_sized { ( $($target_pointer_width:literal $align:literal)* ) => { $( +diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs +index 58b9ba4..91bbd0a 100644 +--- a/library/core/src/cell.rs ++++ b/library/core/src/cell.rs +@@ -2246,8 +2246,6 @@ unsafe_cell_primitive_into_inner! { + u32 "32" + i64 "64" + u64 "64" +- i128 "128" +- u128 "128" + isize "ptr" + usize "ptr" + } -- 2.26.2.7.g19db9cfb68 diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 09e436b3eed..3e7da4e161f 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-04-05" +channel = "nightly-2024-04-11" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index f42a008dc0c..8580f4557e8 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -10,14 +10,13 @@ pushd rust command -v rg >/dev/null 2>&1 || cargo install ripgrep -# FIXME remove this workaround once ICE tests no longer emit an outdated nightly message -for test in $(rg -i --files-with-matches "//@(\[.*\])? failure-status: 101" tests/ui); do - echo "rm $test" +rm -r tests/ui/{unsized-locals/,lto/,linkage*} || true +for test in $(rg --files-with-matches "lto" tests/{codegen-units,ui,incremental}); do rm $test done -rm -r tests/ui/{unsized-locals/,lto/,linkage*} || true -for test in $(rg --files-with-matches "lto" tests/{codegen-units,ui,incremental}); do +# should-fail tests don't work when compiletest is compiled with panic=abort +for test in $(rg --files-with-matches "//@ should-fail" tests/{codegen-units,ui,incremental}); do rm $test done @@ -79,7 +78,6 @@ rm -r tests/run-make/fmt-write-bloat/ # tests an optimization # ====================== rm tests/incremental/thinlto/cgu_invalidated_when_import_{added,removed}.rs # requires LLVM rm -r tests/run-make/cross-lang-lto # same -rm -r tests/run-make/issue-7349 # same rm -r tests/run-make/sepcomp-inlining # same rm -r tests/run-make/sepcomp-separate # same rm -r tests/run-make/sepcomp-cci-copies # same @@ -116,8 +114,6 @@ rm -r tests/run-make/compiler-builtins # Expects lib/rustlib/src/rust to contain # genuine bugs # ============ -rm tests/incremental/spike-neg1.rs # errors out for some reason -rm tests/incremental/spike-neg2.rs # same rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 771e5b21958..f07421431da 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -267,10 +267,19 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { .generic_activity("codegen prelude") .run(|| crate::abi::codegen_fn_prelude(fx, start_block)); - for (bb, bb_data) in traversal::mono_reachable(fx.mir, fx.tcx, fx.instance) { + let reachable_blocks = traversal::mono_reachable_as_bitset(fx.mir, fx.tcx, fx.instance); + + for (bb, bb_data) in fx.mir.basic_blocks.iter_enumerated() { let block = fx.get_block(bb); fx.bcx.switch_to_block(block); + if !reachable_blocks.contains(bb) { + // We want to skip this block, because it's not reachable. But we still create + // the block so terminators in other blocks can reference it. + fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + continue; + } + if bb_data.is_cleanup { // Unwinding after panicking is not supported continue; diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs index 96ab7a29205..eebd181341d 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/unwind.rs @@ -38,6 +38,14 @@ impl UnwindContext { } pub(crate) fn add_function(&mut self, func_id: FuncId, context: &Context, isa: &dyn TargetIsa) { + if let target_lexicon::OperatingSystem::MacOSX { .. } = isa.triple().operating_system { + // The object crate doesn't currently support DW_GNU_EH_PE_absptr, which macOS + // requires for unwinding tables. In addition on arm64 it currently doesn't + // support 32bit relocations as we currently use for the unwinding table. + // See gimli-rs/object#415 and rust-lang/rustc_codegen_cranelift#1371 + return; + } + let unwind_info = if let Some(unwind_info) = context.compiled_code().unwrap().create_unwind_info(isa).unwrap() { diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 500904ce188..e09869cf425 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -220,7 +220,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { constraints.append(&mut clobbers); if !options.contains(InlineAsmOptions::PRESERVES_FLAGS) { match asm_arch { - InlineAsmArch::AArch64 | InlineAsmArch::Arm => { + InlineAsmArch::AArch64 | InlineAsmArch::Arm64EC | InlineAsmArch::Arm => { constraints.push("~{cc}".to_string()); } InlineAsmArch::X86 | InlineAsmArch::X86_64 => { diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 8d4ae10d4bf..961b643fa25 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -22,7 +22,6 @@ use rustc_middle::ty::{ AdtDef, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; -use rustc_span::symbol::sym; use rustc_target::abi::FieldIdx; use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 8760901b71b..938c0a19e33 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -81,6 +81,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_errors::{pluralize, struct_span_code_err, Diag}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; +use rustc_hir::Mutability; use rustc_index::bit_set::BitSet; use rustc_infer::infer::error_reporting::ObligationCauseExt as _; use rustc_infer::infer::outlives::env::OutlivesEnvironment; @@ -91,10 +92,11 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_session::parse::feature_err; -use rustc_span::symbol::{kw, Ident}; -use rustc_span::{self, def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP}; +use rustc_span::symbol::{kw, sym, Ident}; +use rustc_span::{def_id::CRATE_DEF_ID, BytePos, Span, Symbol, DUMMY_SP}; use rustc_target::abi::VariantIdx; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::ObligationCtxt; @@ -466,14 +468,64 @@ fn fn_sig_suggestion<'tcx>( ) } -pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> { +pub fn ty_kind_suggestion<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<String> { + // Keep in sync with `rustc_borrowck/src/diagnostics/conflict_errors.rs:ty_kind_suggestion`. + // FIXME: deduplicate the above. + let implements_default = |ty| { + let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else { + return false; + }; + let infcx = tcx.infer_ctxt().build(); + infcx + .type_implements_trait(default_trait, [ty], ty::ParamEnv::reveal_all()) + .must_apply_modulo_regions() + }; Some(match ty.kind() { - ty::Bool => "true", - ty::Char => "'a'", - ty::Int(_) | ty::Uint(_) => "42", - ty::Float(_) => "3.14159", - ty::Error(_) | ty::Never => return None, - _ => "value", + ty::Never | ty::Error(_) => return None, + ty::Bool => "false".to_string(), + ty::Char => "\'x\'".to_string(), + ty::Int(_) | ty::Uint(_) => "42".into(), + ty::Float(_) => "3.14159".into(), + ty::Slice(_) => "[]".to_string(), + ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => { + "vec![]".to_string() + } + ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::String) => { + "String::new()".to_string() + } + ty::Adt(def, args) if def.is_box() => { + format!("Box::new({})", ty_kind_suggestion(args[0].expect_ty(), tcx)?) + } + ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Option) => { + "None".to_string() + } + ty::Adt(def, args) if Some(def.did()) == tcx.get_diagnostic_item(sym::Result) => { + format!("Ok({})", ty_kind_suggestion(args[0].expect_ty(), tcx)?) + } + ty::Adt(_, _) if implements_default(ty) => "Default::default()".to_string(), + ty::Ref(_, ty, mutability) => { + if let (ty::Str, Mutability::Not) = (ty.kind(), mutability) { + "\"\"".to_string() + } else { + let Some(ty) = ty_kind_suggestion(*ty, tcx) else { + return None; + }; + format!("&{}{ty}", mutability.prefix_str()) + } + } + ty::Array(ty, len) => format!( + "[{}; {}]", + ty_kind_suggestion(*ty, tcx)?, + len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()), + ), + ty::Tuple(tys) => format!( + "({})", + tys.iter() + .map(|ty| ty_kind_suggestion(ty, tcx)) + .collect::<Option<Vec<String>>>()? + .join(", ") + ), + _ => "value".to_string(), }) } @@ -511,7 +563,7 @@ fn suggestion_signature<'tcx>( } ty::AssocKind::Const => { let ty = tcx.type_of(assoc.def_id).instantiate_identity(); - let val = ty_kind_suggestion(ty).unwrap_or("todo!()"); + let val = ty_kind_suggestion(ty, tcx).unwrap_or_else(|| "value".to_string()); format!("const {}: {} = {};", assoc.name, ty, val) } } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index affd678fc6c..3d16f1420d9 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -718,6 +718,11 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } #[instrument(level = "debug", skip(self))] + fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::Pat<'tcx>) { + intravisit::walk_pat(self, p) + } + + #[instrument(level = "debug", skip(self))] fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { use self::hir::TraitItemKind::*; match trait_item.kind { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 9fb8b4ac40e..63aeb165a48 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2234,11 +2234,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .type_of(def_id) .no_bound_vars() .expect("const parameter types cannot be generic"); - let item_def_id = tcx.parent(def_id); - let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id]; - let name = tcx.item_name(def_id); - ty::Const::new_param(tcx, ty::ParamConst::new(index, name), ty) + self.lower_const_param(expr.hir_id, ty) } _ => { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7a1a2c498aa..8f30c3fd377 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -694,10 +694,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); let error = Some(Sorts(ExpectedFound { expected: ty, found: e_ty })); self.annotate_loop_expected_due_to_inference(err, expr, error); - if let Some(val) = ty_kind_suggestion(ty) { + if let Some(val) = ty_kind_suggestion(ty, tcx) { err.span_suggestion_verbose( expr.span.shrink_to_hi(), - "give it a value of the expected type", + "give the `break` a value of the expected type", format!(" {val}"), Applicability::HasPlaceholders, ); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index a199f57aad9..754866c85c4 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -529,16 +529,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } - if let ty::RawPtr(_, _) = &rcvr_ty.kind() { - err.note( - "try using `<*const T>::as_ref()` to get a reference to the \ - type behind the pointer: https://doc.rust-lang.org/std/\ - primitive.pointer.html#method.as_ref", - ); - err.note( - "using `<*const T>::as_ref()` on a pointer which is unaligned or points \ - to invalid or uninitialized memory is undefined behavior", + + // on pointers, check if the method would exist on a reference + if let SelfSource::MethodCall(rcvr_expr) = source + && let ty::RawPtr(ty, ptr_mutbl) = *rcvr_ty.kind() + && let Ok(pick) = self.lookup_probe_for_diagnostic( + item_name, + Ty::new_ref(tcx, ty::Region::new_error_misc(tcx), ty, ptr_mutbl), + self.tcx.hir().expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id)), + ProbeScope::TraitsInScope, + None, + ) + && let ty::Ref(_, _, sugg_mutbl) = *pick.self_ty.kind() + && (sugg_mutbl.is_not() || ptr_mutbl.is_mut()) + { + let (method, method_anchor) = match sugg_mutbl { + Mutability::Not => { + let method_anchor = match ptr_mutbl { + Mutability::Not => "as_ref", + Mutability::Mut => "as_ref-1", + }; + ("as_ref", method_anchor) + } + Mutability::Mut => ("as_mut", "as_mut"), + }; + err.span_note( + tcx.def_span(pick.item.def_id), + format!("the method `{item_name}` exists on the type `{ty}`", ty = pick.self_ty), ); + let mut_str = ptr_mutbl.ptr_str(); + err.note(format!( + "you might want to use the unsafe method `<*{mut_str} T>::{method}` to get \ + an optional reference to the value behind the pointer" + )); + err.note(format!( + "read the documentation for `<*{mut_str} T>::{method}` and ensure you satisfy its \ + safety preconditions before calling it to avoid undefined behavior: \ + https://doc.rust-lang.org/std/primitive.pointer.html#method.{method_anchor}" + )); } let mut ty_span = match rcvr_ty.kind() { diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index c987bfb9a0e..ef569b4bef3 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -367,37 +367,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::BrEnv }, ); + + let num_args = args + .as_coroutine_closure() + .coroutine_closure_sig() + .skip_binder() + .tupled_inputs_ty + .tuple_fields() + .len(); + let typeck_results = self.typeck_results.borrow(); + let tupled_upvars_ty_for_borrow = Ty::new_tup_from_iter( self.tcx, - self.typeck_results - .borrow() - .closure_min_captures_flattened( - self.tcx.coroutine_for_closure(closure_def_id).expect_local(), - ) - // Skip the captures that are just moving the closure's args - // into the coroutine. These are always by move, and we append - // those later in the `CoroutineClosureSignature` helper functions. - .skip( - args.as_coroutine_closure() - .coroutine_closure_sig() - .skip_binder() - .tupled_inputs_ty - .tuple_fields() - .len(), - ) - .map(|captured_place| { - let upvar_ty = captured_place.place.ty(); - let capture = captured_place.info.capture_kind; + ty::analyze_coroutine_closure_captures( + typeck_results.closure_min_captures_flattened(closure_def_id), + typeck_results + .closure_min_captures_flattened( + self.tcx.coroutine_for_closure(closure_def_id).expect_local(), + ) + // Skip the captures that are just moving the closure's args + // into the coroutine. These are always by move, and we append + // those later in the `CoroutineClosureSignature` helper functions. + .skip(num_args), + |(_, parent_capture), (_, child_capture)| { + // This is subtle. See documentation on function. + let needs_ref = should_reborrow_from_env_of_parent_coroutine_closure( + parent_capture, + child_capture, + ); + + let upvar_ty = child_capture.place.ty(); + let capture = child_capture.info.capture_kind; // Not all upvars are captured by ref, so use // `apply_capture_kind_on_capture_ty` to ensure that we // compute the right captured type. - apply_capture_kind_on_capture_ty( + return apply_capture_kind_on_capture_ty( self.tcx, upvar_ty, capture, - Some(closure_env_region), - ) - }), + if needs_ref { Some(closure_env_region) } else { child_capture.region }, + ); + }, + ), ); let coroutine_captures_by_ref_ty = Ty::new_fn_ptr( self.tcx, @@ -1761,6 +1772,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } +/// Determines whether a child capture that is derived from a parent capture +/// should be borrowed with the lifetime of the parent coroutine-closure's env. +/// +/// There are two cases when this needs to happen: +/// +/// (1.) Are we borrowing data owned by the parent closure? We can determine if +/// that is the case by checking if the parent capture is by move, EXCEPT if we +/// apply a deref projection, which means we're reborrowing a reference that we +/// captured by move. +/// +/// ```rust +/// #![feature(async_closure)] +/// let x = &1i32; // Let's call this lifetime `'1`. +/// let c = async move || { +/// println!("{:?}", *x); +/// // Even though the inner coroutine borrows by ref, we're only capturing `*x`, +/// // not `x`, so the inner closure is allowed to reborrow the data for `'1`. +/// }; +/// ``` +/// +/// (2.) If a coroutine is mutably borrowing from a parent capture, then that +/// mutable borrow cannot live for longer than either the parent *or* the borrow +/// that we have on the original upvar. Therefore we always need to borrow the +/// child capture with the lifetime of the parent coroutine-closure's env. +/// +/// ```rust +/// #![feature(async_closure)] +/// let mut x = 1i32; +/// let c = async || { +/// x = 1; +/// // The parent borrows `x` for some `&'1 mut i32`. +/// // However, when we call `c()`, we implicitly autoref for the signature of +/// // `AsyncFnMut::async_call_mut`. Let's call that lifetime `'call`. Since +/// // the maximum that `&'call mut &'1 mut i32` can be reborrowed is `&'call mut i32`, +/// // the inner coroutine should capture w/ the lifetime of the coroutine-closure. +/// }; +/// ``` +/// +/// If either of these cases apply, then we should capture the borrow with the +/// lifetime of the parent coroutine-closure's env. Luckily, if this function is +/// not correct, then the program is not unsound, since we still borrowck and validate +/// the choices made from this function -- the only side-effect is that the user +/// may receive unnecessary borrowck errors. +fn should_reborrow_from_env_of_parent_coroutine_closure<'tcx>( + parent_capture: &ty::CapturedPlace<'tcx>, + child_capture: &ty::CapturedPlace<'tcx>, +) -> bool { + // (1.) + (!parent_capture.is_by_ref() + && !matches!( + child_capture.place.projections.get(parent_capture.place.projections.len()), + Some(Projection { kind: ProjectionKind::Deref, .. }) + )) + // (2.) + || matches!(child_capture.info.capture_kind, UpvarCapture::ByRef(ty::BorrowKind::MutBorrow)) +} + /// Truncate the capture so that the place being borrowed is in accordance with RFC 1240, /// which states that it's unsafe to take a reference into a struct marked `repr(packed)`. fn restrict_repr_packed_field_ref_capture<'tcx>( diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 41df2e3b587..15bd5c08965 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -978,12 +978,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { CopyForDeref(ref place) => write!(fmt, "deref_copy {place:#?}"), AddressOf(mutability, ref place) => { - let kind_str = match mutability { - Mutability::Mut => "mut", - Mutability::Not => "const", - }; - - write!(fmt, "&raw {kind_str} {place:?}") + write!(fmt, "&raw {mut_str} {place:?}", mut_str = mutability.ptr_str()) } Aggregate(ref kind, ref places) => { diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 95d1e08b58b..211d403998f 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -6,6 +6,7 @@ use crate::{mir, ty}; use std::fmt::Write; use crate::query::Providers; +use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; @@ -415,6 +416,72 @@ impl BorrowKind { } } +pub fn analyze_coroutine_closure_captures<'a, 'tcx: 'a, T>( + parent_captures: impl IntoIterator<Item = &'a CapturedPlace<'tcx>>, + child_captures: impl IntoIterator<Item = &'a CapturedPlace<'tcx>>, + mut for_each: impl FnMut((usize, &'a CapturedPlace<'tcx>), (usize, &'a CapturedPlace<'tcx>)) -> T, +) -> impl Iterator<Item = T> + Captures<'a> + Captures<'tcx> { + std::iter::from_coroutine(move || { + let mut child_captures = child_captures.into_iter().enumerate().peekable(); + + // One parent capture may correspond to several child captures if we end up + // refining the set of captures via edition-2021 precise captures. We want to + // match up any number of child captures with one parent capture, so we keep + // peeking off this `Peekable` until the child doesn't match anymore. + for (parent_field_idx, parent_capture) in parent_captures.into_iter().enumerate() { + // Make sure we use every field at least once, b/c why are we capturing something + // if it's not used in the inner coroutine. + let mut field_used_at_least_once = false; + + // A parent matches a child if they share the same prefix of projections. + // The child may have more, if it is capturing sub-fields out of + // something that is captured by-move in the parent closure. + while child_captures.peek().map_or(false, |(_, child_capture)| { + child_prefix_matches_parent_projections(parent_capture, child_capture) + }) { + let (child_field_idx, child_capture) = child_captures.next().unwrap(); + // This analysis only makes sense if the parent capture is a + // prefix of the child capture. + assert!( + child_capture.place.projections.len() >= parent_capture.place.projections.len(), + "parent capture ({parent_capture:#?}) expected to be prefix of \ + child capture ({child_capture:#?})" + ); + + yield for_each( + (parent_field_idx, parent_capture), + (child_field_idx, child_capture), + ); + + field_used_at_least_once = true; + } + + // Make sure the field was used at least once. + assert!( + field_used_at_least_once, + "we captured {parent_capture:#?} but it was not used in the child coroutine?" + ); + } + assert_eq!(child_captures.next(), None, "leftover child captures?"); + }) +} + +fn child_prefix_matches_parent_projections( + parent_capture: &ty::CapturedPlace<'_>, + child_capture: &ty::CapturedPlace<'_>, +) -> bool { + let HirPlaceBase::Upvar(parent_base) = parent_capture.place.base else { + bug!("expected capture to be an upvar"); + }; + let HirPlaceBase::Upvar(child_base) = child_capture.place.base else { + bug!("expected capture to be an upvar"); + }; + + parent_base.var_path.hir_id == child_base.var_path.hir_id + && std::iter::zip(&child_capture.place.projections, &parent_capture.place.projections) + .all(|(child, parent)| child.kind == parent.kind) +} + pub fn provide(providers: &mut Providers) { *providers = Providers { closure_typeinfo, ..*providers } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ee4dc9744ac..e6b773ae512 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -77,9 +77,10 @@ pub use rustc_type_ir::ConstKind::{ pub use rustc_type_ir::*; pub use self::closure::{ - is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo, - CapturedPlace, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList, - RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL, + analyze_coroutine_closure_captures, is_ancestor_or_same_capture, place_to_string_for_capture, + BorrowKind, CaptureInfo, CapturedPlace, ClosureTypeInfo, MinCaptureInformationMap, + MinCaptureList, RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, + CAPTURE_STRUCT_LOCAL, }; pub use self::consts::{ Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 20ebd87c3d4..0bd009cd51d 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -671,13 +671,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { p!("(", print(ty), ") is ", write("{pat:?}")) } ty::RawPtr(ty, mutbl) => { - p!(write( - "*{} ", - match mutbl { - hir::Mutability::Mut => "mut", - hir::Mutability::Not => "const", - } - )); + p!(write("*{} ", mutbl.ptr_str())); p!(print(ty)) } ty::Ref(r, ty, mutbl) => { diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index b26f968bf5e..3d6c1a95204 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -71,7 +71,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_hir as hir; -use rustc_middle::hir::place::{PlaceBase, Projection, ProjectionKind}; +use rustc_middle::hir::place::{Projection, ProjectionKind}; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::{self, dump_mir, MirPass}; use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, TypeVisitableExt}; @@ -124,44 +124,10 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { .tuple_fields() .len(); - let mut field_remapping = UnordMap::default(); - - let mut child_captures = tcx - .closure_captures(coroutine_def_id) - .iter() - .copied() - // By construction we capture all the args first. - .skip(num_args) - .enumerate() - .peekable(); - - // One parent capture may correspond to several child captures if we end up - // refining the set of captures via edition-2021 precise captures. We want to - // match up any number of child captures with one parent capture, so we keep - // peeking off this `Peekable` until the child doesn't match anymore. - for (parent_field_idx, parent_capture) in - tcx.closure_captures(parent_def_id).iter().copied().enumerate() - { - // Make sure we use every field at least once, b/c why are we capturing something - // if it's not used in the inner coroutine. - let mut field_used_at_least_once = false; - - // A parent matches a child if they share the same prefix of projections. - // The child may have more, if it is capturing sub-fields out of - // something that is captured by-move in the parent closure. - while child_captures.peek().map_or(false, |(_, child_capture)| { - child_prefix_matches_parent_projections(parent_capture, child_capture) - }) { - let (child_field_idx, child_capture) = child_captures.next().unwrap(); - - // This analysis only makes sense if the parent capture is a - // prefix of the child capture. - assert!( - child_capture.place.projections.len() >= parent_capture.place.projections.len(), - "parent capture ({parent_capture:#?}) expected to be prefix of \ - child capture ({child_capture:#?})" - ); - + let field_remapping: UnordMap<_, _> = ty::analyze_coroutine_closure_captures( + tcx.closure_captures(parent_def_id).iter().copied(), + tcx.closure_captures(coroutine_def_id).iter().skip(num_args).copied(), + |(parent_field_idx, parent_capture), (child_field_idx, child_capture)| { // Store this set of additional projections (fields and derefs). // We need to re-apply them later. let child_precise_captures = @@ -192,7 +158,7 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { ), }; - field_remapping.insert( + ( FieldIdx::from_usize(child_field_idx + num_args), ( FieldIdx::from_usize(parent_field_idx + num_args), @@ -200,18 +166,10 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { needs_deref, child_precise_captures, ), - ); - - field_used_at_least_once = true; - } - - // Make sure the field was used at least once. - assert!( - field_used_at_least_once, - "we captured {parent_capture:#?} but it was not used in the child coroutine?" - ); - } - assert_eq!(child_captures.next(), None, "leftover child captures?"); + ) + }, + ) + .collect(); if coroutine_kind == ty::ClosureKind::FnOnce { assert_eq!(field_remapping.len(), tcx.closure_captures(parent_def_id).len()); @@ -241,22 +199,6 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody { } } -fn child_prefix_matches_parent_projections( - parent_capture: &ty::CapturedPlace<'_>, - child_capture: &ty::CapturedPlace<'_>, -) -> bool { - let PlaceBase::Upvar(parent_base) = parent_capture.place.base else { - bug!("expected capture to be an upvar"); - }; - let PlaceBase::Upvar(child_base) = child_capture.place.base else { - bug!("expected capture to be an upvar"); - }; - - parent_base.var_path.hir_id == child_base.var_path.hir_id - && std::iter::zip(&child_capture.place.projections, &parent_capture.place.projections) - .all(|(child, parent)| child.kind == parent.kind) -} - struct MakeByMoveBody<'tcx> { tcx: TyCtxt<'tcx>, field_remapping: UnordMap<FieldIdx, (FieldIdx, Ty<'tcx>, bool, &'tcx [Projection<'tcx>])>, diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index 70528c1222c..5ae9a2e2058 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -87,6 +87,20 @@ fn reserved_x18( } } +fn restricted_for_arm64ec( + arch: InlineAsmArch, + _reloc_model: RelocModel, + _target_features: &FxIndexSet<Symbol>, + _target: &Target, + _is_clobber: bool, +) -> Result<(), &'static str> { + if arch == InlineAsmArch::Arm64EC { + Err("x13, x14, x23, x24, x28, v16-v31 cannot be used for Arm64EC") + } else { + Ok(()) + } +} + def_regs! { AArch64 AArch64InlineAsmReg AArch64InlineAsmRegClass { x0: reg = ["x0", "w0"], @@ -102,8 +116,8 @@ def_regs! { x10: reg = ["x10", "w10"], x11: reg = ["x11", "w11"], x12: reg = ["x12", "w12"], - x13: reg = ["x13", "w13"], - x14: reg = ["x14", "w14"], + x13: reg = ["x13", "w13"] % restricted_for_arm64ec, + x14: reg = ["x14", "w14"] % restricted_for_arm64ec, x15: reg = ["x15", "w15"], x16: reg = ["x16", "w16"], x17: reg = ["x17", "w17"], @@ -111,12 +125,12 @@ def_regs! { x20: reg = ["x20", "w20"], x21: reg = ["x21", "w21"], x22: reg = ["x22", "w22"], - x23: reg = ["x23", "w23"], - x24: reg = ["x24", "w24"], + x23: reg = ["x23", "w23"] % restricted_for_arm64ec, + x24: reg = ["x24", "w24"] % restricted_for_arm64ec, x25: reg = ["x25", "w25"], x26: reg = ["x26", "w26"], x27: reg = ["x27", "w27"], - x28: reg = ["x28", "w28"], + x28: reg = ["x28", "w28"] % restricted_for_arm64ec, x30: reg = ["x30", "w30", "lr", "wlr"], v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0", "z0"], v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1", "z1"], @@ -134,22 +148,22 @@ def_regs! { v13: vreg, vreg_low16 = ["v13", "b13", "h13", "s13", "d13", "q13", "z13"], v14: vreg, vreg_low16 = ["v14", "b14", "h14", "s14", "d14", "q14", "z14"], v15: vreg, vreg_low16 = ["v15", "b15", "h15", "s15", "d15", "q15", "z15"], - v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16", "z16"], - v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17", "z17"], - v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18", "z18"], - v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19", "z19"], - v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20", "z20"], - v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21", "z21"], - v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22", "z22"], - v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23", "z23"], - v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24", "z24"], - v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25", "z25"], - v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26", "z26"], - v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27", "z27"], - v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28", "z28"], - v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"], - v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"], - v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"], + v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16", "z16"] % restricted_for_arm64ec, + v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17", "z17"] % restricted_for_arm64ec, + v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18", "z18"] % restricted_for_arm64ec, + v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19", "z19"] % restricted_for_arm64ec, + v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20", "z20"] % restricted_for_arm64ec, + v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21", "z21"] % restricted_for_arm64ec, + v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22", "z22"] % restricted_for_arm64ec, + v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23", "z23"] % restricted_for_arm64ec, + v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24", "z24"] % restricted_for_arm64ec, + v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25", "z25"] % restricted_for_arm64ec, + v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26", "z26"] % restricted_for_arm64ec, + v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27", "z27"] % restricted_for_arm64ec, + v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28", "z28"] % restricted_for_arm64ec, + v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"] % restricted_for_arm64ec, + v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"] % restricted_for_arm64ec, + v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"] % restricted_for_arm64ec, p0: preg = ["p0"], p1: preg = ["p1"], p2: preg = ["p2"], diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 2e04dca98c5..d6bbf4f36cf 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -217,6 +217,7 @@ pub enum InlineAsmArch { X86_64, Arm, AArch64, + Arm64EC, RiscV32, RiscV64, Nvptx64, @@ -246,6 +247,7 @@ impl FromStr for InlineAsmArch { "x86_64" => Ok(Self::X86_64), "arm" => Ok(Self::Arm), "aarch64" => Ok(Self::AArch64), + "arm64ec" => Ok(Self::Arm64EC), "riscv32" => Ok(Self::RiscV32), "riscv64" => Ok(Self::RiscV64), "nvptx64" => Ok(Self::Nvptx64), @@ -341,7 +343,9 @@ impl InlineAsmReg { Ok(match arch { InlineAsmArch::X86 | InlineAsmArch::X86_64 => Self::X86(X86InlineAsmReg::parse(name)?), InlineAsmArch::Arm => Self::Arm(ArmInlineAsmReg::parse(name)?), - InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmReg::parse(name)?), + InlineAsmArch::AArch64 | InlineAsmArch::Arm64EC => { + Self::AArch64(AArch64InlineAsmReg::parse(name)?) + } InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { Self::RiscV(RiscVInlineAsmReg::parse(name)?) } @@ -610,7 +614,9 @@ impl InlineAsmRegClass { Self::X86(X86InlineAsmRegClass::parse(name)?) } InlineAsmArch::Arm => Self::Arm(ArmInlineAsmRegClass::parse(name)?), - InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmRegClass::parse(name)?), + InlineAsmArch::AArch64 | InlineAsmArch::Arm64EC => { + Self::AArch64(AArch64InlineAsmRegClass::parse(name)?) + } InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { Self::RiscV(RiscVInlineAsmRegClass::parse(name)?) } @@ -783,7 +789,7 @@ pub fn allocatable_registers( arm::fill_reg_map(arch, reloc_model, target_features, target, &mut map); map } - InlineAsmArch::AArch64 => { + InlineAsmArch::AArch64 | InlineAsmArch::Arm64EC => { let mut map = aarch64::regclass_map(); aarch64::fill_reg_map(arch, reloc_model, target_features, target, &mut map); map @@ -909,6 +915,10 @@ impl InlineAsmClobberAbi { }), _ => Err(&["C", "system", "efiapi"]), }, + InlineAsmArch::Arm64EC => match name { + "C" | "system" => Ok(InlineAsmClobberAbi::AArch64NoX18), + _ => Err(&["C", "system"]), + }, InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name { "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV), _ => Err(&["C", "system", "efiapi"]), diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 8813955f2af..56ae7ad9f74 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -373,17 +373,8 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> { Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)), Pat(t, p) => write!(f, "pattern_type!({:?} is {:?})", &this.wrap(t), &this.wrap(p)), Slice(t) => write!(f, "[{:?}]", &this.wrap(t)), - RawPtr(ty, mutbl) => { - match mutbl { - Mutability::Mut => write!(f, "*mut "), - Mutability::Not => write!(f, "*const "), - }?; - write!(f, "{:?}", &this.wrap(ty)) - } - Ref(r, t, m) => match m { - Mutability::Mut => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)), - Mutability::Not => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)), - }, + RawPtr(ty, mutbl) => write!(f, "*{} {:?}", mutbl.ptr_str(), this.wrap(ty)), + Ref(r, t, m) => write!(f, "&{:?} {}{:?}", this.wrap(r), m.prefix_str(), this.wrap(t)), FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&this.wrap(s)).finish(), FnPtr(s) => write!(f, "{:?}", &this.wrap(s)), Dynamic(p, r, repr) => match repr { diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index 59acbc73db4..43e11b6d57d 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -19,6 +19,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect - M68k - CSKY - s390x +- Arm64EC ## Register classes @@ -51,6 +52,9 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | CSKY | `freg` | `f[0-31]` | `f` | | s390x | `reg` | `r[0-10]`, `r[12-14]` | `r` | | s390x | `freg` | `f[0-15]` | `f` | +| Arm64EC | `reg` | `x[0-12]`, `x[15-22]`, `x[25-27]`, `x30` | `r` | +| Arm64EC | `vreg` | `v[0-15]` | `w` | +| Arm64EC | `vreg_low16` | `v[0-15]` | `x` | > **Notes**: > - NVPTX doesn't have a fixed register set, so named registers are not supported. @@ -86,6 +90,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | CSKY | `freg` | None | `f32`, | | s390x | `reg`, `reg_addr` | None | `i8`, `i16`, `i32`, `i64` | | s390x | `freg` | None | `f32`, `f64` | +| Arm64EC | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | +| Arm64EC | `vreg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` | ## Register aliases @@ -118,6 +124,12 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | CSKY | `r29` | `rtb` | | CSKY | `r30` | `svbr` | | CSKY | `r31` | `tls` | +| Arm64EC | `x[0-30]` | `w[0-30]` | +| Arm64EC | `x29` | `fp` | +| Arm64EC | `x30` | `lr` | +| Arm64EC | `sp` | `wsp` | +| Arm64EC | `xzr` | `wzr` | +| Arm64EC | `v[0-15]` | `b[0-15]`, `h[0-15]`, `s[0-15]`, `d[0-15]`, `q[0-15]` | > **Notes**: > - TI does not mandate a frame pointer for MSP430, but toolchains are allowed @@ -128,8 +140,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | Architecture | Unsupported register | Reason | | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | All | `sp`, `r15` (s390x) | The stack pointer must be restored to its original value at the end of an asm code block. | -| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x) | The frame pointer cannot be used as an input or output. | -| All | `r19` (Hexagon) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. | +| All | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output. | +| All | `r19` (Hexagon), `x19` (Arm64EC) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. | | MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. | | MIPS | `$1` or `$at` | Reserved for assembler. | | MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. | @@ -145,6 +157,9 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | CSKY | `r15` | This is the link register. | | CSKY | `r[26-30]` | Reserved by its ABI. | | CSKY | `r31` | This is the TLS register. | +| Arm64EC | `xzr` | This is a constant zero register which can't be modified. | +| Arm64EC | `x18` | This is an OS-reserved register. | +| Arm64EC | `x13`, `x14`, `x23`, `x24`, `x28`, `v[16-31]` | These are AArch64 registers that are not supported for Arm64EC. | ## Template modifiers @@ -165,6 +180,16 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | s390x | `freg` | None | `%f0` | None | | CSKY | `reg` | None | `r0` | None | | CSKY | `freg` | None | `f0` | None | +| Arm64EC | `reg` | None | `x0` | `x` | +| Arm64EC | `reg` | `w` | `w0` | `w` | +| Arm64EC | `reg` | `x` | `x0` | `x` | +| Arm64EC | `vreg` | None | `v0` | None | +| Arm64EC | `vreg` | `v` | `v0` | None | +| Arm64EC | `vreg` | `b` | `b0` | `b` | +| Arm64EC | `vreg` | `h` | `h0` | `h` | +| Arm64EC | `vreg` | `s` | `s0` | `s` | +| Arm64EC | `vreg` | `d` | `d0` | `d` | +| Arm64EC | `vreg` | `q` | `q0` | `q` | # Flags covered by `preserves_flags` @@ -177,3 +202,6 @@ These flags registers must be restored upon exiting the asm block if the `preser - The condition code register `ccr`. - s390x - The condition code register `cc`. +- Arm64EC + - Condition flags (`NZCV` register). + - Floating-point status (`FPSR` register). diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index ec944cb7fb4..80dd06dc7ad 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -935,16 +935,25 @@ struct HeaderLine<'ln> { pub(crate) struct CheckDirectiveResult<'ln> { is_known_directive: bool, directive_name: &'ln str, + trailing_directive: Option<&'ln str>, } -// Returns `(is_known_directive, directive_name)`. pub(crate) fn check_directive(directive_ln: &str) -> CheckDirectiveResult<'_> { - let directive_name = - directive_ln.split_once([':', ' ']).map(|(pre, _)| pre).unwrap_or(directive_ln); + let (directive_name, post) = directive_ln.split_once([':', ' ']).unwrap_or((directive_ln, "")); + + let trailing = post.trim().split_once(' ').map(|(pre, _)| pre).unwrap_or(post); + let trailing_directive = { + // 1. is the directive name followed by a space? (to exclude `:`) + matches!(directive_ln.get(directive_name.len()..), Some(s) if s.starts_with(" ")) + // 2. is what is after that directive also a directive (ex: "only-x86 only-arm") + && KNOWN_DIRECTIVE_NAMES.contains(&trailing) + } + .then_some(trailing); CheckDirectiveResult { is_known_directive: KNOWN_DIRECTIVE_NAMES.contains(&directive_name), directive_name: directive_ln, + trailing_directive, } } @@ -1014,7 +1023,8 @@ fn iter_header( if testfile.extension().map(|e| e == "rs").unwrap_or(false) { let directive_ln = non_revisioned_directive_line.trim(); - let CheckDirectiveResult { is_known_directive, .. } = check_directive(directive_ln); + let CheckDirectiveResult { is_known_directive, trailing_directive, .. } = + check_directive(directive_ln); if !is_known_directive { *poisoned = true; @@ -1028,6 +1038,21 @@ fn iter_header( return; } + + if let Some(trailing_directive) = &trailing_directive { + *poisoned = true; + + eprintln!( + "error: detected trailing compiletest test directive `{}` in {}:{}\n \ + help: put the trailing directive in it's own line: `//@ {}`", + trailing_directive, + testfile.display(), + line_number, + trailing_directive, + ); + + return; + } } it(HeaderLine { @@ -1051,7 +1076,8 @@ fn iter_header( let rest = rest.trim_start(); - let CheckDirectiveResult { is_known_directive, directive_name } = check_directive(rest); + let CheckDirectiveResult { is_known_directive, directive_name, .. } = + check_directive(rest); if is_known_directive { *poisoned = true; diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 83f0755b5c8..8a37a4d6d31 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -667,3 +667,24 @@ fn test_non_rs_unknown_directive_not_checked() { ); assert!(!poisoned); } + +#[test] +fn test_trailing_directive() { + let mut poisoned = false; + run_path(&mut poisoned, Path::new("a.rs"), b"//@ only-x86 only-arm"); + assert!(poisoned); +} + +#[test] +fn test_trailing_directive_with_comment() { + let mut poisoned = false; + run_path(&mut poisoned, Path::new("a.rs"), b"//@ only-x86 only-arm with comment"); + assert!(poisoned); +} + +#[test] +fn test_not_trailing_directive() { + let mut poisoned = false; + run_path(&mut poisoned, Path::new("a.rs"), b"//@ revisions: incremental"); + assert!(!poisoned); +} diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index e14932ad99d..211dc347b0f 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -1791,7 +1791,6 @@ ui/issues/issue-2150.rs ui/issues/issue-2151.rs ui/issues/issue-21546.rs ui/issues/issue-21554.rs -ui/issues/issue-21596.rs ui/issues/issue-21600.rs ui/issues/issue-21622.rs ui/issues/issue-21634.rs diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 78de8c0537d..7136bc4d8f2 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -17,7 +17,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: usize = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: usize = 1722; +const ISSUES_ENTRY_LIMIT: usize = 1720; const ROOT_ENTRY_LIMIT: usize = 859; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs index 1b2bd4b3d81..3e2a4773703 100644 --- a/tests/assembly/asm/aarch64-types.rs +++ b/tests/assembly/asm/aarch64-types.rs @@ -1,8 +1,11 @@ +//@ revisions: aarch64 arm64ec //@ assembly-output: emit-asm -//@ compile-flags: --target aarch64-unknown-linux-gnu -//@ needs-llvm-components: aarch64 +//@ [aarch64] compile-flags: --target aarch64-unknown-linux-gnu +//@ [aarch64] needs-llvm-components: aarch64 +//@ [arm64ec] compile-flags: --target arm64ec-pc-windows-msvc +//@ [arm64ec] needs-llvm-components: aarch64 -#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] @@ -77,7 +80,7 @@ extern "C" { static extern_static: u8; } -// CHECK-LABEL: sym_fn: +// CHECK-LABEL: {{("#)?}}sym_fn{{"?}} // CHECK: //APP // CHECK: bl extern_func // CHECK: //NO_APP @@ -86,7 +89,7 @@ pub unsafe fn sym_fn() { asm!("bl {}", sym extern_func); } -// CHECK-LABEL: sym_static: +// CHECK-LABEL: {{("#)?}}sym_static{{"?}} // CHECK: //APP // CHECK: adr x0, extern_static // CHECK: //NO_APP @@ -96,7 +99,7 @@ pub unsafe fn sym_static() { } // Regression test for #75761 -// CHECK-LABEL: issue_75761: +// CHECK-LABEL: {{("#)?}}issue_75761{{"?}} // CHECK: str {{.*}}x30 // CHECK: //APP // CHECK: //NO_APP @@ -144,421 +147,421 @@ macro_rules! check_reg { }; } -// CHECK-LABEL: reg_i8: +// CHECK-LABEL: {{("#)?}}reg_i8{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check!(reg_i8 i8 reg "mov" ""); -// CHECK-LABEL: reg_i16: +// CHECK-LABEL: {{("#)?}}reg_i16{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check!(reg_i16 i16 reg "mov" ""); -// CHECK-LABEL: reg_i32: +// CHECK-LABEL: {{("#)?}}reg_i32{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check!(reg_i32 i32 reg "mov" ""); -// CHECK-LABEL: reg_f32: +// CHECK-LABEL: {{("#)?}}reg_f32{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check!(reg_f32 f32 reg "mov" ""); -// CHECK-LABEL: reg_i64: +// CHECK-LABEL: {{("#)?}}reg_i64{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check!(reg_i64 i64 reg "mov" ""); -// CHECK-LABEL: reg_f64: +// CHECK-LABEL: {{("#)?}}reg_f64{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check!(reg_f64 f64 reg "mov" ""); -// CHECK-LABEL: reg_ptr: +// CHECK-LABEL: {{("#)?}}reg_ptr{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check!(reg_ptr ptr reg "mov" ""); -// CHECK-LABEL: vreg_i8: +// CHECK-LABEL: {{("#)?}}vreg_i8{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_i8 i8 vreg "fmov" "s"); -// CHECK-LABEL: vreg_i16: +// CHECK-LABEL: {{("#)?}}vreg_i16{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_i16 i16 vreg "fmov" "s"); -// CHECK-LABEL: vreg_i32: +// CHECK-LABEL: {{("#)?}}vreg_i32{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_i32 i32 vreg "fmov" "s"); -// CHECK-LABEL: vreg_f32: +// CHECK-LABEL: {{("#)?}}vreg_f32{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_f32 f32 vreg "fmov" "s"); -// CHECK-LABEL: vreg_i64: +// CHECK-LABEL: {{("#)?}}vreg_i64{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_i64 i64 vreg "fmov" "s"); -// CHECK-LABEL: vreg_f64: +// CHECK-LABEL: {{("#)?}}vreg_f64{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_f64 f64 vreg "fmov" "s"); -// CHECK-LABEL: vreg_ptr: +// CHECK-LABEL: {{("#)?}}vreg_ptr{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_ptr ptr vreg "fmov" "s"); -// CHECK-LABEL: vreg_i8x8: +// CHECK-LABEL: {{("#)?}}vreg_i8x8{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_i8x8 i8x8 vreg "fmov" "s"); -// CHECK-LABEL: vreg_i16x4: +// CHECK-LABEL: {{("#)?}}vreg_i16x4{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_i16x4 i16x4 vreg "fmov" "s"); -// CHECK-LABEL: vreg_i32x2: +// CHECK-LABEL: {{("#)?}}vreg_i32x2{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_i32x2 i32x2 vreg "fmov" "s"); -// CHECK-LABEL: vreg_i64x1: +// CHECK-LABEL: {{("#)?}}vreg_i64x1{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_i64x1 i64x1 vreg "fmov" "s"); -// CHECK-LABEL: vreg_f32x2: +// CHECK-LABEL: {{("#)?}}vreg_f32x2{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_f32x2 f32x2 vreg "fmov" "s"); -// CHECK-LABEL: vreg_f64x1: +// CHECK-LABEL: {{("#)?}}vreg_f64x1{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_f64x1 f64x1 vreg "fmov" "s"); -// CHECK-LABEL: vreg_i8x16: +// CHECK-LABEL: {{("#)?}}vreg_i8x16{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_i8x16 i8x16 vreg "fmov" "s"); -// CHECK-LABEL: vreg_i16x8: +// CHECK-LABEL: {{("#)?}}vreg_i16x8{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_i16x8 i16x8 vreg "fmov" "s"); -// CHECK-LABEL: vreg_i32x4: +// CHECK-LABEL: {{("#)?}}vreg_i32x4{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_i32x4 i32x4 vreg "fmov" "s"); -// CHECK-LABEL: vreg_i64x2: +// CHECK-LABEL: {{("#)?}}vreg_i64x2{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_i64x2 i64x2 vreg "fmov" "s"); -// CHECK-LABEL: vreg_f32x4: +// CHECK-LABEL: {{("#)?}}vreg_f32x4{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_f32x4 f32x4 vreg "fmov" "s"); -// CHECK-LABEL: vreg_f64x2: +// CHECK-LABEL: {{("#)?}}vreg_f64x2{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_f64x2 f64x2 vreg "fmov" "s"); -// CHECK-LABEL: vreg_low16_i8: +// CHECK-LABEL: {{("#)?}}vreg_low16_i8{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_i8 i8 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_i16: +// CHECK-LABEL: {{("#)?}}vreg_low16_i16{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_i16 i16 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_f32: +// CHECK-LABEL: {{("#)?}}vreg_low16_f32{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_f32 f32 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_i64: +// CHECK-LABEL: {{("#)?}}vreg_low16_i64{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_i64 i64 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_f64: +// CHECK-LABEL: {{("#)?}}vreg_low16_f64{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_f64 f64 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_ptr: +// CHECK-LABEL: {{("#)?}}vreg_low16_ptr{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_ptr ptr vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_i8x8: +// CHECK-LABEL: {{("#)?}}vreg_low16_i8x8{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_i8x8 i8x8 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_i16x4: +// CHECK-LABEL: {{("#)?}}vreg_low16_i16x4{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_i16x4 i16x4 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_i32x2: +// CHECK-LABEL: {{("#)?}}vreg_low16_i32x2{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_i32x2 i32x2 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_i64x1: +// CHECK-LABEL: {{("#)?}}vreg_low16_i64x1{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_i64x1 i64x1 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_f32x2: +// CHECK-LABEL: {{("#)?}}vreg_low16_f32x2{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_f32x2 f32x2 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_f64x1: +// CHECK-LABEL: {{("#)?}}vreg_low16_f64x1{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_f64x1 f64x1 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_i8x16: +// CHECK-LABEL: {{("#)?}}vreg_low16_i8x16{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_i8x16 i8x16 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_i16x8: +// CHECK-LABEL: {{("#)?}}vreg_low16_i16x8{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_i16x8 i16x8 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_i32x4: +// CHECK-LABEL: {{("#)?}}vreg_low16_i32x4{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_i32x4 i32x4 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_i64x2: +// CHECK-LABEL: {{("#)?}}vreg_low16_i64x2{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_i64x2 i64x2 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_f32x4: +// CHECK-LABEL: {{("#)?}}vreg_low16_f32x4{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_f32x4 f32x4 vreg_low16 "fmov" "s"); -// CHECK-LABEL: vreg_low16_f64x2: +// CHECK-LABEL: {{("#)?}}vreg_low16_f64x2{{"?}} // CHECK: //APP // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}} // CHECK: //NO_APP check!(vreg_low16_f64x2 f64x2 vreg_low16 "fmov" "s"); -// CHECK-LABEL: x0_i8: +// CHECK-LABEL: {{("#)?}}x0_i8{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check_reg!(x0_i8 i8 "x0" "mov"); -// CHECK-LABEL: x0_i16: +// CHECK-LABEL: {{("#)?}}x0_i16{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check_reg!(x0_i16 i16 "x0" "mov"); -// CHECK-LABEL: x0_i32: +// CHECK-LABEL: {{("#)?}}x0_i32{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check_reg!(x0_i32 i32 "x0" "mov"); -// CHECK-LABEL: x0_f32: +// CHECK-LABEL: {{("#)?}}x0_f32{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check_reg!(x0_f32 f32 "x0" "mov"); -// CHECK-LABEL: x0_i64: +// CHECK-LABEL: {{("#)?}}x0_i64{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check_reg!(x0_i64 i64 "x0" "mov"); -// CHECK-LABEL: x0_f64: +// CHECK-LABEL: {{("#)?}}x0_f64{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check_reg!(x0_f64 f64 "x0" "mov"); -// CHECK-LABEL: x0_ptr: +// CHECK-LABEL: {{("#)?}}x0_ptr{{"?}} // CHECK: //APP // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}} // CHECK: //NO_APP check_reg!(x0_ptr ptr "x0" "mov"); -// CHECK-LABEL: v0_i8: +// CHECK-LABEL: {{("#)?}}v0_i8{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_i8 i8 "s0" "fmov"); -// CHECK-LABEL: v0_i16: +// CHECK-LABEL: {{("#)?}}v0_i16{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_i16 i16 "s0" "fmov"); -// CHECK-LABEL: v0_i32: +// CHECK-LABEL: {{("#)?}}v0_i32{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_i32 i32 "s0" "fmov"); -// CHECK-LABEL: v0_f32: +// CHECK-LABEL: {{("#)?}}v0_f32{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_f32 f32 "s0" "fmov"); -// CHECK-LABEL: v0_i64: +// CHECK-LABEL: {{("#)?}}v0_i64{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_i64 i64 "s0" "fmov"); -// CHECK-LABEL: v0_f64: +// CHECK-LABEL: {{("#)?}}v0_f64{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_f64 f64 "s0" "fmov"); -// CHECK-LABEL: v0_ptr: +// CHECK-LABEL: {{("#)?}}v0_ptr{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_ptr ptr "s0" "fmov"); -// CHECK-LABEL: v0_i8x8: +// CHECK-LABEL: {{("#)?}}v0_i8x8{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_i8x8 i8x8 "s0" "fmov"); -// CHECK-LABEL: v0_i16x4: +// CHECK-LABEL: {{("#)?}}v0_i16x4{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_i16x4 i16x4 "s0" "fmov"); -// CHECK-LABEL: v0_i32x2: +// CHECK-LABEL: {{("#)?}}v0_i32x2{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_i32x2 i32x2 "s0" "fmov"); -// CHECK-LABEL: v0_i64x1: +// CHECK-LABEL: {{("#)?}}v0_i64x1{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_i64x1 i64x1 "s0" "fmov"); -// CHECK-LABEL: v0_f32x2: +// CHECK-LABEL: {{("#)?}}v0_f32x2{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_f32x2 f32x2 "s0" "fmov"); -// CHECK-LABEL: v0_f64x1: +// CHECK-LABEL: {{("#)?}}v0_f64x1{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_f64x1 f64x1 "s0" "fmov"); -// CHECK-LABEL: v0_i8x16: +// CHECK-LABEL: {{("#)?}}v0_i8x16{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_i8x16 i8x16 "s0" "fmov"); -// CHECK-LABEL: v0_i16x8: +// CHECK-LABEL: {{("#)?}}v0_i16x8{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_i16x8 i16x8 "s0" "fmov"); -// CHECK-LABEL: v0_i32x4: +// CHECK-LABEL: {{("#)?}}v0_i32x4{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_i32x4 i32x4 "s0" "fmov"); -// CHECK-LABEL: v0_i64x2: +// CHECK-LABEL: {{("#)?}}v0_i64x2{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_i64x2 i64x2 "s0" "fmov"); -// CHECK-LABEL: v0_f32x4: +// CHECK-LABEL: {{("#)?}}v0_f32x4{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP check_reg!(v0_f32x4 f32x4 "s0" "fmov"); -// CHECK-LABEL: v0_f64x2: +// CHECK-LABEL: {{("#)?}}v0_f64x2{{"?}} // CHECK: //APP // CHECK: fmov s0, s0 // CHECK: //NO_APP diff --git a/tests/ui/asm/aarch64/type-check-2-2.stderr b/tests/ui/asm/aarch64/type-check-2-2.stderr index 41f7c01dc82..760aaefac83 100644 --- a/tests/ui/asm/aarch64/type-check-2-2.stderr +++ b/tests/ui/asm/aarch64/type-check-2-2.stderr @@ -8,8 +8,8 @@ LL | asm!("{}", in(reg) x); | help: consider assigning a value | -LL | let x: u64 = 0; - | +++ +LL | let x: u64 = 42; + | ++++ error[E0381]: used binding `y` isn't initialized --> $DIR/type-check-2-2.rs:22:9 @@ -21,8 +21,8 @@ LL | asm!("{}", inout(reg) y); | help: consider assigning a value | -LL | let mut y: u64 = 0; - | +++ +LL | let mut y: u64 = 42; + | ++++ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable --> $DIR/type-check-2-2.rs:28:13 diff --git a/tests/ui/asm/x86_64/type-check-5.stderr b/tests/ui/asm/x86_64/type-check-5.stderr index 7970e76d6a1..4fb75993463 100644 --- a/tests/ui/asm/x86_64/type-check-5.stderr +++ b/tests/ui/asm/x86_64/type-check-5.stderr @@ -8,8 +8,8 @@ LL | asm!("{}", in(reg) x); | help: consider assigning a value | -LL | let x: u64 = 0; - | +++ +LL | let x: u64 = 42; + | ++++ error[E0381]: used binding `y` isn't initialized --> $DIR/type-check-5.rs:18:9 @@ -21,8 +21,8 @@ LL | asm!("{}", inout(reg) y); | help: consider assigning a value | -LL | let mut y: u64 = 0; - | +++ +LL | let mut y: u64 = 42; + | ++++ error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable --> $DIR/type-check-5.rs:24:13 diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs index 1990d0ffe2a..ffb97ca04ac 100644 --- a/tests/ui/async-await/async-borrowck-escaping-closure-error.rs +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.rs @@ -5,7 +5,6 @@ fn foo() -> Box<dyn std::future::Future<Output = u32>> { let x = 0u32; Box::new((async || x)()) //~^ ERROR cannot return value referencing local variable `x` - //~| ERROR cannot return value referencing temporary value } fn main() { diff --git a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr index be67c78221a..4b1ce300b56 100644 --- a/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr +++ b/tests/ui/async-await/async-borrowck-escaping-closure-error.stderr @@ -7,15 +7,6 @@ LL | Box::new((async || x)()) | | `x` is borrowed here | returns a value referencing data owned by the current function -error[E0515]: cannot return value referencing temporary value - --> $DIR/async-borrowck-escaping-closure-error.rs:6:5 - | -LL | Box::new((async || x)()) - | ^^^^^^^^^------------^^^ - | | | - | | temporary value created here - | returns a value referencing data owned by the current function - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/async-await/async-closures/moro-example.rs b/tests/ui/async-await/async-closures/moro-example.rs new file mode 100644 index 00000000000..5a8f42c7ca5 --- /dev/null +++ b/tests/ui/async-await/async-closures/moro-example.rs @@ -0,0 +1,43 @@ +//@ check-pass +//@ edition: 2021 + +#![feature(async_closure)] + +use std::future::Future; +use std::pin::Pin; +use std::{marker::PhantomData, sync::Mutex}; + +type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>; + +pub struct Scope<'scope, 'env: 'scope> { + enqueued: Mutex<Vec<BoxFuture<'scope, ()>>>, + phantom: PhantomData<&'env ()>, +} + +impl<'scope, 'env: 'scope> Scope<'scope, 'env> { + pub fn spawn(&'scope self, future: impl Future<Output = ()> + Send + 'scope) { + self.enqueued.lock().unwrap().push(Box::pin(future)); + } +} + +fn scope_with_closure<'env, B>(_body: B) -> BoxFuture<'env, ()> +where + for<'scope> B: async FnOnce(&'scope Scope<'scope, 'env>), +{ + todo!() +} + +type ScopeRef<'scope, 'env> = &'scope Scope<'scope, 'env>; + +async fn go<'a>(value: &'a i32) { + let closure = async |scope: ScopeRef<'_, 'a>| { + let _future1 = scope.spawn(async { + // Make sure that `*value` is immutably borrowed with lifetime of + // `'a` and not with the lifetime of the containing coroutine-closure. + let _v = *value; + }); + }; + scope_with_closure(closure).await; +} + +fn main() {} diff --git a/tests/ui/async-await/async-closures/no-borrow-from-env.rs b/tests/ui/async-await/async-closures/no-borrow-from-env.rs new file mode 100644 index 00000000000..fe84aeeb32f --- /dev/null +++ b/tests/ui/async-await/async-closures/no-borrow-from-env.rs @@ -0,0 +1,44 @@ +//@ edition: 2021 +//@ check-pass + +#![feature(async_closure)] + +fn outlives<'a>(_: impl Sized + 'a) {} + +async fn call_once(f: impl async FnOnce()) { + f().await; +} + +fn simple<'a>(x: &'a i32) { + let c = async || { println!("{}", *x); }; + outlives::<'a>(c()); + outlives::<'a>(call_once(c)); + + let c = async move || { println!("{}", *x); }; + outlives::<'a>(c()); + outlives::<'a>(call_once(c)); +} + +struct S<'a>(&'a i32); + +fn through_field<'a>(x: S<'a>) { + let c = async || { println!("{}", *x.0); }; + outlives::<'a>(c()); + outlives::<'a>(call_once(c)); + + let c = async move || { println!("{}", *x.0); }; + outlives::<'a>(c()); + outlives::<'a>(call_once(c)); +} + +fn through_field_and_ref<'a>(x: &S<'a>) { + let c = async || { println!("{}", *x.0); }; + outlives::<'a>(c()); + outlives::<'a>(call_once(c)); + + let c = async move || { println!("{}", *x.0); }; + outlives::<'a>(c()); + // outlives::<'a>(call_once(c)); // FIXME(async_closures): Figure out why this fails +} + +fn main() {} diff --git a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs new file mode 100644 index 00000000000..17681161e20 --- /dev/null +++ b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.rs @@ -0,0 +1,47 @@ +//@ edition: 2018 + +// This is `no-borrow-from-env.rs`, but under edition 2018 we still want to make +// sure that we don't ICE or anything, even if precise closure captures means +// that we can't actually borrowck successfully. + +#![feature(async_closure)] + +fn outlives<'a>(_: impl Sized + 'a) {} + +async fn call_once(f: impl async FnOnce()) { + f().await; +} + +fn simple<'a>(x: &'a i32) { + let c = async || { println!("{}", *x); }; //~ ERROR `x` does not live long enough + outlives::<'a>(c()); + outlives::<'a>(call_once(c)); + + let c = async move || { println!("{}", *x); }; + outlives::<'a>(c()); //~ ERROR `c` does not live long enough + outlives::<'a>(call_once(c)); //~ ERROR cannot move out of `c` +} + +struct S<'a>(&'a i32); + +fn through_field<'a>(x: S<'a>) { + let c = async || { println!("{}", *x.0); }; //~ ERROR `x` does not live long enough + outlives::<'a>(c()); + outlives::<'a>(call_once(c)); + + let c = async move || { println!("{}", *x.0); }; //~ ERROR cannot move out of `x` + outlives::<'a>(c()); //~ ERROR `c` does not live long enough + outlives::<'a>(call_once(c)); //~ ERROR cannot move out of `c` +} + +fn through_field_and_ref<'a>(x: &S<'a>) { + let c = async || { println!("{}", *x.0); }; //~ ERROR `x` does not live long enough + outlives::<'a>(c()); + outlives::<'a>(call_once(c)); //~ ERROR explicit lifetime required in the type of `x` + + let c = async move || { println!("{}", *x.0); }; + outlives::<'a>(c()); //~ ERROR `c` does not live long enough + // outlives::<'a>(call_once(c)); // FIXME(async_closures): Figure out why this fails +} + +fn main() {} diff --git a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr new file mode 100644 index 00000000000..569028934cb --- /dev/null +++ b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr @@ -0,0 +1,152 @@ +error[E0597]: `x` does not live long enough + --> $DIR/without-precise-captures-we-are-powerless.rs:16:13 + | +LL | fn simple<'a>(x: &'a i32) { + | -- lifetime `'a` defined here +LL | let c = async || { println!("{}", *x); }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough +LL | outlives::<'a>(c()); +LL | outlives::<'a>(call_once(c)); + | ------------ argument requires that `x` is borrowed for `'a` +... +LL | } + | - `x` dropped here while still borrowed + +error[E0597]: `c` does not live long enough + --> $DIR/without-precise-captures-we-are-powerless.rs:21:20 + | +LL | fn simple<'a>(x: &'a i32) { + | -- lifetime `'a` defined here +... +LL | let c = async move || { println!("{}", *x); }; + | - binding `c` declared here +LL | outlives::<'a>(c()); + | ^-- + | | + | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +LL | outlives::<'a>(call_once(c)); +LL | } + | - `c` dropped here while still borrowed + +error[E0505]: cannot move out of `c` because it is borrowed + --> $DIR/without-precise-captures-we-are-powerless.rs:22:30 + | +LL | fn simple<'a>(x: &'a i32) { + | -- lifetime `'a` defined here +... +LL | let c = async move || { println!("{}", *x); }; + | - binding `c` declared here +LL | outlives::<'a>(c()); + | --- + | | + | borrow of `c` occurs here + | argument requires that `c` is borrowed for `'a` +LL | outlives::<'a>(call_once(c)); + | ^ move out of `c` occurs here + +error[E0597]: `x` does not live long enough + --> $DIR/without-precise-captures-we-are-powerless.rs:28:13 + | +LL | fn through_field<'a>(x: S<'a>) { + | -- lifetime `'a` defined here +LL | let c = async || { println!("{}", *x.0); }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough +LL | outlives::<'a>(c()); +LL | outlives::<'a>(call_once(c)); + | ------------ argument requires that `x` is borrowed for `'a` +... +LL | } + | - `x` dropped here while still borrowed + +error[E0505]: cannot move out of `x` because it is borrowed + --> $DIR/without-precise-captures-we-are-powerless.rs:32:13 + | +LL | fn through_field<'a>(x: S<'a>) { + | -- lifetime `'a` defined here +LL | let c = async || { println!("{}", *x.0); }; + | ---------------------------------- borrow of `x` occurs here +LL | outlives::<'a>(c()); +LL | outlives::<'a>(call_once(c)); + | ------------ argument requires that `x` is borrowed for `'a` +LL | +LL | let c = async move || { println!("{}", *x.0); }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `x` occurs here + +error[E0597]: `c` does not live long enough + --> $DIR/without-precise-captures-we-are-powerless.rs:33:20 + | +LL | fn through_field<'a>(x: S<'a>) { + | -- lifetime `'a` defined here +... +LL | let c = async move || { println!("{}", *x.0); }; + | - binding `c` declared here +LL | outlives::<'a>(c()); + | ^-- + | | + | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +LL | outlives::<'a>(call_once(c)); +LL | } + | - `c` dropped here while still borrowed + +error[E0505]: cannot move out of `c` because it is borrowed + --> $DIR/without-precise-captures-we-are-powerless.rs:34:30 + | +LL | fn through_field<'a>(x: S<'a>) { + | -- lifetime `'a` defined here +... +LL | let c = async move || { println!("{}", *x.0); }; + | - binding `c` declared here +LL | outlives::<'a>(c()); + | --- + | | + | borrow of `c` occurs here + | argument requires that `c` is borrowed for `'a` +LL | outlives::<'a>(call_once(c)); + | ^ move out of `c` occurs here + +error[E0597]: `x` does not live long enough + --> $DIR/without-precise-captures-we-are-powerless.rs:38:13 + | +LL | fn through_field_and_ref<'a>(x: &S<'a>) { + | -- lifetime `'a` defined here +LL | let c = async || { println!("{}", *x.0); }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough +LL | outlives::<'a>(c()); +LL | outlives::<'a>(call_once(c)); + | ------------ argument requires that `x` is borrowed for `'a` +... +LL | } + | - `x` dropped here while still borrowed + +error[E0621]: explicit lifetime required in the type of `x` + --> $DIR/without-precise-captures-we-are-powerless.rs:40:20 + | +LL | fn through_field_and_ref<'a>(x: &S<'a>) { + | ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>` +... +LL | outlives::<'a>(call_once(c)); + | ^^^^^^^^^^^^ lifetime `'a` required + +error[E0597]: `c` does not live long enough + --> $DIR/without-precise-captures-we-are-powerless.rs:43:20 + | +LL | fn through_field_and_ref<'a>(x: &S<'a>) { + | -- lifetime `'a` defined here +... +LL | let c = async move || { println!("{}", *x.0); }; + | - binding `c` declared here +LL | outlives::<'a>(c()); + | ^-- + | | + | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` +LL | // outlives::<'a>(call_once(c)); // FIXME(async_closures): Figure out why this fails +LL | } + | - `c` dropped here while still borrowed + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0505, E0597, E0621. +For more information about an error, try `rustc --explain E0505`. diff --git a/tests/ui/binop/issue-77910-1.stderr b/tests/ui/binop/issue-77910-1.stderr index 6402e568188..74deac900d4 100644 --- a/tests/ui/binop/issue-77910-1.stderr +++ b/tests/ui/binop/issue-77910-1.stderr @@ -32,8 +32,8 @@ LL | xs | help: consider assigning a value | -LL | let xs = todo!(); - | +++++++++ +LL | let xs = &42; + | +++++ error: aborting due to 3 previous errors diff --git a/tests/ui/binop/issue-77910-2.stderr b/tests/ui/binop/issue-77910-2.stderr index a14560ff188..7087f2cdf41 100644 --- a/tests/ui/binop/issue-77910-2.stderr +++ b/tests/ui/binop/issue-77910-2.stderr @@ -21,8 +21,8 @@ LL | xs | help: consider assigning a value | -LL | let xs = todo!(); - | +++++++++ +LL | let xs = &42; + | +++++ error: aborting due to 2 previous errors diff --git a/tests/ui/borrowck/borrowck-block-uninit.stderr b/tests/ui/borrowck/borrowck-block-uninit.stderr index 07c09f1f443..4db98a7a0dc 100644 --- a/tests/ui/borrowck/borrowck-block-uninit.stderr +++ b/tests/ui/borrowck/borrowck-block-uninit.stderr @@ -10,8 +10,8 @@ LL | println!("{}", x); | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-break-uninit-2.stderr b/tests/ui/borrowck/borrowck-break-uninit-2.stderr index 7c0cda31c97..e23ca534e74 100644 --- a/tests/ui/borrowck/borrowck-break-uninit-2.stderr +++ b/tests/ui/borrowck/borrowck-break-uninit-2.stderr @@ -10,8 +10,8 @@ LL | println!("{}", x); = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-break-uninit.stderr b/tests/ui/borrowck/borrowck-break-uninit.stderr index 0d879c6fb7d..0367d224f80 100644 --- a/tests/ui/borrowck/borrowck-break-uninit.stderr +++ b/tests/ui/borrowck/borrowck-break-uninit.stderr @@ -10,8 +10,8 @@ LL | println!("{}", x); = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr b/tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr index a27b6956b30..bfe3c60a84a 100644 --- a/tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr +++ b/tests/ui/borrowck/borrowck-init-in-called-fn-expr.stderr @@ -8,8 +8,8 @@ LL | i | help: consider assigning a value | -LL | let i: isize = 0; - | +++ +LL | let i: isize = 42; + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-init-in-fn-expr.stderr b/tests/ui/borrowck/borrowck-init-in-fn-expr.stderr index 16f4c40f529..a248a6d85b6 100644 --- a/tests/ui/borrowck/borrowck-init-in-fn-expr.stderr +++ b/tests/ui/borrowck/borrowck-init-in-fn-expr.stderr @@ -8,8 +8,8 @@ LL | i | help: consider assigning a value | -LL | let i: isize = 0; - | +++ +LL | let i: isize = 42; + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-init-in-fru.stderr b/tests/ui/borrowck/borrowck-init-in-fru.stderr index f27993e10b4..b5c332a90bc 100644 --- a/tests/ui/borrowck/borrowck-init-in-fru.stderr +++ b/tests/ui/borrowck/borrowck-init-in-fru.stderr @@ -8,8 +8,8 @@ LL | origin = Point { x: 10, ..origin }; | help: consider assigning a value | -LL | let mut origin: Point = todo!(); - | +++++++++ +LL | let mut origin: Point = value; + | +++++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-init-op-equal.stderr b/tests/ui/borrowck/borrowck-init-op-equal.stderr index 241d24341cb..d621c4ab46e 100644 --- a/tests/ui/borrowck/borrowck-init-op-equal.stderr +++ b/tests/ui/borrowck/borrowck-init-op-equal.stderr @@ -8,8 +8,8 @@ LL | v += 1; | help: consider assigning a value | -LL | let v: isize = 0; - | +++ +LL | let v: isize = 42; + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-init-plus-equal.stderr b/tests/ui/borrowck/borrowck-init-plus-equal.stderr index 65de6e8bf5d..109321386ba 100644 --- a/tests/ui/borrowck/borrowck-init-plus-equal.stderr +++ b/tests/ui/borrowck/borrowck-init-plus-equal.stderr @@ -8,8 +8,8 @@ LL | v = v + 1; | help: consider assigning a value | -LL | let mut v: isize = 0; - | +++ +LL | let mut v: isize = 42; + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-return.stderr b/tests/ui/borrowck/borrowck-return.stderr index a1bc3008ea8..f680b9af4f0 100644 --- a/tests/ui/borrowck/borrowck-return.stderr +++ b/tests/ui/borrowck/borrowck-return.stderr @@ -8,8 +8,8 @@ LL | return x; | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-storage-dead.stderr b/tests/ui/borrowck/borrowck-storage-dead.stderr index a08e2a7b535..5f29c61c7eb 100644 --- a/tests/ui/borrowck/borrowck-storage-dead.stderr +++ b/tests/ui/borrowck/borrowck-storage-dead.stderr @@ -8,8 +8,8 @@ LL | let _ = x + 1; | help: consider assigning a value | -LL | let x: i32 = 0; - | +++ +LL | let x: i32 = 42; + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-uninit-after-item.stderr b/tests/ui/borrowck/borrowck-uninit-after-item.stderr index 06bb419aa3b..c6d52a049d2 100644 --- a/tests/ui/borrowck/borrowck-uninit-after-item.stderr +++ b/tests/ui/borrowck/borrowck-uninit-after-item.stderr @@ -9,8 +9,8 @@ LL | baz(bar); | help: consider assigning a value | -LL | let bar = 0; - | +++ +LL | let bar = 42; + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-uninit-in-assignop.stderr b/tests/ui/borrowck/borrowck-uninit-in-assignop.stderr index fdbb451bde4..aaa33f08ff5 100644 --- a/tests/ui/borrowck/borrowck-uninit-in-assignop.stderr +++ b/tests/ui/borrowck/borrowck-uninit-in-assignop.stderr @@ -8,8 +8,8 @@ LL | x += 1; | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:9:5 @@ -21,8 +21,8 @@ LL | x -= 1; | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:12:5 @@ -34,8 +34,8 @@ LL | x *= 1; | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:15:5 @@ -47,8 +47,8 @@ LL | x /= 1; | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:18:5 @@ -60,8 +60,8 @@ LL | x %= 1; | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:21:5 @@ -73,8 +73,8 @@ LL | x ^= 1; | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:24:5 @@ -86,8 +86,8 @@ LL | x &= 1; | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:27:5 @@ -99,8 +99,8 @@ LL | x |= 1; | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:30:5 @@ -112,8 +112,8 @@ LL | x <<= 1; | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-in-assignop.rs:33:5 @@ -125,8 +125,8 @@ LL | x >>= 1; | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error: aborting due to 10 previous errors diff --git a/tests/ui/borrowck/borrowck-uninit-ref-chain.stderr b/tests/ui/borrowck/borrowck-uninit-ref-chain.stderr index 73fded7545c..d6759b8e1cf 100644 --- a/tests/ui/borrowck/borrowck-uninit-ref-chain.stderr +++ b/tests/ui/borrowck/borrowck-uninit-ref-chain.stderr @@ -8,8 +8,8 @@ LL | let _y = &**x; | help: consider assigning a value | -LL | let x: &&Box<i32> = todo!(); - | +++++++++ +LL | let x: &&Box<i32> = &&Box::new(42); + | ++++++++++++++++ error[E0381]: used binding `x` isn't initialized --> $DIR/borrowck-uninit-ref-chain.rs:11:14 @@ -21,7 +21,7 @@ LL | let _y = &**x; | help: consider assigning a value | -LL | let x: &&S<i32, i32> = todo!(); +LL | let x: &&S<i32, i32> = &&value; | +++++++++ error[E0381]: used binding `x` isn't initialized @@ -34,8 +34,8 @@ LL | let _y = &**x; | help: consider assigning a value | -LL | let x: &&i32 = todo!(); - | +++++++++ +LL | let x: &&i32 = &&42; + | ++++++ error[E0381]: partially assigned binding `a` isn't fully initialized --> $DIR/borrowck-uninit-ref-chain.rs:18:5 diff --git a/tests/ui/borrowck/borrowck-uninit.stderr b/tests/ui/borrowck/borrowck-uninit.stderr index 1e004baa143..9538baeafd1 100644 --- a/tests/ui/borrowck/borrowck-uninit.stderr +++ b/tests/ui/borrowck/borrowck-uninit.stderr @@ -8,8 +8,8 @@ LL | foo(x); | help: consider assigning a value | -LL | let x: isize = 0; - | +++ +LL | let x: isize = 42; + | ++++ error[E0381]: used binding `a` isn't initialized --> $DIR/borrowck-uninit.rs:14:32 diff --git a/tests/ui/borrowck/borrowck-use-in-index-lvalue.fixed b/tests/ui/borrowck/borrowck-use-in-index-lvalue.fixed new file mode 100644 index 00000000000..947c7f5b744 --- /dev/null +++ b/tests/ui/borrowck/borrowck-use-in-index-lvalue.fixed @@ -0,0 +1,11 @@ +//@ run-rustfix +#[allow(unused_mut)] +fn test() { + let w: &mut [isize] = &mut []; + w[5] = 0; //~ ERROR [E0381] + + let mut w: &mut [isize] = &mut []; + w[5] = 0; //~ ERROR [E0381] +} + +fn main() { test(); } diff --git a/tests/ui/borrowck/borrowck-use-in-index-lvalue.rs b/tests/ui/borrowck/borrowck-use-in-index-lvalue.rs index d30b1de5cd0..a00fda60abb 100644 --- a/tests/ui/borrowck/borrowck-use-in-index-lvalue.rs +++ b/tests/ui/borrowck/borrowck-use-in-index-lvalue.rs @@ -1,3 +1,5 @@ +//@ run-rustfix +#[allow(unused_mut)] fn test() { let w: &mut [isize]; w[5] = 0; //~ ERROR [E0381] diff --git a/tests/ui/borrowck/borrowck-use-in-index-lvalue.stderr b/tests/ui/borrowck/borrowck-use-in-index-lvalue.stderr index 18e808f10d0..6ec4390ae8d 100644 --- a/tests/ui/borrowck/borrowck-use-in-index-lvalue.stderr +++ b/tests/ui/borrowck/borrowck-use-in-index-lvalue.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `w` isn't initialized - --> $DIR/borrowck-use-in-index-lvalue.rs:3:5 + --> $DIR/borrowck-use-in-index-lvalue.rs:5:5 | LL | let w: &mut [isize]; | - binding declared here but left uninitialized @@ -8,11 +8,11 @@ LL | w[5] = 0; | help: consider assigning a value | -LL | let w: &mut [isize] = todo!(); +LL | let w: &mut [isize] = &mut []; | +++++++++ error[E0381]: used binding `w` isn't initialized - --> $DIR/borrowck-use-in-index-lvalue.rs:6:5 + --> $DIR/borrowck-use-in-index-lvalue.rs:8:5 | LL | let mut w: &mut [isize]; | ----- binding declared here but left uninitialized @@ -21,7 +21,7 @@ LL | w[5] = 0; | help: consider assigning a value | -LL | let mut w: &mut [isize] = todo!(); +LL | let mut w: &mut [isize] = &mut []; | +++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.fixed b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.fixed new file mode 100644 index 00000000000..f6ea5f0b6b8 --- /dev/null +++ b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.fixed @@ -0,0 +1,12 @@ +// Variation on `borrowck-use-uninitialized-in-cast` in which we do a +// trait cast from an uninitialized source. Issue #20791. +//@ run-rustfix +#![allow(unused_variables, dead_code)] + +trait Foo { fn dummy(&self) { } } +impl Foo for i32 { } + +fn main() { + let x: &i32 = &42; + let y = x as *const dyn Foo; //~ ERROR [E0381] +} diff --git a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.rs b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.rs index 3ce72161814..a384fdbf950 100644 --- a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.rs +++ b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.rs @@ -1,5 +1,7 @@ // Variation on `borrowck-use-uninitialized-in-cast` in which we do a // trait cast from an uninitialized source. Issue #20791. +//@ run-rustfix +#![allow(unused_variables, dead_code)] trait Foo { fn dummy(&self) { } } impl Foo for i32 { } diff --git a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr index dcbaa75333e..ef04979f1cd 100644 --- a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr +++ b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `x` isn't initialized - --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:9:13 + --> $DIR/borrowck-use-uninitialized-in-cast-trait.rs:11:13 | LL | let x: &i32; | - binding declared here but left uninitialized @@ -8,8 +8,8 @@ LL | let y = x as *const dyn Foo; | help: consider assigning a value | -LL | let x: &i32 = todo!(); - | +++++++++ +LL | let x: &i32 = &42; + | +++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.fixed b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.fixed new file mode 100644 index 00000000000..9c72015d747 --- /dev/null +++ b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.fixed @@ -0,0 +1,10 @@ +// Check that we detect unused values that are cast to other things. +// The problem was specified to casting to `*`, as creating unsafe +// pointers was not being fully checked. Issue #20791. +//@ run-rustfix +#![allow(unused_variables)] + +fn main() { + let x: &i32 = &42; + let y = x as *const i32; //~ ERROR [E0381] +} diff --git a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.rs b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.rs index a355a546dc6..290deb0f257 100644 --- a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.rs +++ b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.rs @@ -1,6 +1,8 @@ // Check that we detect unused values that are cast to other things. // The problem was specified to casting to `*`, as creating unsafe // pointers was not being fully checked. Issue #20791. +//@ run-rustfix +#![allow(unused_variables)] fn main() { let x: &i32; diff --git a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr index 7ccf6a4c3fc..22a3b721179 100644 --- a/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr +++ b/tests/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `x` isn't initialized - --> $DIR/borrowck-use-uninitialized-in-cast.rs:7:13 + --> $DIR/borrowck-use-uninitialized-in-cast.rs:9:13 | LL | let x: &i32; | - binding declared here but left uninitialized @@ -8,8 +8,8 @@ LL | let y = x as *const i32; | help: consider assigning a value | -LL | let x: &i32 = todo!(); - | +++++++++ +LL | let x: &i32 = &42; + | +++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/issue-103250.stderr b/tests/ui/borrowck/issue-103250.stderr index b7ece5d971d..104bded5b0b 100644 --- a/tests/ui/borrowck/issue-103250.stderr +++ b/tests/ui/borrowck/issue-103250.stderr @@ -9,8 +9,8 @@ LL | Err(last_error) | help: consider assigning a value | -LL | let mut last_error: Box<dyn std::error::Error> = todo!(); - | +++++++++ +LL | let mut last_error: Box<dyn std::error::Error> = Box::new(value); + | +++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/issue-24267-flow-exit.stderr b/tests/ui/borrowck/issue-24267-flow-exit.stderr index 58d1c8c0f73..216f8d49b1b 100644 --- a/tests/ui/borrowck/issue-24267-flow-exit.stderr +++ b/tests/ui/borrowck/issue-24267-flow-exit.stderr @@ -10,8 +10,8 @@ LL | println!("{}", x); = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider assigning a value | -LL | let x: i32 = 0; - | +++ +LL | let x: i32 = 42; + | ++++ error[E0381]: used binding `x` isn't initialized --> $DIR/issue-24267-flow-exit.rs:18:20 @@ -25,8 +25,8 @@ LL | println!("{}", x); = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider assigning a value | -LL | let x: i32 = 0; - | +++ +LL | let x: i32 = 42; + | ++++ error: aborting due to 2 previous errors diff --git a/tests/ui/borrowck/issue-62107-match-arm-scopes.stderr b/tests/ui/borrowck/issue-62107-match-arm-scopes.stderr index e19f37538c1..8705b8450fc 100644 --- a/tests/ui/borrowck/issue-62107-match-arm-scopes.stderr +++ b/tests/ui/borrowck/issue-62107-match-arm-scopes.stderr @@ -9,8 +9,8 @@ LL | ref u if true => {} | help: consider assigning a value | -LL | let e: i32 = 0; - | +++ +LL | let e: i32 = 42; + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/suggest-assign-rvalue.stderr b/tests/ui/borrowck/suggest-assign-rvalue.stderr index 92acba640d7..4305539f1b6 100644 --- a/tests/ui/borrowck/suggest-assign-rvalue.stderr +++ b/tests/ui/borrowck/suggest-assign-rvalue.stderr @@ -8,8 +8,8 @@ LL | apple(chaenomeles); | help: consider assigning a value | -LL | let chaenomeles = 0; - | +++ +LL | let chaenomeles = 42; + | ++++ error[E0381]: used binding `my_float` isn't initialized --> $DIR/suggest-assign-rvalue.rs:23:30 @@ -22,8 +22,8 @@ LL | println!("my_float: {}", my_float); = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider assigning a value | -LL | let my_float: f32 = 0.0; - | +++++ +LL | let my_float: f32 = 3.14159; + | +++++++++ error[E0381]: used binding `demo` isn't initialized --> $DIR/suggest-assign-rvalue.rs:26:28 @@ -50,8 +50,8 @@ LL | println!("demo_no: {:?}", demo_no); = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider assigning a value | -LL | let demo_no: DemoNoDef = todo!(); - | +++++++++ +LL | let demo_no: DemoNoDef = value; + | +++++++ error[E0381]: used binding `arr` isn't initialized --> $DIR/suggest-assign-rvalue.rs:34:27 @@ -64,7 +64,7 @@ LL | println!("arr: {:?}", arr); = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider assigning a value | -LL | let arr: [i32; 5] = todo!(); +LL | let arr: [i32; 5] = [42; 5]; | +++++++++ error[E0381]: used binding `foo` isn't initialized @@ -106,8 +106,8 @@ LL | println!("my_int: {}", *my_int); = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider assigning a value | -LL | let my_int: &i32 = todo!(); - | +++++++++ +LL | let my_int: &i32 = &42; + | +++++ error[E0381]: used binding `hello` isn't initialized --> $DIR/suggest-assign-rvalue.rs:49:27 @@ -120,8 +120,8 @@ LL | println!("hello: {}", hello); = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider assigning a value | -LL | let hello: &str = todo!(); - | +++++++++ +LL | let hello: &str = ""; + | ++++ error[E0381]: used binding `never` isn't initialized --> $DIR/suggest-assign-rvalue.rs:53:27 diff --git a/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr b/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr index 8a32f0d99e7..f8ed792e3c6 100644 --- a/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr +++ b/tests/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr @@ -79,8 +79,8 @@ LL | let c1 = || match x { }; | help: consider assigning a value | -LL | let x: u8 = 0; - | +++ +LL | let x: u8 = 42; + | ++++ error: aborting due to 8 previous errors diff --git a/tests/ui/const-generics/const-generic-default-wont-borrowck.fixed b/tests/ui/const-generics/const-generic-default-wont-borrowck.fixed new file mode 100644 index 00000000000..da48c62df21 --- /dev/null +++ b/tests/ui/const-generics/const-generic-default-wont-borrowck.fixed @@ -0,0 +1,6 @@ +//@ run-rustfix +pub struct X<const N: usize = { + let s: &'static str = ""; s.len() //~ ERROR E0381 +}>; + +fn main() {} diff --git a/tests/ui/const-generics/const-generic-default-wont-borrowck.rs b/tests/ui/const-generics/const-generic-default-wont-borrowck.rs index e64adacac9f..0d7d87100b7 100644 --- a/tests/ui/const-generics/const-generic-default-wont-borrowck.rs +++ b/tests/ui/const-generics/const-generic-default-wont-borrowck.rs @@ -1,4 +1,5 @@ -struct X<const N: usize = { +//@ run-rustfix +pub struct X<const N: usize = { let s: &'static str; s.len() //~ ERROR E0381 }>; diff --git a/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr b/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr index 4cea35f1c8e..83e7f88eda7 100644 --- a/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr +++ b/tests/ui/const-generics/const-generic-default-wont-borrowck.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `s` isn't initialized - --> $DIR/const-generic-default-wont-borrowck.rs:2:26 + --> $DIR/const-generic-default-wont-borrowck.rs:3:26 | LL | let s: &'static str; s.len() | - ^ `*s` used here but it isn't initialized @@ -8,8 +8,8 @@ LL | let s: &'static str; s.len() | help: consider assigning a value | -LL | let s: &'static str = todo!(); s.len() - | +++++++++ +LL | let s: &'static str = ""; s.len() + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-78655.stderr b/tests/ui/consts/issue-78655.stderr index 5a38d023d6f..ccaed03b4c1 100644 --- a/tests/ui/consts/issue-78655.stderr +++ b/tests/ui/consts/issue-78655.stderr @@ -8,8 +8,8 @@ LL | &x | help: consider assigning a value | -LL | let x = 0; - | +++ +LL | let x = 42; + | ++++ error: could not evaluate constant pattern --> $DIR/issue-78655.rs:7:9 diff --git a/tests/ui/drop/repeat-drop-2.stderr b/tests/ui/drop/repeat-drop-2.stderr index 009a2057212..cea7baf6976 100644 --- a/tests/ui/drop/repeat-drop-2.stderr +++ b/tests/ui/drop/repeat-drop-2.stderr @@ -32,8 +32,8 @@ LL | let _ = [x; 0]; | help: consider assigning a value | -LL | let x: u8 = 0; - | +++ +LL | let x: u8 = 42; + | ++++ error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-21596.rs b/tests/ui/issues/issue-21596.rs deleted file mode 100644 index 79f6c91d9ac..00000000000 --- a/tests/ui/issues/issue-21596.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - let x = 8u8; - let z: *const u8 = &x; - println!("{}", z.to_string()); //~ ERROR E0599 -} diff --git a/tests/ui/issues/issue-21596.stderr b/tests/ui/issues/issue-21596.stderr deleted file mode 100644 index 8a7fca5f436..00000000000 --- a/tests/ui/issues/issue-21596.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0599]: `*const u8` doesn't implement `std::fmt::Display` - --> $DIR/issue-21596.rs:4:22 - | -LL | println!("{}", z.to_string()); - | ^^^^^^^^^ `*const u8` cannot be formatted with the default formatter - | - = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref - = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior - = note: the following trait bounds were not satisfied: - `*const u8: std::fmt::Display` - which is required by `*const u8: ToString` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-27042.stderr b/tests/ui/issues/issue-27042.stderr index 01532de999e..ba39399e46e 100644 --- a/tests/ui/issues/issue-27042.stderr +++ b/tests/ui/issues/issue-27042.stderr @@ -19,7 +19,7 @@ LL | loop { break }; | | | this loop is expected to be of type `i32` | -help: give it a value of the expected type +help: give the `break` a value of the expected type | LL | loop { break 42 }; | ++ diff --git a/tests/ui/loops/loop-break-value.rs b/tests/ui/loops/loop-break-value.rs index c35200520cb..d509fc16570 100644 --- a/tests/ui/loops/loop-break-value.rs +++ b/tests/ui/loops/loop-break-value.rs @@ -23,6 +23,10 @@ fn main() { }; }; + let _: Option<String> = loop { + break; //~ ERROR mismatched types + }; + 'while_loop: while true { //~ WARN denote infinite loops with break; break (); //~ ERROR `break` with value from a `while` loop diff --git a/tests/ui/loops/loop-break-value.stderr b/tests/ui/loops/loop-break-value.stderr index a691960f962..0093182422e 100644 --- a/tests/ui/loops/loop-break-value.stderr +++ b/tests/ui/loops/loop-break-value.stderr @@ -1,5 +1,5 @@ warning: label name `'a` shadows a label name that is already in scope - --> $DIR/loop-break-value.rs:136:17 + --> $DIR/loop-break-value.rs:140:17 | LL | 'a: loop { | -- first declared here @@ -8,7 +8,7 @@ LL | let _ = 'a: loop { | ^^ label `'a` already in scope warning: label name `'a` shadows a label name that is already in scope - --> $DIR/loop-break-value.rs:148:17 + --> $DIR/loop-break-value.rs:152:17 | LL | 'a: loop { | -- first declared here @@ -17,7 +17,7 @@ LL | let _ = 'a: loop { | ^^ label `'a` already in scope error[E0425]: cannot find value `LOOP` in this scope - --> $DIR/loop-break-value.rs:95:15 + --> $DIR/loop-break-value.rs:99:15 | LL | 'LOOP: for _ in 0 .. 9 { | ----- a label with a similar name exists @@ -28,7 +28,7 @@ LL | break LOOP; | help: use the similarly named label: `'LOOP` warning: denote infinite loops with `loop { ... }` - --> $DIR/loop-break-value.rs:26:5 + --> $DIR/loop-break-value.rs:30:5 | LL | 'while_loop: while true { | ^^^^^^^^^^^^^^^^^^^^^^^ help: use `loop` @@ -36,7 +36,7 @@ LL | 'while_loop: while true { = note: `#[warn(while_true)]` on by default error[E0571]: `break` with value from a `while` loop - --> $DIR/loop-break-value.rs:28:9 + --> $DIR/loop-break-value.rs:32:9 | LL | 'while_loop: while true { | ----------------------- you can't `break` with a value in a `while` loop @@ -54,7 +54,7 @@ LL | break 'while_loop; | ~~~~~~~~~~~ error[E0571]: `break` with value from a `while` loop - --> $DIR/loop-break-value.rs:30:13 + --> $DIR/loop-break-value.rs:34:13 | LL | 'while_loop: while true { | ----------------------- you can't `break` with a value in a `while` loop @@ -68,7 +68,7 @@ LL | break 'while_loop; | ~~~~~~~~~~~~~~~~~ error[E0571]: `break` with value from a `while` loop - --> $DIR/loop-break-value.rs:38:12 + --> $DIR/loop-break-value.rs:42:12 | LL | while let Some(_) = Some(()) { | ---------------------------- you can't `break` with a value in a `while` loop @@ -81,7 +81,7 @@ LL | if break { | ~~~~~ error[E0571]: `break` with value from a `while` loop - --> $DIR/loop-break-value.rs:43:9 + --> $DIR/loop-break-value.rs:47:9 | LL | while let Some(_) = Some(()) { | ---------------------------- you can't `break` with a value in a `while` loop @@ -94,7 +94,7 @@ LL | break; | ~~~~~ error[E0571]: `break` with value from a `while` loop - --> $DIR/loop-break-value.rs:49:13 + --> $DIR/loop-break-value.rs:53:13 | LL | 'while_let_loop: while let Some(_) = Some(()) { | --------------------------------------------- you can't `break` with a value in a `while` loop @@ -108,7 +108,7 @@ LL | break 'while_let_loop; | ~~~~~~~~~~~~~~~~~~~~~ error[E0571]: `break` with value from a `for` loop - --> $DIR/loop-break-value.rs:56:9 + --> $DIR/loop-break-value.rs:60:9 | LL | for _ in &[1,2,3] { | ----------------- you can't `break` with a value in a `for` loop @@ -121,7 +121,7 @@ LL | break; | ~~~~~ error[E0571]: `break` with value from a `for` loop - --> $DIR/loop-break-value.rs:57:9 + --> $DIR/loop-break-value.rs:61:9 | LL | for _ in &[1,2,3] { | ----------------- you can't `break` with a value in a `for` loop @@ -135,7 +135,7 @@ LL | break; | ~~~~~ error[E0571]: `break` with value from a `for` loop - --> $DIR/loop-break-value.rs:64:13 + --> $DIR/loop-break-value.rs:68:13 | LL | 'for_loop: for _ in &[1,2,3] { | ---------------------------- you can't `break` with a value in a `for` loop @@ -191,7 +191,24 @@ LL | break 'outer_loop "nope"; | ^^^^^^ expected `i32`, found `&str` error[E0308]: mismatched types - --> $DIR/loop-break-value.rs:73:26 + --> $DIR/loop-break-value.rs:27:9 + | +LL | let _: Option<String> = loop { + | - ---- this loop is expected to be of type `Option<String>` + | | + | expected because of this assignment +LL | break; + | ^^^^^ expected `Option<String>`, found `()` + | + = note: expected enum `Option<String>` + found unit type `()` +help: give the `break` a value of the expected type + | +LL | break None; + | ++++ + +error[E0308]: mismatched types + --> $DIR/loop-break-value.rs:77:26 | LL | break; | ----- expected because of this `break` @@ -199,7 +216,7 @@ LL | break 'c 123; | ^^^ expected `()`, found integer error[E0308]: mismatched types - --> $DIR/loop-break-value.rs:80:15 + --> $DIR/loop-break-value.rs:84:15 | LL | break (break, break); | ^-----^^-----^ @@ -212,7 +229,7 @@ LL | break (break, break); found tuple `(!, !)` error[E0308]: mismatched types - --> $DIR/loop-break-value.rs:85:15 + --> $DIR/loop-break-value.rs:89:15 | LL | break; | ----- expected because of this `break` @@ -220,20 +237,20 @@ LL | break 2; | ^ expected `()`, found integer error[E0308]: mismatched types - --> $DIR/loop-break-value.rs:90:9 + --> $DIR/loop-break-value.rs:94:9 | LL | break 2; | ------- expected because of this `break` LL | break; | ^^^^^ expected integer, found `()` | -help: give it a value of the expected type +help: give the `break` a value of the expected type | LL | break value; | +++++ error[E0308]: mismatched types - --> $DIR/loop-break-value.rs:108:9 + --> $DIR/loop-break-value.rs:112:9 | LL | break 'a 1; | ---------- expected because of this `break` @@ -241,13 +258,13 @@ LL | break 'a 1; LL | break; | ^^^^^ expected integer, found `()` | -help: give it a value of the expected type +help: give the `break` a value of the expected type | LL | break value; | +++++ error[E0308]: mismatched types - --> $DIR/loop-break-value.rs:120:9 + --> $DIR/loop-break-value.rs:124:9 | LL | break 'a 1; | ---------- expected because of this `break` @@ -255,13 +272,13 @@ LL | break 'a 1; LL | break 'a; | ^^^^^^^^ expected integer, found `()` | -help: give it a value of the expected type +help: give the `break` a value of the expected type | LL | break 'a value; | +++++ error[E0308]: mismatched types - --> $DIR/loop-break-value.rs:131:15 + --> $DIR/loop-break-value.rs:135:15 | LL | break; | ----- expected because of this `break` @@ -270,7 +287,7 @@ LL | break 2; | ^ expected `()`, found integer error[E0308]: mismatched types - --> $DIR/loop-break-value.rs:140:17 + --> $DIR/loop-break-value.rs:144:17 | LL | break 2; | ------- expected because of this `break` @@ -278,13 +295,13 @@ LL | loop { LL | break 'a; | ^^^^^^^^ expected integer, found `()` | -help: give it a value of the expected type +help: give the `break` a value of the expected type | LL | break 'a value; | +++++ error[E0308]: mismatched types - --> $DIR/loop-break-value.rs:143:15 + --> $DIR/loop-break-value.rs:147:15 | LL | break; | ----- expected because of this `break` @@ -293,7 +310,7 @@ LL | break 2; | ^ expected `()`, found integer error[E0308]: mismatched types - --> $DIR/loop-break-value.rs:152:17 + --> $DIR/loop-break-value.rs:156:17 | LL | break 'a 2; | ---------- expected because of this `break` @@ -301,13 +318,13 @@ LL | loop { LL | break 'a; | ^^^^^^^^ expected integer, found `()` | -help: give it a value of the expected type +help: give the `break` a value of the expected type | LL | break 'a value; | +++++ error[E0308]: mismatched types - --> $DIR/loop-break-value.rs:155:15 + --> $DIR/loop-break-value.rs:159:15 | LL | break; | ----- expected because of this `break` @@ -316,7 +333,7 @@ LL | break 2; | ^ expected `()`, found integer error[E0308]: mismatched types - --> $DIR/loop-break-value.rs:159:15 + --> $DIR/loop-break-value.rs:163:15 | LL | fn main() { | - expected `()` because of this return type @@ -326,7 +343,7 @@ LL | loop { // point at the return type LL | break 2; | ^ expected `()`, found integer -error: aborting due to 25 previous errors; 3 warnings emitted +error: aborting due to 26 previous errors; 3 warnings emitted Some errors have detailed explanations: E0308, E0425, E0571. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/loops/loop-labeled-break-value.stderr b/tests/ui/loops/loop-labeled-break-value.stderr index 694d6c306f6..3be62316e34 100644 --- a/tests/ui/loops/loop-labeled-break-value.stderr +++ b/tests/ui/loops/loop-labeled-break-value.stderr @@ -7,7 +7,7 @@ LL | let _: i32 = loop { break }; | | this loop is expected to be of type `i32` | expected because of this assignment | -help: give it a value of the expected type +help: give the `break` a value of the expected type | LL | let _: i32 = loop { break 42 }; | ++ @@ -21,7 +21,7 @@ LL | let _: i32 = 'inner: loop { break 'inner }; | | this loop is expected to be of type `i32` | expected because of this assignment | -help: give it a value of the expected type +help: give the `break` a value of the expected type | LL | let _: i32 = 'inner: loop { break 'inner 42 }; | ++ @@ -35,7 +35,7 @@ LL | let _: i32 = 'inner2: loop { loop { break 'inner2 } }; | | this loop is expected to be of type `i32` | expected because of this assignment | -help: give it a value of the expected type +help: give the `break` a value of the expected type | LL | let _: i32 = 'inner2: loop { loop { break 'inner2 42 } }; | ++ diff --git a/tests/ui/loops/loop-proper-liveness.stderr b/tests/ui/loops/loop-proper-liveness.stderr index bcd6eb353e5..cd4c064bcd1 100644 --- a/tests/ui/loops/loop-proper-liveness.stderr +++ b/tests/ui/loops/loop-proper-liveness.stderr @@ -10,8 +10,8 @@ LL | println!("{:?}", x); = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider assigning a value | -LL | let x: i32 = 0; - | +++ +LL | let x: i32 = 42; + | ++++ error: aborting due to 1 previous error diff --git a/tests/ui/loops/loop-properly-diverging-2.stderr b/tests/ui/loops/loop-properly-diverging-2.stderr index c9f27a6a672..ba615f9ae4f 100644 --- a/tests/ui/loops/loop-properly-diverging-2.stderr +++ b/tests/ui/loops/loop-properly-diverging-2.stderr @@ -7,7 +7,7 @@ LL | let x: i32 = loop { break }; | | this loop is expected to be of type `i32` | expected because of this assignment | -help: give it a value of the expected type +help: give the `break` a value of the expected type | LL | let x: i32 = loop { break 42 }; | ++ diff --git a/tests/ui/methods/suggest-convert-ptr-to-ref.rs b/tests/ui/methods/suggest-convert-ptr-to-ref.rs new file mode 100644 index 00000000000..ccce3c65470 --- /dev/null +++ b/tests/ui/methods/suggest-convert-ptr-to-ref.rs @@ -0,0 +1,17 @@ +fn main() { + let mut x = 8u8; + let z: *const u8 = &x; + // issue #21596 + println!("{}", z.to_string()); //~ ERROR E0599 + + let t: *mut u8 = &mut x; + println!("{}", t.to_string()); //~ ERROR E0599 + t.make_ascii_lowercase(); //~ ERROR E0599 + + // suggest `as_mut` simply because the name is similar + let _ = t.as_mut_ref(); //~ ERROR E0599 + let _ = t.as_ref_mut(); //~ ERROR E0599 + + // no ptr-to-ref suggestion + z.make_ascii_lowercase(); //~ ERROR E0599 +} diff --git a/tests/ui/methods/suggest-convert-ptr-to-ref.stderr b/tests/ui/methods/suggest-convert-ptr-to-ref.stderr new file mode 100644 index 00000000000..69b20d57be8 --- /dev/null +++ b/tests/ui/methods/suggest-convert-ptr-to-ref.stderr @@ -0,0 +1,70 @@ +error[E0599]: `*const u8` doesn't implement `std::fmt::Display` + --> $DIR/suggest-convert-ptr-to-ref.rs:5:22 + | +LL | println!("{}", z.to_string()); + | ^^^^^^^^^ `*const u8` cannot be formatted with the default formatter + | +note: the method `to_string` exists on the type `&u8` + --> $SRC_DIR/alloc/src/string.rs:LL:COL + = note: you might want to use the unsafe method `<*const T>::as_ref` to get an optional reference to the value behind the pointer + = note: read the documentation for `<*const T>::as_ref` and ensure you satisfy its safety preconditions before calling it to avoid undefined behavior: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref + = note: the following trait bounds were not satisfied: + `*const u8: std::fmt::Display` + which is required by `*const u8: ToString` + +error[E0599]: `*mut u8` doesn't implement `std::fmt::Display` + --> $DIR/suggest-convert-ptr-to-ref.rs:8:22 + | +LL | println!("{}", t.to_string()); + | ^^^^^^^^^ `*mut u8` cannot be formatted with the default formatter + | +note: the method `to_string` exists on the type `&&mut u8` + --> $SRC_DIR/alloc/src/string.rs:LL:COL + = note: you might want to use the unsafe method `<*mut T>::as_ref` to get an optional reference to the value behind the pointer + = note: read the documentation for `<*mut T>::as_ref` and ensure you satisfy its safety preconditions before calling it to avoid undefined behavior: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref-1 + = note: the following trait bounds were not satisfied: + `*mut u8: std::fmt::Display` + which is required by `*mut u8: ToString` + +error[E0599]: no method named `make_ascii_lowercase` found for raw pointer `*mut u8` in the current scope + --> $DIR/suggest-convert-ptr-to-ref.rs:9:7 + | +LL | t.make_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^ method not found in `*mut u8` + | +note: the method `make_ascii_lowercase` exists on the type `&mut u8` + --> $SRC_DIR/core/src/num/mod.rs:LL:COL + = note: you might want to use the unsafe method `<*mut T>::as_mut` to get an optional reference to the value behind the pointer + = note: read the documentation for `<*mut T>::as_mut` and ensure you satisfy its safety preconditions before calling it to avoid undefined behavior: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_mut + +error[E0599]: no method named `as_mut_ref` found for raw pointer `*mut u8` in the current scope + --> $DIR/suggest-convert-ptr-to-ref.rs:12:15 + | +LL | let _ = t.as_mut_ref(); + | ^^^^^^^^^^ + | +help: there is a method `as_mut` with a similar name + | +LL | let _ = t.as_mut(); + | ~~~~~~ + +error[E0599]: no method named `as_ref_mut` found for raw pointer `*mut u8` in the current scope + --> $DIR/suggest-convert-ptr-to-ref.rs:13:15 + | +LL | let _ = t.as_ref_mut(); + | ^^^^^^^^^^ + | +help: there is a method `as_mut` with a similar name + | +LL | let _ = t.as_mut(); + | ~~~~~~ + +error[E0599]: no method named `make_ascii_lowercase` found for raw pointer `*const u8` in the current scope + --> $DIR/suggest-convert-ptr-to-ref.rs:16:7 + | +LL | z.make_ascii_lowercase(); + | ^^^^^^^^^^^^^^^^^^^^ method not found in `*const u8` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr index 7e119fe8cda..49a5a188cde 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.stderr +++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr @@ -56,8 +56,8 @@ LL | let _used = value; | help: consider assigning a value | -LL | let value: NonCopy = todo!(); - | +++++++++ +LL | let value: NonCopy = value; + | +++++++ error[E0381]: used binding `value` isn't initialized --> $DIR/issue-72649-uninit-in-loop.rs:69:21 @@ -70,8 +70,8 @@ LL | let _used = value; | help: consider assigning a value | -LL | let mut value: NonCopy = todo!(); - | +++++++++ +LL | let mut value: NonCopy = value; + | +++++++ error: aborting due to 6 previous errors diff --git a/tests/ui/moves/move-into-dead-array-1.stderr b/tests/ui/moves/move-into-dead-array-1.stderr index 83779fb16ed..d9b719730d6 100644 --- a/tests/ui/moves/move-into-dead-array-1.stderr +++ b/tests/ui/moves/move-into-dead-array-1.stderr @@ -8,8 +8,8 @@ LL | a[i] = d(); | help: consider assigning a value | -LL | let mut a: [D; 4] = todo!(); - | +++++++++ +LL | let mut a: [D; 4] = [value; 4]; + | ++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/moves/move-of-addr-of-mut.stderr b/tests/ui/moves/move-of-addr-of-mut.stderr index 706b52d3402..46f7d39a61a 100644 --- a/tests/ui/moves/move-of-addr-of-mut.stderr +++ b/tests/ui/moves/move-of-addr-of-mut.stderr @@ -9,8 +9,8 @@ LL | std::ptr::addr_of_mut!(x); = note: this error originates in the macro `std::ptr::addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider assigning a value | -LL | let mut x: S = todo!(); - | +++++++++ +LL | let mut x: S = value; + | +++++++ error: aborting due to 1 previous error diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr index bab47064f6c..02cb9cb22a3 100644 --- a/tests/ui/never_type/issue-52443.stderr +++ b/tests/ui/never_type/issue-52443.stderr @@ -36,7 +36,7 @@ error[E0308]: mismatched types LL | [(); loop { break }]; | ^^^^^ expected `usize`, found `()` | -help: give it a value of the expected type +help: give the `break` a value of the expected type | LL | [(); loop { break 42 }]; | ++ diff --git a/tests/ui/nll/match-cfg-fake-edges.stderr b/tests/ui/nll/match-cfg-fake-edges.stderr index d692ded36fa..066e77b17fc 100644 --- a/tests/ui/nll/match-cfg-fake-edges.stderr +++ b/tests/ui/nll/match-cfg-fake-edges.stderr @@ -126,8 +126,8 @@ LL | _ if { x; false } => 2, | help: consider assigning a value | -LL | let x = 0; - | +++ +LL | let x = 42; + | ++++ error[E0381]: used binding `x` isn't initialized --> $DIR/match-cfg-fake-edges.rs:86:31 @@ -142,8 +142,8 @@ LL | _ if let Some(()) = { x; None } => 2, | help: consider assigning a value | -LL | let x = 0; - | +++ +LL | let x = 42; + | ++++ error[E0382]: use of moved value: `x` --> $DIR/match-cfg-fake-edges.rs:99:22 diff --git a/tests/ui/nll/match-on-borrowed.stderr b/tests/ui/nll/match-on-borrowed.stderr index 9273484565a..4e0b048fb4b 100644 --- a/tests/ui/nll/match-on-borrowed.stderr +++ b/tests/ui/nll/match-on-borrowed.stderr @@ -43,8 +43,8 @@ LL | match n {} | help: consider assigning a value | -LL | let n: Never = todo!(); - | +++++++++ +LL | let n: Never = value; + | +++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/type/type-error-break-tail.stderr b/tests/ui/type/type-error-break-tail.stderr index 5ef522fee2a..81f8f52428d 100644 --- a/tests/ui/type/type-error-break-tail.stderr +++ b/tests/ui/type/type-error-break-tail.stderr @@ -8,7 +8,7 @@ LL | loop { LL | if false { break; } | ^^^^^ expected `i32`, found `()` | -help: give it a value of the expected type +help: give the `break` a value of the expected type | LL | if false { break 42; } | ++ diff --git a/tests/ui/uninhabited/privately-uninhabited-mir-call.fixed b/tests/ui/uninhabited/privately-uninhabited-mir-call.fixed new file mode 100644 index 00000000000..76f4251daef --- /dev/null +++ b/tests/ui/uninhabited/privately-uninhabited-mir-call.fixed @@ -0,0 +1,31 @@ +// Verifies that MIR building for a call expression respects +// privacy when checking if a call return type is uninhabited. +//@ run-rustfix +#![allow(unreachable_code, unused_variables)] + +pub mod widget { + enum Unimplemented {} + pub struct Widget(Unimplemented); + + impl Widget { + pub fn new() -> Widget { + todo!(); + } + } + + pub fn f() { + let x: &mut u32; + Widget::new(); + // Ok. Widget type returned from new is known to be uninhabited + // and the following code is considered unreachable. + *x = 1; + } +} + +fn main() { + let y: &mut u32 = &mut 42; + widget::Widget::new(); + // Error. Widget type is not known to be uninhabited here, + // so the following code is considered reachable. + *y = 2; //~ ERROR E0381 +} diff --git a/tests/ui/uninhabited/privately-uninhabited-mir-call.rs b/tests/ui/uninhabited/privately-uninhabited-mir-call.rs index 2764bb563d3..1eec57ae046 100644 --- a/tests/ui/uninhabited/privately-uninhabited-mir-call.rs +++ b/tests/ui/uninhabited/privately-uninhabited-mir-call.rs @@ -1,5 +1,7 @@ // Verifies that MIR building for a call expression respects // privacy when checking if a call return type is uninhabited. +//@ run-rustfix +#![allow(unreachable_code, unused_variables)] pub mod widget { enum Unimplemented {} diff --git a/tests/ui/uninhabited/privately-uninhabited-mir-call.stderr b/tests/ui/uninhabited/privately-uninhabited-mir-call.stderr index 5f2f02c99fb..9d0771ad79e 100644 --- a/tests/ui/uninhabited/privately-uninhabited-mir-call.stderr +++ b/tests/ui/uninhabited/privately-uninhabited-mir-call.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `y` isn't initialized - --> $DIR/privately-uninhabited-mir-call.rs:28:5 + --> $DIR/privately-uninhabited-mir-call.rs:30:5 | LL | let y: &mut u32; | - binding declared here but left uninitialized @@ -9,7 +9,7 @@ LL | *y = 2; | help: consider assigning a value | -LL | let y: &mut u32 = todo!(); +LL | let y: &mut u32 = &mut 42; | +++++++++ error: aborting due to 1 previous error |
