diff options
Diffstat (limited to 'compiler')
79 files changed, 503 insertions, 661 deletions
diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs index 699946f307b..805596ff00a 100644 --- a/compiler/rustc_ast/src/format.rs +++ b/compiler/rustc_ast/src/format.rs @@ -67,12 +67,6 @@ pub struct FormatArguments { names: FxHashMap<Symbol, usize>, } -// FIXME: Rustdoc has trouble proving Send/Sync for this. See #106930. -#[cfg(parallel_compiler)] -unsafe impl Sync for FormatArguments {} -#[cfg(parallel_compiler)] -unsafe impl Send for FormatArguments {} - impl FormatArguments { pub fn new() -> Self { Self { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 9cad8fa5318..be6eb2d1d12 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -886,6 +886,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { .universal_regions() .defining_ty .upvar_tys() + .iter() .position(|ty| self.any_param_predicate_mentions(&predicates, ty, region)) { let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region( diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 98418e2372f..8832d345df2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -43,7 +43,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr: RegionVid, ) -> Option<usize> { let upvar_index = - self.universal_regions().defining_ty.upvar_tys().position(|upvar_ty| { + self.universal_regions().defining_ty.upvar_tys().iter().position(|upvar_ty| { debug!("get_upvar_index_for_region: upvar_ty={upvar_ty:?}"); tcx.any_free_region_meets(&upvar_ty, |r| { let r = r.as_var(); @@ -52,7 +52,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) })?; - let upvar_ty = self.universal_regions().defining_ty.upvar_tys().nth(upvar_index); + let upvar_ty = self.universal_regions().defining_ty.upvar_tys().get(upvar_index); debug!( "get_upvar_index_for_region: found {fr:?} in upvar {upvar_index} which has type {upvar_ty:?}", diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index c19fbf20ca5..16f5e68a06f 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -90,11 +90,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ) { self.prove_predicate( ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Trait( - ty::TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, - polarity: ty::ImplPolarity::Positive, - }, + ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Positive }, ))), locations, category, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index fd4a3ec1a5e..abb11ce7396 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -791,25 +791,20 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { (adt_def.variant(FIRST_VARIANT), args) } ty::Closure(_, args) => { - return match args - .as_closure() - .tupled_upvars_ty() - .tuple_fields() - .get(field.index()) - { + return match args.as_closure().upvar_tys().get(field.index()) { Some(&ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: args.as_closure().upvar_tys().count(), + field_count: args.as_closure().upvar_tys().len(), }), }; } ty::Generator(_, args, _) => { // Only prefix fields (upvars and current state) are // accessible without a variant index. - return match args.as_generator().prefix_tys().nth(field.index()) { - Some(ty) => Ok(ty), + return match args.as_generator().prefix_tys().get(field.index()) { + Some(ty) => Ok(*ty), None => Err(FieldAccessError::OutOfRange { - field_count: args.as_generator().prefix_tys().count(), + field_count: args.as_generator().prefix_tys().len(), }), }; } @@ -1772,10 +1767,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } AggregateKind::Closure(_, args) => { - match args.as_closure().upvar_tys().nth(field_index.as_usize()) { - Some(ty) => Ok(ty), + match args.as_closure().upvar_tys().get(field_index.as_usize()) { + Some(ty) => Ok(*ty), None => Err(FieldAccessError::OutOfRange { - field_count: args.as_closure().upvar_tys().count(), + field_count: args.as_closure().upvar_tys().len(), }), } } @@ -1783,10 +1778,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // It doesn't make sense to look at a field beyond the prefix; // these require a variant index, and are not initialized in // aggregate rvalues. - match args.as_generator().prefix_tys().nth(field_index.as_usize()) { - Some(ty) => Ok(ty), + match args.as_generator().prefix_tys().get(field_index.as_usize()) { + Some(ty) => Ok(*ty), None => Err(FieldAccessError::OutOfRange { - field_count: args.as_generator().prefix_tys().count(), + field_count: args.as_generator().prefix_tys().len(), }), } } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index a751a9732f0..56945f43fcd 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -12,7 +12,6 @@ //! The code in this file doesn't *do anything* with those results; it //! just returns them for other code to use. -use either::Either; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; use rustc_hir as hir; @@ -115,14 +114,12 @@ impl<'tcx> DefiningTy<'tcx> { /// not a closure or generator, there are no upvars, and hence it /// will be an empty list. The order of types in this list will /// match up with the upvar order in the HIR, typesystem, and MIR. - pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx { + pub fn upvar_tys(self) -> &'tcx ty::List<Ty<'tcx>> { match self { - DefiningTy::Closure(_, args) => Either::Left(args.as_closure().upvar_tys()), - DefiningTy::Generator(_, args, _) => { - Either::Right(Either::Left(args.as_generator().upvar_tys())) - } + DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(), + DefiningTy::Generator(_, args, _) => args.as_generator().upvar_tys(), DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => { - Either::Right(Either::Right(iter::empty())) + ty::List::empty() } } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 6ca61aa43d7..7a82d05ce9e 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -85,3 +85,197 @@ impl CounterExpression { Self { kind, lhs, rhs } } } + +/// Corresponds to enum `llvm::coverage::CounterMappingRegion::RegionKind`. +/// +/// Must match the layout of `LLVMRustCounterMappingRegionKind`. +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub enum RegionKind { + /// A CodeRegion associates some code with a counter + CodeRegion = 0, + + /// An ExpansionRegion represents a file expansion region that associates + /// a source range with the expansion of a virtual source file, such as + /// for a macro instantiation or #include file. + ExpansionRegion = 1, + + /// A SkippedRegion represents a source range with code that was skipped + /// by a preprocessor or similar means. + SkippedRegion = 2, + + /// A GapRegion is like a CodeRegion, but its count is only set as the + /// line execution count when its the only region in the line. + GapRegion = 3, + + /// A BranchRegion represents leaf-level boolean expressions and is + /// associated with two counters, each representing the number of times the + /// expression evaluates to true or false. + BranchRegion = 4, +} + +/// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the +/// coverage map, in accordance with the +/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format). +/// The struct composes fields representing the `Counter` type and value(s) (injected counter +/// ID, or expression type and operands), the source file (an indirect index into a "filenames +/// array", encoded separately), and source location (start and end positions of the represented +/// code region). +/// +/// Corresponds to struct `llvm::coverage::CounterMappingRegion`. +/// +/// Must match the layout of `LLVMRustCounterMappingRegion`. +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub struct CounterMappingRegion { + /// The counter type and type-dependent counter data, if any. + counter: Counter, + + /// If the `RegionKind` is a `BranchRegion`, this represents the counter + /// for the false branch of the region. + false_counter: Counter, + + /// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the + /// file_id is an index into a function-specific `virtual_file_mapping` array of indexes + /// that, in turn, are used to look up the filename for this region. + file_id: u32, + + /// If the `RegionKind` is an `ExpansionRegion`, the `expanded_file_id` can be used to find + /// the mapping regions created as a result of macro expansion, by checking if their file id + /// matches the expanded file id. + expanded_file_id: u32, + + /// 1-based starting line of the mapping region. + start_line: u32, + + /// 1-based starting column of the mapping region. + start_col: u32, + + /// 1-based ending line of the mapping region. + end_line: u32, + + /// 1-based ending column of the mapping region. If the high bit is set, the current + /// mapping region is a gap area. + end_col: u32, + + kind: RegionKind, +} + +impl CounterMappingRegion { + pub(crate) fn code_region( + counter: Counter, + file_id: u32, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { + counter, + false_counter: Counter::zero(), + file_id, + expanded_file_id: 0, + start_line, + start_col, + end_line, + end_col, + kind: RegionKind::CodeRegion, + } + } + + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + pub(crate) fn branch_region( + counter: Counter, + false_counter: Counter, + file_id: u32, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { + counter, + false_counter, + file_id, + expanded_file_id: 0, + start_line, + start_col, + end_line, + end_col, + kind: RegionKind::BranchRegion, + } + } + + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + pub(crate) fn expansion_region( + file_id: u32, + expanded_file_id: u32, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { + counter: Counter::zero(), + false_counter: Counter::zero(), + file_id, + expanded_file_id, + start_line, + start_col, + end_line, + end_col, + kind: RegionKind::ExpansionRegion, + } + } + + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + pub(crate) fn skipped_region( + file_id: u32, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { + counter: Counter::zero(), + false_counter: Counter::zero(), + file_id, + expanded_file_id: 0, + start_line, + start_col, + end_line, + end_col, + kind: RegionKind::SkippedRegion, + } + } + + // This function might be used in the future; the LLVM API is still evolving, as is coverage + // support. + #[allow(dead_code)] + pub(crate) fn gap_region( + counter: Counter, + file_id: u32, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { + counter, + false_counter: Counter::zero(), + file_id, + expanded_file_id: 0, + start_line, + start_col, + end_line, + end_col: (1_u32 << 31) | end_col, + kind: RegionKind::GapRegion, + } + } +} diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs index 7e981af0a53..f1e68af25d4 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs @@ -1,4 +1,4 @@ -pub use super::ffi::*; +use crate::coverageinfo::ffi::{Counter, CounterExpression, ExprKind}; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::bug; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 9149b06886b..db9ba0abbde 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -1,9 +1,8 @@ use crate::common::CodegenCx; use crate::coverageinfo; -use crate::coverageinfo::map_data::{Counter, CounterExpression}; +use crate::coverageinfo::ffi::{Counter, CounterExpression, CounterMappingRegion}; use crate::llvm; -use llvm::coverageinfo::CounterMappingRegion; use rustc_codegen_ssa::traits::ConstMethods; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def::DefKind; diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index c1017ab8d7c..afceb7531e6 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -3,10 +3,10 @@ use crate::llvm; use crate::abi::Abi; use crate::builder::Builder; use crate::common::CodegenCx; -use crate::coverageinfo::map_data::{CounterExpression, FunctionCoverage}; +use crate::coverageinfo::ffi::{CounterExpression, CounterMappingRegion}; +use crate::coverageinfo::map_data::FunctionCoverage; use libc::c_uint; -use llvm::coverageinfo::CounterMappingRegion; use rustc_codegen_ssa::traits::{ BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, MiscMethods, StaticMethods, @@ -27,7 +27,7 @@ use rustc_middle::ty::Ty; use std::cell::RefCell; use std::ffi::CString; -mod ffi; +pub(crate) mod ffi; pub(crate) mod map_data; pub mod mapgen; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 40f0bcfdf58..f8cbcbd5ec8 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -990,14 +990,8 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( closure_or_generator_di_node: &'ll DIType, ) -> SmallVec<&'ll DIType> { let (&def_id, up_var_tys) = match closure_or_generator_ty.kind() { - ty::Generator(def_id, args, _) => { - let upvar_tys: SmallVec<_> = args.as_generator().prefix_tys().collect(); - (def_id, upvar_tys) - } - ty::Closure(def_id, args) => { - let upvar_tys: SmallVec<_> = args.as_closure().upvar_tys().collect(); - (def_id, upvar_tys) - } + ty::Generator(def_id, args, _) => (def_id, args.as_generator().prefix_tys()), + ty::Closure(def_id, args) => (def_id, args.as_closure().upvar_tys()), _ => { bug!( "build_upvar_field_di_nodes() called with non-closure-or-generator-type: {:?}", @@ -1007,9 +1001,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( }; debug_assert!( - up_var_tys - .iter() - .all(|&t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) + up_var_tys.iter().all(|t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) ); let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index b4beb80ca8b..d3239d5c358 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -379,6 +379,7 @@ pub fn build_generator_variant_struct_type_di_node<'ll, 'tcx>( // Fields that are common to all states let common_fields: SmallVec<_> = generator_args .prefix_tys() + .iter() .zip(common_upvar_names) .enumerate() .map(|(index, (upvar_ty, upvar_name))| { diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 7407cfa8c5b..b167facfb02 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1,8 +1,6 @@ #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] -use crate::coverageinfo::map_data as coverage_map; - use super::debuginfo::{ DIArray, DIBasicType, DIBuilder, DICompositeType, DIDerivedType, DIDescriptor, DIEnumerator, DIFile, DIFlags, DIGlobalVariableExpression, DILexicalBlock, DILocation, DINameSpace, @@ -688,204 +686,6 @@ extern "C" { pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint); -pub mod coverageinfo { - use super::coverage_map; - - /// Corresponds to enum `llvm::coverage::CounterMappingRegion::RegionKind`. - /// - /// Must match the layout of `LLVMRustCounterMappingRegionKind`. - #[derive(Copy, Clone, Debug)] - #[repr(C)] - pub enum RegionKind { - /// A CodeRegion associates some code with a counter - CodeRegion = 0, - - /// An ExpansionRegion represents a file expansion region that associates - /// a source range with the expansion of a virtual source file, such as - /// for a macro instantiation or #include file. - ExpansionRegion = 1, - - /// A SkippedRegion represents a source range with code that was skipped - /// by a preprocessor or similar means. - SkippedRegion = 2, - - /// A GapRegion is like a CodeRegion, but its count is only set as the - /// line execution count when its the only region in the line. - GapRegion = 3, - - /// A BranchRegion represents leaf-level boolean expressions and is - /// associated with two counters, each representing the number of times the - /// expression evaluates to true or false. - BranchRegion = 4, - } - - /// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the - /// coverage map, in accordance with the - /// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format). - /// The struct composes fields representing the `Counter` type and value(s) (injected counter - /// ID, or expression type and operands), the source file (an indirect index into a "filenames - /// array", encoded separately), and source location (start and end positions of the represented - /// code region). - /// - /// Corresponds to struct `llvm::coverage::CounterMappingRegion`. - /// - /// Must match the layout of `LLVMRustCounterMappingRegion`. - #[derive(Copy, Clone, Debug)] - #[repr(C)] - pub struct CounterMappingRegion { - /// The counter type and type-dependent counter data, if any. - counter: coverage_map::Counter, - - /// If the `RegionKind` is a `BranchRegion`, this represents the counter - /// for the false branch of the region. - false_counter: coverage_map::Counter, - - /// An indirect reference to the source filename. In the LLVM Coverage Mapping Format, the - /// file_id is an index into a function-specific `virtual_file_mapping` array of indexes - /// that, in turn, are used to look up the filename for this region. - file_id: u32, - - /// If the `RegionKind` is an `ExpansionRegion`, the `expanded_file_id` can be used to find - /// the mapping regions created as a result of macro expansion, by checking if their file id - /// matches the expanded file id. - expanded_file_id: u32, - - /// 1-based starting line of the mapping region. - start_line: u32, - - /// 1-based starting column of the mapping region. - start_col: u32, - - /// 1-based ending line of the mapping region. - end_line: u32, - - /// 1-based ending column of the mapping region. If the high bit is set, the current - /// mapping region is a gap area. - end_col: u32, - - kind: RegionKind, - } - - impl CounterMappingRegion { - pub(crate) fn code_region( - counter: coverage_map::Counter, - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter, - false_counter: coverage_map::Counter::zero(), - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::CodeRegion, - } - } - - // This function might be used in the future; the LLVM API is still evolving, as is coverage - // support. - #[allow(dead_code)] - pub(crate) fn branch_region( - counter: coverage_map::Counter, - false_counter: coverage_map::Counter, - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter, - false_counter, - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::BranchRegion, - } - } - - // This function might be used in the future; the LLVM API is still evolving, as is coverage - // support. - #[allow(dead_code)] - pub(crate) fn expansion_region( - file_id: u32, - expanded_file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter: coverage_map::Counter::zero(), - false_counter: coverage_map::Counter::zero(), - file_id, - expanded_file_id, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::ExpansionRegion, - } - } - - // This function might be used in the future; the LLVM API is still evolving, as is coverage - // support. - #[allow(dead_code)] - pub(crate) fn skipped_region( - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter: coverage_map::Counter::zero(), - false_counter: coverage_map::Counter::zero(), - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col, - kind: RegionKind::SkippedRegion, - } - } - - // This function might be used in the future; the LLVM API is still evolving, as is coverage - // support. - #[allow(dead_code)] - pub(crate) fn gap_region( - counter: coverage_map::Counter, - file_id: u32, - start_line: u32, - start_col: u32, - end_line: u32, - end_col: u32, - ) -> Self { - Self { - counter, - false_counter: coverage_map::Counter::zero(), - file_id, - expanded_file_id: 0, - start_line, - start_col, - end_line, - end_col: (1_u32 << 31) | end_col, - kind: RegionKind::GapRegion, - } - } - } -} - pub mod debuginfo { use super::{InvariantOpaque, Metadata}; use bitflags::bitflags; @@ -1911,9 +1711,9 @@ extern "C" { pub fn LLVMRustCoverageWriteMappingToBuffer( VirtualFileMappingIDs: *const c_uint, NumVirtualFileMappingIDs: c_uint, - Expressions: *const coverage_map::CounterExpression, + Expressions: *const crate::coverageinfo::ffi::CounterExpression, NumExpressions: c_uint, - MappingRegions: *const coverageinfo::CounterMappingRegion, + MappingRegions: *const crate::coverageinfo::ffi::CounterMappingRegion, NumMappingRegions: c_uint, BufferOut: &RustString, ); diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 671c2be1de9..2905874eec5 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -282,7 +282,7 @@ const_eval_pointer_out_of_bounds = *[many] bytes } starting at offset {$ptr_offset} is out-of-bounds const_eval_pointer_use_after_free = - pointer to {$allocation} was dereferenced after this allocation got freed + {$bad_pointer_message}: {$alloc_id} has been freed, so this pointer is dangling const_eval_ptr_as_bytes_1 = this code performed an operation that depends on the underlying bytes representing a pointer const_eval_ptr_as_bytes_2 = diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 6630eeca27e..032f4be6c99 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -214,9 +214,9 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> { // &str or &&str assert!(args.len() == 1); - let mut msg_place = self.deref_operand(&args[0])?; + let mut msg_place = self.deref_pointer(&args[0])?; while msg_place.layout.ty.is_ref() { - msg_place = self.deref_operand(&msg_place)?; + msg_place = self.deref_pointer(&msg_place)?; } let msg = Symbol::intern(self.read_str(&msg_place)?); diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 7c1dbddfc26..f785bcfed6c 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -102,7 +102,7 @@ pub(crate) fn const_to_valtree_inner<'tcx>( ty::FnPtr(_) | ty::RawPtr(_) => Err(ValTreeCreationError::NonSupportedType), ty::Ref(_, _, _) => { - let Ok(derefd_place)= ecx.deref_operand(place) else { + let Ok(derefd_place)= ecx.deref_pointer(place) else { return Err(ValTreeCreationError::Other); }; debug!(?derefd_place); diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index e1109e584b7..8cbc68d9061 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -492,7 +492,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { InvalidMeta(InvalidMetaKind::SliceTooBig) => const_eval_invalid_meta_slice, InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta, UnterminatedCString(_) => const_eval_unterminated_c_string, - PointerUseAfterFree(_) => const_eval_pointer_use_after_free, + PointerUseAfterFree(_, _) => const_eval_pointer_use_after_free, PointerOutOfBounds { ptr_size: Size::ZERO, .. } => const_eval_zst_pointer_out_of_bounds, PointerOutOfBounds { .. } => const_eval_pointer_out_of_bounds, DanglingIntPointer(0, _) => const_eval_dangling_null_pointer, @@ -545,8 +545,10 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> { UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => { builder.set_arg("pointer", ptr); } - PointerUseAfterFree(allocation) => { - builder.set_arg("allocation", allocation); + PointerUseAfterFree(alloc_id, msg) => { + builder + .set_arg("alloc_id", alloc_id) + .set_arg("bad_pointer_message", bad_pointer_message(msg, handler)); } PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => { builder diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index be7c14f33c2..29f3e6c724b 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -144,7 +144,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } sym::min_align_of_val | sym::size_of_val => { - // Avoid `deref_operand` -- this is not a deref, the ptr does not have to be + // Avoid `deref_pointer` -- this is not a deref, the ptr does not have to be // dereferenceable! let place = self.ref_to_mplace(&self.read_immediate(&args[0])?)?; let (size, align) = self @@ -225,7 +225,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(val, dest)?; } sym::discriminant_value => { - let place = self.deref_operand(&args[0])?; + let place = self.deref_pointer(&args[0])?; let variant = self.read_discriminant(&place)?; let discr = self.discriminant_for_variant(place.layout, variant)?; self.write_scalar(discr, dest)?; diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 02d022a2252..940a312d03b 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -317,7 +317,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { kind = "static_mem" ) } - None => err_ub!(PointerUseAfterFree(alloc_id)), + None => err_ub!(PointerUseAfterFree(alloc_id, CheckInAllocMsg::MemoryAccessTest)), } .into()); }; @@ -380,7 +380,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { M::enforce_alignment(self), CheckInAllocMsg::MemoryAccessTest, |alloc_id, offset, prov| { - let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?; + let (size, align) = self + .get_live_alloc_size_and_align(alloc_id, CheckInAllocMsg::MemoryAccessTest)?; Ok((size, align, (alloc_id, offset, prov))) }, ) @@ -404,7 +405,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { CheckAlignment::Error, msg, |alloc_id, _, _| { - let (size, align) = self.get_live_alloc_size_and_align(alloc_id)?; + let (size, align) = self.get_live_alloc_size_and_align(alloc_id, msg)?; Ok((size, align, ())) }, )?; @@ -414,7 +415,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Low-level helper function to check if a ptr is in-bounds and potentially return a reference /// to the allocation it points to. Supports both shared and mutable references, as the actual /// checking is offloaded to a helper closure. `align` defines whether and which alignment check - /// is done. Returns `None` for size 0, and otherwise `Some` of what `alloc_size` returned. + /// is done. + /// + /// If this returns `None`, the size is 0; it can however return `Some` even for size 0. fn check_and_deref_ptr<T>( &self, ptr: Pointer<Option<M::Provenance>>, @@ -515,7 +518,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } Some(GlobalAlloc::Function(..)) => throw_ub!(DerefFunctionPointer(id)), Some(GlobalAlloc::VTable(..)) => throw_ub!(DerefVTablePointer(id)), - None => throw_ub!(PointerUseAfterFree(id)), + None => throw_ub!(PointerUseAfterFree(id, CheckInAllocMsg::MemoryAccessTest)), Some(GlobalAlloc::Static(def_id)) => { assert!(self.tcx.is_static(def_id)); assert!(!self.tcx.is_thread_local_static(def_id)); @@ -761,11 +764,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - /// Obtain the size and alignment of a live allocation. - pub fn get_live_alloc_size_and_align(&self, id: AllocId) -> InterpResult<'tcx, (Size, Align)> { + /// Obtain the size and alignment of a *live* allocation. + fn get_live_alloc_size_and_align( + &self, + id: AllocId, + msg: CheckInAllocMsg, + ) -> InterpResult<'tcx, (Size, Align)> { let (size, align, kind) = self.get_alloc_info(id); if matches!(kind, AllocKind::Dead) { - throw_ub!(PointerUseAfterFree(id)) + throw_ub!(PointerUseAfterFree(id, msg)) } Ok((size, align)) } diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 96a960118ce..5f4f5434b18 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -419,7 +419,7 @@ where /// /// Only call this if you are sure the place is "valid" (aligned and inbounds), or do not /// want to ever use the place for memory access! - /// Generally prefer `deref_operand`. + /// Generally prefer `deref_pointer`. pub fn ref_to_mplace( &self, val: &ImmTy<'tcx, M::Provenance>, @@ -439,8 +439,9 @@ where } /// Take an operand, representing a pointer, and dereference it to a place. + /// Corresponds to the `*` operator in Rust. #[instrument(skip(self), level = "debug")] - pub fn deref_operand( + pub fn deref_pointer( &self, src: &impl Readable<'tcx, M::Provenance>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index bce43aedb69..539b58b7e9b 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -290,7 +290,7 @@ where OpaqueCast(ty) => base.transmute(self.layout_of(ty)?, self)?, Field(field, _) => self.project_field(base, field.index())?, Downcast(_, variant) => self.project_downcast(base, variant)?, - Deref => self.deref_operand(&base.to_op(self)?)?.into(), + Deref => self.deref_pointer(&base.to_op(self)?)?.into(), Index(local) => { let layout = self.layout_of(self.tcx.types.usize)?; let n = self.local_to_op(self.frame(), local, Some(layout))?; diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index ead172f04a3..0ef5522729a 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -224,8 +224,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Len(place) => { let src = self.eval_place(place)?; - let op = self.place_to_op(&src)?; - let len = op.len(self)?; + let len = src.len(self)?; self.write_scalar(Scalar::from_target_usize(len, self), &dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index d0191ea978a..bf33c5cca10 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -661,7 +661,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let receiver_place = loop { match receiver.layout.ty.kind() { ty::Ref(..) | ty::RawPtr(..) => { - // We do *not* use `deref_operand` here: we don't want to conceptually + // We do *not* use `deref_pointer` here: we don't want to conceptually // create a place that must be dereferenceable, since the receiver might // be a raw pointer and (for `*const dyn Trait`) we don't need to // actually access memory to resolve this method. diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index aee95f70bc2..ff22d3d2d5a 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -345,6 +345,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' value: &OpTy<'tcx, M::Provenance>, ptr_kind: PointerKind, ) -> InterpResult<'tcx> { + // Not using `deref_pointer` since we do the dereferenceable check ourselves below. let place = self.ecx.ref_to_mplace(&self.read_immediate(value, ptr_kind.into())?)?; // Handle wide pointers. // Check metadata early, for better diagnostics @@ -515,9 +516,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' Ok(true) } ty::RawPtr(..) => { - // We are conservative with uninit for integers, but try to - // actually enforce the strict rules for raw pointers (mostly because - // that lets us re-use `ref_to_mplace`). let place = self.ecx.ref_to_mplace(&self.read_immediate(value, ExpectedKind::RawPtr)?)?; if place.layout.is_unsized() { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index ad5ffa6511f..b077c10907e 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -746,6 +746,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } // Attempting to call a trait method? + // FIXME(effects) do we need this? if let Some(trait_id) = tcx.trait_of_item(callee) { trace!("attempting to call a trait method"); if !self.tcx.features().const_trait_impl { @@ -761,7 +762,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { } let trait_ref = TraitRef::from_method(tcx, trait_id, fn_args); - let trait_ref = trait_ref.with_constness(ty::BoundConstness::ConstIfConst); let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index b152644a551..8293bdfd969 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -155,12 +155,12 @@ impl Qualif for NeedsNonConstDrop { return false; } + // FIXME(effects) constness let obligation = Obligation::new( cx.tcx, ObligationCause::dummy_with_span(cx.body.span), cx.param_env, - ty::TraitRef::from_lang_item(cx.tcx, LangItem::Destruct, cx.body.span, [ty]) - .with_constness(ty::BoundConstness::ConstIfConst), + ty::TraitRef::from_lang_item(cx.tcx, LangItem::Destruct, cx.body.span, [ty]), ); let infcx = cx.tcx.infer_ctxt().build(); diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 31effadd2c2..83004492c8b 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -630,7 +630,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } ty::Closure(_, args) => { let args = args.as_closure(); - let Some(f_ty) = args.upvar_tys().nth(f.as_usize()) else { + let Some(&f_ty) = args.upvar_tys().get(f.as_usize()) else { fail_out_of_bounds(self, location); return; }; @@ -667,7 +667,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { f_ty.ty } else { - let Some(f_ty) = args.as_generator().prefix_tys().nth(f.index()) else { + let Some(&f_ty) = args.as_generator().prefix_tys().get(f.index()) + else { fail_out_of_bounds(self, location); return; }; diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index bc109e7ad51..b40e3123522 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -713,7 +713,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); debug!(?poly_trait_ref, ?assoc_bindings); - bounds.push_trait_bound(tcx, poly_trait_ref, span, constness, polarity); + bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); let mut dup_bindings = FxHashMap::default(); for binding in &assoc_bindings { diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index a36ec0c5730..30c2ab8f545 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -62,11 +62,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { match bound_pred.skip_binder() { ty::ClauseKind::Trait(trait_pred) => { assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive); - trait_bounds.push(( - bound_pred.rebind(trait_pred.trait_ref), - span, - trait_pred.constness, - )); + trait_bounds.push((bound_pred.rebind(trait_pred.trait_ref), span)); } ty::ClauseKind::Projection(proj) => { projection_bounds.push((bound_pred.rebind(proj), span)); @@ -86,7 +82,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Expand trait aliases recursively and check that only one regular (non-auto) trait // is used and no 'maybe' bounds are used. let expanded_traits = - traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b))); + traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b))); let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self) @@ -126,7 +122,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if regular_traits.is_empty() && auto_traits.is_empty() { let trait_alias_span = trait_bounds .iter() - .map(|&(trait_ref, _, _)| trait_ref.def_id()) + .map(|&(trait_ref, _)| trait_ref.def_id()) .find(|&trait_ref| tcx.is_trait_alias(trait_ref)) .map(|trait_ref| tcx.def_span(trait_ref)); let reported = @@ -157,10 +153,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let regular_traits_refs_spans = trait_bounds .into_iter() - .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id())); + .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); - for (base_trait_ref, span, constness) in regular_traits_refs_spans { - assert_eq!(constness, ty::BoundConstness::NotConst); + for (base_trait_ref, span) in regular_traits_refs_spans { let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx); for pred in traits::elaborate(tcx, [base_pred]) { debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred); diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index 531100e1fe6..1d9ae2b9cb7 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -42,13 +42,12 @@ impl<'tcx> Bounds<'tcx> { tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, span: Span, - constness: ty::BoundConstness, polarity: ty::ImplPolarity, ) { self.clauses.push(( trait_ref .map_bound(|trait_ref| { - ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness, polarity }) + ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity }) }) .to_predicate(tcx), span, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 6206ba508ae..e64848da86b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -194,7 +194,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span. match (tcx.impl_polarity(def_id), impl_.polarity) { (ty::ImplPolarity::Positive, _) => { - check_impl(tcx, item, impl_.self_ty, &impl_.of_trait, impl_.constness); + check_impl(tcx, item, impl_.self_ty, &impl_.of_trait); } (ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => { // FIXME(#27579): what amount of WF checking do we need for neg impls? @@ -1191,7 +1191,6 @@ fn check_impl<'tcx>( item: &'tcx hir::Item<'tcx>, ast_self_ty: &hir::Ty<'_>, ast_trait_ref: &Option<hir::TraitRef<'_>>, - constness: hir::Constness, ) { enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| { match ast_trait_ref { @@ -1205,14 +1204,8 @@ fn check_impl<'tcx>( Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), trait_ref, ); - let trait_pred = ty::TraitPredicate { - trait_ref, - constness: match constness { - hir::Constness::Const => ty::BoundConstness::ConstIfConst, - hir::Constness::NotConst => ty::BoundConstness::NotConst, - }, - polarity: ty::ImplPolarity::Positive, - }; + let trait_pred = + ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Positive }; let mut obligations = traits::wf::trait_obligations( wfcx.infcx, wfcx.param_env, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index ab3b2dde078..2950ce683a3 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -10,7 +10,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{GenericPredicates, Generics, ImplTraitInTraitData, ToPredicate}; -use rustc_span::symbol::{sym, Ident}; +use rustc_span::symbol::Ident; use rustc_span::{Span, Symbol, DUMMY_SP}; /// Returns a list of all type predicates (explicit and implicit) for the definition with @@ -37,17 +37,10 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic // from the trait itself that *shouldn't* be shown as the source of // an obligation and instead be skipped. Otherwise we'd use // `tcx.def_span(def_id);` - - let constness = if tcx.has_attr(def_id, sym::const_trait) { - ty::BoundConstness::ConstIfConst - } else { - ty::BoundConstness::NotConst - }; - let span = rustc_span::DUMMY_SP; result.predicates = tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once(( - ty::TraitRef::identity(tcx, def_id).with_constness(constness).to_predicate(tcx), + ty::TraitRef::identity(tcx, def_id).to_predicate(tcx), span, )))); } @@ -204,7 +197,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // (see below). Recall that a default impl is not itself an impl, but rather a // set of defaults that can be incorporated into another impl. if let Some(trait_ref) = is_default_impl_trait { - predicates.insert((trait_ref.without_const().to_predicate(tcx), tcx.def_span(def_id))); + predicates.insert((trait_ref.to_predicate(tcx), tcx.def_span(def_id))); } // Collect the region predicates that were declared inline as @@ -777,8 +770,7 @@ pub(super) fn type_param_predicates( if param_id == item_hir_id { let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id.to_def_id()); - extend = - Some((identity_trait_ref.without_const().to_predicate(tcx), item.span)); + extend = Some((identity_trait_ref.to_predicate(tcx), item.span)); } generics } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 8b2c93d8fd3..3760195a5e8 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -431,45 +431,13 @@ fn check_predicates<'tcx>( /// /// So we make that check in this function and try to raise a helpful error message. fn trait_predicates_eq<'tcx>( - tcx: TyCtxt<'tcx>, + _tcx: TyCtxt<'tcx>, predicate1: ty::Predicate<'tcx>, predicate2: ty::Predicate<'tcx>, - span: Span, + _span: Span, ) -> bool { - let pred1_kind = predicate1.kind().skip_binder(); - let pred2_kind = predicate2.kind().skip_binder(); - let (trait_pred1, trait_pred2) = match (pred1_kind, pred2_kind) { - ( - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred1)), - ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred2)), - ) => (pred1, pred2), - // Just use plain syntactic equivalence if either of the predicates aren't - // trait predicates or have bound vars. - _ => return predicate1 == predicate2, - }; - - let predicates_equal_modulo_constness = { - let pred1_unconsted = - ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..trait_pred1 }; - let pred2_unconsted = - ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..trait_pred2 }; - pred1_unconsted == pred2_unconsted - }; - - if !predicates_equal_modulo_constness { - return false; - } - - // Check that the predicate on the specializing impl is at least as const as - // the one on the base. - match (trait_pred2.constness, trait_pred1.constness) { - (ty::BoundConstness::ConstIfConst, ty::BoundConstness::NotConst) => { - tcx.sess.emit_err(errors::MissingTildeConst { span }); - } - _ => {} - } - - true + // FIXME(effects) + predicate1 == predicate2 } #[instrument(level = "debug", skip(tcx))] @@ -482,7 +450,6 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc // items. ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, - constness: _, polarity: _, })) => { if !matches!( @@ -536,7 +503,6 @@ fn trait_predicate_kind<'tcx>( match predicate.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, - constness: _, polarity: _, })) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind), ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_)) diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 1ef257e87d6..6952a3fa66f 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -156,7 +156,6 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc match pred.kind().skip_binder() { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref: ty::TraitRef { def_id: _, args, .. }, - constness: _, polarity: _, }) => { for subst in &args[1..] { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 8f5737dd4ad..eb6359ed72f 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2988,7 +2988,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Binder::dummy(ty::TraitPredicate { trait_ref: impl_trait_ref, polarity: ty::ImplPolarity::Positive, - constness: ty::BoundConstness::NotConst, }), |derived| { traits::ImplDerivedObligation(Box::new( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index ecafb50f420..1433c67d55d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1461,10 +1461,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param_env, bounds, ) { - // N.B. We are remapping all predicates to non-const since we don't know if we just - // want them as function pointers or we are calling them from a const-context. The - // actual checking will occur in `rustc_const_eval::transform::check_consts`. - self.register_predicate(obligation.without_const(self.tcx)); + self.register_predicate(obligation); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index e102c51c7ee..e3d97b41980 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1856,19 +1856,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.adjust_fulfillment_error_for_expr_obligation(error) || before_span != error.obligation.cause.span { - // Store both the predicate and the predicate *without constness* - // since sometimes we instantiate and check both of these in a - // method call, for example. remap_cause.insert(( before_span, error.obligation.predicate, error.obligation.cause.clone(), )); - remap_cause.insert(( - before_span, - error.obligation.predicate.without_const(self.tcx), - error.obligation.cause.clone(), - )); } else { // If it failed to be adjusted once around, it may be adjusted // via the "remap cause" mapping the second time... diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 356e7022aea..597696843c4 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -341,15 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Construct an obligation let poly_trait_ref = ty::Binder::dummy(trait_ref); - ( - traits::Obligation::new( - self.tcx, - cause, - self.param_env, - poly_trait_ref.without_const(), - ), - args, - ) + (traits::Obligation::new(self.tcx, cause, self.param_env, poly_trait_ref), args) } /// `lookup_method_in_trait` is used for overloaded operators. diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 05eed1923d1..7164102a30e 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1599,8 +1599,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } } - let predicate = - ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx); + let predicate = ty::Binder::dummy(trait_ref).to_predicate(self.tcx); parent_pred = Some(predicate); let obligation = traits::Obligation::new(self.tcx, cause.clone(), self.param_env, predicate); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index f6c07931023..b9d8c5a7540 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -94,7 +94,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, self.body_id, self.param_env, - poly_trait_ref.without_const(), + poly_trait_ref, ); self.predicate_may_hold(&obligation) }) diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 9c90b704586..a6052f52917 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -448,7 +448,9 @@ where ty::Closure(_, ref args) => { // Skip lifetime parameters of the enclosing item(s) - args.as_closure().tupled_upvars_ty().visit_with(self); + for upvar in args.as_closure().upvar_tys() { + upvar.visit_with(self); + } args.as_closure().sig_as_fn_ptr_ty().visit_with(self); } @@ -456,7 +458,9 @@ where // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. - args.as_generator().tupled_upvars_ty().visit_with(self); + for upvar in args.as_generator().upvar_tys() { + upvar.visit_with(self); + } args.as_generator().return_ty().visit_with(self); args.as_generator().yield_ty().visit_with(self); args.as_generator().resume_ty().visit_with(self); diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index 11f43469400..64b9714c7c0 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -25,7 +25,7 @@ pub trait TraitEngine<'tcx>: 'tcx { cause, recursion_depth: 0, param_env, - predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(infcx.tcx), + predicate: ty::Binder::dummy(trait_ref).to_predicate(infcx.tcx), }, ); } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index a9da6104b38..dc41630196b 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -77,13 +77,6 @@ impl<'tcx> PredicateObligation<'tcx> { recursion_depth: self.recursion_depth, }) } - - pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> PredicateObligation<'tcx> { - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = self.predicate.kind().skip_binder() && trait_pred.is_const_if_const() { - self.predicate = tcx.mk_predicate(self.predicate.kind().map_bound(|_| ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred.without_const())))); - } - self - } } impl<'tcx> PolyTraitObligation<'tcx> { diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 87ba6b3ec50..93dfbe63bcd 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -264,11 +264,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { }; let obligations = - predicates.predicates.iter().enumerate().map(|(index, &(mut clause, span))| { - // when parent predicate is non-const, elaborate it to non-const predicates. - if data.constness == ty::BoundConstness::NotConst { - clause = clause.without_const(tcx); - } + predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| { elaboratable.child_with_derived_cause( clause.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), span, diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 16e17fc9d6a..f482e3d7c12 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -318,7 +318,11 @@ lint_invalid_nan_comparisons_eq_ne = incorrect NaN comparison, NaN cannot be dir lint_invalid_nan_comparisons_lt_le_gt_ge = incorrect NaN comparison, NaN is not orderable -lint_invalid_reference_casting = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` +lint_invalid_reference_casting_assign_to_ref = assigning to `&T` is undefined behavior, consider using an `UnsafeCell` + .label = casting happend here + +lint_invalid_reference_casting_borrow_as_mut = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell` + .label = casting happend here lint_lintpass_by_hand = implementing `LintPass` by hand .help = try using `declare_lint_pass!` or `impl_lint_pass!` instead diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 53089294fe2..96fd3ccf774 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -218,7 +218,7 @@ late_lint_methods!( BoxPointers: BoxPointers, PathStatements: PathStatements, LetUnderscore: LetUnderscore, - InvalidReferenceCasting: InvalidReferenceCasting, + InvalidReferenceCasting: InvalidReferenceCasting::default(), // Depends on referenced function signatures in expressions UnusedResults: UnusedResults, NonUpperCaseGlobals: NonUpperCaseGlobals, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 968172693a9..a6a48bf4ffa 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -745,8 +745,18 @@ pub enum InvalidFromUtf8Diag { // reference_casting.rs #[derive(LintDiagnostic)] -#[diag(lint_invalid_reference_casting)] -pub struct InvalidReferenceCastingDiag; +pub enum InvalidReferenceCastingDiag { + #[diag(lint_invalid_reference_casting_borrow_as_mut)] + BorrowAsMut { + #[label] + orig_cast: Option<Span>, + }, + #[diag(lint_invalid_reference_casting_assign_to_ref)] + AssignToRef { + #[label] + orig_cast: Option<Span>, + }, +} // hidden_unicode_codepoints.rs #[derive(LintDiagnostic)] diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index d343aaf35d5..ed3d4721049 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -1,7 +1,8 @@ use rustc_ast::Mutability; -use rustc_hir::{Expr, ExprKind, MutTy, TyKind, UnOp}; -use rustc_middle::ty; -use rustc_span::sym; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, QPath, StmtKind, UnOp}; +use rustc_middle::ty::{self, TypeAndMut}; +use rustc_span::{sym, Span}; use crate::{lints::InvalidReferenceCastingDiag, LateContext, LateLintPass, LintContext}; @@ -12,7 +13,6 @@ declare_lint! { /// ### Example /// /// ```rust,compile_fail - /// # #![deny(invalid_reference_casting)] /// fn x(r: &i32) { /// unsafe { /// *(r as *const i32 as *mut i32) += 1; @@ -30,46 +30,103 @@ declare_lint! { /// `UnsafeCell` is the only way to obtain aliasable data that is considered /// mutable. INVALID_REFERENCE_CASTING, - Allow, + Deny, "casts of `&T` to `&mut T` without interior mutability" } -declare_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]); +#[derive(Default)] +pub struct InvalidReferenceCasting { + casted: FxHashMap<HirId, Span>, +} + +impl_lint_pass!(InvalidReferenceCasting => [INVALID_REFERENCE_CASTING]); impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { - let ExprKind::Unary(UnOp::Deref, e) = &expr.kind else { + fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx rustc_hir::Stmt<'tcx>) { + let StmtKind::Local(local) = stmt.kind else { + return; + }; + let Local { init: Some(init), els: None, .. } = local else { return; }; - let e = e.peel_blocks(); - let e = if let ExprKind::Cast(e, t) = e.kind - && let TyKind::Ptr(MutTy { mutbl: Mutability::Mut, .. }) = t.kind { - e - } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind - && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) - && cx.tcx.is_diagnostic_item(sym::ptr_cast_mut, def_id) { + if is_cast_from_const_to_mut(cx, init) { + self.casted.insert(local.pat.hir_id, init.span); + } + } + + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + // &mut <expr> + let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind { + expr + // <expr> = ... + } else if let ExprKind::Assign(expr, _, _) = expr.kind { + expr + // <expr> += ... + } else if let ExprKind::AssignOp(_, expr, _) = expr.kind { expr } else { return; }; - let e = e.peel_blocks(); - let e = if let ExprKind::Cast(e, t) = e.kind - && let TyKind::Ptr(MutTy { mutbl: Mutability::Not, .. }) = t.kind { - e - } else if let ExprKind::Call(path, [arg]) = e.kind - && let ExprKind::Path(ref qpath) = path.kind - && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && cx.tcx.is_diagnostic_item(sym::ptr_from_ref, def_id) { - arg + let ExprKind::Unary(UnOp::Deref, e) = &inner.kind else { + return; + }; + + let orig_cast = if is_cast_from_const_to_mut(cx, e) { + None + } else if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind + && let Res::Local(hir_id) = &path.res + && let Some(orig_cast) = self.casted.get(hir_id) { + Some(*orig_cast) } else { return; }; - let e = e.peel_blocks(); - if let ty::Ref(..) = cx.typeck_results().node_type(e.hir_id).kind() { - cx.emit_spanned_lint(INVALID_REFERENCE_CASTING, expr.span, InvalidReferenceCastingDiag); - } + cx.emit_spanned_lint( + INVALID_REFERENCE_CASTING, + expr.span, + if matches!(expr.kind, ExprKind::AddrOf(..)) { + InvalidReferenceCastingDiag::BorrowAsMut { orig_cast } + } else { + InvalidReferenceCastingDiag::AssignToRef { orig_cast } + }, + ); } } + +fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool { + let e = e.peel_blocks(); + + // <expr> as *mut ... + let e = if let ExprKind::Cast(e, t) = e.kind + && let ty::RawPtr(TypeAndMut { mutbl: Mutability::Mut, .. }) = cx.typeck_results().node_type(t.hir_id).kind() { + e + // <expr>.cast_mut() + } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind + && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id) + && cx.tcx.is_diagnostic_item(sym::ptr_cast_mut, def_id) { + expr + } else { + return false; + }; + + let e = e.peel_blocks(); + + // <expr> as *const ... + let e = if let ExprKind::Cast(e, t) = e.kind + && let ty::RawPtr(TypeAndMut { mutbl: Mutability::Not, .. }) = cx.typeck_results().node_type(t.hir_id).kind() { + e + // ptr::from_ref(<expr>) + } else if let ExprKind::Call(path, [arg]) = e.kind + && let ExprKind::Path(ref qpath) = path.kind + && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() + && cx.tcx.is_diagnostic_item(sym::ptr_from_ref, def_id) { + arg + } else { + return false; + }; + + let e = e.peel_blocks(); + matches!(cx.typeck_results().node_type(e.hir_id).kind(), ty::Ref(_, _, Mutability::Not)) +} diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 13b3dac85d1..cc58d51befd 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -25,6 +25,9 @@ metadata_conflicting_alloc_error_handler = metadata_conflicting_global_alloc = the `#[global_allocator]` in {$other_crate_name} conflicts with global allocator in: {$crate_name} +metadata_consider_adding_std = + consider adding the standard library to the sysroot with `x build library --target {$locator_triple}` + metadata_consider_building_std = consider building the standard library from source with `cargo build -Zbuild-std` diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index fca06c0f47c..91220629fb6 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -623,6 +623,7 @@ pub struct CannotFindCrate { pub is_nightly_build: bool, pub profiler_runtime: Symbol, pub locator_triple: TargetTriple, + pub is_ui_testing: bool, } impl IntoDiagnostic<'_> for CannotFindCrate { @@ -646,12 +647,19 @@ impl IntoDiagnostic<'_> for CannotFindCrate { } else { diag.note(fluent::metadata_target_no_std_support); } - // NOTE: this suggests using rustup, even though the user may not have it installed. - // That's because they could choose to install it; or this may give them a hint which - // target they need to install from their distro. + if self.missing_core { - diag.help(fluent::metadata_consider_downloading_target); + if env!("CFG_RELEASE_CHANNEL") == "dev" && !self.is_ui_testing { + // Note: Emits the nicer suggestion only for the dev channel. + diag.help(fluent::metadata_consider_adding_std); + } else { + // NOTE: this suggests using rustup, even though the user may not have it installed. + // That's because they could choose to install it; or this may give them a hint which + // target they need to install from their distro. + diag.help(fluent::metadata_consider_downloading_target); + } } + // Suggest using #![no_std]. #[no_core] is unstable and not really supported anyway. // NOTE: this is a dummy span if `extern crate std` was injected by the compiler. // If it's not a dummy, that means someone added `extern crate std` explicitly and diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index fb9dd660d2f..a0c552f5fd6 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -1130,6 +1130,7 @@ impl CrateError { is_nightly_build: sess.is_nightly_build(), profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: locator.triple, + is_ui_testing: sess.opts.unstable_opts.ui_testing, }); } } @@ -1146,6 +1147,7 @@ impl CrateError { is_nightly_build: sess.is_nightly_build(), profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: sess.opts.target_triple.clone(), + is_ui_testing: sess.opts.unstable_opts.ui_testing, }); } } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index d44dfa2172a..eaa6c0ce2d6 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -282,8 +282,8 @@ pub enum UndefinedBehaviorInfo<'a> { InvalidMeta(InvalidMetaKind), /// Reading a C string that does not end within its allocation. UnterminatedCString(Pointer), - /// Dereferencing a dangling pointer after it got freed. - PointerUseAfterFree(AllocId), + /// Using a pointer after it got freed. + PointerUseAfterFree(AllocId, CheckInAllocMsg), /// Used a pointer outside the bounds it is valid for. /// (If `ptr_size > 0`, determines the size of the memory range that was expected to be in-bounds.) PointerOutOfBounds { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0f7bed0845c..df39103bc19 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -911,7 +911,7 @@ where if i == tag_field { return TyMaybeWithLayout::TyAndLayout(tag_layout(tag)); } - TyMaybeWithLayout::Ty(args.as_generator().prefix_tys().nth(i).unwrap()) + TyMaybeWithLayout::Ty(args.as_generator().prefix_tys()[i]) } }, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2b4c834f766..6b0f0132062 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -498,11 +498,9 @@ impl<'tcx> Predicate<'tcx> { .map_bound(|kind| match kind { PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, - constness, polarity, })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, - constness, polarity: polarity.flip()?, }))), @@ -513,19 +511,6 @@ impl<'tcx> Predicate<'tcx> { Some(tcx.mk_predicate(kind)) } - pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> Self { - if let PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { trait_ref, constness, polarity })) = self.kind().skip_binder() - && constness != BoundConstness::NotConst - { - self = tcx.mk_predicate(self.kind().rebind(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate { - trait_ref, - constness: BoundConstness::NotConst, - polarity, - })))); - } - self - } - #[instrument(level = "debug", skip(tcx), ret)] pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool { match self.kind().skip_binder() { @@ -629,10 +614,6 @@ impl<'tcx> Clause<'tcx> { None } } - - pub fn without_const(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> { - self.as_predicate().without_const(tcx).expect_clause() - } } #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] @@ -852,8 +833,6 @@ impl<'tcx> Clause<'tcx> { pub struct TraitPredicate<'tcx> { pub trait_ref: TraitRef<'tcx>, - pub constness: BoundConstness, - /// If polarity is Positive: we are proving that the trait is implemented. /// /// If polarity is Negative: we are proving that a negative impl of this trait @@ -878,24 +857,6 @@ impl<'tcx> TraitPredicate<'tcx> { pub fn self_ty(self) -> Ty<'tcx> { self.trait_ref.self_ty() } - - #[inline] - pub fn is_const_if_const(self) -> bool { - self.constness == BoundConstness::ConstIfConst - } - - pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool { - match (self.constness, constness) { - (BoundConstness::NotConst, _) - | (BoundConstness::ConstIfConst, hir::Constness::Const) => true, - (BoundConstness::ConstIfConst, hir::Constness::NotConst) => false, - } - } - - pub fn without_const(mut self) -> Self { - self.constness = BoundConstness::NotConst; - self - } } impl<'tcx> PolyTraitPredicate<'tcx> { @@ -909,11 +870,6 @@ impl<'tcx> PolyTraitPredicate<'tcx> { } #[inline] - pub fn is_const_if_const(self) -> bool { - self.skip_binder().is_const_if_const() - } - - #[inline] pub fn polarity(self) -> ImplPolarity { self.skip_binder().polarity } @@ -1287,7 +1243,7 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> { #[inline(always)] fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> { - self.without_const() + TraitPredicate { trait_ref: self, polarity: ImplPolarity::Positive } } } @@ -1328,7 +1284,6 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { self.map_bound(|trait_ref| TraitPredicate { trait_ref, - constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Positive, }) } @@ -1826,24 +1781,6 @@ impl<'tcx> ParamEnv<'tcx> { } } -// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate(tcx)` to ensure that -// the constness of trait bounds is being propagated correctly. -impl<'tcx> PolyTraitRef<'tcx> { - #[inline] - pub fn with_constness(self, constness: BoundConstness) -> PolyTraitPredicate<'tcx> { - self.map_bound(|trait_ref| ty::TraitPredicate { - trait_ref, - constness, - polarity: ty::ImplPolarity::Positive, - }) - } - - #[inline] - pub fn without_const(self) -> PolyTraitPredicate<'tcx> { - self.with_constness(BoundConstness::NotConst) - } -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] #[derive(HashStable, Lift)] pub struct ParamEnvAnd<'tcx, T> { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f146f8aa8b4..6e68022031a 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -827,7 +827,7 @@ pub trait PrettyPrinter<'tcx>: if !args.as_generator().is_valid() { p!("unavailable"); } else { - self = self.comma_sep(args.as_generator().upvar_tys())?; + self = self.comma_sep(args.as_generator().upvar_tys().iter())?; } p!(")"); @@ -900,7 +900,7 @@ pub trait PrettyPrinter<'tcx>: print(args.as_closure().sig_as_fn_ptr_ty()) ); p!(" upvar_tys=("); - self = self.comma_sep(args.as_closure().upvar_tys())?; + self = self.comma_sep(args.as_closure().upvar_tys().iter())?; p!(")"); } } @@ -2806,10 +2806,7 @@ define_print_and_forward_display! { } TraitPredPrintModifiersAndPath<'tcx> { - if let ty::BoundConstness::ConstIfConst = self.0.constness { - p!("~const ") - } - + // FIXME(effects) print `~const` here if let ty::ImplPolarity::Negative = self.0.polarity { p!("!") } @@ -2843,9 +2840,7 @@ define_print_and_forward_display! { ty::TraitPredicate<'tcx> { p!(print(self.trait_ref.self_ty()), ": "); - if let ty::BoundConstness::ConstIfConst = self.constness && cx.tcx().features().const_trait_impl { - p!("~const "); - } + // FIXME(effects) print `~const` here if let ty::ImplPolarity::Negative = self.polarity { p!("!"); } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index bf9adabdab1..47512d350e5 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -826,7 +826,6 @@ impl<'tcx> Relate<'tcx> for ty::TraitPredicate<'tcx> { ) -> RelateResult<'tcx, ty::TraitPredicate<'tcx>> { Ok(ty::TraitPredicate { trait_ref: relation.relate(a.trait_ref, b.trait_ref)?, - constness: relation.relate(a.constness, b.constness)?, polarity: relation.relate(a.polarity, b.polarity)?, }) } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index c6b6f0e8990..1347b35556d 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -172,9 +172,7 @@ impl fmt::Debug for ty::ParamConst { impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let ty::BoundConstness::ConstIfConst = self.constness { - write!(f, "~const ")?; - } + // FIXME(effects) printing? write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 3e023ccdead..a695febf087 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -296,15 +296,13 @@ impl<'tcx> ClosureArgs<'tcx> { /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. #[inline] - pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx { + pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> { match self.tupled_upvars_ty().kind() { - TyKind::Error(_) => None, - TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), + TyKind::Error(_) => ty::List::empty(), + TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), } - .into_iter() - .flatten() } /// Returns the tuple type representing the upvars for this closure. @@ -436,15 +434,13 @@ impl<'tcx> GeneratorArgs<'tcx> { /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. #[inline] - pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx { + pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> { match self.tupled_upvars_ty().kind() { - TyKind::Error(_) => None, - TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), + TyKind::Error(_) => ty::List::empty(), + TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), } - .into_iter() - .flatten() } /// Returns the tuple type representing the upvars for this generator. @@ -576,7 +572,7 @@ impl<'tcx> GeneratorArgs<'tcx> { /// This is the types of the fields of a generator which are not stored in a /// variant. #[inline] - pub fn prefix_tys(self) -> impl Iterator<Item = Ty<'tcx>> { + pub fn prefix_tys(self) -> &'tcx List<Ty<'tcx>> { self.upvar_tys() } } @@ -592,20 +588,18 @@ impl<'tcx> UpvarArgs<'tcx> { /// In case there was a type error in figuring out the types of the captured path, an /// empty iterator is returned. #[inline] - pub fn upvar_tys(self) -> impl Iterator<Item = Ty<'tcx>> + 'tcx { + pub fn upvar_tys(self) -> &'tcx List<Ty<'tcx>> { let tupled_tys = match self { UpvarArgs::Closure(args) => args.as_closure().tupled_upvars_ty(), UpvarArgs::Generator(args) => args.as_generator().tupled_upvars_ty(), }; match tupled_tys.kind() { - TyKind::Error(_) => None, - TyKind::Tuple(..) => Some(self.tupled_upvars_ty().tuple_fields()), + TyKind::Error(_) => ty::List::empty(), + TyKind::Tuple(..) => self.tupled_upvars_ty().tuple_fields(), TyKind::Infer(_) => bug!("upvar_tys called before capture types are inferred"), ty => bug!("Unexpected representation of upvar types tuple {:?}", ty), } - .into_iter() - .flatten() } #[inline] @@ -728,7 +722,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { use crate::ty::ToPredicate; match self.skip_binder() { ExistentialPredicate::Trait(tr) => { - self.rebind(tr).with_self_ty(tcx, self_ty).without_const().to_predicate(tcx) + self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx) } ExistentialPredicate::Projection(p) => { self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) @@ -743,7 +737,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { let err_args = ty::GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]); ty::TraitRef::new(tcx, did, err_args) }; - self.rebind(trait_ref).without_const().to_predicate(tcx) + self.rebind(trait_ref).to_predicate(tcx) } } } @@ -875,18 +869,6 @@ impl<'tcx> TraitRef<'tcx> { ) } - /// Converts this trait ref to a trait predicate with a given `constness` and a positive polarity. - #[inline] - pub fn with_constness(self, constness: ty::BoundConstness) -> ty::TraitPredicate<'tcx> { - ty::TraitPredicate { trait_ref: self, constness, polarity: ty::ImplPolarity::Positive } - } - - /// Converts this trait ref to a trait predicate without `const` and a positive polarity. - #[inline] - pub fn without_const(self) -> ty::TraitPredicate<'tcx> { - self.with_constness(ty::BoundConstness::NotConst) - } - #[inline] pub fn self_ty(&self) -> Ty<'tcx> { self.args.type_at(0) diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 1d7d905c937..9e02b027182 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -860,20 +860,14 @@ where fn open_drop(&mut self) -> BasicBlock { let ty = self.place_ty(self.place); match ty.kind() { - ty::Closure(_, args) => { - let tys: Vec<_> = args.as_closure().upvar_tys().collect(); - self.open_drop_for_tuple(&tys) - } + ty::Closure(_, args) => self.open_drop_for_tuple(&args.as_closure().upvar_tys()), // Note that `elaborate_drops` only drops the upvars of a generator, // and this is ok because `open_drop` here can only be reached // within that own generator's resume function. // This should only happen for the self argument on the resume function. // It effectively only contains upvars until the generator transformation runs. // See librustc_body/transform/generator.rs for more details. - ty::Generator(_, args, _) => { - let tys: Vec<_> = args.as_generator().upvar_tys().collect(); - self.open_drop_for_tuple(&tys) - } + ty::Generator(_, args, _) => self.open_drop_for_tuple(&args.as_generator().upvar_tys()), ty::Tuple(fields) => self.open_drop_for_tuple(fields), ty::Adt(def, args) => self.open_drop_for_adt(*def, args), ty::Dynamic(..) => self.complete_drop(self.succ, self.unwind), diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 669135f80bc..797a1a86846 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -856,7 +856,7 @@ fn sanitize_witness<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, witness: Ty<'tcx>, - upvars: Vec<Ty<'tcx>>, + upvars: &'tcx ty::List<Ty<'tcx>>, layout: &GeneratorLayout<'tcx>, ) { let did = body.source.def_id(); @@ -1471,7 +1471,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let args = args.as_generator(); ( args.discr_ty(tcx), - args.upvar_tys().collect::<Vec<_>>(), + args.upvar_tys(), args.witness(), movability == hir::Movability::Movable, ) diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 5fa780a372b..af9efb82beb 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -147,7 +147,7 @@ where fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> ControlFlow<V::BreakTy> { match clause.kind().skip_binder() { - ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness: _, polarity: _ }) => { + ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => { self.visit_trait(trait_ref) } ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => { diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 6efc1e7302c..38153cccfdd 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -72,7 +72,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { cause: traits::ObligationCause::dummy(), param_env, recursion_depth: 0, - predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx), + predicate: ty::Binder::dummy(trait_ref).to_predicate(self.tcx), }; self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr) } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 5ec48c7ac57..8bf003f863e 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -727,7 +727,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { self.tcx(), ty::TraitPredicate { trait_ref: self_trait_ref, - constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Positive, }, ); diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 94d3cd035aa..ba5000da6cd 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -97,7 +97,6 @@ impl<'tcx> AutoTraitFinder<'tcx> { orig_env, ty::TraitPredicate { trait_ref, - constness: ty::BoundConstness::NotConst, polarity: if polarity { ImplPolarity::Positive } else { @@ -260,7 +259,6 @@ impl<'tcx> AutoTraitFinder<'tcx> { predicates.push_back(ty::Binder::dummy(ty::TraitPredicate { trait_ref: ty::TraitRef::new(infcx.tcx, trait_did, [ty]), - constness: ty::BoundConstness::NotConst, // Auto traits are positive polarity: ty::ImplPolarity::Positive, })); diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 61f693e1bd1..820973dc090 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -97,7 +97,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { cause, recursion_depth: 0, param_env, - predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), + predicate: ty::Binder::dummy(trait_ref).to_predicate(tcx), }); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 95485850d0e..eae13eb6302 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -100,7 +100,6 @@ pub trait InferCtxtExt<'tcx> { &self, param_env: ty::ParamEnv<'tcx>, ty: ty::Binder<'tcx, Ty<'tcx>>, - constness: ty::BoundConstness, polarity: ty::ImplPolarity, ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>; } @@ -356,7 +355,6 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { &self, param_env: ty::ParamEnv<'tcx>, ty: ty::Binder<'tcx, Ty<'tcx>>, - constness: ty::BoundConstness, polarity: ty::ImplPolarity, ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> { self.commit_if_ok(|_| { @@ -372,12 +370,13 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { span: DUMMY_SP, kind: TypeVariableOriginKind::MiscVariable, }); + // FIXME(effects) let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, [ty.skip_binder(), var]); let obligation = Obligation::new( self.tcx, ObligationCause::dummy(), param_env, - ty.rebind(ty::TraitPredicate { trait_ref, constness, polarity }), + ty.rebind(ty::TraitPredicate { trait_ref, polarity }), ); let ocx = ObligationCtxt::new(self); ocx.register_obligation(obligation); @@ -689,8 +688,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let trait_predicate = bound_predicate.rebind(trait_predicate); let trait_predicate = self.resolve_vars_if_possible(trait_predicate); - let predicate_is_const = ty::BoundConstness::ConstIfConst - == trait_predicate.skip_binder().constness; + // FIXME(effects) + let predicate_is_const = false; if self.tcx.sess.has_errors().is_some() && trait_predicate.references_error() @@ -1909,9 +1908,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .all_impls(trait_pred.def_id()) .filter_map(|def_id| { if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative - || !trait_pred - .skip_binder() - .is_constness_satisfied_by(self.tcx.constness(def_id)) || !self.tcx.is_user_visible_dep(def_id.krate) { return None; @@ -2996,7 +2992,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { && let Ok((implemented_kind, params)) = self.type_implements_fn_trait( obligation.param_env, trait_ref.self_ty(), - trait_predicate.skip_binder().constness, trait_predicate.skip_binder().polarity, ) { @@ -3099,14 +3094,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn maybe_add_note_for_unsatisfied_const( &self, - obligation: &PredicateObligation<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, - trait_predicate: &ty::PolyTraitPredicate<'tcx>, - err: &mut Diagnostic, - span: Span, + _obligation: &PredicateObligation<'tcx>, + _trait_ref: ty::PolyTraitRef<'tcx>, + _trait_predicate: &ty::PolyTraitPredicate<'tcx>, + _err: &mut Diagnostic, + _span: Span, ) -> UnsatisfiedConst { - let mut unsatisfied_const = UnsatisfiedConst(false); - if trait_predicate.is_const_if_const() { + let unsatisfied_const = UnsatisfiedConst(false); + // FIXME(effects) + /* if trait_predicate.is_const_if_const() { let non_const_predicate = trait_ref.without_const(); let non_const_obligation = Obligation { cause: obligation.cause.clone(), @@ -3126,7 +3122,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ), ); } - } + } */ unsatisfied_const } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 593f669e9bb..d2210c6d5d9 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -133,7 +133,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( def_id: DefId, ) -> bool { let trait_ref = ty::TraitRef::new(infcx.tcx, def_id, [ty]); - pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref.without_const()) + pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref) } /// FIXME(@lcnr): this function doesn't seem right and shouldn't exist? diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 76752edc4ae..5823b4508d9 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -574,7 +574,6 @@ fn virtual_call_violation_for_method<'tcx>( // implement auto traits if the underlying type does as well. if let ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref: pred_trait_ref, - constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Positive, }) = pred.kind().skip_binder() && pred_trait_ref.self_ty() == tcx.types.self_param diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 98f45826727..3d800421b76 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1306,7 +1306,7 @@ fn normalize_to_error<'a, 'tcx>( cause, recursion_depth: depth, param_env, - predicate: trait_ref.without_const().to_predicate(selcx.tcx()), + predicate: trait_ref.to_predicate(selcx.tcx()), }; let tcx = selcx.infcx.tcx; let new_value = selcx.infcx.next_ty_var(TypeVariableOrigin { @@ -1867,8 +1867,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( if selcx.infcx.predicate_must_hold_modulo_regions( &obligation.with( selcx.tcx(), - ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]) - .without_const(), + ty::TraitRef::from_lang_item(selcx.tcx(), LangItem::Sized, obligation.cause.span(),[self_ty]), ), ) => { @@ -2152,8 +2151,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( LangItem::Sized, obligation.cause.span(), [self_ty], - ) - .without_const(); + ); obligations.push(obligation.with(tcx, sized_predicate)); } (metadata_ty.into(), obligations) diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index ef989d8c9d6..9484a50e3a9 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -291,9 +291,9 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( return Err(NoSolution); } - constraints.outlives.extend( - args.as_generator().upvar_tys().map(|t| -> ty::GenericArg<'tcx> { t.into() }), - ); + constraints + .outlives + .extend(args.as_generator().upvar_tys().iter().map(ty::GenericArg::from)); constraints.outlives.push(args.as_generator().resume_ty().into()); } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index b9f31be25b1..8f2f02a5e41 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -154,9 +154,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .infcx .probe(|_| self.match_projection_obligation_against_definition_bounds(obligation)); - candidates - .vec - .extend(result.into_iter().map(|(idx, constness)| ProjectionCandidate(idx, constness))); + // FIXME(effects) proper constness needed? + candidates.vec.extend( + result.into_iter().map(|idx| ProjectionCandidate(idx, ty::BoundConstness::NotConst)), + ); } /// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 7140fedb74a..bf09681c66d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -59,7 +59,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ParamCandidate(param) => { let obligations = self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref)); - ImplSource::Param(param.skip_binder().constness, obligations) + // FIXME(effects) + ImplSource::Param(ty::BoundConstness::NotConst, obligations) } ImplCandidate(impl_def_id) => { @@ -128,14 +129,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { subobligation.set_depth_from_parent(obligation.recursion_depth); } - if !obligation.predicate.is_const_if_const() { - // normalize nested predicates according to parent predicate's constness. - impl_src = impl_src.map(|mut o| { - o.predicate = o.predicate.without_const(self.tcx()); - o - }); - } - Ok(impl_src) } @@ -1305,6 +1298,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // If we have a projection type, make sure to normalize it so we replace it // with a fresh infer variable ty::Alias(ty::Projection | ty::Inherent, ..) => { + // FIXME(effects) this needs constness let predicate = normalize_with_depth_to( self, obligation.param_env, @@ -1317,7 +1311,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cause.span, [nested_ty], ), - constness: ty::BoundConstness::ConstIfConst, polarity: ty::ImplPolarity::Positive, }), &mut nested, @@ -1336,6 +1329,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // since it's either not `const Drop` (and we raise an error during selection), // or it's an ADT (and we need to check for a custom impl during selection) _ => { + // FIXME(effects) this needs constness let predicate = self_ty.rebind(ty::TraitPredicate { trait_ref: ty::TraitRef::from_lang_item( self.tcx(), @@ -1343,7 +1337,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cause.span, [nested_ty], ), - constness: ty::BoundConstness::ConstIfConst, polarity: ty::ImplPolarity::Positive, }); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6080a440de6..5da8d838db2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1583,7 +1583,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &PolyTraitObligation<'tcx>, - ) -> smallvec::SmallVec<[(usize, ty::BoundConstness); 2]> { + ) -> smallvec::SmallVec<[usize; 2]> { let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate); let placeholder_trait_predicate = self.infcx.instantiate_binder_with_placeholders(poly_trait_predicate); @@ -1632,7 +1632,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => false, } }) { - return Some((idx, pred.constness)); + return Some(idx); } } None @@ -1820,7 +1820,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { (ParamCandidate(other), ParamCandidate(victim)) => { let same_except_bound_vars = other.skip_binder().trait_ref == victim.skip_binder().trait_ref - && other.skip_binder().constness == victim.skip_binder().constness && other.skip_binder().polarity == victim.skip_binder().polarity && !other.skip_binder().trait_ref.has_escaping_bound_vars(); if same_except_bound_vars { @@ -1830,12 +1829,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // probably best characterized as a "hack", since we might prefer to just do our // best to *not* create essentially duplicate candidates in the first place. DropVictim::drop_if(other.bound_vars().len() <= victim.bound_vars().len()) - } else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref - && victim.skip_binder().constness == ty::BoundConstness::NotConst - && other.skip_binder().polarity == victim.skip_binder().polarity - { - // Drop otherwise equivalent non-const candidates in favor of const candidates. - DropVictim::Yes } else { DropVictim::No } @@ -2169,7 +2162,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let all = args .as_generator() .upvar_tys() - .chain(iter::once(args.as_generator().witness())) + .iter() + .chain([args.as_generator().witness()]) .collect::<Vec<_>>(); Where(obligation.predicate.rebind(all)) } @@ -2210,7 +2204,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { // Not yet resolved. Ambiguous } else { - Where(obligation.predicate.rebind(args.as_closure().upvar_tys().collect())) + Where(obligation.predicate.rebind(args.as_closure().upvar_tys().to_vec())) } } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 61e631c438d..729cf2f3313 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -500,16 +500,12 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti let mut pretty_predicates = Vec::with_capacity(predicates.len() + types_without_default_bounds.len()); - for (mut p, _) in predicates { + for (p, _) in predicates { if let Some(poly_trait_ref) = p.as_trait_clause() { if Some(poly_trait_ref.def_id()) == sized_trait { types_without_default_bounds.remove(&poly_trait_ref.self_ty().skip_binder()); continue; } - - if ty::BoundConstness::ConstIfConst == poly_trait_ref.skip_binder().constness { - p = p.without_const(tcx); - } } pretty_predicates.push(p.to_string()); } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 4c27fe8b29b..a76272e9d09 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -101,7 +101,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { let tcx = self.tcx; let trait_ref = item.trait_ref(); - let pred = trait_ref.without_const().to_predicate(tcx); + let pred = trait_ref.to_predicate(tcx); debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); @@ -113,9 +113,13 @@ impl<'tcx> TraitAliasExpander<'tcx> { // Don't recurse if this trait alias is already on the stack for the DFS search. let anon_pred = anonymize_predicate(tcx, pred); - if item.path.iter().rev().skip(1).any(|&(tr, _)| { - anonymize_predicate(tcx, tr.without_const().to_predicate(tcx)) == anon_pred - }) { + if item + .path + .iter() + .rev() + .skip(1) + .any(|&(tr, _)| anonymize_predicate(tcx, tr.to_predicate(tcx)) == anon_pred) + { return false; } diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 3964dda1fdb..427ac368432 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -86,7 +86,7 @@ fn prepare_vtable_segments_inner<'tcx, T>( let mut emit_vptr_on_new_entry = false; let mut visited = PredicateSet::new(tcx); - let predicate = trait_ref.without_const().to_predicate(tcx); + let predicate = trait_ref.to_predicate(tcx); let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> = smallvec![(trait_ref, emit_vptr_on_new_entry, maybe_iter(None))]; visited.insert(predicate); diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 5f6bb04fda4..f26310665f9 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -348,11 +348,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } // if the trait predicate is not const, the wf obligations should not be const as well. - let obligations = if trait_pred.constness == ty::BoundConstness::NotConst { - self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.args) - } else { - self.nominal_obligations(trait_ref.def_id, trait_ref.args) - }; + let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.args); debug!("compute_trait_pred obligations {:?}", obligations); let param_env = self.param_env; @@ -445,8 +441,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // `i32: Clone` // `i32: Copy` // ] - // Projection types do not require const predicates. - let obligations = self.nominal_obligations_without_const(data.def_id, data.args); + let obligations = self.nominal_obligations(data.def_id, data.args); self.out.extend(obligations); self.compute_projection_args(data.args); @@ -472,8 +467,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.recursion_depth, &mut self.out, ); - // Inherent projection types do not require const predicates. - let obligations = self.nominal_obligations_without_const(data.def_id, args); + let obligations = self.nominal_obligations(data.def_id, args); self.out.extend(obligations); } @@ -516,7 +510,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause, self.recursion_depth, self.param_env, - ty::Binder::dummy(trait_ref).without_const(), + ty::Binder::dummy(trait_ref), )); } } @@ -667,7 +661,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } ty::FnDef(did, args) => { - let obligations = self.nominal_obligations_without_const(did, args); + let obligations = self.nominal_obligations(did, args); self.out.extend(obligations); } @@ -822,11 +816,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn nominal_obligations_inner( + fn nominal_obligations( &mut self, def_id: DefId, args: GenericArgsRef<'tcx>, - remap_constness: bool, ) -> Vec<traits::PredicateObligation<'tcx>> { let predicates = self.tcx().predicates_of(def_id); let mut origins = vec![def_id; predicates.predicates.len()]; @@ -841,16 +834,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { debug_assert_eq!(predicates.predicates.len(), origins.len()); iter::zip(predicates, origins.into_iter().rev()) - .map(|((mut pred, span), origin_def_id)| { + .map(|((pred, span), origin_def_id)| { let code = if span.is_dummy() { traits::ItemObligation(origin_def_id) } else { traits::BindingObligation(origin_def_id, span) }; let cause = self.cause(code); - if remap_constness { - pred = pred.without_const(self.tcx()); - } traits::Obligation::with_depth( self.tcx(), cause, @@ -863,22 +853,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { .collect() } - fn nominal_obligations( - &mut self, - def_id: DefId, - args: GenericArgsRef<'tcx>, - ) -> Vec<traits::PredicateObligation<'tcx>> { - self.nominal_obligations_inner(def_id, args, false) - } - - fn nominal_obligations_without_const( - &mut self, - def_id: DefId, - args: GenericArgsRef<'tcx>, - ) -> Vec<traits::PredicateObligation<'tcx>> { - self.nominal_obligations_inner(def_id, args, true) - } - fn from_object_ty( &mut self, ty: Ty<'tcx>, diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 3500c2cc370..6b4273c03e4 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -317,7 +317,9 @@ fn layout_of_uncached<'tcx>( ty::Closure(_, ref args) => { let tys = args.as_closure().upvar_tys(); univariant( - &tys.map(|ty| Ok(cx.layout_of(ty)?.layout)).try_collect::<IndexVec<_, _>>()?, + &tys.iter() + .map(|ty| Ok(cx.layout_of(ty)?.layout)) + .try_collect::<IndexVec<_, _>>()?, &ReprOptions::default(), StructKind::AlwaysSized, )? @@ -729,7 +731,7 @@ fn generator_layout<'tcx>( // Build a prefix layout, including "promoting" all ineligible // locals as part of the prefix. We compute the layout of all of // these fields at once to get optimal packing. - let tag_index = args.as_generator().prefix_tys().count(); + let tag_index = args.as_generator().prefix_tys().len(); // `info.variant_fields` already accounts for the reserved variants, so no need to add them. let max_discr = (info.variant_fields.len() - 1) as u128; @@ -748,6 +750,7 @@ fn generator_layout<'tcx>( let prefix_layouts = args .as_generator() .prefix_tys() + .iter() .map(|ty| Ok(cx.layout_of(ty)?.layout)) .chain(iter::once(Ok(tag_layout))) .chain(promoted_layouts) @@ -1062,6 +1065,7 @@ fn variant_info_for_generator<'tcx>( let upvar_fields: Vec<_> = args .as_generator() .upvar_tys() + .iter() .zip(upvar_names) .enumerate() .map(|(field_idx, (_, name))| { diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index f89558a4599..34fd31e49e1 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -120,12 +120,16 @@ where _ if component.is_copy_modulo_regions(tcx, self.param_env) => (), ty::Closure(_, args) => { - queue_type(self, args.as_closure().tupled_upvars_ty()); + for upvar in args.as_closure().upvar_tys() { + queue_type(self, upvar); + } } ty::Generator(def_id, args, _) => { let args = args.as_generator(); - queue_type(self, args.tupled_upvars_ty()); + for upvar in args.upvar_tys() { + queue_type(self, upvar); + } let witness = args.witness(); let interior_tys = match witness.kind() { |
