diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_error_codes/src/error_codes/E0373.md | 21 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_mir/src/transform/check_unsafety.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/expr/into.rs | 108 | ||||
| -rw-r--r-- | compiler/rustc_span/src/symbol.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/check/intrinsic.rs | 1 |
7 files changed, 74 insertions, 91 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index be5b247bb9f..8946ac43bc6 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -824,7 +824,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( } ty => unreachable!("bswap {}", ty), } - }; + } let res = CValue::by_val(swap(&mut fx.bcx, arg), fx.layout_of(T)); ret.write_cvalue(fx, res); }; diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md index fd969877931..effa597aad9 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0373.md +++ b/compiler/rustc_error_codes/src/error_codes/E0373.md @@ -50,3 +50,24 @@ fn foo() -> Box<Fn(u32) -> u32> { Now that the closure has its own copy of the data, there's no need to worry about safety. + +This error may also be encountered while using `async` blocks: + +```compile_fail,E0373,edition2018 +use std::future::Future; + +async fn f() { + let v = vec![1, 2, 3i32]; + spawn(async { //~ ERROR E0373 + println!("{:?}", v) + }); +} + +fn spawn<F: Future + Send + 'static>(future: F) { + unimplemented!() +} +``` + +Similarly to closures, `async` blocks are not executed immediately and may +capture closed-over data by reference. For more information, see +https://rust-lang.github.io/async-book/03_async_await/01_chapter.html. diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index db02ee67910..a5fb8a1cbe8 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -141,6 +141,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.add_moved_or_invoked_closure_note(location, used_place, &mut err); let mut is_loop_move = false; + let mut in_pattern = false; for move_site in &move_site_vec { let move_out = self.move_data.moves[(*move_site).moi]; @@ -256,6 +257,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "ref ".to_string(), Applicability::MachineApplicable, ); + in_pattern = true; } if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() { @@ -302,7 +304,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let place = &self.move_data.move_paths[mpi].place; let ty = place.ty(self.body, self.infcx.tcx).ty; - if is_loop_move { + // If we're in pattern, we do nothing in favor of the previous suggestion (#80913). + if is_loop_move & !in_pattern { if let ty::Ref(_, _, hir::Mutability::Mut) = ty.kind() { // We have a `&mut` ref, we need to reborrow on each iteration (#62112). err.span_suggestion_verbose( @@ -1318,21 +1321,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Applicability::MachineApplicable, ); - let msg = match category { + match category { ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => { - format!("{} is returned here", kind) + let msg = format!("{} is returned here", kind); + err.span_note(constraint_span, &msg); } ConstraintCategory::CallArgument => { fr_name.highlight_region_name(&mut err); - format!("function requires argument type to outlive `{}`", fr_name) + if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) { + err.note( + "async blocks are not executed immediately and must either take a \ + reference or ownership of outside variables they use", + ); + } else { + let msg = format!("function requires argument type to outlive `{}`", fr_name); + err.span_note(constraint_span, &msg); + } } _ => bug!( "report_escaping_closure_capture called with unexpected constraint \ category: `{:?}`", category ), - }; - err.span_note(constraint_span, &msg); + } + err } diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs index e64955c4986..0732d2568ad 100644 --- a/compiler/rustc_mir/src/transform/check_unsafety.rs +++ b/compiler/rustc_mir/src/transform/check_unsafety.rs @@ -223,13 +223,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { // Check for raw pointer `Deref`. for (base, proj) in place.iter_projections() { if proj == ProjectionElem::Deref { - let source_info = self.source_info; // Backup source_info so we can restore it later. - if base.projection.is_empty() && decl.internal { - // Internal locals are used in the `move_val_init` desugaring. - // We want to check unsafety against the source info of the - // desugaring, rather than the source info of the RHS. - self.source_info = self.body.local_decls[place.local].source_info; - } let base_ty = base.ty(self.body, self.tcx).ty; if base_ty.is_unsafe_ptr() { self.require_unsafe( @@ -237,7 +230,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { UnsafetyViolationDetails::DerefOfRawPointer, ) } - self.source_info = source_info; // Restore backed-up source_info. } } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 9777a97b57e..639f2bbc6e0 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -10,9 +10,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_middle::middle::region; use rustc_middle::mir::*; -use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; -use rustc_span::symbol::sym; -use rustc_target::spec::abi::Abi; +use rustc_middle::ty::{CanonicalUserTypeAnnotation}; use std::slice; @@ -219,79 +217,41 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, ) } - ExprKind::Call { ty, fun, args, from_hir_call, fn_span } => { - let intrinsic = match *ty.kind() { - ty::FnDef(def_id, _) => { - let f = ty.fn_sig(this.hir.tcx()); - if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { - Some(this.hir.tcx().item_name(def_id)) - } else { - None - } - } - _ => None, - }; + ExprKind::Call { ty: _, fun, args, from_hir_call, fn_span } => { let fun = unpack!(block = this.as_local_operand(block, fun)); - if let Some(sym::move_val_init) = intrinsic { - // `move_val_init` has "magic" semantics - the second argument is - // always evaluated "directly" into the first one. - - let mut args = args.into_iter(); - let ptr = args.next().expect("0 arguments to `move_val_init`"); - let val = args.next().expect("1 argument to `move_val_init`"); - assert!(args.next().is_none(), ">2 arguments to `move_val_init`"); - - let ptr = this.hir.mirror(ptr); - let ptr_ty = ptr.ty; - // Create an *internal* temp for the pointer, so that unsafety - // checking won't complain about the raw pointer assignment. - let ptr_temp = this - .local_decls - .push(LocalDecl::with_source_info(ptr_ty, source_info).internal()); - let ptr_temp = Place::from(ptr_temp); - // No need for a scope, ptr_temp doesn't need drop - let block = unpack!(this.into(ptr_temp, None, block, ptr)); - // Maybe we should provide a scope here so that - // `move_val_init` wouldn't leak on panic even with an - // arbitrary `val` expression, but `schedule_drop`, - // borrowck and drop elaboration all prevent us from - // dropping `ptr_temp.deref()`. - this.into(this.hir.tcx().mk_place_deref(ptr_temp), None, block, val) - } else { - let args: Vec<_> = args - .into_iter() - .map(|arg| unpack!(block = this.as_local_call_operand(block, arg))) - .collect(); - - let success = this.cfg.start_new_block(); - - this.record_operands_moved(&args); - - debug!("into_expr: fn_span={:?}", fn_span); - - this.cfg.terminate( - block, - source_info, - TerminatorKind::Call { - func: fun, - args, - cleanup: None, - // FIXME(varkor): replace this with an uninhabitedness-based check. - // This requires getting access to the current module to call - // `tcx.is_ty_uninhabited_from`, which is currently tricky to do. - destination: if expr.ty.is_never() { - None - } else { - Some((destination, success)) - }, - from_hir_call, - fn_span, + let args: Vec<_> = args + .into_iter() + .map(|arg| unpack!(block = this.as_local_call_operand(block, arg))) + .collect(); + + let success = this.cfg.start_new_block(); + + this.record_operands_moved(&args); + + debug!("into_expr: fn_span={:?}", fn_span); + + this.cfg.terminate( + block, + source_info, + TerminatorKind::Call { + func: fun, + args, + cleanup: None, + // FIXME(varkor): replace this with an uninhabitedness-based check. + // This requires getting access to the current module to call + // `tcx.is_ty_uninhabited_from`, which is currently tricky to do. + destination: if expr.ty.is_never() { + None + } else { + Some((destination, success)) }, - ); - this.diverge_from(block); - schedule_drop(this); - success.unit() - } + from_hir_call, + fn_span, + }, + ); + this.diverge_from(block); + schedule_drop(this); + success.unit() } ExprKind::Use { source } => this.into(destination, scope, block, source), ExprKind::Borrow { arg, borrow_kind } => { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b6cf584d875..63f95a39084 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -716,7 +716,6 @@ symbols! { more_struct_aliases, movbe_target_feature, move_ref_pattern, - move_val_init, mul, mul_assign, mul_with_overflow, diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index e4e6cf73c7e..e99db7a247c 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -157,7 +157,6 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { } sym::forget => (1, vec![param(0)], tcx.mk_unit()), sym::transmute => (2, vec![param(0)], param(1)), - sym::move_val_init => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()), sym::prefetch_read_data | sym::prefetch_write_data | sym::prefetch_read_instruction |
