diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 923b9ddf9afbb..b17dc7f3ddde6 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -1,7 +1,6 @@ use std::mem; use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, Diagnostic, IntoDiagArg}; -use rustc_hir::CRATE_HIR_ID; use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo}; use rustc_middle::mir::AssertKind; use rustc_middle::query::TyCtxtAt; @@ -9,7 +8,7 @@ use rustc_middle::ty::TyCtxt; use rustc_middle::ty::{layout::LayoutError, ConstInt}; use rustc_span::{Span, Symbol}; -use super::CompileTimeInterpreter; +use super::CompileTimeMachine; use crate::errors::{self, FrameNote, ReportErrorExt}; use crate::interpret::{err_inval, err_machine_stop}; use crate::interpret::{ErrorHandled, Frame, InterpError, InterpErrorInfo, MachineStopType}; @@ -156,11 +155,11 @@ where } } -/// Emit a lint from a const-eval situation. +/// Emit a lint from a const-eval situation, with a backtrace. // Even if this is unused, please don't remove it -- chances are we will need to emit a lint during const-eval again in the future! pub(super) fn lint<'tcx, L>( tcx: TyCtxtAt<'tcx>, - machine: &CompileTimeInterpreter<'tcx>, + machine: &CompileTimeMachine<'tcx>, lint: &'static rustc_session::lint::Lint, decorator: impl FnOnce(Vec) -> L, ) where @@ -168,12 +167,5 @@ pub(super) fn lint<'tcx, L>( { let (span, frames) = get_span_and_frames(tcx, &machine.stack); - tcx.emit_node_span_lint( - lint, - // We use the root frame for this so the crate that defines the const defines whether the - // lint is emitted. - machine.stack.first().and_then(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID), - span, - decorator(frames), - ); + tcx.emit_node_span_lint(lint, machine.best_lint_scope(*tcx), span, decorator(frames)); } diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 36f468d3308a8..4b8145eb4855b 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -17,7 +17,7 @@ use rustc_span::def_id::LocalDefId; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{self, Abi}; -use super::{CanAccessMutGlobal, CompileTimeEvalContext, CompileTimeInterpreter}; +use super::{CanAccessMutGlobal, CompileTimeInterpCx, CompileTimeMachine}; use crate::const_eval::CheckAlignment; use crate::errors::ConstEvalError; use crate::errors::{self, DanglingPtrInFinal}; @@ -32,7 +32,7 @@ use crate::CTRL_C_RECEIVED; // Returns a pointer to where the result lives #[instrument(level = "trace", skip(ecx, body))] fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( - ecx: &mut CompileTimeEvalContext<'tcx>, + ecx: &mut CompileTimeInterpCx<'tcx>, cid: GlobalId<'tcx>, body: &'tcx mir::Body<'tcx>, ) -> InterpResult<'tcx, R> { @@ -114,7 +114,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( let err_diag = errors::MutablePtrInFinal { span: ecx.tcx.span, kind: intern_kind }; ecx.tcx.emit_node_span_lint( lint::builtin::CONST_EVAL_MUTABLE_PTR_IN_FINAL_VALUE, - ecx.best_lint_scope(), + ecx.machine.best_lint_scope(*ecx.tcx), err_diag.span, err_diag, ) @@ -139,13 +139,13 @@ pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>( root_span: Span, param_env: ty::ParamEnv<'tcx>, can_access_mut_global: CanAccessMutGlobal, -) -> CompileTimeEvalContext<'tcx> { +) -> CompileTimeInterpCx<'tcx> { debug!("mk_eval_cx: {:?}", param_env); InterpCx::new( tcx, root_span, param_env, - CompileTimeInterpreter::new(can_access_mut_global, CheckAlignment::No), + CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No), ) } @@ -156,7 +156,7 @@ pub fn mk_eval_cx_for_const_val<'tcx>( param_env: ty::ParamEnv<'tcx>, val: mir::ConstValue<'tcx>, ty: Ty<'tcx>, -) -> Option<(CompileTimeEvalContext<'tcx>, OpTy<'tcx>)> { +) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> { let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No); let op = ecx.const_val_to_op(val, ty, None).ok()?; Some((ecx, op)) @@ -170,7 +170,7 @@ pub fn mk_eval_cx_for_const_val<'tcx>( /// encounter an `Indirect` they cannot handle. #[instrument(skip(ecx), level = "debug")] pub(super) fn op_to_const<'tcx>( - ecx: &CompileTimeEvalContext<'tcx>, + ecx: &CompileTimeInterpCx<'tcx>, op: &OpTy<'tcx>, for_diagnostics: bool, ) -> ConstValue<'tcx> { @@ -328,14 +328,14 @@ pub trait InterpretationResult<'tcx> { /// evaluation query. fn make_result( mplace: MPlaceTy<'tcx>, - ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>, + ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>, ) -> Self; } impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> { fn make_result( mplace: MPlaceTy<'tcx>, - _ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>, + _ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>, ) -> Self { ConstAlloc { alloc_id: mplace.ptr().provenance.unwrap().alloc_id(), ty: mplace.layout.ty } } @@ -383,7 +383,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( // they do not have to behave "as if" they were evaluated at runtime. // For consts however we want to ensure they behave "as if" they were evaluated at runtime, // so we have to reject reading mutable global memory. - CompileTimeInterpreter::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error), + CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error), ); let res = ecx.load_mir(cid.instance.def, cid.promoted); res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, body)).map_err(|error| { @@ -417,7 +417,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( #[inline(always)] fn const_validate_mplace<'tcx>( - ecx: &InterpCx<'tcx, CompileTimeInterpreter<'tcx>>, + ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>, mplace: &MPlaceTy<'tcx>, cid: GlobalId<'tcx>, ) -> Result<(), ErrorHandled> { @@ -447,7 +447,7 @@ fn const_validate_mplace<'tcx>( #[inline(always)] fn report_validation_error<'tcx>( - ecx: &InterpCx<'tcx, CompileTimeInterpreter<'tcx>>, + ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>, error: InterpErrorInfo<'tcx>, alloc_id: AllocId, ) -> ErrorHandled { diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 79a161d3f03d7..4f6df857142cf 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -9,12 +9,13 @@ use rustc_data_structures::fx::IndexEntry; use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; use rustc_hir::LangItem; +use rustc_hir::{self as hir, CRATE_HIR_ID}; use rustc_middle::bug; use rustc_middle::mir; use rustc_middle::mir::AssertMessage; use rustc_middle::query::TyCtxtAt; -use rustc_middle::ty; use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::WRITES_THROUGH_IMMUTABLE_POINTER; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; @@ -44,7 +45,7 @@ const TINY_LINT_TERMINATOR_LIMIT: usize = 20; const PROGRESS_INDICATOR_START: usize = 4_000_000; /// Extra machine state for CTFE, and the Machine instance -pub struct CompileTimeInterpreter<'tcx> { +pub struct CompileTimeMachine<'tcx> { /// The number of terminators that have been evaluated. /// /// This is used to produce lints informing the user that the compiler is not stuck. @@ -89,12 +90,12 @@ impl From for CanAccessMutGlobal { } } -impl<'tcx> CompileTimeInterpreter<'tcx> { +impl<'tcx> CompileTimeMachine<'tcx> { pub(crate) fn new( can_access_mut_global: CanAccessMutGlobal, check_alignment: CheckAlignment, ) -> Self { - CompileTimeInterpreter { + CompileTimeMachine { num_evaluated_steps: 0, stack: Vec::new(), can_access_mut_global, @@ -163,7 +164,7 @@ impl interpret::AllocMap for FxIndexMap { } } -pub(crate) type CompileTimeEvalContext<'tcx> = InterpCx<'tcx, CompileTimeInterpreter<'tcx>>; +pub(crate) type CompileTimeInterpCx<'tcx> = InterpCx<'tcx, CompileTimeMachine<'tcx>>; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum MemoryKind { @@ -195,7 +196,7 @@ impl interpret::MayLeak for ! { } } -impl<'tcx> CompileTimeEvalContext<'tcx> { +impl<'tcx> CompileTimeInterpCx<'tcx> { fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) { let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo()); @@ -369,7 +370,16 @@ impl<'tcx> CompileTimeEvalContext<'tcx> { } } -impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> { +impl<'tcx> CompileTimeMachine<'tcx> { + #[inline(always)] + /// Find the first stack frame that is within the current crate, if any. + /// Otherwise, return the crate's HirId + pub fn best_lint_scope(&self, tcx: TyCtxt<'tcx>) -> hir::HirId { + self.stack.iter().find_map(|frame| frame.lint_root(tcx)).unwrap_or(CRATE_HIR_ID) + } +} + +impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { compile_time_machine!(<'tcx>); type MemoryKind = MemoryKind; @@ -600,7 +610,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeInterpreter<'tcx> { // By default, we stop after a million steps, but the user can disable this lint // to be able to run until the heat death of the universe or power loss, whichever // comes first. - let hir_id = ecx.best_lint_scope(); + let hir_id = ecx.machine.best_lint_scope(*ecx.tcx); let is_error = ecx .tcx .lint_level_at_node( diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 66993476bef43..2e8ad445cf5e8 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -9,7 +9,7 @@ use rustc_target::abi::{Abi, VariantIdx}; use tracing::{debug, instrument, trace}; use super::eval_queries::{mk_eval_cx_to_read_const_val, op_to_const}; -use super::machine::CompileTimeEvalContext; +use super::machine::CompileTimeInterpCx; use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES}; use crate::const_eval::CanAccessMutGlobal; use crate::errors::MaxNumNodesInConstErr; @@ -21,7 +21,7 @@ use crate::interpret::{ #[instrument(skip(ecx), level = "debug")] fn branches<'tcx>( - ecx: &CompileTimeEvalContext<'tcx>, + ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>, n: usize, variant: Option, @@ -59,7 +59,7 @@ fn branches<'tcx>( #[instrument(skip(ecx), level = "debug")] fn slice_branches<'tcx>( - ecx: &CompileTimeEvalContext<'tcx>, + ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>, num_nodes: &mut usize, ) -> ValTreeCreationResult<'tcx> { @@ -77,7 +77,7 @@ fn slice_branches<'tcx>( #[instrument(skip(ecx), level = "debug")] fn const_to_valtree_inner<'tcx>( - ecx: &CompileTimeEvalContext<'tcx>, + ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>, num_nodes: &mut usize, ) -> ValTreeCreationResult<'tcx> { @@ -219,7 +219,7 @@ fn reconstruct_place_meta<'tcx>( #[instrument(skip(ecx), level = "debug", ret)] fn create_valtree_place<'tcx>( - ecx: &mut CompileTimeEvalContext<'tcx>, + ecx: &mut CompileTimeInterpCx<'tcx>, layout: TyAndLayout<'tcx>, valtree: ty::ValTree<'tcx>, ) -> MPlaceTy<'tcx> { @@ -364,7 +364,7 @@ pub fn valtree_to_const_value<'tcx>( /// Put a valtree into memory and return a reference to that. fn valtree_to_ref<'tcx>( - ecx: &mut CompileTimeEvalContext<'tcx>, + ecx: &mut CompileTimeInterpCx<'tcx>, valtree: ty::ValTree<'tcx>, pointee_ty: Ty<'tcx>, ) -> Immediate { @@ -380,7 +380,7 @@ fn valtree_to_ref<'tcx>( #[instrument(skip(ecx), level = "debug")] fn valtree_into_mplace<'tcx>( - ecx: &mut CompileTimeEvalContext<'tcx>, + ecx: &mut CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>, valtree: ty::ValTree<'tcx>, ) { @@ -457,6 +457,6 @@ fn valtree_into_mplace<'tcx>( } } -fn dump_place<'tcx>(ecx: &CompileTimeEvalContext<'tcx>, place: &MPlaceTy<'tcx>) { +fn dump_place<'tcx>(ecx: &CompileTimeInterpCx<'tcx>, place: &MPlaceTy<'tcx>) { trace!("{:?}", ecx.dump_place(&PlaceTy::from(place.clone()))); } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 6357219750816..4d93038a81e44 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -4,7 +4,6 @@ use std::{fmt, mem}; use either::{Either, Left, Right}; use tracing::{debug, info, info_span, instrument, trace}; -use hir::CRATE_HIR_ID; use rustc_errors::DiagCtxt; use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData}; use rustc_index::IndexVec; @@ -271,13 +270,18 @@ impl<'tcx, Prov: Provenance, Extra> Frame<'tcx, Prov, Extra> { } } - pub fn lint_root(&self) -> Option { - self.current_source_info().and_then(|source_info| { - match &self.body.source_scopes[source_info.scope].local_data { + pub fn lint_root(&self, tcx: TyCtxt<'tcx>) -> Option { + // We first try to get a HirId via the current source scope, + // and fall back to `body.source`. + self.current_source_info() + .and_then(|source_info| match &self.body.source_scopes[source_info.scope].local_data { mir::ClearCrossCrate::Set(data) => Some(data.lint_root), mir::ClearCrossCrate::Clear => None, - } - }) + }) + .or_else(|| { + let def_id = self.body.source.def_id().as_local(); + def_id.map(|def_id| tcx.local_def_id_to_hir_id(def_id)) + }) } /// Returns the address of the buffer where the locals are stored. This is used by `Place` as a @@ -509,17 +513,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.stack().last().map_or(self.tcx.span, |f| f.current_span()) } - /// Find the first stack frame that is within the current crate, if any; - /// otherwise return the crate's HirId. - #[inline(always)] - pub fn best_lint_scope(&self) -> hir::HirId { - self.stack() - .iter() - .find_map(|frame| frame.body.source.def_id().as_local()) - .map_or(CRATE_HIR_ID, |def_id| self.tcx.local_def_id_to_hir_id(def_id)) - } - - #[inline(always)] pub(crate) fn stack(&self) -> &[Frame<'tcx, M::Provenance, M::FrameExtra>] { M::stack(self) } diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 3066e0933d94d..8b0a2afa4d669 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -45,7 +45,7 @@ pub trait HasStaticRootDefId { fn static_def_id(&self) -> Option; } -impl HasStaticRootDefId for const_eval::CompileTimeInterpreter<'_> { +impl HasStaticRootDefId for const_eval::CompileTimeMachine<'_> { fn static_def_id(&self) -> Option { Some(self.static_root_ids?.1) } diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 10fd6399b9a37..f6537ed6ea9ed 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -1,4 +1,4 @@ -use crate::const_eval::{CompileTimeEvalContext, CompileTimeInterpreter, InterpretationResult}; +use crate::const_eval::{CompileTimeInterpCx, CompileTimeMachine, InterpretationResult}; use rustc_hir::def_id::LocalDefId; use rustc_middle::mir; use rustc_middle::mir::interpret::{Allocation, InterpResult, Pointer}; @@ -84,7 +84,7 @@ where impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx> { fn make_result( mplace: MPlaceTy<'tcx>, - ecx: &mut InterpCx<'tcx, CompileTimeInterpreter<'tcx>>, + ecx: &mut InterpCx<'tcx, CompileTimeMachine<'tcx>>, ) -> Self { let alloc_id = mplace.ptr().provenance.unwrap().alloc_id(); let alloc = ecx.memory.alloc_map.swap_remove(&alloc_id).unwrap().1; @@ -93,7 +93,7 @@ impl<'tcx> InterpretationResult<'tcx> for mir::interpret::ConstAllocation<'tcx> } pub(crate) fn create_static_alloc<'tcx>( - ecx: &mut CompileTimeEvalContext<'tcx>, + ecx: &mut CompileTimeInterpCx<'tcx>, static_def_id: LocalDefId, layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx>> { diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs index 62c5f8734a249..3b07bee2d9c27 100644 --- a/compiler/rustc_const_eval/src/util/caller_location.rs +++ b/compiler/rustc_const_eval/src/util/caller_location.rs @@ -7,12 +7,12 @@ use rustc_middle::ty::{self, Mutability}; use rustc_span::symbol::Symbol; use tracing::trace; -use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, CompileTimeEvalContext}; +use crate::const_eval::{mk_eval_cx_to_read_const_val, CanAccessMutGlobal, CompileTimeInterpCx}; use crate::interpret::*; /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers. fn alloc_caller_location<'tcx>( - ecx: &mut CompileTimeEvalContext<'tcx>, + ecx: &mut CompileTimeInterpCx<'tcx>, filename: Symbol, line: u32, col: u32, diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 68fb122a765da..daf57285ebe6d 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -3,7 +3,7 @@ use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, Val use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt}; use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants}; -use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeInterpreter}; +use crate::const_eval::{CanAccessMutGlobal, CheckAlignment, CompileTimeMachine}; use crate::interpret::{InterpCx, MemoryKind, OpTy}; /// Determines if this type permits "raw" initialization by just transmuting some memory into an @@ -45,7 +45,7 @@ fn might_permit_raw_init_strict<'tcx>( tcx: TyCtxt<'tcx>, kind: ValidityRequirement, ) -> Result> { - let machine = CompileTimeInterpreter::new(CanAccessMutGlobal::No, CheckAlignment::Error); + let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error); let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine); diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index c3ccba487ede7..69461957f804d 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -244,7 +244,9 @@ language_item_table! { AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0); CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None; - Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Minimum(1); + Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Exact(1); + CoroutineReturn, sym::coroutine_return, coroutine_return, Target::AssocTy, GenericRequirement::Exact(1); + CoroutineYield, sym::coroutine_yield, coroutine_yield, Target::AssocTy, GenericRequirement::Exact(1); CoroutineResume, sym::coroutine_resume, coroutine_resume, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None; Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None; diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 01bd732a4cd84..5e9c3c64e39ed 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -225,6 +225,50 @@ impl<'a, 'tcx> At<'a, 'tcx> { } } + /// Used in the new solver since we don't care about tracking an `ObligationCause`. + pub fn relate_no_trace( + self, + expected: T, + variance: ty::Variance, + actual: T, + ) -> Result>>, NoSolution> + where + T: Relate>, + { + let mut fields = CombineFields::new( + self.infcx, + TypeTrace::dummy(self.cause), + self.param_env, + DefineOpaqueTypes::Yes, + ); + fields.sub().relate_with_variance( + variance, + ty::VarianceDiagInfo::default(), + expected, + actual, + )?; + Ok(fields.goals) + } + + /// Used in the new solver since we don't care about tracking an `ObligationCause`. + pub fn eq_structurally_relating_aliases_no_trace( + self, + expected: T, + actual: T, + ) -> Result>>, NoSolution> + where + T: Relate>, + { + let mut fields = CombineFields::new( + self.infcx, + TypeTrace::dummy(self.cause), + self.param_env, + DefineOpaqueTypes::Yes, + ); + fields.equate(StructurallyRelateAliases::Yes).relate(expected, actual)?; + Ok(fields.goals) + } + /// Computes the least-upper-bound, or mutual supertype, of two /// values. The order of the arguments doesn't matter, but since /// this can result in an error (e.g., if asked to compute LUB of @@ -303,7 +347,7 @@ impl<'tcx> ToTrace<'tcx> for Ty<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), + values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), } } } @@ -315,7 +359,10 @@ impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> { a: Self, b: Self, ) -> TypeTrace<'tcx> { - TypeTrace { cause: cause.clone(), values: Regions(ExpectedFound::new(a_is_expected, a, b)) } + TypeTrace { + cause: cause.clone(), + values: ValuePairs::Regions(ExpectedFound::new(a_is_expected, a, b)), + } } } @@ -328,7 +375,7 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), + values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), } } } @@ -344,13 +391,13 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> { cause: cause.clone(), values: match (a.unpack(), b.unpack()) { (GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => { - Regions(ExpectedFound::new(a_is_expected, a, b)) + ValuePairs::Regions(ExpectedFound::new(a_is_expected, a, b)) } (GenericArgKind::Type(a), GenericArgKind::Type(b)) => { - Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())) + ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())) } (GenericArgKind::Const(a), GenericArgKind::Const(b)) => { - Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())) + ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())) } ( @@ -379,7 +426,10 @@ impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> { a: Self, b: Self, ) -> TypeTrace<'tcx> { - TypeTrace { cause: cause.clone(), values: Terms(ExpectedFound::new(a_is_expected, a, b)) } + TypeTrace { + cause: cause.clone(), + values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a, b)), + } } } @@ -392,7 +442,7 @@ impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)), + values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)), } } } @@ -406,7 +456,7 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: Aliases(ExpectedFound::new(a_is_expected, a.into(), b.into())), + values: ValuePairs::Aliases(ExpectedFound::new(a_is_expected, a.into(), b.into())), } } } @@ -418,7 +468,10 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> { a: Self, b: Self, ) -> TypeTrace<'tcx> { - TypeTrace { cause: cause.clone(), values: Aliases(ExpectedFound::new(a_is_expected, a, b)) } + TypeTrace { + cause: cause.clone(), + values: ValuePairs::Aliases(ExpectedFound::new(a_is_expected, a, b)), + } } } @@ -431,7 +484,7 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: PolySigs(ExpectedFound::new( + values: ValuePairs::PolySigs(ExpectedFound::new( a_is_expected, ty::Binder::dummy(a), ty::Binder::dummy(b), @@ -449,7 +502,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyFnSig<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: PolySigs(ExpectedFound::new(a_is_expected, a, b)), + values: ValuePairs::PolySigs(ExpectedFound::new(a_is_expected, a, b)), } } } @@ -463,7 +516,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ExistentialTraitRef(ExpectedFound::new(a_is_expected, a, b)), + values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(a_is_expected, a, b)), } } } @@ -477,7 +530,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ExistentialProjection(ExpectedFound::new(a_is_expected, a, b)), + values: ValuePairs::ExistentialProjection(ExpectedFound::new(a_is_expected, a, b)), } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index ed483c6cbeb41..7fb07a5d30c43 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1707,6 +1707,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ValuePairs::ExistentialProjection(_) => { (false, Mismatch::Fixed("existential projection")) } + ValuePairs::Dummy => { + bug!("do not expect to report a type error from a ValuePairs::Dummy") + } }; let Some(vals) = self.values_str(values) else { // Derived error. Cancel the emitter. @@ -2250,12 +2253,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { values: ValuePairs<'tcx>, ) -> Option<(DiagStyledString, DiagStyledString, Option)> { match values { - infer::Regions(exp_found) => self.expected_found_str(exp_found), - infer::Terms(exp_found) => self.expected_found_str_term(exp_found), - infer::Aliases(exp_found) => self.expected_found_str(exp_found), - infer::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found), - infer::ExistentialProjection(exp_found) => self.expected_found_str(exp_found), - infer::TraitRefs(exp_found) => { + ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found), + ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found), + ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found), + ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found), + ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found), + ValuePairs::TraitRefs(exp_found) => { let pretty_exp_found = ty::error::ExpectedFound { expected: exp_found.expected.print_trait_sugared(), found: exp_found.found.print_trait_sugared(), @@ -2267,7 +2270,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ret => ret, } } - infer::PolySigs(exp_found) => { + ValuePairs::PolySigs(exp_found) => { let exp_found = self.resolve_vars_if_possible(exp_found); if exp_found.references_error() { return None; @@ -2275,6 +2278,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found); Some((exp, fnd, None)) } + ValuePairs::Dummy => { + bug!("do not expect to report a type error from a ValuePairs::Dummy") + } } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 32b50053b5076..dcf415e720fb5 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -9,9 +9,8 @@ pub use rustc_middle::ty::IntVarValue; pub use BoundRegionConversionTime::*; pub use RegionVariableOrigin::*; pub use SubregionOrigin::*; -pub use ValuePairs::*; -use crate::infer::relate::RelateResult; +use crate::infer::relate::{Relate, RelateResult}; use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine}; use error_reporting::TypeErrCtxt; use free_regions::RegionRelations; @@ -35,6 +34,7 @@ use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::select; +use rustc_middle::traits::solve::{Goal, NoSolution}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BoundVarReplacerDelegate; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; @@ -44,7 +44,7 @@ use rustc_middle::ty::{ConstVid, EffectVid, FloatVid, IntVid, TyVid}; use rustc_middle::ty::{GenericArg, GenericArgKind, GenericArgs, GenericArgsRef}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::Symbol; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use snapshot::undo_log::InferCtxtUndoLogs; use std::cell::{Cell, RefCell}; use std::fmt; @@ -352,27 +352,27 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { } } - fn universe_of_ct(&self, ct: ConstVid) -> Option { - // Same issue as with `universe_of_ty` - match self.probe_const_var(ct) { + fn universe_of_lt(&self, lt: ty::RegionVid) -> Option { + match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) { Err(universe) => Some(universe), Ok(_) => None, } } - fn universe_of_lt(&self, lt: ty::RegionVid) -> Option { - match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) { + fn universe_of_ct(&self, ct: ConstVid) -> Option { + // Same issue as with `universe_of_ty` + match self.probe_const_var(ct) { Err(universe) => Some(universe), Ok(_) => None, } } - fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> { - self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid) + fn root_ty_var(&self, var: TyVid) -> TyVid { + self.root_var(var) } - fn defining_opaque_types(&self) -> &'tcx ty::List { - self.defining_opaque_types + fn root_const_var(&self, var: ConstVid) -> ConstVid { + self.root_const_var(var) } fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> Ty<'tcx> { @@ -405,6 +405,72 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { } } } + + fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> { + self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid) + } + + fn defining_opaque_types(&self) -> &'tcx ty::List { + self.defining_opaque_types + } + + fn next_ty_infer(&self) -> Ty<'tcx> { + self.next_ty_var(DUMMY_SP) + } + + fn next_const_infer(&self) -> ty::Const<'tcx> { + self.next_const_var(DUMMY_SP) + } + + fn fresh_args_for_item(&self, def_id: DefId) -> ty::GenericArgsRef<'tcx> { + self.fresh_args_for_item(DUMMY_SP, def_id) + } + + fn instantiate_binder_with_infer + Copy>( + &self, + value: ty::Binder<'tcx, T>, + ) -> T { + self.instantiate_binder_with_fresh_vars( + DUMMY_SP, + BoundRegionConversionTime::HigherRankedType, + value, + ) + } + + fn enter_forall> + Copy, U>( + &self, + value: ty::Binder<'tcx, T>, + f: impl FnOnce(T) -> U, + ) -> U { + self.enter_forall(value, f) + } + + fn relate>>( + &self, + param_env: ty::ParamEnv<'tcx>, + lhs: T, + variance: ty::Variance, + rhs: T, + ) -> Result>>, NoSolution> { + self.at(&ObligationCause::dummy(), param_env).relate_no_trace(lhs, variance, rhs) + } + + fn eq_structurally_relating_aliases>>( + &self, + param_env: ty::ParamEnv<'tcx>, + lhs: T, + rhs: T, + ) -> Result>>, NoSolution> { + self.at(&ObligationCause::dummy(), param_env) + .eq_structurally_relating_aliases_no_trace(lhs, rhs) + } + + fn resolve_vars_if_possible(&self, value: T) -> T + where + T: TypeFoldable>, + { + self.resolve_vars_if_possible(value) + } } /// See the `error_reporting` module for more details. @@ -417,6 +483,7 @@ pub enum ValuePairs<'tcx> { PolySigs(ExpectedFound>), ExistentialTraitRef(ExpectedFound>), ExistentialProjection(ExpectedFound>), + Dummy, } impl<'tcx> ValuePairs<'tcx> { @@ -1812,7 +1879,7 @@ impl<'tcx> TypeTrace<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), + values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), } } @@ -1824,7 +1891,7 @@ impl<'tcx> TypeTrace<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)), + values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)), } } @@ -1836,9 +1903,13 @@ impl<'tcx> TypeTrace<'tcx> { ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), + values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), } } + + fn dummy(cause: &ObligationCause<'tcx>) -> TypeTrace<'tcx> { + TypeTrace { cause: cause.clone(), values: ValuePairs::Dummy } + } } impl<'tcx> SubregionOrigin<'tcx> { diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 886dbd317afa3..a89ebe46c3749 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -204,6 +204,23 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef> for AdtDef<'tcx> { fn def_id(self) -> DefId { self.did() } + + fn is_phantom_data(self) -> bool { + self.is_phantom_data() + } + + fn all_field_tys( + self, + tcx: TyCtxt<'tcx>, + ) -> ty::EarlyBinder<'tcx, impl Iterator>> { + ty::EarlyBinder::bind( + self.all_fields().map(move |field| tcx.type_of(field.did).skip_binder()), + ) + } + + fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option>> { + self.sized_constraint(tcx) + } } #[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 65d744239a6ab..3651c990c9792 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -70,9 +70,9 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; use rustc_type_ir::fold::TypeFoldable; +use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::TyKind::*; -use rustc_type_ir::WithCachedTypeInfo; -use rustc_type_ir::{CollectAndApply, Interner, TypeFlags}; +use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo}; use tracing::{debug, instrument}; use std::assert_matches::assert_matches; @@ -154,7 +154,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type VariancesOf = &'tcx [ty::Variance]; - fn variances_of(self, def_id: Self::DefId) -> Self::VariancesOf { + fn variances_of(self, def_id: DefId) -> Self::VariancesOf { self.variances_of(def_id) } @@ -198,7 +198,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn trait_ref_and_own_args_for_alias( self, - def_id: Self::DefId, + def_id: DefId, args: Self::GenericArgs, ) -> (rustc_type_ir::TraitRef, Self::GenericArgsSlice) { assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst); @@ -246,7 +246,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.mk_type_list_from_iter(args) } - fn parent(self, def_id: Self::DefId) -> Self::DefId { + fn parent(self, def_id: DefId) -> DefId { self.parent(def_id) } @@ -259,15 +259,85 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn features(self) -> Self::Features { self.features() } + + fn bound_coroutine_hidden_types( + self, + def_id: DefId, + ) -> impl IntoIterator>>> { + self.bound_coroutine_hidden_types(def_id) + } + + fn fn_sig(self, def_id: DefId) -> ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>> { + self.fn_sig(def_id) + } + + fn coroutine_movability(self, def_id: DefId) -> rustc_ast::Movability { + self.coroutine_movability(def_id) + } + + fn coroutine_for_closure(self, def_id: DefId) -> DefId { + self.coroutine_for_closure(def_id) + } + + fn generics_require_sized_self(self, def_id: DefId) -> bool { + self.generics_require_sized_self(def_id) + } + + fn item_bounds( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + self.item_bounds(def_id).map_bound(IntoIterator::into_iter) + } + + fn super_predicates_of( + self, + def_id: DefId, + ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { + ty::EarlyBinder::bind( + self.super_predicates_of(def_id).instantiate_identity(self).predicates.into_iter(), + ) + } + + fn has_target_features(self, def_id: DefId) -> bool { + !self.codegen_fn_attrs(def_id).target_features.is_empty() + } + + fn require_lang_item(self, lang_item: TraitSolverLangItem) -> DefId { + self.require_lang_item( + match lang_item { + TraitSolverLangItem::Future => hir::LangItem::Future, + TraitSolverLangItem::FutureOutput => hir::LangItem::FutureOutput, + TraitSolverLangItem::AsyncFnKindHelper => hir::LangItem::AsyncFnKindHelper, + TraitSolverLangItem::AsyncFnKindUpvars => hir::LangItem::AsyncFnKindUpvars, + }, + None, + ) + } + + fn associated_type_def_ids(self, def_id: DefId) -> impl IntoIterator { + self.associated_items(def_id) + .in_definition_order() + .filter(|assoc_item| matches!(assoc_item.kind, ty::AssocKind::Type)) + .map(|assoc_item| assoc_item.def_id) + } } impl<'tcx> rustc_type_ir::inherent::Abi> for abi::Abi { + fn rust() -> Self { + abi::Abi::Rust + } + fn is_rust(self) -> bool { matches!(self, abi::Abi::Rust) } } impl<'tcx> rustc_type_ir::inherent::Safety> for hir::Safety { + fn safe() -> Self { + hir::Safety::Safe + } + fn is_safe(self) -> bool { matches!(self, hir::Safety::Safe) } @@ -281,6 +351,10 @@ impl<'tcx> rustc_type_ir::inherent::Features> for &'tcx rustc_featu fn generic_const_exprs(self) -> bool { self.generic_const_exprs } + + fn coroutine_clone(self) -> bool { + self.coroutine_clone + } } type InternedSet<'tcx, T> = ShardedHashMap, ()>; diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 7fff3d0132493..54c88e48614b0 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -41,6 +41,8 @@ pub struct GenericArg<'tcx> { marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>, } +impl<'tcx> rustc_type_ir::inherent::GenericArg> for GenericArg<'tcx> {} + impl<'tcx> rustc_type_ir::inherent::GenericArgs> for ty::GenericArgsRef<'tcx> { fn type_at(self, i: usize) -> Ty<'tcx> { self.type_at(i) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 83f8de6b6f93f..c322c87bce4ad 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -488,6 +488,8 @@ pub struct Term<'tcx> { marker: PhantomData<(Ty<'tcx>, Const<'tcx>)>, } +impl<'tcx> rustc_type_ir::inherent::Term> for Term<'tcx> {} + impl<'tcx> rustc_type_ir::inherent::IntoKind for Term<'tcx> { type Kind = TermKind<'tcx>; diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 785aa8d456fc6..ae36f2624ca5f 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -49,6 +49,18 @@ impl<'tcx> rustc_type_ir::inherent::Predicate> for Predicate<'tcx> fn is_coinductive(self, interner: TyCtxt<'tcx>) -> bool { self.is_coinductive(interner) } + + fn allow_normalization(self) -> bool { + self.allow_normalization() + } +} + +impl<'tcx> rustc_type_ir::inherent::IntoKind for Predicate<'tcx> { + type Kind = ty::Binder<'tcx, ty::PredicateKind<'tcx>>; + + fn kind(self) -> Self::Kind { + self.kind() + } } impl<'tcx> rustc_type_ir::visit::Flags for Predicate<'tcx> { @@ -120,6 +132,7 @@ impl<'tcx> Predicate<'tcx> { /// unsoundly accept some programs. See #91068. #[inline] pub fn allow_normalization(self) -> bool { + // Keep this in sync with the one in `rustc_type_ir::inherent`! match self.kind().skip_binder() { PredicateKind::Clause(ClauseKind::WellFormed(_)) | PredicateKind::AliasRelate(..) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index ba9ed0d5b70a6..8308e537e5edf 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -786,6 +786,10 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { tcx.types.bool } + fn new_u8(tcx: TyCtxt<'tcx>) -> Self { + tcx.types.u8 + } + fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferTy) -> Self { Ty::new_infer(tcx, infer) } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 121a3b99a39ee..0f8f28e3462ab 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -330,8 +330,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let is_sized = !self.feature_unsized_locals || self.local_decls[local].ty.is_sized(self.tcx, self.param_env); if is_sized { - self.rev_locals.ensure_contains_elem(value, SmallVec::new); - self.rev_locals[value].push(local); + self.rev_locals.ensure_contains_elem(value, SmallVec::new).push(local); } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index a72fbdb902159..6a74ddc5508a7 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -898,7 +898,7 @@ fn create_and_seed_worklist( match tcx.def_kind(id) { DefKind::Impl { .. } => false, DefKind::AssocConst | DefKind::AssocFn => !matches!(tcx.associated_item(id).container, AssocItemContainer::ImplContainer), - DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()), + DefKind::Struct => struct_all_fields_are_public(tcx, id.to_def_id()) || has_allow_dead_code_or_lang_attr(tcx, id).is_some(), _ => true }) .map(|id| (id, ComesFromAllowExpect::No)) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index d1541527cf595..8d470c6c61ef4 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -2783,33 +2783,65 @@ fn show_candidates( // by iterating through a hash map, so make sure they are ordered: for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] { path_strings.sort_by(|a, b| a.0.cmp(&b.0)); + path_strings.dedup_by(|a, b| a.0 == b.0); let core_path_strings = path_strings.extract_if(|p| p.0.starts_with("core::")).collect::>(); - path_strings.extend(core_path_strings); - path_strings.dedup_by(|a, b| a.0 == b.0); + let std_path_strings = + path_strings.extract_if(|p| p.0.starts_with("std::")).collect::>(); + let foreign_crate_path_strings = + path_strings.extract_if(|p| !p.0.starts_with("crate::")).collect::>(); + + // We list the `crate` local paths first. + // Then we list the `std`/`core` paths. + if std_path_strings.len() == core_path_strings.len() { + // Do not list `core::` paths if we are already listing the `std::` ones. + path_strings.extend(std_path_strings); + } else { + path_strings.extend(std_path_strings); + path_strings.extend(core_path_strings); + } + // List all paths from foreign crates last. + path_strings.extend(foreign_crate_path_strings); } - accessible_path_strings.sort(); if !accessible_path_strings.is_empty() { - let (determiner, kind, name, through) = + let (determiner, kind, s, name, through) = if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] { ( "this", *descr, + "", format!(" `{name}`"), if *via_import { " through its public re-export" } else { "" }, ) } else { - ("one of these", "items", String::new(), "") + // Get the unique item kinds and if there's only one, we use the right kind name + // instead of the more generic "items". + let mut kinds = accessible_path_strings + .iter() + .map(|(_, descr, _, _, _)| *descr) + .collect::>() + .into_iter(); + let kind = if let Some(kind) = kinds.next() + && let None = kinds.next() + { + kind + } else { + "item" + }; + let s = if kind.ends_with('s') { "es" } else { "s" }; + + ("one of these", kind, s, String::new(), "") }; let instead = if let Instead::Yes = instead { " instead" } else { "" }; let mut msg = if let DiagMode::Pattern = mode { format!( - "if you meant to match on {kind}{instead}{name}, use the full path in the pattern", + "if you meant to match on {kind}{s}{instead}{name}, use the full path in the \ + pattern", ) } else { - format!("consider importing {determiner} {kind}{through}{instead}") + format!("consider importing {determiner} {kind}{s}{through}{instead}") }; for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e245dfb9f5d77..c89323b7f1691 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -635,7 +635,9 @@ symbols! { coroutine, coroutine_clone, coroutine_resume, + coroutine_return, coroutine_state, + coroutine_yield, coroutines, cosf128, cosf16, diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 98f98d9992d30..d6074617cafe7 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -1,14 +1,14 @@ //! Code which is used by built-in goals that match "structurally", such a auto //! traits, `Copy`/`Clone`. + +use rustc_ast_ir::{Movability, Mutability}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::LangItem; -use rustc_hir::{def_id::DefId, Movability, Mutability}; -use rustc_infer::infer::InferCtxt; -use rustc_infer::traits::query::NoSolution; -use rustc_macros::{TypeFoldable, TypeVisitable}; -use rustc_middle::bug; -use rustc_middle::traits::solve::Goal; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, Upcast}; +use rustc_next_trait_solver::solve::{Goal, NoSolution}; +use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_type_ir::inherent::*; +use rustc_type_ir::lang_items::TraitSolverLangItem; +use rustc_type_ir::{self as ty, InferCtxtLike, Interner, Upcast}; +use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use crate::solve::EvalCtxt; @@ -17,12 +17,16 @@ use crate::solve::EvalCtxt; // For types with an "existential" binder, i.e. coroutine witnesses, we also // instantiate the binder with placeholders eagerly. #[instrument(level = "trace", skip(ecx), ret)] -pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( - ecx: &EvalCtxt<'_, InferCtxt<'tcx>>, - ty: Ty<'tcx>, -) -> Result>>, NoSolution> { +pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait( + ecx: &EvalCtxt<'_, Infcx>, + ty: I::Ty, +) -> Result>, NoSolution> +where + Infcx: InferCtxtLike, + I: Interner, +{ let tcx = ecx.interner(); - match *ty.kind() { + match ty.kind() { ty::Uint(_) | ty::Int(_) | ty::Bool @@ -34,7 +38,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( | ty::Char => Ok(vec![]), // Treat `str` like it's defined as `struct str([u8]);` - ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(tcx, tcx.types.u8))]), + ty::Str => Ok(vec![ty::Binder::dummy(Ty::new_slice(tcx, Ty::new_u8(tcx)))]), ty::Dynamic(..) | ty::Param(..) @@ -43,7 +47,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( | ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => { - bug!("unexpected type `{ty}`") + panic!("unexpected type `{ty:?}`") } ty::RawPtr(element_ty, _) | ty::Ref(_, element_ty, _) => { @@ -56,7 +60,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ty::Tuple(tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet - Ok(tys.iter().map(ty::Binder::dummy).collect()) + Ok(tys.into_iter().map(ty::Binder::dummy).collect()) } ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]), @@ -76,31 +80,38 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ty::CoroutineWitness(def_id, args) => Ok(ecx .interner() .bound_coroutine_hidden_types(def_id) - .map(|bty| bty.instantiate(tcx, args)) + .into_iter() + .map(|bty| bty.instantiate(tcx, &args)) .collect()), // For `PhantomData`, we pass `T`. ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![ty::Binder::dummy(args.type_at(0))]), - ty::Adt(def, args) => { - Ok(def.all_fields().map(|f| ty::Binder::dummy(f.ty(tcx, args))).collect()) - } + ty::Adt(def, args) => Ok(def + .all_field_tys(tcx) + .iter_instantiated(tcx, &args) + .map(ty::Binder::dummy) + .collect()), ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => { // We can resolve the `impl Trait` to its concrete type, // which enforces a DAG between the functions requiring // the auto trait bounds in question. - Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, args))]) + Ok(vec![ty::Binder::dummy(tcx.type_of(def_id).instantiate(tcx, &args))]) } } } #[instrument(level = "trace", skip(ecx), ret)] -pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( - ecx: &EvalCtxt<'_, InferCtxt<'tcx>>, - ty: Ty<'tcx>, -) -> Result>>, NoSolution> { - match *ty.kind() { +pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait( + ecx: &EvalCtxt<'_, Infcx>, + ty: I::Ty, +) -> Result>, NoSolution> +where + Infcx: InferCtxtLike, + I: Interner, +{ + match ty.kind() { // impl Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char, &mut? T, [T; N], dyn* Trait, ! // impl Sized for Coroutine, CoroutineWitness, Closure, CoroutineClosure ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) @@ -133,7 +144,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( ty::Bound(..) | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("unexpected type `{ty}`") + panic!("unexpected type `{ty:?}`") } // impl Sized for () @@ -151,7 +162,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( // if the ADT is sized for all possible args. ty::Adt(def, args) => { if let Some(sized_crit) = def.sized_constraint(ecx.interner()) { - Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.interner(), args))]) + Ok(vec![ty::Binder::dummy(sized_crit.instantiate(ecx.interner(), &args))]) } else { Ok(vec![]) } @@ -160,11 +171,15 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>( } #[instrument(level = "trace", skip(ecx), ret)] -pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( - ecx: &EvalCtxt<'_, InferCtxt<'tcx>>, - ty: Ty<'tcx>, -) -> Result>>, NoSolution> { - match *ty.kind() { +pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait( + ecx: &EvalCtxt<'_, Infcx>, + ty: I::Ty, +) -> Result>, NoSolution> +where + Infcx: InferCtxtLike, + I: Interner, +{ + match ty.kind() { // impl Copy/Clone for FnDef, FnPtr ty::FnDef(..) | ty::FnPtr(_) | ty::Error(_) => Ok(vec![]), @@ -196,11 +211,11 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ty::Bound(..) | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("unexpected type `{ty}`") + panic!("unexpected type `{ty:?}`") } // impl Copy/Clone for (T1, T2, .., Tn) where T1: Copy/Clone, T2: Copy/Clone, .. Tn: Copy/Clone - ty::Tuple(tys) => Ok(tys.iter().map(ty::Binder::dummy).collect()), + ty::Tuple(tys) => Ok(tys.into_iter().map(ty::Binder::dummy).collect()), // impl Copy/Clone for Closure where Self::TupledUpvars: Copy/Clone ty::Closure(_, args) => Ok(vec![ty::Binder::dummy(args.as_closure().tupled_upvars_ty())]), @@ -212,7 +227,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ty::Coroutine(def_id, args) => match ecx.interner().coroutine_movability(def_id) { Movability::Static => Err(NoSolution), Movability::Movable => { - if ecx.interner().features().coroutine_clone { + if ecx.interner().features().coroutine_clone() { let coroutine = args.as_coroutine(); Ok(vec![ ty::Binder::dummy(coroutine.tupled_upvars_ty()), @@ -228,27 +243,26 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>( ty::CoroutineWitness(def_id, args) => Ok(ecx .interner() .bound_coroutine_hidden_types(def_id) - .map(|bty| bty.instantiate(ecx.interner(), args)) + .into_iter() + .map(|bty| bty.instantiate(ecx.interner(), &args)) .collect()), } } // Returns a binder of the tupled inputs types and output type from a builtin callable type. -pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( - tcx: TyCtxt<'tcx>, - self_ty: Ty<'tcx>, +pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable( + tcx: I, + self_ty: I::Ty, goal_kind: ty::ClosureKind, -) -> Result, Ty<'tcx>)>>, NoSolution> { - match *self_ty.kind() { +) -> Result>, NoSolution> { + match self_ty.kind() { // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed. ty::FnDef(def_id, args) => { let sig = tcx.fn_sig(def_id); - if sig.skip_binder().is_fn_trait_compatible() - && tcx.codegen_fn_attrs(def_id).target_features.is_empty() - { + if sig.skip_binder().is_fn_trait_compatible() && !tcx.has_target_features(def_id) { Ok(Some( - sig.instantiate(tcx, args) - .map_bound(|sig| (Ty::new_tup(tcx, sig.inputs()), sig.output())), + sig.instantiate(tcx, &args) + .map_bound(|sig| (Ty::new_tup(tcx, &sig.inputs()), sig.output())), )) } else { Err(NoSolution) @@ -257,7 +271,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed. ty::FnPtr(sig) => { if sig.is_fn_trait_compatible() { - Ok(Some(sig.map_bound(|sig| (Ty::new_tup(tcx, sig.inputs()), sig.output())))) + Ok(Some(sig.map_bound(|sig| (Ty::new_tup(tcx, &sig.inputs()), sig.output())))) } else { Err(NoSolution) } @@ -311,7 +325,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( tcx, goal_kind, // No captures by ref, so this doesn't matter. - tcx.lifetimes.re_static, + Region::new_static(tcx), def_id, args, sig, @@ -326,7 +340,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( coroutine_closure_to_ambiguous_coroutine( tcx, goal_kind, // No captures by ref, so this doesn't matter. - tcx.lifetimes.re_static, + Region::new_static(tcx), def_id, args, sig, @@ -362,22 +376,24 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>( ty::Bound(..) | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("unexpected type `{self_ty}`") + panic!("unexpected type `{self_ty:?}`") } } } /// Relevant types for an async callable, including its inputs, output, /// and the return type you get from awaiting the output. -#[derive(Copy, Clone, Debug, TypeVisitable, TypeFoldable)] -pub(in crate::solve) struct AsyncCallableRelevantTypes<'tcx> { - pub tupled_inputs_ty: Ty<'tcx>, +#[derive(derivative::Derivative)] +#[derivative(Clone(bound = ""), Copy(bound = ""), Debug(bound = ""))] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] +pub(in crate::solve) struct AsyncCallableRelevantTypes { + pub tupled_inputs_ty: I::Ty, /// Type returned by calling the closure /// i.e. `f()`. - pub output_coroutine_ty: Ty<'tcx>, + pub output_coroutine_ty: I::Ty, /// Type returned by `await`ing the output /// i.e. `f().await`. - pub coroutine_return_ty: Ty<'tcx>, + pub coroutine_return_ty: I::Ty, } // Returns a binder of the tupled inputs types, output type, and coroutine type @@ -385,16 +401,13 @@ pub(in crate::solve) struct AsyncCallableRelevantTypes<'tcx> { // the coroutine-closure, emit an additional trait predicate for `AsyncFnKindHelper` // which enforces the closure is actually callable with the given trait. When we // know the kind already, we can short-circuit this check. -pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tcx>( - tcx: TyCtxt<'tcx>, - self_ty: Ty<'tcx>, +pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable( + tcx: I, + self_ty: I::Ty, goal_kind: ty::ClosureKind, - env_region: ty::Region<'tcx>, -) -> Result< - (ty::Binder<'tcx, AsyncCallableRelevantTypes<'tcx>>, Vec>), - NoSolution, -> { - match *self_ty.kind() { + env_region: I::Region, +) -> Result<(ty::Binder>, Vec), NoSolution> { + match self_ty.kind() { ty::CoroutineClosure(def_id, args) => { let args = args.as_coroutine_closure(); let kind_ty = args.kind_ty(); @@ -421,7 +434,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc nested.push( ty::TraitRef::new( tcx, - tcx.require_lang_item(LangItem::AsyncFnKindHelper, None), + tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper), [kind_ty, Ty::from_closure_kind(tcx, goal_kind)], ) .upcast(tcx), @@ -445,7 +458,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc ty::FnDef(..) | ty::FnPtr(..) => { let bound_sig = self_ty.fn_sig(tcx); let sig = bound_sig.skip_binder(); - let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None); + let future_trait_def_id = tcx.require_lang_item(TraitSolverLangItem::Future); // `FnDef` and `FnPtr` only implement `AsyncFn*` when their // return type implements `Future`. let nested = vec![ @@ -453,11 +466,11 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc .rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()])) .upcast(tcx), ]; - let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None); + let future_output_def_id = tcx.require_lang_item(TraitSolverLangItem::FutureOutput); let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]); Ok(( bound_sig.rebind(AsyncCallableRelevantTypes { - tupled_inputs_ty: Ty::new_tup(tcx, sig.inputs()), + tupled_inputs_ty: Ty::new_tup(tcx, &sig.inputs()), output_coroutine_ty: sig.output(), coroutine_return_ty: future_output_ty, }), @@ -468,7 +481,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc let args = args.as_closure(); let bound_sig = args.sig(); let sig = bound_sig.skip_binder(); - let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None); + let future_trait_def_id = tcx.require_lang_item(TraitSolverLangItem::Future); // `Closure`s only implement `AsyncFn*` when their return type // implements `Future`. let mut nested = vec![ @@ -486,7 +499,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc } } else { let async_fn_kind_trait_def_id = - tcx.require_lang_item(LangItem::AsyncFnKindHelper, None); + tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper); // When we don't know the closure kind (and therefore also the closure's upvars, // which are computed at the same time), we must delay the computation of the // generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait @@ -504,7 +517,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc ); } - let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None); + let future_output_def_id = tcx.require_lang_item(TraitSolverLangItem::FutureOutput); let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]); Ok(( bound_sig.rebind(AsyncCallableRelevantTypes { @@ -542,21 +555,21 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<'tc ty::Bound(..) | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("unexpected type `{self_ty}`") + panic!("unexpected type `{self_ty:?}`") } } } /// Given a coroutine-closure, project to its returned coroutine when we are *certain* /// that the closure's kind is compatible with the goal. -fn coroutine_closure_to_certain_coroutine<'tcx>( - tcx: TyCtxt<'tcx>, +fn coroutine_closure_to_certain_coroutine( + tcx: I, goal_kind: ty::ClosureKind, - goal_region: ty::Region<'tcx>, - def_id: DefId, - args: ty::CoroutineClosureArgs>, - sig: ty::CoroutineClosureSignature>, -) -> Ty<'tcx> { + goal_region: I::Region, + def_id: I::DefId, + args: ty::CoroutineClosureArgs, + sig: ty::CoroutineClosureSignature, +) -> I::Ty { sig.to_coroutine_given_kind_and_upvars( tcx, args.parent_args(), @@ -573,20 +586,20 @@ fn coroutine_closure_to_certain_coroutine<'tcx>( /// yet what the closure's upvars are. /// /// Note that we do not also push a `AsyncFnKindHelper` goal here. -fn coroutine_closure_to_ambiguous_coroutine<'tcx>( - tcx: TyCtxt<'tcx>, +fn coroutine_closure_to_ambiguous_coroutine( + tcx: I, goal_kind: ty::ClosureKind, - goal_region: ty::Region<'tcx>, - def_id: DefId, - args: ty::CoroutineClosureArgs>, - sig: ty::CoroutineClosureSignature>, -) -> Ty<'tcx> { - let upvars_projection_def_id = tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None); + goal_region: I::Region, + def_id: I::DefId, + args: ty::CoroutineClosureArgs, + sig: ty::CoroutineClosureSignature, +) -> I::Ty { + let upvars_projection_def_id = tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindUpvars); let tupled_upvars_ty = Ty::new_projection( tcx, upvars_projection_def_id, [ - ty::GenericArg::from(args.kind_ty()), + I::GenericArg::from(args.kind_ty()), Ty::from_closure_kind(tcx, goal_kind).into(), goal_region.into(), sig.tupled_inputs_ty.into(), @@ -643,41 +656,44 @@ fn coroutine_closure_to_ambiguous_coroutine<'tcx>( // This is unsound in general and once that is fixed, we don't need to // normalize eagerly here. See https://github.com/lcnr/solver-woes/issues/9 // for more details. -pub(in crate::solve) fn predicates_for_object_candidate<'tcx>( - ecx: &EvalCtxt<'_, InferCtxt<'tcx>>, - param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::TraitRef<'tcx>, - object_bound: &'tcx ty::List>, -) -> Vec>> { +pub(in crate::solve) fn predicates_for_object_candidate( + ecx: &EvalCtxt<'_, Infcx>, + param_env: I::ParamEnv, + trait_ref: ty::TraitRef, + object_bounds: I::BoundExistentialPredicates, +) -> Vec> +where + Infcx: InferCtxtLike, + I: Interner, +{ let tcx = ecx.interner(); let mut requirements = vec![]; - requirements.extend( - tcx.super_predicates_of(trait_ref.def_id).instantiate(tcx, trait_ref.args).predicates, - ); - for item in tcx.associated_items(trait_ref.def_id).in_definition_order() { - // FIXME(associated_const_equality): Also add associated consts to - // the requirements here. - if item.kind == ty::AssocKind::Type { - // associated types that require `Self: Sized` do not show up in the built-in - // implementation of `Trait for dyn Trait`, and can be dropped here. - if tcx.generics_require_sized_self(item.def_id) { - continue; - } - - requirements - .extend(tcx.item_bounds(item.def_id).iter_instantiated(tcx, trait_ref.args)); + requirements + .extend(tcx.super_predicates_of(trait_ref.def_id).iter_instantiated(tcx, &trait_ref.args)); + + // FIXME(associated_const_equality): Also add associated consts to + // the requirements here. + for associated_type_def_id in tcx.associated_type_def_ids(trait_ref.def_id) { + // associated types that require `Self: Sized` do not show up in the built-in + // implementation of `Trait for dyn Trait`, and can be dropped here. + if tcx.generics_require_sized_self(associated_type_def_id) { + continue; } + + requirements.extend( + tcx.item_bounds(associated_type_def_id).iter_instantiated(tcx, &trait_ref.args), + ); } let mut replace_projection_with = FxHashMap::default(); - for bound in object_bound { + for bound in object_bounds { if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() { let proj = proj.with_self_ty(tcx, trait_ref.self_ty()); let old_ty = replace_projection_with.insert(proj.def_id(), bound.rebind(proj)); assert_eq!( old_ty, None, - "{} has two generic parameters: {} and {}", + "{:?} has two generic parameters: {:?} and {:?}", proj.projection_term, proj.term, old_ty.unwrap() @@ -696,20 +712,22 @@ pub(in crate::solve) fn predicates_for_object_candidate<'tcx>( .collect() } -struct ReplaceProjectionWith<'a, 'tcx> { - ecx: &'a EvalCtxt<'a, InferCtxt<'tcx>>, - param_env: ty::ParamEnv<'tcx>, - mapping: FxHashMap>, - nested: Vec>>, +struct ReplaceProjectionWith<'a, Infcx: InferCtxtLike, I: Interner> { + ecx: &'a EvalCtxt<'a, Infcx>, + param_env: I::ParamEnv, + mapping: FxHashMap>>, + nested: Vec>, } -impl<'tcx> TypeFolder> for ReplaceProjectionWith<'_, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { +impl, I: Interner> TypeFolder + for ReplaceProjectionWith<'_, Infcx, I> +{ + fn interner(&self) -> I { self.ecx.interner() } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Alias(ty::Projection, alias_ty) = *ty.kind() + fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { + if let ty::Alias(ty::Projection, alias_ty) = ty.kind() && let Some(replacement) = self.mapping.get(&alias_ty.def_id) { // We may have a case where our object type's projection bound is higher-ranked, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 43013a01069e5..860c580374d13 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -1,9 +1,6 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; -use rustc_infer::infer::at::ToTrace; -use rustc_infer::infer::{ - BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt, -}; +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::solve::{MaybeCause, NestedNormalizationGoals}; use rustc_infer::traits::ObligationCause; @@ -15,11 +12,13 @@ use rustc_middle::traits::solve::{ use rustc_middle::ty::AliasRelationDirection; use rustc_middle::ty::TypeFolder; use rustc_middle::ty::{ - self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, + self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, }; use rustc_span::DUMMY_SP; use rustc_type_ir::fold::TypeSuperFoldable; +use rustc_type_ir::inherent::*; +use rustc_type_ir::relate::Relate; +use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_type_ir::{self as ir, CanonicalVarValues, Interner}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use std::ops::ControlFlow; @@ -456,28 +455,6 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { } } - #[instrument(level = "trace", skip(self))] - pub(super) fn add_normalizes_to_goal(&mut self, mut goal: Goal<'tcx, ty::NormalizesTo<'tcx>>) { - goal.predicate = goal - .predicate - .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env }); - self.inspect.add_normalizes_to_goal(self.infcx, self.max_input_universe, goal); - self.nested_goals.normalizes_to_goals.push(goal); - } - - #[instrument(level = "debug", skip(self))] - pub(super) fn add_goal( - &mut self, - source: GoalSource, - mut goal: Goal<'tcx, ty::Predicate<'tcx>>, - ) { - goal.predicate = goal - .predicate - .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env }); - self.inspect.add_goal(self.infcx, self.max_input_universe, source, goal); - self.nested_goals.goals.push((source, goal)); - } - // Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning // the certainty of all the goals. #[instrument(level = "trace", skip(self))] @@ -600,27 +577,61 @@ impl, I: Interner> EvalCtxt<'_, Infcx> { pub(super) fn interner(&self) -> I { self.infcx.interner() } -} -impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { - pub(super) fn next_ty_infer(&mut self) -> Ty<'tcx> { - let ty = self.infcx.next_ty_var(DUMMY_SP); + #[instrument(level = "trace", skip(self))] + pub(super) fn add_normalizes_to_goal( + &mut self, + mut goal: ir::solve::Goal>, + ) { + goal.predicate = goal + .predicate + .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env }); + self.inspect.add_normalizes_to_goal(self.infcx, self.max_input_universe, goal); + self.nested_goals.normalizes_to_goals.push(goal); + } + + #[instrument(level = "debug", skip(self))] + pub(super) fn add_goal( + &mut self, + source: GoalSource, + mut goal: ir::solve::Goal, + ) { + goal.predicate = goal + .predicate + .fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env }); + self.inspect.add_goal(self.infcx, self.max_input_universe, source, goal); + self.nested_goals.goals.push((source, goal)); + } + + #[instrument(level = "trace", skip(self, goals))] + pub(super) fn add_goals( + &mut self, + source: GoalSource, + goals: impl IntoIterator>, + ) { + for goal in goals { + self.add_goal(source, goal); + } + } + + pub(super) fn next_ty_infer(&mut self) -> I::Ty { + let ty = self.infcx.next_ty_infer(); self.inspect.add_var_value(ty); ty } - pub(super) fn next_const_infer(&mut self) -> ty::Const<'tcx> { - let ct = self.infcx.next_const_var(DUMMY_SP); + pub(super) fn next_const_infer(&mut self) -> I::Const { + let ct = self.infcx.next_const_infer(); self.inspect.add_var_value(ct); ct } /// Returns a ty infer or a const infer depending on whether `kind` is a `Ty` or `Const`. /// If `kind` is an integer inference variable this will still return a ty infer var. - pub(super) fn next_term_infer_of_kind(&mut self, kind: ty::Term<'tcx>) -> ty::Term<'tcx> { - match kind.unpack() { - ty::TermKind::Ty(_) => self.next_ty_infer().into(), - ty::TermKind::Const(_) => self.next_const_infer().into(), + pub(super) fn next_term_infer_of_kind(&mut self, kind: I::Term) -> I::Term { + match kind.kind() { + ir::TermKind::Ty(_) => self.next_ty_infer().into(), + ir::TermKind::Const(_) => self.next_const_infer().into(), } } @@ -631,18 +642,18 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { #[instrument(level = "trace", skip(self), ret)] pub(super) fn term_is_fully_unconstrained( &self, - goal: Goal<'tcx, ty::NormalizesTo<'tcx>>, + goal: ir::solve::Goal>, ) -> bool { - let universe_of_term = match goal.predicate.term.unpack() { - ty::TermKind::Ty(ty) => { - if let &ty::Infer(ty::TyVar(vid)) = ty.kind() { + let universe_of_term = match goal.predicate.term.kind() { + ir::TermKind::Ty(ty) => { + if let ir::Infer(ir::TyVar(vid)) = ty.kind() { self.infcx.universe_of_ty(vid).unwrap() } else { return false; } } - ty::TermKind::Const(ct) => { - if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() { + ir::TermKind::Const(ct) => { + if let ir::ConstKind::Infer(ir::InferConst::Var(vid)) = ct.kind() { self.infcx.universe_of_ct(vid).unwrap() } else { return false; @@ -650,14 +661,14 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { } }; - struct ContainsTermOrNotNameable<'a, 'tcx> { - term: ty::Term<'tcx>, - universe_of_term: ty::UniverseIndex, - infcx: &'a InferCtxt<'tcx>, + struct ContainsTermOrNotNameable<'a, Infcx: InferCtxtLike, I: Interner> { + term: I::Term, + universe_of_term: ir::UniverseIndex, + infcx: &'a Infcx, } - impl<'a, 'tcx> ContainsTermOrNotNameable<'a, 'tcx> { - fn check_nameable(&self, universe: ty::UniverseIndex) -> ControlFlow<()> { + impl, I: Interner> ContainsTermOrNotNameable<'_, Infcx, I> { + fn check_nameable(&self, universe: ir::UniverseIndex) -> ControlFlow<()> { if self.universe_of_term.can_name(universe) { ControlFlow::Continue(()) } else { @@ -666,21 +677,23 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { } } - impl<'tcx> TypeVisitor> for ContainsTermOrNotNameable<'_, 'tcx> { + impl, I: Interner> TypeVisitor + for ContainsTermOrNotNameable<'_, Infcx, I> + { type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { - match *t.kind() { - ty::Infer(ty::TyVar(vid)) => { - if let ty::TermKind::Ty(term) = self.term.unpack() - && let Some(term_vid) = term.ty_vid() - && self.infcx.root_var(vid) == self.infcx.root_var(term_vid) + fn visit_ty(&mut self, t: I::Ty) -> Self::Result { + match t.kind() { + ir::Infer(ir::TyVar(vid)) => { + if let ir::TermKind::Ty(term) = self.term.kind() + && let ir::Infer(ir::TyVar(term_vid)) = term.kind() + && self.infcx.root_ty_var(vid) == self.infcx.root_ty_var(term_vid) { ControlFlow::Break(()) } else { self.check_nameable(self.infcx.universe_of_ty(vid).unwrap()) } } - ty::Placeholder(p) => self.check_nameable(p.universe), + ir::Placeholder(p) => self.check_nameable(p.universe()), _ => { if t.has_non_region_infer() || t.has_placeholders() { t.super_visit_with(self) @@ -691,11 +704,11 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { } } - fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result { + fn visit_const(&mut self, c: I::Const) -> Self::Result { match c.kind() { - ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { - if let ty::TermKind::Const(term) = self.term.unpack() - && let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind() + ir::ConstKind::Infer(ir::InferConst::Var(vid)) => { + if let ir::TermKind::Const(term) = self.term.kind() + && let ir::ConstKind::Infer(ir::InferConst::Var(term_vid)) = term.kind() && self.infcx.root_const_var(vid) == self.infcx.root_const_var(term_vid) { ControlFlow::Break(()) @@ -703,7 +716,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { self.check_nameable(self.infcx.universe_of_ct(vid).unwrap()) } } - ty::ConstKind::Placeholder(p) => self.check_nameable(p.universe), + ir::ConstKind::Placeholder(p) => self.check_nameable(p.universe()), _ => { if c.has_non_region_infer() || c.has_placeholders() { c.super_visit_with(self) @@ -725,23 +738,13 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { } #[instrument(level = "trace", skip(self, param_env), ret)] - pub(super) fn eq>( + pub(super) fn eq>( &mut self, - param_env: ty::ParamEnv<'tcx>, + param_env: I::ParamEnv, lhs: T, rhs: T, ) -> Result<(), NoSolution> { - self.infcx - .at(&ObligationCause::dummy(), param_env) - // New solver ignores DefineOpaqueTypes, so choose Yes for consistency - .eq(DefineOpaqueTypes::Yes, lhs, rhs) - .map(|InferOk { value: (), obligations }| { - self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into())); - }) - .map_err(|e| { - trace!(?e, "failed to equate"); - NoSolution - }) + self.relate(param_env, lhs, ir::Variance::Invariant, rhs) } /// This should be used when relating a rigid alias with another type. @@ -752,10 +755,10 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { #[instrument(level = "trace", skip(self, param_env), ret)] pub(super) fn relate_rigid_alias_non_alias( &mut self, - param_env: ty::ParamEnv<'tcx>, - alias: ty::AliasTerm<'tcx>, - variance: ty::Variance, - term: ty::Term<'tcx>, + param_env: I::ParamEnv, + alias: ir::AliasTerm, + variance: ir::Variance, + term: I::Term, ) -> Result<(), NoSolution> { // NOTE: this check is purely an optimization, the structural eq would // always fail if the term is not an inference variable. @@ -770,12 +773,10 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { // Alternatively we could modify `Equate` for this case by adding another // variant to `StructurallyRelateAliases`. let identity_args = self.fresh_args_for_item(alias.def_id); - let rigid_ctor = ty::AliasTerm::new(tcx, alias.def_id, identity_args); + let rigid_ctor = ir::AliasTerm::new(tcx, alias.def_id, identity_args); let ctor_term = rigid_ctor.to_term(tcx); - let InferOk { value: (), obligations } = self - .infcx - .at(&ObligationCause::dummy(), param_env) - .eq_structurally_relating_aliases(term, ctor_term)?; + let obligations = + self.infcx.eq_structurally_relating_aliases(param_env, term, ctor_term)?; debug_assert!(obligations.is_empty()); self.relate(param_env, alias, variance, rigid_ctor) } else { @@ -787,58 +788,38 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { /// unconstrained "return value" or when we're sure that all aliases in /// the types are rigid. #[instrument(level = "trace", skip(self, param_env), ret)] - pub(super) fn eq_structurally_relating_aliases>( + pub(super) fn eq_structurally_relating_aliases>( &mut self, - param_env: ty::ParamEnv<'tcx>, + param_env: I::ParamEnv, lhs: T, rhs: T, ) -> Result<(), NoSolution> { - let cause = ObligationCause::dummy(); - let InferOk { value: (), obligations } = - self.infcx.at(&cause, param_env).eq_structurally_relating_aliases(lhs, rhs)?; - assert!(obligations.is_empty()); + let result = self.infcx.eq_structurally_relating_aliases(param_env, lhs, rhs)?; + assert_eq!(result, vec![]); Ok(()) } #[instrument(level = "trace", skip(self, param_env), ret)] - pub(super) fn sub>( + pub(super) fn sub>( &mut self, - param_env: ty::ParamEnv<'tcx>, + param_env: I::ParamEnv, sub: T, sup: T, ) -> Result<(), NoSolution> { - self.infcx - .at(&ObligationCause::dummy(), param_env) - // New solver ignores DefineOpaqueTypes, so choose Yes for consistency - .sub(DefineOpaqueTypes::Yes, sub, sup) - .map(|InferOk { value: (), obligations }| { - self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into())); - }) - .map_err(|e| { - trace!(?e, "failed to subtype"); - NoSolution - }) + self.relate(param_env, sub, ir::Variance::Covariant, sup) } #[instrument(level = "trace", skip(self, param_env), ret)] - pub(super) fn relate>( + pub(super) fn relate>( &mut self, - param_env: ty::ParamEnv<'tcx>, + param_env: I::ParamEnv, lhs: T, - variance: ty::Variance, + variance: ir::Variance, rhs: T, ) -> Result<(), NoSolution> { - self.infcx - .at(&ObligationCause::dummy(), param_env) - // New solver ignores DefineOpaqueTypes, so choose Yes for consistency - .relate(DefineOpaqueTypes::Yes, lhs, variance, rhs) - .map(|InferOk { value: (), obligations }| { - self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into())); - }) - .map_err(|e| { - trace!(?e, "failed to relate"); - NoSolution - }) + let goals = self.infcx.relate(param_env, lhs, variance, rhs)?; + self.add_goals(GoalSource::Misc, goals); + Ok(()) } /// Equates two values returning the nested goals without adding them @@ -847,58 +828,47 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { /// If possible, try using `eq` instead which automatically handles nested /// goals correctly. #[instrument(level = "trace", skip(self, param_env), ret)] - pub(super) fn eq_and_get_goals>( + pub(super) fn eq_and_get_goals>( &self, - param_env: ty::ParamEnv<'tcx>, + param_env: I::ParamEnv, lhs: T, rhs: T, - ) -> Result>>, NoSolution> { - self.infcx - .at(&ObligationCause::dummy(), param_env) - // New solver ignores DefineOpaqueTypes, so choose Yes for consistency - .eq(DefineOpaqueTypes::Yes, lhs, rhs) - .map(|InferOk { value: (), obligations }| { - obligations.into_iter().map(|o| o.into()).collect() - }) - .map_err(|e| { - trace!(?e, "failed to equate"); - NoSolution - }) + ) -> Result>, NoSolution> { + self.infcx.relate(param_env, lhs, ir::Variance::Invariant, rhs) } - pub(super) fn instantiate_binder_with_infer> + Copy>( + pub(super) fn instantiate_binder_with_infer + Copy>( &self, - value: ty::Binder<'tcx, T>, + value: ir::Binder, ) -> T { - self.infcx.instantiate_binder_with_fresh_vars( - DUMMY_SP, - BoundRegionConversionTime::HigherRankedType, - value, - ) + self.infcx.instantiate_binder_with_infer(value) } - pub(super) fn enter_forall> + Copy, U>( + pub(super) fn enter_forall + Copy, U>( &self, - value: ty::Binder<'tcx, T>, + value: ir::Binder, f: impl FnOnce(T) -> U, ) -> U { self.infcx.enter_forall(value, f) } + pub(super) fn resolve_vars_if_possible(&self, value: T) -> T where - T: TypeFoldable>, + T: TypeFoldable, { self.infcx.resolve_vars_if_possible(value) } - pub(super) fn fresh_args_for_item(&mut self, def_id: DefId) -> ty::GenericArgsRef<'tcx> { - let args = self.infcx.fresh_args_for_item(DUMMY_SP, def_id); + pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs { + let args = self.infcx.fresh_args_for_item(def_id); for arg in args { self.inspect.add_var_value(arg); } args } +} +impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { pub(super) fn register_ty_outlives(&self, ty: Ty<'tcx>, lt: ty::Region<'tcx>) { self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy()); } @@ -1096,28 +1066,36 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { /// /// This is a performance optimization to more eagerly detect cycles during trait /// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs. -struct ReplaceAliasWithInfer<'me, 'a, 'tcx> { - ecx: &'me mut EvalCtxt<'a, InferCtxt<'tcx>>, - param_env: ty::ParamEnv<'tcx>, +struct ReplaceAliasWithInfer<'me, 'a, Infcx, I> +where + Infcx: InferCtxtLike, + I: Interner, +{ + ecx: &'me mut EvalCtxt<'a, Infcx>, + param_env: I::ParamEnv, } -impl<'tcx> TypeFolder> for ReplaceAliasWithInfer<'_, '_, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { +impl TypeFolder for ReplaceAliasWithInfer<'_, '_, Infcx, I> +where + Infcx: InferCtxtLike, + I: Interner, +{ + fn interner(&self) -> I { self.ecx.interner() } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match *ty.kind() { - ty::Alias(..) if !ty.has_escaping_bound_vars() => { + fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { + match ty.kind() { + ir::Alias(..) if !ty.has_escaping_bound_vars() => { let infer_ty = self.ecx.next_ty_infer(); - let normalizes_to = ty::PredicateKind::AliasRelate( + let normalizes_to = ir::PredicateKind::AliasRelate( ty.into(), infer_ty.into(), AliasRelationDirection::Equate, ); self.ecx.add_goal( GoalSource::Misc, - Goal::new(self.interner(), self.param_env, normalizes_to), + ir::solve::Goal::new(self.interner(), self.param_env, normalizes_to), ); infer_ty } @@ -1125,18 +1103,18 @@ impl<'tcx> TypeFolder> for ReplaceAliasWithInfer<'_, '_, 'tcx> { } } - fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + fn fold_const(&mut self, ct: I::Const) -> I::Const { match ct.kind() { - ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => { + ir::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => { let infer_ct = self.ecx.next_const_infer(); - let normalizes_to = ty::PredicateKind::AliasRelate( + let normalizes_to = ir::PredicateKind::AliasRelate( ct.into(), infer_ct.into(), AliasRelationDirection::Equate, ); self.ecx.add_goal( GoalSource::Misc, - Goal::new(self.interner(), self.param_env, normalizes_to), + ir::solve::Goal::new(self.interner(), self.param_env, normalizes_to), ); infer_ct } @@ -1144,7 +1122,7 @@ impl<'tcx> TypeFolder> for ReplaceAliasWithInfer<'_, '_, 'tcx> { } } - fn fold_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + fn fold_predicate(&mut self, predicate: I::Predicate) -> I::Predicate { if predicate.allow_normalization() { predicate.super_fold_with(self) } else { predicate } } } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs index 84c04900ae484..35750598bc740 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs @@ -34,10 +34,11 @@ use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; /// trees. At the end of trait solving `ProofTreeBuilder::finalize` /// is called to recursively convert the whole structure to a /// finished proof tree. -pub(in crate::solve) struct ProofTreeBuilder< +pub(in crate::solve) struct ProofTreeBuilder::Interner> +where Infcx: InferCtxtLike, - I: Interner = ::Interner, -> { + I: Interner, +{ _infcx: PhantomData, state: Option>>, } diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index c47b01949641b..fdcf4ff11e468 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -235,17 +235,6 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { } impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { - #[instrument(level = "trace", skip(self, goals))] - fn add_goals( - &mut self, - source: GoalSource, - goals: impl IntoIterator>>, - ) { - for goal in goals { - self.add_goal(source, goal); - } - } - /// Try to merge multiple possible ways to prove a goal, if that is not possible returns `None`. /// /// In this case we tend to flounder and return ambiguity by calling `[EvalCtxt::flounder]`. diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 787f08a084ee6..50253d815283a 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::NormalizesTo; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{TypeVisitableExt, Upcast}; use rustc_middle::{bug, span_bug}; -use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP}; +use rustc_span::{ErrorGuaranteed, DUMMY_SP}; mod anon_const; mod inherent; @@ -719,13 +719,16 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { let coroutine = args.as_coroutine(); - let name = tcx.associated_item(goal.predicate.def_id()).name; - let term = if name == sym::Return { + let lang_items = tcx.lang_items(); + let term = if Some(goal.predicate.def_id()) == lang_items.coroutine_return() { coroutine.return_ty().into() - } else if name == sym::Yield { + } else if Some(goal.predicate.def_id()) == lang_items.coroutine_yield() { coroutine.yield_ty().into() } else { - bug!("unexpected associated item `<{self_ty} as Coroutine>::{name}`") + bug!( + "unexpected associated item `<{self_ty} as Coroutine>::{}`", + tcx.item_name(goal.predicate.def_id()) + ) }; Self::probe_and_consider_implied_clause( diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 2c9cb79664b34..32409e13842e0 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1373,15 +1373,16 @@ fn confirm_coroutine_candidate<'cx, 'tcx>( coroutine_sig, ); - let name = tcx.associated_item(obligation.predicate.def_id).name; - let ty = if name == sym::Return { + let lang_items = tcx.lang_items(); + let ty = if Some(obligation.predicate.def_id) == lang_items.coroutine_return() { return_ty - } else if name == sym::Yield { + } else if Some(obligation.predicate.def_id) == lang_items.coroutine_yield() { yield_ty } else { span_bug!( tcx.def_span(obligation.predicate.def_id), - "unexpected associated type: `Coroutine::{name}`" + "unexpected associated type: `Coroutine::{}`", + tcx.item_name(obligation.predicate.def_id), ); }; diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs index 24e10722448cc..92a717a0d9efb 100644 --- a/compiler/rustc_type_ir/src/infcx.rs +++ b/compiler/rustc_type_ir/src/infcx.rs @@ -1,23 +1,75 @@ -use crate::{ConstVid, EffectVid, FloatVid, IntVid, Interner, RegionVid, TyVid, UniverseIndex}; +use crate::fold::TypeFoldable; +use crate::relate::Relate; +use crate::solve::{Goal, NoSolution}; +use crate::{self as ty, Interner}; -pub trait InferCtxtLike { +pub trait InferCtxtLike: Sized { type Interner: Interner; fn interner(&self) -> Self::Interner; - fn universe_of_ty(&self, ty: TyVid) -> Option; - fn universe_of_lt(&self, lt: RegionVid) -> Option; - fn universe_of_ct(&self, ct: ConstVid) -> Option; + fn universe_of_ty(&self, ty: ty::TyVid) -> Option; + fn universe_of_lt(&self, lt: ty::RegionVid) -> Option; + fn universe_of_ct(&self, ct: ty::ConstVid) -> Option; - fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> ::Ty; - fn opportunistic_resolve_int_var(&self, vid: IntVid) -> ::Ty; - fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> ::Ty; - fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> ::Const; + fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid; + fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid; + + fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> ::Ty; + fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> ::Ty; + fn opportunistic_resolve_float_var( + &self, + vid: ty::FloatVid, + ) -> ::Ty; + fn opportunistic_resolve_ct_var( + &self, + vid: ty::ConstVid, + ) -> ::Const; fn opportunistic_resolve_effect_var( &self, - vid: EffectVid, + vid: ty::EffectVid, ) -> ::Const; - fn opportunistic_resolve_lt_var(&self, vid: RegionVid) -> ::Region; + fn opportunistic_resolve_lt_var( + &self, + vid: ty::RegionVid, + ) -> ::Region; fn defining_opaque_types(&self) -> ::DefiningOpaqueTypes; + + fn next_ty_infer(&self) -> ::Ty; + fn next_const_infer(&self) -> ::Const; + fn fresh_args_for_item( + &self, + def_id: ::DefId, + ) -> ::GenericArgs; + + fn instantiate_binder_with_infer + Copy>( + &self, + value: ty::Binder, + ) -> T; + + fn enter_forall + Copy, U>( + &self, + value: ty::Binder, + f: impl FnOnce(T) -> U, + ) -> U; + + fn relate>( + &self, + param_env: ::ParamEnv, + lhs: T, + variance: ty::Variance, + rhs: T, + ) -> Result::Predicate>>, NoSolution>; + + fn eq_structurally_relating_aliases>( + &self, + param_env: ::ParamEnv, + lhs: T, + rhs: T, + ) -> Result::Predicate>>, NoSolution>; + + fn resolve_vars_if_possible(&self, value: T) -> T + where + T: TypeFoldable; } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 2fc765f1c8fae..6b84592978a26 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -29,6 +29,8 @@ pub trait Ty>: { fn new_bool(interner: I) -> Self; + fn new_u8(interner: I) -> Self; + fn new_infer(interner: I, var: ty::InferTy) -> Self; fn new_var(interner: I, var: ty::TyVid) -> Self; @@ -39,6 +41,18 @@ pub trait Ty>: fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy) -> Self; + fn new_projection( + interner: I, + def_id: I::DefId, + args: impl IntoIterator>, + ) -> Self { + Ty::new_alias( + interner, + ty::AliasTyKind::Projection, + ty::AliasTy::new(interner, def_id, args), + ) + } + fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self; fn new_adt(interner: I, adt_def: I::AdtDef, args: I::GenericArgs) -> Self; @@ -75,6 +89,12 @@ pub trait Ty>: It: Iterator, T: CollectAndApply; + fn new_fn_def(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self; + + fn new_fn_ptr(interner: I, sig: ty::Binder>) -> Self; + + fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self; + fn tuple_fields(self) -> I::Tys; fn to_opt_closure_kind(self) -> Option; @@ -83,11 +103,29 @@ pub trait Ty>: fn from_coroutine_closure_kind(interner: I, kind: ty::ClosureKind) -> Self; - fn new_fn_def(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self; - - fn new_fn_ptr(interner: I, sig: ty::Binder>) -> Self; - - fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self; + fn is_ty_var(self) -> bool { + matches!(self.kind(), ty::Infer(ty::TyVar(_))) + } + + fn fn_sig(self, interner: I) -> ty::Binder> { + match self.kind() { + ty::FnPtr(sig) => sig, + ty::FnDef(def_id, args) => interner.fn_sig(def_id).instantiate(interner, &args), + ty::Error(_) => { + // ignore errors (#54954) + ty::Binder::dummy(ty::FnSig { + inputs_and_output: Default::default(), + c_variadic: false, + safety: I::Safety::safe(), + abi: I::Abi::rust(), + }) + } + ty::Closure(..) => panic!( + "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`", + ), + _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self), + } + } } pub trait Tys>: @@ -103,12 +141,16 @@ pub trait Tys>: fn split_inputs_and_output(self) -> (I::FnInputTys, I::Ty); } -pub trait Abi>: Copy + Debug + Hash + Eq + TypeVisitable { +pub trait Abi>: Copy + Debug + Hash + Eq + Relate { + fn rust() -> Self; + /// Whether this ABI is `extern "Rust"`. fn is_rust(self) -> bool; } -pub trait Safety>: Copy + Debug + Hash + Eq + TypeVisitable { +pub trait Safety>: Copy + Debug + Hash + Eq + Relate { + fn safe() -> Self; + fn is_safe(self) -> bool; fn prefix_str(self) -> &'static str; @@ -122,7 +164,6 @@ pub trait Region>: + Into + IntoKind> + Flags - + TypeVisitable + Relate { fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundRegion) -> Self; @@ -158,12 +199,57 @@ pub trait Const>: fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst) -> Self; fn new_expr(interner: I, expr: I::ExprConst) -> Self; + + fn is_ct_var(self) -> bool { + matches!(self.kind(), ty::ConstKind::Infer(ty::InferConst::Var(_))) + } } pub trait GenericsOf> { fn count(&self) -> usize; } +pub trait GenericArg>: + Copy + + Debug + + Hash + + Eq + + IntoKind> + + TypeVisitable + + Relate + + From + + From + + From +{ +} + +pub trait Term>: + Copy + Debug + Hash + Eq + IntoKind> + TypeFoldable + Relate +{ + fn as_type(&self) -> Option { + if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None } + } + + fn expect_type(&self) -> I::Ty { + self.as_type().expect("expected a type, but found a const") + } + + fn as_const(&self) -> Option { + if let ty::TermKind::Const(c) = self.kind() { Some(c) } else { None } + } + + fn expect_const(&self) -> I::Const { + self.as_const().expect("expected a const, but found a type") + } + + fn is_infer(self) -> bool { + match self.kind() { + ty::TermKind::Ty(ty) => ty.is_ty_var(), + ty::TermKind::Const(ct) => ct.is_ct_var(), + } + } +} + pub trait GenericArgs>: Copy + Debug @@ -172,7 +258,6 @@ pub trait GenericArgs>: + IntoIterator + Deref> + Default - + TypeFoldable + Relate { fn type_at(self, i: usize) -> I::Ty; @@ -188,6 +273,16 @@ pub trait GenericArgs>: fn split_closure_args(self) -> ty::ClosureArgsParts; fn split_coroutine_closure_args(self) -> ty::CoroutineClosureArgsParts; fn split_coroutine_args(self) -> ty::CoroutineArgsParts; + + fn as_closure(self) -> ty::ClosureArgs { + ty::ClosureArgs { args: self } + } + fn as_coroutine_closure(self) -> ty::CoroutineClosureArgs { + ty::CoroutineClosureArgs { args: self } + } + fn as_coroutine(self) -> ty::CoroutineArgs { + ty::CoroutineArgs { args: self } + } } pub trait Predicate>: @@ -198,9 +293,20 @@ pub trait Predicate>: + TypeSuperVisitable + TypeSuperFoldable + Flags + + UpcastFrom> + + UpcastFrom>> + + UpcastFrom> + + UpcastFrom>> + + UpcastFrom + UpcastFrom> + + UpcastFrom> + + UpcastFrom>> + + IntoKind>> { fn is_coinductive(self, interner: I) -> bool; + + // FIXME: Eventually uplift the impl out of rustc and make this defaulted. + fn allow_normalization(self) -> bool; } pub trait Clause>: @@ -208,6 +314,7 @@ pub trait Clause>: + Debug + Hash + Eq + + TypeFoldable // FIXME: Remove these, uplift the `Upcast` impls. + UpcastFrom>> + UpcastFrom>> @@ -242,8 +349,17 @@ pub trait ParamLike { pub trait AdtDef: Copy + Debug + Hash + Eq { fn def_id(self) -> I::DefId; + + fn is_phantom_data(self) -> bool; + + // FIXME: perhaps use `all_fields` and expose `FieldDef`. + fn all_field_tys(self, interner: I) -> ty::EarlyBinder>; + + fn sized_constraint(self, interner: I) -> Option>; } pub trait Features: Copy { fn generic_const_exprs(self) -> bool; + + fn coroutine_clone(self) -> bool; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index b7f412ecb8ea9..a2b71e1fc2575 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -1,3 +1,4 @@ +use rustc_ast_ir::Movability; use smallvec::SmallVec; use std::fmt::Debug; use std::hash::Hash; @@ -6,6 +7,7 @@ use std::ops::Deref; use crate::fold::TypeFoldable; use crate::inherent::*; use crate::ir_print::IrPrint; +use crate::lang_items::TraitSolverLangItem; use crate::relate::Relate; use crate::solve::inspect::CanonicalGoalEvaluationStep; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; @@ -31,20 +33,8 @@ pub trait Interner: type GenericArgs: GenericArgs; type GenericArgsSlice: Copy + Debug + Hash + Eq + Deref; - type GenericArg: Copy - + Debug - + Hash - + Eq - + IntoKind> - + TypeVisitable - + Relate; - type Term: Copy - + Debug - + Hash - + Eq - + IntoKind> - + TypeFoldable - + Relate; + type GenericArg: GenericArg; + type Term: Term; type BoundVarKinds: Copy + Debug @@ -74,11 +64,16 @@ pub trait Interner: // Things stored inside of tys type ErrorGuaranteed: Copy + Debug + Hash + Eq; - type BoundExistentialPredicates: Copy + Debug + Hash + Eq + Relate; + type BoundExistentialPredicates: Copy + + Debug + + Hash + + Eq + + Relate + + IntoIterator>>; type AllocId: Copy + Debug + Hash + Eq; type Pat: Copy + Debug + Hash + Eq + Debug + Relate; - type Safety: Safety + TypeFoldable + Relate; - type Abi: Abi + TypeFoldable + Relate; + type Safety: Safety; + type Abi: Abi; // Kinds of consts type Const: Const; @@ -153,6 +148,38 @@ pub trait Interner: type Features: Features; fn features(self) -> Self::Features; + + fn bound_coroutine_hidden_types( + self, + def_id: Self::DefId, + ) -> impl IntoIterator>>; + + fn fn_sig( + self, + def_id: Self::DefId, + ) -> ty::EarlyBinder>>; + + fn coroutine_movability(self, def_id: Self::DefId) -> Movability; + + fn coroutine_for_closure(self, def_id: Self::DefId) -> Self::DefId; + + fn generics_require_sized_self(self, def_id: Self::DefId) -> bool; + + fn item_bounds( + self, + def_id: Self::DefId, + ) -> ty::EarlyBinder>; + + fn super_predicates_of( + self, + def_id: Self::DefId, + ) -> ty::EarlyBinder>; + + fn has_target_features(self, def_id: Self::DefId) -> bool; + + fn require_lang_item(self, lang_item: TraitSolverLangItem) -> Self::DefId; + + fn associated_type_def_ids(self, def_id: Self::DefId) -> impl IntoIterator; } /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` diff --git a/compiler/rustc_type_ir/src/lang_items.rs b/compiler/rustc_type_ir/src/lang_items.rs new file mode 100644 index 0000000000000..9a3b324fcd765 --- /dev/null +++ b/compiler/rustc_type_ir/src/lang_items.rs @@ -0,0 +1,8 @@ +/// Lang items used by the new trait solver. This can be mapped to whatever internal +/// representation of `LangItem`s used in the underlying compiler implementation. +pub enum TraitSolverLangItem { + Future, + FutureOutput, + AsyncFnKindHelper, + AsyncFnKindUpvars, +} diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index a76e278cc05d0..7f0c3df381daf 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -32,6 +32,7 @@ pub mod error; pub mod fold; pub mod inherent; pub mod ir_print; +pub mod lang_items; pub mod lift; pub mod relate; pub mod solve; diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index cd3534ecb1239..6b5054a9f0612 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -3043,8 +3043,7 @@ pub const unsafe fn copy(src: *const T, dst: *mut T, count: usize) { unsafe { ub_checks::assert_unsafe_precondition!( check_language_ub, - "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \ - and the specified memory ranges do not overlap", + "ptr::copy requires that both pointer arguments are aligned and non-null", ( src: *const () = src as *const (), dst: *mut () = dst as *mut (), diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 863f0d61df374..5956a08593ad4 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1059,7 +1059,7 @@ macro_rules! nonzero_integer_signedness_dependent_methods { unsafe { Self::new_unchecked(self.get().unchecked_add(other)) } } - /// Returns the smallest power of two greater than or equal to n. + /// Returns the smallest power of two greater than or equal to `self`. /// Checks for overflow and returns [`None`] /// if the next power of two is greater than the type’s maximum value. /// As a consequence, the result cannot wrap to zero. diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 1491c27372bfb..cdbd695008e86 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2830,7 +2830,7 @@ macro_rules! uint_impl { /// /// When return value overflows (i.e., `self > (1 << (N-1))` for type /// `uN`), it panics in debug mode and the return value is wrapped to 0 in - /// release mode (the only situation in which method can return 0). + /// release mode (the only situation in which this method can return 0). /// /// # Examples /// @@ -2851,7 +2851,7 @@ macro_rules! uint_impl { self.one_less_than_next_power_of_two() + 1 } - /// Returns the smallest power of two greater than or equal to `n`. If + /// Returns the smallest power of two greater than or equal to `self`. If /// the next power of two is greater than the type's maximum value, /// `None` is returned, otherwise the power of two is wrapped in `Some`. /// diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs index 6a6c5db1ab115..753f14c6b85ec 100644 --- a/library/core/src/ops/coroutine.rs +++ b/library/core/src/ops/coroutine.rs @@ -76,6 +76,7 @@ pub trait Coroutine { /// values which are allowed to be returned each time a coroutine yields. /// For example an iterator-as-a-coroutine would likely have this type as /// `T`, the type being iterated over. + #[cfg_attr(not(bootstrap), lang = "coroutine_yield")] type Yield; /// The type of value this coroutine returns. @@ -84,6 +85,7 @@ pub trait Coroutine { /// `return` statement or implicitly as the last expression of a coroutine /// literal. For example futures would use this as `Result` as it /// represents a completed future. + #[cfg_attr(not(bootstrap), lang = "coroutine_return")] type Return; /// Resumes the execution of this coroutine. diff --git a/library/std/src/process.rs b/library/std/src/process.rs index c926c89f7a97f..f351dab78dc1a 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -629,6 +629,25 @@ impl Command { /// .spawn() /// .expect("sh command failed to start"); /// ``` + /// + /// # Caveats + /// + /// [`Command::new`] is only intended to accept the path of the program. If you pass a program + /// path along with arguments like `Command::new("ls -l").spawn()`, it will try to search for + /// `ls -l` literally. The arguments need to be passed separately, such as via [`arg`] or + /// [`args`]. + /// + /// ```no_run + /// use std::process::Command; + /// + /// Command::new("ls") + /// .arg("-l") // arg passed separately + /// .spawn() + /// .expect("ls command failed to start"); + /// ``` + /// + /// [`arg`]: Self::arg + /// [`args`]: Self::args #[stable(feature = "process", since = "1.0.0")] pub fn new>(program: S) -> Command { Command { inner: imp::Command::new(program.as_ref()) } diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 2deb9168df2ab..b96e26dbb3aea 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -93,7 +93,7 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result>, Str return Ok(None); } - get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &vec!["rs"]) + get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &["rs"]) } #[derive(serde_derive::Deserialize)] diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 354eb2b600381..9268b335db7c2 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -149,12 +149,14 @@ impl Step for Miri { &[], ); miri.add_rustc_lib_path(builder); - // Forward arguments. miri.arg("--").arg("--target").arg(target.rustc_target_arg()); - miri.args(builder.config.args()); // miri tests need to know about the stage sysroot - miri.env("MIRI_SYSROOT", &miri_sysroot); + miri.arg("--sysroot").arg(miri_sysroot); + + // Forward arguments. This may contain further arguments to the program + // after another --, so this must be at the end. + miri.args(builder.config.args()); let mut miri = Command::from(miri); builder.run(&mut miri); diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 9f33e4312740f..b4d47cba7c5bc 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -495,7 +495,7 @@ impl Builder { Some(p) => p, None => return false, }; - pkg.target.get(&c.target).is_some() + pkg.target.contains_key(&c.target) }; extensions.retain(&has_component); components.retain(&has_component); diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index a3c857b0268c9..b4522de6897d4 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -21,7 +21,7 @@ fn output_result(cmd: &mut Command) -> Result { String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))? )); } - Ok(String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?) + String::from_utf8(output.stdout).map_err(|err| format!("{err:?}")) } /// Finds the remote for rust-lang/rust. @@ -64,18 +64,14 @@ pub fn rev_exists(rev: &str, git_dir: Option<&Path>) -> Result { match output.status.code() { Some(0) => Ok(true), Some(128) => Ok(false), - None => { - return Err(format!( - "git didn't exit properly: {}", - String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))? - )); - } - Some(code) => { - return Err(format!( - "git command exited with status code: {code}: {}", - String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))? - )); - } + None => Err(format!( + "git didn't exit properly: {}", + String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))? + )), + Some(code) => Err(format!( + "git command exited with status code: {code}: {}", + String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))? + )), } } @@ -96,7 +92,7 @@ pub fn updated_master_branch( } } - Err(format!("Cannot find any suitable upstream master branch")) + Err("Cannot find any suitable upstream master branch".to_owned()) } pub fn get_git_merge_base( @@ -118,7 +114,7 @@ pub fn get_git_merge_base( pub fn get_git_modified_files( config: &GitConfig<'_>, git_dir: Option<&Path>, - extensions: &Vec<&str>, + extensions: &[&str], ) -> Result>, String> { let merge_base = get_git_merge_base(config, git_dir)?; diff --git a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr index ce3b9495eb1ea..cd2031af1c6da 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6252.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6252.stderr @@ -4,9 +4,7 @@ error[E0412]: cannot find type `PhantomData` in this scope LL | _n: PhantomData, | ^^^^^^^^^^^ not found in this scope | -help: consider importing one of these items - | -LL + use core::marker::PhantomData; +help: consider importing this struct | LL + use std::marker::PhantomData; | diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index b0047770564c4..da7f03441e72f 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -582,7 +582,7 @@ impl TargetCfgs { name, Some( value - .strip_suffix("\"") + .strip_suffix('\"') .expect("key-value pair should be properly quoted"), ), ) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index cc972223f6dfb..ffc706d19a984 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -82,7 +82,7 @@ impl EarlyProps { panic!("errors encountered during EarlyProps parsing"); } - return props; + props } } @@ -382,7 +382,7 @@ impl TestProps { // Individual flags can be single-quoted to preserve spaces; see // . flags - .split("'") + .split('\'') .enumerate() .flat_map(|(i, f)| { if i % 2 == 1 { vec![f] } else { f.split_whitespace().collect() } @@ -613,7 +613,7 @@ impl TestProps { for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { if let Ok(val) = env::var(key) { - if self.exec_env.iter().find(|&&(ref x, _)| x == key).is_none() { + if !self.exec_env.iter().any(|&(ref x, _)| x == key) { self.exec_env.push(((*key).to_owned(), val)) } } @@ -991,7 +991,7 @@ pub(crate) fn check_directive(directive_ln: &str) -> CheckDirectiveResult<'_> { let trailing = post.trim().split_once(' ').map(|(pre, _)| pre).unwrap_or(post); let trailing_directive = { // 1. is the directive name followed by a space? (to exclude `:`) - matches!(directive_ln.get(directive_name.len()..), Some(s) if s.starts_with(" ")) + matches!(directive_ln.get(directive_name.len()..), Some(s) if s.starts_with(' ')) // 2. is what is after that directive also a directive (ex: "only-x86 only-arm") && KNOWN_DIRECTIVE_NAMES.contains(&trailing) } @@ -1363,7 +1363,7 @@ pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option { } let version = String::from_utf8(output.stdout).ok()?; for line in version.lines() { - if let Some(version) = line.split("LLVM version ").skip(1).next() { + if let Some(version) = line.split("LLVM version ").nth(1) { return extract_llvm_version(version); } } @@ -1394,7 +1394,7 @@ where let min = parse(min)?; let max = match max { - Some(max) if max.is_empty() => return None, + Some("") => return None, Some(max) => parse(max)?, _ => min, }; @@ -1466,12 +1466,12 @@ pub fn make_test_description( decision!(ignore_gdb(config, ln)); decision!(ignore_lldb(config, ln)); - if config.target == "wasm32-unknown-unknown" { - if config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS) { - decision!(IgnoreDecision::Ignore { - reason: "ignored on WASM as the run results cannot be checked there".into(), - }); - } + if config.target == "wasm32-unknown-unknown" + && config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS) + { + decision!(IgnoreDecision::Ignore { + reason: "ignored on WASM as the run results cannot be checked there".into(), + }); } should_fail |= config.parse_name_directive(ln, "should-fail"); diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index 510043e3bfd8f..522c52b1de2a7 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -58,7 +58,7 @@ pub(super) fn parse_cfg_name_directive<'a>( // Some of the matchers might be "" depending on what the target information is. To avoid // problems we outright reject empty directives. - if name == "" { + if name.is_empty() { return ParsedNameDirective::not_a_directive(); } diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 62e71e9b59ddb..0cf05b32e9681 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -1147,7 +1147,7 @@ fn extract_lldb_version(full_version_line: &str) -> Option<(u32, bool)> { } fn not_a_digit(c: char) -> bool { - !c.is_digit(10) + !c.is_ascii_digit() } fn check_overlapping_tests(found_paths: &HashSet) { diff --git a/src/tools/compiletest/src/read2.rs b/src/tools/compiletest/src/read2.rs index 3f1921cb6bd5a..8c06339f3c36d 100644 --- a/src/tools/compiletest/src/read2.rs +++ b/src/tools/compiletest/src/read2.rs @@ -6,7 +6,6 @@ mod tests; pub use self::imp::read2; use std::io::{self, Write}; -use std::mem::replace; use std::process::{Child, Output}; #[derive(Copy, Clone, Debug)] @@ -101,10 +100,10 @@ impl ProcOutput { return; } - let mut head = replace(bytes, Vec::new()); + let mut head = std::mem::take(bytes); // Don't truncate if this as a whole line. // That should make it less likely that we cut a JSON line in half. - if head.last() != Some(&('\n' as u8)) { + if head.last() != Some(&b'\n') { head.truncate(MAX_OUT_LEN); } let skipped = new_len - head.len(); diff --git a/src/tools/compiletest/src/read2/tests.rs b/src/tools/compiletest/src/read2/tests.rs index 5ad2db3cb830b..9e052ff069b99 100644 --- a/src/tools/compiletest/src/read2/tests.rs +++ b/src/tools/compiletest/src/read2/tests.rs @@ -64,9 +64,9 @@ fn test_abbreviate_filterss_are_detected() { #[test] fn test_abbreviate_filters_avoid_abbreviations() { let mut out = ProcOutput::new(); - let filters = &[std::iter::repeat('a').take(64).collect::()]; + let filters = &["a".repeat(64)]; - let mut expected = vec![b'.'; MAX_OUT_LEN - FILTERED_PATHS_PLACEHOLDER_LEN as usize]; + let mut expected = vec![b'.'; MAX_OUT_LEN - FILTERED_PATHS_PLACEHOLDER_LEN]; expected.extend_from_slice(filters[0].as_bytes()); out.extend(&expected, filters); @@ -81,7 +81,7 @@ fn test_abbreviate_filters_avoid_abbreviations() { #[test] fn test_abbreviate_filters_can_still_cause_abbreviations() { let mut out = ProcOutput::new(); - let filters = &[std::iter::repeat('a').take(64).collect::()]; + let filters = &["a".repeat(64)]; let mut input = vec![b'.'; MAX_OUT_LEN]; input.extend_from_slice(filters[0].as_bytes()); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 9e1d5ea61aa8b..72b57d91c234e 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -374,11 +374,11 @@ impl<'test> TestCx<'test> { // if a test does not crash, consider it an error if proc_res.status.success() || matches!(proc_res.status.code(), Some(1 | 0)) { - self.fatal(&format!( + self.fatal( "test no longer crashes/triggers ICE! Please give it a mearningful name, \ add a doc-comment to the start of the test explaining why it exists and \ - move it to tests/ui or wherever you see fit." - )); + move it to tests/ui or wherever you see fit.", + ); } } @@ -697,10 +697,10 @@ impl<'test> TestCx<'test> { // since it is extensively used in the testsuite. check_cfg.push_str("cfg(FALSE"); for revision in &self.props.revisions { - check_cfg.push_str(","); - check_cfg.push_str(&normalize_revision(&revision)); + check_cfg.push(','); + check_cfg.push_str(&normalize_revision(revision)); } - check_cfg.push_str(")"); + check_cfg.push(')'); cmd.args(&["--check-cfg", &check_cfg]); } @@ -818,7 +818,7 @@ impl<'test> TestCx<'test> { // Append the other `cdb-command:`s for line in &dbg_cmds.commands { script_str.push_str(line); - script_str.push_str("\n"); + script_str.push('\n'); } script_str.push_str("qq\n"); // Quit the debugger (including remote debugger, if any) @@ -1200,7 +1200,7 @@ impl<'test> TestCx<'test> { // Append the other commands for line in &dbg_cmds.commands { script_str.push_str(line); - script_str.push_str("\n"); + script_str.push('\n'); } // Finally, quit the debugger @@ -1250,7 +1250,7 @@ impl<'test> TestCx<'test> { // Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS. let options_to_remove = ["-O".to_owned(), "-g".to_owned(), "--debuginfo".to_owned()]; - options.iter().filter(|x| !options_to_remove.contains(x)).map(|x| x.clone()).collect() + options.iter().filter(|x| !options_to_remove.contains(x)).cloned().collect() } fn maybe_add_external_args(&self, cmd: &mut Command, args: &Vec) { @@ -2504,8 +2504,8 @@ impl<'test> TestCx<'test> { // This works with both `--emit asm` (as default output name for the assembly) // and `ptx-linker` because the latter can write output at requested location. let output_path = self.output_base_name().with_extension(extension); - let output_file = TargetLocation::ThisFile(output_path.clone()); - output_file + + TargetLocation::ThisFile(output_path.clone()) } } @@ -2752,7 +2752,7 @@ impl<'test> TestCx<'test> { for entry in walkdir::WalkDir::new(dir) { let entry = entry.expect("failed to read file"); if entry.file_type().is_file() - && entry.path().extension().and_then(|p| p.to_str()) == Some("html".into()) + && entry.path().extension().and_then(|p| p.to_str()) == Some("html") { let status = Command::new("tidy").args(&tidy_args).arg(entry.path()).status().unwrap(); @@ -2783,8 +2783,7 @@ impl<'test> TestCx<'test> { &compare_dir, self.config.verbose, |file_type, extension| { - file_type.is_file() - && (extension == Some("html".into()) || extension == Some("js".into())) + file_type.is_file() && (extension == Some("html") || extension == Some("js")) }, ) { return; @@ -2830,11 +2829,11 @@ impl<'test> TestCx<'test> { } match String::from_utf8(line.clone()) { Ok(line) => { - if line.starts_with("+") { + if line.starts_with('+') { write!(&mut out, "{}", line.green()).unwrap(); - } else if line.starts_with("-") { + } else if line.starts_with('-') { write!(&mut out, "{}", line.red()).unwrap(); - } else if line.starts_with("@") { + } else if line.starts_with('@') { write!(&mut out, "{}", line.blue()).unwrap(); } else { out.write_all(line.as_bytes()).unwrap(); @@ -2907,7 +2906,7 @@ impl<'test> TestCx<'test> { && line.ends_with(';') { if let Some(ref mut other_files) = other_files { - other_files.push(line.rsplit("mod ").next().unwrap().replace(";", "")); + other_files.push(line.rsplit("mod ").next().unwrap().replace(';', "")); } None } else { @@ -3139,7 +3138,7 @@ impl<'test> TestCx<'test> { let mut string = String::new(); for cgu in cgus { string.push_str(&cgu[..]); - string.push_str(" "); + string.push(' '); } string @@ -3172,10 +3171,7 @@ impl<'test> TestCx<'test> { // CGUs joined with "--". This function splits such composite CGU names // and handles each component individually. fn remove_crate_disambiguators_from_set_of_cgu_names(cgus: &str) -> String { - cgus.split("--") - .map(|cgu| remove_crate_disambiguator_from_cgu(cgu)) - .collect::>() - .join("--") + cgus.split("--").map(remove_crate_disambiguator_from_cgu).collect::>().join("--") } } @@ -3357,7 +3353,7 @@ impl<'test> TestCx<'test> { // endif } - if self.config.target.contains("msvc") && self.config.cc != "" { + if self.config.target.contains("msvc") && !self.config.cc.is_empty() { // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe` // and that `lib.exe` lives next to it. let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe"); @@ -3639,7 +3635,7 @@ impl<'test> TestCx<'test> { // endif } - if self.config.target.contains("msvc") && self.config.cc != "" { + if self.config.target.contains("msvc") && !self.config.cc.is_empty() { // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe` // and that `lib.exe` lives next to it. let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe"); @@ -3830,7 +3826,7 @@ impl<'test> TestCx<'test> { && !self.props.dont_check_compiler_stderr { self.fatal_proc_rec( - &format!("compiler output got truncated, cannot compare with reference file"), + "compiler output got truncated, cannot compare with reference file", &proc_res, ); } @@ -4011,8 +4007,8 @@ impl<'test> TestCx<'test> { crate_name.to_str().expect("crate name implies file name must be valid UTF-8"); // replace `a.foo` -> `a__foo` for crate name purposes. // replace `revision-name-with-dashes` -> `revision_name_with_underscore` - let crate_name = crate_name.replace(".", "__"); - let crate_name = crate_name.replace("-", "_"); + let crate_name = crate_name.replace('.', "__"); + let crate_name = crate_name.replace('-', "_"); rustc.arg("--crate-name"); rustc.arg(crate_name); } @@ -4060,7 +4056,7 @@ impl<'test> TestCx<'test> { fn check_mir_dump(&self, test_info: MiroptTest) { let test_dir = self.testpaths.file.parent().unwrap(); let test_crate = - self.testpaths.file.file_stem().unwrap().to_str().unwrap().replace("-", "_"); + self.testpaths.file.file_stem().unwrap().to_str().unwrap().replace('-', "_"); let MiroptTest { run_filecheck, suffix, files, passes: _ } = test_info; diff --git a/src/tools/compiletest/src/runtest/debugger.rs b/src/tools/compiletest/src/runtest/debugger.rs index eebe5f3580b30..ed6cc97a8abba 100644 --- a/src/tools/compiletest/src/runtest/debugger.rs +++ b/src/tools/compiletest/src/runtest/debugger.rs @@ -148,5 +148,5 @@ fn check_single_line(line: &str, check_line: &str) -> bool { rest = &rest[pos + current_fragment.len()..]; } - if !can_end_anywhere && !rest.is_empty() { false } else { true } + can_end_anywhere || rest.is_empty() } diff --git a/src/tools/compiletest/src/tests.rs b/src/tools/compiletest/src/tests.rs index e6725dba26051..4292f234adc78 100644 --- a/src/tools/compiletest/src/tests.rs +++ b/src/tools/compiletest/src/tests.rs @@ -58,11 +58,11 @@ fn test_extract_lldb_version() { #[test] fn is_test_test() { - assert_eq!(true, is_test(&OsString::from("a_test.rs"))); - assert_eq!(false, is_test(&OsString::from(".a_test.rs"))); - assert_eq!(false, is_test(&OsString::from("a_cat.gif"))); - assert_eq!(false, is_test(&OsString::from("#a_dog_gif"))); - assert_eq!(false, is_test(&OsString::from("~a_temp_file"))); + assert!(is_test(&OsString::from("a_test.rs"))); + assert!(!is_test(&OsString::from(".a_test.rs"))); + assert!(!is_test(&OsString::from("a_cat.gif"))); + assert!(!is_test(&OsString::from("#a_dog_gif"))); + assert!(!is_test(&OsString::from("~a_temp_file"))); } #[test] diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index 5e35ce242fe4e..1713a4d812c4b 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -418,15 +418,13 @@ impl<'a> Validator<'a> { } else { self.fail_expecting(id, expected); } - } else { - if !self.missing_ids.contains(id) { - self.missing_ids.insert(id); + } else if !self.missing_ids.contains(id) { + self.missing_ids.insert(id); - let sels = json_find::find_selector(&self.krate_json, &Value::String(id.0.clone())); - assert_ne!(sels.len(), 0); + let sels = json_find::find_selector(&self.krate_json, &Value::String(id.0.clone())); + assert_ne!(sels.len(), 0); - self.fail(id, ErrorKind::NotFound(sels)) - } + self.fail(id, ErrorKind::NotFound(sels)) } } diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs index 73f5738469ed1..f246d71d499b4 100644 --- a/src/tools/lint-docs/src/groups.rs +++ b/src/tools/lint-docs/src/groups.rs @@ -121,13 +121,13 @@ impl<'a> LintExtractor<'a> { }; to_link.extend(group_lints); let brackets: Vec<_> = group_lints.iter().map(|l| format!("[{}]", l)).collect(); - write!(result, "| {} | {} | {} |\n", group_name, description, brackets.join(", ")) + writeln!(result, "| {} | {} | {} |", group_name, description, brackets.join(", ")) .unwrap(); } result.push('\n'); result.push_str("[warn-by-default]: listing/warn-by-default.md\n"); for lint_name in to_link { - let lint_def = match lints.iter().find(|l| l.name == lint_name.replace("-", "_")) { + let lint_def = match lints.iter().find(|l| l.name == lint_name.replace('-', "_")) { Some(def) => def, None => { let msg = format!( @@ -144,9 +144,9 @@ impl<'a> LintExtractor<'a> { } } }; - write!( + writeln!( result, - "[{}]: listing/{}#{}\n", + "[{}]: listing/{}#{}", lint_name, lint_def.level.doc_filename(), lint_name diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs index c79b377727abf..72d6a495e7e79 100644 --- a/src/tools/lint-docs/src/lib.rs +++ b/src/tools/lint-docs/src/lib.rs @@ -84,8 +84,8 @@ impl Lint { for &expected in &["### Example", "### Explanation", "{{produces}}"] { if expected == "{{produces}}" && self.is_ignored() { if self.doc_contains("{{produces}}") { - return Err(format!( - "the lint example has `ignore`, but also contains the {{{{produces}}}} marker\n\ + return Err( + "the lint example has `ignore`, but also contains the {{produces}} marker\n\ \n\ The documentation generator cannot generate the example output when the \ example is ignored.\n\ @@ -111,7 +111,7 @@ impl Lint { Replacing the output with the text of the example you \ compiled manually yourself.\n\ " - ).into()); + .into()); } continue; } @@ -519,11 +519,11 @@ impl<'a> LintExtractor<'a> { let mut these_lints: Vec<_> = lints.iter().filter(|lint| lint.level == level).collect(); these_lints.sort_unstable_by_key(|lint| &lint.name); for lint in &these_lints { - write!(result, "* [`{}`](#{})\n", lint.name, lint.name.replace("_", "-")).unwrap(); + writeln!(result, "* [`{}`](#{})", lint.name, lint.name.replace('_', "-")).unwrap(); } result.push('\n'); for lint in &these_lints { - write!(result, "## {}\n\n", lint.name.replace("_", "-")).unwrap(); + write!(result, "## {}\n\n", lint.name.replace('_', "-")).unwrap(); for line in &lint.doc { result.push_str(line); result.push('\n'); @@ -583,7 +583,7 @@ fn add_rename_redirect(level: Level, output: &mut String) { let filename = level.doc_filename().replace(".md", ".html"); output.push_str(RENAME_START); for (from, to) in *names { - write!(output, " \"#{from}\": \"{filename}#{to}\",\n").unwrap(); + writeln!(output, " \"#{from}\": \"{filename}#{to}\",").unwrap(); } output.push_str(RENAME_END); } diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs index 89f4d8957c8bf..1237951b3f042 100644 --- a/src/tools/opt-dist/src/training.rs +++ b/src/tools/opt-dist/src/training.rs @@ -216,11 +216,9 @@ pub fn gather_bolt_profiles( log::info!("Profile file count: {}", profiles.len()); // Delete the gathered profiles - for profile in glob::glob(&format!("{profile_prefix}*"))?.into_iter() { - if let Ok(profile) = profile { - if let Err(error) = std::fs::remove_file(&profile) { - log::error!("Cannot delete BOLT profile {}: {error:?}", profile.display()); - } + for profile in glob::glob(&format!("{profile_prefix}*"))?.flatten() { + if let Err(error) = std::fs::remove_file(&profile) { + log::error!("Cannot delete BOLT profile {}: {error:?}", profile.display()); } } diff --git a/src/tools/remote-test-client/src/main.rs b/src/tools/remote-test-client/src/main.rs index 590c735596ed9..dd2c09c430b61 100644 --- a/src/tools/remote-test-client/src/main.rs +++ b/src/tools/remote-test-client/src/main.rs @@ -317,13 +317,11 @@ fn run(support_lib_count: usize, exe: String, all_args: Vec) { t!(io::copy(&mut (&mut client).take(amt), &mut stdout)); t!(stdout.flush()); } + } else if amt == 0 { + stderr_done = true; } else { - if amt == 0 { - stderr_done = true; - } else { - t!(io::copy(&mut (&mut client).take(amt), &mut stderr)); - t!(stderr.flush()); - } + t!(io::copy(&mut (&mut client).take(amt), &mut stderr)); + t!(stderr.flush()); } } diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs index 68d7aa56c438b..79f96c5022382 100644 --- a/src/tools/remote-test-server/src/main.rs +++ b/src/tools/remote-test-server/src/main.rs @@ -282,7 +282,7 @@ fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>, conf cmd.env(library_path, env::join_paths(paths).unwrap()); // Some tests assume RUST_TEST_TMPDIR exists - cmd.env("RUST_TEST_TMPDIR", tmp.to_owned()); + cmd.env("RUST_TEST_TMPDIR", tmp); let socket = Arc::new(Mutex::new(reader.into_inner())); diff --git a/src/tools/tidy/src/alphabetical.rs b/src/tools/tidy/src/alphabetical.rs index 150a9594350ed..a29286fa2c596 100644 --- a/src/tools/tidy/src/alphabetical.rs +++ b/src/tools/tidy/src/alphabetical.rs @@ -88,7 +88,7 @@ fn check_section<'a>( let trimmed_line = line.trim_start_matches(' '); if trimmed_line.starts_with("//") - || (trimmed_line.starts_with("#") && !trimmed_line.starts_with("#!")) + || (trimmed_line.starts_with('#') && !trimmed_line.starts_with("#!")) || trimmed_line.starts_with(is_close_bracket) { continue; diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index 64ba79dc1857e..c82e8b6fee98e 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -61,7 +61,7 @@ mod os_impl { fs::remove_file(&path).expect("Deleted temp file"); // If the file is executable, then we assume that this // filesystem does not track executability, so skip this check. - return if exec { Unsupported } else { Supported }; + if exec { Unsupported } else { Supported } } Err(e) => { // If the directory is read-only or we otherwise don't have rights, @@ -76,7 +76,7 @@ mod os_impl { panic!("unable to create temporary file `{:?}`: {:?}", path, e); } - }; + } } for &source_dir in sources { @@ -92,7 +92,7 @@ mod os_impl { } } - return true; + true } // FIXME: check when rust-installer test sh files will be removed, diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 2dd3d17f9e3e7..7337c9843c7b6 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -699,11 +699,9 @@ fn check_permitted_dependencies( for dep in deps { let dep = pkg_from_id(metadata, dep); // If this path is in-tree, we don't require it to be explicitly permitted. - if dep.source.is_some() { - if !permitted_dependencies.contains(dep.name.as_str()) { - tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id); - has_permitted_dep_error = true; - } + if dep.source.is_some() && !permitted_dependencies.contains(dep.name.as_str()) { + tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id); + has_permitted_dep_error = true; } } diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index 39f7e70b69393..47e2be761e6ab 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -308,11 +308,9 @@ fn check_error_codes_tests( for line in file.lines() { let s = line.trim(); // Assuming the line starts with `error[E`, we can substring the error code out. - if s.starts_with("error[E") { - if &s[6..11] == code { - found_code = true; - break; - } + if s.starts_with("error[E") && &s[6..11] == code { + found_code = true; + break; }; } diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs index b54fa5c6b2c92..fb626cac3fa05 100644 --- a/src/tools/tidy/src/ext_tool_checks.rs +++ b/src/tools/tidy/src/ext_tool_checks.rs @@ -78,9 +78,9 @@ fn check_impl( let mut py_path = None; let (cfg_args, file_args): (Vec<_>, Vec<_>) = pos_args - .into_iter() + .iter() .map(OsStr::new) - .partition(|arg| arg.to_str().is_some_and(|s| s.starts_with("-"))); + .partition(|arg| arg.to_str().is_some_and(|s| s.starts_with('-'))); if python_lint || python_fmt { let venv_path = outdir.join("venv"); @@ -277,10 +277,11 @@ fn create_venv_at_path(path: &Path) -> Result<(), Error> { let stderr = String::from_utf8_lossy(&out.stderr); let err = if stderr.contains("No module named virtualenv") { - Error::Generic(format!( + Error::Generic( "virtualenv not found: you may need to install it \ (`python3 -m pip install venv`)" - )) + .to_owned(), + ) } else { Error::Generic(format!( "failed to create venv at '{}' using {sys_py}: {stderr}", diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 2d3888ec75f25..7bcb85335e07d 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -463,10 +463,13 @@ pub fn check(path: &Path, bad: &mut bool) { } } // for now we just check libcore - if trimmed.contains("unsafe {") && !trimmed.starts_with("//") && !last_safety_comment { - if file.components().any(|c| c.as_os_str() == "core") && !is_test { - suppressible_tidy_err!(err, skip_undocumented_unsafe, "undocumented unsafe"); - } + if trimmed.contains("unsafe {") + && !trimmed.starts_with("//") + && !last_safety_comment + && file.components().any(|c| c.as_os_str() == "core") + && !is_test + { + suppressible_tidy_err!(err, skip_undocumented_unsafe, "undocumented unsafe"); } if trimmed.contains("// SAFETY:") { last_safety_comment = true; @@ -487,10 +490,10 @@ pub fn check(path: &Path, bad: &mut bool) { "copyright notices attributed to the Rust Project Developers are deprecated" ); } - if !file.components().any(|c| c.as_os_str() == "rustc_baked_icu_data") { - if is_unexplained_ignore(&extension, line) { - err(UNEXPLAINED_IGNORE_DOCTEST_INFO); - } + if !file.components().any(|c| c.as_os_str() == "rustc_baked_icu_data") + && is_unexplained_ignore(&extension, line) + { + err(UNEXPLAINED_IGNORE_DOCTEST_INFO); } if filename.ends_with(".cpp") && line.contains("llvm_unreachable") { @@ -525,26 +528,24 @@ pub fn check(path: &Path, bad: &mut bool) { backtick_count += comment_text.chars().filter(|ch| *ch == '`').count(); } comment_block = Some((start_line, backtick_count)); - } else { - if let Some((start_line, backtick_count)) = comment_block.take() { - if backtick_count % 2 == 1 { - let mut err = |msg: &str| { - tidy_error!(bad, "{}:{start_line}: {msg}", file.display()); - }; - let block_len = (i + 1) - start_line; - if block_len == 1 { - suppressible_tidy_err!( - err, - skip_odd_backticks, - "comment with odd number of backticks" - ); - } else { - suppressible_tidy_err!( - err, - skip_odd_backticks, - "{block_len}-line comment block with odd number of backticks" - ); - } + } else if let Some((start_line, backtick_count)) = comment_block.take() { + if backtick_count % 2 == 1 { + let mut err = |msg: &str| { + tidy_error!(bad, "{}:{start_line}: {msg}", file.display()); + }; + let block_len = (i + 1) - start_line; + if block_len == 1 { + suppressible_tidy_err!( + err, + skip_odd_backticks, + "comment with odd number of backticks" + ); + } else { + suppressible_tidy_err!( + err, + skip_odd_backticks, + "{block_len}-line comment block with odd number of backticks" + ); } } } diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs index 63a0383416652..1cecf998e284b 100644 --- a/src/tools/tidy/src/walk.rs +++ b/src/tools/tidy/src/walk.rs @@ -79,13 +79,11 @@ pub(crate) fn walk_no_read( let walker = walker.filter_entry(move |e| { !skip(e.path(), e.file_type().map(|ft| ft.is_dir()).unwrap_or(false)) }); - for entry in walker.build() { - if let Ok(entry) = entry { - if entry.file_type().map_or(true, |kind| kind.is_dir() || kind.is_symlink()) { - continue; - } - f(&entry); + for entry in walker.build().flatten() { + if entry.file_type().map_or(true, |kind| kind.is_dir() || kind.is_symlink()) { + continue; } + f(&entry); } } @@ -97,11 +95,9 @@ pub(crate) fn walk_dir( ) { let mut walker = ignore::WalkBuilder::new(path); let walker = walker.filter_entry(move |e| !skip(e.path())); - for entry in walker.build() { - if let Ok(entry) = entry { - if entry.path().is_dir() { - f(&entry); - } + for entry in walker.build().flatten() { + if entry.path().is_dir() { + f(&entry); } } } diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index c470d502a6548..55bfbed8b0e10 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -52,7 +52,7 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) { ); } } else { - return tidy_error!(bad, "failed to check version of `x`: {}", cargo_list.status); + tidy_error!(bad, "failed to check version of `x`: {}", cargo_list.status) } } diff --git a/tests/ui/const-generics/issues/issue-82956.stderr b/tests/ui/const-generics/issues/issue-82956.stderr index d0fc7112426a9..a956fc741f4d4 100644 --- a/tests/ui/const-generics/issues/issue-82956.stderr +++ b/tests/ui/const-generics/issues/issue-82956.stderr @@ -4,7 +4,7 @@ error[E0433]: failed to resolve: use of undeclared type `IntoIter` LL | let mut iter = IntoIter::new(self); | ^^^^^^^^ use of undeclared type `IntoIter` | -help: consider importing one of these items +help: consider importing one of these structs | LL + use std::array::IntoIter; | diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.rs b/tests/ui/consts/const_refs_to_static-ice-121413.rs index 8a24fb799b6b8..8fc3912efd08e 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.rs +++ b/tests/ui/consts/const_refs_to_static-ice-121413.rs @@ -5,12 +5,16 @@ // ignore-tidy-linelength #![feature(const_refs_to_static)] const REF_INTERIOR_MUT: &usize = { + //~^ HELP consider importing this struct static FOO: Sync = AtomicUsize::new(0); //~^ ERROR failed to resolve: use of undeclared type `AtomicUsize` //~| WARN trait objects without an explicit `dyn` are deprecated //~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time //~| ERROR the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| HELP if this is an object-safe trait, use `dyn` + //~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static)` + //~| HELP the trait `Sized` is not implemented for `(dyn Sync + 'static)` unsafe { &*(&FOO as *const _ as *const usize) } }; pub fn main() {} diff --git a/tests/ui/consts/const_refs_to_static-ice-121413.stderr b/tests/ui/consts/const_refs_to_static-ice-121413.stderr index c977c698a92e9..fbe32a70293aa 100644 --- a/tests/ui/consts/const_refs_to_static-ice-121413.stderr +++ b/tests/ui/consts/const_refs_to_static-ice-121413.stderr @@ -1,5 +1,5 @@ error[E0433]: failed to resolve: use of undeclared type `AtomicUsize` - --> $DIR/const_refs_to_static-ice-121413.rs:8:24 + --> $DIR/const_refs_to_static-ice-121413.rs:9:24 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^^^^^^^^ use of undeclared type `AtomicUsize` @@ -10,7 +10,7 @@ LL + use std::sync::atomic::AtomicUsize; | warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/const_refs_to_static-ice-121413.rs:8:17 + --> $DIR/const_refs_to_static-ice-121413.rs:9:17 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^ @@ -24,7 +24,7 @@ LL | static FOO: dyn Sync = AtomicUsize::new(0); | +++ error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time - --> $DIR/const_refs_to_static-ice-121413.rs:8:17 + --> $DIR/const_refs_to_static-ice-121413.rs:9:17 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^ doesn't have a size known at compile-time @@ -32,7 +32,7 @@ LL | static FOO: Sync = AtomicUsize::new(0); = help: the trait `Sized` is not implemented for `(dyn Sync + 'static)` error[E0277]: the size for values of type `(dyn Sync + 'static)` cannot be known at compilation time - --> $DIR/const_refs_to_static-ice-121413.rs:8:24 + --> $DIR/const_refs_to_static-ice-121413.rs:9:24 | LL | static FOO: Sync = AtomicUsize::new(0); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr b/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr index 5c610f36322dc..b1a15b8594a0a 100644 --- a/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr +++ b/tests/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr @@ -22,7 +22,7 @@ error[E0425]: cannot find value `Set` in this scope LL | fn setup() -> Set { Set } | ^^^ not found in this scope | -help: consider importing one of these items +help: consider importing one of these unit variants | LL + use AffixHeart::Set; | diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr index 78e6376bca2e8..cc229764ad3fb 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr @@ -24,8 +24,7 @@ LL | fn f() { my_core::mem::drop(0); } LL | a!(); | ---- in this macro invocation | - = help: consider importing one of these items: - core::mem + = help: consider importing this module: std::mem = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -35,9 +34,7 @@ error[E0433]: failed to resolve: use of undeclared crate or module `my_core` LL | fn f() { my_core::mem::drop(0); } | ^^^^^^^ use of undeclared crate or module `my_core` | -help: consider importing one of these items - | -LL + use core::mem; +help: consider importing this module | LL + use std::mem; | diff --git a/tests/ui/imports/cycle-import-in-std-1.stderr b/tests/ui/imports/cycle-import-in-std-1.stderr index d4e6f32cc109e..a7dfc6231bace 100644 --- a/tests/ui/imports/cycle-import-in-std-1.stderr +++ b/tests/ui/imports/cycle-import-in-std-1.stderr @@ -4,8 +4,7 @@ error[E0432]: unresolved import `ops` LL | use ops::{self as std}; | ^^^^^^^^^^^ no external crate `ops` | - = help: consider importing one of these items instead: - core::ops + = help: consider importing this module instead: std::ops error: aborting due to 1 previous error diff --git a/tests/ui/imports/cycle-import-in-std-2.stderr b/tests/ui/imports/cycle-import-in-std-2.stderr index dc0270dffe4a7..8d94693cd51d4 100644 --- a/tests/ui/imports/cycle-import-in-std-2.stderr +++ b/tests/ui/imports/cycle-import-in-std-2.stderr @@ -4,8 +4,7 @@ error[E0432]: unresolved import `ops` LL | use ops::{self as std}; | ^^^^^^^^^^^ no external crate `ops` | - = help: consider importing one of these items instead: - core::ops + = help: consider importing this module instead: std::ops error: aborting due to 1 previous error diff --git a/tests/ui/imports/import-alias-issue-121168.edition2018.stderr b/tests/ui/imports/import-alias-issue-121168.edition2018.stderr index b61a0e3edd524..e14e700c33d81 100644 --- a/tests/ui/imports/import-alias-issue-121168.edition2018.stderr +++ b/tests/ui/imports/import-alias-issue-121168.edition2018.stderr @@ -4,7 +4,7 @@ error[E0412]: cannot find type `Foo` in this scope LL | let _: Foo = todo!(); | ^^^ not found in this scope | -help: consider importing one of these items +help: consider importing one of these structs | LL + use crate::nice_crate_name::Foo; | diff --git a/tests/ui/imports/import-alias-issue-121168.edition2021.stderr b/tests/ui/imports/import-alias-issue-121168.edition2021.stderr index b61a0e3edd524..e14e700c33d81 100644 --- a/tests/ui/imports/import-alias-issue-121168.edition2021.stderr +++ b/tests/ui/imports/import-alias-issue-121168.edition2021.stderr @@ -4,7 +4,7 @@ error[E0412]: cannot find type `Foo` in this scope LL | let _: Foo = todo!(); | ^^^ not found in this scope | -help: consider importing one of these items +help: consider importing one of these structs | LL + use crate::nice_crate_name::Foo; | diff --git a/tests/ui/imports/issue-56125.stderr b/tests/ui/imports/issue-56125.stderr index d2a0f436c42d0..0c4a569c7ea71 100644 --- a/tests/ui/imports/issue-56125.stderr +++ b/tests/ui/imports/issue-56125.stderr @@ -4,16 +4,16 @@ error[E0432]: unresolved import `empty::issue_56125` LL | use empty::issue_56125; | ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty` | -help: consider importing one of these items instead +help: consider importing one of these modules instead | +LL | use crate::m3::last_segment::issue_56125; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | use crate::m3::non_last_segment::non_last_segment::issue_56125; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL | use ::issue_56125::issue_56125; | ~~~~~~~~~~~~~~~~~~~~~~~~~~ LL | use ::issue_56125::last_segment::issue_56125; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LL | use ::issue_56125::non_last_segment::non_last_segment::issue_56125; - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LL | use crate::m3::last_segment::issue_56125; - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ and 1 other candidate error[E0659]: `issue_56125` is ambiguous diff --git a/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs b/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs new file mode 100644 index 0000000000000..8cd1524045b15 --- /dev/null +++ b/tests/ui/lint/dead-code/allow-unconstructed-pub-struct.rs @@ -0,0 +1,33 @@ +//@ check-pass + +mod ffi { + use super::*; + + extern "C" { + pub fn DomPromise_AddRef(promise: *const Promise); + pub fn DomPromise_Release(promise: *const Promise); + } +} + +#[repr(C)] +#[allow(unused)] +pub struct Promise { + private: [u8; 0], + __nosync: ::std::marker::PhantomData<::std::rc::Rc>, +} + +pub unsafe trait RefCounted { + unsafe fn addref(&self); + unsafe fn release(&self); +} + +unsafe impl RefCounted for Promise { + unsafe fn addref(&self) { + ffi::DomPromise_AddRef(self) + } + unsafe fn release(&self) { + ffi::DomPromise_Release(self) + } +} + +fn main() {} diff --git a/tests/ui/lint/use_suggestion_json.stderr b/tests/ui/lint/use_suggestion_json.stderr index acc36550642d6..4683e5dd8f3c2 100644 --- a/tests/ui/lint/use_suggestion_json.stderr +++ b/tests/ui/lint/use_suggestion_json.stderr @@ -95,7 +95,7 @@ mod foo { ], "children": [ { - "message": "consider importing one of these items", + "message": "consider importing one of these structs", "code": null, "level": "help", "spans": [ @@ -386,7 +386,7 @@ mod foo { \u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let x: Iter;\u001b[0m \u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mnot found in this scope\u001b[0m \u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m -\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: consider importing one of these items\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: consider importing one of these structs\u001b[0m \u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m \u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;10m+ use std::collections::binary_heap::Iter;\u001b[0m \u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m diff --git a/tests/ui/namespace/namespace-mix.stderr b/tests/ui/namespace/namespace-mix.stderr index 4eff08ead42ce..b80363fe8f848 100644 --- a/tests/ui/namespace/namespace-mix.stderr +++ b/tests/ui/namespace/namespace-mix.stderr @@ -12,7 +12,7 @@ help: a tuple struct with a similar name exists | LL | check(m1::TS); | ~~ -help: consider importing one of these items instead +help: consider importing one of these constants instead | LL + use m2::S; | @@ -40,7 +40,7 @@ help: a tuple struct with a similar name exists | LL | check(xm1::TS); | ~~ -help: consider importing one of these items instead +help: consider importing one of these constants instead | LL + use m2::S; | @@ -66,7 +66,7 @@ help: a tuple variant with a similar name exists | LL | check(m7::TV); | ~~ -help: consider importing one of these items instead +help: consider importing one of these constants instead | LL + use m8::V; | @@ -94,7 +94,7 @@ help: a tuple variant with a similar name exists | LL | check(xm7::TV); | ~~ -help: consider importing one of these items instead +help: consider importing one of these constants instead | LL + use m8::V; | diff --git a/tests/ui/resolve/issue-16058.stderr b/tests/ui/resolve/issue-16058.stderr index 914990c35ff76..12b1ac8a5fb44 100644 --- a/tests/ui/resolve/issue-16058.stderr +++ b/tests/ui/resolve/issue-16058.stderr @@ -4,7 +4,7 @@ error[E0574]: expected struct, variant or union type, found enum `Result` LL | Result { | ^^^^^^ not a struct, variant or union type | -help: consider importing one of these items instead +help: consider importing one of these type aliases instead | LL + use std::fmt::Result; | diff --git a/tests/ui/resolve/issue-21221-1.stderr b/tests/ui/resolve/issue-21221-1.stderr index a38116cd7287a..ccf03afaa19fe 100644 --- a/tests/ui/resolve/issue-21221-1.stderr +++ b/tests/ui/resolve/issue-21221-1.stderr @@ -4,14 +4,14 @@ error[E0405]: cannot find trait `Mul` in this scope LL | impl Mul for Foo { | ^^^ not found in this scope | -help: consider importing one of these items +help: consider importing one of these traits + | +LL + use std::ops::Mul; | LL + use mul1::Mul; | LL + use mul2::Mul; | -LL + use std::ops::Mul; - | error[E0412]: cannot find type `Mul` in this scope --> $DIR/issue-21221-1.rs:58:16 @@ -19,14 +19,14 @@ error[E0412]: cannot find type `Mul` in this scope LL | fn getMul() -> Mul { | ^^^ not found in this scope | -help: consider importing one of these items +help: consider importing one of these traits + | +LL + use std::ops::Mul; | LL + use mul1::Mul; | LL + use mul2::Mul; | -LL + use std::ops::Mul; - | error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope --> $DIR/issue-21221-1.rs:63:6 diff --git a/tests/ui/resolve/issue-21221-2.stderr b/tests/ui/resolve/issue-21221-2.stderr index 3bd4c1a5d1315..5db327955eb10 100644 --- a/tests/ui/resolve/issue-21221-2.stderr +++ b/tests/ui/resolve/issue-21221-2.stderr @@ -4,7 +4,7 @@ error[E0405]: cannot find trait `T` in this scope LL | impl T for Foo { } | ^ not found in this scope | -help: consider importing one of these items +help: consider importing one of these traits | LL + use baz::T; | diff --git a/tests/ui/resolve/issue-50599.stderr b/tests/ui/resolve/issue-50599.stderr index e5eacd741fbe2..24fb3d580b8fa 100644 --- a/tests/ui/resolve/issue-50599.stderr +++ b/tests/ui/resolve/issue-50599.stderr @@ -4,7 +4,7 @@ error[E0425]: cannot find value `LOG10_2` in module `std::f64` LL | const M: usize = (f64::from(N) * std::f64::LOG10_2) as usize; | ^^^^^^^ not found in `std::f64` | -help: consider importing one of these items +help: consider importing one of these constants | LL + use std::f128::consts::LOG10_2; | diff --git a/tests/ui/resolve/issue-73427.stderr b/tests/ui/resolve/issue-73427.stderr index c5e245d884b7b..0a9a504f79caa 100644 --- a/tests/ui/resolve/issue-73427.stderr +++ b/tests/ui/resolve/issue-73427.stderr @@ -105,7 +105,7 @@ help: the following enum variant is available | LL | (E::TupleWithFields(/* fields */)).foo(); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -help: consider importing one of these items instead +help: consider importing one of these constants instead | LL + use std::f128::consts::E; | diff --git a/tests/ui/resolve/privacy-enum-ctor.stderr b/tests/ui/resolve/privacy-enum-ctor.stderr index 01c8a38d2a48a..ee3aecddcc342 100644 --- a/tests/ui/resolve/privacy-enum-ctor.stderr +++ b/tests/ui/resolve/privacy-enum-ctor.stderr @@ -82,7 +82,7 @@ help: a function with a similar name exists | LL | let _: E = m::f; | ~ -help: consider importing one of these items instead +help: consider importing one of these constants instead | LL + use std::f128::consts::E; | @@ -123,7 +123,7 @@ help: alternatively, the following enum variant is available | LL | let _: E = (E::Fn(/* fields */)); | ~~~~~~~~~~~~~~~~~~~~~ -help: consider importing one of these items instead +help: consider importing one of these constants instead | LL + use std::f128::consts::E; | diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr index 7f989c15f1c05..d0c084f7bd5d0 100644 --- a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr +++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/not-allowed.stderr @@ -4,10 +4,8 @@ error[E0432]: unresolved import `alloc` LL | use alloc; | ^^^^^ no external crate `alloc` | -help: consider importing one of these items instead +help: consider importing this module instead | -LL | use core::alloc; - | ~~~~~~~~~~~ LL | use std::alloc; | ~~~~~~~~~~ diff --git a/tests/ui/rust-2018/issue-52202-use-suggestions.stderr b/tests/ui/rust-2018/issue-52202-use-suggestions.stderr index 49736205f204b..ee1a336ea98f6 100644 --- a/tests/ui/rust-2018/issue-52202-use-suggestions.stderr +++ b/tests/ui/rust-2018/issue-52202-use-suggestions.stderr @@ -4,7 +4,7 @@ error[E0422]: cannot find struct, variant or union type `Drain` in this scope LL | let _d = Drain {}; | ^^^^^ not found in this scope | -help: consider importing one of these items +help: consider importing one of these structs | LL + use crate::plumbing::Drain; | diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.fixed b/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.fixed new file mode 100644 index 0000000000000..02d667d984421 --- /dev/null +++ b/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.fixed @@ -0,0 +1,22 @@ +//@ edition:2018 +// +// This is a regression test for #83564. +// For some reason, Rust 2018 or higher is required to reproduce the bug. +//@ run-rustfix +//@ revisions: no_std std +//@ [no_std]compile-flags: --cfg=no_std -C panic=abort +#![cfg_attr(no_std, no_std)] + +use core::num::NonZero; + +fn main() { + //~^ HELP consider importing this struct + let _x = NonZero::new(5u32).unwrap(); + //~^ ERROR failed to resolve: use of undeclared type `NonZero` +} + +#[allow(dead_code)] +#[cfg_attr(no_std, panic_handler)] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.stderr b/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.stderr similarity index 71% rename from tests/ui/suggestions/core-std-import-order-issue-83564.stderr rename to tests/ui/suggestions/core-std-import-order-issue-83564.no_std.stderr index 8665cc6d87cf5..d73f613bf9c8a 100644 --- a/tests/ui/suggestions/core-std-import-order-issue-83564.stderr +++ b/tests/ui/suggestions/core-std-import-order-issue-83564.no_std.stderr @@ -1,15 +1,13 @@ error[E0433]: failed to resolve: use of undeclared type `NonZero` - --> $DIR/core-std-import-order-issue-83564.rs:8:14 + --> $DIR/core-std-import-order-issue-83564.rs:12:14 | LL | let _x = NonZero::new(5u32).unwrap(); | ^^^^^^^ use of undeclared type `NonZero` | -help: consider importing one of these items +help: consider importing this struct | LL + use core::num::NonZero; | -LL + use std::num::NonZero; - | error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.rs b/tests/ui/suggestions/core-std-import-order-issue-83564.rs index 6f2bdd7a38af5..5bb5bfe176ba8 100644 --- a/tests/ui/suggestions/core-std-import-order-issue-83564.rs +++ b/tests/ui/suggestions/core-std-import-order-issue-83564.rs @@ -2,9 +2,19 @@ // // This is a regression test for #83564. // For some reason, Rust 2018 or higher is required to reproduce the bug. +//@ run-rustfix +//@ revisions: no_std std +//@ [no_std]compile-flags: --cfg=no_std -C panic=abort +#![cfg_attr(no_std, no_std)] fn main() { - //~^ HELP consider importing one of these items + //~^ HELP consider importing this struct let _x = NonZero::new(5u32).unwrap(); //~^ ERROR failed to resolve: use of undeclared type `NonZero` } + +#[allow(dead_code)] +#[cfg_attr(no_std, panic_handler)] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.std.fixed b/tests/ui/suggestions/core-std-import-order-issue-83564.std.fixed new file mode 100644 index 0000000000000..3492b42c685f9 --- /dev/null +++ b/tests/ui/suggestions/core-std-import-order-issue-83564.std.fixed @@ -0,0 +1,22 @@ +//@ edition:2018 +// +// This is a regression test for #83564. +// For some reason, Rust 2018 or higher is required to reproduce the bug. +//@ run-rustfix +//@ revisions: no_std std +//@ [no_std]compile-flags: --cfg=no_std -C panic=abort +#![cfg_attr(no_std, no_std)] + +use std::num::NonZero; + +fn main() { + //~^ HELP consider importing this struct + let _x = NonZero::new(5u32).unwrap(); + //~^ ERROR failed to resolve: use of undeclared type `NonZero` +} + +#[allow(dead_code)] +#[cfg_attr(no_std, panic_handler)] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/tests/ui/suggestions/core-std-import-order-issue-83564.std.stderr b/tests/ui/suggestions/core-std-import-order-issue-83564.std.stderr new file mode 100644 index 0000000000000..ebfe197b45d69 --- /dev/null +++ b/tests/ui/suggestions/core-std-import-order-issue-83564.std.stderr @@ -0,0 +1,14 @@ +error[E0433]: failed to resolve: use of undeclared type `NonZero` + --> $DIR/core-std-import-order-issue-83564.rs:12:14 + | +LL | let _x = NonZero::new(5u32).unwrap(); + | ^^^^^^^ use of undeclared type `NonZero` + | +help: consider importing this struct + | +LL + use std::num::NonZero; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/suggestions/crate-or-module-typo.stderr b/tests/ui/suggestions/crate-or-module-typo.stderr index 457d779064682..084d0408a8e7d 100644 --- a/tests/ui/suggestions/crate-or-module-typo.stderr +++ b/tests/ui/suggestions/crate-or-module-typo.stderr @@ -30,9 +30,7 @@ help: there is a crate or module with a similar name | LL | bar: std::cell::Cell | ~~~ -help: consider importing one of these items - | -LL + use core::cell; +help: consider importing this module | LL + use std::cell; | diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.rs b/tests/ui/suggestions/suggest-tryinto-edition-change.rs index 3732177487450..f45670ae7c1e2 100644 --- a/tests/ui/suggestions/suggest-tryinto-edition-change.rs +++ b/tests/ui/suggestions/suggest-tryinto-edition-change.rs @@ -1,5 +1,5 @@ // Make sure that trying to access `TryInto`, `TryFrom`, `FromIterator` in pre-2021 mentions -// Edition 2021 change +// Edition 2021 change. //@ edition:2018 fn test() { @@ -11,19 +11,16 @@ fn test() { //~^ ERROR failed to resolve: use of undeclared type //~| NOTE use of undeclared type //~| NOTE 'std::convert::TryFrom' is included in the prelude starting in Edition 2021 - //~| NOTE 'core::convert::TryFrom' is included in the prelude starting in Edition 2021 let _i: i16 = TryInto::try_into(0_i32).unwrap(); //~^ ERROR failed to resolve: use of undeclared type //~| NOTE use of undeclared type //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021 - //~| NOTE 'core::convert::TryInto' is included in the prelude starting in Edition 2021 let _v: Vec<_> = FromIterator::from_iter(&[1]); //~^ ERROR failed to resolve: use of undeclared type //~| NOTE use of undeclared type //~| NOTE 'std::iter::FromIterator' is included in the prelude starting in Edition 2021 - //~| NOTE 'core::iter::FromIterator' is included in the prelude starting in Edition 2021 } fn main() { diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr index db7c40101cdc2..5be55f75cd15d 100644 --- a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr +++ b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr @@ -4,45 +4,36 @@ error[E0433]: failed to resolve: use of undeclared type `TryFrom` LL | let _i: i16 = TryFrom::try_from(0_i32).unwrap(); | ^^^^^^^ use of undeclared type `TryFrom` | - = note: 'core::convert::TryFrom' is included in the prelude starting in Edition 2021 = note: 'std::convert::TryFrom' is included in the prelude starting in Edition 2021 -help: consider importing one of these items - | -LL + use core::convert::TryFrom; +help: consider importing this trait | LL + use std::convert::TryFrom; | error[E0433]: failed to resolve: use of undeclared type `TryInto` - --> $DIR/suggest-tryinto-edition-change.rs:16:19 + --> $DIR/suggest-tryinto-edition-change.rs:15:19 | LL | let _i: i16 = TryInto::try_into(0_i32).unwrap(); | ^^^^^^^ use of undeclared type `TryInto` | - = note: 'core::convert::TryInto' is included in the prelude starting in Edition 2021 = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 -help: consider importing one of these items - | -LL + use core::convert::TryInto; +help: consider importing this trait | LL + use std::convert::TryInto; | error[E0433]: failed to resolve: use of undeclared type `FromIterator` - --> $DIR/suggest-tryinto-edition-change.rs:22:22 + --> $DIR/suggest-tryinto-edition-change.rs:20:22 | LL | let _v: Vec<_> = FromIterator::from_iter(&[1]); | ^^^^^^^^^^^^ use of undeclared type `FromIterator` | - = note: 'core::iter::FromIterator' is included in the prelude starting in Edition 2021 = note: 'std::iter::FromIterator' is included in the prelude starting in Edition 2021 help: a trait with a similar name exists | LL | let _v: Vec<_> = IntoIterator::from_iter(&[1]); | ~~~~~~~~~~~~ -help: consider importing one of these items - | -LL + use core::iter::FromIterator; +help: consider importing this trait | LL + use std::iter::FromIterator; |