diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 15d73ed732f50..fd5c21cfdf627 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -14,7 +14,7 @@ use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ - self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, + self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm, }; @@ -2579,7 +2579,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut Diagnostic) { let tcx = self.infcx.tcx; if let ( - Some(Terminator { kind: TerminatorKind::Call { from_hir_call: false, .. }, .. }), + Some(Terminator { + kind: TerminatorKind::Call { call_source: CallSource::OverloadedOperator, .. }, + .. + }), Some((method_did, method_substs)), ) = ( &self.body[loan.reserve_location.block].terminator, diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 1d430a93a876d..6c01fd63b1ec7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -6,8 +6,8 @@ use rustc_hir::intravisit::Visitor; use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::{ - Body, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place, - Rvalue, Statement, StatementKind, TerminatorKind, + Body, CallSource, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, + Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind, }; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::{self, RegionVid, TyCtxt}; @@ -494,7 +494,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else if self.was_captured_by_trait_object(borrow) { LaterUseKind::TraitCapture } else if location.statement_index == block.statements.len() { - if let TerminatorKind::Call { func, from_hir_call: true, .. } = + if let TerminatorKind::Call { func, call_source: CallSource::Normal, .. } = &block.terminator().kind { // Just point to the function, to reduce the chance of overlapping spans. diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 20370e4c6ac3c..1d3cc851888cf 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -13,8 +13,9 @@ use rustc_index::IndexSlice; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ - AggregateKind, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location, Operand, Place, - PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, + AggregateKind, CallSource, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location, + Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, + TerminatorKind, }; use rustc_middle::ty::print::Print; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; @@ -414,7 +415,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if !is_terminator { continue; } else if let Some(Terminator { - kind: TerminatorKind::Call { func, from_hir_call: false, .. }, + kind: + TerminatorKind::Call { + func, + call_source: CallSource::OverloadedOperator, + .. + }, .. }) = &bbd.terminator { @@ -839,7 +845,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("move_spans: target_temp = {:?}", target_temp); if let Some(Terminator { - kind: TerminatorKind::Call { fn_span, from_hir_call, .. }, .. + kind: TerminatorKind::Call { fn_span, call_source, .. }, .. }) = &self.body[location.block].terminator { let Some((method_did, method_substs)) = @@ -859,7 +865,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { method_did, method_substs, *fn_span, - *from_hir_call, + call_source.from_hir_call(), Some(self.infcx.tcx.fn_arg_names(method_did)[0]), ); diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index b2ff25ecb96f4..e4fbe6ea4f438 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -128,7 +128,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { destination, target: _, unwind: _, - from_hir_call: _, + call_source: _, fn_span: _, } => { self.consume_operand(location, func); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 99a988f2c629e..4fcdda311bfd3 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -710,7 +710,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro destination, target: _, unwind: _, - from_hir_call: _, + call_source: _, fn_span: _, } => { self.consume_operand(loc, (func, span), flow_state); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 33f75437478b5..0eb544c40863c 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1370,7 +1370,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } // FIXME: check the values } - TerminatorKind::Call { func, args, destination, from_hir_call, target, .. } => { + TerminatorKind::Call { func, args, destination, call_source, target, .. } => { self.check_operand(func, term_location); for arg in args { self.check_operand(arg, term_location); @@ -1446,7 +1446,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .add_element(region_vid, term_location); } - self.check_call_inputs(body, term, &sig, args, term_location, *from_hir_call); + self.check_call_inputs(body, term, &sig, args, term_location, *call_source); } TerminatorKind::Assert { cond, msg, .. } => { self.check_operand(cond, term_location); @@ -1573,7 +1573,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { sig: &ty::FnSig<'tcx>, args: &[Operand<'tcx>], term_location: Location, - from_hir_call: bool, + call_source: CallSource, ) { debug!("check_call_inputs({:?}, {:?})", sig, args); if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) { @@ -1591,7 +1591,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let op_arg_ty = op_arg.ty(body, self.tcx()); let op_arg_ty = self.normalize(op_arg_ty, term_location); - let category = if from_hir_call { + let category = if call_source.from_hir_call() { ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty)) } else { ConstraintCategory::Boring diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 5abb4644e1b09..ce10780f9de12 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -421,7 +421,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { target, fn_span, unwind: _, - from_hir_call: _, + call_source: _, } => { fx.tcx.prof.generic_activity("codegen call").run(|| { crate::abi::codegen_terminator_call( diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index a4a8aad87269d..0cec560ba4518 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1280,7 +1280,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { destination, target, unwind, - from_hir_call: _, + call_source: _, fn_span, } => self.codegen_call_terminator( helper, diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index bf660c59cabda..e99005316b3fd 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -210,6 +210,9 @@ const_eval_long_running = .label = the const evaluator is currently interpreting this expression .help = the constant being evaluated +const_eval_match_eq_non_const = cannot match on `{$ty}` in {const_eval_const_context}s + .note = `{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es + const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id} const_eval_memory_access_test = memory access failed diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index eed3091d481e3..ca38cce710e60 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -271,6 +271,18 @@ pub struct RawBytesNote { pub bytes: String, } +// FIXME(fee1-dead) do not use stringly typed `ConstContext` + +#[derive(Diagnostic)] +#[diag(const_eval_match_eq_non_const, code = "E0015")] +#[note] +pub struct NonConstMatchEq<'tcx> { + #[primary_span] + pub span: Span, + pub ty: Ty<'tcx>, + pub kind: ConstContext, +} + #[derive(Diagnostic)] #[diag(const_eval_for_loop_into_iter_non_const, code = "E0015")] pub struct NonConstForLoopIntoIter<'tcx> { diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 7269ff8d53cdf..719d8a14b4134 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -62,7 +62,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { destination, target, unwind, - from_hir_call: _, + call_source: _, fn_span: _, } => { let old_stack = self.frame_idx(); 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 106cf1114749a..2aaf1340eb409 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -702,7 +702,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { self.super_terminator(terminator, location); match &terminator.kind { - TerminatorKind::Call { func, args, fn_span, from_hir_call, .. } => { + TerminatorKind::Call { func, args, fn_span, call_source, .. } => { let ConstCx { tcx, body, param_env, .. } = *self.ccx; let caller = self.def_id(); @@ -755,7 +755,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { callee, substs, span: *fn_span, - from_hir_call: *from_hir_call, + call_source: *call_source, feature: Some(sym::const_trait_impl), }); return; @@ -797,7 +797,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { callee, substs, span: *fn_span, - from_hir_call: *from_hir_call, + call_source: *call_source, feature: None, }); @@ -823,7 +823,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { callee, substs, span: *fn_span, - from_hir_call: *from_hir_call, + call_source: *call_source, feature: None, }); return; @@ -866,7 +866,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { callee, substs, span: *fn_span, - from_hir_call: *from_hir_call, + call_source: *call_source, feature: None, }); return; @@ -926,7 +926,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { callee, substs, span: *fn_span, - from_hir_call: *from_hir_call, + call_source: *call_source, feature: None, }); return; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 236e43bdfcc71..32bd9cda6f2b4 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -7,7 +7,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; -use rustc_middle::mir; +use rustc_middle::mir::{self, CallSource}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty}; @@ -100,7 +100,7 @@ pub struct FnCallNonConst<'tcx> { pub callee: DefId, pub substs: SubstsRef<'tcx>, pub span: Span, - pub from_hir_call: bool, + pub call_source: CallSource, pub feature: Option, } @@ -110,7 +110,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { ccx: &ConstCx<'_, 'tcx>, _: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let FnCallNonConst { caller, callee, substs, span, from_hir_call, feature } = *self; + let FnCallNonConst { caller, callee, substs, span, call_source, feature } = *self; let ConstCx { tcx, param_env, .. } = *ccx; let diag_trait = |err, self_ty: Ty<'_>, trait_id| { @@ -157,7 +157,8 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { } }; - let call_kind = call_kind(tcx, ccx.param_env, callee, substs, span, from_hir_call, None); + let call_kind = + call_kind(tcx, ccx.param_env, callee, substs, span, call_source.from_hir_call(), None); debug!(?call_kind); @@ -219,48 +220,59 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { err } CallKind::Operator { trait_id, self_ty, .. } => { - let mut sugg = None; - - if Some(trait_id) == ccx.tcx.lang_items().eq_trait() { - match (substs[0].unpack(), substs[1].unpack()) { - (GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty)) - if self_ty == rhs_ty - && self_ty.is_ref() - && self_ty.peel_refs().is_primitive() => - { - let mut num_refs = 0; - let mut tmp_ty = self_ty; - while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() { - num_refs += 1; - tmp_ty = *inner_ty; - } - let deref = "*".repeat(num_refs); - - if let Ok(call_str) = ccx.tcx.sess.source_map().span_to_snippet(span) { - if let Some(eq_idx) = call_str.find("==") { - if let Some(rhs_idx) = - call_str[(eq_idx + 2)..].find(|c: char| !c.is_whitespace()) - { - let rhs_pos = - span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx); - let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos); - sugg = Some(errors::ConsiderDereferencing { - deref, - span: span.shrink_to_lo(), - rhs_span, - }); + let mut err = if let CallSource::MatchCmp = call_source { + tcx.sess.create_err(errors::NonConstMatchEq { + span, + kind: ccx.const_kind(), + ty: self_ty, + }) + } else { + let mut sugg = None; + + if Some(trait_id) == ccx.tcx.lang_items().eq_trait() { + match (substs[0].unpack(), substs[1].unpack()) { + (GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty)) + if self_ty == rhs_ty + && self_ty.is_ref() + && self_ty.peel_refs().is_primitive() => + { + let mut num_refs = 0; + let mut tmp_ty = self_ty; + while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() { + num_refs += 1; + tmp_ty = *inner_ty; + } + let deref = "*".repeat(num_refs); + + if let Ok(call_str) = + ccx.tcx.sess.source_map().span_to_snippet(span) + { + if let Some(eq_idx) = call_str.find("==") { + if let Some(rhs_idx) = call_str[(eq_idx + 2)..] + .find(|c: char| !c.is_whitespace()) + { + let rhs_pos = span.lo() + + BytePos::from_usize(eq_idx + 2 + rhs_idx); + let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos); + sugg = Some(errors::ConsiderDereferencing { + deref, + span: span.shrink_to_lo(), + rhs_span, + }); + } } } } + _ => {} } - _ => {} } - } - let mut err = tcx.sess.create_err(errors::NonConstOperator { - span, - kind: ccx.const_kind(), - sugg, - }); + tcx.sess.create_err(errors::NonConstOperator { + span, + kind: ccx.const_kind(), + sugg, + }) + }; + diag_trait(&mut err, self_ty, trait_id); err } diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 44b143c77f36e..1cb6400baaa2d 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -792,7 +792,9 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { }; match terminator.kind { - TerminatorKind::Call { mut func, mut args, from_hir_call, fn_span, .. } => { + TerminatorKind::Call { + mut func, mut args, call_source: desugar, fn_span, .. + } => { self.visit_operand(&mut func, loc); for arg in &mut args { self.visit_operand(arg, loc); @@ -808,7 +810,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { unwind: UnwindAction::Continue, destination: Place::from(new_temp), target: Some(new_target), - from_hir_call, + call_source: desugar, fn_span, }, source_info: SourceInfo::outermost(terminator.source_info.span), diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index b62f689ec6b89..9ce03060e0fe9 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -370,13 +370,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Fudge the receiver, so we can do new inference on it. let possible_rcvr_ty = possible_rcvr_ty.fold_with(&mut fudger); let method = self - .lookup_method( + .lookup_method_for_diagnostic( possible_rcvr_ty, segment, DUMMY_SP, call_expr, binding, - args, ) .ok()?; // Unify the method signature with our incompatible arg, to @@ -435,14 +434,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(rcvr_ty) = self.node_ty_opt(rcvr.hir_id) else { continue; }; let rcvr_ty = rcvr_ty.fold_with(&mut fudger); let Ok(method) = - self.lookup_method(rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr, args) + self.lookup_method_for_diagnostic(rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr) else { continue; }; let ideal_rcvr_ty = rcvr_ty.fold_with(&mut fudger); let ideal_method = self - .lookup_method(ideal_rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr, args) + .lookup_method_for_diagnostic(ideal_rcvr_ty, segment, DUMMY_SP, parent_expr, rcvr) .ok() .and_then(|method| { let _ = self.at(&ObligationCause::dummy(), self.param_env) diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 98529b66602fa..6cd7bd5d196df 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -26,6 +26,7 @@ struct ConfirmContext<'a, 'tcx> { span: Span, self_expr: &'tcx hir::Expr<'tcx>, call_expr: &'tcx hir::Expr<'tcx>, + skip_record_for_diagnostics: bool, } impl<'a, 'tcx> Deref for ConfirmContext<'a, 'tcx> { @@ -59,6 +60,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr); confirm_cx.confirm(unadjusted_self_ty, pick, segment) } + + pub fn confirm_method_for_diagnostic( + &self, + span: Span, + self_expr: &'tcx hir::Expr<'tcx>, + call_expr: &'tcx hir::Expr<'tcx>, + unadjusted_self_ty: Ty<'tcx>, + pick: &probe::Pick<'tcx>, + segment: &hir::PathSegment<'_>, + ) -> ConfirmResult<'tcx> { + let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr); + confirm_cx.skip_record_for_diagnostics = true; + confirm_cx.confirm(unadjusted_self_ty, pick, segment) + } } impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { @@ -68,7 +83,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self_expr: &'tcx hir::Expr<'tcx>, call_expr: &'tcx hir::Expr<'tcx>, ) -> ConfirmContext<'a, 'tcx> { - ConfirmContext { fcx, span, self_expr, call_expr } + ConfirmContext { fcx, span, self_expr, call_expr, skip_record_for_diagnostics: false } } fn confirm( @@ -219,7 +234,9 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self.register_predicates(autoderef.into_obligations()); // Write out the final adjustments. - self.apply_adjustments(self.self_expr, adjustments); + if !self.skip_record_for_diagnostics { + self.apply_adjustments(self.self_expr, adjustments); + } target } @@ -453,7 +470,10 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { }); debug!("instantiate_method_substs: user_type_annotation={:?}", user_type_annotation); - self.fcx.write_user_type_annotation(self.call_expr.hir_id, user_type_annotation); + + if !self.skip_record_for_diagnostics { + self.fcx.write_user_type_annotation(self.call_expr.hir_id, user_type_annotation); + } } self.normalize(self.span, substs) diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index cca97d1051720..59736b42cf7a8 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -254,6 +254,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(result.callee) } + pub fn lookup_method_for_diagnostic( + &self, + self_ty: Ty<'tcx>, + segment: &hir::PathSegment<'_>, + span: Span, + call_expr: &'tcx hir::Expr<'tcx>, + self_expr: &'tcx hir::Expr<'tcx>, + ) -> Result, MethodError<'tcx>> { + let pick = self.lookup_probe_for_diagnostic( + segment.ident, + self_ty, + call_expr, + ProbeScope::TraitsInScope, + None, + )?; + + Ok(self + .confirm_method_for_diagnostic(span, self_expr, call_expr, self_ty, &pick, segment) + .callee) + } + #[instrument(level = "debug", skip(self, call_expr))] pub fn lookup_probe( &self, diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 1a65f74f4fe22..fb3841f877687 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -512,6 +512,31 @@ pub struct CopyNonOverlapping<'tcx> { pub count: Operand<'tcx>, } +/// Represents how a `TerminatorKind::Call` was constructed, used for diagnostics +#[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, PartialEq, Hash, HashStable)] +#[derive(TypeFoldable, TypeVisitable)] +pub enum CallSource { + /// This came from something such as `a > b` or `a + b`. In THIR, if `from_hir_call` + /// is false then this is the desugaring. + OverloadedOperator, + /// This was from comparison generated by a match, used by const-eval for better errors + /// when the comparison cannot be done in compile time. + /// + /// See https://github.com/rust-lang/rust/issues/90237. + MatchCmp, + /// Other types of desugaring that did not come from the HIR, but we don't care about + /// for diagnostics (yet). + Misc, + /// Normal function call, no special source + Normal, +} + +impl CallSource { + pub fn from_hir_call(self) -> bool { + matches!(self, CallSource::Normal) + } +} + /////////////////////////////////////////////////////////////////////////// // Terminators @@ -638,11 +663,10 @@ pub enum TerminatorKind<'tcx> { target: Option, /// Action to be taken if the call unwinds. unwind: UnwindAction, - /// `true` if this is from a call in HIR rather than from an overloaded - /// operator. True for overloaded function call. - from_hir_call: bool, + /// Where this call came from in HIR/THIR. + call_source: CallSource, /// This `Span` is the span of the function, without the dot and receiver - /// (e.g. `foo(a, b)` in `x.foo(a, b)` + /// e.g. `foo(a, b)` in `x.foo(a, b)` fn_span: Span, }, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 8d44e929afde3..ce55b770cbcb4 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -519,7 +519,7 @@ macro_rules! make_mir_visitor { destination, target: _, unwind: _, - from_hir_call: _, + call_source: _, fn_span: _ } => { self.visit_operand(func, location); 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 ebf830cb9c1f6..4cb9d7babe14f 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -128,7 +128,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { destination, target: Some(target), unwind: UnwindAction::Continue, - from_hir_call: *from_hir_call, + call_source: if *from_hir_call { CallSource::Normal } else { + CallSource::OverloadedOperator + }, fn_span: *fn_span, }) }, diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 3742d640e3b58..fd08b32807c40 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -173,7 +173,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination: storage, target: Some(success), unwind: UnwindAction::Continue, - from_hir_call: false, + call_source: CallSource::Misc, fn_span: expr_span, }, ); diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 29ff916d2cc9c..731f3996244ca 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -277,7 +277,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .ty .is_inhabited_from(this.tcx, this.parent_module, this.param_env) .then_some(success), - from_hir_call, + call_source: if from_hir_call { + CallSource::Normal + } else { + CallSource::OverloadedOperator + }, fn_span, }, ); diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index dbdb5b4a9a179..f431023f2b669 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -264,7 +264,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination: ref_str, target: Some(eq_block), unwind: UnwindAction::Continue, - from_hir_call: false, + call_source: CallSource::Misc, fn_span: source_info.span } ); @@ -496,7 +496,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination: eq_result, target: Some(eq_block), unwind: UnwindAction::Continue, - from_hir_call: false, + call_source: CallSource::MatchCmp, fn_span: source_info.span, }, ); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 7976b148f75e2..a2e00d3bfc57d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -359,6 +359,15 @@ impl<'tcx> ConstToPat<'tcx> { def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx(), substs)), ))?, }, + ty::Slice(elem_ty) => PatKind::Slice { + prefix: cv + .unwrap_branch() + .iter() + .map(|val| self.recur(*val, *elem_ty, false)) + .collect::>()?, + slice: None, + suffix: Box::new([]), + }, ty::Array(elem_ty, _) => PatKind::Array { prefix: cv .unwrap_branch() @@ -372,58 +381,6 @@ impl<'tcx> ConstToPat<'tcx> { // `&str` is represented as a valtree, let's keep using this // optimization for now. ty::Str => PatKind::Constant { value: mir::ConstantKind::Ty(tcx.mk_const(cv, ty)) }, - // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when - // matching against references, you can only use byte string literals. - // The typechecker has a special case for byte string literals, by treating them - // as slices. This means we turn `&[T; N]` constants into slice patterns, which - // has no negative effects on pattern matching, even if we're actually matching on - // arrays. - ty::Array(elem_ty, _) if !self.treat_byte_string_as_slice => { - let old = self.behind_reference.replace(true); - // References have the same valtree representation as their pointee. - let array = cv; - let val = PatKind::Deref { - subpattern: Box::new(Pat { - kind: PatKind::Array { - prefix: array.unwrap_branch() - .iter() - .map(|val| self.recur(*val, elem_ty, false)) - .collect::>()?, - slice: None, - suffix: Box::new([]), - }, - span, - ty: tcx.mk_slice(elem_ty), - }), - }; - self.behind_reference.set(old); - val - } - ty::Array(elem_ty, _) | - // Cannot merge this with the catch all branch below, because the `const_deref` - // changes the type from slice to array, we need to keep the original type in the - // pattern. - ty::Slice(elem_ty) => { - let old = self.behind_reference.replace(true); - // References have the same valtree representation as their pointee. - let array = cv; - let val = PatKind::Deref { - subpattern: Box::new(Pat { - kind: PatKind::Slice { - prefix: array.unwrap_branch() - .iter() - .map(|val| self.recur(*val, elem_ty, false)) - .collect::>()?, - slice: None, - suffix: Box::new([]), - }, - span, - ty: tcx.mk_slice(elem_ty), - }), - }; - self.behind_reference.set(old); - val - } // Backwards compatibility hack: support references to non-structural types, // but hard error if we aren't behind a double reference. We could just use // the fallback code path below, but that would allow *more* of this fishy @@ -431,11 +388,9 @@ impl<'tcx> ConstToPat<'tcx> { // instead of a hard error. ty::Adt(_, _) if !self.type_marked_structural(*pointee_ty) => { if self.behind_reference.get() { - if !self.saw_const_match_error.get() - && !self.saw_const_match_lint.get() - { - self.saw_const_match_lint.set(true); - tcx.emit_spanned_lint( + if !self.saw_const_match_error.get() && !self.saw_const_match_lint.get() { + self.saw_const_match_lint.set(true); + tcx.emit_spanned_lint( lint::builtin::INDIRECT_STRUCTURAL_MATCH, self.id, span, @@ -456,7 +411,7 @@ impl<'tcx> ConstToPat<'tcx> { // convert the dereferenced constant to a pattern that is the sub-pattern of the // deref pattern. _ => { - if !pointee_ty.is_sized(tcx, param_env) { + if !pointee_ty.is_sized(tcx, param_env) && !pointee_ty.is_slice() { let err = UnsizedPattern { span, non_sm_ty: *pointee_ty }; tcx.sess.emit_err(err); @@ -464,8 +419,20 @@ impl<'tcx> ConstToPat<'tcx> { PatKind::Wild } else { let old = self.behind_reference.replace(true); + // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when + // matching against references, you can only use byte string literals. + // The typechecker has a special case for byte string literals, by treating them + // as slices. This means we turn `&[T; N]` constants into slice patterns, which + // has no negative effects on pattern matching, even if we're actually matching on + // arrays. + let pointee_ty = match *pointee_ty.kind() { + ty::Array(elem_ty, _) if self.treat_byte_string_as_slice => { + tcx.mk_slice(elem_ty) + } + _ => *pointee_ty, + }; // References have the same valtree representation as their pointee. - let subpattern = self.recur(cv, *pointee_ty, false)?; + let subpattern = self.recur(cv, pointee_ty, false)?; self.behind_reference.set(old); PatKind::Deref { subpattern } } diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 4fc45eaf5220d..27232b70d960b 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -654,7 +654,7 @@ where destination: unit_temp, target: Some(succ), unwind: unwind.into_action(), - from_hir_call: true, + call_source: CallSource::Misc, fn_span: self.source_info.span, }, source_info: self.source_info, diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 0c379288a0962..804b44a6bf05d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -502,15 +502,7 @@ impl Direction for Forward { propagate(target, exit_state); } - Call { - unwind, - destination, - target, - func: _, - args: _, - from_hir_call: _, - fn_span: _, - } => { + Call { unwind, destination, target, func: _, args: _, call_source: _, fn_span: _ } => { if let UnwindAction::Cleanup(unwind) = unwind { propagate(unwind, exit_state); } diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index 45c2fe55aca9f..cb0ec144ef0b7 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -40,7 +40,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> { destination: dummy_place.clone(), target: Some(mir::START_BLOCK), unwind: mir::UnwindAction::Continue, - from_hir_call: false, + call_source: mir::CallSource::Misc, fn_span: DUMMY_SP, }, ); @@ -54,7 +54,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> { destination: dummy_place.clone(), target: Some(mir::START_BLOCK), unwind: mir::UnwindAction::Continue, - from_hir_call: false, + call_source: mir::CallSource::Misc, fn_span: DUMMY_SP, }, ); diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 096bc0acfccb9..fe9631653ea72 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -399,7 +399,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { destination, target, unwind: _, - from_hir_call: _, + call_source: _, fn_span: _, } => { self.gather_operand(func); diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index 90b58933df7c0..25891d3ca0f88 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -140,7 +140,7 @@ impl<'tcx> MockBlocks<'tcx> { destination: self.dummy_place.clone(), target: Some(TEMP_BLOCK), unwind: UnwindAction::Continue, - from_hir_call: false, + call_source: CallSource::Misc, fn_span: DUMMY_SP, }, ) diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index b1c9c4acc40e4..7f631cccddf54 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -34,7 +34,7 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> { destination: _, target: _, unwind: _, - from_hir_call: _, + call_source: _, fn_span: _, } = &terminator.kind { diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index fe3f8ed047a70..04134eb2fb169 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1692,7 +1692,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { destination, target: Some(_), unwind: _, - from_hir_call: _, + call_source: _, fn_span: _, } => { self.check_assigned_place(*destination, |this| { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 9c8c0ea0be004..fa8257cf9849c 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -30,8 +30,8 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_index::IndexVec; use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{ - traversal, AnalysisPhase, Body, ClearCrossCrate, ConstQualifs, Constant, LocalDecl, MirPass, - MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, + traversal, AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstQualifs, Constant, LocalDecl, + MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, Statement, StatementKind, TerminatorKind, START_BLOCK, }; use rustc_middle::query::Providers; @@ -189,7 +189,7 @@ fn remap_mir_for_const_eval_select<'tcx>( }; method(place) }).collect(); - terminator.kind = TerminatorKind::Call { func, args: arguments, destination, target, unwind, from_hir_call: false, fn_span }; + terminator.kind = TerminatorKind::Call { func, args: arguments, destination, target, unwind, call_source: CallSource::Misc, fn_span }; } _ => {} } diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index 6e40dfa0d1382..b7cc0db95597d 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -54,7 +54,7 @@ fn lower_slice_len_call<'tcx>( args, destination, target: Some(bb), - from_hir_call: true, + call_source: CallSource::Normal, .. } => { // some heuristics for fast rejection diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 5f12f1937c06c..9d6ef9db4ea1b 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -500,7 +500,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { destination: dest, target: Some(next), unwind: UnwindAction::Cleanup(cleanup), - from_hir_call: true, + call_source: CallSource::Normal, fn_span: self.span, }, false, @@ -789,7 +789,7 @@ fn build_call_shim<'tcx>( } else { UnwindAction::Continue }, - from_hir_call: true, + call_source: CallSource::Misc, fn_span: span, }, false, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 47d8e5993fd82..23ef9bf53a195 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -304,21 +304,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let res = binding.res(); self.check_reserved_macro_name(key.ident, res); self.set_binding_parent_module(binding, module); - self.update_resolution(module, key, |this, resolution| { - if let Some(old_binding) = resolution.binding { - if res == Res::Err && old_binding.res() != Res::Err { - // Do not override real bindings with `Res::Err`s from error recovery. - return Ok(()); - } + + let mut resolution = self.resolution(module, key).borrow_mut(); + let old_binding = resolution.binding(); + let mut t = Ok(()); + if let Some(old_binding) = resolution.binding { + if res == Res::Err && old_binding.res() != Res::Err { + // Do not override real bindings with `Res::Err`s from error recovery. + } else { match (old_binding.is_glob_import(), binding.is_glob_import()) { (true, true) => { if res != old_binding.res() { - resolution.binding = Some(this.ambiguity( + resolution.binding = Some(self.ambiguity( AmbiguityKind::GlobVsGlob, old_binding, binding, )); - } else if !old_binding.vis.is_at_least(binding.vis, this.tcx) { + } else if !old_binding.vis.is_at_least(binding.vis, self.tcx) { // We are glob-importing the same item but with greater visibility. resolution.binding = Some(binding); } @@ -330,7 +332,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { && key.ns == MacroNS && nonglob_binding.expansion != LocalExpnId::ROOT { - resolution.binding = Some(this.ambiguity( + resolution.binding = Some(self.ambiguity( AmbiguityKind::GlobVsExpanded, nonglob_binding, glob_binding, @@ -342,12 +344,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(old_binding) = resolution.shadowed_glob { assert!(old_binding.is_glob_import()); if glob_binding.res() != old_binding.res() { - resolution.shadowed_glob = Some(this.ambiguity( + resolution.shadowed_glob = Some(self.ambiguity( AmbiguityKind::GlobVsGlob, old_binding, glob_binding, )); - } else if !old_binding.vis.is_at_least(binding.vis, this.tcx) { + } else if !old_binding.vis.is_at_least(binding.vis, self.tcx) { resolution.shadowed_glob = Some(glob_binding); } } else { @@ -355,53 +357,27 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } (false, false) => { - return Err(old_binding); + t = Err(old_binding); } } - } else { - resolution.binding = Some(binding); } + } else { + resolution.binding = Some(binding); + }; - Ok(()) - }) - } - - fn ambiguity( - &self, - kind: AmbiguityKind, - primary_binding: &'a NameBinding<'a>, - secondary_binding: &'a NameBinding<'a>, - ) -> &'a NameBinding<'a> { - self.arenas.alloc_name_binding(NameBinding { - ambiguity: Some((secondary_binding, kind)), - ..primary_binding.clone() - }) - } - - // Use `f` to mutate the resolution of the name in the module. - // If the resolution becomes a success, define it in the module's glob importers. - fn update_resolution(&mut self, module: Module<'a>, key: BindingKey, f: F) -> T - where - F: FnOnce(&mut Resolver<'a, 'tcx>, &mut NameResolution<'a>) -> T, - { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. - let (binding, t) = { - let resolution = &mut *self.resolution(module, key).borrow_mut(); - let old_binding = resolution.binding(); - - let t = f(self, resolution); - - match resolution.binding() { - _ if old_binding.is_some() => return t, - None => return t, - Some(binding) => match old_binding { - Some(old_binding) if ptr::eq(old_binding, binding) => return t, - _ => (binding, t), - }, - } + let (binding, t) = match resolution.binding() { + _ if old_binding.is_some() => return t, + None => return t, + Some(binding) => match old_binding { + Some(old_binding) if ptr::eq(old_binding, binding) => return t, + _ => (binding, t), + }, }; + drop(resolution); + // Define `binding` in `module`s glob importers. for import in module.glob_importers.borrow_mut().iter() { let mut ident = key.ident; @@ -420,6 +396,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { t } + fn ambiguity( + &self, + kind: AmbiguityKind, + primary_binding: &'a NameBinding<'a>, + secondary_binding: &'a NameBinding<'a>, + ) -> &'a NameBinding<'a> { + self.arenas.alloc_name_binding(NameBinding { + ambiguity: Some((secondary_binding, kind)), + ..primary_binding.clone() + }) + } + // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics. fn import_dummy_binding(&mut self, import: &'a Import<'a>, is_indeterminate: bool) { @@ -769,9 +757,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .emit(); } let key = BindingKey::new(target, ns); - this.update_resolution(parent, key, |_, resolution| { - resolution.single_imports.remove(&Interned::new_unchecked(import)); - }); + let mut resolution = this.resolution(parent, key).borrow_mut(); + resolution.single_imports.remove(&Interned::new_unchecked(import)); } } } diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 6bd030b13d1ce..5327f8a3cc37f 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -346,7 +346,7 @@ impl<'tcx> Stable for mir::Terminator<'tcx> { target: target.as_usize(), unwind: unwind.stable(), }, - Call { func, args, destination, target, unwind, from_hir_call: _, fn_span: _ } => { + Call { func, args, destination, target, unwind, call_source: _, fn_span: _ } => { Terminator::Call { func: func.stable(), args: args.iter().map(|arg| arg.stable()).collect(), diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index c9baa09f4074a..95dcaf5dd7397 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -3,7 +3,6 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::ascii; -use crate::convert::TryInto; use crate::intrinsics; use crate::mem; use crate::ops::{Add, Mul, Sub}; @@ -278,18 +277,12 @@ macro_rules! widening_impl { macro_rules! conv_rhs_for_unchecked_shift { ($SelfT:ty, $x:expr) => {{ - #[inline] - fn conv(x: u32) -> $SelfT { - // FIXME(const-hack) replace with `.try_into().ok().unwrap_unchecked()`. - // SAFETY: Any legal shift amount must be losslessly representable in the self type. - unsafe { x.try_into().ok().unwrap_unchecked() } - } - #[inline] - const fn const_conv(x: u32) -> $SelfT { - x as _ + // If the `as` cast will truncate, ensure we still tell the backend + // that the pre-truncation value was also small. + if <$SelfT>::BITS < 32 { + intrinsics::assume($x <= (<$SelfT>::MAX as u32)); } - - intrinsics::const_eval_select(($x,), const_conv, conv) + $x as $SelfT }}; } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 01d0dbafd1ef6..9212362f6c9e1 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -44,7 +44,8 @@ const MIR_OPT_BLESS_TARGET_MAPPING: &[(&str, &str)] = &[ ("i686-pc-windows-msvc", "x86_64-pc-windows-msvc"), ("i686-pc-windows-gnu", "x86_64-pc-windows-gnu"), ("i686-apple-darwin", "x86_64-apple-darwin"), - ("i686-apple-darwin", "aarch64-apple-darwin"), + // ARM Macs don't have a corresponding 32-bit target that they can (easily) + // build for, so there is no entry for "aarch64-apple-darwin" here. ]; fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool { 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 860a489494c88..425a8eaee3092 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 @@ -317,7 +317,7 @@ fn check_terminator<'tcx>( TerminatorKind::Call { func, args, - from_hir_call: _, + call_source: _, destination: _, target: _, unwind: _, diff --git a/tests/codegen/unchecked_shifts.rs b/tests/codegen/unchecked_shifts.rs index 60d0cb09acaf9..0924dda08ee66 100644 --- a/tests/codegen/unchecked_shifts.rs +++ b/tests/codegen/unchecked_shifts.rs @@ -8,6 +8,7 @@ // CHECK-LABEL: @unchecked_shl_unsigned_same #[no_mangle] pub unsafe fn unchecked_shl_unsigned_same(a: u32, b: u32) -> u32 { + // CHECK-NOT: assume // CHECK-NOT: and i32 // CHECK: shl i32 %a, %b // CHECK-NOT: and i32 @@ -30,6 +31,7 @@ pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 { // CHECK-LABEL: @unchecked_shl_unsigned_bigger #[no_mangle] pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 { + // CHECK-NOT: assume // CHECK: %[[EXT:.+]] = zext i32 %b to i64 // CHECK: shl i64 %a, %[[EXT]] a.unchecked_shl(b) @@ -38,6 +40,7 @@ pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 { // CHECK-LABEL: @unchecked_shr_signed_same #[no_mangle] pub unsafe fn unchecked_shr_signed_same(a: i32, b: u32) -> i32 { + // CHECK-NOT: assume // CHECK-NOT: and i32 // CHECK: ashr i32 %a, %b // CHECK-NOT: and i32 @@ -60,6 +63,7 @@ pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 { // CHECK-LABEL: @unchecked_shr_signed_bigger #[no_mangle] pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 { + // CHECK-NOT: assume // CHECK: %[[EXT:.+]] = zext i32 %b to i64 // CHECK: ashr i64 %a, %[[EXT]] a.unchecked_shr(b) diff --git a/tests/mir-opt/inline/unchecked_shifts.rs b/tests/mir-opt/inline/unchecked_shifts.rs index 64ec26b587d28..22f84e44a6411 100644 --- a/tests/mir-opt/inline/unchecked_shifts.rs +++ b/tests/mir-opt/inline/unchecked_shifts.rs @@ -16,3 +16,15 @@ pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 { pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 { a.unchecked_shr(b) } + +// EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.diff +// EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_bigger.PreCodegen.after.mir +pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 { + a.unchecked_shl(b) +} + +// EMIT_MIR unchecked_shifts.unchecked_shr_signed_bigger.Inline.diff +// EMIT_MIR unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.mir +pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 { + a.unchecked_shr(b) +} diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.panic-abort.diff new file mode 100644 index 0000000000000..1ed65b310ac00 --- /dev/null +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.panic-abort.diff @@ -0,0 +1,36 @@ +- // MIR for `unchecked_shl_unsigned_bigger` before Inline ++ // MIR for `unchecked_shl_unsigned_bigger` after Inline + + fn unchecked_shl_unsigned_bigger(_1: u64, _2: u32) -> u64 { + debug a => _1; + debug b => _2; + let mut _0: u64; + let mut _3: u64; + let mut _4: u32; ++ scope 1 (inlined core::num::::unchecked_shl) { ++ debug self => _3; ++ debug rhs => _4; ++ let mut _5: u64; ++ scope 2 { ++ } ++ } + + bb0: { + StorageLive(_3); + _3 = _1; + StorageLive(_4); + _4 = _2; +- _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable]; ++ StorageLive(_5); ++ _5 = _4 as u64 (IntToInt); ++ _0 = unchecked_shl::(_3, move _5) -> [return: bb1, unwind unreachable]; + } + + bb1: { ++ StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.panic-unwind.diff new file mode 100644 index 0000000000000..7a27675638b01 --- /dev/null +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.panic-unwind.diff @@ -0,0 +1,36 @@ +- // MIR for `unchecked_shl_unsigned_bigger` before Inline ++ // MIR for `unchecked_shl_unsigned_bigger` after Inline + + fn unchecked_shl_unsigned_bigger(_1: u64, _2: u32) -> u64 { + debug a => _1; + debug b => _2; + let mut _0: u64; + let mut _3: u64; + let mut _4: u32; ++ scope 1 (inlined core::num::::unchecked_shl) { ++ debug self => _3; ++ debug rhs => _4; ++ let mut _5: u64; ++ scope 2 { ++ } ++ } + + bb0: { + StorageLive(_3); + _3 = _1; + StorageLive(_4); + _4 = _2; +- _0 = core::num::::unchecked_shl(move _3, move _4) -> bb1; ++ StorageLive(_5); ++ _5 = _4 as u64 (IntToInt); ++ _0 = unchecked_shl::(_3, move _5) -> [return: bb1, unwind unreachable]; + } + + bb1: { ++ StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.PreCodegen.after.panic-abort.mir new file mode 100644 index 0000000000000..eee56b9560d06 --- /dev/null +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.PreCodegen.after.panic-abort.mir @@ -0,0 +1,25 @@ +// MIR for `unchecked_shl_unsigned_bigger` after PreCodegen + +fn unchecked_shl_unsigned_bigger(_1: u64, _2: u32) -> u64 { + debug a => _1; + debug b => _2; + let mut _0: u64; + scope 1 (inlined core::num::::unchecked_shl) { + debug self => _1; + debug rhs => _2; + let mut _3: u64; + scope 2 { + } + } + + bb0: { + StorageLive(_3); + _3 = _2 as u64 (IntToInt); + _0 = unchecked_shl::(_1, move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.PreCodegen.after.panic-unwind.mir new file mode 100644 index 0000000000000..eee56b9560d06 --- /dev/null +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_bigger.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,25 @@ +// MIR for `unchecked_shl_unsigned_bigger` after PreCodegen + +fn unchecked_shl_unsigned_bigger(_1: u64, _2: u32) -> u64 { + debug a => _1; + debug b => _2; + let mut _0: u64; + scope 1 (inlined core::num::::unchecked_shl) { + debug self => _1; + debug rhs => _2; + let mut _3: u64; + scope 2 { + } + } + + bb0: { + StorageLive(_3); + _3 = _2 as u64 (IntToInt); + _0 = unchecked_shl::(_1, move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff index 093925b8e4fa1..6c809f0b533e7 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff @@ -7,16 +7,36 @@ let mut _0: u16; let mut _3: u16; let mut _4: u32; ++ scope 1 (inlined core::num::::unchecked_shl) { ++ debug self => _3; ++ debug rhs => _4; ++ let mut _5: u16; ++ let mut _6: bool; ++ let mut _7: u32; ++ scope 2 { ++ } ++ } bb0: { StorageLive(_3); _3 = _1; StorageLive(_4); _4 = _2; - _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable]; +- _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable]; ++ StorageLive(_5); ++ StorageLive(_6); ++ StorageLive(_7); ++ _7 = const 65535_u32; ++ _6 = Le(_4, move _7); ++ StorageDead(_7); ++ assume(move _6); ++ StorageDead(_6); ++ _5 = _4 as u16 (IntToInt); ++ _0 = unchecked_shl::(_3, move _5) -> [return: bb1, unwind unreachable]; } bb1: { ++ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff index 50934e0439a3b..0753c1b05df44 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff @@ -7,16 +7,36 @@ let mut _0: u16; let mut _3: u16; let mut _4: u32; ++ scope 1 (inlined core::num::::unchecked_shl) { ++ debug self => _3; ++ debug rhs => _4; ++ let mut _5: u16; ++ let mut _6: bool; ++ let mut _7: u32; ++ scope 2 { ++ } ++ } bb0: { StorageLive(_3); _3 = _1; StorageLive(_4); _4 = _2; - _0 = core::num::::unchecked_shl(move _3, move _4) -> bb1; +- _0 = core::num::::unchecked_shl(move _3, move _4) -> bb1; ++ StorageLive(_5); ++ StorageLive(_6); ++ StorageLive(_7); ++ _7 = const 65535_u32; ++ _6 = Le(_4, move _7); ++ StorageDead(_7); ++ assume(move _6); ++ StorageDead(_6); ++ _5 = _4 as u16 (IntToInt); ++ _0 = unchecked_shl::(_3, move _5) -> [return: bb1, unwind unreachable]; } bb1: { ++ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir index 46f3511b14ca9..7bf10b365a6cf 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir @@ -4,12 +4,31 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 { debug a => _1; debug b => _2; let mut _0: u16; + scope 1 (inlined core::num::::unchecked_shl) { + debug self => _1; + debug rhs => _2; + let mut _3: u32; + let mut _4: bool; + let mut _5: u16; + scope 2 { + } + } bb0: { - _0 = core::num::::unchecked_shl(_1, _2) -> [return: bb1, unwind unreachable]; + StorageLive(_5); + StorageLive(_4); + StorageLive(_3); + _3 = const 65535_u32; + _4 = Le(_2, move _3); + StorageDead(_3); + assume(move _4); + StorageDead(_4); + _5 = _2 as u16 (IntToInt); + _0 = unchecked_shl::(_1, move _5) -> [return: bb1, unwind unreachable]; } bb1: { + StorageDead(_5); return; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir index 35fee449c35c8..7bf10b365a6cf 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir @@ -4,12 +4,31 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 { debug a => _1; debug b => _2; let mut _0: u16; + scope 1 (inlined core::num::::unchecked_shl) { + debug self => _1; + debug rhs => _2; + let mut _3: u32; + let mut _4: bool; + let mut _5: u16; + scope 2 { + } + } bb0: { - _0 = core::num::::unchecked_shl(_1, _2) -> bb1; + StorageLive(_5); + StorageLive(_4); + StorageLive(_3); + _3 = const 65535_u32; + _4 = Le(_2, move _3); + StorageDead(_3); + assume(move _4); + StorageDead(_4); + _5 = _2 as u16 (IntToInt); + _0 = unchecked_shl::(_1, move _5) -> [return: bb1, unwind unreachable]; } bb1: { + StorageDead(_5); return; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff new file mode 100644 index 0000000000000..04ddb4e80ff56 --- /dev/null +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-abort.diff @@ -0,0 +1,36 @@ +- // MIR for `unchecked_shr_signed_bigger` before Inline ++ // MIR for `unchecked_shr_signed_bigger` after Inline + + fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 { + debug a => _1; + debug b => _2; + let mut _0: i64; + let mut _3: i64; + let mut _4: u32; ++ scope 1 (inlined core::num::::unchecked_shr) { ++ debug self => _3; ++ debug rhs => _4; ++ let mut _5: i64; ++ scope 2 { ++ } ++ } + + bb0: { + StorageLive(_3); + _3 = _1; + StorageLive(_4); + _4 = _2; +- _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable]; ++ StorageLive(_5); ++ _5 = _4 as i64 (IntToInt); ++ _0 = unchecked_shr::(_3, move _5) -> [return: bb1, unwind unreachable]; + } + + bb1: { ++ StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff new file mode 100644 index 0000000000000..762aa1564b507 --- /dev/null +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.Inline.panic-unwind.diff @@ -0,0 +1,36 @@ +- // MIR for `unchecked_shr_signed_bigger` before Inline ++ // MIR for `unchecked_shr_signed_bigger` after Inline + + fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 { + debug a => _1; + debug b => _2; + let mut _0: i64; + let mut _3: i64; + let mut _4: u32; ++ scope 1 (inlined core::num::::unchecked_shr) { ++ debug self => _3; ++ debug rhs => _4; ++ let mut _5: i64; ++ scope 2 { ++ } ++ } + + bb0: { + StorageLive(_3); + _3 = _1; + StorageLive(_4); + _4 = _2; +- _0 = core::num::::unchecked_shr(move _3, move _4) -> bb1; ++ StorageLive(_5); ++ _5 = _4 as i64 (IntToInt); ++ _0 = unchecked_shr::(_3, move _5) -> [return: bb1, unwind unreachable]; + } + + bb1: { ++ StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir new file mode 100644 index 0000000000000..858760d065c94 --- /dev/null +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-abort.mir @@ -0,0 +1,25 @@ +// MIR for `unchecked_shr_signed_bigger` after PreCodegen + +fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 { + debug a => _1; + debug b => _2; + let mut _0: i64; + scope 1 (inlined core::num::::unchecked_shr) { + debug self => _1; + debug rhs => _2; + let mut _3: i64; + scope 2 { + } + } + + bb0: { + StorageLive(_3); + _3 = _2 as i64 (IntToInt); + _0 = unchecked_shr::(_1, move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir new file mode 100644 index 0000000000000..858760d065c94 --- /dev/null +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.panic-unwind.mir @@ -0,0 +1,25 @@ +// MIR for `unchecked_shr_signed_bigger` after PreCodegen + +fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 { + debug a => _1; + debug b => _2; + let mut _0: i64; + scope 1 (inlined core::num::::unchecked_shr) { + debug self => _1; + debug rhs => _2; + let mut _3: i64; + scope 2 { + } + } + + bb0: { + StorageLive(_3); + _3 = _2 as i64 (IntToInt); + _0 = unchecked_shr::(_1, move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + return; + } +} diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-abort.diff index 1659a51b090d2..5739336cb4f3c 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-abort.diff @@ -7,16 +7,36 @@ let mut _0: i16; let mut _3: i16; let mut _4: u32; ++ scope 1 (inlined core::num::::unchecked_shr) { ++ debug self => _3; ++ debug rhs => _4; ++ let mut _5: i16; ++ let mut _6: bool; ++ let mut _7: u32; ++ scope 2 { ++ } ++ } bb0: { StorageLive(_3); _3 = _1; StorageLive(_4); _4 = _2; - _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable]; +- _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable]; ++ StorageLive(_5); ++ StorageLive(_6); ++ StorageLive(_7); ++ _7 = const 32767_u32; ++ _6 = Le(_4, move _7); ++ StorageDead(_7); ++ assume(move _6); ++ StorageDead(_6); ++ _5 = _4 as i16 (IntToInt); ++ _0 = unchecked_shr::(_3, move _5) -> [return: bb1, unwind unreachable]; } bb1: { ++ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff index cb5ec37feb360..e04912e1d1cff 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff @@ -7,16 +7,36 @@ let mut _0: i16; let mut _3: i16; let mut _4: u32; ++ scope 1 (inlined core::num::::unchecked_shr) { ++ debug self => _3; ++ debug rhs => _4; ++ let mut _5: i16; ++ let mut _6: bool; ++ let mut _7: u32; ++ scope 2 { ++ } ++ } bb0: { StorageLive(_3); _3 = _1; StorageLive(_4); _4 = _2; - _0 = core::num::::unchecked_shr(move _3, move _4) -> bb1; +- _0 = core::num::::unchecked_shr(move _3, move _4) -> bb1; ++ StorageLive(_5); ++ StorageLive(_6); ++ StorageLive(_7); ++ _7 = const 32767_u32; ++ _6 = Le(_4, move _7); ++ StorageDead(_7); ++ assume(move _6); ++ StorageDead(_6); ++ _5 = _4 as i16 (IntToInt); ++ _0 = unchecked_shr::(_3, move _5) -> [return: bb1, unwind unreachable]; } bb1: { ++ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-abort.mir index 9f2f40002a32d..08b044f4f9e62 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-abort.mir @@ -4,12 +4,31 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 { debug a => _1; debug b => _2; let mut _0: i16; + scope 1 (inlined core::num::::unchecked_shr) { + debug self => _1; + debug rhs => _2; + let mut _3: u32; + let mut _4: bool; + let mut _5: i16; + scope 2 { + } + } bb0: { - _0 = core::num::::unchecked_shr(_1, _2) -> [return: bb1, unwind unreachable]; + StorageLive(_5); + StorageLive(_4); + StorageLive(_3); + _3 = const 32767_u32; + _4 = Le(_2, move _3); + StorageDead(_3); + assume(move _4); + StorageDead(_4); + _5 = _2 as i16 (IntToInt); + _0 = unchecked_shr::(_1, move _5) -> [return: bb1, unwind unreachable]; } bb1: { + StorageDead(_5); return; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-unwind.mir index aaf3bb62e8a33..08b044f4f9e62 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-unwind.mir @@ -4,12 +4,31 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 { debug a => _1; debug b => _2; let mut _0: i16; + scope 1 (inlined core::num::::unchecked_shr) { + debug self => _1; + debug rhs => _2; + let mut _3: u32; + let mut _4: bool; + let mut _5: i16; + scope 2 { + } + } bb0: { - _0 = core::num::::unchecked_shr(_1, _2) -> bb1; + StorageLive(_5); + StorageLive(_4); + StorageLive(_3); + _3 = const 32767_u32; + _4 = Le(_2, move _3); + StorageDead(_3); + assume(move _4); + StorageDead(_4); + _5 = _2 as i16 (IntToInt); + _0 = unchecked_shr::(_1, move _5) -> [return: bb1, unwind unreachable]; } bb1: { + StorageDead(_5); return; } } diff --git a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir index 10b93a15799bd..1a7d5433e3597 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir @@ -7,17 +7,17 @@ fn checked_shl(_1: u32, _2: u32) -> Option { scope 1 (inlined core::num::::checked_shl) { debug self => _1; debug rhs => _2; - let mut _11: u32; - let mut _12: bool; + let mut _7: u32; + let mut _8: bool; scope 2 { - debug a => _11; - debug b => _10; + debug a => _7; + debug b => _6; } scope 3 (inlined core::num::::overflowing_shl) { debug self => _1; debug rhs => _2; - let mut _9: u32; - let mut _10: bool; + let mut _5: u32; + let mut _6: bool; scope 4 (inlined core::num::::wrapping_shl) { debug self => _1; debug rhs => _2; @@ -27,52 +27,7 @@ fn checked_shl(_1: u32, _2: u32) -> Option { scope 6 (inlined core::num::::unchecked_shl) { debug self => _1; debug rhs => _4; - let mut _8: u32; scope 7 { - scope 8 (inlined core::num::::unchecked_shl::conv) { - debug x => _4; - let mut _5: std::result::Result; - let mut _7: std::option::Option; - scope 9 { - scope 10 (inlined >::try_into) { - debug self => _4; - scope 11 (inlined >::try_from) { - debug value => _4; - scope 12 (inlined >::into) { - debug self => _4; - scope 13 (inlined >::from) { - debug t => _4; - } - } - } - } - scope 14 (inlined Result::::ok) { - debug self => _5; - let _6: u32; - scope 15 { - debug x => _6; - } - } - scope 16 (inlined #[track_caller] Option::::unwrap_unchecked) { - debug self => _7; - let mut _13: &std::option::Option; - scope 17 { - debug val => _8; - } - scope 18 { - scope 20 (inlined unreachable_unchecked) { - scope 21 { - scope 22 (inlined unreachable_unchecked::runtime) { - } - } - } - } - scope 19 (inlined Option::::is_some) { - debug self => _13; - } - } - } - } } } } @@ -81,46 +36,32 @@ fn checked_shl(_1: u32, _2: u32) -> Option { } bb0: { - StorageLive(_10); - StorageLive(_11); - StorageLive(_9); + StorageLive(_6); + StorageLive(_7); + StorageLive(_5); StorageLive(_4); StorageLive(_3); _3 = const 31_u32; _4 = BitAnd(_2, move _3); StorageDead(_3); - StorageLive(_8); - StorageLive(_7); - StorageLive(_5); - _5 = Result::::Ok(_4); - StorageLive(_6); - _6 = move ((_5 as Ok).0: u32); - _7 = Option::::Some(move _6); - StorageDead(_6); - StorageDead(_5); - StorageLive(_13); - _8 = move ((_7 as Some).0: u32); - StorageDead(_13); - StorageDead(_7); - _9 = unchecked_shl::(_1, move _8) -> [return: bb1, unwind unreachable]; + _5 = unchecked_shl::(_1, _4) -> [return: bb1, unwind unreachable]; } bb1: { - StorageDead(_8); StorageDead(_4); - _10 = Ge(_2, const _); - _11 = move _9; - StorageDead(_9); - StorageLive(_12); - _12 = unlikely(_10) -> [return: bb2, unwind unreachable]; + _6 = Ge(_2, const _); + _7 = move _5; + StorageDead(_5); + StorageLive(_8); + _8 = unlikely(_6) -> [return: bb2, unwind unreachable]; } bb2: { - switchInt(move _12) -> [0: bb3, otherwise: bb4]; + switchInt(move _8) -> [0: bb3, otherwise: bb4]; } bb3: { - _0 = Option::::Some(_11); + _0 = Option::::Some(_7); goto -> bb5; } @@ -130,9 +71,9 @@ fn checked_shl(_1: u32, _2: u32) -> Option { } bb5: { - StorageDead(_12); - StorageDead(_11); - StorageDead(_10); + StorageDead(_8); + StorageDead(_7); + StorageDead(_6); return; } } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr new file mode 100644 index 0000000000000..bd0dd126c5e6b --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.gated.stderr @@ -0,0 +1,26 @@ +error[E0277]: can't compare `str` with `str` in const contexts + --> $DIR/match-non-const-eq.rs:6:9 + | +LL | "a" => (), + | ^^^ no implementation for `str == str` + | + = help: the trait `~const PartialEq` is not implemented for `str` +note: the trait `PartialEq` is implemented for `str`, but that implementation is not `const` + --> $DIR/match-non-const-eq.rs:6:9 + | +LL | "a" => (), + | ^^^ + +error[E0015]: cannot match on `str` in constant functions + --> $DIR/match-non-const-eq.rs:6:9 + | +LL | "a" => (), + | ^^^ + | + = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0015, E0277. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.rs new file mode 100644 index 0000000000000..0d04101a38307 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.rs @@ -0,0 +1,12 @@ +// revisions: stock gated +#![cfg_attr(gated, feature(const_trait_impl))] + +const fn foo(input: &'static str) { + match input { + "a" => (), //[gated]~ ERROR can't compare `str` with `str` in const contexts + //~^ ERROR cannot match on `str` in constant functions + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.stock.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.stock.stderr new file mode 100644 index 0000000000000..dcb9b49ea04cf --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/match-non-const-eq.stock.stderr @@ -0,0 +1,13 @@ +error[E0015]: cannot match on `str` in constant functions + --> $DIR/match-non-const-eq.rs:6:9 + | +LL | "a" => (), + | ^^^ + | + = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es + = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.rs b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.rs new file mode 100644 index 0000000000000..0c2d71707c9f0 --- /dev/null +++ b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.rs @@ -0,0 +1,29 @@ +pub trait NSWindow: Sized { + fn frame(self) -> () { + unimplemented!() + } + fn setFrame_display_(self, display: ()) {} +} +impl NSWindow for () {} + +pub struct NSRect {} + +use std::ops::Deref; +struct MainThreadSafe(T); +impl Deref for MainThreadSafe { + type Target = T; + + fn deref(&self) -> &T { + unimplemented!() + } +} + +fn main() { + || { + let ns_window = MainThreadSafe(()); + // Don't record adjustments twice for `*ns_window` + (*ns_window).frame(); + ns_window.setFrame_display_(0); + //~^ ERROR mismatched types + }; +} diff --git a/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr new file mode 100644 index 0000000000000..02e87d701b687 --- /dev/null +++ b/tests/ui/typeck/dont-record-adjustments-when-pointing-at-arg.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/dont-record-adjustments-when-pointing-at-arg.rs:26:37 + | +LL | ns_window.setFrame_display_(0); + | ----------------- ^ expected `()`, found integer + | | + | arguments to this method are incorrect + | +note: method defined here + --> $DIR/dont-record-adjustments-when-pointing-at-arg.rs:5:8 + | +LL | fn setFrame_display_(self, display: ()) {} + | ^^^^^^^^^^^^^^^^^ ----------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.