diff --git a/RELEASES.md b/RELEASES.md index f418ab23d10a..4e974bbe9747 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -3861,6 +3861,8 @@ Version 1.41.1 (2020-02-27) * [Always check types of static items][69145] * [Always check lifetime bounds of `Copy` impls][69145] * [Fix miscompilation in callers of `Layout::repeat`][69225] +* [Rust 1.41.0 was announced as the last Rust release with tier 1 or tier 2 support for 32-bit Apple targets][apple-32bit-drop]. + That announcement did not expect a patch release. 1.41.1 also includes release binaries for these targets. [69225]: https://github.com/rust-lang/rust/issues/69225 [69145]: https://github.com/rust-lang/rust/pull/69145 @@ -3953,7 +3955,7 @@ Misc Compatibility Notes ------------------- -- [As previously announced 1.41.0 will be the last tier 1 release for 32-bit +- [As previously announced 1.41 will be the last tier 1 release for 32-bit Apple targets.][apple-32bit-drop] This means that the source code is still available to build, but the targets are no longer being tested and release binaries for those platforms will no longer be distributed by the Rust project. diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index 6217676d5c15..1006a047cce0 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -118,15 +118,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location LocalMutationIsAllowed::Yes, ); } - TerminatorKind::DropAndReplace { - place: drop_place, - value: new_value, - target: _, - unwind: _, - } => { - self.mutate_place(location, *drop_place, Deep); - self.consume_operand(location, new_value); - } TerminatorKind::Call { func, args, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 0fc3240c5600..92acd7555095 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -743,15 +743,6 @@ fn visit_terminator_before_primary_effect( flow_state, ); } - TerminatorKind::DropAndReplace { - place: drop_place, - value: new_value, - target: _, - unwind: _, - } => { - self.mutate_place(loc, (*drop_place, span), Deep, flow_state); - self.consume_operand(loc, (new_value, span), flow_state); - } TerminatorKind::Call { func, args, @@ -866,7 +857,6 @@ fn visit_terminator_after_primary_effect( | TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ } | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } | TerminatorKind::Goto { .. } diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index a687d3f53524..9731b10aa99d 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -435,8 +435,7 @@ fn compute_drop_live_points_for_block(&mut self, mpi: MovePathIndex, term_point: // // What we *actually* generate is a store to a temporary // for the call (`TMP = call()...`) and then a - // `DropAndReplace` to swap that with `X` - // (`DropAndReplace` has very particular semantics). + // `Drop(X)` followed by `X = TMP` to swap that with `X`. } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 06c7b8b8f873..d85e058bb208 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1312,24 +1312,6 @@ fn check_terminator( // no checks needed for these } - TerminatorKind::DropAndReplace { place, value, target: _, unwind: _ } => { - let place_ty = place.ty(body, tcx).ty; - let rv_ty = value.ty(body, tcx); - - let locations = term_location.to_locations(); - if let Err(terr) = - self.sub_types(rv_ty, place_ty, locations, ConstraintCategory::Assignment) - { - span_mirbug!( - self, - term, - "bad DropAndReplace ({:?} = {:?}): {:?}", - place_ty, - rv_ty, - terr - ); - } - } TerminatorKind::SwitchInt { discr, .. } => { self.check_operand(discr, term_location); @@ -1629,7 +1611,6 @@ fn check_iscleanup(&mut self, body: &Body<'tcx>, block_data: &BasicBlockData<'tc } TerminatorKind::Unreachable => {} TerminatorKind::Drop { target, unwind, .. } - | TerminatorKind::DropAndReplace { target, unwind, .. } | TerminatorKind::Assert { target, cleanup: unwind, .. } => { self.assert_iscleanup(body, block_data, target, is_cleanup); if let Some(unwind) = unwind { diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index 18dbe24d3b8b..c5991e0bc254 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -71,9 +71,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location TerminatorKind::Call { destination, .. } => { self.remove_never_initialized_mut_locals(*destination); } - TerminatorKind::DropAndReplace { place, .. } => { - self.remove_never_initialized_mut_locals(*place); - } _ => {} } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 7f857528c7c5..cb0e272cedab 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -499,7 +499,6 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { TerminatorKind::Yield { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::GeneratorDrop => { bug!("shouldn't exist at codegen {:?}", bb_data.terminator()); } diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 49c4f1aaaefc..1930db72ead4 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -543,8 +543,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } | TerminatorKind::Assert { .. } => {} - TerminatorKind::DropAndReplace { .. } - | TerminatorKind::Yield { .. } + TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } => unreachable!(), diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 95aad10fdb0f..0ce395e912db 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -295,7 +295,6 @@ fn discover_masters<'tcx>( TerminatorKind::Call { cleanup: unwind, .. } | TerminatorKind::InlineAsm { cleanup: unwind, .. } | TerminatorKind::Assert { cleanup: unwind, .. } - | TerminatorKind::DropAndReplace { unwind, .. } | TerminatorKind::Drop { unwind, .. } => { if let Some(unwind) = unwind { debug!( diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 57a19a4ab1ea..71c71d59b7ab 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1305,10 +1305,6 @@ fn codegen_terminator( mergeable_succ(), ), - mir::TerminatorKind::DropAndReplace { .. } => { - bug!("undesugared DropAndReplace in codegen: {:?}", terminator); - } - mir::TerminatorKind::Call { ref func, ref args, diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 2aea7c79b6d3..685a5599cded 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -171,11 +171,7 @@ pub(super) fn eval_terminator( Unreachable => throw_ub!(Unreachable), // These should never occur for MIR we actually run. - DropAndReplace { .. } - | FalseEdge { .. } - | FalseUnwind { .. } - | Yield { .. } - | GeneratorDrop => span_bug!( + FalseEdge { .. } | FalseUnwind { .. } | Yield { .. } | GeneratorDrop => span_bug!( terminator.source_info.span, "{:#?} should have been eliminated by MIR pass", terminator.kind diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index cc3aa84bd717..656baa784d77 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -985,8 +985,7 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location // Forbid all `Drop` terminators unless the place being dropped is a local with no // projections that cannot be `NeedsNonConstDrop`. - TerminatorKind::Drop { place: dropped_place, .. } - | TerminatorKind::DropAndReplace { place: dropped_place, .. } => { + TerminatorKind::Drop { place: dropped_place, .. } => { // If we are checking live drops after drop-elaboration, don't emit duplicate // errors here. if super::post_drop_elaboration::checking_enabled(self.ccx) { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs index cf4e875c91f0..43806035a44a 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs @@ -80,8 +80,7 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc trace!("visit_terminator: terminator={:?} location={:?}", terminator, location); match &terminator.kind { - mir::TerminatorKind::Drop { place: dropped_place, .. } - | mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => { + mir::TerminatorKind::Drop { place: dropped_place, .. } => { let dropped_ty = dropped_place.ty(self.body, self.tcx).ty; if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) { // Instead of throwing a bug, we just return here. This is because we have to diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index 805e6096b35c..78c74e1892dc 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -222,23 +222,8 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc // The effect of assignment to the return place in `TerminatorKind::Call` is not applied // here; that occurs in `apply_call_return_effect`. - if let mir::TerminatorKind::DropAndReplace { value, place, .. } = &terminator.kind { - let qualif = qualifs::in_operand::( - self.ccx, - &mut |l| self.state.qualif.contains(l), - value, - ); - - if !place.is_indirect() { - self.assign_qualif_direct(place, qualif); - } - } - // We ignore borrow on drop because custom drop impls are not allowed in consts. // FIXME: Reconsider if accounting for borrows in drops is necessary for const drop. - - // We need to assign qualifs to the dropped location before visiting the operand that - // replaces it since qualifs can be cleared on move. self.super_terminator(terminator, location); } } diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 272fe3d1b310..8ecd8f639ddd 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -846,18 +846,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location self.check_edge(location, *unwind, EdgeKind::Unwind); } } - TerminatorKind::DropAndReplace { target, unwind, .. } => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { - self.fail( - location, - "`DropAndReplace` should have been removed during drop elaboration", - ); - } - self.check_edge(location, *target, EdgeKind::Normal); - if let Some(unwind) = unwind { - self.check_edge(location, *unwind, EdgeKind::Unwind); - } - } TerminatorKind::Call { func, args, destination, target, cleanup, .. } => { let func_ty = func.ty(&self.body.local_decls, self.tcx); match func_ty.kind() { diff --git a/compiler/rustc_hir_analysis/locales/en-US.ftl b/compiler/rustc_hir_analysis/locales/en-US.ftl index 3c62529442c3..df4288164448 100644 --- a/compiler/rustc_hir_analysis/locales/en-US.ftl +++ b/compiler/rustc_hir_analysis/locales/en-US.ftl @@ -163,3 +163,10 @@ hir_analysis_pass_to_variadic_function = can't pass `{$ty}` to variadic function .help = cast the value to `{$cast_ty}` hir_analysis_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}` + +hir_analysis_invalid_union_field = + field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union + .note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` + +hir_analysis_invalid_union_field_sugg = + wrap the field type in `ManuallyDrop<...>` diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 3449d3d439df..be0ae4ce2ef6 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,5 +1,5 @@ use crate::check::intrinsicck::InlineAsmCtxt; -use crate::errors::LinkageType; +use crate::errors::{self, LinkageType}; use super::compare_impl_item::check_type_bounds; use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; @@ -114,9 +114,11 @@ fn allowed_union_field<'tcx>( allowed_union_field(*elem, tcx, param_env) } _ => { - // Fallback case: allow `ManuallyDrop` and things that are `Copy`. + // Fallback case: allow `ManuallyDrop` and things that are `Copy`, + // also no need to report an error if the type is unresolved. ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) || ty.is_copy_modulo_regions(tcx, param_env) + || ty.references_error() } } } @@ -131,26 +133,14 @@ fn allowed_union_field<'tcx>( Some(Node::Field(field)) => (field.span, field.ty.span), _ => unreachable!("mir field has to correspond to hir field"), }; - struct_span_err!( - tcx.sess, + tcx.sess.emit_err(errors::InvalidUnionField { field_span, - E0740, - "unions cannot contain fields that may need dropping" - ) - .note( - "a type is guaranteed not to need dropping \ - when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type", - ) - .multipart_suggestion_verbose( - "when the type does not implement `Copy`, \ - wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped", - vec![ - (ty_span.shrink_to_lo(), "std::mem::ManuallyDrop<".into()), - (ty_span.shrink_to_hi(), ">".into()), - ], - Applicability::MaybeIncorrect, - ) - .emit(); + sugg: errors::InvalidUnionFieldSuggestion { + lo: ty_span.shrink_to_lo(), + hi: ty_span.shrink_to_hi(), + }, + note: (), + }); return false; } else if field_ty.needs_drop(tcx, param_env) { // This should never happen. But we can get here e.g. in case of name resolution errors. diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 74fec93d91e1..dd40706f1d34 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -5,7 +5,7 @@ error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, MultiSpan, }; -use rustc_macros::Diagnostic; +use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -430,3 +430,23 @@ pub(crate) struct CastThinPointerToFatPointer<'tcx> { pub expr_ty: Ty<'tcx>, pub cast_ty: String, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_invalid_union_field, code = "E0740")] +pub(crate) struct InvalidUnionField { + #[primary_span] + pub field_span: Span, + #[subdiagnostic] + pub sugg: InvalidUnionFieldSuggestion, + #[note] + pub note: (), +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(hir_analysis_invalid_union_field_sugg, applicability = "machine-applicable")] +pub(crate) struct InvalidUnionFieldSuggestion { + #[suggestion_part(code = "std::mem::ManuallyDrop<")] + pub lo: Span, + #[suggestion_part(code = ">")] + pub hi: Span, +} diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index a8f8121153fa..ac7d984c1618 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -301,16 +301,12 @@ pub(in super::super) fn instantiate_bounds( span: Span, def_id: DefId, substs: SubstsRef<'tcx>, - ) -> (ty::InstantiatedPredicates<'tcx>, Vec) { + ) -> ty::InstantiatedPredicates<'tcx> { let bounds = self.tcx.predicates_of(def_id); - let spans: Vec = bounds.predicates.iter().map(|(_, span)| *span).collect(); let result = bounds.instantiate(self.tcx, substs); let result = self.normalize(span, result); - debug!( - "instantiate_bounds(bounds={:?}, substs={:?}) = {:?}, {:?}", - bounds, substs, result, spans, - ); - (result, spans) + debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}", bounds, substs, result); + result } pub(in super::super) fn normalize(&self, span: Span, value: T) -> T @@ -1389,7 +1385,7 @@ fn add_required_obligations_with_code( } _ => false, }; - let (bounds, _) = self.instantiate_bounds(span, def_id, &substs); + let bounds = self.instantiate_bounds(span, def_id, &substs); for mut obligation in traits::predicates_for_generics( |idx, predicate_span| { diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 001b24c31dee..a43330e2d4ea 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -374,9 +374,18 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { } } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, mut t: Ty<'tcx>) -> Ty<'tcx> { match *t.kind() { - ty::Infer(ty::TyVar(vid)) => { + ty::Infer(ty::TyVar(mut vid)) => { + // We need to canonicalize the *root* of our ty var. + // This is so that our canonical response correctly reflects + // any equated inference vars correctly! + let root_vid = self.infcx.root_var(vid); + if root_vid != vid { + t = self.infcx.tcx.mk_ty_var(root_vid); + vid = root_vid; + } + debug!("canonical: type var found with vid {:?}", vid); match self.infcx.probe_ty_var(vid) { // `t` could be a float / int variable; canonicalize that instead. @@ -467,9 +476,18 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { } } - fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + fn fold_const(&mut self, mut ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { - ty::ConstKind::Infer(InferConst::Var(vid)) => { + ty::ConstKind::Infer(InferConst::Var(mut vid)) => { + // We need to canonicalize the *root* of our const var. + // This is so that our canonical response correctly reflects + // any equated inference vars correctly! + let root_vid = self.infcx.root_const_var(vid); + if root_vid != vid { + ct = self.infcx.tcx.mk_const(ty::InferConst::Var(root_vid), ct.ty()); + vid = root_vid; + } + debug!("canonical: const var found with vid {:?}", vid); match self.infcx.probe_const_var(vid) { Ok(c) => { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index fb067e7ac213..4a2a55573131 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1359,6 +1359,10 @@ pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid { self.inner.borrow_mut().type_variables().root_var(var) } + pub fn root_const_var(&self, var: ty::ConstVid<'tcx>) -> ty::ConstVid<'tcx> { + self.inner.borrow_mut().const_unification_table().find(var) + } + /// Where possible, replaces type/const variables in /// `value` with their final value. Note that region variables /// are unaffected. If a type/const variable has not been unified, it diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 28a3b51b7fc9..e52610faf5af 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -265,7 +265,6 @@ pub fn terminator_kind_name(term: &Terminator<'_>) -> &'static str { Return => "Return", Unreachable => "Unreachable", Drop { .. } => "Drop", - DropAndReplace { .. } => "DropAndReplace", Call { .. } => "Call", Assert { .. } => "Assert", Yield { .. } => "Yield", diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index ae09562a85e9..58c060db6600 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -133,7 +133,6 @@ pub enum AnalysisPhase { pub enum RuntimePhase { /// In addition to the semantic changes, beginning with this phase, the following variants are /// disallowed: - /// * [`TerminatorKind::DropAndReplace`] /// * [`TerminatorKind::Yield`] /// * [`TerminatorKind::GeneratorDrop`] /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array` @@ -596,43 +595,6 @@ pub enum TerminatorKind<'tcx> { /// > consider indirect assignments. Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option }, - /// Drops the place and assigns a new value to it. - /// - /// This first performs the exact same operation as the pre drop-elaboration `Drop` terminator; - /// it then additionally assigns the `value` to the `place` as if by an assignment statement. - /// This assignment occurs both in the unwind and the regular code paths. The semantics are best - /// explained by the elaboration: - /// - /// ```ignore (MIR) - /// BB0 { - /// DropAndReplace(P <- V, goto BB1, unwind BB2) - /// } - /// ``` - /// - /// becomes - /// - /// ```ignore (MIR) - /// BB0 { - /// Drop(P, goto BB1, unwind BB2) - /// } - /// BB1 { - /// // P is now uninitialized - /// P <- V - /// } - /// BB2 { - /// // P is now uninitialized -- its dtor panicked - /// P <- V - /// } - /// ``` - /// - /// Disallowed after drop elaboration. - DropAndReplace { - place: Place<'tcx>, - value: Operand<'tcx>, - target: BasicBlock, - unwind: Option, - }, - /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of /// the referred to function. The operand types must match the argument types of the function. /// The return place type must match the return type. The type of the `func` operand must be diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 6e905224c133..cd970270727f 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -148,7 +148,6 @@ pub fn successors(&self) -> Successors<'_> { | Call { target: None, cleanup: Some(t), .. } | Call { target: Some(t), cleanup: None, .. } | Yield { resume: t, drop: None, .. } - | DropAndReplace { target: t, unwind: None, .. } | Drop { target: t, unwind: None, .. } | Assert { target: t, cleanup: None, .. } | FalseUnwind { real_target: t, unwind: None } @@ -158,7 +157,6 @@ pub fn successors(&self) -> Successors<'_> { } Call { target: Some(t), cleanup: Some(ref u), .. } | Yield { resume: t, drop: Some(ref u), .. } - | DropAndReplace { target: t, unwind: Some(ref u), .. } | Drop { target: t, unwind: Some(ref u), .. } | Assert { target: t, cleanup: Some(ref u), .. } | FalseUnwind { real_target: t, unwind: Some(ref u) } @@ -188,7 +186,6 @@ pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { | Call { target: None, cleanup: Some(ref mut t), .. } | Call { target: Some(ref mut t), cleanup: None, .. } | Yield { resume: ref mut t, drop: None, .. } - | DropAndReplace { target: ref mut t, unwind: None, .. } | Drop { target: ref mut t, unwind: None, .. } | Assert { target: ref mut t, cleanup: None, .. } | FalseUnwind { real_target: ref mut t, unwind: None } @@ -198,7 +195,6 @@ pub fn successors_mut(&mut self) -> SuccessorsMut<'_> { } Call { target: Some(ref mut t), cleanup: Some(ref mut u), .. } | Yield { resume: ref mut t, drop: Some(ref mut u), .. } - | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } | Drop { target: ref mut t, unwind: Some(ref mut u), .. } | Assert { target: ref mut t, cleanup: Some(ref mut u), .. } | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } @@ -225,7 +221,6 @@ pub fn unwind(&self) -> Option<&Option> { | TerminatorKind::FalseEdge { .. } => None, TerminatorKind::Call { cleanup: ref unwind, .. } | TerminatorKind::Assert { cleanup: ref unwind, .. } - | TerminatorKind::DropAndReplace { ref unwind, .. } | TerminatorKind::Drop { ref unwind, .. } | TerminatorKind::FalseUnwind { ref unwind, .. } | TerminatorKind::InlineAsm { cleanup: ref unwind, .. } => Some(unwind), @@ -245,7 +240,6 @@ pub fn unwind_mut(&mut self) -> Option<&mut Option> { | TerminatorKind::FalseEdge { .. } => None, TerminatorKind::Call { cleanup: ref mut unwind, .. } | TerminatorKind::Assert { cleanup: ref mut unwind, .. } - | TerminatorKind::DropAndReplace { ref mut unwind, .. } | TerminatorKind::Drop { ref mut unwind, .. } | TerminatorKind::FalseUnwind { ref mut unwind, .. } | TerminatorKind::InlineAsm { cleanup: ref mut unwind, .. } => Some(unwind), @@ -309,9 +303,6 @@ pub fn fmt_head(&self, fmt: &mut W) -> fmt::Result { Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value), Unreachable => write!(fmt, "unreachable"), Drop { place, .. } => write!(fmt, "drop({:?})", place), - DropAndReplace { place, value, .. } => { - write!(fmt, "replace({:?} <- {:?})", place, value) - } Call { func, args, destination, .. } => { write!(fmt, "{:?} = ", destination)?; write!(fmt, "{:?}(", func)?; @@ -403,10 +394,10 @@ pub fn fmt_successor_labels(&self) -> Vec> { Call { target: None, cleanup: None, .. } => vec![], Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()], Yield { drop: None, .. } => vec!["resume".into()], - DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => { + Drop { unwind: None, .. } => { vec!["return".into()] } - DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => { + Drop { unwind: Some(_), .. } => { vec!["return".into(), "unwind".into()] } Assert { cleanup: None, .. } => vec!["".into()], diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 5c056b29975c..14b18618aa8d 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -495,20 +495,6 @@ fn super_terminator(&mut self, ); } - TerminatorKind::DropAndReplace { - place, - value, - target: _, - unwind: _, - } => { - self.visit_place( - place, - PlaceContext::MutatingUse(MutatingUseContext::Drop), - location - ); - self.visit_operand(value, location); - } - TerminatorKind::Call { func, args, diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 09d2eb96d0f1..5e77f2dc1268 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -59,14 +59,6 @@ pub fn parse_terminator(&self, expr_id: ExprId) -> PResult> unwind: None, }) }, - @call("mir_drop_and_replace", args) => { - Ok(TerminatorKind::DropAndReplace { - place: self.parse_place(args[0])?, - value: self.parse_operand(args[1])?, - target: self.parse_block(args[2])?, - unwind: None, - }) - }, @call("mir_call", args) => { let destination = self.parse_place(args[0])?; let target = self.parse_block(args[1])?; diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 770701b3750d..4bc2c0ca791e 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -1072,7 +1072,6 @@ pub(crate) fn diverge_from(&mut self, start: BasicBlock) { TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::InlineAsm { .. } ), @@ -1432,8 +1431,7 @@ fn add_entry(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) { *unwind = Some(to); } } - TerminatorKind::DropAndReplace { unwind, .. } - | TerminatorKind::FalseUnwind { unwind, .. } + TerminatorKind::FalseUnwind { unwind, .. } | TerminatorKind::Call { cleanup: unwind, .. } | TerminatorKind::Assert { cleanup: unwind, .. } | TerminatorKind::InlineAsm { cleanup: unwind, .. } => { diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index f67f24b43c4d..f6db329fd7cf 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -128,7 +128,6 @@ fn node_examined( TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Goto { .. } diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 2ae3ae02fcc4..a40c38aa4c33 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -480,7 +480,6 @@ fn join_state_into_successors_of<'tcx, A>( Assert { target, cleanup: unwind, expected: _, msg: _, cond: _ } | Drop { target, unwind, place: _ } - | DropAndReplace { target, unwind, value: _, place: _ } | FalseUnwind { real_target: target, unwind } => { if let Some(unwind) = unwind { propagate(unwind, exit_state); diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 6f4e7fd4682c..08fadfe68a17 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -111,8 +111,7 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc self.super_terminator(terminator, location); match terminator.kind { - mir::TerminatorKind::Drop { place: dropped_place, .. } - | mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => { + mir::TerminatorKind::Drop { place: dropped_place, .. } => { // Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut // self` as a parameter. In the general case, a drop impl could launder that // reference into the surrounding environment through a raw pointer, thus creating diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index fcf0ce9d8211..60fd5169054d 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -202,7 +202,6 @@ fn before_terminator_effect( TerminatorKind::Abort | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::GeneratorDrop @@ -240,7 +239,6 @@ fn terminator_effect( | TerminatorKind::Abort | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::GeneratorDrop diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 4a163028fcf4..fa62960eee0f 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -392,11 +392,6 @@ fn gather_terminator(&mut self, term: &Terminator<'tcx>) { self.create_move_path(place); self.gather_init(place.as_ref(), InitKind::Deep); } - TerminatorKind::DropAndReplace { place, ref value, .. } => { - self.create_move_path(place); - self.gather_operand(value); - self.gather_init(place.as_ref(), InitKind::Deep); - } TerminatorKind::Call { ref func, ref args, diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 34c60b5ff3c2..b1474a770c59 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -230,7 +230,7 @@ fn super_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State { state.flood_with(place.as_ref(), self.map(), Self::Value::bottom()); } - TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } => { + TerminatorKind::Yield { .. } => { // They would have an effect, but are not allowed in this phase. bug!("encountered disallowed terminator"); } diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 9b4b720702b6..893018e0d8e7 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -74,7 +74,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { }; layout::fn_can_unwind(tcx, fn_def_id, sig.abi()) } - TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => { + TerminatorKind::Drop { .. } => { tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Unwind && layout::fn_can_unwind(tcx, None, Abi::Rust) } diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 9b2260f68251..896fcd9cdd60 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -64,9 +64,6 @@ fn add_moves_for_packed_drops_patch<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { add_move_for_packed_drop(tcx, body, &mut patch, terminator, loc, data.is_cleanup); } - TerminatorKind::DropAndReplace { .. } => { - span_bug!(terminator.source_info.span, "replace in AddMovesForPackedDrops"); - } _ => {} } } diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 7d2146214c6d..916f2904dda8 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -100,7 +100,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { } // `Drop` is also a call, but it doesn't return anything so we are good. - TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => None, + TerminatorKind::Drop { .. } => None, // Not a block ending in a Call -> ignore. _ => None, } diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 71605113dd57..c61947c566d7 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -55,7 +55,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location | TerminatorKind::Drop { .. } | TerminatorKind::Yield { .. } | TerminatorKind::Assert { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::Resume | TerminatorKind::Abort diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 6b2eefce24d5..9bc4b26db92e 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -1007,7 +1007,6 @@ fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Loca | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 6c1980ff3ad9..77402b8737e2 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -686,7 +686,6 @@ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs index 22ea8710e6a9..0e7dc171a5d0 100644 --- a/compiler/rustc_mir_transform/src/coverage/debug.rs +++ b/compiler/rustc_mir_transform/src/coverage/debug.rs @@ -822,7 +822,6 @@ pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str { TerminatorKind::Return => "Return", TerminatorKind::Unreachable => "Unreachable", TerminatorKind::Drop { .. } => "Drop", - TerminatorKind::DropAndReplace { .. } => "DropAndReplace", TerminatorKind::Call { .. } => "Call", TerminatorKind::Assert { .. } => "Assert", TerminatorKind::Yield { .. } => "Yield", diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index a2671eef2e94..c03cacd8615e 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -156,7 +156,6 @@ fn compute_basic_coverage_blocks( | TerminatorKind::Resume | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Call { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::Assert { .. } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 8ee316773aea..d9f68f5d93ac 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -850,7 +850,6 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option) -> String { TerminatorKind::Assert { target, .. } | TerminatorKind::Call { target: Some(target), .. } | TerminatorKind::Drop { target, .. } - | TerminatorKind::DropAndReplace { target, .. } | TerminatorKind::FalseEdge { real_target: target, .. } | TerminatorKind::FalseUnwind { real_target: target, .. } | TerminatorKind::Goto { target } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 2e481b972781..3823b6201c34 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -650,8 +650,7 @@ fn for_terminator<'tcx>(&mut self, terminator: &TerminatorKind<'tcx>) { TerminatorKind::Drop { .. } => { // `Drop`s create a `&mut` and so are not considered } - TerminatorKind::DropAndReplace { .. } - | TerminatorKind::Yield { .. } + TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } => { diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 29424f09695f..3faccca823a5 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -18,15 +18,14 @@ use rustc_target::abi::VariantIdx; use std::fmt; -/// During MIR building, Drop and DropAndReplace terminators are inserted in every place where a drop may occur. +/// During MIR building, Drop terminators are inserted in every place where a drop may occur. /// However, in this phase, the presence of these terminators does not guarantee that a destructor will run, /// as the target of the drop may be uninitialized. /// In general, the compiler cannot determine at compile time whether a destructor will run or not. /// -/// At a high level, this pass refines Drop and DropAndReplace to only run the destructor if the +/// At a high level, this pass refines Drop to only run the destructor if the /// target is initialized. The way this is achievied is by inserting drop flags for every variable /// that may be dropped, and then using those flags to determine whether a destructor should run. -/// This pass also removes DropAndReplace, replacing it with a Drop paired with an assign statement. /// Once this is complete, Drop terminators in the MIR correspond to a call to the "drop glue" or /// "drop shim" for the type of the dropped place. /// @@ -121,8 +120,7 @@ fn remove_dead_unwinds<'tcx>( .into_results_cursor(body); for (bb, bb_data) in body.basic_blocks.iter_enumerated() { let place = match bb_data.terminator().kind { - TerminatorKind::Drop { ref place, unwind: Some(_), .. } - | TerminatorKind::DropAndReplace { ref place, unwind: Some(_), .. } => { + TerminatorKind::Drop { ref place, unwind: Some(_), .. } => { und.derefer(place.as_ref(), body).unwrap_or(*place) } _ => continue, @@ -343,8 +341,7 @@ fn collect_drop_flags(&mut self) { } let terminator = data.terminator(); let place = match terminator.kind { - TerminatorKind::Drop { ref place, .. } - | TerminatorKind::DropAndReplace { ref place, .. } => { + TerminatorKind::Drop { ref place, .. } => { self.un_derefer.derefer(place.as_ref(), self.body).unwrap_or(*place) } _ => continue, @@ -441,103 +438,11 @@ fn elaborate_drops(&mut self) { } } } - TerminatorKind::DropAndReplace { mut place, ref value, target, unwind } => { - assert!(!data.is_cleanup); - - if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) { - place = new_place; - } - self.elaborate_replace(loc, place, value, target, unwind); - } _ => continue, } } } - /// Elaborate a MIR `replace` terminator. This instruction - /// is not directly handled by codegen, and therefore - /// must be desugared. - /// - /// The desugaring drops the location if needed, and then writes - /// the value (including setting the drop flag) over it in *both* arms. - /// - /// The `replace` terminator can also be called on places that - /// are not tracked by elaboration (for example, - /// `replace x[i] <- tmp0`). The borrow checker requires that - /// these locations are initialized before the assignment, - /// so we just generate an unconditional drop. - fn elaborate_replace( - &mut self, - loc: Location, - place: Place<'tcx>, - value: &Operand<'tcx>, - target: BasicBlock, - unwind: Option, - ) { - let bb = loc.block; - let data = &self.body[bb]; - let terminator = data.terminator(); - assert!(!data.is_cleanup, "DropAndReplace in unwind path not supported"); - - let assign = Statement { - kind: StatementKind::Assign(Box::new((place, Rvalue::Use(value.clone())))), - source_info: terminator.source_info, - }; - - let unwind = unwind.unwrap_or_else(|| self.patch.resume_block()); - let unwind = self.patch.new_block(BasicBlockData { - statements: vec![assign.clone()], - terminator: Some(Terminator { - kind: TerminatorKind::Goto { target: unwind }, - ..*terminator - }), - is_cleanup: true, - }); - - let target = self.patch.new_block(BasicBlockData { - statements: vec![assign], - terminator: Some(Terminator { kind: TerminatorKind::Goto { target }, ..*terminator }), - is_cleanup: false, - }); - - match self.move_data().rev_lookup.find(place.as_ref()) { - LookupResult::Exact(path) => { - debug!("elaborate_drop_and_replace({:?}) - tracked {:?}", terminator, path); - self.init_data.seek_before(loc); - elaborate_drop( - &mut Elaborator { ctxt: self }, - terminator.source_info, - place, - path, - target, - Unwind::To(unwind), - bb, - ); - on_all_children_bits(self.tcx, self.body, self.move_data(), path, |child| { - self.set_drop_flag( - Location { block: target, statement_index: 0 }, - child, - DropFlagState::Present, - ); - self.set_drop_flag( - Location { block: unwind, statement_index: 0 }, - child, - DropFlagState::Present, - ); - }); - } - LookupResult::Parent(parent) => { - // drop and replace behind a pointer/array/whatever. The location - // must be initialized. - debug!("elaborate_drop_and_replace({:?}) - untracked {:?}", terminator, parent); - self.patch.patch_terminator( - bb, - TerminatorKind::Drop { place, target, unwind: Some(unwind) }, - ); - } - } - } - fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { span, @@ -609,22 +514,12 @@ fn drop_flags_for_locs(&mut self) { debug!("drop_flags_for_locs({:?})", data); for i in 0..(data.statements.len() + 1) { debug!("drop_flag_for_locs: stmt {}", i); - let mut allow_initializations = true; if i == data.statements.len() { match data.terminator().kind { TerminatorKind::Drop { .. } => { // drop elaboration should handle that by itself continue; } - TerminatorKind::DropAndReplace { .. } => { - // this contains the move of the source and - // the initialization of the destination. We - // only want the former - the latter is handled - // by the elaboration code and must be done - // *after* the destination is dropped. - assert!(self.patch.is_patched(bb)); - allow_initializations = false; - } TerminatorKind::Resume => { // It is possible for `Resume` to be patched // (in particular it can be patched to be replaced with @@ -641,11 +536,7 @@ fn drop_flags_for_locs(&mut self) { self.body, self.env, loc, - |path, ds| { - if ds == DropFlagState::Absent || allow_initializations { - self.set_drop_flag(loc, path, ds) - } - }, + |path, ds| self.set_drop_flag(loc, path, ds), ) } diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 746326f9bde8..129f366bcd0b 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1199,7 +1199,6 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { // These may unwind. TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } | TerminatorKind::Assert { .. } => return true, @@ -1691,7 +1690,6 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Assert { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 6e6d6566f4bc..9cba8870f237 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -453,9 +453,7 @@ fn check_mir_body( checker.visit_basic_block_data(bb, blk); let term = blk.terminator(); - if let TerminatorKind::Drop { ref place, target, unwind } - | TerminatorKind::DropAndReplace { ref place, target, unwind, .. } = term.kind - { + if let TerminatorKind::Drop { ref place, target, unwind } = term.kind { work_list.push(target); // If the place doesn't actually need dropping, treat it like a regular goto. @@ -815,8 +813,7 @@ fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { let tcx = self.tcx; match terminator.kind { - TerminatorKind::Drop { ref place, unwind, .. } - | TerminatorKind::DropAndReplace { ref place, unwind, .. } => { + TerminatorKind::Drop { ref place, unwind, .. } => { // If the place doesn't actually need dropping, treat it like a regular goto. let ty = self.instance.subst_mir(tcx, &place.ty(self.callee_body, tcx).ty); if ty.needs_drop(tcx, self.param_env) { @@ -1120,8 +1117,7 @@ fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, loc: Location) *tgt = self.map_block(*tgt); } } - TerminatorKind::Drop { ref mut target, ref mut unwind, .. } - | TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => { + TerminatorKind::Drop { ref mut target, ref mut unwind, .. } => { *target = self.map_block(*target); *unwind = self.map_unwind(*unwind); } diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index e3a03aa08af4..6c067f452992 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -75,7 +75,6 @@ fn is_nop_landing_pad( | TerminatorKind::Unreachable | TerminatorKind::Call { .. } | TerminatorKind::Assert { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Drop { .. } | TerminatorKind::InlineAsm { .. } => false, } diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index 78b6f714a9b0..e72729b152e6 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -1,5 +1,5 @@ use rustc_index::bit_set::ChunkedBitSet; -use rustc_middle::mir::{Body, Field, Rvalue, Statement, StatementKind, TerminatorKind}; +use rustc_middle::mir::{Body, Field, TerminatorKind}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; @@ -8,7 +8,7 @@ use crate::MirPass; -/// Removes `Drop` and `DropAndReplace` terminators whose target is known to be uninitialized at +/// Removes `Drop` terminators whose target is known to be uninitialized at /// that point. /// /// This is redundant with drop elaboration, but we need to do it prior to const-checking, and @@ -37,8 +37,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut to_remove = vec![]; for (bb, block) in body.basic_blocks.iter_enumerated() { let terminator = block.terminator(); - let (TerminatorKind::Drop { place, .. } | TerminatorKind::DropAndReplace { place, .. }) - = &terminator.kind + let TerminatorKind::Drop { place, .. } = &terminator.kind else { continue }; maybe_inits.seek_before_primary_effect(body.terminator_loc(bb)); @@ -64,24 +63,12 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { for bb in to_remove { let block = &mut body.basic_blocks_mut()[bb]; - let (TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. }) + let TerminatorKind::Drop { target, .. } = &block.terminator().kind else { unreachable!() }; // Replace block terminator with `Goto`. - let target = *target; - let old_terminator_kind = std::mem::replace( - &mut block.terminator_mut().kind, - TerminatorKind::Goto { target }, - ); - - // If this is a `DropAndReplace`, we need to emulate the assignment to the return place. - if let TerminatorKind::DropAndReplace { place, value, .. } = old_terminator_kind { - block.statements.push(Statement { - source_info: block.terminator().source_info, - kind: StatementKind::Assign(Box::new((place, Rvalue::Use(value)))), - }); - } + block.terminator_mut().kind = TerminatorKind::Goto { target: *target }; } } } diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index a24d2d34d791..c3f5b881ab8b 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -108,7 +108,6 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { // The following terminators are not allowed TerminatorKind::Resume | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Call { .. } | TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } @@ -170,7 +169,6 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop | TerminatorKind::Assert { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Drop { .. } | TerminatorKind::Call { .. } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 45e659eab6c8..f529944acce6 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -808,8 +808,7 @@ fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Loc let callee_ty = self.monomorphize(callee_ty); visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output) } - mir::TerminatorKind::Drop { ref place, .. } - | mir::TerminatorKind::DropAndReplace { ref place, .. } => { + mir::TerminatorKind::Drop { ref place, .. } => { let ty = place.ty(self.body, self.tcx).ty; let ty = self.monomorphize(ty); visit_drop_use(self.tcx, ty, true, source, self.output); diff --git a/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs index c048d4a2aad7..981a8f45e454 100644 --- a/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs @@ -261,12 +261,23 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { self.interner().mk_re_late_bound(self.binder_index, br) } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + fn fold_ty(&mut self, mut t: Ty<'tcx>) -> Ty<'tcx> { let kind = match *t.kind() { - ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) { - Ok(t) => return self.fold_ty(t), - Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)), - }, + ty::Infer(ty::TyVar(mut vid)) => { + // We need to canonicalize the *root* of our ty var. + // This is so that our canonical response correctly reflects + // any equated inference vars correctly! + let root_vid = self.infcx.root_var(vid); + if root_vid != vid { + t = self.infcx.tcx.mk_ty_var(root_vid); + vid = root_vid; + } + + match self.infcx.probe_ty_var(vid) { + Ok(t) => return self.fold_ty(t), + Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)), + } + } ty::Infer(ty::IntVar(_)) => { let nt = self.infcx.shallow_resolve(t); if nt != t { @@ -338,13 +349,23 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { self.interner().mk_bound(self.binder_index, bt) } - fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { + fn fold_const(&mut self, mut c: ty::Const<'tcx>) -> ty::Const<'tcx> { let kind = match c.kind() { - ty::ConstKind::Infer(ty::InferConst::Var(vid)) => match self.infcx.probe_const_var(vid) - { - Ok(c) => return self.fold_const(c), - Err(universe) => CanonicalVarKind::Const(universe, c.ty()), - }, + ty::ConstKind::Infer(ty::InferConst::Var(mut vid)) => { + // We need to canonicalize the *root* of our const var. + // This is so that our canonical response correctly reflects + // any equated inference vars correctly! + let root_vid = self.infcx.root_const_var(vid); + if root_vid != vid { + c = self.infcx.tcx.mk_const(ty::InferConst::Var(root_vid), c.ty()); + vid = root_vid; + } + + match self.infcx.probe_const_var(vid) { + Ok(c) => return self.fold_const(c), + Err(universe) => CanonicalVarKind::Const(universe, c.ty()), + } + } ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => { bug!("fresh var during canonicalization: {c:?}") } diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 57b6a4527371..43fd415e871e 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -238,6 +238,7 @@ fn evaluate_goal( && has_changed && !self.in_projection_eq_hack && !self.search_graph.in_cycle() + && false { let (_orig_values, canonical_goal) = self.canonicalize_goal(goal); let canonical_response = diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 0e047977caa7..62bad5b49b46 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -155,10 +155,12 @@ fn pred_known_to_hold_modulo_regions<'tcx>( predicate: pred.to_predicate(infcx.tcx), }; - let result = infcx.predicate_must_hold_modulo_regions(&obligation); + let result = infcx.evaluate_obligation_no_overflow(&obligation); debug!(?result); - if result && has_non_region_infer { + if result.must_apply_modulo_regions() && !has_non_region_infer { + true + } else if result.may_apply() { // Because of inference "guessing", selection can sometimes claim // to succeed while the success requires a guess. To ensure // this function's result remains infallible, we must confirm @@ -179,7 +181,7 @@ fn pred_known_to_hold_modulo_regions<'tcx>( } } } else { - result + false } } diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 72db1d87ca3c..d2d9771bdce2 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -227,7 +227,7 @@ //! are no resume and abort terminators, and terminators that might unwind do not have any way to //! indicate the unwind block. //! -//! - [`Goto`], [`Return`], [`Unreachable`], [`Drop`](Drop()), and [`DropAndReplace`] have associated functions. +//! - [`Goto`], [`Return`], [`Unreachable`] and [`Drop`](Drop()) have associated functions. //! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block` //! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the //! otherwise branch. @@ -259,7 +259,6 @@ pub fn $($sig)* { panic!() } define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock); define!("mir_unreachable", fn Unreachable() -> BasicBlock); define!("mir_drop", fn Drop(place: T, goto: BasicBlock)); -define!("mir_drop_and_replace", fn DropAndReplace(place: T, value: T, goto: BasicBlock)); define!("mir_call", fn Call(place: T, goto: BasicBlock, call: T)); define!("mir_storage_live", fn StorageLive(local: T)); define!("mir_storage_dead", fn StorageDead(local: T)); diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 9b5e116aa5c9..47d742ef7964 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1721,6 +1721,15 @@ pub fn cargo( cargo.env("RUSTC_VERBOSE", self.verbosity.to_string()); + // Downstream forks of the Rust compiler might want to use a custom libc to add support for + // targets that are not yet available upstream. Adding a patch to replace libc with a + // custom one would cause compilation errors though, because Cargo would interpret the + // custom libc as part of the workspace, and apply the check-cfg lints on it. + // + // The libc build script emits check-cfg flags only when this environment variable is set, + // so this line allows the use of custom libcs. + cargo.env("LIBC_CHECK_CFG", "1"); + if source_type == SourceType::InTree { let mut lint_flags = Vec::new(); // When extending this list, add the new lints to the RUSTFLAGS of the diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 1a35fe05067f..c00800291dbd 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -299,10 +299,6 @@ fn check_terminator<'tcx>( | TerminatorKind::Unreachable => Ok(()), TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body), - TerminatorKind::DropAndReplace { place, value, .. } => { - check_place(tcx, *place, span, body)?; - check_operand(tcx, value, span, body) - }, TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body), diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js index 2f0ca1ec3d0b..80bfd38d1e96 100644 --- a/src/tools/rustdoc-gui/tester.js +++ b/src/tools/rustdoc-gui/tester.js @@ -31,7 +31,7 @@ function isNumeric(s) { } function parseOptions(args) { - var opts = { + const opts = { "doc_folder": "", "tests_folder": "", "files": [], @@ -42,7 +42,7 @@ function parseOptions(args) { "executable_path": null, "no_sandbox": false, }; - var correspondances = { + const correspondances = { "--doc-folder": "doc_folder", "--tests-folder": "tests_folder", "--debug": "debug", @@ -52,39 +52,41 @@ function parseOptions(args) { "--no-sandbox": "no_sandbox", }; - for (var i = 0; i < args.length; ++i) { - if (args[i] === "--doc-folder" - || args[i] === "--tests-folder" - || args[i] === "--file" - || args[i] === "--jobs" - || args[i] === "--executable-path") { + for (let i = 0; i < args.length; ++i) { + const arg = args[i]; + if (arg === "--doc-folder" + || arg === "--tests-folder" + || arg === "--file" + || arg === "--jobs" + || arg === "--executable-path") { i += 1; if (i >= args.length) { - console.log("Missing argument after `" + args[i - 1] + "` option."); + console.log("Missing argument after `" + arg + "` option."); return null; } - if (args[i - 1] === "--jobs") { - if (!isNumeric(args[i])) { + const arg_value = args[i]; + if (arg === "--jobs") { + if (!isNumeric(arg_value)) { console.log( - "`--jobs` option expects a positive number, found `" + args[i] + "`"); + "`--jobs` option expects a positive number, found `" + arg_value + "`"); return null; } - opts["jobs"] = parseInt(args[i]); - } else if (args[i - 1] !== "--file") { - opts[correspondances[args[i - 1]]] = args[i]; + opts["jobs"] = parseInt(arg_value); + } else if (arg !== "--file") { + opts[correspondances[arg]] = arg_value; } else { - opts["files"].push(args[i]); + opts["files"].push(arg_value); } - } else if (args[i] === "--help") { + } else if (arg === "--help") { showHelp(); process.exit(0); - } else if (args[i] === "--no-sandbox") { + } else if (arg === "--no-sandbox") { console.log("`--no-sandbox` is being used. Be very careful!"); - opts[correspondances[args[i]]] = true; - } else if (correspondances[args[i]]) { - opts[correspondances[args[i]]] = true; + opts[correspondances[arg]] = true; + } else if (correspondances[arg]) { + opts[correspondances[arg]] = true; } else { - console.log("Unknown option `" + args[i] + "`."); + console.log("Unknown option `" + arg + "`."); console.log("Use `--help` to see the list of options"); return null; } @@ -186,7 +188,7 @@ function createEmptyResults() { } async function main(argv) { - let opts = parseOptions(argv.slice(2)); + const opts = parseOptions(argv.slice(2)); if (opts === null) { process.exit(1); } diff --git a/tests/mir-opt/building/custom/terminators.drop_first.built.after.mir b/tests/mir-opt/building/custom/terminators.drop_first.built.after.mir index c903e5946961..ada78c0fc782 100644 --- a/tests/mir-opt/building/custom/terminators.drop_first.built.after.mir +++ b/tests/mir-opt/building/custom/terminators.drop_first.built.after.mir @@ -4,10 +4,11 @@ fn drop_first(_1: WriteOnDrop<'_>, _2: WriteOnDrop<'_>) -> () { let mut _0: (); // return place in scope 0 at $DIR/terminators.rs:+0:59: +0:59 bb0: { - replace(_1 <- move _2) -> bb1; // scope 0 at $DIR/terminators.rs:+3:13: +3:49 + drop(_1) -> bb1; // scope 0 at $DIR/terminators.rs:+3:13: +3:30 } bb1: { - return; // scope 0 at $DIR/terminators.rs:+7:13: +7:21 + _1 = move _2; // scope 0 at $DIR/terminators.rs:+7:13: +7:24 + return; // scope 0 at $DIR/terminators.rs:+8:13: +8:21 } } diff --git a/tests/mir-opt/building/custom/terminators.rs b/tests/mir-opt/building/custom/terminators.rs index c23233fcf9ac..f12405661685 100644 --- a/tests/mir-opt/building/custom/terminators.rs +++ b/tests/mir-opt/building/custom/terminators.rs @@ -48,10 +48,11 @@ fn drop(&mut self) { fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { mir!( { - DropAndReplace(a, Move(b), retblock) + Drop(a, retblock) } retblock = { + a = Move(b); Return() } ) diff --git a/tests/ui/traits/new-solver/canonical-ty-var-eq-in-response.rs b/tests/ui/traits/new-solver/canonical-ty-var-eq-in-response.rs new file mode 100644 index 000000000000..d1c6b1077e8e --- /dev/null +++ b/tests/ui/traits/new-solver/canonical-ty-var-eq-in-response.rs @@ -0,0 +1,39 @@ +// check-pass +// compile-flags: -Ztrait-solver=next + +trait Mirror { + type Item; +} + +struct Wrapper(T); +impl Mirror for Wrapper { + type Item = T; +} + +fn mirror() +where + Wrapper: Mirror, +{ +} + +fn main() { + mirror::<_ /* ?0 */>(); + + // Solving ` as Mirror>::Item = i32` + + // First, we replace the term with a fresh infer var: + // ` as Mirror>::Item = ?1` + + // We select the impl candidate on line #6, which leads us to learn that + // `?0 == ?1`. + + // That should be reflected in our canonical response, which should have + // `^0 = ^0, ^1 = ^0` + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // !! We used to return a totally unconstrained response here :< !! + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + // Then, during the "equate term" part of the projection solving, we + // instantiate the response from the unconstrained projection predicate, + // and equate `?0 == i32`. +} diff --git a/tests/ui/traits/new-solver/deduce-ty-from-object.rs b/tests/ui/traits/new-solver/deduce-ty-from-object.rs new file mode 100644 index 000000000000..7398bce7b61c --- /dev/null +++ b/tests/ui/traits/new-solver/deduce-ty-from-object.rs @@ -0,0 +1,6 @@ +// check-pass +// compile-flags: -Ztrait-solver=next + +fn main() { + let x: Box> = Box::new(std::iter::empty()); +} diff --git a/tests/ui/union/field_checks.rs b/tests/ui/union/field_checks.rs index d5d1e44ac855..bb4eccb4cf89 100644 --- a/tests/ui/union/field_checks.rs +++ b/tests/ui/union/field_checks.rs @@ -21,15 +21,15 @@ union U24 { // OK } union U3 { - a: String, //~ ERROR unions cannot contain fields that may need dropping + a: String, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } union U32 { // field that does not drop but is not `Copy`, either - a: std::cell::RefCell, //~ ERROR unions cannot contain fields that may need dropping + a: std::cell::RefCell, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } union U4 { - a: T, //~ ERROR unions cannot contain fields that may need dropping + a: T, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } union U5 { // Having a drop impl is OK @@ -41,11 +41,11 @@ fn drop(&mut self) {} } union U5Nested { // a nested union that drops is NOT OK - nest: U5, //~ ERROR unions cannot contain fields that may need dropping + nest: U5, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } union U5Nested2 { // for now we don't special-case empty arrays - nest: [U5; 0], //~ ERROR unions cannot contain fields that may need dropping + nest: [U5; 0], //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } union U6 { // OK diff --git a/tests/ui/union/field_checks.stderr b/tests/ui/union/field_checks.stderr index 1f97e97ac6ed..32407a749709 100644 --- a/tests/ui/union/field_checks.stderr +++ b/tests/ui/union/field_checks.stderr @@ -1,59 +1,59 @@ -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/field_checks.rs:24:5 | LL | a: String, | ^^^^^^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/field_checks.rs:28:5 | LL | a: std::cell::RefCell, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop>, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/field_checks.rs:32:5 | LL | a: T, | ^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/field_checks.rs:44:5 | LL | nest: U5, | ^^^^^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | nest: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/field_checks.rs:48:5 | LL | nest: [U5; 0], | ^^^^^^^^^^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | nest: std::mem::ManuallyDrop<[U5; 0]>, | +++++++++++++++++++++++ + diff --git a/tests/ui/union/issue-41073.rs b/tests/ui/union/issue-41073.rs index 4dfdc606bb40..f7a82b4e7cf5 100644 --- a/tests/ui/union/issue-41073.rs +++ b/tests/ui/union/issue-41073.rs @@ -1,5 +1,5 @@ union Test { - a: A, //~ ERROR unions cannot contain fields that may need dropping + a: A, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union b: B } diff --git a/tests/ui/union/issue-41073.stderr b/tests/ui/union/issue-41073.stderr index b3887fa0f90b..ae1c4dfed9a2 100644 --- a/tests/ui/union/issue-41073.stderr +++ b/tests/ui/union/issue-41073.stderr @@ -1,11 +1,11 @@ -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/issue-41073.rs:2:5 | LL | a: A, | ^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + diff --git a/tests/ui/union/union-with-drop-fields.mirunsafeck.stderr b/tests/ui/union/union-with-drop-fields.mirunsafeck.stderr index 93fe996d2a47..9861a21cb3d8 100644 --- a/tests/ui/union/union-with-drop-fields.mirunsafeck.stderr +++ b/tests/ui/union/union-with-drop-fields.mirunsafeck.stderr @@ -1,35 +1,35 @@ -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/union-with-drop-fields.rs:11:5 | LL | a: String, | ^^^^^^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/union-with-drop-fields.rs:19:5 | LL | a: S, | ^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/union-with-drop-fields.rs:24:5 | LL | a: T, | ^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + diff --git a/tests/ui/union/union-with-drop-fields.rs b/tests/ui/union/union-with-drop-fields.rs index a7a8b69e784a..9720830fb1ff 100644 --- a/tests/ui/union/union-with-drop-fields.rs +++ b/tests/ui/union/union-with-drop-fields.rs @@ -8,7 +8,7 @@ union U { } union W { - a: String, //~ ERROR unions cannot contain fields that may need dropping + a: String, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union b: String, // OK, only one field is reported } @@ -16,12 +16,12 @@ union W { // `S` doesn't implement `Drop` trait, but still has non-trivial destructor union Y { - a: S, //~ ERROR unions cannot contain fields that may need dropping + a: S, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } // We don't know if `T` is trivially-destructable or not until trans union J { - a: T, //~ ERROR unions cannot contain fields that may need dropping + a: T, //~ ERROR field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union } union H { diff --git a/tests/ui/union/union-with-drop-fields.thirunsafeck.stderr b/tests/ui/union/union-with-drop-fields.thirunsafeck.stderr index 93fe996d2a47..9861a21cb3d8 100644 --- a/tests/ui/union/union-with-drop-fields.thirunsafeck.stderr +++ b/tests/ui/union/union-with-drop-fields.thirunsafeck.stderr @@ -1,35 +1,35 @@ -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/union-with-drop-fields.rs:11:5 | LL | a: String, | ^^^^^^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/union-with-drop-fields.rs:19:5 | LL | a: S, | ^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + -error[E0740]: unions cannot contain fields that may need dropping +error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union --> $DIR/union-with-drop-fields.rs:24:5 | LL | a: T, | ^^^^ | - = note: a type is guaranteed not to need dropping when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type -help: when the type does not implement `Copy`, wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped + = note: union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>` +help: wrap the field type in `ManuallyDrop<...>` | LL | a: std::mem::ManuallyDrop, | +++++++++++++++++++++++ + diff --git a/tests/ui/union/unresolved-field-isnt-copy.rs b/tests/ui/union/unresolved-field-isnt-copy.rs new file mode 100644 index 000000000000..7a6d79b2faa8 --- /dev/null +++ b/tests/ui/union/unresolved-field-isnt-copy.rs @@ -0,0 +1,8 @@ +// Unresolved fields are not copy, but also shouldn't report an extra E0740. + +pub union Foo { + x: *const Missing, + //~^ ERROR cannot find type `Missing` in this scope +} + +fn main() {} diff --git a/tests/ui/union/unresolved-field-isnt-copy.stderr b/tests/ui/union/unresolved-field-isnt-copy.stderr new file mode 100644 index 000000000000..22301582eefc --- /dev/null +++ b/tests/ui/union/unresolved-field-isnt-copy.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Missing` in this scope + --> $DIR/unresolved-field-isnt-copy.rs:4:15 + | +LL | x: *const Missing, + | ^^^^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`.